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
commit7ac4d61c5a06fda4c9d4a398fb49f400b2b76f15 (patch)
tree3400e4fd6cba29bb6e4525d788509acd5803d3ee /kernel/gsp_rm_emulation.c
parent70459a9782098fe409dcf49ec2496e568c826903 (diff)
downloadopen-iov-7ac4d61c5a06fda4c9d4a398fb49f400b2b76f15.tar.gz
open-iov-7ac4d61c5a06fda4c9d4a398fb49f400b2b76f15.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);