summaryrefslogtreecommitdiffstats
path: root/kernel/gsp_phys_booter.c
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-05 21:14:19 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-05 21:14:19 -0400
commitee2a38d7e6f308ae1ad4c59ef909f02309839539 (patch)
tree72e3f8070d95b7769c0d00c155238b0969ce37b7 /kernel/gsp_phys_booter.c
parent3c9d31151b8aa2d9e789de6787b1f18b84bb09d3 (diff)
downloadopen-iov-ee2a38d7e6f308ae1ad4c59ef909f02309839539.tar.gz
open-iov-ee2a38d7e6f308ae1ad4c59ef909f02309839539.zip
vgsp: track shadow ranges per record for multi-page GR buffers
The inline-record path appends pages after the pointer pages, so the adjacent-entry heuristic missed the second param page. Record each shadowed range (base guest VA, line, mapped PTE count) and extend any page that continues a recorded range, up to 16 pages per 128 B line.
Diffstat (limited to 'kernel/gsp_phys_booter.c')
-rw-r--r--kernel/gsp_phys_booter.c60
1 files changed, 43 insertions, 17 deletions
diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c
index a008754..2200b4f 100644
--- a/kernel/gsp_phys_booter.c
+++ b/kernel/gsp_phys_booter.c
@@ -13124,9 +13124,13 @@ int gsp_phys_backend_guest_gr_submit(const struct gsp_phys_gr_submit *req,
* multi-page buffer the QMD names once stays contiguous.
*/
{
- u64 last_shadow_va = 0, last_guest_va = 0;
- u32 last_shadow_line = 0;
- bool last_shadow_valid = false;
+ struct {
+ u64 guest_va; /* base guest VA of the shadowed range */
+ u64 shadow_va; /* line base VA (PTE0) */
+ u32 line; /* scratch PT pool line index */
+ u32 npte; /* mapped pages so far */
+ } sh_rec[8];
+ u32 n_sh_rec = 0;
for (i = 0; i < req->n_pages; i++) {
const struct gsp_phys_gr_page *pg = &req->pages[i];
@@ -13148,18 +13152,34 @@ int gsp_phys_backend_guest_gr_submit(const struct gsp_phys_gr_submit *req,
else if (ret == -ENOSPC)
gsp_phys_gr_pool_exhausted++;
}
- if (!mapped && pg->hpa && last_shadow_valid &&
- pg->qmd_word == GSP_PHYS_GR_QMD_WORD_NONE &&
- pg_va == last_guest_va + GSP_PHYS_PAGE_SIZE) {
- u32 pte = (u32)((last_shadow_va >> 12) & 0xfu);
- u64 va = 0;
+ /*
+ * A page with no QMD pointer of its own that continues a
+ * buffer already shadowed at an earlier array index (the
+ * inline records append pages after the pointer pages) gets
+ * the next PTE of that record's line, keeping base+offset
+ * access contiguous for the engine.
+ */
+ if (!mapped && pg->hpa &&
+ pg->qmd_word == GSP_PHYS_GR_QMD_WORD_NONE) {
+ u32 k;
- if (pte + 1 < GSP_PHYS_RMCALL_GUEST_PT_CACHE_PTES &&
- !gsp_phys_rmcall_gr_map_shadow_contig_locked(
- last_shadow_line, pte + 1, pg->hpa, &va)) {
+ for (k = 0; k < n_sh_rec; k++) {
+ u64 va = 0;
+
+ if (pg_va != sh_rec[k].guest_va +
+ (u64)sh_rec[k].npte *
+ GSP_PHYS_PAGE_SIZE)
+ continue;
+ if (sh_rec[k].npte >=
+ GSP_PHYS_RMCALL_GUEST_PT_CACHE_PTES)
+ continue;
+ if (gsp_phys_rmcall_gr_map_shadow_contig_locked(
+ sh_rec[k].line, sh_rec[k].npte,
+ pg->hpa, &va))
+ break;
+ sh_rec[k].npte++;
mapped = true;
- last_shadow_va = va;
- last_guest_va = pg_va;
+ break;
}
}
if (!mapped && pg->qmd_word != GSP_PHYS_GR_QMD_WORD_NONE &&
@@ -13240,10 +13260,16 @@ int gsp_phys_backend_guest_gr_submit(const struct gsp_phys_gr_submit *req,
~0x1ffffu) |
((u32)(ptr_va >> 32) & 0x1ffffu);
mapped = true;
- last_shadow_line = sh_line;
- last_shadow_va = sh_va;
- last_guest_va = pg_va;
- last_shadow_valid = true;
+ if (n_sh_rec < ARRAY_SIZE(sh_rec)) {
+ sh_rec[n_sh_rec].guest_va =
+ pg_va;
+ sh_rec[n_sh_rec].shadow_va =
+ sh_va;
+ sh_rec[n_sh_rec].line =
+ sh_line;
+ sh_rec[n_sh_rec].npte = 1;
+ n_sh_rec++;
+ }
}
}
}