diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/gsp_phys_booter.c | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c index 24b2b7f..4cf1c55 100644 --- a/kernel/gsp_phys_booter.c +++ b/kernel/gsp_phys_booter.c @@ -22439,6 +22439,16 @@ static u32 gsp_phys_rmcall_build_gr_launch(u32 *pb, bool release = req && req->mme_release; u32 pre_words_out = 0; u32 win_emit_off = 0; + /* + * Saved-window release reorder: the DRAW_IAB CALL_MME_MACRO(34) + * run (plus its 0x1644 lead-in) is lifted to just ahead of the + * window's first CALL run. The 728 B state window carries the + * slot-34 call AFTER its 0x33/0x39 setup calls; the c780 + * release replay executed those first, latched DS 0x84000420 + * and never reached slot 34 (mac=0x33/0x0/0x39). c716's 324 B + * DRAW window puts CALL(34) first and ran mac=0x22. + */ + u32 mme_draw_src = 0, mme_draw_span = 0, mme_draw_dst = 0; const u32 *pl = NULL; u32 pl_n = 0, pl_gen = 0, pl_room = 0; u32 block_cap = READ_ONCE(gsp_phys_rmcall_gr_block_cap); @@ -24729,6 +24739,72 @@ if (gsp_phys_gr_slot_kept(j, sa_mask, if (rearm) pr_info("vgsp-gr: MME-SA-REARM %u slot(s) re-pointed before the window (h=0x%x push=0x%llx)\n", rearm, req->h_object, req->push_va); + /* + * Release window reorder: locate the window's first + * CALL run and its slot-34 CALL_MME_MACRO run so the + * DRAW_IAB call can be lifted ahead of the setup calls + * (see the mme_draw_* declaration comment). The slot-34 + * run's immediately preceding 0x1644 pair travels with + * it (c716's DRAW window has the same [0,0] lead-in + * directly before the call). + */ + if (release && + READ_ONCE(gsp_phys_rmcall_gr_mme_release_sa_arm)) { + u32 rr = 0, first = 0; + u32 s34 = 0, s34span = 0, leadsp = 0; + u32 prev = 0, prevsp = 0, prevm = 0; + + while (rr < win3d_n) { + u32 h = win3d[rr]; + u32 op = (h >> 29) & 7u; + u32 cnt = (h >> 16) & 0xfffu; + u32 span = ((op == 1u || op == 3u || + op == 5u) && cnt && + rr + 1u + cnt <= win3d_n) ? + 1u + cnt : 1u; + u32 m0 = (h & 0xfffu) << 2; + u32 nk = 0, k; + bool call = false, slot34 = false; + + if (op == 1u || op == 3u) + nk = span - 1u; + else if (op == 4u || op == 5u) + nk = 1u; + for (k = 0; k < nk; k++) { + u32 m = m0 + 4u * k; + + if (m < 0x3800u || + m >= 0x3a00u || (m & 7u)) + continue; + call = true; + if ((m - 0x3800u) / 8u == 34u) + slot34 = true; + } + if (call && !first) + first = rr; + if (slot34 && !s34) { + s34 = rr; + s34span = span; + if (rr == prev + prevsp && + prevm == 0x1644u) + leadsp = prevsp; + } + prev = rr; + prevsp = span; + prevm = m0; + rr += span; + } + if (s34 && first && s34 > first + leadsp) { + mme_draw_dst = first; + mme_draw_src = s34 - leadsp; + mme_draw_span = s34span + leadsp; + pr_info("vgsp-gr: MME-DRAW-PLAN slot=34 src_off=0x%x dst_off=0x%x span=%u lead=%u window=%u h=0x%x push=0x%llx\n", + mme_draw_src * 4u, + mme_draw_dst * 4u, + mme_draw_span, leadsp, win3d_n, + req->h_object, req->push_va); + } + } } /* * r1447: the release actually fires on this launch (the calls @@ -24952,6 +25028,33 @@ if (gsp_phys_gr_slot_kept(j, sa_mask, elided, req->h_object, req->push_va, win3d_n, w); p += w; + } else if (mme_draw_span && mme_draw_src > mme_draw_dst) { + /* + * Release window with the slot-34 DRAW_IAB call: + * emit the head state binds, then the CALL(34) run + * (with its 0x1644 lead-in), then the rest of the + * window without the moved run. This reproduces the + * c716 DRAW-window call order (CALL(34) before the + * 0x33/0x39 setup calls) that ran mac=0x22. + */ + u32 leadn = mme_draw_dst; + u32 midn = mme_draw_src - mme_draw_dst; + u32 tailn = win3d_n - mme_draw_src - mme_draw_span; + + memcpy(p, win3d, (size_t)leadn * 4u); + p += leadn; + memcpy(p, &win3d[mme_draw_src], + (size_t)mme_draw_span * 4u); + p += mme_draw_span; + memcpy(p, &win3d[mme_draw_dst], (size_t)midn * 4u); + p += midn; + memcpy(p, &win3d[mme_draw_src + mme_draw_span], + (size_t)tailn * 4u); + p += tailn; + pr_info("vgsp-gr: MME-DRAW-MOVE slot=34 src_off=0x%x dst_off=0x%x span=%u window=%u h=0x%x push=0x%llx\n", + mme_draw_src * 4u, mme_draw_dst * 4u, + mme_draw_span, win3d_n, req->h_object, + req->push_va); } else { memcpy(p, win3d, (size_t)win3d_n * 4); p += win3d_n; |
