From 1b7963baa31cf4399d6f2c9917272b2b42b55a4d Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Wed, 30 Sep 2026 23:44:55 -0400 Subject: gsp-phys: boot-layout stage 3b - boot-argument pages, WPR meta and FB layout (no device writes) --- kernel/Makefile | 1 + kernel/gsp_phys_boot.c | 406 +++++++++++++++++++++++++++++++++++++++++++++++++ kernel/gsp_phys_boot.h | 52 +++++++ kernel/gsp_phys_gpu.c | 31 +++- 4 files changed, 486 insertions(+), 4 deletions(-) create mode 100644 kernel/gsp_phys_boot.c create mode 100644 kernel/gsp_phys_boot.h diff --git a/kernel/Makefile b/kernel/Makefile index 6080164..b20dd87 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -17,6 +17,7 @@ open-iov-vfio-y := \ firmware_analyzer.o \ dynamic_rpc_dispatcher.o \ gsp_phys_gpu.o \ + gsp_phys_boot.o \ architecture/architecture.o \ version/version.o diff --git a/kernel/gsp_phys_boot.c b/kernel/gsp_phys_boot.c new file mode 100644 index 0000000..0118e06 --- /dev/null +++ b/kernel/gsp_phys_boot.c @@ -0,0 +1,406 @@ +/* + * Real-GSP boot bring-up stage 3b: boot-argument allocation and WPR layout. + * + * A real GSP boot needs three host-DMA pages - the WPR metadata the booter + * consumes, the libos init arguments, and the GSP/bootloader arguments - plus + * the video-memory layout recorded in that metadata. This file mirrors the + * layout computation the distribution driver performs for Turing, fills the + * 256-byte WprMeta structure and logs every field. + * + * Stage 3b writes nothing to the device: no BAR/register access happens here, + * the metadata page is filled in host memory only. Disabled by default + * (gsp_phys_layout=N); claim must be enabled too (gsp_phys_gpu=1). + */ + +#include +#include +#include +#include +#include +#include + +#include "gsp_phys_boot.h" + +static bool gsp_phys_layout_param; +module_param_named(gsp_phys_layout, gsp_phys_layout_param, bool, 0644); +MODULE_PARM_DESC(gsp_phys_layout, + "Allocate the GSP boot-argument pages and compute/log the WPR/FB layout on the claimed GPU (default 0, no device writes)"); + +bool gsp_phys_layout_enabled(void) +{ + return gsp_phys_layout_param; +} + +/* Boot-argument allocation sizes (mirror of the reference allocator). */ +#define GSP_PHYS_PAGE_SIZE 0x1000 +#define GSP_PHYS_LIBOS_ARGS_SIZE 0x1000 +#define GSP_PHYS_GSP_ARGS_SIZE 0x1000 + +/* + * The boot binary ("bootloader"/SK ucode) is not a section of the staged + * .fwimage; the distribution driver carries it as compiled-in bindata. The + * Turing boot ucode image is 4 KB, but the staged image cannot confirm the + * exact size, so this stays a clearly-named stub used for layout only. + */ +#define GSP_PHYS_BOOTLOADER_SIZE_STUB 0x1000 + +/* Turing-era layout constants (HAL values for TU102..AD10x). */ +#define GSP_PHYS_FRTS_SIZE (0x100 * 0x1000) +#define GSP_PHYS_WPR_END_ALIGN 0x20000 +#define GSP_PHYS_BOOTBIN_ALIGN 0x1000 +#define GSP_PHYS_FW_ALIGN 0x10000 +#define GSP_PHYS_MB (1ULL << 20) +#define GSP_PHYS_PRAMIN_SIZE (1 * GSP_PHYS_MB) +#define GSP_PHYS_NON_WPR_HEAP_SIZE (1 * GSP_PHYS_MB) +#define GSP_PHYS_FW_HEAP_OS_CARVEOUT 0 +#define GSP_PHYS_FW_HEAP_BASE_RM_SIZE (8 * GSP_PHYS_MB) +#define GSP_PHYS_FW_HEAP_PER_GB_FB (96 * 1024) +#define GSP_PHYS_FW_HEAP_CLIENT_ALLOC ((48 * 1024) * 2048) +#define GSP_PHYS_FW_HEAP_MIN_MB 64 +#define GSP_PHYS_FW_HEAP_MAX_MB 256 +#define GSP_PHYS_PRESCRUBBED_TOP_FB (256 * GSP_PHYS_MB) + +#define GSP_PHYS_WPR_META_MAGIC 0xdc3aae21371a60b3ULL +#define GSP_PHYS_WPR_META_REVISION 1 +#define GSP_PHYS_WPR_META_FLAG_CLOCK_BOOST (1U << 0) + +/* + * GspFwWprMeta, the 256-byte handoff structure the booter consumes from the + * WPR metadata page. Field order and offsets follow the driver ABI (magic at + * 0, revision at 8, layout fields from 88, verified at 248); the two unions + * alias signature/free-list and partition/crash-queue members respectively. + */ +struct gsp_phys_wpr_meta { + __u64 magic; + __u64 revision; + __u64 sysmem_addr_of_radix3_elf; + __u64 size_of_radix3_elf; + __u64 sysmem_addr_of_bootloader; + __u64 size_of_bootloader; + __u64 bootloader_code_offset; + __u64 bootloader_data_offset; + __u64 bootloader_manifest_offset; + union { + struct { + __u64 sysmem_addr_of_signature; + __u64 size_of_signature; + }; + struct { + __u32 gsp_fw_heap_free_list_wpr_offset; + __u32 unused0; + __u64 unused1; + }; + }; + __u64 gsp_fw_rsvd_start; + __u64 non_wpr_heap_offset; + __u64 non_wpr_heap_size; + __u64 gsp_fw_wpr_start; + __u64 gsp_fw_heap_offset; + __u64 gsp_fw_heap_size; + __u64 gsp_fw_offset; + __u64 boot_bin_offset; + __u64 frts_offset; + __u64 frts_size; + __u64 gsp_fw_wpr_end; + __u64 fb_size; + __u64 vga_workspace_offset; + __u64 vga_workspace_size; + __u64 boot_count; + union { + struct { + __u64 partition_rpc_addr; + __u16 partition_rpc_request_offset; + __u16 partition_rpc_reply_offset; + __u32 elf_code_offset; + __u32 elf_data_offset; + __u32 elf_code_size; + __u32 elf_data_size; + __u32 ls_ucode_version; + }; + struct { + __u32 partition_rpc_padding[4]; + __u64 sysmem_addr_of_crash_report_queue; + __u32 size_of_crash_report_queue; + __u32 ls_ucode_version_padding[1]; + }; + }; + __u8 gsp_fw_heap_vf_partition_count; + __u8 flags; + __u8 padding[2]; + __u32 pmu_reserved_size; + __u64 verified; +}; + +static u64 gsp_phys_align_down(u64 value, u64 align) +{ + return value & ~(align - 1); +} + +static u64 gsp_phys_align_up(u64 value, u64 align) +{ + return (value + align - 1) & ~(align - 1); +} + +/* + * GSP FW (WPR) heap size for a bare-metal Turing part. Ported from the + * reference: a base RM reservation, a per-GB-of-FB term, and a client-channel + * allocation term, clamped to the architecture min/max and to the pre-scrubbed + * top of FB (Turing has no scrubber ucode, so the heap must fit there). + */ +static u64 gsp_phys_fw_heap_size(u64 fb_size, u64 anterior, u64 posterior) +{ + const u64 fb_size_gb = gsp_phys_align_up(fb_size, 1ULL << 30) >> 30; + u64 max_scrubbed_mb = U32_MAX; + u64 heap; + + if (anterior + posterior < GSP_PHYS_PRESCRUBBED_TOP_FB) + max_scrubbed_mb = (GSP_PHYS_PRESCRUBBED_TOP_FB - + anterior - posterior) >> 20; + + heap = GSP_PHYS_FW_HEAP_OS_CARVEOUT + + GSP_PHYS_FW_HEAP_BASE_RM_SIZE + + gsp_phys_align_up(GSP_PHYS_FW_HEAP_PER_GB_FB * fb_size_gb, + GSP_PHYS_MB) + + gsp_phys_align_up((u64)GSP_PHYS_FW_HEAP_CLIENT_ALLOC, + GSP_PHYS_MB); + + heap = max(heap, (u64)GSP_PHYS_FW_HEAP_MIN_MB * GSP_PHYS_MB); + heap = min(heap, min((u64)GSP_PHYS_FW_HEAP_MAX_MB, + max_scrubbed_mb) * GSP_PHYS_MB); + return heap; +} + +static bool gsp_phys_wpr_layout_valid(const struct gsp_phys_wpr_meta *m) +{ + return m->frts_size <= m->gsp_fw_wpr_end && + m->gsp_fw_offset < m->boot_bin_offset && + m->boot_bin_offset < m->frts_offset && + m->frts_offset < m->gsp_fw_wpr_end && + m->gsp_fw_wpr_end <= m->vga_workspace_offset && + m->gsp_fw_wpr_start < m->gsp_fw_heap_offset && + m->non_wpr_heap_offset < m->gsp_fw_wpr_start && + m->gsp_fw_rsvd_start == m->non_wpr_heap_offset && + m->gsp_fw_offset > 0 && + m->non_wpr_heap_offset > 0; +} + +static void gsp_phys_wpr_meta_dump(const struct gsp_phys_wpr_meta *m) +{ + pr_info("gsp-phys-boot: GspFwWprMeta sizeof=%zu (must be 256) magic=0x%llx revision=%llu flags=0x%x\n", + sizeof(*m), (u64)m->magic, (u64)m->revision, m->flags); + pr_info("gsp-phys-boot: fbSize=0x%llx vgaWorkspace=0x%llx - 0x%llx (0x%llx)\n", + m->fb_size, m->vga_workspace_offset, + m->vga_workspace_offset + m->vga_workspace_size - 1, + m->vga_workspace_size); + pr_info("gsp-phys-boot: gspFwRsvdStart=0x%llx\n", m->gsp_fw_rsvd_start); + pr_info("gsp-phys-boot: nonWprHeap=0x%llx - 0x%llx (0x%llx)\n", + m->non_wpr_heap_offset, + m->non_wpr_heap_offset + m->non_wpr_heap_size - 1, + m->non_wpr_heap_size); + pr_info("gsp-phys-boot: gspFwWprStart=0x%llx\n", m->gsp_fw_wpr_start); + pr_info("gsp-phys-boot: gspFwHeap=0x%llx - 0x%llx (0x%llx)\n", + m->gsp_fw_heap_offset, + m->gsp_fw_heap_offset + m->gsp_fw_heap_size - 1, + m->gsp_fw_heap_size); + pr_info("gsp-phys-boot: gspFwOffset=0x%llx - 0x%llx (0x%llx)\n", + m->gsp_fw_offset, m->gsp_fw_offset + m->size_of_radix3_elf - 1, + m->size_of_radix3_elf); + pr_info("gsp-phys-boot: bootBinOffset=0x%llx - 0x%llx (0x%llx)\n", + m->boot_bin_offset, + m->boot_bin_offset + m->size_of_bootloader - 1, + m->size_of_bootloader); + pr_info("gsp-phys-boot: frtsOffset=0x%llx - 0x%llx (0x%llx)\n", + m->frts_offset, m->frts_offset + m->frts_size - 1, m->frts_size); + pr_info("gsp-phys-boot: gspFwWprEnd=0x%llx bootCount=%llu verified=%llu\n", + m->gsp_fw_wpr_end, (u64)m->boot_count, (u64)m->verified); + pr_info("gsp-phys-boot: stubs: sysmemAddrOfRadix3Elf/Bootloader/Signature=0 crashReportQueue=0 (image not staged in 3b), bootloader offsets=0\n"); +} + +/* + * Stage 3b entry: allocate the boot-argument pages on the claimed device and + * compute/record the WPR layout in the metadata page. No device writes. + */ +int gsp_phys_boot_layout_init(struct gsp_phys_boot *boot, struct pci_dev *pdev, + u64 fw_image_size, resource_size_t usable_fb_size) +{ + struct gsp_phys_wpr_meta *meta; + u64 vbios_reserved_offset; + u64 non_wpr_heap_size, wpr_meta_size; + u64 pre_wpr_heap, post_wpr_heap, wpr_heap_size; + int ret; + + if (!gsp_phys_layout_enabled() || boot->initialized) + return 0; + if (!pdev || !fw_image_size) + return -EINVAL; + + BUILD_BUG_ON(sizeof(struct gsp_phys_wpr_meta) != 256); + + pr_info("gsp-phys-boot: stage 3b layout+allocation on %s (no device writes)\n", + pci_name(pdev)); + pr_info("gsp-phys-boot: usable FB = 0x%llx (approximation: BAR1 aperture length, NOT the physical FB size)\n", + (u64)usable_fb_size); + pr_info("gsp-phys-boot: staged GSP-RM image (.fwimage) size = 0x%llx\n", + fw_image_size); + pr_info("gsp-phys-boot: stub: boot binary size assumed 0x%x (boot ucode is compiled-in bindata, not a .fwimage section)\n", + GSP_PHYS_BOOTLOADER_SIZE_STUB); + pr_info("gsp-phys-boot: wprEndMargin=0 (reference normal first-boot path; no override/retry margin)\n"); + + boot->wpr_meta_size = GSP_PHYS_PAGE_SIZE; + boot->wpr_meta_va = dma_alloc_coherent(&pdev->dev, boot->wpr_meta_size, + &boot->wpr_meta_dma, GFP_KERNEL); + if (!boot->wpr_meta_va) { + pr_err("gsp-phys-boot: WPR meta page allocation failed\n"); + ret = -ENOMEM; + goto err; + } + boot->libos_args_size = GSP_PHYS_LIBOS_ARGS_SIZE; + boot->libos_args_va = dma_alloc_coherent(&pdev->dev, boot->libos_args_size, + &boot->libos_args_dma, GFP_KERNEL); + if (!boot->libos_args_va) { + pr_err("gsp-phys-boot: libos init arguments allocation failed\n"); + ret = -ENOMEM; + goto err; + } + boot->gsp_args_size = GSP_PHYS_GSP_ARGS_SIZE; + boot->gsp_args_va = dma_alloc_coherent(&pdev->dev, boot->gsp_args_size, + &boot->gsp_args_dma, GFP_KERNEL); + if (!boot->gsp_args_va) { + pr_err("gsp-phys-boot: GSP/bootloader arguments allocation failed\n"); + ret = -ENOMEM; + goto err; + } + + pr_info("gsp-phys-boot: WPR meta page 0x%zx bytes dma=0x%llx va=%p (coherent/uncached, zeroed)\n", + boot->wpr_meta_size, (u64)boot->wpr_meta_dma, boot->wpr_meta_va); + pr_info("gsp-phys-boot: libos args 0x%zx bytes dma=0x%llx va=%p (coherent, zeroed; filled in a later stage)\n", + boot->libos_args_size, (u64)boot->libos_args_dma, + boot->libos_args_va); + pr_info("gsp-phys-boot: gsp args 0x%zx bytes dma=0x%llx va=%p (coherent, zeroed; filled in a later stage)\n", + boot->gsp_args_size, (u64)boot->gsp_args_dma, boot->gsp_args_va); + + meta = boot->wpr_meta_va; + + /* + * Layout from the top of FB downward. Turing has no VBIOS MMU-lock + * region (the lock read is invalid on this generation), so the VGA + * workspace bottom is the reserved-area boundary. + */ + meta->fb_size = usable_fb_size; + meta->vga_workspace_offset = usable_fb_size - GSP_PHYS_PRAMIN_SIZE; + meta->vga_workspace_size = usable_fb_size - meta->vga_workspace_offset; + vbios_reserved_offset = meta->vga_workspace_offset; + + meta->size_of_radix3_elf = fw_image_size; + meta->gsp_fw_wpr_end = gsp_phys_align_down(vbios_reserved_offset, + GSP_PHYS_WPR_END_ALIGN); + meta->frts_size = GSP_PHYS_FRTS_SIZE; + meta->frts_offset = meta->gsp_fw_wpr_end - meta->frts_size; + meta->size_of_bootloader = GSP_PHYS_BOOTLOADER_SIZE_STUB; + meta->boot_bin_offset = gsp_phys_align_down(meta->frts_offset - + meta->size_of_bootloader, + GSP_PHYS_BOOTBIN_ALIGN); + meta->gsp_fw_offset = gsp_phys_align_down(meta->boot_bin_offset - + meta->size_of_radix3_elf, + GSP_PHYS_FW_ALIGN); + + non_wpr_heap_size = gsp_phys_align_up((u64)GSP_PHYS_NON_WPR_HEAP_SIZE, + GSP_PHYS_MB); + wpr_meta_size = gsp_phys_align_up((u64)sizeof(*meta), GSP_PHYS_MB); + pre_wpr_heap = wpr_meta_size + non_wpr_heap_size; + post_wpr_heap = gsp_phys_align_up(usable_fb_size - meta->gsp_fw_offset, + GSP_PHYS_MB); + wpr_heap_size = gsp_phys_fw_heap_size(usable_fb_size, pre_wpr_heap, + post_wpr_heap); + + meta->gsp_fw_heap_offset = gsp_phys_align_down(meta->gsp_fw_offset - + wpr_heap_size, GSP_PHYS_MB); + meta->gsp_fw_heap_size = gsp_phys_align_down(meta->gsp_fw_offset - + meta->gsp_fw_heap_offset, + GSP_PHYS_MB); + meta->gsp_fw_heap_vf_partition_count = 0; + meta->gsp_fw_wpr_start = meta->gsp_fw_heap_offset - wpr_meta_size; + meta->non_wpr_heap_size = non_wpr_heap_size; + meta->non_wpr_heap_offset = meta->gsp_fw_wpr_start - non_wpr_heap_size; + meta->gsp_fw_rsvd_start = meta->non_wpr_heap_offset; + + /* Sysmem image addresses are not staged yet (stage 3d fills them). */ + meta->sysmem_addr_of_radix3_elf = 0; + meta->sysmem_addr_of_bootloader = 0; + meta->bootloader_code_offset = 0; + meta->bootloader_data_offset = 0; + meta->bootloader_manifest_offset = 0; + meta->sysmem_addr_of_signature = 0; + meta->size_of_signature = 0; + meta->sysmem_addr_of_crash_report_queue = 0; + meta->size_of_crash_report_queue = 0; + + meta->boot_count = 0; + meta->verified = 0; + meta->revision = GSP_PHYS_WPR_META_REVISION; + meta->magic = GSP_PHYS_WPR_META_MAGIC; + meta->flags = GSP_PHYS_WPR_META_FLAG_CLOCK_BOOST; + + pr_info("gsp-phys-boot: FW heap size = 0x%llx (pre=0x%llx post=0x%llx, min %uMB max %uMB, pre-scrubbed top 0x%llx)\n", + wpr_heap_size, pre_wpr_heap, post_wpr_heap, + GSP_PHYS_FW_HEAP_MIN_MB, GSP_PHYS_FW_HEAP_MAX_MB, + (u64)GSP_PHYS_PRESCRUBBED_TOP_FB); + + if (!gsp_phys_wpr_layout_valid(meta)) { + pr_err("gsp-phys-boot: computed layout is inconsistent (frame too small for image/heap?)\n"); + ret = -EINVAL; + goto err; + } + + gsp_phys_wpr_meta_dump(meta); + + boot->fb_size = meta->fb_size; + boot->vga_workspace_offset = meta->vga_workspace_offset; + boot->vga_workspace_size = meta->vga_workspace_size; + boot->gsp_fw_wpr_end = meta->gsp_fw_wpr_end; + boot->frts_offset = meta->frts_offset; + boot->frts_size = meta->frts_size; + boot->boot_bin_offset = meta->boot_bin_offset; + boot->size_of_bootloader = meta->size_of_bootloader; + boot->gsp_fw_offset = meta->gsp_fw_offset; + boot->size_of_radix3_elf = meta->size_of_radix3_elf; + boot->gsp_fw_heap_offset = meta->gsp_fw_heap_offset; + boot->gsp_fw_heap_size = meta->gsp_fw_heap_size; + boot->gsp_fw_wpr_start = meta->gsp_fw_wpr_start; + boot->non_wpr_heap_offset = meta->non_wpr_heap_offset; + boot->non_wpr_heap_size = meta->non_wpr_heap_size; + boot->gsp_fw_rsvd_start = meta->gsp_fw_rsvd_start; + + boot->initialized = true; + pr_info("gsp-phys-boot: stage 3b complete: boot args allocated, WPR meta filled (no device writes)\n"); + return 0; + +err: + gsp_phys_boot_layout_fini(boot, pdev); + return ret; +} + +void gsp_phys_boot_layout_fini(struct gsp_phys_boot *boot, struct pci_dev *pdev) +{ + if (!boot->initialized && !boot->wpr_meta_va && !boot->libos_args_va && + !boot->gsp_args_va) + return; + if (!pdev) + return; + + if (boot->wpr_meta_va) + dma_free_coherent(&pdev->dev, boot->wpr_meta_size, + boot->wpr_meta_va, boot->wpr_meta_dma); + if (boot->libos_args_va) + dma_free_coherent(&pdev->dev, boot->libos_args_size, + boot->libos_args_va, boot->libos_args_dma); + if (boot->gsp_args_va) + dma_free_coherent(&pdev->dev, boot->gsp_args_size, + boot->gsp_args_va, boot->gsp_args_dma); + + boot->wpr_meta_va = NULL; + boot->libos_args_va = NULL; + boot->gsp_args_va = NULL; + boot->initialized = false; + pr_info("gsp-phys-boot: boot-argument pages freed\n"); +} diff --git a/kernel/gsp_phys_boot.h b/kernel/gsp_phys_boot.h new file mode 100644 index 0000000..8ab203a --- /dev/null +++ b/kernel/gsp_phys_boot.h @@ -0,0 +1,52 @@ +#ifndef GSP_PHYS_BOOT_H +#define GSP_PHYS_BOOT_H + +#include +#include +#include + +/* + * Real-GSP boot bring-up stage 3b: boot-argument DMA memory and the computed + * WPR/FB layout. Allocated and filled by gsp_phys_boot.c while the module owns + * the physical GPU. Stage 3b writes no device registers; the WPR metadata page + * is filled in host memory only, ready for the later FWSEC/booter stages. + */ +struct gsp_phys_boot { + bool initialized; + + /* Boot-argument pages (DMA-coherent and GPU-addressable) */ + void *wpr_meta_va; + dma_addr_t wpr_meta_dma; + size_t wpr_meta_size; + void *libos_args_va; + dma_addr_t libos_args_dma; + size_t libos_args_size; + void *gsp_args_va; + dma_addr_t gsp_args_dma; + size_t gsp_args_size; + + /* Computed layout, FB byte offsets measured from the FB base */ + u64 fb_size; + u64 vga_workspace_offset; + u64 vga_workspace_size; + u64 gsp_fw_wpr_end; + u64 frts_offset; + u64 frts_size; + u64 boot_bin_offset; + u64 size_of_bootloader; + u64 gsp_fw_offset; + u64 size_of_radix3_elf; + u64 gsp_fw_heap_offset; + u64 gsp_fw_heap_size; + u64 gsp_fw_wpr_start; + u64 non_wpr_heap_offset; + u64 non_wpr_heap_size; + u64 gsp_fw_rsvd_start; +}; + +bool gsp_phys_layout_enabled(void); +int gsp_phys_boot_layout_init(struct gsp_phys_boot *boot, struct pci_dev *pdev, + u64 fw_image_size, resource_size_t usable_fb_size); +void gsp_phys_boot_layout_fini(struct gsp_phys_boot *boot, struct pci_dev *pdev); + +#endif /* GSP_PHYS_BOOT_H */ diff --git a/kernel/gsp_phys_gpu.c b/kernel/gsp_phys_gpu.c index df46c5a..0724cf3 100644 --- a/kernel/gsp_phys_gpu.c +++ b/kernel/gsp_phys_gpu.c @@ -18,8 +18,10 @@ #include #include #include +#include #include "gsp_phys_gpu.h" +#include "gsp_phys_boot.h" #define GSP_PHYS_VENDOR 0x10de #define GSP_PHYS_DEVICE 0x1ed3 @@ -65,11 +67,13 @@ struct gsp_phys_gpu { resource_size_t bar3_len; const struct firmware *fw; u32 fw_crc32; + u64 fw_image_size; bool fw_loaded; bool enabled; bool regions; bool drv_registered; bool claimed; + struct gsp_phys_boot boot; }; static struct gsp_phys_gpu phys; @@ -95,6 +99,7 @@ static void gsp_phys_fw_unload(void) phys.fw = NULL; phys.fw_loaded = false; phys.fw_crc32 = 0; + phys.fw_image_size = 0; } static const char *gsp_phys_fw_section_name(const struct firmware *fw, @@ -165,16 +170,24 @@ static int gsp_phys_fw_load(void) const Elf64_Shdr *sh = (const Elf64_Shdr *) (phys.fw->data + eh->e_shoff + (u64)i * eh->e_shentsize); + const char *name; if (sh->sh_offset > phys.fw->size || sh->sh_size > phys.fw->size - sh->sh_offset) continue; + name = gsp_phys_fw_section_name(phys.fw, sh); + if (!strcmp(name, ".fwimage")) + phys.fw_image_size = sh->sh_size; pr_info("gsp-phys-fw: [%02u] %-24s type=%u addr=0x%llx " - "off=0x%llx size=0x%llx\n", i, - gsp_phys_fw_section_name(phys.fw, sh), + "off=0x%llx size=0x%llx\n", i, name, sh->sh_type, (u64)sh->sh_addr, (u64)sh->sh_offset, (u64)sh->sh_size); } + + if (phys.fw_image_size) + pr_info("gsp-phys-fw: GSP-RM image section .fwimage " + "size=0x%llx (boot-layout input)\n", + phys.fw_image_size); } return 0; @@ -374,10 +387,17 @@ int gsp_phys_gpu_claim(void) pci_dev_put(pdev); pr_info("gsp-phys: physical GPU claimed (backend rung 1)\n"); - if (gsp_phys_fw_load()) + if (gsp_phys_fw_load()) { pr_warn("gsp-phys: firmware load failed; backend stays at rung 1\n"); - else + } else { pr_info("gsp-phys: real GSP firmware staged (backend rung 2)\n"); + + if (gsp_phys_layout_enabled() && + gsp_phys_boot_layout_init(&phys.boot, phys.pdev, + phys.fw_image_size, phys.bar1_len)) + pr_warn("gsp-phys: boot layout/allocation failed; " + "backend stays at rung 2\n"); + } return 0; } EXPORT_SYMBOL_GPL(gsp_phys_gpu_claim); @@ -389,6 +409,9 @@ void gsp_phys_gpu_release(void) if (!phys.drv_registered && !phys.claimed) return; + if (phys.pdev) + gsp_phys_boot_layout_fini(&phys.boot, phys.pdev); + gsp_phys_fw_unload(); pdev = pci_get_device(GSP_PHYS_VENDOR, GSP_PHYS_DEVICE, NULL); -- cgit v1.2.3