summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-20 14:47:29 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-20 14:47:29 -0400
commit87d62c6300b22ad93c8f68ab77ea6004eb2da3eb (patch)
treea5973f9f7b63ffe6f5060813326bb44b1ab73bfd /kernel
parent8fc2b3a71a9a7ab0990cd7ea241e03dad67832eb (diff)
downloadopen-iov-87d62c6300b22ad93c8f68ab77ea6004eb2da3eb.tar.gz
open-iov-87d62c6300b22ad93c8f68ab77ea6004eb2da3eb.zip
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
Diffstat (limited to 'kernel')
-rw-r--r--kernel/gsp_sema_service.c39
1 files 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;