diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-09-24 02:29:04 -0400 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-09-24 02:29:04 -0400 |
| commit | 5c9d18abaac6ce45c8faec26b3f3b637cd764eb5 (patch) | |
| tree | 189accac8d94601fc26a2561198b8bb4817acc0d /kernel/gsp_rm_emulation.c | |
| parent | 0b799c9487477fd31a56e0c386e6ba3896c4c569 (diff) | |
| download | open-iov-5c9d18abaac6ce45c8faec26b3f3b637cd764eb5.tar.gz open-iov-5c9d18abaac6ce45c8faec26b3f3b637cd764eb5.zip | |
kernel: completion-event hints and GSP-RM state introspection
- re-post the completion event for a bounded window after a channel
completes work (notifier consumed or semaphore release applied), so a
client that starts waiting after the edge-triggered wake-up still gets
a wake-up; the OS event classes carry no source object, so the hint
broadcasts to the registered events
- add rmstate (dump msgq cursors, guest consumption position, event
table) and rmpost (post an event record by index or to all) debug
parameters, both executing in kthreads because the IOMMU read path
only works with a NULL current->mm or the mapping owner's mm
- report the underlying error codes from the event post path
Diffstat (limited to 'kernel/gsp_rm_emulation.c')
| -rw-r--r-- | kernel/gsp_rm_emulation.c | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/kernel/gsp_rm_emulation.c b/kernel/gsp_rm_emulation.c index 986132e..5120d4e 100644 --- a/kernel/gsp_rm_emulation.c +++ b/kernel/gsp_rm_emulation.c @@ -633,6 +633,146 @@ int gsp_rm_post_channel_event(struct nv_vgpu_device *vgpu, u32 h_src) return posted ? 0 : -ENOENT; } +/* + * Debug: post the event record for one registered event (or all of them with + * idx 0xffffffff). Used to test the guest's event path on demand without + * waiting for a channel submission. + */ +static int gsp_rm_post_event_idx(struct gsp_emu_context *ctx, u32 idx) +{ + struct gsp_rm_emu *rm = ctx->rm_emu; + u8 payload[32]; + + 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); + + return gsp_rm_send(ctx, GSPRM_RPC_EVENT_POST_EVENT, 0, 0, + payload, sizeof(payload)); +} + +int gsp_rm_force_post(struct nv_vgpu_device *vgpu, u32 idx) +{ + struct gsp_emu_context *ctx = vgpu ? vgpu->gsp_comm_ctx : NULL; + struct gsp_rm_emu *rm; + u32 i; + int n = 0, last = -ENOENT; + + if (!ctx) + return -ENODEV; + rm = ctx->rm_emu; + if (!rm) + return -ENODEV; + + if (idx != 0xffffffffu) { + int r = gsp_rm_post_event_idx(ctx, idx); + + return r ? r : 1; + } + + for (i = 0; i < rm->events_n; i++) { + int r = gsp_rm_post_event_idx(ctx, i); + + if (r) + last = r; + else + n++; + } + + return n ? 0 : last; +} + +/* + * Post the completion event to every registered OS event (the classes the + * guest allocates carry no source object, so a per-channel association is + * not available in the ABI). Used by the service's completion hint so a + * client that starts waiting after the event fired still gets a wake-up. + */ +int gsp_rm_post_all_events(struct nv_vgpu_device *vgpu) +{ + return gsp_rm_force_post(vgpu, 0xffffffffu); +} + +/* + * Debug: dump the msgq cursors (ours and the guest's) and the event table. + * The guest's consumption cursor of the status queue lives in its own + * command-queue buffer at the rxHdrOff it advertised (SWAP_RX queues store + * the peer read pointer in the local buffer). + */ +int gsp_rm_dump_state(struct nv_vgpu_device *vgpu) +{ + struct gsp_emu_context *ctx = vgpu ? vgpu->gsp_comm_ctx : NULL; + struct gsp_rm_emu *rm; + u8 cmd_hdr[32] = {0}, stat_hdr[32] = {0}; + u32 cmd_write = 0, cmd_flags = 0, cmd_rxoff = 0, cmd_entryoff = 0; + u32 stat_write = 0, stat_flags = 0, stat_rxoff = 0; + u32 guest_read = 0xdeadbeef, our_cmd_read = 0xdeadbeef; + u64 cmd_gpa_now = 0, stat_gpa_now = 0; + int cmd_ret = -1, stat_ret = -1, gr_ret = -1; + u32 i; + + if (!ctx) + return -ENODEV; + rm = ctx->rm_emu; + if (!rm || !rm->parsed) + return -ENODEV; + + cmd_gpa_now = gsp_rm_off_to_gpa(rm, rm->cmd_off); + stat_gpa_now = gsp_rm_off_to_gpa(rm, rm->stat_off); + + cmd_ret = gsp_rm_read_buf(ctx, rm->cmd_off, cmd_hdr, sizeof(cmd_hdr)); + if (cmd_ret == 0) { + memcpy(&cmd_write, cmd_hdr + 16, 4); + memcpy(&cmd_flags, cmd_hdr + 20, 4); + memcpy(&cmd_rxoff, cmd_hdr + 24, 4); + memcpy(&cmd_entryoff, cmd_hdr + 28, 4); + } + stat_ret = gsp_rm_read_buf(ctx, rm->stat_off, stat_hdr, sizeof(stat_hdr)); + if (stat_ret == 0) { + memcpy(&stat_write, stat_hdr + 16, 4); + memcpy(&stat_flags, stat_hdr + 20, 4); + memcpy(&stat_rxoff, stat_hdr + 24, 4); + } + + if (cmd_rxoff && cmd_rxoff < 0x1000) + gr_ret = gsp_rm_read_buf(ctx, rm->cmd_off + cmd_rxoff, + &guest_read, 4); + if (stat_rxoff && stat_rxoff < 0x1000) + gsp_rm_read_buf(ctx, rm->stat_off + stat_rxoff, &our_cmd_read, 4); + + nv_vgpu_info(vgpu, + "GSPRM: rmstate cmd{gpa=0x%llx->0x%llx off=0x%llx size=0x%x mc=%u ptes=%u read=%d our_read=%u hdr{wr=%u fl=0x%x rxoff=0x%x entryoff=0x%x}} " + "stat{gpa=0x%llx->0x%llx off=0x%llx size=0x%x mc=%u read=%d our_write=%u seq=%u hdr{wr=%u fl=0x%x rxoff=0x%x ours_written=%u} guest_read=%u gr_ret=%d}", + rm->cmd_gpa, cmd_gpa_now, rm->cmd_off, rm->cmd_size, + rm->cmd_msgcount, rm->mq.pageTableEntryCount, cmd_ret, + rm->cmd_read, cmd_write, cmd_flags, cmd_rxoff, cmd_entryoff, + rm->stat_gpa, stat_gpa_now, rm->stat_off, rm->stat_size, + rm->stat_msgcount, stat_ret, rm->stat_write, rm->stat_seq, + stat_write, stat_flags, stat_rxoff, our_cmd_read, + guest_read, gr_ret); + + + nv_vgpu_info(vgpu, "GSPRM: rmstate events_n=%u posted=%llu", + rm->events_n, rm->events_posted); + + for (i = 0; i < rm->events_n && i < GSPRM_MAX_EVENTS; i++) { + if (!rm->events[i].valid) + continue; + nv_vgpu_info(vgpu, + "GSPRM: event[%u] hClient=0x%x hEvent=0x%x hSrc=0x%x notifyIndex=0x%x data=0x%x", + i, rm->events[i].h_client, rm->events[i].h_event, + rm->events[i].h_src, rm->events[i].notify_index, + rm->events[i].data); + } + + return 0; +} + /* ============================================================ * Queue-chain discovery (libos args -> RMARGS -> GSP_ARGUMENTS_CACHED) * ============================================================ */ |
