summaryrefslogtreecommitdiffstats
path: root/kernel/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/main.c')
-rw-r--r--kernel/main.c99
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);