summaryrefslogtreecommitdiffstats
path: root/kernel/gsp_sema_service.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/gsp_sema_service.c')
-rw-r--r--kernel/gsp_sema_service.c93
1 files changed, 74 insertions, 19 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c
index 444298a..4fd160e 100644
--- a/kernel/gsp_sema_service.c
+++ b/kernel/gsp_sema_service.c
@@ -3895,6 +3895,51 @@ static int svc_pool_pa_resolve(struct nv_vgpu_device *vgpu, u32 h, u64 va,
if (!svc_pool_boot_lookup(va, &pa, &a)) {
u32 bprobe = 0;
+ /*
+ * r580: the boot cache survives session flushes, but a pool
+ * page MOVES between sessions (the client's new allocation)
+ * while the old page often stays readable - the read-back
+ * proof cannot tell. The client's own page tables are the
+ * ground truth for where ITS tracker reads, so try the
+ * structural walk BEFORE trusting the cache: a differing,
+ * read-proven walk page wins and the cached page stays as the
+ * fan-out's secondary candidate. Live evidence (r579 boot):
+ * releases were written to the stale cache pa=0x11e6d9000
+ * while the current page was 0x134730000 (the pin) and the
+ * client's tracker starved; the pool-wr line said
+ * src=bootcache.
+ */
+ {
+ u64 wpa2 = 0;
+ int wap2 = SVC_APERTURE_SYS;
+ bool walk_hit = false;
+
+ if (!svc_walk_discovered(vgpu, page, &wpa2, &wap2) ||
+ !svc_walk_vaspaces(vgpu, page, &wpa2, &wap2))
+ walk_hit = true;
+ if (walk_hit &&
+ (wpa2 & ~(u64)(SEMA_PAGE_SIZE - 1)) !=
+ (pa & ~(u64)(SEMA_PAGE_SIZE - 1)) &&
+ !svc_pool_pa_identity(va, wpa2)) {
+ u64 exact = (wpa2 & ~(u64)(SEMA_PAGE_SIZE - 1)) |
+ (va & (SEMA_PAGE_SIZE - 1));
+
+ if (!svc_read_ap(vgpu, exact, svc_ap_of(wap2),
+ &bprobe, sizeof(bprobe))) {
+ svc_pool_boot_store(va, pa, a);
+ svc_pool_pa_store(va, exact, wap2);
+ svc_tr_clear_failure(page);
+ if (src)
+ *src = "walk-over-boot";
+ svc_pool_pa_note(h, va, exact,
+ "walk-over-boot");
+ *addr = exact;
+ *ap = wap2;
+ return 0;
+ }
+ }
+ }
+
if (!svc_read_ap(vgpu, pa, svc_ap_of(a), &bprobe,
sizeof(bprobe))) {
svc_tr_clear_failure(page);
@@ -25633,6 +25678,32 @@ static int svc_thread(void *arg)
* progress. (With two guests, any guest's progress keeps the
* loop tight; the next iteration pumps both.)
*/
+ /*
+ * r580: the completion hint must also run while the pump is
+ * making progress - the fast path below skips it, and a
+ * completion burst saturates the event burst budget and drops
+ * wake-ups (r579 boot: events_dropped=724; the sentinel
+ * "no postable event (events_n=8 dropped=724)" repeated every
+ * 0.5 s). A client that starts waiting mid-burst needs the
+ * 0.5 s re-post even under load; the per-event dedup keeps the
+ * extra volume bounded.
+ */
+ for (g = 0; g < n_vgpus; g++) {
+ vgpu = vgpus[g];
+ if (time_before(jiffies,
+ (unsigned long)svc.post_hint_until) &&
+ time_after(jiffies,
+ (unsigned long)svc.last_hint + HZ / 2)) {
+ int rc;
+
+ svc.last_hint = jiffies;
+ rc = gsp_rm_post_all_events(vgpu);
+ if (gsp_sema_dbg)
+ pr_info_ratelimited("sema-svc: completion hint rc=%d\n",
+ rc);
+ }
+ }
+
if (pumped) {
msleep(1);
continue;
@@ -25644,30 +25715,14 @@ static int svc_thread(void *arg)
/*
* Push-buffer base discovery: a chunked walk of guest
* RAM finds the pages whose first push names a
- * channel, so a channel that appears with work
- * already waiting is pinned and pumped without
- * waiting for the rolling sweep.
*/
svc_pb_discover(vgpu);
/*
- * Completion hint: re-post the events for a few
- * seconds after a completion, so a client that starts
- * waiting after the edge-triggered wake-up still
- * observes it.
+ * r580: the completion hint was hoisted above the
+ * pumped fast path (it must run under load too); it is
+ * not repeated here.
*/
- if (time_before(jiffies,
- (unsigned long)svc.post_hint_until) &&
- time_after(jiffies,
- (unsigned long)svc.last_hint + HZ / 2)) {
- int rc;
-
- svc.last_hint = jiffies;
- rc = gsp_rm_post_all_events(vgpu);
- if (gsp_sema_dbg)
- pr_info_ratelimited("sema-svc: completion hint rc=%d\n",
- rc);
- }
/*
* Fast path for the pushes themselves: every mapped