diff options
Diffstat (limited to 'kernel/gsp_phys_booter.c')
| -rw-r--r-- | kernel/gsp_phys_booter.c | 91 |
1 files changed, 64 insertions, 27 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) |
