summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/gsp_phys_booter.c91
-rw-r--r--kernel/gsp_sema_service.c35
2 files changed, 97 insertions, 29 deletions
diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c
index 67092b7..72b500a 100644
--- a/kernel/gsp_phys_booter.c
+++ b/kernel/gsp_phys_booter.c
@@ -16486,6 +16486,15 @@ int gsp_phys_backend_guest_gr_submit(const struct gsp_phys_gr_submit *req,
static u32 sked_sample[11];
static u32 sked_tick;
static bool sked_first;
+ /*
+ * m142: per-bounce-page checksums captured at copy-in. The copy-out
+ * compares them to report how many pages the engine actually modified;
+ * an all-unchanged window after a reported completion is the
+ * "front-end ran, grid never dispatched / read zeros" signature that
+ * previously masqueraded as a successful launch. Safe as static: the
+ * only caller is the single-inflight ordered gsp-phys-work item.
+ */
+ static u32 bounce_csum_in[GSP_PHYS_RMCALL_GR_MAIL_SLOT];
sked_tick = 0;
sked_first = true;
u32 qmd_win_pde = 0, qmd_win_installed = 0;
@@ -17259,6 +17268,49 @@ gr_page_unmapped:
}
}
+ /*
+ * m142: copy the guest data pages into the bounce window BEFORE the
+ * doorbell. This block used to run after gsp_phys_rmcall_publish_locked()
+ * kicked the engine: the engine front end starts executing as soon as
+ * the doorbell rings (observed ~7 ms, not guaranteed), so the kernel
+ * could read the bounce window before it was filled. Filling first
+ * removes the race entirely; per-page checksums are kept so the
+ * copy-out can prove whether the engine modified the window at all.
+ */
+ if (req->n_data && boot_stage.rmcall_gr_bounce.pages) {
+ u32 dcopied = 0, dfailed = 0, di;
+
+ for (di = 0; di < req->n_data; di++) {
+ u32 bi = (u32)((req->data[di].reloc_va -
+ GSP_PHYS_RMCALL_GR_BOUNCE_VA0) >>
+ 12);
+ const u8 *src;
+ u8 *dst;
+ u32 ci = 0, csum = 0;
+
+ if (bi >= GSP_PHYS_RMCALL_GR_MAIL_SLOT ||
+ !req->data[di].hpa) {
+ dfailed++;
+ continue;
+ }
+ src = (const u8 *)__va(req->data[di].hpa);
+ dst = gsp_phys_chunk_page_va(
+ &boot_stage.rmcall_gr_bounce, bi);
+ memcpy(dst, src, GSP_PHYS_PAGE_SIZE);
+ for (ci = 0; ci < GSP_PHYS_PAGE_SIZE; ci += 4)
+ csum += get_unaligned_le32(dst + ci);
+ bounce_csum_in[bi] = csum;
+ dcopied++;
+ }
+ dma_wmb();
+ pr_info("vgsp-gr: bounce copy-in: %u pages, %u skipped (pre-publish)\n",
+ dcopied, dfailed);
+ for (di = 0; di < req->n_data && di < 3; di++)
+ pr_info("vgsp-gr: data[%u] va=0x%llx hpa=0x%llx reloc=0x%llx\n",
+ di, req->data[di].va, req->data[di].hpa,
+ req->data[di].reloc_va);
+ }
+
ret = gsp_phys_rmcall_publish_locked(bar0, boot_stage.rmcall_va_pb,
words, &sub);
mutex_unlock(&gsp_phys_rm_lock);
@@ -17293,27 +17345,6 @@ gr_page_unmapped:
}
}
if (req->n_data && boot_stage.rmcall_gr_bounce.pages) {
- u32 dcopied = 0, dfailed = 0, di;
-
- for (di = 0; di < req->n_data; di++) {
- u32 bi = (u32)((req->data[di].reloc_va -
- GSP_PHYS_RMCALL_GR_BOUNCE_VA0) >>
- 12);
-
- if (bi >= GSP_PHYS_RMCALL_GR_MAIL_SLOT ||
- !req->data[di].hpa) {
- dfailed++;
- continue;
- }
- memcpy(gsp_phys_chunk_page_va(
- &boot_stage.rmcall_gr_bounce, bi),
- (u8 *)__va(req->data[di].hpa),
- GSP_PHYS_PAGE_SIZE);
- dcopied++;
- }
- dma_wmb();
- pr_info("vgsp-gr: bounce copy-in: %u pages, %u skipped\n",
- dcopied, dfailed);
if (gsp_phys_rmcall_gr_recommit_value()) {
struct gsp_phys_rmcall_pdb_params rp;
struct {
@@ -17725,24 +17756,30 @@ gr_page_unmapped:
* by the kernels, so copying them back is a no-op.
*/
if (req->n_data && boot_stage.rmcall_gr_bounce.pages) {
- u32 wbi, wrote = 0;
+ u32 wbi, wrote = 0, changed = 0;
for (wbi = 0; wbi < req->n_data; wbi++) {
u32 bi = (u32)((req->data[wbi].reloc_va -
GSP_PHYS_RMCALL_GR_BOUNCE_VA0) >>
12);
+ const u8 *src;
+ u32 ci, csum = 0;
if (bi >= GSP_PHYS_RMCALL_GR_MAIL_SLOT ||
!req->data[wbi].hpa)
continue;
- memcpy((u8 *)__va(req->data[wbi].hpa),
- gsp_phys_chunk_page_va(
- &boot_stage.rmcall_gr_bounce, bi),
+ src = gsp_phys_chunk_page_va(
+ &boot_stage.rmcall_gr_bounce, bi);
+ for (ci = 0; ci < GSP_PHYS_PAGE_SIZE; ci += 4)
+ csum += get_unaligned_le32(src + ci);
+ if (csum != bounce_csum_in[bi])
+ changed++;
+ memcpy((u8 *)__va(req->data[wbi].hpa), src,
GSP_PHYS_PAGE_SIZE);
wrote++;
}
- pr_info("vgsp-gr: bounce copy-out: %u pages written back\n",
- wrote);
+ pr_info("vgsp-gr: bounce copy-out: %u pages written back, %u changed by engine\n",
+ wrote, changed);
}
poll = w1;
if (bar0)
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c
index ee73027..ec269c5 100644
--- a/kernel/gsp_sema_service.c
+++ b/kernel/gsp_sema_service.c
@@ -12127,6 +12127,8 @@ static bool svc_gr_page_inline_covers(u64 page)
* the mail message). */
#define SVC_GR_DATA_BOUNCE_MAX 100u
+static u32 svc_gr_data_log; /* m142: bounded per-page attribution log */
+
static void svc_gr_data_fill(struct nv_vgpu_device *vgpu)
{
u64 wins[16];
@@ -12237,8 +12239,26 @@ static void svc_gr_data_fill(struct nv_vgpu_device *vgpu)
break;
if (x < svc_fwd_req.gr_n_data)
continue; /* already mapped */
- if (svc_resolve_va(vgpu, va, &pa, &ap))
- break;
+ /*
+ * m142: guest-truth injected pins first, the same order
+ * the pool resolver uses (svc_pool_pa_resolve). The
+ * learned/scanned sources can hold a stale page for a
+ * VA a previous client mapped (the dual-PA class proven
+ * on the pool semaphore, r88); a bounce built from the
+ * wrong page silently runs the kernel on zeros while
+ * every launch still reports OK.
+ */
+ {
+ u64 ipa = 0;
+ int iap = SVC_APERTURE_SYS;
+
+ if (!svc_ipin_lookup(va, &ipa, &iap)) {
+ pa = ipa;
+ ap = (u32)iap;
+ } else if (svc_resolve_va(vgpu, va, &pa, &ap)) {
+ break;
+ }
+ }
if (svc_fwd_req.gr_n_data >= SVC_GR_DATA_BOUNCE_MAX) {
pr_info("vgsp-sema: svc-gr data fill: %u candidate ptrs, %u pages resolved (reloc 0x%llx+) CAP-HIT\n",
n_cand, svc_fwd_req.gr_n_data,
@@ -12252,6 +12272,17 @@ static void svc_gr_data_fill(struct nv_vgpu_device *vgpu)
((u64)svc_fwd_req.gr_n_data << 12);
rec->ap = (u8)svc_ap_of(ap);
svc_fwd_req.gr_n_data++;
+ /*
+ * m142: bounded per-page attribution log. A wrong data
+ * page is invisible in the aggregate counters; these
+ * lines let a post-mortem compare the chosen PA against
+ * the guest's own mapping.
+ */
+ if (svc_gr_data_log < 16) {
+ svc_gr_data_log++;
+ pr_info("vgsp-sema: svc-gr data page va=0x%llx -> pa=0x%llx ap=%u\n",
+ va, rec->pa, rec->ap);
+ }
}
(void)base;
pr_info("vgsp-sema: svc-gr candidate[%u] base=0x%llx -> %u new pages (total %u)\n",