diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-22 19:26:59 -0400 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-22 19:26:59 -0400 |
| commit | 58c2718c2e20d0e9394671e7132150f6905ed12e (patch) | |
| tree | 26780056f73a836cfa70d999e3a0842eb463f0ff /kernel/gsp_sema_service.c | |
| parent | 8f7d265476f233f91b75c0cdfd8b6f3a8ce1afcb (diff) | |
| download | open-iov-58c2718c2e20d0e9394671e7132150f6905ed12e.tar.gz open-iov-58c2718c2e20d0e9394671e7132150f6905ed12e.zip | |
r505b opdef flush marks the slot complete; bound the slot arrays for large rings
Two fixes for the r505 multikernel livelock (opdef held=18359, expired=61,
client at DEVICE forever while the pump looped on ring slot 1):
- after the bounded opdef hold expires and svc_opdef_flush delivers the
withheld releases, the slot's ops are permanently skipped - but the
decode-time bookkeeping had stored slot_ops_complete=0 (op_tr_pending was
set when it ran), so every pin-batch rewind replay of the slot re-decoded
it, re-set op_tr_pending and re-held the entry forever. Mark the slot
complete on flush so a replay suppresses the ops (entry_replay) and the
entry consumes normally.
- the per-slot op arrays are SVC_GPFIFO_MAX_BITS (1024) but the X/GL
channel's ring is 8192 slots: bound every slot-index write/read
(entry_ident is zeroed past the array size, so the bookkeeping skips).
Diffstat (limited to 'kernel/gsp_sema_service.c')
| -rw-r--r-- | kernel/gsp_sema_service.c | 41 |
1 files changed, 38 insertions, 3 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index 1e9f981..35abb15 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -21263,10 +21263,17 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu) */ { u64 ident = (u64)e0 | ((u64)e1 << 32); - bool same = ident && + /* + * r505b: the per-slot op bookkeeping arrays are + * SVC_GPFIFO_MAX_BITS (1024) entries; the X/GL + * channel's ring is 8192 slots. Bound every slot + * index here or a large ring writes out of + * bounds. + */ + bool same = ident && idx < SVC_GPFIFO_MAX_BITS && ch->slot_ops_ident[idx] == ident; - entry_ident = ident; + entry_ident = (idx < SVC_GPFIFO_MAX_BITS) ? ident : 0; /* * A complete prior pass suppresses every op. * A partial pass (an operand's targeted scan @@ -21720,7 +21727,7 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu) kfree(pb); break; } - if (svc.op_tr_pending) + if (svc.op_tr_pending) { /* * Deadline hit: the * operand never @@ -21732,6 +21739,34 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu) */ svc_opdef_flush(vgpu, ch, (u32)idx); + /* + * r505b: mark the slot's + * ops complete. The op was + * permanently skipped, but + * the decode above stored + * complete=0 (op_tr_pending + * was set), so every pin- + * batch rewind replay of + * this slot re-decoded it, + * re-set op_tr_pending and + * re-held the entry in a + * livelock (multikernel on + * r505: opdef held=18359, + * expired=61, the client + * waiting forever while the + * pump looped on slot 1). + * Nothing is owed after the + * flush, so a replay must + * skip the ops. + */ + if ((u32)idx < + SVC_GPFIFO_MAX_BITS) { + ch->slot_ops_complete[idx] = + 1; + ch->slot_ops_done[idx] = + entry_done; + } + } rel_seen = (svc_rel_count != rel_n_before); { bool fwd_guest_queued; |
