diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-18 03:15:35 -0400 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-18 03:15:54 -0400 |
| commit | 6f7afe700f0919da50533568d48a44d5d158adb7 (patch) | |
| tree | 7d42a6100bc448902ab771dafbee8020b170e827 /kernel/gsp_sema_service.c | |
| parent | 0892871eda284756b232e1ab157b0b4e170930cc (diff) | |
| download | open-iov-6f7afe700f0919da50533568d48a44d5d158adb7.tar.gz open-iov-6f7afe700f0919da50533568d48a44d5d158adb7.zip | |
vgsp: m181 relocation-page unification - launch-internal pages (param/program/banks) resolve through the landing table; zero-write diagnostics
Audit of the QMD relocation/mirror path vs the m180 landing table (r210
evidence: /tmp dmesg, 0 ledger DIVERGE, four multi-page clients still
wrong, 3 zero-write NO-STORES accepts):
The relocation itself does NOT pick PAs: gsp_phys_gr_rewrite_data_vars()
matches a device-VA-shaped 8-byte value against req->data[x].va (the
fill's gr_data list, which m180 fed through the ledger) and rewrites it to
req->data[x].reloc_va. The bounce page for reloc_va is the same page the
tracking wait and the copy-out use, so a *matched* pointer is ledger-
consistent by construction. The un-unified halves of that path are the
page the relocation READS and the page the m129 mirror PATCHES: both come
from pg->pa, resolved by svc_gr_page_note() with the independent sources
(pin/lat/map/walks/scan), never the landing table. The CE inline writes
that author those launches' param/program/bank pages go through
svc_grce_inline_write(), which (m180) records its landing and diverges to
it; svc_gr_page_note could still hand the win0 shadow copy and the mirror
a stale page. Consequences, both observed classes: relocation matches
nothing (the page holds another session's pointers) -> the engine runs
against unrelocated guest VAs it cannot walk -> grid aborts with zero
stores while the ack still lands; or the engine executes on a previous
client's parameter block -> plausible-but-wrong results invisible to the
ledger.
Fix (kernel/gsp_sema_service.c):
- svc_gr_page_note() consults svc_ledger_lookup() first for every
launch-internal page. On a hit it uses the recorded landing (and pins
it, so later resolves and the win0 copy path agree); when the
independent sources would answer differently it logs (bounded)
"sema-ledger: RELOC-DIVERGE va=... ledger_pa=... <src>_pa=... (ledger
wins)" - the requested relocation-vs-ledger witness. Non-hit pages keep
the historical svc_resolve_va path unchanged.
Diagnostics (kernel/gsp_phys_booter.c):
- the m135 below-0x100 guard now shape-checks first and logs
"bank N RELOC-SKIP @off: value is operand page ... (left guest-VA)".
r210 shows the same offset-0 bank pointer in EVERY client (green ones
included: the driver control block), so the guard is unchanged until a
dereferenced pointer in that range is proven; the log makes that
provable in one cycle.
- the zero-write accept now also dumps the deposit QMD words
(gsp_phys_gr_deposit_rb_log) so the next NO-STORES event shows whether
the engine consumed the header words, and the dual-bank sentinel line
is reworded to state facts only (the other bank is normally the
previous launch's legitimately-consumed deposit; the earlier "older
deposit consumed" reading was misleading). r210 classification: all
three NO-STORES events had THIS deposit fetched (sentinel overwritten)
and 0/968..0/967 stores even at +1 s, i.e. engine-side non-execution of
a fetched deposit - consistent with the stale-launch-page abort
mechanism above; the deposit-readback words will discriminate further.
Not changed (deliberate): the m135 guard semantics, the relocation
targets, the sentinel contract, retry/accept policy, and every semaphore
path (mm2/gate/rewind effects untouched).
make kernel -j green (srcversion DAB7E3AA75D364382DD6A3C; only the
pre-existing gsp_phys_rmcall_stage3 printf warning). Main tree untouched;
nothing pushed.
Diffstat (limited to 'kernel/gsp_sema_service.c')
| -rw-r--r-- | kernel/gsp_sema_service.c | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index 1cb771a..ccccfec 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -4794,6 +4794,7 @@ static u32 svc_ledger_n; static u64 svc_ledger_diverges; static u64 svc_ledger_stores; static u64 svc_ledger_rewrites; +static u64 svc_ledger_reloc_diverges; static u32 svc_ledger_store_log; static inline u32 svc_ledger_home(u64 page) @@ -4881,6 +4882,7 @@ static void svc_ledger_clear(void) memset(svc_ledger, 0, sizeof(svc_ledger)); svc_ledger_n = 0; svc_ledger_rewrites = 0; + svc_ledger_reloc_diverges = 0; } static int svc_copy(struct nv_vgpu_device *vgpu, u64 dst, u64 src, size_t total, @@ -13962,6 +13964,8 @@ static void svc_fwd_relay_select(struct svc_fwd_req *req) * svc_gr_req_fill from its QMD pointer association and the captured inline * bytes. Overflow is a failure (fail-closed), not a silent drop. */ +static const char *svc_gr_src_probe(struct nv_vgpu_device *vgpu, u64 va, + u64 *pa_out, u32 *ap_out); static void svc_gr_page_note(struct nv_vgpu_device *vgpu, u64 va, u32 qmd_word) { u64 page = va & ~(u64)(SEMA_PAGE_SIZE - 1); @@ -13986,6 +13990,58 @@ static void svc_gr_page_note(struct nv_vgpu_device *vgpu, u64 va, u32 qmd_word) i = svc_fwd_req.gr_n_pages++; svc_fwd_req.gr_pages[i].va = page; svc_fwd_req.gr_pages[i].qmd_word = qmd_word; + /* + * m181 (relocation/ledger unification): the unified landing table is + * the authority for a page a host write already landed on. The CE + * inline writes that author these launch pages (param, program, + * constant banks, inline destinations) go through + * svc_grce_inline_write(), which records its landing. The backend's + * QMD relocation reads the page content through pg->pa (win0 shadow + * copy) and the m129 mirror patches that same page, so resolving + * independently here could hand the engine a stale page whose + * pointer values are not this launch's VAs: the relocation then + * matches nothing, the engine executes against unrelocated guest VAs + * it cannot walk, and the grid aborts silently (zero stores, ack + * still delivered) - the cross-session zero-write class - or runs on + * the previous client's parameters (the multi-page wrongness). + * Resolve once, from the table, and record the independent answer as + * stale when it differs. + */ + { + u64 lpa = 0; + u32 lap = 0; + + if (!svc_ledger_lookup(page, &lpa, &lap)) { + u64 rpa = 0; + u32 rap = 0; + const char *rsrc = svc_gr_src_probe(vgpu, page, &rpa, + &rap); + + if (rpa && + ((lpa & ~(u64)(SEMA_PAGE_SIZE - 1)) != + (rpa & ~(u64)(SEMA_PAGE_SIZE - 1)) || + (u32)lap != (u32)rap)) { + svc_ledger_reloc_diverges++; + if (svc_ledger_reloc_diverges <= 16) + pr_info("sema-ledger: RELOC-DIVERGE va=0x%llx ledger_pa=0x%llx %s_pa=0x%llx (ledger wins)\n", + page, + lpa & ~(u64)(SEMA_PAGE_SIZE - 1), + rsrc, rpa & + ~(u64)(SEMA_PAGE_SIZE - 1)); + } + svc_fwd_req.gr_pages[i].pa = + lpa & ~(u64)(SEMA_PAGE_SIZE - 1); + svc_fwd_req.gr_pages[i].ap = (u8)lap; + /* + * Keep the pin table consistent with the authority so + * the win0 copy path and later resolves agree (and no + * stale self-pin is planted for this VA). + */ + svc_pin_store(page, lpa & ~(u64)(SEMA_PAGE_SIZE - 1), + (int)lap); + return; + } + } if (svc_resolve_va(vgpu, page, &pa, &ap)) return; svc_fwd_req.gr_pages[i].pa = pa & ~(u64)(SEMA_PAGE_SIZE - 1); |
