diff --git a/drivers/gpu/nvgpu/Makefile b/drivers/gpu/nvgpu/Makefile
index 966c5eea3..f6b3a6737 100644
--- a/drivers/gpu/nvgpu/Makefile
+++ b/drivers/gpu/nvgpu/Makefile
@@ -77,6 +77,7 @@ nvgpu-$(CONFIG_TEGRA_GR_VIRTUALIZATION) += \
vgpu/mm_vgpu.o \
vgpu/debug_vgpu.o \
vgpu/vgpu.o \
+ vgpu/dbg_vgpu.o \
vgpu/gk20a/vgpu_hal_gk20a.o \
vgpu/gk20a/vgpu_gr_gk20a.o \
vgpu/gm20b/vgpu_hal_gm20b.o \
diff --git a/drivers/gpu/nvgpu/vgpu/dbg_vgpu.c b/drivers/gpu/nvgpu/vgpu/dbg_vgpu.c
new file mode 100644
index 000000000..ef12c3fd9
--- /dev/null
+++ b/drivers/gpu/nvgpu/vgpu/dbg_vgpu.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+#include
+
+#include "gk20a/gk20a.h"
+#include "gk20a/channel_gk20a.h"
+#include "gk20a/dbg_gpu_gk20a.h"
+#include "vgpu.h"
+
+static int vgpu_exec_regops(struct dbg_session_gk20a *dbg_s,
+ struct nvgpu_dbg_gpu_reg_op *ops,
+ u64 num_ops)
+{
+ struct channel_gk20a *ch = dbg_s->ch;
+ struct gk20a_platform *platform = gk20a_get_platform(dbg_s->g->dev);
+ struct tegra_vgpu_cmd_msg msg;
+ struct tegra_vgpu_reg_ops_params *p = &msg.params.reg_ops;
+ void *oob;
+ size_t oob_size;
+ void *handle = NULL;
+ int ops_size, err = 0;
+
+ gk20a_dbg_fn("");
+ BUG_ON(sizeof(*ops) != sizeof(struct tegra_vgpu_reg_op));
+
+ handle = tegra_gr_comm_oob_get_ptr(TEGRA_GR_COMM_CTX_CLIENT,
+ tegra_gr_comm_get_server_vmid(),
+ TEGRA_VGPU_QUEUE_CMD,
+ &oob, &oob_size);
+ if (!handle)
+ return -EINVAL;
+
+ ops_size = sizeof(*ops) * num_ops;
+ if (oob_size < ops_size) {
+ err = -ENOMEM;
+ goto fail;
+ }
+
+ memcpy(oob, ops, ops_size);
+
+ msg.cmd = TEGRA_VGPU_CMD_REG_OPS;
+ msg.handle = platform->virt_handle;
+ p->handle = ch ? ch->virt_ctx : 0;
+ p->num_ops = num_ops;
+ p->is_profiler = dbg_s->is_profiler;
+ err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
+ err = err ? err : msg.ret;
+ if (!err)
+ memcpy(ops, oob, ops_size);
+
+fail:
+ tegra_gr_comm_oob_put_ptr(handle);
+ return err;
+}
+
+void vgpu_dbg_init(void)
+{
+ dbg_gpu_session_ops_gk20a.exec_reg_ops = vgpu_exec_regops;
+}
diff --git a/drivers/gpu/nvgpu/vgpu/vgpu.c b/drivers/gpu/nvgpu/vgpu/vgpu.c
index 6f91db4c1..3791d8a75 100644
--- a/drivers/gpu/nvgpu/vgpu/vgpu.c
+++ b/drivers/gpu/nvgpu/vgpu/vgpu.c
@@ -408,6 +408,7 @@ int vgpu_probe(struct platform_device *dev)
return err;
vgpu_init_support(dev);
+ vgpu_dbg_init();
init_rwsem(&gk20a->busy_lock);
diff --git a/drivers/gpu/nvgpu/vgpu/vgpu.h b/drivers/gpu/nvgpu/vgpu/vgpu.h
index ffb863cd6..32f4b1108 100644
--- a/drivers/gpu/nvgpu/vgpu/vgpu.h
+++ b/drivers/gpu/nvgpu/vgpu/vgpu.h
@@ -58,6 +58,8 @@ int vgpu_comm_sendrecv(struct tegra_vgpu_cmd_msg *msg, size_t size_in,
void vgpu_init_hal_common(struct gk20a *g);
int vgpu_gk20a_init_hal(struct gk20a *g);
int vgpu_gm20b_init_hal(struct gk20a *g);
+
+void vgpu_dbg_init(void);
#else
static inline int vgpu_pm_prepare_poweroff(struct device *dev)
{
diff --git a/include/linux/tegra_vgpu.h b/include/linux/tegra_vgpu.h
index 4db3a16f1..b0e25c602 100644
--- a/include/linux/tegra_vgpu.h
+++ b/include/linux/tegra_vgpu.h
@@ -72,7 +72,8 @@ enum {
TEGRA_VGPU_CMD_AS_MAP_EX,
TEGRA_VGPU_CMD_CHANNEL_BIND_GR_CTXSW_BUFFERS,
TEGRA_VGPU_CMD_SET_MMU_DEBUG_MODE,
- TEGRA_VGPU_CMD_SET_SM_DEBUG_MODE
+ TEGRA_VGPU_CMD_SET_SM_DEBUG_MODE,
+ TEGRA_VGPU_CMD_REG_OPS
};
struct tegra_vgpu_connect_params {
@@ -271,6 +272,26 @@ struct tegra_vgpu_sm_debug_mode {
u32 enable;
};
+struct tegra_vgpu_reg_op {
+ u8 op;
+ u8 type;
+ u8 status;
+ u8 quad;
+ u32 group_mask;
+ u32 sub_group_mask;
+ u32 offset;
+ u32 value_lo;
+ u32 value_hi;
+ u32 and_n_mask_lo;
+ u32 and_n_mask_hi;
+};
+
+struct tegra_vgpu_reg_ops_params {
+ u64 handle;
+ u64 num_ops;
+ u32 is_profiler;
+};
+
struct tegra_vgpu_cmd_msg {
u32 cmd;
int ret;
@@ -297,6 +318,7 @@ struct tegra_vgpu_cmd_msg {
struct tegra_vgpu_gr_bind_ctxsw_buffers_params gr_bind_ctxsw_buffers;
struct tegra_vgpu_mmu_debug_mode mmu_debug_mode;
struct tegra_vgpu_sm_debug_mode sm_debug_mode;
+ struct tegra_vgpu_reg_ops_params reg_ops;
char padding[192];
} params;
};