diff options
Diffstat (limited to 'kernel/main.c')
| -rw-r--r-- | kernel/main.c | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/kernel/main.c b/kernel/main.c index 05a49b1..25bd5eb 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -3023,5 +3023,104 @@ static const struct kernel_param_ops nv_vgpu_inject_irq_ops = { module_param_cb(inject_irq, &nv_vgpu_inject_irq_ops, NULL, 0200); MODULE_PARM_DESC(inject_irq, "Deliver MSI-X vector N to the guest (debug)"); +/* + * Debug: dump the GSP-RM msgq cursors (ours and the guest's) plus the + * registered event objects: + * echo 1 > .../parameters/rmstate + * + * Runs in a kthread: vfio_iommu_type1_dma_rw only works when current->mm is + * NULL (kthread) or matches the mapping's mm (QEMU). + */ +static int nv_vgpu_rmstate_thread(void *arg) +{ + struct completion *done = arg; + struct nv_vgpu_device *vgpu; + + mutex_lock(&nv_vgpu_driver.lock); + list_for_each_entry(vgpu, &nv_vgpu_driver.devices, list) { + if (atomic_read(&vgpu->vfio_dev_open_count) <= 0) + continue; + gsp_rm_dump_state(vgpu); + } + mutex_unlock(&nv_vgpu_driver.lock); + + complete(done); + return 0; +} + +static int nv_vgpu_rmstate_set(const char *val, const struct kernel_param *kp) +{ + DECLARE_COMPLETION_ONSTACK(done); + struct task_struct *task; + + task = kthread_run(nv_vgpu_rmstate_thread, &done, "vgpu-rmstate"); + if (IS_ERR(task)) + return PTR_ERR(task); + wait_for_completion(&done); + return 0; +} + +static const struct kernel_param_ops nv_vgpu_rmstate_ops = { + .set = nv_vgpu_rmstate_set, +}; + +module_param_cb(rmstate, &nv_vgpu_rmstate_ops, NULL, 0200); +MODULE_PARM_DESC(rmstate, "Dump GSP-RM msgq cursors and event table (debug)"); + +/* + * Debug: post an event record to the guest (idx < events_n, or 0xffffffff + * for every registered event): + * echo 0 > .../parameters/rmpost + */ +struct nv_vgpu_rmpost_req { + u32 idx; + int rc; + struct completion done; +}; + +static int nv_vgpu_rmpost_thread(void *arg) +{ + struct nv_vgpu_rmpost_req *req = arg; + struct nv_vgpu_device *vgpu; + + mutex_lock(&nv_vgpu_driver.lock); + list_for_each_entry(vgpu, &nv_vgpu_driver.devices, list) { + if (atomic_read(&vgpu->vfio_dev_open_count) <= 0) + continue; + req->rc = gsp_rm_force_post(vgpu, req->idx); + pr_info("gsp-resman-vfio: rmpost idx=%u -> %d\n", + req->idx, req->rc); + } + mutex_unlock(&nv_vgpu_driver.lock); + + complete(&req->done); + return 0; +} + +static int nv_vgpu_rmpost_set(const char *val, const struct kernel_param *kp) +{ + static struct nv_vgpu_rmpost_req req; + struct task_struct *task; + + memset(&req, 0, sizeof(req)); + req.rc = -ENODEV; + if (kstrtou32(val, 0, &req.idx)) + return -EINVAL; + + init_completion(&req.done); + task = kthread_run(nv_vgpu_rmpost_thread, &req, "vgpu-rmpost"); + if (IS_ERR(task)) + return PTR_ERR(task); + wait_for_completion(&req.done); + return 0; +} + +static const struct kernel_param_ops nv_vgpu_rmpost_ops = { + .set = nv_vgpu_rmpost_set, +}; + +module_param_cb(rmpost, &nv_vgpu_rmpost_ops, NULL, 0200); +MODULE_PARM_DESC(rmpost, "Post a GSP-RM event to the guest by event index (debug)"); + module_init(nv_vgpu_init); module_exit(nv_vgpu_exit); |
