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.c63
1 files changed, 62 insertions, 1 deletions
diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c
index b2d759e..74ebbd5 100644
--- a/kernel/gsp_phys_booter.c
+++ b/kernel/gsp_phys_booter.c
@@ -20130,8 +20130,69 @@ static u32 gsp_phys_rmcall_gr_3d_patch_window(const u32 *in, u32 n, u32 *out,
if (wv < 0x10000u || (wv & 3u))
continue;
if (!gsp_phys_rmcall_gr_3d_reloc(
- &up, &lo, req, n_shadow))
+ &up, &lo, req, n_shadow)) {
+ /*
+ * SESSION 153-CONTINUED-51:
+ * the payload page missed the
+ * launch's page set (the QMD
+ * pointer region caps the set
+ * far below a full window's
+ * operand count - r1071: the
+ * macro payload pages
+ * 0x44fd200..0x44fde00 were
+ * ~12 distinct pages while the
+ * set held 7; the words stayed
+ * RAW and the engine fetched an
+ * untranslatable guest VA on
+ * every full window - the
+ * 0xbadf1201 priv-error
+ * poison). Resolve the page
+ * through the SAME trusted
+ * ledger/pin/walk chain the
+ * launch pages use (the
+ * RELOC-FIXED resolver) and
+ * shadow-map it exactly like a
+ * matched page. A resolve/map
+ * miss or a shadow VA that
+ * cannot fit the 32-bit slot
+ * stays verbatim (never
+ * guessed).
+ */
+ struct gsp_sema_gr_reloc r;
+ u64 va2 = (u64)wv;
+ u64 sh2 = 0;
+ u32 line2 = 0;
+
+ if (gsp_sema_gr_reloc_resolve(
+ va2, &r) ||
+ !r.hpa)
+ continue;
+ if (*n_shadow >=
+ GSP_PHYS_RMCALL_GR_SHADOW_PAGES)
+ continue;
+ if (gsp_phys_rmcall_gr_map_shadow_locked(
+ *n_shadow, r.hpa,
+ &sh2, &line2))
+ continue;
+ if (line2 != 0xffffffffu)
+ (*n_shadow)++;
+ sh2 |= va2 &
+ (GSP_PHYS_PAGE_SIZE - 1);
+ up = (u32)(sh2 >> 32) & 0xffu;
+ lo = (wv & 0x3u) |
+ ((u32)sh2 & 0xfffffffcu);
+ if (up != 0)
+ continue;
+ d[wi] = lo;
+ reloc++;
+ if (mme_log < 32) {
+ mme_log++;
+ pr_info("vgsp-gr: mme-reloc-rsv addr=0x%x wi=%u w=0x%x -> 0x%x\n",
+ addr, wi, wv,
+ lo);
+ }
continue;
+ }
if (up != 0)
continue;
d[wi] = lo;