summaryrefslogtreecommitdiffstats
path: root/kernel/gsp_sema_service.c
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-05 21:46:02 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-05 21:46:02 -0400
commit66e6d16680d77a58fa235d837ba897879e8ae1f9 (patch)
treee655c043e6df6102bc02046afafbabbdc8a988b2 /kernel/gsp_sema_service.c
parente0e96fe151e9bf690dd215e46da135da1dcc2317 (diff)
downloadopen-iov-66e6d16680d77a58fa235d837ba897879e8ae1f9.tar.gz
open-iov-66e6d16680d77a58fa235d837ba897879e8ae1f9.zip
vgsp: point inline-QMD launch at the guest QMD buffer + GR post-mortem logging
Diffstat (limited to 'kernel/gsp_sema_service.c')
-rw-r--r--kernel/gsp_sema_service.c54
1 files changed, 54 insertions, 0 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c
index b43b222..7467b45 100644
--- a/kernel/gsp_sema_service.c
+++ b/kernel/gsp_sema_service.c
@@ -44,6 +44,7 @@
#include <linux/workqueue.h>
#include <linux/mm.h>
#include <linux/vmalloc.h>
+#include <asm/unaligned.h>
#include "nvidia-vgpu-vfio.h"
#include "gsp_sema_service.h"
@@ -3330,6 +3331,21 @@ static void svc_gr_cand_capture(struct svc_channel *ch,
svc_gr_cand.param_size, svc_gr_cand.rel_va,
svc_gr_cand.rel_payload, svc_gr_cand.rel_flags,
svc_gr_cand.n_pointer, svc_gr_cand.n_inline);
+ if (push && push_len >= 16) {
+ u32 n = push_len / 4;
+ char buf[6 * 16 + 1];
+ u32 i, o = 0;
+
+ if (n > 32)
+ n = 32;
+ for (i = 0; i < n; i++) {
+ o += scnprintf(buf + o, sizeof(buf) - o, "%08x ",
+ get_unaligned_le32(push + i * 4));
+ if (o >= sizeof(buf) - 12)
+ break;
+ }
+ pr_info("sema-gr: push[%u dwords]: %s\n", n, buf);
+ }
}
/*
@@ -7987,6 +8003,15 @@ struct svc_fwd_req {
u64 gr_push_va;
u32 gr_push_len;
u64 gr_qmd_dev_va;
+ /*
+ * The QMD buffer page (the inline-QMD destination the CUDA driver
+ * uses), resolved VA->guest PA on the service thread. The work item
+ * turns gr_qmd_pa into an HPA; the backend maps that page and points
+ * SET_INLINE_QMD_ADDRESS_A/B at it so the IQ2M copies the QMD into
+ * the guest's own buffer, exactly like the driver's qmd->devVA.
+ */
+ u64 gr_qmd_pa;
+ u8 gr_qmd_ap; /* SVC_APERTURE_* of gr_qmd_pa */
u32 gr_rel_flags;
u64 gr_rel_va;
u32 gr_rel_payload;
@@ -8873,6 +8898,18 @@ static void svc_fwd_gr_work(void)
gs.qmd = svc_fwd_req.gr_qmd;
gs.qmd_words = SVC_GR_QMD_WORDS;
gs.qmd_va = svc_fwd_req.gr_qmd_dev_va;
+ gs.qmd_hpa = 0;
+ if (svc_fwd_req.gr_qmd_pa) {
+ u8 qkind = (svc_fwd_req.gr_qmd_ap == SVC_APERTURE_FB) ?
+ SVC_APERTURE_FB : SVC_APERTURE_SYS;
+ u64 qhpa = 0;
+ u32 qoff = 0;
+
+ if (!svc_fwd_operand_hpa(svc_fwd_req.vgpu, qkind,
+ svc_fwd_req.gr_qmd_pa, 0,
+ SEMA_PAGE_SIZE, &qhpa, &qoff) && !qoff)
+ gs.qmd_hpa = qhpa;
+ }
gs.pages = pages;
gs.n_pages = svc_fwd_req.gr_n_pages;
gs.inl = (const struct gsp_phys_gr_inline *)svc_fwd_req.gr_inline;
@@ -9229,6 +9266,23 @@ static int svc_gr_req_fill(struct nv_vgpu_device *vgpu,
svc_fwd_req.gr_push_va = svc_gr_cand.push_va;
svc_fwd_req.gr_push_len = svc_gr_cand.push_len;
svc_fwd_req.gr_qmd_dev_va = svc_gr_cand.qmd_dev_va;
+ /*
+ * Resolve the QMD buffer page now, on the service thread. A miss
+ * leaves gr_qmd_pa 0 and the backend keeps the module scratch page as
+ * the inline-QMD destination (fail-open; the launch can still run).
+ */
+ svc_fwd_req.gr_qmd_pa = 0;
+ svc_fwd_req.gr_qmd_ap = SVC_APERTURE_SYS;
+ if (svc_gr_cand.qmd_dev_va) {
+ u64 qpa = 0;
+ u32 qap = SVC_APERTURE_SYS;
+
+ if (!svc_resolve_va(vgpu, svc_gr_cand.qmd_dev_va, &qpa, &qap)) {
+ svc_fwd_req.gr_qmd_pa =
+ qpa & ~(u64)(SEMA_PAGE_SIZE - 1);
+ svc_fwd_req.gr_qmd_ap = (u8)svc_ap_of(qap);
+ }
+ }
svc_fwd_req.gr_rel_flags = svc_gr_cand.rel_flags;
svc_fwd_req.gr_rel_va = svc_gr_cand.rel_va;
svc_fwd_req.gr_rel_payload = svc_gr_cand.rel_payload;