summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-05 12:50:44 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-05 12:50:44 -0400
commit5f511b70d272a898d0dc5a46d56ccb07c69060f0 (patch)
tree10a2c58c4c50c7db44193d734f00bd97487eabc0 /kernel
parent79327c204237052d16b948c8fb42e0d4c992564e (diff)
downloadopen-iov-5f511b70d272a898d0dc5a46d56ccb07c69060f0.tar.gz
open-iov-5f511b70d272a898d0dc5a46d56ccb07c69060f0.zip
vgsp: GR ctx query ABI fix, server-managed ctx map exclusion, raw diag capture
- NV2080_CTRL_GR_CTX_BUFFER_INFO is 80 bytes (NvBool is NvU8: flags at 56..59, uuid at 60) and the params are 5136 bytes, not 5648; the previous ABI mismatch is why GR_GET_CTX_BUFFER_INFO returned NV_ERR_INVALID_ARGUMENT (0x1f) on every shared-VAS cycle. - Under gsp_phys_srv_ctxbuf the GSP-RM server allocates/maps/commits the engine context itself: do not install the client GR context-window PDEs and do not map the client ctx VA in the PDB, so a client mapping cannot clobber the server's own context-window page table. - Dump the server-written INSTANCE/RAMFC chunks after BIND/SCHEDULE on the shared GR path so the committed engine-context pointer/VA can be located. - Emit the full NOCAT diag buffer as 16-byte hex rows (the printable copy is capped at 192 dotted bytes and hides binary fault dumps). Untested on hardware at commit time; the next supervised GR cycle validates.
Diffstat (limited to 'kernel')
-rw-r--r--kernel/gsp_phys_booter.c113
1 files changed, 97 insertions, 16 deletions
diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c
index 223420f..d5585e4 100644
--- a/kernel/gsp_phys_booter.c
+++ b/kernel/gsp_phys_booter.c
@@ -3830,7 +3830,7 @@ static void gsp_phys_status_nocat_record(struct seq_file *m,
struct gsp_phys_fault_info fi;
char engine[GSP_PHYS_NOCAT_LEN_SOURCE];
char diag[GSP_PHYS_STATUS_DIAG_MAX + 1];
- u32 bugcheck = 0, diag_len = 0, diag_avail = 0, i;
+ u32 bugcheck = 0, diag_len = 0, diag_avail = 0, diag_total, i;
memset(&fi, 0, sizeof(fi));
gsp_phys_nocat_decode(rec, &fi);
@@ -3846,6 +3846,7 @@ static void gsp_phys_status_nocat_record(struct seq_file *m,
diag_avail = len - GSP_PHYS_NOCAT_OFF_DIAGBUF;
if (diag_len && diag_avail > diag_len)
diag_avail = diag_len;
+ diag_total = diag_avail;
if (diag_avail > GSP_PHYS_STATUS_DIAG_MAX)
diag_avail = GSP_PHYS_STATUS_DIAG_MAX;
for (i = 0; i < diag_avail; i++) {
@@ -3868,6 +3869,26 @@ static void gsp_phys_status_nocat_record(struct seq_file *m,
rec->first_slot, fi.nocat_rec_type, fi.nocat_error_code,
fi.nocat_subsystem, bugcheck, diag_len, diag_avail, engine,
diag);
+ /*
+ * Raw hex companion: the printable copy above is capped at 192 dotted
+ * bytes, which hides the numeric fields and binary dumps the fault
+ * decoders need (recType=2 engine dumps, recType=3 FECS/TDR dumps,
+ * recType=4 GR fault records). Emit the full available diag as
+ * 16-byte hex rows so a failing cycle is fully decodable offline.
+ */
+ for (i = 0; i < diag_total; i += 16) {
+ char hex[3 * 16 + 1];
+ u32 j, n = diag_total - i;
+
+ if (n > 16)
+ n = 16;
+ for (j = 0; j < n; j++)
+ snprintf(hex + j * 3, 4, "%02x ",
+ p[GSP_PHYS_NOCAT_OFF_DIAGBUF + i + j]);
+ hex[n * 3] = '\0';
+ gsp_phys_status_emit(m, "func=0x1020 diaghex[%03u]: %s",
+ i, hex);
+ }
}
/* Any other function: one compact header line. */
@@ -6020,8 +6041,10 @@ struct gsp_phys_rmcall_mem_virtual_params {
__le32 pad;
};
-/* NV2080_CTRL_GR_CTX_BUFFER_INFO (88 bytes),
- * ctrl/ctrl2080/ctrl2080gr.h:1066-1081. */
+/* NV2080_CTRL_GR_CTX_BUFFER_INFO (80 bytes),
+ * ctrl/ctrl2080/ctrl2080gr.h:1066-1081. NvBool is NvU8 in the SDK
+ * (nvtypes.h:272), so the four boolean flags are one byte each and the
+ * uuid follows them at offset 60; the struct is 80 bytes, not 88. */
struct gsp_phys_rmcall_ctx_buffer_info {
__le64 alignment;
__le64 size;
@@ -6032,15 +6055,16 @@ struct gsp_phys_rmcall_ctx_buffer_info {
__le32 aperture;
__le32 kind;
__le32 page_size;
- __le32 b_is_contigous;
- __le32 b_global_buffer;
- __le32 b_local_buffer;
- __le32 b_device_descendant;
+ u8 b_is_contigous;
+ u8 b_global_buffer;
+ u8 b_local_buffer;
+ u8 b_device_descendant;
u8 uuid[16];
+ u8 pad[4];
};
/*
- * NV2080_CTRL_GR_GET_CTX_BUFFER_INFO_PARAMS (5648 bytes): hUserClient,
+ * NV2080_CTRL_GR_GET_CTX_BUFFER_INFO_PARAMS (5136 bytes): hUserClient,
* hChannel, bufferCount and the inline 64-entry info array
* (ctrl2080gr.h:1107-1112). Best-effort readback only.
*/
@@ -6408,9 +6432,13 @@ static int gsp_phys_rmcall_map_pt_window(void __iomem *bar0)
/*
* Install the GR context window PT pages too (VA 0x2200000 window
* number 17 + i), so the engine can load/restore the context through
- * the mapped VA the promote installs.
+ * the mapped VA the promote installs. Skipped under
+ * gsp_phys_srv_ctxbuf: the server owns that mapping on this path and
+ * a client PDE install there risks clobbering the server's own
+ * context-window page table.
*/
- for (i = 0; i < boot_stage.rmcall_ctx_pt_pages; i++) {
+ for (i = 0; !gsp_phys_srv_ctxbuf_value() &&
+ i < boot_stage.rmcall_ctx_pt_pages; i++) {
u32 ctx_index = (u32)((GSP_PHYS_RMCALL_VA_GR_CTX >> 21) + i);
u64 ctx_pt_pa = (u64)gsp_phys_chunk_page_dma(
&boot_stage.rmcall_ctx_pt[i], 0);
@@ -7468,8 +7496,13 @@ static void gsp_phys_rmcall_pdb_build(void)
* and previously zero PD0 entries are written: the ladder and scratch
* mappings stay byte-identical, no engine-fetched line is rewritten, and
* the COPY0 ladder never enters this block.
+ *
+ * Skipped entirely under gsp_phys_srv_ctxbuf: the server allocates,
+ * maps and commits the engine context itself on that path, and a
+ * client PT/VA mapping of our private buffer must not overwrite the
+ * server's own PDE for its ctx window.
*/
- if (boot_stage.rmcall_ctx_prepared) {
+ if (boot_stage.rmcall_ctx_prepared && !gsp_phys_srv_ctxbuf_value()) {
for (i = 0; i < boot_stage.rmcall_ctx_pt_pages; i++) {
u32 pd0_idx = (u32)(((GSP_PHYS_RMCALL_VA_GR_CTX >> 21) +
i) & 0xffu);
@@ -8834,7 +8867,7 @@ static void gsp_phys_rmcall_gr_ctx_info(void __iomem *bar0)
le64_to_cpu(ci->size),
le64_to_cpu(ci->page_count),
le64_to_cpu(ci->alignment),
- le32_to_cpu(ci->b_is_contigous));
+ ci->b_is_contigous);
/* MAIN is bufferType 0 (NV2080_CTRL_GR_CTX_BUFFER_INFO enum). */
if (le32_to_cpu(ci->buffer_type) == 0 &&
!boot_stage.rmcall_srv_main_valid) {
@@ -10533,6 +10566,38 @@ static int gsp_phys_backend_guest_ce_copy_trigger(u64 src_hpa, u32 src_off,
* proceeds (the server writes the token before the notifier update,
* kernel_channel.c:3471-3477).
*/
+
+/*
+ * Shared-management GR context diagnostic: dump the first words of the
+ * server-written channel instance block and RAMFC so the engine-context
+ * pointer/VA the server committed can be located (the ctxsw fault is an
+ * engine-side context-image rejection; the instance block carries the engine
+ * context pointer, kernel_graphics_context.c:1138-1141). Host-visible chunks;
+ * bounded to one 4 KB page each. Enabled whenever the shared + srvctx GR
+ * ladder runs; volume is a few hundred lines per cycle.
+ */
+static void gsp_phys_rmcall_ctx_diag_dump(const char *what,
+ struct gsp_phys_boot_chunk *c)
+{
+ u32 i, words = GSP_PHYS_PAGE_SIZE / 4u;
+
+ if (!c || !c->pages) {
+ pr_info("vgsp-boot: rm-call: %s dump skipped (chunk absent)\n", what);
+ return;
+ }
+ for (i = 0; i + 8 <= words; i += 8) {
+ const __le32 *p =
+ (const __le32 *)gsp_phys_chunk_page_va(c, 0) + i;
+
+ pr_info("vgsp-boot: rm-call: %s[%04x]: %08x %08x %08x %08x %08x %08x %08x %08x\n",
+ what, i * 4,
+ le32_to_cpu(p[0]), le32_to_cpu(p[1]),
+ le32_to_cpu(p[2]), le32_to_cpu(p[3]),
+ le32_to_cpu(p[4]), le32_to_cpu(p[5]),
+ le32_to_cpu(p[6]), le32_to_cpu(p[7]));
+ }
+}
+
static int gsp_phys_rmcall_stage4(void __iomem *bar0)
{
struct gsp_phys_boot_chunk *userd_c = &boot_stage.rmcall_chunks[GSP_PHYS_RMCALL_BUF_USERD];
@@ -10632,6 +10697,20 @@ static int gsp_phys_rmcall_stage4(void __iomem *bar0)
boot_stage.rmcall_tsg, rpc_result, status);
/*
+ * Shared-management GR diagnostic: the server owns the engine context;
+ * dump the instance/RAMFC words here (post-BIND/SCHEDULE, pre-submit)
+ * so the committed engine-context pointer/VA can be correlated with
+ * the server MAIN PA reported by the fixed GET_CTX_BUFFER_INFO query.
+ */
+ if (gsp_phys_rmcall_vas_shared_value() &&
+ gsp_phys_rmcall_engine_is_gr()) {
+ gsp_phys_rmcall_ctx_diag_dump("INSTANCE",
+ &boot_stage.rmcall_chunks[GSP_PHYS_RMCALL_BUF_INSTANCE]);
+ gsp_phys_rmcall_ctx_diag_dump("RAMFC",
+ &boot_stage.rmcall_chunks[GSP_PHYS_RMCALL_BUF_RAMFC]);
+ }
+
+ /*
* (c) SET_WORK_SUBMIT_TOKEN_NOTIF_INDEX (nvidia-push-init.c:303-316).
* Advisory, not fatal: with no error-context object (hErrorContext=0)
* the server's memory and ctxdma lookups both fail and it returns
@@ -12662,10 +12741,12 @@ static_assert(offsetof(struct gsp_phys_rmcall_promote_params, entry_count) == 40
"NV2080_CTRL_GPU_PROMOTE_CTX_PARAMS.entryCount must be at offset 40");
static_assert(offsetof(struct gsp_phys_rmcall_promote_params, entry) == 48,
"NV2080_CTRL_GPU_PROMOTE_CTX_PARAMS.promoteEntry must be at offset 48 (8-byte aligned)");
-static_assert(sizeof(struct gsp_phys_rmcall_ctx_buffer_info) == 88,
- "NV2080_CTRL_GR_CTX_BUFFER_INFO must be 88 bytes (reference ABI)");
-static_assert(sizeof(struct gsp_phys_rmcall_ctx_buffer_info_params) == 5648,
- "NV2080_CTRL_GR_GET_CTX_BUFFER_INFO_PARAMS must be 5648 bytes (reference ABI)");
+static_assert(sizeof(struct gsp_phys_rmcall_ctx_buffer_info) == 80,
+ "NV2080_CTRL_GR_CTX_BUFFER_INFO must be 80 bytes (NvBool = NvU8)");
+static_assert(offsetof(struct gsp_phys_rmcall_ctx_buffer_info, uuid) == 60,
+ "NV2080_CTRL_GR_CTX_BUFFER_INFO.uuid must be at offset 60");
+static_assert(sizeof(struct gsp_phys_rmcall_ctx_buffer_info_params) == 5136,
+ "NV2080_CTRL_GR_GET_CTX_BUFFER_INFO_PARAMS must be 5136 bytes");
static_assert(offsetof(struct gsp_phys_rmcall_ctx_buffer_info_params,
ctx_buffer_info) == 16,
"NV2080_CTRL_GR_GET_CTX_BUFFER_INFO_PARAMS.ctxBufferInfo must be at offset 16 (8-byte aligned)");