summaryrefslogtreecommitdiffstats
path: root/kernel/gsp_phys_booter.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/gsp_phys_booter.c')
-rw-r--r--kernel/gsp_phys_booter.c116
1 files changed, 116 insertions, 0 deletions
diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c
index 7ba74ce..6fae2f2 100644
--- a/kernel/gsp_phys_booter.c
+++ b/kernel/gsp_phys_booter.c
@@ -16744,6 +16744,61 @@ static u32 *gsp_phys_rmcall_build_gr_init(u32 *p)
}
/*
+ * r597: extract the SEM_EXECUTE ACQUIRE groups from the captured guest
+ * prelude and copy them, verbatim, ahead of the rebuilt inline-QMD window.
+ * Two encodings are recognised:
+ * - C46F host-semaphore group: INC_METHOD addr 0x5c count>=5, words
+ * {LO, HI, PAYLOAD_LO, PAYLOAD_HI, EXECUTE}; EXECUTE & 7 != 1 is an
+ * acquire (the pump's own op decode).
+ * - C5C0 SET_REPORT_SEMAPHORE A..D: addr 0x1b00 count>=4, word D's low
+ * two bits select release (0) / acquire (non-zero).
+ * Only the wait methods are taken, so the proven window (init + inline QMD
+ * + PCAS + release) is untouched. Returns the number of words emitted.
+ */
+static u32 gsp_phys_rmcall_gr_emit_acquires(u32 *p,
+ const struct gsp_phys_gr_submit *req,
+ u32 budget)
+{
+ u32 off = 0, words = 0;
+
+ if (!gsp_phys_rmcall_gr_acq_value() || !req || !req->raw)
+ return 0;
+ while (off < req->raw_qmd_hdr && words + 8 < budget) {
+ u32 hdr = req->raw[off];
+ u32 op = (hdr >> 29) & 0x7;
+ u32 count = (hdr >> 16) & 0xfff;
+ u32 addr = (hdr & 0x1fff) << 2;
+ u32 n = 1 + count;
+
+ if ((op != 1 && op != 3) || !count ||
+ off + n > req->raw_qmd_hdr) {
+ off++;
+ continue;
+ }
+ if (addr == 0x5c && count >= 5) {
+ u32 v4 = req->raw[off + 5];
+ u64 va = ((u64)(req->raw[off + 2] & 0xff) << 32) |
+ (u64)(req->raw[off + 1] & 0xfffffffc);
+
+ if ((v4 & 0x7) != 1 && va) {
+ memcpy(p + words, &req->raw[off], n * 4);
+ words += n;
+ }
+ } else if (addr >= 0x1b00 && addr <= 0x1b0c &&
+ count >= 4) {
+ u32 d = req->raw[off + 4] & 0x3;
+
+ if (d != 0) {
+ memcpy(p + words, &req->raw[off], n * 4);
+ words += n;
+ }
+ }
+ off += n;
+ }
+ return words;
+}
+
+/*
* GR launch method block: the inline QMD run at its original shape and the
* channel REPORT_SEMAPHORE release. The stock guest push does NOT emit
* SET_OBJECT before the inline run (the compute class is bound on the
@@ -16776,6 +16831,25 @@ static u32 gsp_phys_rmcall_build_gr_launch(u32 *pb,
GSP_PHYS_RMCALL_GR_SET_QMD_VIRT_CONTROL,
GSP_PHYS_RMCALL_GR_QMD_VIRT_IQ2M_SEND_PCAS);
/*
+ * r597: the prelude's acquire groups (if any) go before the QMD run
+ * so the engine cannot read the launch's data pages until the copy
+ * channel's semaphore has advanced.
+ */
+ {
+ u32 w = gsp_phys_rmcall_gr_emit_acquires(p, req,
+ 128u);
+ static u32 acq_log;
+
+ if (w) {
+ p += w;
+ if (acq_log < 16) {
+ acq_log++;
+ pr_info("vgsp-gr: prelude acquire groups emitted words=%u h=0x%x push=0x%llx\n",
+ w, req->h_object, req->push_va);
+ }
+ }
+ }
+ /*
* Verbatim replay: copy the captured GRCE prelude and the guest's
* own inline-QMD run, keeping the method headers, and relocate only
* the ADDRESS_A/B data words and the 64 QMD words exactly like the
@@ -19368,6 +19442,8 @@ int gsp_phys_backend_guest_gr_submit(const struct gsp_phys_gr_submit *req,
u32 one_word = (qmd[24] >> 31) & 1;
bool rel_mod = gsp_phys_rmcall_gr_rel_mod_value() != 0;
+ int rel_map_ret = 0;
+
if (!rel_mod && req->rel_hpa && one_word && !red_en &&
n_shadow < GSP_PHYS_RMCALL_GR_SHADOW_PAGES) {
u64 sh_va = 0;
@@ -19387,6 +19463,7 @@ int gsp_phys_backend_guest_gr_submit(const struct gsp_phys_gr_submit *req,
0xffu);
qmd[25] = req->rel_payload;
} else {
+ rel_map_ret = ret;
ret = 0;
}
}
@@ -19415,6 +19492,23 @@ int gsp_phys_backend_guest_gr_submit(const struct gsp_phys_gr_submit *req,
* completed on the guest word (the r414 saxpy hang).
*/
qmd_rel_redirected = true;
+ /*
+ * r633 diag: name the exact redirect cause. rel_hpa==0
+ * means the caller could not resolve the release page
+ * (capture resolution or PA->HPA); map_ret!=0 means the
+ * page was resolved but its shadow mapping failed.
+ */
+ {
+ static u32 qmdrel_redir_log;
+
+ if (qmdrel_redir_log < 32) {
+ qmdrel_redir_log++;
+ pr_info("vgsp-gr: qmd-rel redirect: rel_hpa=0x%llx map_ret=%d one_word=%u red_en=%u rel_mod=%d n_shadow=%u pay=%u\n",
+ req->rel_hpa, rel_map_ret,
+ one_word, red_en, rel_mod ? 1 : 0,
+ n_shadow, req->rel_payload);
+ }
+ }
}
}
@@ -20544,6 +20638,28 @@ gr_page_unmapped:
gsp_phys_rmcall_gr_qmdvirt_value(),
boot_stage.rmcall_token,
qmd_rel, want_ch, poll_ms, qmdwin_note);
+ {
+ /*
+ * r596 diag: the raw-prelude geometry the verbatim gate tests.
+ * The verbatim replay needs
+ * raw && raw_words >= hdr + 67 &&
+ * raw_qmd_end == hdr + 67 &&
+ * INIT_WORDS + hdr + 67 + TAIL_WORDS <= METHOD_WORDS
+ * Bounded to the first eight launches so the geometry is on
+ * record without flooding a battery run.
+ */
+ static u32 prelude_geom_log;
+
+ if (gsp_phys_rmcall_gr_prelude_value() && prelude_geom_log < 8) {
+ prelude_geom_log++;
+ pr_info("vgsp-gr: prelude geom raw=%u raw_words=%u hdr=%u end=%u want_end=%u v=%d\n",
+ req->raw ? 1u : 0u, req->raw_words,
+ req->raw_qmd_hdr, req->raw_qmd_end,
+ req->raw_qmd_hdr +
+ GSP_PHYS_RMCALL_GR_QMD_WINDOW_WORDS,
+ gsp_phys_rmcall_gr_prelude_value());
+ }
+ }
if (qmd_win_diag)
pr_info("vgsp-gr: qmd dest va=0x%llx pdeIndex=%u installed=%u win_mask=0x%llx ensure_ret=%d\n",
qmd_dst, qmd_win_pde, qmd_win_installed,