summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-24 13:03:56 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-24 13:03:56 -0400
commit016c290447c72a72eaac8337cbf09b32f87e9093 (patch)
tree831493455212e4daf2e7902b68c5f159d6d0b80f
parenta329dc681fc062c2c5ba5a6c6e8fa128617cf780 (diff)
downloadopen-iov-016c290447c72a72eaac8337cbf09b32f87e9093.tar.gz
open-iov-016c290447c72a72eaac8337cbf09b32f87e9093.zip
vgsp-rm r623: oserrlog - deliver a synthetic OS_ERROR_LOG (0x1006) engine-fault report to the guest's RM queue (debug param; payload mirrors the GSP ABI decode: exceptType/runlistId/chid/errString/prevXid) - the suspected missing recovery half after a synth-fault (post-fault clients stick pre-submission)
-rw-r--r--kernel/gsp_rm_emulation.c42
-rw-r--r--kernel/gsp_rm_emulation.h6
-rw-r--r--kernel/main.c79
3 files changed, 127 insertions, 0 deletions
diff --git a/kernel/gsp_rm_emulation.c b/kernel/gsp_rm_emulation.c
index 2a957b3..7011f77 100644
--- a/kernel/gsp_rm_emulation.c
+++ b/kernel/gsp_rm_emulation.c
@@ -926,6 +926,48 @@ int gsp_rm_post_channel_event(struct nv_vgpu_device *vgpu, u32 h_src)
}
/*
+ * r623 experiment: deliver a synthetic OS_ERROR_LOG (0x1006) record to the
+ * guest's RM queue - the error report a real GSP sends into the client's
+ * message queue when an engine faults. r618's synth-fault writes the channel
+ * notifier and posts a generic event; after it, the NEXT client stuck
+ * pre-submission (r620 atomics; r616b saxpy/math). If the guest's fault
+ * handling marks the device recoverable only when the 0x1006 report arrives,
+ * this record is the missing half. Payload mirrors the GSP ABI decode in
+ * gsp_phys_booter.c (GSP_PHYS_OSERR_OFF_*): exceptType u32, runlistId u32,
+ * chid u32, errString[256], prevXid u32. Manual/debug only.
+ */
+int gsp_rm_send_os_error_log(struct nv_vgpu_device *vgpu, u32 except_type,
+ u32 runlist_id, u32 chid, const char *engine)
+{
+ struct gsp_emu_context *ctx = vgpu ? vgpu->gsp_comm_ctx : NULL;
+ struct gsp_rm_emu *rm;
+ u8 payload[272] = {0};
+ int rc;
+
+ if (!ctx)
+ return -ENODEV;
+ rm = ctx->rm_emu;
+ if (!rm || !rm->parsed)
+ return -EAGAIN;
+
+ memcpy(payload + 0, &except_type, 4);
+ memcpy(payload + 4, &runlist_id, 4);
+ memcpy(payload + 8, &chid, 4);
+ snprintf((char *)payload + 12, 255, "ENGINE %s",
+ engine && *engine ? engine : "GR");
+ /* prevXid stays 0 */
+
+ rc = gsp_rm_send(ctx, 0x1006, (u32)rm->stat_seq + 1, 0, payload,
+ sizeof(payload));
+ if (!rc)
+ nv_vgpu_info(vgpu,
+ "vgsp-rm: OS_ERROR_LOG sent (synthetic) except=0x%x rl=%u chid=%u engine=%s\n",
+ except_type, runlist_id, chid,
+ engine && *engine ? engine : "GR");
+ return rc;
+}
+
+/*
* Debug: post the event record for one registered event (or all of them with
* idx 0xffffffff). Used to test the guest's event path on demand without
* waiting for a channel submission.
diff --git a/kernel/gsp_rm_emulation.h b/kernel/gsp_rm_emulation.h
index a0bd4c7..a4b1afd 100644
--- a/kernel/gsp_rm_emulation.h
+++ b/kernel/gsp_rm_emulation.h
@@ -230,6 +230,12 @@ int gsp_rm_emu_init(struct nv_vgpu_device *vgpu, struct gsp_emu_context *ctx);
void gsp_rm_emu_fini(struct gsp_emu_context *ctx);
int gsp_rm_post_channel_event(struct nv_vgpu_device *vgpu, u32 h_src);
int gsp_rm_force_post(struct nv_vgpu_device *vgpu, u32 idx);
+/*
+ * r623: deliver a synthetic OS_ERROR_LOG (0x1006) record to the guest's RM
+ * queue (the engine-fault report a real GSP sends). Debug/experiment only.
+ */
+int gsp_rm_send_os_error_log(struct nv_vgpu_device *vgpu, u32 except_type,
+ u32 runlist_id, u32 chid, const char *engine);
int gsp_rm_post_all_events(struct nv_vgpu_device *vgpu);
int gsp_rm_dump_state(struct nv_vgpu_device *vgpu);
int gsp_rm_scan_guest_ram(struct nv_vgpu_device *vgpu, u64 needle,
diff --git a/kernel/main.c b/kernel/main.c
index 9a5d912..dd11d12 100644
--- a/kernel/main.c
+++ b/kernel/main.c
@@ -3952,5 +3952,84 @@ static const struct kernel_param_ops nv_vgpu_faultpoke_ops = {
module_param_cb(grfaultpoke, &nv_vgpu_faultpoke_ops, NULL, 0200);
MODULE_PARM_DESC(grfaultpoke, "Write a channel error notifier + post its event (r616 experiment)");
+/*
+ * Debug r623: deliver a synthetic OS_ERROR_LOG (0x1006) engine-fault report
+ * to the guest's RM queue:
+ * echo 1 > .../parameters/oserrlog
+ * echo 0x1,0,0 > .../parameters/oserrlog (exceptType,runlistId,chid)
+ * Experiment: after a synth-fault, the next client sticks pre-submission; if
+ * the guest's fault handling completes only when the 0x1006 report arrives,
+ * this record is the missing recovery half.
+ */
+struct nv_vgpu_oserrlog_req {
+ u32 except_type, runlist_id, chid;
+ int rc;
+ struct completion done;
+};
+
+static int nv_vgpu_oserrlog_thread(void *arg)
+{
+ struct nv_vgpu_oserrlog_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_send_os_error_log(vgpu, req->except_type,
+ req->runlist_id, req->chid,
+ "GR");
+ pr_info("vgsp: oserrlog except=0x%x rl=%u chid=%u -> %d\n",
+ req->except_type, req->runlist_id, req->chid, req->rc);
+ }
+ mutex_unlock(&nv_vgpu_driver.lock);
+
+ complete(&req->done);
+ return 0;
+}
+
+static int nv_vgpu_oserrlog_set(const char *val, const struct kernel_param *kp)
+{
+ static struct nv_vgpu_oserrlog_req req;
+ struct task_struct *task;
+ char buf[64];
+ char *c1, *c2;
+
+ memset(&req, 0, sizeof(req));
+ req.rc = -ENODEV;
+ strscpy(buf, val, sizeof(buf));
+ req.except_type = 1; /* generic engine exception, as the synth-fault */
+ {
+ c1 = strchr(buf, ',');
+ if (c1) {
+ *c1++ = '\0';
+ c2 = strchr(c1, ',');
+ if (c2) {
+ *c2++ = '\0';
+ if (kstrtou32(c2, 0, &req.chid))
+ return -EINVAL;
+ }
+ if (kstrtou32(c1, 0, &req.runlist_id))
+ return -EINVAL;
+ }
+ if (kstrtou32(buf, 0, &req.except_type))
+ return -EINVAL;
+ }
+
+ init_completion(&req.done);
+ task = kthread_run(nv_vgpu_oserrlog_thread, &req, "vgpu-oserrlog");
+ if (IS_ERR(task))
+ return PTR_ERR(task);
+ wait_for_completion(&req.done);
+ return 0;
+}
+
+static const struct kernel_param_ops nv_vgpu_oserrlog_ops = {
+ .set = nv_vgpu_oserrlog_set,
+};
+
+module_param_cb(oserrlog, &nv_vgpu_oserrlog_ops, NULL, 0200);
+MODULE_PARM_DESC(oserrlog, "Send a synthetic OS_ERROR_LOG (0x1006) RM record to the guest (r623 experiment)");
+
module_init(nv_vgpu_init);
module_exit(nv_vgpu_exit);