From 4465833fa61dbed0519b770774b4ed439cf22054 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Thu, 1 Oct 2026 13:11:30 -0400 Subject: gsp-phys: queue the pre-boot GSP_SET_SYSTEM_INFO and SET_REGISTRY async RPCs The real-GSP boot path staged the message queue but never queued the two fire-and-forget init RPCs the production client places in it before the booter starts. GSP-RM therefore created its GPU object without any system information and aborted RM init (live GSP_INIT_DONE rpc_result=0x59), with the resource-manager's object-database lookups asserting from the first journal record. Submit function 72 (GSP_SET_SYSTEM_INFO, 928-byte v17_00 payload carrying the BAR physical bases, domain/bus/slot, PCI IDs, the BAR0 config-mirror offset, link/FLR capabilities and upstream-port flags read from the pci_dev) and function 73 (SET_REGISTRY, header-only empty table, which the server explicitly accepts) through the existing submit-only queue producer after all stage-3d preconditions and before the GSP falcon reset/Booter Load kick. The wire layouts are re-declared in the module with per-field static asserts against the reference ABI; payloads are heap-allocated, so no new stack frames are introduced. --- kernel/gsp_phys_booter.c | 478 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 478 insertions(+) (limited to 'kernel/gsp_phys_booter.c') diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c index ad37831..d59da78 100644 --- a/kernel/gsp_phys_booter.c +++ b/kernel/gsp_phys_booter.c @@ -40,6 +40,8 @@ #include #include #include +#include +#include #include #include @@ -182,6 +184,23 @@ bool gsp_phys_boot_requested(void) #define GSP_PHYS_RPC_FUNC_UNLOADING_GUEST_DRIVER 47u #define GSP_PHYS_RPC_FUNC_SET_GUEST_SYSTEM_INFO 1u #define GSP_PHYS_RPC_FUNC_GET_GSP_STATIC_INFO 65u +#define GSP_PHYS_RPC_FUNC_GSP_SET_SYSTEM_INFO 72u +#define GSP_PHYS_RPC_FUNC_SET_REGISTRY 73u + +/* + * PCIe config-space mirror window, as carried in GspSystemInfo. The field is + * a BAR0 register offset, not a host buffer: the GSP-RM server feeds it to + * osPciInitHandle()/osPciReadDword(), which do sysBar0Read(base + config + * offset), i.e. they read the GPU's hardware config mirror in its own BAR0. + * On Turing that is DEVICE_BASE(NV_PCFG) = 0x88000 with a 4 KB extent + * (`NV_PCFG 0x00088FFF:0x00088000` in the published turing/tu102 swref), and + * the CPU-RM BIF HAL for this family returns exactly those two values + * (kbifGetPciConfigSpacePriMirror_GM107). Do not allocate a DMA buffer here: + * GSP-RM would interpret its physical address as a BAR0 offset and read an + * unrelated register window. + */ +#define GSP_PHYS_PCI_CONFIG_MIRROR_BASE 0x00088000u +#define GSP_PHYS_PCI_CONFIG_MIRROR_SIZE 0x00001000u /* * GSP command-queue doorbell. After publishing writePtr the reference @@ -409,6 +428,101 @@ struct gsp_phys_rpc_set_guest_system_info { char guest_title[0x100]; }; +/* + * GspSystemInfo, the GSP_SET_SYSTEM_INFO (function 72, v17_00) payload. The + * reference queues this RPC into the command queue before the GSP is booted + * (kgspQueueAsyncInitRpcs, kernel_gsp.c:3358-3381, called from kgspInitRm + * before _kgspBootGspRm) so GSP-RM consumes it before OBJGPU is created. + * + * Field offsets/widths below were derived by compiling the reference header + * (kernel/gpu/gsp/gsp_static_config.h) with offsetof/sizeof against the + * 570.144 tree and are also pinned in the tracked ABI check file + * (gsp_abi_check.c:324-375, ABI_CHECK_SIZE_GE 920). The reference sender + * transmits sizeof(GspSystemInfo) = 928 bytes (hostPageSize was appended at + * offset 920); the whole struct is sent with rpc.length = 32 + 928 = 960. + * Static asserts at the end of this file re-check every offset here without + * including any reference header in the kernel module. + */ +struct gsp_phys_gsp_system_info { + __le64 gpu_phys_addr; /* 0 */ + __le64 gpu_phys_fb_addr; /* 8 */ + __le64 gpu_phys_inst_addr; /* 16 */ + __le64 gpu_phys_io_addr; /* 24 */ + __le64 nv_domain_bus_device_func; /* 32 */ + __le64 sim_access_buf_phys_addr; /* 40 */ + __le64 notify_op_shared_surface_phys_addr; /* 48 */ + __le64 pcie_atomics_op_mask; /* 56 */ + __le64 console_mem_size; /* 64 */ + __le64 max_user_va; /* 72 */ + __le32 pci_config_mirror_base; /* 80 */ + __le32 pci_config_mirror_size; /* 84 */ + __le32 pci_device_id; /* 88 */ + __le32 pci_sub_device_id; /* 92 */ + __le32 pci_revision_id; /* 96 */ + __le32 pcie_atomics_cpl_device_cap_mask; /* 100 */ + u8 oor_arch; /* 104 */ + u8 pad0[7]; /* 105..111 */ + __le64 cl_pdb_properties; /* 112 */ + __le32 chipset; /* 120 */ + u8 b_gpu_behind_bridge; /* 124 */ + u8 b_flr_supported; /* 125 */ + u8 b64b_bar0_supported; /* 126 */ + u8 b_mnoc_available; /* 127 */ + __le32 chipset_l1ss_enable; /* 128 */ + u8 b_upstream_l0s_unsupported; /* 132 */ + u8 b_upstream_l1_unsupported; /* 133 */ + u8 b_upstream_l1_por_supported; /* 134 */ + u8 b_upstream_l1_por_mobile_only; /* 135 */ + u8 b_system_has_mux; /* 136 */ + u8 upstream_address_valid; /* 137 */ + u8 fhb_bus_info[10]; /* 138 */ + u8 chipset_id_info[10]; /* 148 */ + u8 pad1[2]; /* 158..159 */ + u8 acpi_method_data[676]; /* 160 */ + __le32 hypervisor_type; /* 836 */ + u8 b_is_passthru; /* 840 */ + u8 pad2[7]; /* 841..847 */ + __le64 sys_timer_offset_ns; /* 848 */ + u8 gsp_vf_info[40]; /* 856 */ + u8 b_is_primary; /* 896 */ + u8 is_grid_build; /* 897 */ + u8 pad3[2]; /* 898..899 */ + __le32 pcie_config_reg_link_cap; /* 900 */ + __le32 grid_build_csp; /* 904 */ + u8 b_preserve_video_memory_allocations; /* 908 */ + u8 b_tdr_event_supported; /* 909 */ + u8 b_feature_stretch_vblank_capable; /* 910 */ + u8 b_enable_dynamic_granularity_page_arrays; /* 911 */ + u8 b_clock_boost_supported; /* 912 */ + u8 b_route_disp_intrs_to_cpu; /* 913 */ + u8 pad4[6]; /* 914..919 */ + __le64 host_page_size; /* 920 */ +}; + +/* + * PACKED_REGISTRY_TABLE, the SET_REGISTRY (function 73, v17_00) payload + * (g_os_nvoc.h:217-230; ABI checks gsp_abi_check.c:2126-2136). The header is + * 8 bytes: `size` is the total table size (header + entry array + name/value + * blob, entries[] = 16 bytes each) and `numEntries` the number of entries. + * An empty table is size = 8, numEntries = 0 and is explicitly accepted by + * the GSP-RM server: _rpcSetRegistry maps osUnpackageRegistry()'s + * NV_WARN_NOTHING_TO_DO to "Registry is empty." and continues (the Nouveau + * client is documented to send no keys). Payload 8 bytes, rpc.length = 40. + */ +struct gsp_phys_packed_registry_entry { + __le32 name_offset; /* offset from table base to the NUL-terminated name */ + u8 type; /* REGISTRY_TABLE_ENTRY_TYPE_* */ + u8 pad[3]; + __le32 data; /* dword value or offset to value bytes */ + __le32 length; /* value length in bytes */ +}; + +struct gsp_phys_packed_registry_table { + __le32 size; /* total table size including this header */ + __le32 num_entries; + /* struct gsp_phys_packed_registry_entry entries[] follows */ +}; + /* * GspStaticConfigInfo reply field offsets, pinned by the reference ABI checks * (gsp_abi_check.c:266-320, ABI_CHECK_SIZE_GE 1656). Only the fields this @@ -495,6 +609,7 @@ static struct gsp_phys_boot_stage { u32 rm_probe_last_payload_len; /* last probe reply payload bytes */ u32 rm_probe_attempts; /* rm-probe triggers this boot */ bool seq_dump_logged; /* 0x1002 hex/opcode dump done this boot */ + bool preinit_submitted; /* fn 72/73 queued before the booter kick */ u32 tx_seq_num; /* next command-queue element seqNum */ u32 status_read_ptr; /* next status-queue slot to consume (persists * across stage 3e and debugfs probe walks) */ @@ -1145,6 +1260,8 @@ static void gsp_phys_boot_telemetry(void __iomem *bar0) readl(bar0 + GSP_PHYS_GFW_BOOT)); } +static int gsp_phys_preinit_rpcs(void __iomem *bar0, struct pci_dev *pdev); + int gsp_phys_boot_run(struct gsp_phys_boot *boot, struct pci_dev *pdev, void __iomem *bar0) { @@ -1171,6 +1288,26 @@ int gsp_phys_boot_run(struct gsp_phys_boot *boot, struct pci_dev *pdev, return -EPERM; } + /* + * Queue the pre-boot async init RPCs (GSP_SET_SYSTEM_INFO 72 then + * SET_REGISTRY 73) into the already-staged command queue, exactly + * where the reference does it relative to the boot: kgspQueueAsyncInitRpcs + * runs before _kgspBootGspRm starts the booter, so GSP-RM consumes + * both messages at early init before OBJGPU is created. A failed + * publish aborts the boot; GSP-RM would otherwise start with zero + * system info (gpuPhys* and the config mirror all zero). + */ + if (!boot_stage.preinit_submitted) { + ret = gsp_phys_preinit_rpcs(bar0, pdev); + if (ret) { + pr_err("gsp-phys-boot: stage 3d FAILED: pre-boot async init RPCs (fn %u/%u) were not queued (%d); refusing to start GSP-RM without system info\n", + GSP_PHYS_RPC_FUNC_GSP_SET_SYSTEM_INFO, + GSP_PHYS_RPC_FUNC_SET_REGISTRY, ret); + return ret; + } + boot_stage.preinit_submitted = true; + } + pr_info("gsp-phys-boot: stage 3d: resetting GSP falcon into RISC-V, libos args 0x%llx\n", (u64)boot->libos_args_dma); gsp_phys_scratch14_log(bar0, "pre-gsp-reset"); @@ -2730,6 +2867,197 @@ int gsp_phys_queue_tx_submit(void __iomem *bar0, u32 function, return 0; } +/* + * Fill the GspSystemInfo payload from the claimed pci_dev, mirroring the + * reference rpcGspSetSystemInfo_v17_00 field by field (rpc.c:9446-9604): + * + * - gpuPhys*: the Linux OS layer attaches the GPU with + * nv->regs->cpu_address / nv->fb->cpu_address / + * nv->bars[NV_GPU_BAR_INDEX_IMEM].cpu_address (osinit.c:703-708), all of + * which are pci_resource_start() values of the memory BARs in order + * (nv-pci.c:816-823: regs = first memory BAR, fb = second, imem = third). + * gpuPhysIoAddr is never set on Linux and stays 0. + * - nvDomainBusDeviceFunc = gpuEncodeDomainBusDevice(domain, bus, slot) with + * domain bits 63:32, bus 15:8, slot (device) 7:0; nv-pci.c passes + * NV_PCI_SLOT_NUMBER (PCI_SLOT(devfn), function excluded). + * - PCI IDs/revision from the pci_dev. + * - pciConfigMirror*: the BIF HAL's BAR0 offset/size (see the constant + * comment above). + * - FLR comes from the PCIe device capability (kbifCacheFlrSupport_TU102 + * reads the same bit through the XVE mirror); the link capability is the + * PCIe Link Capabilities register (kbifGetGpuLinkCapabilities_IMPL). + * b64bBar0Supported/bMnocAvailable/pcieAtomics* are only ever set on + * GA100+/GB100 BIFs, so the reference sends 0 on TU10x. + * - ASPM/L1SS/bBehindBridge/upstreamAddressValid mirror chipset_pcie.c's + * upstream-port walk (upstream port = pci_upstream_bridge()). + * - maxUserVa = TASK_SIZE (osGetMaxUserVa -> os_get_max_user_va), host page + * size = PAGE_SIZE, bIsPrimary from the VGA arbiter default device + * (osinit.c:955: primary_vga || client_managed_console; the dGPU on this + * host is a secondary device). + * - Everything else is a documented conservative zero (hypervisorType, + * SR-IOV VF info, grid, ACPI method data, system mux, POR flags, timer + * offset, passthru, console memory, dynamic-granularity arrays, TDR, + * stretch-vblank, route display interrupts; Windows/display/optional + * paths that are inactive in a bare-metal Linux headless boot). + * bClockBoostSupported is 1 (the task-specified value for this board). + */ +static void gsp_phys_preinit_fill_system_info( + struct gsp_phys_gsp_system_info *info, struct pci_dev *pdev) +{ + struct pci_dev *bridge; + u64 bars[3] = { 0, 0, 0 }; + u32 cap = 0; + unsigned int i, nbars = 0; + + memset(info, 0, sizeof(*info)); + + /* + * The reference BAR walk: memory BARs with a nonzero start and size + * in PCI config order (nv-pci.c:816-823). + */ + for (i = 0; i < 6 && nbars < ARRAY_SIZE(bars); i++) { + if (!pci_resource_start(pdev, i) || !pci_resource_len(pdev, i)) + continue; + if ((pci_resource_flags(pdev, i) & PCI_BASE_ADDRESS_SPACE) != + PCI_BASE_ADDRESS_SPACE_MEMORY) + continue; + bars[nbars++] = pci_resource_start(pdev, i); + } + info->gpu_phys_addr = cpu_to_le64(bars[0]); + info->gpu_phys_fb_addr = cpu_to_le64(bars[1]); + info->gpu_phys_inst_addr = cpu_to_le64(bars[2]); + info->gpu_phys_io_addr = cpu_to_le64(0); + + info->nv_domain_bus_device_func = cpu_to_le64( + ((u64)pci_domain_nr(pdev->bus) << 32) | + ((u64)pdev->bus->number << 8) | + (u64)PCI_SLOT(pdev->devfn)); + + info->pci_config_mirror_base = + cpu_to_le32(GSP_PHYS_PCI_CONFIG_MIRROR_BASE); + info->pci_config_mirror_size = + cpu_to_le32(GSP_PHYS_PCI_CONFIG_MIRROR_SIZE); + info->pci_device_id = cpu_to_le32(pdev->device); + info->pci_sub_device_id = cpu_to_le32(pdev->subsystem_device); + info->pci_revision_id = cpu_to_le32(pdev->revision); + info->oor_arch = 0; /* OOR_ARCH_X86_64 */ + + if (!pcie_capability_read_dword(pdev, PCI_EXP_DEVCAP, &cap) && + (cap & PCI_EXP_DEVCAP_FLR)) + info->b_flr_supported = 1; + cap = 0; + if (!pcie_capability_read_dword(pdev, PCI_EXP_LNKCAP, &cap)) + info->pcie_config_reg_link_cap = cpu_to_le32(cap); + + bridge = pci_upstream_bridge(pdev); + if (bridge) { + info->b_gpu_behind_bridge = 1; + info->upstream_address_valid = 1; + + cap = 0; + if (!pcie_capability_read_dword(bridge, PCI_EXP_LNKCAP, + &cap)) { + if (!(cap & PCI_EXP_LNKCAP_ASPM_L0S)) + info->b_upstream_l0s_unsupported = 1; + if (!(cap & PCI_EXP_LNKCAP_ASPM_L1)) + info->b_upstream_l1_unsupported = 1; + } else { + info->b_upstream_l0s_unsupported = 1; + info->b_upstream_l1_unsupported = 1; + } + + cap = 0; + i = pci_find_ext_capability(bridge, PCI_EXT_CAP_ID_L1SS); + if (i && !pci_read_config_dword(bridge, i + PCI_L1SS_CTL1, + &cap)) + info->chipset_l1ss_enable = cpu_to_le32(cap); + } + + info->max_user_va = cpu_to_le64((u64)TASK_SIZE); + info->host_page_size = cpu_to_le64((u64)PAGE_SIZE); + info->b_is_primary = (vga_default_device() == pdev) ? 1 : 0; + info->b_clock_boost_supported = 1; + info->b_route_disp_intrs_to_cpu = 0; /* Linux: NV_FALSE */ +} + +/* + * Queue the two pre-boot async init RPCs the reference calls + * kgspQueueAsyncInitRpcs (kernel_gsp.c:3358-3381): GSP_SET_SYSTEM_INFO (72, + * rpcGspSetSystemInfo_v17_00, 928-byte payload) then SET_REGISTRY (73, + * rpcSetRegistry_v17_00, empty PACKED_REGISTRY_TABLE: size 8/numEntries 0, + * which the GSP-RM server accepts and continues on). Both are fire-and-forget + * (no rpc_result wait): the GSP-RM server's function table entries return + * "nothing" and no reply is expected. The existing TX producer already has + * submit-only semantics, so both records go through gsp_phys_queue_tx_submit + * with increasing seqNum. + */ +static int gsp_phys_preinit_rpcs(void __iomem *bar0, struct pci_dev *pdev) +{ + struct gsp_phys_gsp_system_info *info; + struct gsp_phys_packed_registry_table *reg; + int ret; + + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + gsp_phys_preinit_fill_system_info(info, pdev); + pr_info("gsp-phys-boot: pre-boot GSP_SET_SYSTEM_INFO (fn%u) prepared: gpuPhys=0x%llx fb=0x%llx inst=0x%llx io=0x%llx dbf=0x%llx mirror=0x%x/0x%x ids=%04x:%04x:%02x maxUserVa=0x%llx pageSize=0x%llx flr=%u behindBridge=%u l1ss=0x%x lnkCap=0x%x primary=%u\n", + GSP_PHYS_RPC_FUNC_GSP_SET_SYSTEM_INFO, + le64_to_cpu(info->gpu_phys_addr), + le64_to_cpu(info->gpu_phys_fb_addr), + le64_to_cpu(info->gpu_phys_inst_addr), + le64_to_cpu(info->gpu_phys_io_addr), + le64_to_cpu(info->nv_domain_bus_device_func), + le32_to_cpu(info->pci_config_mirror_base), + le32_to_cpu(info->pci_config_mirror_size), + le32_to_cpu(info->pci_device_id), + le32_to_cpu(info->pci_sub_device_id), + info->pci_revision_id, le64_to_cpu(info->max_user_va), + le64_to_cpu(info->host_page_size), info->b_flr_supported, + info->b_gpu_behind_bridge, + le32_to_cpu(info->chipset_l1ss_enable), + le32_to_cpu(info->pcie_config_reg_link_cap), + info->b_is_primary); + ret = gsp_phys_queue_tx_submit(bar0, + GSP_PHYS_RPC_FUNC_GSP_SET_SYSTEM_INFO, + info, sizeof(*info)); + kfree(info); + if (ret) { + pr_err("gsp-phys-boot: pre-boot GSP_SET_SYSTEM_INFO (fn%u) submit failed: %d\n", + GSP_PHYS_RPC_FUNC_GSP_SET_SYSTEM_INFO, ret); + return ret; + } + + /* + * Empty registry table (size 8, numEntries 0): the reference CPU-RM + * treats an empty local table as a warning, but the GSP-RM server + * explicitly maps osUnpackageRegistry()'s NV_WARN_NOTHING_TO_DO to + * "Registry is empty." and answers success, so the header-only form + * is the minimal valid payload. + */ + reg = kzalloc(sizeof(*reg), GFP_KERNEL); + if (!reg) + return -ENOMEM; + reg->size = cpu_to_le32(sizeof(*reg)); + reg->num_entries = cpu_to_le32(0); + pr_info("gsp-phys-boot: pre-boot SET_REGISTRY (fn%u) prepared: size=%u numEntries=0 (header-only table; GSP-RM accepts the empty case)\n", + GSP_PHYS_RPC_FUNC_SET_REGISTRY, (unsigned int)sizeof(*reg)); + ret = gsp_phys_queue_tx_submit(bar0, + GSP_PHYS_RPC_FUNC_SET_REGISTRY, + reg, sizeof(*reg)); + kfree(reg); + if (ret) { + pr_err("gsp-phys-boot: pre-boot SET_REGISTRY (fn%u) submit failed: %d\n", + GSP_PHYS_RPC_FUNC_SET_REGISTRY, ret); + return ret; + } + + pr_info("gsp-phys-boot: pre-boot async init RPCs queued (fn%u then fn%u); GSP-RM will consume them at early init before OBJGPU creation\n", + GSP_PHYS_RPC_FUNC_GSP_SET_SYSTEM_INFO, + GSP_PHYS_RPC_FUNC_SET_REGISTRY); + return 0; +} + static DEFINE_MUTEX(gsp_phys_rm_lock); int gsp_phys_boot_rm_unload(void __iomem *bar0) @@ -3728,3 +4056,153 @@ static_assert(GSP_PHYS_NOCAT_OFF_FAULTENGINE + GSP_PHYS_NOCAT_LEN_SOURCE <= static_assert(offsetof(struct gsp_phys_nocat_journal_record, diag_buffer) == GSP_PHYS_NOCAT_OFF_DIAGBUF, "NOCAT diagBuffer must live at payload offset 180 (reference ABI)"); + +/* + * GspSystemInfo wire ABI, pinned against the reference header compile + * (offsetof/sizeof of kernel/gpu/gsp/gsp_static_config.h, 570.144) and the + * tracked ABI checks (gsp_abi_check.c:324-375). Reference sender payload is + * 928 bytes (hostPageSize appended at 920), rpc.length = 32 + 928 = 960. + */ +static_assert(sizeof(struct gsp_phys_gsp_system_info) == 928, + "GspSystemInfo must be 928 bytes (reference 570.144 ABI)"); +static_assert(offsetof(struct gsp_phys_gsp_system_info, gpu_phys_addr) == 0, + "GspSystemInfo.gpuPhysAddr offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_gsp_system_info, gpu_phys_fb_addr) == 8, + "GspSystemInfo.gpuPhysFbAddr offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_gsp_system_info, gpu_phys_inst_addr) == 16, + "GspSystemInfo.gpuPhysInstAddr offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_gsp_system_info, gpu_phys_io_addr) == 24, + "GspSystemInfo.gpuPhysIoAddr offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_gsp_system_info, + nv_domain_bus_device_func) == 32, + "GspSystemInfo.nvDomainBusDeviceFunc offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_gsp_system_info, + sim_access_buf_phys_addr) == 40, + "GspSystemInfo.simAccessBufPhysAddr offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_gsp_system_info, + notify_op_shared_surface_phys_addr) == 48, + "GspSystemInfo.notifyOpSharedSurfacePhysAddr offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_gsp_system_info, + pcie_atomics_op_mask) == 56, + "GspSystemInfo.pcieAtomicsOpMask offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_gsp_system_info, console_mem_size) == 64, + "GspSystemInfo.consoleMemSize offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_gsp_system_info, max_user_va) == 72, + "GspSystemInfo.maxUserVa offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_gsp_system_info, + pci_config_mirror_base) == 80, + "GspSystemInfo.pciConfigMirrorBase offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_gsp_system_info, + pci_config_mirror_size) == 84, + "GspSystemInfo.pciConfigMirrorSize offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_gsp_system_info, pci_device_id) == 88, + "GspSystemInfo.PCIDeviceID offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_gsp_system_info, pci_sub_device_id) == 92, + "GspSystemInfo.PCISubDeviceID offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_gsp_system_info, pci_revision_id) == 96, + "GspSystemInfo.PCIRevisionID offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_gsp_system_info, + pcie_atomics_cpl_device_cap_mask) == 100, + "GspSystemInfo.pcieAtomicsCplDeviceCapMask offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_gsp_system_info, oor_arch) == 104, + "GspSystemInfo.oorArch offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_gsp_system_info, + cl_pdb_properties) == 112, + "GspSystemInfo.clPdbProperties offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_gsp_system_info, chipset) == 120, + "GspSystemInfo.Chipset offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_gsp_system_info, + b_gpu_behind_bridge) == 124, + "GspSystemInfo.bGpuBehindBridge offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_gsp_system_info, b_flr_supported) == 125, + "GspSystemInfo.bFlrSupported offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_gsp_system_info, + b64b_bar0_supported) == 126, + "GspSystemInfo.b64bBar0Supported offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_gsp_system_info, b_mnoc_available) == 127, + "GspSystemInfo.bMnocAvailable offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_gsp_system_info, + chipset_l1ss_enable) == 128, + "GspSystemInfo.chipsetL1ssEnable offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_gsp_system_info, + b_upstream_l0s_unsupported) == 132, + "GspSystemInfo.bUpstreamL0sUnsupported offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_gsp_system_info, + b_upstream_l1_unsupported) == 133, + "GspSystemInfo.bUpstreamL1Unsupported offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_gsp_system_info, + b_upstream_l1_por_supported) == 134, + "GspSystemInfo.bUpstreamL1PorSupported offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_gsp_system_info, + b_upstream_l1_por_mobile_only) == 135, + "GspSystemInfo.bUpstreamL1PorMobileOnly offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_gsp_system_info, + b_system_has_mux) == 136, + "GspSystemInfo.bSystemHasMux offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_gsp_system_info, + upstream_address_valid) == 137, + "GspSystemInfo.upstreamAddressValid offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_gsp_system_info, fhb_bus_info) == 138, + "GspSystemInfo.FHBBusInfo offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_gsp_system_info, chipset_id_info) == 148, + "GspSystemInfo.chipsetIDInfo offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_gsp_system_info, acpi_method_data) == 160, + "GspSystemInfo.acpiMethodData offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_gsp_system_info, hypervisor_type) == 836, + "GspSystemInfo.hypervisorType offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_gsp_system_info, b_is_passthru) == 840, + "GspSystemInfo.bIsPassthru offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_gsp_system_info, + sys_timer_offset_ns) == 848, + "GspSystemInfo.sysTimerOffsetNs offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_gsp_system_info, gsp_vf_info) == 856, + "GspSystemInfo.gspVFInfo offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_gsp_system_info, b_is_primary) == 896, + "GspSystemInfo.bIsPrimary offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_gsp_system_info, is_grid_build) == 897, + "GspSystemInfo.isGridBuild offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_gsp_system_info, + pcie_config_reg_link_cap) == 900, + "GspSystemInfo.pcieConfigReg.linkCap offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_gsp_system_info, grid_build_csp) == 904, + "GspSystemInfo.gridBuildCsp offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_gsp_system_info, + b_preserve_video_memory_allocations) == 908, + "GspSystemInfo.bPreserveVideoMemoryAllocations offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_gsp_system_info, + b_tdr_event_supported) == 909, + "GspSystemInfo.bTdrEventSupported offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_gsp_system_info, + b_feature_stretch_vblank_capable) == 910, + "GspSystemInfo.bFeatureStretchVblankCapable offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_gsp_system_info, + b_enable_dynamic_granularity_page_arrays) == 911, + "GspSystemInfo.bEnableDynamicGranularityPageArrays offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_gsp_system_info, + b_clock_boost_supported) == 912, + "GspSystemInfo.bClockBoostSupported offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_gsp_system_info, + b_route_disp_intrs_to_cpu) == 913, + "GspSystemInfo.bRouteDispIntrsToCPU offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_gsp_system_info, host_page_size) == 920, + "GspSystemInfo.hostPageSize offset (reference 570.144 ABI)"); +static_assert(GSP_PHYS_MSG_ELEMENT_PAYLOAD_OFF + + sizeof(struct gsp_phys_gsp_system_info) <= GSP_PHYS_MSG_SIZE, + "GspSystemInfo must fit one 4 KB queue element"); + +static_assert(sizeof(struct gsp_phys_packed_registry_entry) == 16, + "PACKED_REGISTRY_ENTRY must be 16 bytes (natural alignment, reference ABI)"); +static_assert(offsetof(struct gsp_phys_packed_registry_entry, name_offset) == 0, + "PACKED_REGISTRY_ENTRY.nameOffset offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_packed_registry_entry, type) == 4, + "PACKED_REGISTRY_ENTRY.type offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_packed_registry_entry, data) == 8, + "PACKED_REGISTRY_ENTRY.data offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_packed_registry_entry, length) == 12, + "PACKED_REGISTRY_ENTRY.length offset (reference ABI)"); +static_assert(sizeof(struct gsp_phys_packed_registry_table) == 8, + "PACKED_REGISTRY_TABLE header must be 8 bytes (reference ABI)"); +static_assert(offsetof(struct gsp_phys_packed_registry_table, size) == 0, + "PACKED_REGISTRY_TABLE.size offset (reference ABI)"); +static_assert(offsetof(struct gsp_phys_packed_registry_table, num_entries) == 4, + "PACKED_REGISTRY_TABLE.numEntries offset (reference ABI)"); -- cgit v1.2.3