From a94c1b0ed4fd8043e3235fe337bf8d0f2472f9f5 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Wed, 30 Sep 2026 06:44:10 -0400 Subject: sema-svc: destination-keyed copy watch (dump page-table writes) sema_copy_dst=dumps the source bytes of every copy whose destination falls in the given page, so the 32-byte page-directory updates the guest writes into vidmem can be read directly and their entry encoding learned. --- kernel/gsp_sema_service.c | 34 ++++++++++++++++++++++++++++++++++ kernel/gsp_sema_service.h | 3 +++ kernel/main.c | 8 ++++++++ 3 files changed, 45 insertions(+) (limited to 'kernel') diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index db52299..018e28c 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -345,6 +345,7 @@ struct sema_svc { u64 lda_log; /* LAUNCH_DMA inventory budget */ u64 copy_watch_log; /* sema_copy_watch log budget */ u64 copy_pat_log; /* sema_copy_pat log budget */ + u64 copy_dst_log; /* sema_copy_dst log budget */ u64 push_pat_log; /* push-content pattern budget */ u64 dma_skip_log; /* unrecognized-DMA budget */ u64 grce_log; /* GRCE inline-write budget */ @@ -2098,6 +2099,32 @@ static int svc_copy(struct nv_vgpu_device *vgpu, u64 dst, u64 src, size_t total, } } + /* + * Destination-keyed watch: dump the source bytes of every copy whose + * destination lies in gsp_sema_copy_dst's page. This reads the + * page-table entries the guest writes into vidmem directly. + */ + if (gsp_sema_copy_dst && + (dst & ~0xfffULL) == (gsp_sema_copy_dst & ~0xfffULL) && + svc.copy_dst_log < 32) { + u8 peek[32]; + u32 n = total < sizeof(peek) ? (u32)total : sizeof(peek); + + memset(peek, 0, sizeof(peek)); + if (src_aperture == CE_APERTURE_VID) { + u8 *base = vgpu->bars[1].vaddr; + + if (base && src + n <= vgpu->bars[1].size) + memcpy(peek, base + src, n); + } else { + svc_read(vgpu, src, peek, n); + } + svc.copy_dst_log++; + pr_info("sema-copy-dst: dst=0x%llx off=0x%llx total=%zu src=0x%llx sap=%u data=%*phN h=0x%x\n", + dst, dst & 0xfffULL, total, src, src_aperture, + n, peek, svc.cur_ch); + } + for (o = 0; o < total; ) { size_t chunk = total - o; u32 i; @@ -3943,6 +3970,13 @@ unsigned gsp_sema_copy_watch; */ u64 gsp_sema_copy_pat; +/* + * Data-path watch: log copies whose destination falls in this address's + * page, dumping the source bytes. Used to read the page-table entries the + * guest writes to vidmem (32-byte PD updates) and learn their encoding. + */ +u64 gsp_sema_copy_dst; + /* * Grace window (ms) an untranslatable CE entry stays pending before the * fallback acknowledges its release and consumes it. The push's work (data diff --git a/kernel/gsp_sema_service.h b/kernel/gsp_sema_service.h index 234ec2f..51397b9 100644 --- a/kernel/gsp_sema_service.h +++ b/kernel/gsp_sema_service.h @@ -100,6 +100,9 @@ extern unsigned gsp_sema_copy_watch; /* Data-path watch: 8-byte value matched in copy src/dst and push bytes. */ extern u64 gsp_sema_copy_pat; +/* Data-path watch: dump copies landing in this page (source bytes). */ +extern u64 gsp_sema_copy_dst; + /* CE pending-entry grace window in ms before the release fallback fires. */ extern unsigned gsp_sema_ce_grace_ms; diff --git a/kernel/main.c b/kernel/main.c index 7fe2d15..d6e6c9d 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -2475,6 +2475,14 @@ MODULE_PARM_DESC(sema_copy_watch, "Copy size whose first bytes are logged (defau module_param_named(sema_copy_pat, gsp_sema_copy_pat, ullong, 0644); MODULE_PARM_DESC(sema_copy_pat, "8-byte pattern matched in copy src/dst and pushes (default 0)"); +/* + * Data-path watch: dump the source bytes of copies whose destination falls + * in this address's page (up to 32 samples): + * echo 0x200000 > .../parameters/sema_copy_dst + */ +module_param_named(sema_copy_dst, gsp_sema_copy_dst, ullong, 0644); +MODULE_PARM_DESC(sema_copy_dst, "Dump source bytes of copies landing in this page (default 0)"); + /* * Grace window (ms) an untranslatable CE entry stays pending before the * fallback acknowledges its release and consumes it. Its work must run before -- cgit v1.2.3