From 489ee1c344db5fa43d643da05af77e9061195e56 Mon Sep 17 00:00:00 2001 From: Zhigang Luo Date: Mon, 31 Aug 2026 15:39:03 -0400 Subject: [PATCH] drm/amdgpu: take the A+A VF GMC aperture from SRAT The A+A VF FB BAR is not usable, so resolve its aperture from SRAT in GMC early_init. Skip later aperture assignment for SPM-backed devices, and restrict the existing mmhub-based override to native A+A and APU. The GPU reaches its HBM at a system physical address, so vram_base_offset becomes aper_base as well, which makes PDB0 map GPU address 0 onto that address. The XGMI node segment size comes from the same place: once early_init has resolved the aperture, use its size rather than the value derived from the register, which does not describe the VF partition. v2: - Use (sriov_vf || passthrough) and amdgpu_virt_vram_is_spm() instead of connected_to_cpu for the SRAT aperture and node segment size. v3: - Resolve the SRAT aperture in GMC early_init and skip later aperture assignment in mc_init for SPM-backed devices. - Rely on amdgpu_virt_vram_is_spm() without redundant VF/passthrough checks. Signed-off-by: Zhigang Luo Signed-off-by: Fangsheng Huang Signed-off-by: YuBiao Wang Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c | 57 ++++++++++++++++++----- drivers/gpu/drm/amd/amdgpu/mmhub_v4_2_0.c | 5 +- 2 files changed, 49 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c index 8e3fe16668c9..ab707b1c7867 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c @@ -639,6 +639,7 @@ static void gmc_v12_0_set_gfxhub_funcs(struct amdgpu_device *adev) static int gmc_v12_0_early_init(struct amdgpu_ip_block *ip_block) { struct amdgpu_device *adev = ip_block->adev; + int r; if (adev->smuio.funcs && adev->smuio.funcs->is_host_gpu_xgmi_supported) @@ -661,6 +662,18 @@ static int gmc_v12_0_early_init(struct amdgpu_ip_block *ip_block) gmc_v12_0_set_mmhub_funcs(adev); gmc_v12_0_set_umc_funcs(adev); + if (amdgpu_virt_vram_is_spm(adev)) { + u64 aper_base, aper_size; + + r = amdgpu_acpi_find_gpu_memory_in_srat(adev, &aper_base, + &aper_size); + if (r) + return r; + + adev->gmc.aper_base = aper_base; + adev->gmc.aper_size = aper_size; + } + adev->gmc.shared_aperture_start = 0x2000000000000000ULL; adev->gmc.shared_aperture_end = adev->gmc.shared_aperture_start + (4ULL << 30) - 1; @@ -707,10 +720,19 @@ static void gmc_v12_0_vram_gtt_location(struct amdgpu_device *adev, amdgpu_gmc_agp_location(adev, mc); } /* base offset of vram pages */ - if (amdgpu_sriov_vf(adev)) + if (amdgpu_virt_vram_is_spm(adev)) { + /* + * For SPM-backed VRAM, PDB0 entries use PTE_SYSTEM, so the + * address is a system physical address. vram_base_offset must + * be aper_base so PDB0 maps GPU address 0 onto the HBM system + * physical address. + */ + adev->vm_manager.vram_base_offset = adev->gmc.aper_base; + } else if (amdgpu_sriov_vf(adev)) { adev->vm_manager.vram_base_offset = 0; - else + } else { adev->vm_manager.vram_base_offset = adev->mmhub.funcs->get_mc_fb_offset(adev); + } adev->vm_manager.vram_base_offset += adev->gmc.xgmi.physical_node_id * adev->gmc.xgmi.node_segment_size; @@ -747,17 +769,28 @@ static int gmc_v12_0_mc_init(struct amdgpu_device *adev) return r; } - adev->gmc.aper_base = pci_resource_start(adev->pdev, 0); - adev->gmc.aper_size = pci_resource_len(adev->pdev, 0); - #ifdef CONFIG_X86_64 - if (((adev->flags & AMD_IS_APU) && !amdgpu_passthrough(adev)) || - (adev->gmc.xgmi.connected_to_cpu)) { - adev->gmc.aper_base = - adev->mmhub.funcs->get_mc_fb_offset(adev) + - adev->gmc.xgmi.physical_node_id * - adev->gmc.xgmi.node_segment_size; - adev->gmc.aper_size = adev->gmc.real_vram_size; + /* + * SPM-backed devices resolve the aperture from SRAT during early_init. + * For native A+A (non-VF) or APU, override aper_base using mmhub + * offset. Otherwise derive the aperture from BAR 0. + */ + if (!amdgpu_virt_vram_is_spm(adev)) { + if (!amdgpu_sriov_vf(adev) && + (((adev->flags & AMD_IS_APU) && + !amdgpu_passthrough(adev)) || + adev->gmc.xgmi.connected_to_cpu)) { + adev->gmc.aper_base = + adev->mmhub.funcs->get_mc_fb_offset(adev) + + adev->gmc.xgmi.physical_node_id * + adev->gmc.xgmi.node_segment_size; + adev->gmc.aper_size = adev->gmc.real_vram_size; + } else { + adev->gmc.aper_base = + pci_resource_start(adev->pdev, 0); + adev->gmc.aper_size = + pci_resource_len(adev->pdev, 0); + } } #endif /* In case the PCI BAR is larger than the actual amount of vram */ diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v4_2_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v4_2_0.c index 4495d52b4b07..4c0a2d671cfc 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v4_2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v4_2_0.c @@ -154,7 +154,10 @@ static int mmhub_v4_2_0_get_xgmi_info(struct amdgpu_device *adev) if (adev->gmc.xgmi.physical_node_id > max_physical_node_id) return -EINVAL; - adev->gmc.xgmi.node_segment_size = seg_size; + if (amdgpu_virt_vram_is_spm(adev) && adev->gmc.aper_size) + adev->gmc.xgmi.node_segment_size = adev->gmc.aper_size; + else + adev->gmc.xgmi.node_segment_size = seg_size; return 0; }