From 87d62c6300b22ad93c8f68ab77ea6004eb2da3eb Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Tue, 20 Oct 2026 14:47:29 -0400 Subject: sema: CE fill byte-exact semantics per the driver's own memset push - LINE_LENGTH_IN is the size in BYTES (count=line_length/elem; the old count=line_length wrote elem x too much), value from DST_X mapping (CONST_A/CONST_B), r367 --- kernel/gsp_sema_service.c | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index 2eb9610..59e7262 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -8914,15 +8914,41 @@ static void svc_decode_stream(struct nv_vgpu_device *vgpu, const u8 *buf, ((st.remap_comp >> 16) & 0x3) : 0; u32 ndst = st.have_remap ? ((st.remap_comp >> 24) & 0x3) : 0; + u32 dst_x = st.have_remap ? + (st.remap_comp & 0x7) : 4; struct svc_memset_op *m = &ops[n_ops]; m->type = 0; m->dst = st.offset_out; + /* + * r367: the driver's own memset push + * (channel_utils.c) proves the + * encoding: LINE_LENGTH_IN is the + * fill SIZE IN BYTES, and + * SET_REMAP_COMPONENTS selects + * COMPONENT_SIZE ([17:16], 0..3 -> + * 1/2/3/4 bytes) and + * NUM_DST_COMPONENTS ([25:24], n+1 + * components). elem = + * (csz+1)*(ndst+1) is the pattern + * width; count must therefore be + * line_length/elem - the old + * count=line_length wrote + * elem x too much (r365: a 383620- + * byte memset wrote 1534480 bytes, + * clobbering the bytes after it). + * The value comes from the mapped + * constants: X<-CONST_A (4) and + * Y<-CONST_B (5); with two + * components the pattern is + * B:A 64-bit. + */ if (st.have_remap) m->value = ndst >= 1 ? (((u64)st.remap_b << 32) | st.remap_a) : - st.remap_b; + (dst_x == 5 ? st.remap_b : + st.remap_a); else /* * r357: a fill-shaped transfer @@ -8952,7 +8978,16 @@ static void svc_decode_stream(struct nv_vgpu_device *vgpu, const u8 *buf, m->value = 0; m->elem = st.have_remap ? (csz + 1) * (ndst + 1) : 1; - m->count = st.line_length; + if (m->elem > 1 && + st.line_length % m->elem) { + /* not pattern-divisible: exact + * byte count wins */ + m->elem = 1; + m->count = st.line_length; + } else { + m->count = st.line_length / + m->elem; + } m->phys = DMA_DST_TYPE_PHYSICAL(dma); m->aperture = st.have_dst_mode ? st.dst_phys_mode : CE_APERTURE_VID; -- cgit v1.2.3