From 436cbf9d39677d17bc340b7dc35bd8ad3e601606 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Fri, 13 Nov 2026 10:20:00 -0500 Subject: vgsp: extend the live PA acceptance bound to the registered guest-RAM top (svc_pa_max/svc_push_pa_ceiling) The direct-GL client parks its VAS page directory and push pages in the 4-14 GiB high RAM band while the runtime bound stopped at 10 GiB (param/compile), so svc_ap_ok rejected every walk read above 10 GiB before vfio_dma_rw could answer: the client ring walk reported 'L0 read fail' / 'walk rc=-2' on the one boot the RAM content scan latched the real ring (c296), and the push bodies stayed unreadable (src=3 window garbage / src=255). svc_pa_max() now never shrinks below the registered guest-RAM top (sanity-clamped to the scan max), and svc_push_pa_ceiling() floors on the same live bound. c297 (first boot with the fix): 'RING-VAS h=0xbeef0100 gpfifo=0x4020000 mapped by VAS 0xbeef0300 (pdb=0x110aae000) -> pa=0x23771f000' and pushdec 'src=4 plausible=1' with the read ceiling witness ceil=0x380000000. --- kernel/gsp_sema_service.c | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) (limited to 'kernel/gsp_sema_service.c') diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index 83ab2db..9730c58 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -283,9 +283,30 @@ static bool gsp_sema_ce_ram; static inline u64 svc_pa_max(void) { u64 top = READ_ONCE(gsp_sema_gr_scan_top); + u64 reg = gsp_phys_guest_ram_top(); if (!top || top > SEMA_PA_MAX) - return SEMA_PA_MAX; + top = SEMA_PA_MAX; + /* + * CONT.478: the registered guest-RAM ranges are readable content + * truth - extend (never shrink) the live bound to the registered top. + * On the 12 GiB boot the guest's system RAM reaches GPA 0x380000000 + * (the 4-14 GiB high band) while the param/compile bounds stopped at + * 10 GiB, so svc_ap_ok rejected every page-table walk and push read + * above 10 GiB before vfio_dma_rw could answer: the direct-GL client + * parks its VAS page directory at 0x33e537000 (13.9 GiB) and its + * push pages in the same band, so every walk missed with "L0 read + * fail" / "walk rc=-2" while the ring page (4.3 GiB, below the old + * bound) resolved fine - entries decoded, bodies stayed unreadable. + * A read above the registered top can only return padding zeros, so + * the extension never invents content; the sanity clamp keeps a + * misregistered range from unbounding the scans. + */ + if (reg > top) { + if (reg > SVC_GR_SCAN_TOP_MAX) + reg = SVC_GR_SCAN_TOP_MAX; + top = reg; + } return top; } @@ -25947,8 +25968,17 @@ static u64 svc_push_pa_ceiling(void) if (top > SVC_GR_SCAN_TOP_MAX) top = SVC_GR_SCAN_TOP_MAX; - if (top < SEMA_PA_MAX) - top = SEMA_PA_MAX; + /* + * CONT.478: the floor is the live acceptance bound, not the old + * compile-time 10 GiB - svc_pa_max() now follows the registered + * guest-RAM top, so the read ceiling covers the same 4-14 GiB high + * band the direct-GL client's push pages live in. Without this the + * walk could resolve a push above 10 GiB and the read path would + * still reject it ("sema-pinrej ... ceiling") - the same bound bug + * on the other side of the source chain. + */ + if (top < svc_pa_max()) + top = svc_pa_max(); /* * SESSION 153-CONTINUED-67: never let the ceiling exceed the highest * GPA any registered guest-RAM range covers - a read above it can -- cgit v1.2.3