summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-20 14:35:55 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-20 14:35:55 -0400
commit9a173062ec9372f22b605cfeeaf96ee6ce37c4db (patch)
tree9367cd995a3ec51db6957edadcbb60fb28b73583
parent51267805d1d3bcb073fa3284e5307db651f31a48 (diff)
downloadopen-iov-9a173062ec9372f22b605cfeeaf96ee6ce37c4db.tar.gz
open-iov-9a173062ec9372f22b605cfeeaf96ee6ce37c4db.zip
sema: decode count=1 SET_REMAP_CONST A/B/COMPONENTS (the CE page-table fill constants) + opt-in vidmem-window fill execution (gsp_sema_winfill, off) + FILL-RAW raw-push diagnostic; remapconst log budget 256
-rw-r--r--kernel/gsp_sema_service.c106
-rw-r--r--kernel/gsp_sema_service.h6
-rw-r--r--kernel/main.c2
3 files changed, 112 insertions, 2 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c
index 157fd1a..2db3c83 100644
--- a/kernel/gsp_sema_service.c
+++ b/kernel/gsp_sema_service.c
@@ -4028,6 +4028,7 @@ static u64 svc_wait_giveup;
static u32 svc_wait_log; /* per-session held-row print budget */
static u32 svc_wait_pass_log; /* per-session resolved-row budget */
static u32 svc_remapconst_log; /* r343 FILL: SET_REMAP_CONST_A rows */
+static u32 svc_fill_raw_log; /* r365 FILL-RAW: raw dropped-fill dumps */
static u32 svc_fill_noremap; /* r343 FILL: fail-closed holds */
static u64 svc_wait_rel_va; /* this entry's own release (mirror) */
static u32 svc_wait_rel_payload;
@@ -4348,6 +4349,7 @@ struct svc_push_state {
u32 sem_va_hi, sem_va_lo, sem_payload;
u32 have_sem;
u32 have_remap;
+ u32 have_remap_a, have_remap_b, have_remap_c;
u32 release_dma;
u32 sem_inc;
u32 rs_upper, rs_lower, rs_payload;
@@ -8741,7 +8743,7 @@ static void svc_decode_stream(struct nv_vgpu_device *vgpu, const u8 *buf,
* captures the real run shape even when the count
* guard below cannot use it.
*/
- if (svc_remapconst_log < 32) {
+ if (svc_remapconst_log < 256) {
svc_remapconst_log++;
pr_info("sema-remapconst: h=0x%x push=0x%llx off=0x%x count=%u v0=0x%x v1=0x%x v2=0x%x trusted=%d allow=%u\n",
ch->h_object, push_va, off, count,
@@ -8753,6 +8755,37 @@ static void svc_decode_stream(struct nv_vgpu_device *vgpu, const u8 *buf,
st.remap_b = v1;
st.remap_comp = v2;
st.have_remap = 1;
+ st.have_remap_a = 1;
+ st.have_remap_b = 1;
+ st.have_remap_c = 1;
+ } else if (count >= 1) {
+ /*
+ * r365: the driver also pushes the fill constants
+ * as SEPARATE count=1 methods (the CE
+ * page-table fills carry only SET_REMAP_CONST_A
+ * with A=0). The old count>=3-only decode
+ * dropped those, so have_remap stayed 0 and the
+ * fill decoded no op - the guest's page-table
+ * writes never reached the shadow (the
+ * first-client GRFILL-DROP class).
+ */
+ st.remap_a = v0;
+ st.have_remap_a = 1;
+ st.have_remap = 1;
+ }
+ break;
+ case CE_M_SET_REMAP_CONST_B:
+ if (count >= 1) {
+ st.remap_b = v0;
+ st.have_remap_b = 1;
+ st.have_remap = 1;
+ }
+ break;
+ case CE_M_SET_REMAP_COMPONENTS:
+ if (count >= 1) {
+ st.remap_comp = v0;
+ st.have_remap_c = 1;
+ st.have_remap = 1;
}
break;
case CE_M_SET_SRC_PHYS_MODE:
@@ -8850,11 +8883,16 @@ static void svc_decode_stream(struct nv_vgpu_device *vgpu, const u8 *buf,
st.dst_phys_mode == CE_APERTURE_SYS &&
st.offset_out + (u64)st.line_length <=
SEMA_PA_MAX;
+ /* r365: vidmem-window fill (see gsp_sema_winfill). */
+ bool winfill = gsp_sema_winfill &&
+ st.offset_out >= SVC_VIDMEM_VA_LO &&
+ st.offset_out < SVC_VIDMEM_VA_BASE +
+ svc_fb_shadow_size(vgpu);
if (DMA_REMAP_ENABLE(dma) &&
(st.have_remap ||
(st.offset_out >= SVC_VAS_FLOOR) ||
- ramfill) &&
+ ramfill || winfill) &&
DMA_DST_MEMORY_LAYOUT_PITCH(dma) &&
n_ops < SVC_MAX_MEMSETS) {
u32 csz = st.have_remap ?
@@ -8956,6 +8994,51 @@ static void svc_decode_stream(struct nv_vgpu_device *vgpu, const u8 *buf,
}
/*
+ * r365 FILL-RAW: the fill class that still decodes no
+ * op (window VA, no remap const decoded) - dump the
+ * raw push and decode its method stream so the true
+ * value/component encoding is on record. Bounded.
+ */
+ if (allow_ops && transfer != 0 &&
+ DMA_REMAP_ENABLE(dma) &&
+ DMA_DST_MEMORY_LAYOUT_PITCH(dma) &&
+ st.have_out && !st.have_in && !st.have_remap &&
+ svc_fill_raw_log < 48) {
+ u32 dl = len < 160 ? len : 160;
+ u32 mo = 0, mn = 0;
+
+ svc_fill_raw_log++;
+ pr_info("sema-fill-raw: h=0x%x push=0x%llx out=0x%llx line=%u dma=0x%08x dmode=%u have_dstmode=%u trusted=%d allow=%d\n",
+ ch->h_object, push_va, st.offset_out,
+ st.line_length, dma, st.dst_phys_mode,
+ st.have_dst_mode, trusted, allow_ops);
+ pr_info("sema-fill-raw: raw len=%u %*phN\n",
+ len, dl, buf);
+ /* decode the first method pairs */
+ while (mo + 8 <= len && mn < 14) {
+ u32 h2, c2, a2;
+
+ memcpy(&h2, buf + mo, 4);
+ c2 = (h2 >> 16) & 0xfff;
+ a2 = (h2 & 0x1fff) << 2;
+ if ((h2 >> 29) != 1 || !c2 ||
+ mo + 4 + c2 * 4 > len)
+ break;
+ if (c2 >= 2)
+ pr_info("sema-fill-raw: m[%u] addr=0x%x cnt=%u v0=0x%08x v1=0x%08x\n",
+ mn, a2, c2,
+ *(const u32 *)(buf + mo + 4),
+ *(const u32 *)(buf + mo + 8));
+ else
+ pr_info("sema-fill-raw: m[%u] addr=0x%x cnt=%u v0=0x%08x\n",
+ mn, a2, c2,
+ *(const u32 *)(buf + mo + 4));
+ mo += 4 + c2 * 4;
+ mn++;
+ }
+ }
+
+ /*
* r343 FILL diagnostic (LOG-ONLY, no hold): a
* fill-shaped transfer (REMAP_ENABLE + destination
* PITCH, OFFSET_OUT and no OFFSET_IN) whose value
@@ -9967,6 +10050,7 @@ static void svc_session_flush(void)
svc_wait_log = 0;
svc_wait_pass_log = 0;
svc_remapconst_log = 0;
+ svc_fill_raw_log = 0;
svc_fill_noremap = 0;
svc_wait_n = 0;
svc_wait_rel_have = false;
@@ -12339,6 +12423,24 @@ bool gsp_sema_rel_recover;
bool gsp_sema_dbg;
/*
+ * r365: execute fill-shaped CE transfers whose destination is a VIDMEM
+ * WINDOW VA (>= SVC_VIDMEM_VA_LO, below the 1 TiB VA floor). The guest's
+ * page-table writes arrive exactly this way (dma=0x586, REMAP+PITCH, a
+ * count=1 SET_REMAP_CONST_A, line=4, out=0x2000c0xxx) and previously
+ * decoded no op, so the shadow never saw them and the first client of a
+ * fresh boot dropped operand pages (GRFILL-DROP -> launch held/fail-open
+ * with 8 dropped pages -> wrong results or a client wedge).
+ *
+ * The op is built with the VA unchanged (phys=0): svc_fill's virtual path
+ * resolves it through the guest's own published page tables
+ * (svc_op_translate) and only falls back to the shadow for floor-range
+ * VAs - never through the window convention (r362 proved a forced
+ * `addr - SVC_VIDMEM_VA_BASE` writes the wrong page and corrupts results:
+ * reduce sum=0 + mail hang). Default off for A/B.
+ */
+bool gsp_sema_winfill;
+
+/*
* Skip executing a push's collected work (CE memsets/copies into the vidmem
* shadow) while still applying its semaphore release. The client only ever
* observes the release; the shadow writes exist so the emulation can walk
diff --git a/kernel/gsp_sema_service.h b/kernel/gsp_sema_service.h
index fe5cae6..929684d 100644
--- a/kernel/gsp_sema_service.h
+++ b/kernel/gsp_sema_service.h
@@ -287,6 +287,12 @@ extern unsigned gsp_phys_gr_fill_hold;
extern unsigned gsp_sema_walk_trace;
/*
+ * r365: execute fill-shaped CE transfers to VIDMEM-window VAs (the guest's
+ * page-table writes). Off by default; see the definition in the .c.
+ */
+extern bool gsp_sema_winfill;
+
+/*
* m164 CLASS-2: hold window (ms) for a GR launch push whose decode saw QMD
* words but built no launch candidate; 0 disables the hold.
*/
diff --git a/kernel/main.c b/kernel/main.c
index bbaf845..be5ff5e 100644
--- a/kernel/main.c
+++ b/kernel/main.c
@@ -2790,6 +2790,8 @@ module_param_named(gsp_phys_gr_fill_hold, gsp_phys_gr_fill_hold, uint, 0644);
MODULE_PARM_DESC(gsp_phys_gr_fill_hold, "GR fill hold on unresolved operand pages (default 0: log-only, never hold)");
module_param_named(gsp_sema_walk_trace, gsp_sema_walk_trace, uint, 0644);
MODULE_PARM_DESC(gsp_sema_walk_trace, "Trace GMMU walks for unresolved high-VA operands (default 0: off)");
+module_param_named(gsp_sema_winfill, gsp_sema_winfill, bool, 0644);
+MODULE_PARM_DESC(gsp_sema_winfill, "Execute fill-shaped CE transfers to VIDMEM-window VAs (default 0: off)");
/*
* F1-b: while a forwarded GR launch is in flight, defer (do not apply) a