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.c176
1 files changed, 171 insertions, 5 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c
index f94a768..25598bd 100644
--- a/kernel/gsp_sema_service.c
+++ b/kernel/gsp_sema_service.c
@@ -476,6 +476,15 @@ struct svc_channel {
unsigned long push_hold_until; /* absolute deadline of the bounded
* work-before-release hold for an
* unreadable CE entry (0 = none) */
+ unsigned long gr_setup_hold_until; /* SESSION 153-CONTINUED-54: absolute
+ * deadline of the GR setup-push hold:
+ * an unreadable/all-zero MME-setup
+ * (or >= 12 KB) GR push stays pending
+ * past the 1-failed-rescue consume
+ * until the demanded guest pin lands
+ * (0 = none) */
+ u64 gr_setup_hold_va; /* entry VA the setup hold was armed for */
+ u32 gr_setup_hold_idx; /* GPFIFO slot the setup hold was armed for */
unsigned long defer_since; /* first failure of the pending GR entry
* (0 = none): the entry is left pending
* for the GR grace window so a late
@@ -22025,8 +22034,111 @@ unsigned gsp_sema_ce_grace_ms = 25000;
*/
unsigned gsp_sema_push_hold_ms = 2500;
+/*
+ * SESSION 153-CONTINUED-54: GR setup-push hold.
+ *
+ * The client's 12288 B C597 MME-setup push ("LOAD_MME_* program upload")
+ * reads unreadable/all-zero on the first-read lottery boots and used to be
+ * consumed ("skipping stale entry ... after 1 failed rescues") before the
+ * demand channel's injected pin could land, so the MME prelude capture
+ * missed the macro program for the whole boot. When such a push's first
+ * read fails, demand every 4K VA page of the push through the stalled-VA
+ * demand channel (pin_gr_stream harvests the rows and the guest resolves +
+ * injects the pages) and hold the entry pending PAST the rescue-consume
+ * until the pin lands (the cheap-wait guard re-reads when it does) or this
+ * window expires. Bounded by an absolute per-(va,slot) deadline; 0
+ * disables the hold (the demand rows are still emitted).
+ *
+ * r1083-r1087: DEFAULT 0 (off). A 20 s hold blocks the whole ring behind
+ * the held entry, and on the three hold-active boots (r1083/r1084/r1085)
+ * the GL client derailed into the black-dud/churn class, while the r1087
+ * boot (hold=0) read the beef windows fine (the wall moved back to the
+ * incomplete MME prelude + dispatch stall). The demand channel also cannot
+ * yet resolve the GL pushbuffer VA families (0x4000000+ / 0x42xxxxx), so
+ * the pin the hold waits for never lands and the hold only delays. Re-enable
+ * (e.g. sema_gr_setup_hold_ms=20000) once the guest content resolver covers
+ * those VA families.
+ */
+unsigned gsp_sema_gr_setup_hold_ms;
+
static unsigned long svc_gr_ring_tried; /* ranks that got a diagnostic line */
+/*
+ * Is this a GR push whose readability the MME-setup capture depends on?
+ * The client's C597 setup push is 12288 B; any GR push of that size is a
+ * candidate. A smaller push qualifies only when it is READABLE and its
+ * method runs hit the MME setup families (the unreadable case has no bytes
+ * to scan, hence the length rule alone).
+ */
+static bool svc_gr_setup_push(u32 len, const u8 *buf)
+{
+ u32 off = 0;
+
+ if (len >= 12288u)
+ return true;
+ if (!buf)
+ return false;
+ while (off + 4u <= len) {
+ u32 hdr, op, cnt, addr;
+
+ memcpy(&hdr, buf + off, 4);
+ op = (hdr >> 29) & 7u;
+ cnt = (hdr >> 16) & 0xfffu;
+ addr = (hdr & 0x1fffu) << 2;
+ if ((op == 1u || op == 3u || op == 5u) && cnt &&
+ svc_mme_setup_run_addr(addr))
+ return true;
+ off += ((op == 1u || op == 3u || op == 5u) && cnt) ?
+ (1u + cnt) * 4u : 4u;
+ }
+ return false;
+}
+
+/*
+ * Demand every 4K page of the push and arm the per-(va,slot) hold. The
+ * demand is the existing stalled-VA channel: svc_log_stalled_va rows are
+ * deduped and harvested by tools/guest-diag/pin_gr_stream.py, which asks
+ * the guest scanner to resolve the VA set and inject the pages. Only one
+ * arm line per (va,slot) is logged. `page_cap` bounds the VA rows (the
+ * 12288 B setup push needs 3; the cap keeps a bulk push from eating the
+ * 256-entry stalled-VA budget).
+ */
+static void svc_gr_setup_hold_arm(struct svc_channel *ch, u64 va, u32 idx,
+ u32 len)
+{
+ u64 page = va & ~(u64)(SEMA_PAGE_SIZE - 1);
+ u32 poff;
+
+ if (!va || !gsp_sema_gr_setup_hold_ms)
+ return;
+ if (ch->gr_setup_hold_va != va || ch->gr_setup_hold_idx != idx) {
+ ch->gr_setup_hold_va = va;
+ ch->gr_setup_hold_idx = idx;
+ ch->gr_setup_hold_until =
+ jiffies + msecs_to_jiffies(gsp_sema_gr_setup_hold_ms);
+ pr_info("sema-chan: GR setup hold h=0x%x entry=%u va=0x%llx len=%u armed (demanding 4K pages; pending until the pin lands, window %u ms)\n",
+ ch->h_object, idx, va, len, gsp_sema_gr_setup_hold_ms);
+ }
+ for (poff = 0; poff < len && poff < 0x8000u; poff += SEMA_PAGE_SIZE)
+ svc_log_stalled_va(page + poff);
+}
+
+static bool svc_gr_setup_hold_active(const struct svc_channel *ch, u64 va,
+ u32 idx)
+{
+ return ch->gr_setup_hold_until &&
+ ch->gr_setup_hold_va == va &&
+ ch->gr_setup_hold_idx == idx &&
+ time_before(jiffies, ch->gr_setup_hold_until);
+}
+
+static void svc_gr_setup_hold_clear(struct svc_channel *ch)
+{
+ ch->gr_setup_hold_until = 0;
+ ch->gr_setup_hold_va = 0;
+ ch->gr_setup_hold_idx = ~0u;
+}
+
static bool svc_gr_ram_ring_scan(struct nv_vgpu_device *vgpu,
struct svc_channel *ch, u64 *pa_out)
{
@@ -33436,6 +33548,7 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu)
c->unread_va = 0;
c->unread_until = 0;
c->defer_since = 0;
+ svc_gr_setup_hold_clear(c);
}
}
/*
@@ -34277,6 +34390,7 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu)
ch->defer_since = 0;
ch->unread_va = 0;
ch->unread_until = 0;
+ svc_gr_setup_hold_clear(ch);
svc_replay_note(ch, (u32)ch->last_get, put);
ch->last_get = (ch->last_get + 1) %
ch->gpfifo_entries;
@@ -34499,7 +34613,9 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu)
* exists for the page, the put advances (a new
* push at the same VA), or the window expires.
*/
- if (ch->engine_type && ch->unread_va == va &&
+ if ((ch->engine_type ||
+ svc_gr_setup_hold_active(ch, va, (u32)idx)) &&
+ ch->unread_va == va &&
ch->unread_idx == idx &&
time_before(jiffies, ch->unread_until)) {
u64 tpa = 0, vpa = 0;
@@ -34998,6 +35114,7 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu)
if (!unreadable) {
ch->push_hold_until = 0;
+ svc_gr_setup_hold_clear(ch);
/*
* The entry words repeated, but the
* push bytes may not have: a client
@@ -35867,13 +35984,33 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu)
1 : 0;
ch->gr_nocap_since =
jiffies;
+ /*
+ * SESSION 153-CONTINUED-54: an
+ * all-zero setup push gets the
+ * same 4K-page demand + pending
+ * hold as the unreadable one.
+ */
+ if (svc_gr_setup_push(len, pb))
+ svc_gr_setup_hold_arm(ch,
+ va,
+ (u32)idx,
+ len);
}
- if (gsp_sema_gr_nocap_hold_ms &&
+ {
+ u32 nocap_ms =
+ gsp_sema_gr_nocap_hold_ms;
+
+ if (svc_gr_setup_push(len, pb) &&
+ gsp_sema_gr_setup_hold_ms >
+ nocap_ms)
+ nocap_ms =
+ gsp_sema_gr_setup_hold_ms;
+ if (nocap_ms &&
!ch->gr_ram_ring &&
time_before(jiffies,
ch->gr_nocap_since +
msecs_to_jiffies(
- gsp_sema_gr_nocap_hold_ms)) &&
+ nocap_ms)) &&
!svc_hold_bypass()) {
/* Force a fresh capture on
* the retry: a replay decode
@@ -35892,7 +36029,7 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu)
svc_gr_cand_push_owed(va) ?
1 : 0,
svc_gr_qmd_seen,
- gsp_sema_gr_nocap_hold_ms);
+ nocap_ms);
}
kfree(pb);
break;
@@ -35913,6 +36050,7 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu)
ch->h_object,
(u32)idx, va, len,
owed_done);
+ }
}
}
/*
@@ -36157,6 +36295,16 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu)
idx, va, len);
svc_log_stalled_va(va);
/*
+ * SESSION 153-CONTINUED-54:
+ * demand the setup push's 4K
+ * pages and hold it pending.
+ */
+ if (!ch->engine_type &&
+ svc_gr_setup_push(len, NULL))
+ svc_gr_setup_hold_arm(ch, va,
+ (u32)idx,
+ len);
+ /*
* GR stale-skip clock: the
* rescue-failure skip gate below
* requires defer_since, yet every
@@ -36205,6 +36353,19 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu)
ch->unread_ipin_pa = ipa;
}
/*
+ * SESSION 153-CONTINUED-54: a held
+ * GR setup push waits cheaply for
+ * the whole hold window (the fresh-
+ * pin check still releases it the
+ * moment the demanded pin lands).
+ */
+ if (svc_gr_setup_hold_active(ch, va,
+ (u32)idx) &&
+ time_before(ch->unread_until,
+ ch->gr_setup_hold_until))
+ ch->unread_until =
+ ch->gr_setup_hold_until;
+ /*
* Bounded work-before-release
* hold (CE): the deferred retry
* probe shows the page's
@@ -36525,7 +36686,9 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu)
ch->defer_since &&
time_after(jiffies,
ch->defer_since +
- msecs_to_jiffies(gsp_sema_gr_grace_ms))) {
+ msecs_to_jiffies(gsp_sema_gr_grace_ms)) &&
+ !svc_gr_setup_hold_active(ch, va,
+ (u32)idx)) {
/*
* The slot no longer holds this
* push (overwritten buffer): the
@@ -36570,6 +36733,7 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu)
ch->defer_since = 0;
ch->unread_va = 0;
ch->unread_until = 0;
+ svc_gr_setup_hold_clear(ch);
/*
* m177: deliver any
* withheld set even
@@ -36669,6 +36833,7 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu)
ch->gr_nocap_va = 0;
ch->unread_va = 0;
ch->unread_until = 0;
+ svc_gr_setup_hold_clear(ch);
/* GRFIX FIX1c (r214): do NOT reset the per-launch
* bound record here - a consume of an unrelated entry
* would re-arm the held launch's bound every pass
@@ -38220,6 +38385,7 @@ static void svc_stall_watch_check(void)
continue;
ch->unread_va = 0;
ch->unread_until = 0;
+ svc_gr_setup_hold_clear(ch);
ch->gr_hold_idx = ~0u;
ch->gr_hold_until = 0;
ch->gr_nocap_idx = ~0u;