summaryrefslogtreecommitdiffstats
path: root/kernel/gsp_sema_service.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/gsp_sema_service.c')
-rw-r--r--kernel/gsp_sema_service.c56
1 files changed, 41 insertions, 15 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c
index 5bc387e..dd02aa0 100644
--- a/kernel/gsp_sema_service.c
+++ b/kernel/gsp_sema_service.c
@@ -15344,6 +15344,16 @@ static u32 svc_gl_cb_copy_h;
static u32 svc_gl_cb_copy_val;
static u32 svc_gl_cb_copy_hash;
static u32 svc_gl_cb_copy_log;
+/*
+ * r1494: the last fixed-CB page that resolved through a SYS (engine-page)
+ * source and passed the matrix gate. The client VA can move/reuse after
+ * the first frame (r1492 read back a method page with the same VA and
+ * r1493 fell back to identity), so a later resolution miss must not zero
+ * the seed page: reuse this page for the rest of the boot. Only a page
+ * that was never credibly resolved falls back to the synthetic identity.
+ */
+static u8 svc_gl_cb_good[SEMA_PAGE_SIZE];
+static bool svc_gl_cb_good_valid;
static u32 svc_gl_cb_hash(const u8 *p, u32 n)
{
@@ -15558,33 +15568,49 @@ have:
* r1491: a source whose 0x80 block is not a credible matrix would
* still collapse every vertex. Only a SYS (engine-page) read is
* trusted; an FB-shadow read is by construction not the engine's
- * page, so author the identity positive control there too.
- */
- if ((ssrc == 4 || ssrc == 5 || ssrc == 6 || ssrc == 7) ||
- !svc_gl_cb_matrix_ok(buf)) {
+ * page, so it must not become the seed either.
+ *
+ * r1494: split "is this the real CB?" from "what do we write?".
+ * A validated SYS page becomes the boot's remembered real CB. When
+ * a later resolution misses (or answers with a method page), write
+ * that remembered page again instead of the identity fallback -
+ * the fallback may only run when no real CB was ever resolved this
+ * boot. Do not skip the write on an unchanged hash: the seed page
+ * lives in the client's screen allocation and the guest can have
+ * rewritten it between launches, so "same content as last time" is
+ * not the same as "page still holds it".
+ */
+ if (ssrc != 4 && ssrc != 5 && ssrc != 6 && ssrc != 7 &&
+ svc_gl_cb_matrix_ok(buf)) {
+ memcpy(svc_gl_cb_good, buf, sizeof(svc_gl_cb_good));
+ svc_gl_cb_good_valid = true;
+ } else if (svc_gl_cb_good_valid) {
+ memcpy(buf, svc_gl_cb_good, sizeof(svc_gl_cb_good));
+ src = "cached-real";
+ ssrc = 9;
+ } else {
memset(buf, 0, sizeof(buf));
put_unaligned_le32(0x3f800000u, buf + 0x80); /* m00 */
put_unaligned_le32(0x3f800000u, buf + 0x94); /* m11 */
put_unaligned_le32(0x3f800000u, buf + 0xa8); /* m22 */
put_unaligned_le32(0x3f800000u, buf + 0xbc); /* m33 */
src = "synthetic-id";
+ ssrc = 7;
}
hash = svc_gl_cb_hash(buf, sizeof(buf));
- if (svc_gl_cb_copy_h == h_object && svc_gl_cb_copy_val == val &&
- svc_gl_cb_copy_hash == hash)
- return;
+ (void)hash;
rc = svc_grce_inline_write(vgpu, sema_gl_cb_copy_to, buf, sizeof(buf),
h_object);
- if (svc_gl_cb_copy_log < 24u) {
- u32 w0, w1;
+ if (svc_gl_cb_copy_log < 96u) {
+ u32 w[8];
- memcpy(&w0, buf, 4);
- memcpy(&w1, buf + 4, 4);
+ memcpy(w, buf, sizeof(w));
svc_gl_cb_copy_log++;
- pr_info("vgsp-sema: sema-gl: cb-copy src=0x%llx dst=0x%llx pa=0x%llx ap=%u hpa=0x%llx ssrc=%d first=%08x %08x src=%s write=%d (fixed-CB page -> forced seed page)\n",
- src_va, sema_gl_cb_copy_to, pa, ap, hpa, ssrc, w0, w1,
- src, rc);
- if (svc_gl_cb_copy_log <= 4u)
+ pr_info("vgsp-sema: sema-gl: cb-copy src=0x%llx dst=0x%llx pa=0x%llx ap=%u hpa=0x%llx ssrc=%d first8=%08x %08x %08x %08x %08x %08x %08x %08x src=%s write=%d cached=%d (fixed-CB page -> forced seed page)\n",
+ src_va, sema_gl_cb_copy_to, pa, ap, hpa, ssrc,
+ w[0], w[1], w[2], w[3], w[4], w[5], w[6], w[7],
+ src, rc, svc_gl_cb_good_valid ? 1 : 0);
+ if (svc_gl_cb_copy_log <= 12u)
svc_gl_cb_dump_matrix(buf, src, pa, ap, ssrc);
}
if (!rc) {