diff options
Diffstat (limited to 'kernel/main.c')
| -rw-r--r-- | kernel/main.c | 89 |
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); |
