summaryrefslogtreecommitdiffstats
path: root/kernel/gsp_rm_emulation.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/gsp_rm_emulation.c')
-rw-r--r--kernel/gsp_rm_emulation.c80
1 files changed, 53 insertions, 27 deletions
diff --git a/kernel/gsp_rm_emulation.c b/kernel/gsp_rm_emulation.c
index d381c65..f44c01b 100644
--- a/kernel/gsp_rm_emulation.c
+++ b/kernel/gsp_rm_emulation.c
@@ -754,6 +754,46 @@ static void gsp_rm_evlog_post(struct nv_vgpu_device *vgpu,
}
/*
+ * r577 experiment knobs (runtime-writable; default 0 = legacy behaviour).
+ * The r576 live experiment showed the guest consumes our POST_EVENT records
+ * (rmstate cursors match) yet never enters nv_post_event (clean single-probe
+ * window, forced rmpost rounds -> entries-written 0): the guest RM drops
+ * them somewhere between the status-queue read and osNotifyEvent. These
+ * knobs let one boot A/B the record contents without rebuilding:
+ * gsp_rm_ev_seq - when nonzero, event records carry the status-queue
+ * sequence as the RPC-level sequence (legacy: 0)
+ * gsp_rm_ev_nlist - when nonzero, bNotifyList (payload byte 28) is set,
+ * selecting the driver's notifier-list dispatch path
+ * gsp_rm_ev_cl - when nonzero, overrides the payload hClient (e.g. to
+ * the kernel RM client) for the CliGetEventInfo lookup
+ */
+unsigned gsp_rm_ev_seq;
+unsigned gsp_rm_ev_nlist;
+unsigned gsp_rm_ev_cl;
+
+static void gsp_rm_fill_ev_payload(const struct gsp_rm_emu *rm, u32 i,
+ u8 *payload)
+{
+ u32 h_client = rm->events[i].h_client;
+
+ memset(payload, 0, 32);
+ if (gsp_rm_ev_cl)
+ h_client = gsp_rm_ev_cl;
+ memcpy(payload + 0, &h_client, 4);
+ memcpy(payload + 4, &rm->events[i].h_event, 4);
+ memcpy(payload + 8, &rm->events[i].notify_index, 4);
+ memcpy(payload + 12, &rm->events[i].data, 4);
+ /* info16@16, status@20, eventDataSize@24 = 0 */
+ if (gsp_rm_ev_nlist)
+ payload[28] = 1; /* bNotifyList */
+}
+
+static u32 gsp_rm_ev_sequence(const struct gsp_rm_emu *rm)
+{
+ return gsp_rm_ev_seq ? rm->stat_seq : 0;
+}
+
+/*
* Post the GPU event that tells the guest's CPU-side RM a channel's
* submitted work is complete. A real GPU raises an interrupt, the host GSP
* turns it into an NV_VGPU_MSG_EVENT_POST_EVENT record for the client's
@@ -785,17 +825,13 @@ int gsp_rm_post_channel_event(struct nv_vgpu_device *vgpu, u32 h_src)
if (!rm->events[i].valid || rm->events[i].h_src != h_src)
continue;
- memset(payload, 0, sizeof(payload));
- memcpy(payload + 0, &rm->events[i].h_client, 4);
- memcpy(payload + 4, &rm->events[i].h_event, 4);
- memcpy(payload + 8, &rm->events[i].notify_index, 4);
- memcpy(payload + 12, &rm->events[i].data, 4);
- /* info16@16, status@20, eventDataSize@24, bNotifyList@28 = 0 */
+ gsp_rm_fill_ev_payload(rm, i, payload);
{
int rc = gsp_rm_send_flags(ctx,
GSPRM_RPC_EVENT_POST_EVENT,
- 0, 0, payload,
- sizeof(payload), true);
+ gsp_rm_ev_sequence(rm), 0,
+ payload, sizeof(payload),
+ true);
gsp_rm_evlog_post(vgpu, rm, i, "chan", rc);
if (rc)
@@ -815,15 +851,12 @@ int gsp_rm_post_channel_event(struct nv_vgpu_device *vgpu, u32 h_src)
for (i = 0; i < rm->events_n; i++) {
if (!rm->events[i].valid)
continue;
- memset(payload, 0, sizeof(payload));
- memcpy(payload + 0, &rm->events[i].h_client, 4);
- memcpy(payload + 4, &rm->events[i].h_event, 4);
- memcpy(payload + 8, &rm->events[i].notify_index, 4);
- memcpy(payload + 12, &rm->events[i].data, 4);
+ gsp_rm_fill_ev_payload(rm, i, payload);
{
int rc = gsp_rm_send_flags(ctx,
GSPRM_RPC_EVENT_POST_EVENT,
- 0, 0, payload,
+ gsp_rm_ev_sequence(rm),
+ 0, payload,
sizeof(payload),
true);
@@ -861,14 +894,10 @@ static int gsp_rm_post_event_idx(struct gsp_emu_context *ctx, u32 idx)
if (idx >= rm->events_n || !rm->events[idx].valid)
return -EINVAL;
- memset(payload, 0, sizeof(payload));
- memcpy(payload + 0, &rm->events[idx].h_client, 4);
- memcpy(payload + 4, &rm->events[idx].h_event, 4);
- memcpy(payload + 8, &rm->events[idx].notify_index, 4);
- memcpy(payload + 12, &rm->events[idx].data, 4);
+ gsp_rm_fill_ev_payload(rm, idx, payload);
- rc = gsp_rm_send(ctx, GSPRM_RPC_EVENT_POST_EVENT, 0, 0,
- payload, sizeof(payload));
+ rc = gsp_rm_send(ctx, GSPRM_RPC_EVENT_POST_EVENT,
+ gsp_rm_ev_sequence(rm), 0, payload, sizeof(payload));
if (!rc)
rm->events[idx].last_post = jiffies;
return rc;
@@ -946,14 +975,11 @@ int gsp_rm_post_all_events(struct nv_vgpu_device *vgpu)
continue;
}
- memset(payload, 0, sizeof(payload));
- memcpy(payload + 0, &rm->events[i].h_client, 4);
- memcpy(payload + 4, &rm->events[i].h_event, 4);
- memcpy(payload + 8, &rm->events[i].notify_index, 4);
- memcpy(payload + 12, &rm->events[i].data, 4);
+ gsp_rm_fill_ev_payload(rm, i, payload);
{
int rc = gsp_rm_send(ctx, GSPRM_RPC_EVENT_POST_EVENT,
- 0, 0, payload, sizeof(payload));
+ gsp_rm_ev_sequence(rm), 0,
+ payload, sizeof(payload));
gsp_rm_evlog_post(vgpu, rm, i, "all", rc);
if (rc)