summaryrefslogtreecommitdiffstats
path: root/kernel/gsp_rm_emulation.c
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-09-26 02:03:37 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-09-26 02:03:37 -0400
commit7e227179b0c7d776919004e18e21f82909e8a40c (patch)
treea0fa796fcfbc17e744feef7dd30825b802ebc9c6 /kernel/gsp_rm_emulation.c
parent61a24325e7343880c15593be70ae1f704372a2ba (diff)
downloadopen-iov-7e227179b0c7d776919004e18e21f82909e8a40c.tar.gz
open-iov-7e227179b0c7d776919004e18e21f82909e8a40c.zip
gsp_rm: cap event records between replies so the status ring cannot wrap
Diffstat (limited to 'kernel/gsp_rm_emulation.c')
-rw-r--r--kernel/gsp_rm_emulation.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/kernel/gsp_rm_emulation.c b/kernel/gsp_rm_emulation.c
index a1c653e..52cf645 100644
--- a/kernel/gsp_rm_emulation.c
+++ b/kernel/gsp_rm_emulation.c
@@ -478,6 +478,31 @@ static int gsp_rm_send(struct gsp_emu_context *ctx, u32 function,
* service's thread. */
mutex_lock(&rm->stat_lock);
+ /*
+ * Bound the number of event records written between replies. Events are
+ * only wake-ups (the client re-reads channel state), so dropping some is
+ * harmless, but an unbounded event burst can wrap the status ring while
+ * a client is blocked waiting for its reply - the read then returns a
+ * newer record and the client aborts with "Bad sequence number".
+ */
+ if (function == GSPRM_RPC_EVENT_POST_EVENT) {
+ if (rm->event_burst >= GSPRM_EVENT_BURST_MAX) {
+ rm->events_dropped++;
+ if (rm->events_dropped <= 8 ||
+ (rm->events_dropped % 1000) == 0)
+ nv_vgpu_info(ctx->vgpu,
+ "GSPRM: event burst capped (%u), dropped total=%llu",
+ GSPRM_EVENT_BURST_MAX,
+ rm->events_dropped);
+ mutex_unlock(&rm->stat_lock);
+ kfree(buf);
+ return -EAGAIN;
+ }
+ rm->event_burst++;
+ } else {
+ rm->event_burst = 0;
+ }
+
record_size = gsp_rm_build_record(rm, buf, buf_size, function,
sequence, result, data, data_len,
&elem_count);