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.c75
1 files changed, 73 insertions, 2 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c
index 7bb7440..f21f589 100644
--- a/kernel/gsp_sema_service.c
+++ b/kernel/gsp_sema_service.c
@@ -13920,6 +13920,9 @@ static u32 svc_pushpg_split_log;
* validated candidate). Reads stay defensively copied through
* svc_read_ap()/vfio_dma_rw(), which enforce the aperture bounds.
*/
+/* r707d: bounded push-read failure witness (see below). */
+static u32 svc_pushfail_log;
+
static int svc_read_va_push_ex(struct nv_vgpu_device *vgpu,
struct svc_channel *ch, u64 va, void *buf,
size_t len, bool skip_ipin)
@@ -13935,6 +13938,7 @@ static int svc_read_va_push_ex(struct nv_vgpu_device *vgpu,
bool have_win, done = false;
bool first = (p == buf);
int last_rc = -ENOENT;
+ int trusted_rc = 0;
u32 src;
have_win = !svc_pb_win_lookup(ch, page_va, &win_pa);
@@ -13988,7 +13992,9 @@ static int svc_read_va_push_ex(struct nv_vgpu_device *vgpu,
default:
/* learned cache / discovered map / page
* directories / targeted rm_mem resolve */
- if (svc_lookup_trusted(vgpu, va, &pa, &ap))
+ trusted_rc = svc_lookup_trusted(vgpu, va,
+ &pa, &ap);
+ if (trusted_rc)
continue;
break;
}
@@ -14051,8 +14057,29 @@ static int svc_read_va_push_ex(struct nv_vgpu_device *vgpu,
continue;
done = true;
}
- if (!done)
+ if (!done) {
+ if (svc_pushfail_log < 96) {
+ u64 ipa = 0, apa = 0;
+ int iap = 0, aap = 0;
+ bool has_ipin =
+ (svc_ipin_lookup(va, &ipa, &iap) == 0);
+ bool has_alt =
+ (svc_ipin_alt_lookup(va, &apa, &aap) == 0);
+
+ svc_pushfail_log++;
+ pr_info("sema-pushfail: va=0x%llx chunk=0x%llx page=0x%llx last_rc=%d trusted_rc=%d ipin=%d pa=0x%llx alt=%d pa=0x%llx win=%d pa=0x%llx\n",
+ (unsigned long long)va,
+ (unsigned long long)chunk,
+ (unsigned long long)page_va,
+ last_rc, trusted_rc, has_ipin,
+ (unsigned long long)ipa,
+ has_alt,
+ (unsigned long long)apa,
+ have_win,
+ (unsigned long long)win_pa);
+ }
return last_rc;
+ }
p += chunk;
va += chunk;
len -= chunk;
@@ -15650,6 +15677,29 @@ static u64 svc_pdb_disc_va;
static u64 svc_pdb_disc_pa;
static bool svc_pdb_disc_pending;
+/*
+ * r707r: bounded channel rewind (debug). After the VAS pdb anchor lands,
+ * entries skipped before it never re-decode on their own (their unread
+ * window expires into a skip), so the release they carry would be lost for
+ * that put epoch. A host tool asks for a rewind (sema_chan_rewind: a hex
+ * h_object, or "all"); the pump re-processes the channel from slot 0 with
+ * the consumed-slot bitmap and the per-entry rescue state cleared.
+ */
+static u32 svc_rewind_h;
+static bool svc_rewind_all;
+static bool svc_rewind_pending;
+
+int gsp_sema_service_chan_rewind(u32 h_object)
+{
+ if (!svc.task)
+ return -ENODEV;
+ svc_rewind_h = h_object;
+ svc_rewind_all = (h_object == 0xffffffffu);
+ svc_rewind_pending = true;
+ wake_up_process(svc.task);
+ return 0;
+}
+
int gsp_sema_service_pdb_discover(u64 ring_va, u64 ring_pa)
{
if (!svc.task)
@@ -23597,6 +23647,27 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu)
bool stalled = false;
spin_lock_irqsave(&svc.chan_lock, flags);
+ if (svc_rewind_pending) {
+ svc_rewind_pending = false;
+ for (i = 0; i < SVC_MAX_CHANNELS; i++) {
+ struct svc_channel *c = &svc.chan[i];
+
+ if (!c->valid || c->vgpu != vgpu)
+ continue;
+ if (!svc_rewind_all && c->h_object != svc_rewind_h)
+ continue;
+ pr_info("sema-chan: rewind h=0x%x last_get=%u put=%u (slot bitmap + rescue state cleared)\n",
+ c->h_object,
+ (unsigned int)c->last_get,
+ (unsigned int)c->put_prev);
+ bitmap_zero(c->slot_done_epoch, SVC_GPFIFO_MAX_BITS);
+ c->last_get = 0;
+ c->rescue_fail = 0;
+ c->unread_va = 0;
+ c->unread_until = 0;
+ c->defer_since = 0;
+ }
+ }
/*
* r507o stream-order: walk the CE channels BEFORE the GR channels.
* The client's stream order places its H2D copies before the kernel