diff options
Diffstat (limited to 'kernel/gsp_phys_booter.c')
| -rw-r--r-- | kernel/gsp_phys_booter.c | 113 |
1 files changed, 110 insertions, 3 deletions
diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c index 0f7e91c..009eb4f 100644 --- a/kernel/gsp_phys_booter.c +++ b/kernel/gsp_phys_booter.c @@ -17186,6 +17186,7 @@ int gsp_phys_backend_guest_gr_submit(const struct gsp_phys_gr_submit *req, int qmd_win_ret = 0; bool qmd_win_diag = false; bool qmdwin_on = false; + u32 qw_bank = 0; char qmdwin_note[32] = ""; bool rearmed = false; u32 attempts = 0; @@ -17818,7 +17819,7 @@ gr_page_unmapped: NULL; if (boot_stage.rmcall_gr_qmdwin_va && qw) { - u32 qw_bank = (epoch & 1u) % + qw_bank = (epoch & 1u) % GSP_PHYS_RMCALL_GR_QMDWIN_SLOTS; qmdwin_on = true; @@ -18643,6 +18644,69 @@ gr_page_unmapped: break; } } + /* + * m160 (fresh-ack + fresh-deposit retry): the m153 + * retry re-published the same PB and then polled + * the release words WITHOUT clearing them - the + * previous attempt's ack (the identical payload) + * satisfied the poll instantly, so every retry + * burned only the retirement wait and concluded + * "engine wrote 0" without ever having waited for + * the engine to consume the re-published entry + * (r162: 3 dud retries, ~870 ms each, then + * accepted). Clear the guest release words (and + * the module semaphore when the QMD won't reach a + * guest page) so the poll below waits for a FRESH + * ack, and move the inline-QMD deposit to the + * other qmdwin bank (fresh epoch) and rebuild the + * method block for it, so the engine cannot have + * a cached fetch line or a stale deposit for the + * retry's entry. The mechanical sequence is + * exactly the one r162's ok=7 saga used when it + * recovered the no-execute launch (fresh ring + * entry + resched + fresh deposit). + */ + if (qmd_rel_hpa) + WRITE_ONCE(*(u32 *)((u8 *)__va(qmd_rel_hpa) + + qmd_rel_off), 0); + if (ch_rel_hpa) + WRITE_ONCE(*(u32 *)((u8 *)__va(ch_rel_hpa) + + ch_rel_off), 0); + WRITE_ONCE(*(u32 *)sem_va, 0); + WRITE_ONCE(*(u32 *)(sem_va + 4), 0); + wmb(); + if (qmdwin_on && + boot_stage.rmcall_gr_qmdwin.pages) { + epoch = ++boot_stage.rmcall_gr_submit_epoch; + if (!epoch) + epoch = ++boot_stage.rmcall_gr_submit_epoch; + qw_bank = (epoch & 1u) % + GSP_PHYS_RMCALL_GR_QMDWIN_SLOTS; + qmd_dst = boot_stage.rmcall_gr_qmdwin_va + + (u64)qw_bank * + GSP_PHYS_PAGE_SIZE; + qmd_dst_mem = gsp_phys_chunk_page_va( + &boot_stage.rmcall_gr_qmdwin, + qw_bank); + if (qmd_dst_mem) { + memcpy(qmd_dst_mem, qmd, + GSP_PHYS_GR_QMD_WORDS * 4); + put_unaligned_le32( + GSP_PHYS_GR_QMD_SENTINEL, + qmd_dst_mem + + GSP_PHYS_GR_QMD_SENTINEL_WORD * 4); + } + words = gsp_phys_rmcall_build_gr_launch( + methods, req, qmd, qmd_dst, + ch_sem_va, want_ch); + memcpy(gsp_phys_chunk_page_va(pb, 0), + methods, words * 4); + pr_info("vgsp-gr: outcome retry %u: release words zeroed + fresh qmdwin bank %u dest 0x%llx + PB rebuilt\n", + attempts, qw_bank, qmd_dst); + } else { + pr_info("vgsp-gr: outcome retry %u: release words zeroed (qmdwin off)\n", + attempts); + } gsp_phys_gr_fill_bounce(req, bounce_csum_in); mutex_lock(&gsp_phys_rm_lock); ret = gsp_phys_rmcall_publish_locked( @@ -18661,8 +18725,10 @@ gr_page_unmapped: { unsigned long dl = jiffies + msecs_to_jiffies( - GSP_PHYS_RMCALL_GR_RETRY_MS); + GSP_PHYS_RMCALL_GR_POLL_MS); + unsigned long ack_start = jiffies; u32 rw0 = 0, rw1 = 0; + bool acked = false; for (;;) { if (qmd_rel_hpa) @@ -18683,18 +18749,59 @@ gr_page_unmapped: *(u32 *)(sem_va + 4)); if ((!qmd_rel || rw0 == want_qmd) && - rw1 == want_ch) + rw1 == want_ch) { + acked = true; break; + } if (time_after_eq(jiffies, dl)) break; msleep(GSP_PHYS_RMCALL_POLL_MS); } + pr_info("vgsp-gr: outcome retry %u: fresh ack %s (qmd_rel=0x%08x want=0x%08x ch_rel=0x%08x after %u ms)\n", + attempts, + acked ? "OK" : "TIMEOUT", + rw0, want_qmd, rw1, + jiffies_to_msecs(jiffies - + ack_start)); } wrote = gsp_phys_gr_output_retire_wait( req, bounce_csum_in); pr_info("vgsp-gr: outcome retry %u done: engine wrote %u page(s)\n", attempts, wrote); } + /* + * m160: if every fresh-ack retry still produced no + * engine writes, the release words may be left zeroed + * from the last retry. Restore the expected payloads so + * the guest client observes its completion and proceeds + * to its own result check (a genuinely lost launch then + * surfaces as the client's own FAIL, never as a hang). + */ + if (wrote == 0) { + bool restored = false; + + if (qmd_rel_hpa) { + u8 *rp = (u8 *)__va(qmd_rel_hpa) + + qmd_rel_off; + + if (READ_ONCE(*(u32 *)rp) != want_qmd) { + WRITE_ONCE(*(u32 *)rp, want_qmd); + restored = true; + } + } + if (ch_rel_hpa) { + u8 *rp = (u8 *)__va(ch_rel_hpa) + + ch_rel_off; + + if (READ_ONCE(*(u32 *)rp) != want_ch) { + WRITE_ONCE(*(u32 *)rp, want_ch); + restored = true; + } + } + if (restored) + pr_info("vgsp-gr: no-write accept: release words restored (qmd=0x%08x ch=0x%08x); client's own check decides\n", + want_qmd, want_ch); + } } } /* |
