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.c45
1 files changed, 44 insertions, 1 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c
index 0578d3c..5505c1e 100644
--- a/kernel/gsp_sema_service.c
+++ b/kernel/gsp_sema_service.c
@@ -313,6 +313,7 @@ struct sema_svc {
u64 memsets_fail;
u64 ring_ops; /* op runs from ring-decoded pushes */
u64 lda_log; /* LAUNCH_DMA inventory budget */
+ u64 entry_log; /* per-push summary budget */
u64 releases_seen;
u64 releases_applied;
u64 releases_missed; /* no VA->PA entry */
@@ -1545,6 +1546,9 @@ struct svc_push_state {
u32 sem_inc;
u32 rs_upper, rs_lower, rs_payload;
u32 have_rs_addr, have_rs_payload;
+ u64 rel_va; /* last release decoded in this push */
+ u32 rel_payload;
+ u32 have_rel;
};
/* ------------------------------------------------------------------ */
@@ -1725,6 +1729,7 @@ static void svc_decode_stream(struct nv_vgpu_device *vgpu, const u8 *buf,
struct svc_push_state st;
struct svc_memset_op ops[SVC_MAX_MEMSETS];
u32 n_ops = 0;
+ u32 ops_runs = 0;
u32 off = 0;
memset(&st, 0, sizeof(st));
@@ -1825,11 +1830,15 @@ static void svc_decode_stream(struct nv_vgpu_device *vgpu, const u8 *buf,
if (page_pa)
svc_mark_hot(page_pa);
svc.pushes_seen++;
+ st.rel_va = va;
+ st.rel_payload = payload;
+ st.have_rel = 1;
/* The push's work always runs; see the
* REPORT_SEM comment below. */
if (allow_ops && n_ops) {
svc_run_ops(vgpu, ops, n_ops);
svc.ring_ops++;
+ ops_runs++;
}
n_ops = 0;
if (!svc_sem_read(vgpu, va, &cur) &&
@@ -1889,6 +1898,9 @@ static void svc_decode_stream(struct nv_vgpu_device *vgpu, const u8 *buf,
if (page_pa)
svc_mark_hot(page_pa);
svc.pushes_seen++;
+ st.rel_va = va;
+ st.rel_payload = st.rs_payload;
+ st.have_rel = 1;
/*
* The push's collected work always runs on
* real hardware; the semaphore release only
@@ -1907,6 +1919,7 @@ static void svc_decode_stream(struct nv_vgpu_device *vgpu, const u8 *buf,
if (allow_ops && n_ops) {
svc_run_ops(vgpu, ops, n_ops);
svc.ring_ops++;
+ ops_runs++;
}
n_ops = 0;
if (svc_sem_read(vgpu, va, &cur))
@@ -2044,6 +2057,9 @@ static void svc_decode_stream(struct nv_vgpu_device *vgpu, const u8 *buf,
svc.pushes_seen++;
sem_va = ((u64)st.sem_va_hi << 32) |
st.sem_va_lo;
+ st.rel_va = sem_va;
+ st.rel_payload = st.sem_payload;
+ st.have_rel = 1;
if (st.have_sem && st.sem_payload &&
sem_va >= SEMA_VA_LO && sem_va < SEMA_VA_HI) {
@@ -2067,6 +2083,7 @@ static void svc_decode_stream(struct nv_vgpu_device *vgpu, const u8 *buf,
if (allow_ops && n_ops) {
svc_run_ops(vgpu, ops, n_ops);
svc.ring_ops++;
+ ops_runs++;
}
if (pending) {
svc.pushes_pending++;
@@ -2090,6 +2107,21 @@ static void svc_decode_stream(struct nv_vgpu_device *vgpu, const u8 *buf,
}
off += 4 + count * 4;
}
+
+ if (ch_h && svc.entry_log < 64) {
+ svc.entry_log++;
+ {
+ u8 tail[24];
+ u32 tlen = len >= sizeof(tail) ? sizeof(tail) : len;
+
+ if (tlen)
+ memcpy(tail, buf + len - tlen, tlen);
+ pr_info("sema-push: h=0x%x eng=%u len=%u ops_runs=%u rel=0x%llx pay=%u have_rel=%u tail=%*phN\n",
+ ch_h, ch_eng, len, ops_runs, st.rel_va,
+ st.rel_payload, st.have_rel, tlen,
+ tlen ? tail : NULL);
+ }
+ }
}
/* ------------------------------------------------------------------ */
@@ -3278,9 +3310,20 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu)
/* Rescue succeeded, retry the read. */
if (!svc_read_va_trusted(vgpu, va, pb,
len)) {
+ /*
+ * Never run work decoded from a
+ * rescued page: the rescue matches
+ * the expected release bytes in
+ * arbitrary RAM and has matched GSP
+ * firmware/code pages, whose bytes
+ * decode as plausible but bogus
+ * method streams (ops_runs could
+ * fill vidmem with garbage). Only
+ * the release is applied.
+ */
svc_decode_stream(vgpu, pb,
len, 0,
- ch->engine_type != 0,
+ false,
ch->h_object,
ch->engine_type);
ch->submissions++;