summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-19 10:20:17 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-19 10:21:03 -0400
commita9ad97f0a2342fe821d682d463d85dd8add9d360 (patch)
tree88f886aa8f7597affafdd7c4e84728d5820e9956
parentfc203ded15863dc343442b7bb5fd0c796c5af503 (diff)
downloadopen-iov-a9ad97f0a2342fe821d682d463d85dd8add9d360.tar.gz
open-iov-a9ad97f0a2342fe821d682d463d85dd8add9d360.zip
vgsp: fail4 r249-r252 - GRCE slot-run rule + arg-rec order fix; probe fully green
Two fixes on top of c66a0172: 1. Slot rule for LOAD_INLINE_DATA runs: in the UVM upload pushes each run fills a whole 32 KB slot - its data runs to the next run header (or to the next 0x8000 boundary for the last run), regardless of the count field (observed slot starts every 0x8000: cnt=4095 and cnt=2497/2753 variants). Compact pushes keep the count*4 reading. The old reading truncated each slot run to half its data and walked the tail as methods. 2. Argument-ring order: the bridge's arg-block search must see the run's START as the inline-write destination; the new cursor advance must not leak into rec->dst_va (an end-of-run dst_va made the QMD param patch miss and the engine never consumed the launch - regression found and bisected against the pre-session ko via victory_mail). Verified one boot (r251/r252, standard params): ctaid_probe RAWA 0 1 2 3 4 5 6 7 + last8 16376..16383, PROBE1/PROBE2/PROBE2B bad=0; transformer STATUS OK; victory_mail STATUS OK. Residual (distinct class, NOT the H2D delivery): streams2 bad=65534, memcpy_roundtrip bad=8388608, victory_multikernel bad=2883066. Their big spans collapse to a single rec/bank entry in the launch tables ('bank 0 hit @0x168: VA -> reloc' for one page of the span) and the engine write-back replicates one page across the span (OUT-ALIAS-WIT partners) - the original span-aliasing class on the large-buffer paths.
-rw-r--r--kernel/gsp_sema_service.c66
1 files changed, 59 insertions, 7 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c
index a5b1d93..6dd83c9 100644
--- a/kernel/gsp_sema_service.c
+++ b/kernel/gsp_sema_service.c
@@ -7504,11 +7504,58 @@ static void svc_decode_stream(struct nv_vgpu_device *vgpu, const u8 *buf,
*/
if (op == 3 && subch == 1 && addr == GRCE_M_LOAD_INLINE_DATA &&
count && off + 4 + count * 4 <= len) {
+ /*
+ * fail4 slot rule: in the UVM upload pushes each
+ * LOAD_INLINE_DATA run fills a whole 32 KB slot - its
+ * data runs from the header to the next run header
+ * (or to the next 0x8000 boundary when this is the
+ * last run), regardless of the count field. A compact
+ * push (no room for a following slot) keeps the
+ * count*4 reading (the small parameter banks). The
+ * old count*4 reading truncated the big runs to half
+ * their slot and left the tail to be misparsed as
+ * methods (the split-upload bug).
+ */
+ bool slot_run = (off + 0x8000 < len);
+ u32 slot_end = off + 0x8000;
+ u32 slot_bytes = 0;
+ /*
+ * fail4: the bridge's argument-block search needs the
+ * run's START as its destination; the cursor advance
+ * below must not leak into the rec (an end-of-run
+ * dst_va makes the QMD param patch miss and the
+ * engine never consumes the launch).
+ */
+ u64 run_dst = st.offset_out;
+
+ if (slot_run) {
+ u32 p;
+
+ for (p = off + 4 + count * 4;
+ p + 4 <= slot_end && p + 4 <= len; p += 4) {
+ u32 h2;
+
+ memcpy(&h2, buf + p, 4);
+ if (((h2 >> 29) & 0x7) == 3 &&
+ ((h2 >> 13) & 0x7) == 1 &&
+ ((h2 & 0x1fff) << 2) ==
+ GRCE_M_LOAD_INLINE_DATA &&
+ ((h2 >> 16) & 0xfff)) {
+ slot_end = p;
+ break;
+ }
+ }
+ slot_bytes = slot_end - (off + 4);
+ if (slot_bytes > 0x8000 - 4)
+ slot_bytes = 0x8000 - 4;
+ }
if ((trusted || allow_ops) && !gsp_sema_skip_ops &&
st.have_out && st.line_length) {
- u32 bytes = st.line_length *
- (st.gr_line_count ? st.gr_line_count : 1);
- u32 have = count * 4;
+ u32 bytes = slot_run ? slot_bytes :
+ st.line_length *
+ (st.gr_line_count ?
+ st.gr_line_count : 1);
+ u32 have = slot_run ? slot_bytes : count * 4;
if (bytes > have)
bytes = have;
@@ -7557,18 +7604,23 @@ static void svc_decode_stream(struct nv_vgpu_device *vgpu, const u8 *buf,
* kernel arguments in the QMD parameter bank, and the
* destination VA may not be readable later.
*/
- if (st.have_out && st.offset_out) {
+ if (st.have_out && run_dst) {
struct svc_grce_rec *rec =
&svc_grce_dst_ring[svc_grce_dst_ring_next %
SVC_GRCE_DST_MAX];
- rec->dst_va = st.offset_out;
- rec->len = min_t(u32, count * 4,
+ rec->dst_va = run_dst;
+ rec->len = min_t(u32,
+ slot_run ? slot_bytes : count * 4,
GSP_BRIDGE_INLINE_BYTES);
memcpy(rec->data, buf + off + 4, rec->len);
svc_grce_dst_ring_next++;
}
- off += 4 + count * 4;
+ /*
+ * fail4 slot rule: hop to the next slot's run header
+ * instead of walking the slot's raw tail as methods.
+ */
+ off += slot_run ? (slot_end - off) : 4 + count * 4;
continue;
}