diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/gsp_emulation.c | 30 | ||||
| -rw-r--r-- | kernel/gsp_emulation.h | 5 | ||||
| -rw-r--r-- | kernel/gsp_rm_emulation.c | 40 |
3 files changed, 64 insertions, 11 deletions
diff --git a/kernel/gsp_emulation.c b/kernel/gsp_emulation.c index 3b6f6e5..5522bf3 100644 --- a/kernel/gsp_emulation.c +++ b/kernel/gsp_emulation.c @@ -138,6 +138,32 @@ enum gsp_emu_boot_stage { }; /* + * gsp_emu_clear_boot_state - return the emulated GSP to a cold state. + * + * On real hardware, driver unload tears down WPR2 (Booter Unload) so the + * next probe's _kgspBootGspRm WPR2-up check passes. Turing guests produce + * no observable BAR0 writes on unload, so callers must trigger this on + * indirect death signals (ENGINE reset, GSP-RM queue going stale). + * Clears WPR2, RISCV active status and the falcon stage tracker, and + * drops the parsed GSP-RM queue state. + */ +void gsp_emu_clear_boot_state(struct gsp_emu_context *ctx, const char *reason) +{ + nv_vgpu_info(ctx->vgpu, "GSP-BOOT: clearing boot state (%s)", reason); + + gsp_emu_shadow_write32(ctx, GSP_EMU_REG_WPR2_ADDR_LO, 0); + gsp_emu_shadow_write32(ctx, GSP_EMU_REG_WPR2_ADDR_HI, 0); + gsp_emu_shadow_write32(ctx, GSP_EMU_REG_RISCV_STATUS, 0); + gsp_emu_shadow_write32(ctx, GSP_EMU_REG_GSP_MAILBOX0, 0); + gsp_emu_shadow_write32(ctx, GSP_EMU_REG_GSP_MAILBOX1, 0); + + ctx->boot_stage = GSP_BOOT_STAGE_IDLE; + ctx->flcn_kick_count = 0; + + gsp_rm_emu_reset(ctx); +} + +/* * gsp_emu_poll_boot - drive the guest's physical GSP boot to completion. * * The guest driver kicks falcon ucodes (FWSEC for FRTS, then Booter Load for @@ -155,12 +181,10 @@ static void gsp_emu_poll_boot(struct gsp_emu_context *ctx) /* GSP ENGINE reset asserted -> falcon rebooted, restart stage tracking */ if ((engine & 0x1) && ctx->boot_stage != GSP_BOOT_STAGE_IDLE) { - ctx->boot_stage = GSP_BOOT_STAGE_IDLE; - ctx->flcn_kick_count = 0; nv_vgpu_info(ctx->vgpu, "GSP-BOOT: falcon reset, back to IDLE"); /* The guest is rebooting the GSP (new probe or unload): the * GSP-RM queue state is stale, reset it too. */ - gsp_rm_emu_reset(ctx); + gsp_emu_clear_boot_state(ctx, "ENGINE reset"); return; } diff --git a/kernel/gsp_emulation.h b/kernel/gsp_emulation.h index 668d567..fe4186e 100644 --- a/kernel/gsp_emulation.h +++ b/kernel/gsp_emulation.h @@ -44,6 +44,7 @@ #define GSP_EMU_REG_GSP_CPUCTL 0x110100 /* bit1 STARTCPU, bit4 HALTED */ #define GSP_EMU_REG_GSP_ENGINE 0x1103c0 /* bit0 RESET */ #define GSP_EMU_REG_GSP_MAILBOX0 0x110040 +#define GSP_EMU_REG_GSP_MAILBOX1 0x110044 #define GSP_EMU_REG_VBIOS_SCRATCH_0E 0x001438 /* FRTS err code (0=NONE) */ #define GSP_EMU_REG_WPR2_ADDR_LO 0x1fa824 #define GSP_EMU_REG_WPR2_ADDR_HI 0x1fa828 @@ -121,6 +122,10 @@ static inline u32 gsp_emu_shadow_read32(struct gsp_emu_context *ctx, u32 offset) int gsp_emu_init(struct nv_vgpu_device *vgpu); void gsp_emu_cleanup(struct nv_vgpu_device *vgpu); + +/* Clear emulated GSP boot state (WPR2/RISCV/stages/RM queues) on + * ENGINE reset or detected GSP death (stale msgq). */ +void gsp_emu_clear_boot_state(struct gsp_emu_context *ctx, const char *reason); int gsp_emu_process_rpc(struct gsp_emu_context *ctx); void gsp_emu_inject_completion_interrupt(struct gsp_emu_context *ctx, u32 seq_id); diff --git a/kernel/gsp_rm_emulation.c b/kernel/gsp_rm_emulation.c index e152e5c..1ed63ab 100644 --- a/kernel/gsp_rm_emulation.c +++ b/kernel/gsp_rm_emulation.c @@ -526,7 +526,12 @@ static void gsp_rm_build_static_info(u8 *buf) val64 = 0; memcpy(®ion->reserved, &val64, 8); val32 = 0; memcpy(®ion->performance, &val32, 4); region->supportCompressed = 0; - region->supportISO = 0; + /* memmgrCalcReservedFbSpace asserts that SOME region supports + * ISO "even if we have no display" - without it the reserved + * space split fails and kdisp can't allocate its channel + * table. A single ISO-capable region satisfies fast/slow/iso + * assignment. */ + region->supportISO = 1; region->bProtected = 0; memset(region->blackList, 0, sizeof(region->blackList)); } @@ -670,6 +675,7 @@ struct gsp_rm_control_req { static void gsp_rm_handle_fifo_device_table(struct gsp_emu_context *ctx, u32 sequence, struct gsp_rm_control_req *req, + const u8 *req_params, u32 *out_status, u8 *out_params, u32 *out_params_size) { @@ -678,8 +684,14 @@ static void gsp_rm_handle_fifo_device_table(struct gsp_emu_context *ctx, fifo_params = (struct tu104_fifo_get_device_info_params *)out_params; base = 0; - if (req->paramsSize >= 4) - memcpy(&base, (u8 *)(req + 1), 4); + /* baseIndex is the first field of the request params, which live in + * the queue element buffer (NOT after the local header struct!). Only + * readable when the whole request fits in the first element. */ + if (req->paramsSize >= 4 && + req->paramsSize + GSP_RM_CTRL_HDR_SIZE <= GSPRM_MAX_SINGLE_ELEM_DATA) + memcpy(&base, req_params, 4); + if (base >= TU104_FIFO_TABLE_MAX_DEVICES) + base = 0; /* How many entries to return in this page */ count = TU104_ENGINE_TABLE_SIZE - base; @@ -847,6 +859,7 @@ static void gsp_rm_handle_rm_control(struct gsp_emu_context *ctx, switch (req.cmd) { case TU104_CTRL_FIFO_GET_DEVICE_INFO_TABLE: gsp_rm_handle_fifo_device_table(ctx, sequence, &req, + req_data + GSP_RM_CTRL_HDR_SIZE, &out_status, reply + GSP_RM_CTRL_HDR_SIZE, &out_params_size); break; @@ -975,9 +988,15 @@ static void gsp_rm_poll_commands(struct gsp_emu_context *ctx) if (tx.writePtr < rm->cmd_read || (tx.writePtr - rm->cmd_read) > rm->cmd_msgcount) { - nv_vgpu_warn(ctx->vgpu, "GSPRM: cmd writePtr jumped %u -> %u, resyncing", + /* The writePtr is monotonic for the life of a boot. A backward + * or insane jump means the queue buffer was torn down - the + * guest driver unloaded (or crashed) without an observable + * GSP shutdown. Declare the emulated GSP dead: clear WPR2 / + * RISCV / boot stages so the next probe's WPR2-up check + * passes and it re-boots from scratch. */ + nv_vgpu_warn(ctx->vgpu, "GSPRM: cmd writePtr jumped %u -> %u, GSP boot declared dead", rm->cmd_read, tx.writePtr); - rm->cmd_read = tx.writePtr; + gsp_emu_clear_boot_state(ctx, "stale GSP-RM queue"); return; } @@ -1003,12 +1022,17 @@ static void gsp_rm_poll_commands(struct gsp_emu_context *ctx) if (signature != GSPRM_RPC_SIGNATURE || elem_count == 0 || elem_count > rm->cmd_msgcount) { - nv_vgpu_warn(ctx->vgpu, "GSPRM: bad element idx=%u sig=0x%x elemCount=%u fn=%u, skipping", + /* The driver always writes a valid element BEFORE + * bumping writePtr. An advanced writePtr with garbage + * content means the queue buffer is stale (freed and + * reused by the guest after unload/crash) - declare + * the emulated GSP dead so the next probe re-boots. */ + nv_vgpu_warn(ctx->vgpu, "GSPRM: garbage element idx=%u sig=0x%x elemCount=%u fn=%u, GSP boot declared dead", rm->cmd_read, signature, elem_count, hdr->function); - rm->cmd_read++; kfree(elem); - continue; + gsp_emu_clear_boot_state(ctx, "garbage GSP-RM queue"); + return; } gsp_rm_handle_element(ctx, elem); |
