diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-11-09 14:05:39 -0500 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-11-09 14:05:39 -0500 |
| commit | 3701f985edb89224f6a5c1237b21ddb8e527e126 (patch) | |
| tree | 4843a6f76df8e05cd50088c888007fed0f99206f | |
| parent | a47a2124d4c8110e9cfb6fb500a108bcea7becb4 (diff) | |
| download | open-iov-3701f985edb89224f6a5c1237b21ddb8e527e126.tar.gz open-iov-3701f985edb89224f6a5c1237b21ddb8e527e126.zip | |
vgsp-sema: resolve the scrubber's finish words through the GPU page tables
The guest PMA scrubber's host-side completion (channel buffer + pbSize +
entries*8) was resolved through the learned VA->PA pair map first. When
the guest reused the scrubber's GPU VA for a new channel buffer, that map
still named the previous allocation's page, and the host authored the
finish payload there while the guest polled the new page through its
kernel VAS (h=0xc). r1667 live proof: walk_probe 0x12006c000 -> only
VAS[1] (h=0xc) resolves to PA 0x10812a000 (the page the guest's vmalloc
mapping of the channel buffer points at, and the value it polls); the
pair map returned 0x10526a000. Writing the finish value to the correct
page (via the guest scanner registration) immediately released Xorg from
the RM memory-manager wait and the queued GSP status records drained.
Changes:
- svc_scrub_pass(): resolve hsem/fin through svc_walk_vaspaces() first,
fall back to the pair map only when no VAS maps the VA.
- Struct svc_scrub gains authored_gen; a new pa_gen (fresh scanner
registration or a corrected derivation) forces one authoring pass even
when the scrubber's PUT did not advance, so an already-waiting guest
is released without a new submission.
| -rw-r--r-- | kernel/gsp_sema_service.c | 18 |
1 files changed, 15 insertions, 3 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index 1b77ea0..7f61c57 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -1068,6 +1068,7 @@ struct svc_scrub { u32 put_last; u64 submitted; /* blocks submitted since seeding */ u64 authored; /* last authored finish value */ + u32 authored_gen; /* pa_gen at the last authored write */ u32 pa_gen; /* scanner registration generation (logged) */ u32 session_gen; /* m176: session generation of the last registration */ u32 log_budget; @@ -45344,8 +45345,17 @@ static void svc_scrub_pass(struct nv_vgpu_device *vgpu) u64 pa = 0; int ap = SVC_APERTURE_SYS; - if (svc_lookup(vgpu, hva, &pa, &ap) || !pa) { - if (svc_walk_vaspaces(vgpu, hva, &pa, &ap) || !pa) + /* + * r1667: resolve through the GPU page tables FIRST. The learned + * VA->PA pair map can name a stale page for a reused VA (the guest + * polls its scrubber finish word through the kernel VAS h=0xc, + * which the walk resolves correctly, while svc_lookup returned an + * old page from a previous allocation and the scrub wait never + * completed). Fall back to the pair map only when no walkable VAS + * maps the VA. + */ + if (svc_walk_vaspaces(vgpu, hva, &pa, &ap) || !pa) { + if (svc_lookup(vgpu, hva, &pa, &ap) || !pa) pa = 0; } /* The scrub words are guest RAM; an FB translation is not. */ @@ -45412,7 +45422,8 @@ static void svc_scrub_pass(struct nv_vgpu_device *vgpu) delta = s->entries; /* exact wrap */ s->submitted += delta; s->put_last = put; - } else if (s->submitted == s->authored) { + } else if (s->submitted == s->authored && + s->authored_gen == s->pa_gen) { return; /* nothing new; no guest writes */ } @@ -45438,6 +45449,7 @@ static void svc_scrub_pass(struct nv_vgpu_device *vgpu) sizeof(fin)); } s->authored = s->submitted; + s->authored_gen = s->pa_gen; } /* |
