summaryrefslogtreecommitdiffstats
path: root/kernel/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/main.c')
-rw-r--r--kernel/main.c89
1 files changed, 89 insertions, 0 deletions
diff --git a/kernel/main.c b/kernel/main.c
index 637c79b..0a1ebc2 100644
--- a/kernel/main.c
+++ b/kernel/main.c
@@ -2560,5 +2560,94 @@ static const struct kernel_param_ops nv_vgpu_dump_vidmem_ops = {
module_param_cb(dump_vidmem, &nv_vgpu_dump_vidmem_ops, NULL, 0200);
MODULE_PARM_DESC(dump_vidmem, "Dump emulated vidmem range (hex offset,hex len)");
+/*
+ * Debug: hex-dump a guest physical range (kthread: guest-DMA needs it):
+ * echo 0x<gpa>,0x<len> > .../parameters/dump_guest
+ */
+struct nv_vgpu_dump_guest_req {
+ u64 gpa;
+ unsigned long len;
+ struct completion done;
+};
+
+static int nv_vgpu_dump_guest_thread(void *arg)
+{
+ struct nv_vgpu_dump_guest_req *req = arg;
+ struct nv_vgpu_device *vgpu;
+ u32 *buf;
+ unsigned long i;
+
+ buf = kmalloc(256, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ mutex_lock(&nv_vgpu_driver.lock);
+ list_for_each_entry(vgpu, &nv_vgpu_driver.devices, list) {
+ u64 o;
+
+ if (atomic_read(&vgpu->vfio_dev_open_count) <= 0)
+ continue;
+ pr_info("gsp-resman-vfio: guest dump 0x%llx..0x%llx\n",
+ req->gpa, req->gpa + req->len);
+ for (o = 0; o < req->len; o += 256) {
+ unsigned long chunk = min_t(unsigned long, 256,
+ req->len - o);
+
+ if (vfio_dma_rw(&vgpu->vfio_dev, req->gpa + o, buf,
+ chunk, false)) {
+ pr_info("gsp-resman-vfio: guest dump read failed at 0x%llx\n",
+ req->gpa + o);
+ break;
+ }
+ for (i = 0; i < chunk / 4; i += 4)
+ pr_info("gsp-resman-vfio: 0x%llx: %08x %08x %08x %08x\n",
+ req->gpa + o + i * 4, buf[i], buf[i + 1],
+ buf[i + 2], buf[i + 3]);
+ }
+ }
+ mutex_unlock(&nv_vgpu_driver.lock);
+
+ kfree(buf);
+ complete(&req->done);
+ return 0;
+}
+
+static int nv_vgpu_dump_guest_set(const char *val, const struct kernel_param *kp)
+{
+ static struct nv_vgpu_dump_guest_req req;
+ struct task_struct *task;
+ char buf[64];
+ char *comma;
+
+ memset(&req, 0, sizeof(req));
+ strscpy(buf, val, sizeof(buf));
+ comma = strchr(buf, ',');
+ if (comma)
+ *comma = '\0';
+ if (kstrtoull(buf, 0, &req.gpa))
+ return -EINVAL;
+ req.len = 0x100;
+ if (comma && kstrtoul(comma + 1, 0, &req.len))
+ return -EINVAL;
+ if (!req.len)
+ req.len = 0x100;
+ if (req.len > 0x4000)
+ req.len = 0x4000;
+
+ init_completion(&req.done);
+ task = kthread_run(nv_vgpu_dump_guest_thread, &req, "vgpu-dump");
+ if (IS_ERR(task))
+ return PTR_ERR(task);
+ wait_for_completion(&req.done);
+ return 0;
+}
+
+static const struct kernel_param_ops nv_vgpu_dump_guest_ops = {
+ .set = nv_vgpu_dump_guest_set,
+};
+
+module_param_cb(dump_guest, &nv_vgpu_dump_guest_ops, NULL, 0200);
+MODULE_PARM_DESC(dump_guest, "Hex-dump a guest physical range (hex gpa,hex len)");
+
module_init(nv_vgpu_init);
module_exit(nv_vgpu_exit);