diff options
| -rw-r--r-- | kernel/gsp_sema_service.c | 106 | ||||
| -rw-r--r-- | kernel/gsp_sema_service.h | 6 | ||||
| -rw-r--r-- | kernel/main.c | 2 |
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 |
