summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-09-29 12:43:12 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-09-29 12:43:12 -0400
commit942a87ec02b551b5eb36d447d828666684081636 (patch)
treea0b7febcc9fcebea7b9ce7328ef50d5557d0af36 /kernel
parentff97caae114db5447fc71b89ead7e8d2c4d404a8 (diff)
downloadopen-iov-942a87ec02b551b5eb36d447d828666684081636.tar.gz
open-iov-942a87ec02b551b5eb36d447d828666684081636.zip
sema-svc: learn the tracking-sem VA from readable pushes for the release fallback
Diffstat (limited to 'kernel')
-rw-r--r--kernel/gsp_sema_service.c56
1 files changed, 42 insertions, 14 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c
index 343981c..2127f38 100644
--- a/kernel/gsp_sema_service.c
+++ b/kernel/gsp_sema_service.c
@@ -139,6 +139,7 @@ struct svc_channel {
u32 last_get; /* next GPFIFO entry we have still to run */
u64 submissions; /* GPFIFO entries executed */
u32 expected_sem_payload; /* next semaphore payload we expect for this channel's tracking sem */
+ u64 last_rel_va; /* last tracking-sem VA seen in a readable push */
u32 logged_expected; /* last pool value logged (rate limit) */
unsigned long rescue_last; /* rate limit for the full-RAM rescue scan */
u32 rescue_fail; /* consecutive failed rescues for the entry */
@@ -1728,8 +1729,7 @@ static void svc_rebuild(struct nv_vgpu_device *vgpu)
/* push application */
/* ------------------------------------------------------------------ */
-/* C5B5 (TURING_DMA_COPY_A) methods, from the class interface. */
-#define CE_M_SET_SEMAPHORE_A 0x240
+/* C5B5 (TURING_DMA_COPY_A) methods, from the class interface. */#define CE_M_SET_SEMAPHORE_A 0x240
#define CE_M_SET_SEMAPHORE_B 0x244
#define CE_M_SET_SEMAPHORE_PAY 0x248
#define CE_M_SET_SRC_PHYS_MODE 0x260
@@ -1989,6 +1989,14 @@ static bool svc_method_stream_plausible(const u8 *buf, u32 len)
* translation is executed at the push's release method (see below); pages
* decoded from raw sweeps never execute work at all.
*/
+/*
+ * Last tracking-semaphore VA decoded from a readable push. The pump copies
+ * it into the channel so the unreadable-push fallback targets the semaphore
+ * the client actually waits on (its pool index is allocated by UVM and does
+ * not match the channel rank).
+ */
+static u64 svc_rel_va_seen;
+
static void svc_decode_stream(struct nv_vgpu_device *vgpu, const u8 *buf,
u32 len, u64 page_pa, bool allow_ops,
u32 ch_h, u32 ch_eng, u64 push_va)
@@ -2119,6 +2127,7 @@ static void svc_decode_stream(struct nv_vgpu_device *vgpu, const u8 *buf,
st.rel_va = va;
st.rel_payload = payload;
st.have_rel = 1;
+ svc_rel_va_seen = va;
/* The push's work always runs; see the
* REPORT_SEM comment below. */
if (allow_ops && n_ops) {
@@ -2188,6 +2197,7 @@ static void svc_decode_stream(struct nv_vgpu_device *vgpu, const u8 *buf,
st.rel_va = va;
st.rel_payload = st.rs_payload;
st.have_rel = 1;
+ svc_rel_va_seen = va;
/*
* The push's collected work always runs on
* real hardware; the semaphore release only
@@ -3800,12 +3810,19 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu)
* need but their other methods may
* alias CE encodings.
*/
- svc_decode_stream(vgpu, pb,
- len, 0,
- ch->engine_type != 0,
- ch->h_object,
- ch->engine_type,
- va);
+ {
+ u64 rel_before = svc_rel_va_seen;
+
+ svc_decode_stream(vgpu, pb,
+ len, 0,
+ ch->engine_type != 0,
+ ch->h_object,
+ ch->engine_type,
+ va);
+ if (svc_rel_va_seen != rel_before)
+ ch->last_rel_va =
+ svc_rel_va_seen;
+ }
ch->submissions++;
svc.gpfifo_entries_done++;
/* Advance expected payload for this channel's tracking semaphore. */
@@ -3841,12 +3858,20 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu)
* fill vidmem with garbage). Only
* the release is applied.
*/
- svc_decode_stream(vgpu, pb,
- len, 0,
- false,
- ch->h_object,
- ch->engine_type,
- va);
+ {
+ u64 rel_before =
+ svc_rel_va_seen;
+
+ svc_decode_stream(vgpu, pb,
+ len, 0,
+ false,
+ ch->h_object,
+ ch->engine_type,
+ va);
+ if (svc_rel_va_seen != rel_before)
+ ch->last_rel_va =
+ svc_rel_va_seen;
+ }
ch->submissions++;
svc.gpfifo_entries_done++;
if (ch->engine_type && ch->expected_sem_payload)
@@ -3901,6 +3926,8 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu)
ch->engine_type &&
ch->expected_sem_payload) {
u64 pool_va =
+ ch->last_rel_va ?
+ ch->last_rel_va :
0x121000000ULL +
4ULL * ch->ce_index;
u64 spa = 0;
@@ -3984,6 +4011,7 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu)
*/
svc.chan[k].expected_sem_payload =
ch->expected_sem_payload;
+ svc.chan[k].last_rel_va = ch->last_rel_va;
svc.chan[k].rescue_last = ch->rescue_last;
svc.chan[k].rescue_fail = ch->rescue_fail;
break;