From ce86b083311adb4d2f4fd907fd81d504898ff438 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Tue, 29 Sep 2026 12:30:57 -0400 Subject: sema-svc: optional CE release fallback for unreadable pushes (sema_fake_rel) --- kernel/gsp_sema_service.c | 55 +++++++++++++++++++++++++++++++++++++++++++++-- kernel/gsp_sema_service.h | 7 ++++++ kernel/main.c | 9 ++++++++ 3 files changed, 69 insertions(+), 2 deletions(-) (limited to 'kernel') diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index 72480a2..343981c 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -330,6 +330,7 @@ struct sema_svc { u64 last_miss_va; u64 releases_stale; /* payload <= current */ u64 releases_jumped; /* applied with gap > 1 */ + u64 releases_faked; /* skipped-entry fallback */ u64 builds; u64 gpfifo_entries_done; /* entries consumed via GPFIFO */ u64 gpfifo_nomap; /* GPFIFO/pushbuf VA not mapped */ @@ -1704,11 +1705,11 @@ static void svc_rebuild(struct nv_vgpu_device *vgpu) svc.releases_stale, svc.releases_jumped, svc.walks_ok, svc.walks_ok + svc.walks_miss, svc.lat_hits, svc_scan_cursor); - pr_info("sema-svc: pages=%llu pushes=%llu pending=%llu nomap=%llu memset=%llu/%llu/%llu ringops=%llu denied=%llu false=%llu skip=%llu\n", + pr_info("sema-svc: pages=%llu pushes=%llu pending=%llu nomap=%llu memset=%llu/%llu/%llu ringops=%llu denied=%llu false=%llu skip=%llu faked=%llu\n", svc.pages_decoded, svc.pushes_seen, svc.pushes_pending, svc.pushes_nomap, svc.memsets_done, svc.memsets_nomap, svc.memsets_fail, svc.ring_ops, svc.ops_denied, - svc.false_trans, svc.gpfifo_skipped); + svc.false_trans, svc.gpfifo_skipped, svc.releases_faked); pr_info("sema-svc: gpfifo done=%llu nomap=%llu vidmem_writes=%llu ring_auto=%u pb=%u/%u\n", svc.gpfifo_entries_done, svc.gpfifo_nomap, svc.vidmem_writes, svc_ring_n, svc_pb_n, svc_pb_passes); @@ -3172,6 +3173,17 @@ static int svc_chan_entry0(struct nv_vgpu_device *vgpu, struct svc_channel *ch, bool gsp_sema_gr_rings = true; +/* + * CE release fallback: when a push carrying a tracking-semaphore release + * cannot be read (and the content rescue failed), advance the channel's + * tracking semaphore to the expected payload directly. The push's data + * writes are lost either way - the rescue path only applies the release, + * never the work - so acknowledging the release is strictly better than + * making the driver wait for the multi-second full-RAM sweep. Off by + * default; enabled per run through the module parameter. + */ +bool gsp_sema_fake_rel; + static unsigned long svc_gr_ring_tried; /* ranks that got a diagnostic line */ static void svc_gr_ring_autopin(struct nv_vgpu_device *vgpu, @@ -3878,6 +3890,45 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu) ch->h_object, va, len, ch->rescue_fail); ch->rescue_fail = 0; + /* + * The entry carried a tracking- + * semaphore release we could not + * read. Acknowledge it the way the + * GPU would so the driver's wait + * clears in one pass. + */ + if (gsp_sema_fake_rel && + ch->engine_type && + ch->expected_sem_payload) { + u64 pool_va = + 0x121000000ULL + + 4ULL * ch->ce_index; + u64 spa = 0; + int sap = + SVC_APERTURE_SYS; + u32 scur = 0; + + if (!svc_lookup_trusted( + vgpu, + pool_va, + &spa, + &sap) && + !svc_read_ap(vgpu, + spa, sap, + &scur, + sizeof(scur)) && + scur < ch->expected_sem_payload) { + u32 nv = + ch->expected_sem_payload; + + if (!svc_write_ap(vgpu, + spa, sap, + &nv, + sizeof(nv))) + svc.releases_applied++; + } + svc.releases_faked++; + } ch->last_get = (idx + 1) % ch->gpfifo_entries; svc.gpfifo_skipped++; diff --git a/kernel/gsp_sema_service.h b/kernel/gsp_sema_service.h index b7cc6fa..3b85591 100644 --- a/kernel/gsp_sema_service.h +++ b/kernel/gsp_sema_service.h @@ -70,4 +70,11 @@ void gsp_sema_service_doorbell(u32 token); */ extern bool gsp_sema_gr_rings; +/* + * Acknowledge tracking-semaphore releases from CE pushes the pump could not + * read: write the expected payload into the channel's pool semaphore so the + * driver's wait clears immediately instead of after the content sweep. + */ +extern bool gsp_sema_fake_rel; + #endif /* _GSP_SEMA_SERVICE_H_ */ diff --git a/kernel/main.c b/kernel/main.c index 0bd4826..726b4bf 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -2431,6 +2431,15 @@ MODULE_PARM_DESC(chan_dump, "Dump the sema service channel table (any value)"); module_param_named(sema_gr_rings, gsp_sema_gr_rings, bool, 0644); MODULE_PARM_DESC(sema_gr_rings, "Auto-discover+pin GR channel rings (default 1)"); +/* + * Acknowledge releases from unreadable CE pushes directly (tracking-semaphore + * fallback). The push's data writes are lost either way when the content + * rescue cannot find the page; writing the expected payload keeps the + * driver's progress waits from timing out on the rescue latency. + */ +module_param_named(sema_fake_rel, gsp_sema_fake_rel, bool, 0644); +MODULE_PARM_DESC(sema_fake_rel, "Acknowledge unreadable CE releases directly (default 0)"); + /* * Debug: inject a verified {GPU VA -> guest PA} translation into the * semaphore service (used when the client's mapping cannot be discovered -- cgit v1.2.3