diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/gsp_rm_emulation.c | 19 | ||||
| -rw-r--r-- | kernel/gsp_sema_service.c | 94 | ||||
| -rw-r--r-- | kernel/gsp_sema_service.h | 12 |
3 files changed, 122 insertions, 3 deletions
diff --git a/kernel/gsp_rm_emulation.c b/kernel/gsp_rm_emulation.c index 957729b..b928faf 100644 --- a/kernel/gsp_rm_emulation.c +++ b/kernel/gsp_rm_emulation.c @@ -4273,6 +4273,25 @@ static void gsp_rm_handle_rm_alloc(struct gsp_emu_context *ctx, memcpy(&rp[3], reply + GSPRM_ALLOC_HDR_SIZE + 12, 4); gsp_rm_grobj_note(ho, class_id); + /* + * eng23 (CONT.483): the RM record is the direct-GL lane's + * class bind. The X lane carries its C597 SET_OBJECT inline + * in the init push (hw class bind, sticky); the direct-GL + * client's channel (0xbeef01xx family) binds the class + * channel-side - it allocates TURING_A (0xc597) with + * hParent = its own channel (measured: alloc 0xc597 + * h=0xbeef9097 parent=0xbeef0100 client=0xc1d0001a, twice, + * while 0xbeef0100 was a registered channel with engine 0) + * and never re-emits a bind push. Without the note the + * section recognizer's sticky-attachment gate drops every + * one of that channel's pushes and no C597 section is ever + * opened (CONT.481/482: 0 sections for 0xbeef0100 on a boot + * where the whole setup push was readable). Report hParent + * to the sema service, which applies it as the sticky 3D + * bind on its own thread. + */ + if (hp && hp != hc) + gsp_sema_service_gl_attach(hp, 0); if (rm->gr3d_alloc_log < GSPRM_GR3D_LOG_MAX) { rm->gr3d_alloc_log++; nv_vgpu_info(ctx->vgpu, diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index efb4fc1..de92b8e 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -9946,6 +9946,51 @@ static bool svc_gl_att_accept_run(u64 h, u32 subch) } /* + * eng23 (CONT.483): the RM-record attach request. + * + * The attachment tables above are owned by the service thread (only the + * decode path writes them). The GSP-RM emulation thread learns the + * direct-GL client's class bind from the 0xc597 allocation's hParent and + * must not write those tables directly (a memmove under a concurrent + * svc_gl_att_has reader could expose a torn table). Queue one request + * (handle + subchannel + generation) and apply it on the service thread + * at the top of each pass - the attach is sticky, so a one-pass delay is + * harmless, and a later 0xc597 re-alloc simply refreshes the same entry. + */ +static u64 svc_gl_att_req_h; +static u32 svc_gl_att_req_sub; +static u32 svc_gl_att_req_gen; +static u32 svc_gl_att_req_done; + +void gsp_sema_service_gl_attach(u32 h_object, u32 subch) +{ + if (!h_object || subch > SVC_SUBCH_CE) + return; + WRITE_ONCE(svc_gl_att_req_h, h_object); + WRITE_ONCE(svc_gl_att_req_sub, subch); + WRITE_ONCE(svc_gl_att_req_gen, READ_ONCE(svc_gl_att_req_gen) + 1); +} + +static void svc_gl_att_drain(void) +{ + u64 h; + u32 subch, gen; + + gen = READ_ONCE(svc_gl_att_req_gen); + if (gen == svc_gl_att_req_done) + return; + h = READ_ONCE(svc_gl_att_req_h); + subch = READ_ONCE(svc_gl_att_req_sub); + svc_gl_att_req_done = gen; + if (!h) + return; + svc_gl_att_note(h, subch); + if (gsp_sema_dbg) + pr_info("sema-gl: RM-record attach h=0x%llx subch=%u (0xc597 alloc parent; sticky)\n", + h, subch); +} + +/* * SESSION 153 (G-B gate: the client's own C597 draws must open sections). * The replay guard at svc_gl_flush consults svc_gr_cand_push_seen(), which * returns true when the push VA sits in the GR candidate ring - even when @@ -15901,7 +15946,18 @@ static bool svc_fb_push_rescue(struct nv_vgpu_device *vgpu, u32 h_object, { static struct svc_fb_push_hit hits[8]; u8 *base = vgpu->bars[1].vaddr; - u64 lim = min_t(u64, svc_fb_shadow_size(vgpu), 0x4000000ULL), off; + /* + * eng22: the old 64 MiB scan cap assumed every push window parks in + * the low FB. The two recovered windows sat at fb 0x16290c/0x1f6110, + * but the 59556-byte setup push found no window below the cap. Since + * the GL client's pushbuffer is a vidmem allocation written through + * the BAR1 aperture, its mirror offset in the 2 GiB mdev shadow is + * allocation-dependent and may land above 64 MiB; whether the cap is + * what hid the big push is exactly what widening it tests. A + * zero/fill shadow stays cheap: all-zero windows never pass + * svc_method_stream_plausible, and a hit is cached per length. + */ + u64 lim = min_t(u64, svc_fb_shadow_size(vgpu), 0x80000000ULL), off; /* * The client writes the pushbuffer at its VA's page offset inside the * BAR1 window, so a push whose VA is 0x...004 starts 4 bytes into a @@ -21653,7 +21709,16 @@ static void svc_decode_stream(struct nv_vgpu_device *vgpu, const u8 *buf, cnt2 = (h2 >> 16) & 0xfff; sc2 = (h2 >> 13) & 0x7; ad2 = (h2 & 0x1fff) << 2; - if (op2 == 4 && ad2 == 0x1618 && sc2 == 0) { + /* + * eng23 (CONT.483): the direct-GL client's BEGIN + * (0x1618) rides inside a multi-method INC run + * (op 1), not as the one-word IMMD (op 4) this + * scan was written for; accept both shapes so the + * late-attach path fires on its pushes too. + */ + if ((op2 == 4 && ad2 == 0x1618 && sc2 == 0) || + (op2 == 1 && cnt2 && sc2 == 0 && ad2 <= 0x1618u && + (0x1618u - ad2) < cnt2 * 4u)) { svc_gl_att_note(ch->h_object, 0); if (gsp_sema_dbg && svc_gl_draw_log < 64) { svc_gl_draw_log++; @@ -21986,10 +22051,30 @@ static void svc_decode_stream(struct nv_vgpu_device *vgpu, const u8 *buf, * The window then runs from gl_win_start to the pass end * (the section close at the END method / push tail), which * svc_gl_flush slices into the verbatim 3D replay. + * + * eng23 (CONT.483): the direct-GL client emits NVC597_BEGIN + * (0x1618) as a METHOD INSIDE a multi-method INC run - the + * value census decoded `method=0x1618 op=1 value=01047220` + * from a payload word of a run that started below 0x1618 - + * not in the one-word IMMD form (op 4) the X lane's driver + * emits. The same holds for the render-target setup family + * (0x840): the direct-GL draw push carries it inside a run + * whose start covers it (measured c335: run addr=0x80c + * count=256 covers 0x80c..0xc0c, i.e. 0x840 and the whole + * viewport/clip block in one run). Accept both inside-run + * forms on attached channels too (the run carrying the + * method opens the section; the run body itself is scanned + * into the window like the IMMD/RT-setup openers' preceding + * state). */ if (gsp_sema_gl_xlate && !ch->engine_type && ((op == 4 && addr == 0x1618) || - (op == 1 && addr == 0x840 && count >= 4)) && + (op == 1 && addr == 0x840 && count >= 4) || + (op == 1 && count && + ((addr <= 0x840u && + (0x840u - addr) < count * 4u) || + (addr <= 0x1618u && + (0x1618u - addr) < count * 4u)))) && !svc_gl.seen && svc_gl_att_accept_run(ch->h_object, subch)) { u64 keep_rel = svc_gl.rel_va; @@ -50642,6 +50727,9 @@ static int svc_thread(void *arg) /* Host-injection queue drain: once per pass, not per guest. */ svc_handle_map_add(); + /* eng23 (CONT.483): apply RM-record 3D attaches on this + * thread (the only writer of the attachment tables). */ + svc_gl_att_drain(); for (g = 0; g < n_vgpus; g++) { struct svc_guest_sess *sess; diff --git a/kernel/gsp_sema_service.h b/kernel/gsp_sema_service.h index 36f9902..6f07209 100644 --- a/kernel/gsp_sema_service.h +++ b/kernel/gsp_sema_service.h @@ -107,6 +107,18 @@ struct sema_vaspace_desc { void gsp_sema_service_vaspace_add(const struct sema_vaspace_desc *desc); void gsp_sema_service_vaspace_del(u32 h_vaspace); /* + * eng23 (CONT.483): RM-record 3D-class attachment. The X lane carries its + * C597 SET_OBJECT inline in the init push, but the direct-GL client's + * channel binds the class channel-side: the client allocates TURING_A + * (0xc597) with hParent = its own channel and never re-emits a bind push + * (observed: alloc 0xc597 h=0xbeef9097 parent=0xbeef0100). The GSP-RM + * emulation reports that allocation here, and the service thread applies + * it as the sticky attachment the section recognizer gates on (same + * effect as the X lane's inline bind). Called from the RM thread, applied + * on the service thread - no shared-table writes cross threads. + */ +void gsp_sema_service_gl_attach(u32 h_object, u32 subch); +/* * CONT.407: a client's DUP_OBJECT of a VAS gives the destination client a * NEW handle for the SAME page directory (measured: the GL client dups X's * VAS 0x10005 as 0xbfef0001, then allocates its GR channel with |
