[PATCH v6 3/4] drm/amdgpu: enable pdb0 for hibernation on SRIOV
Zhang, GuoQing (Sam)
GuoQing.Zhang at amd.com
Tue May 20 05:10:46 UTC 2025
On 2025/5/19 21:57, Christian König wrote:
> On 5/19/25 10:20, Samuel Zhang wrote:
>> When switching to new GPU index after hibernation and then resume,
>> VRAM offset of each VRAM BO will be changed, and the cached gpu
>> addresses needed to updated.
>>
>> This is to enable pdb0 and switch to use pdb0-based virtual gpu
>> address by default in amdgpu_bo_create_reserved(). since the virtual
>> addresses do not change, this can avoid the need to update all
>> cached gpu addresses all over the codebase.
>>
>> Signed-off-by: Emily Deng <Emily.Deng at amd.com>
>> Signed-off-by: Samuel Zhang <guoqing.zhang at amd.com>
>> ---
>> drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 32 ++++++++++++++++++------
>> drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h | 1 +
>> drivers/gpu/drm/amd/amdgpu/gfxhub_v1_2.c | 2 +-
>> drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 10 +++++---
>> drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c | 6 +++--
>> 5 files changed, 37 insertions(+), 14 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
>> index d1fa5e8e3937..265d6c777af5 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
>> @@ -38,6 +38,8 @@
>> #include <drm/drm_drv.h>
>> #include <drm/ttm/ttm_tt.h>
>>
>> +static const u64 four_gb = 0x100000000ULL;
>> +
>> /**
>> * amdgpu_gmc_pdb0_alloc - allocate vram for pdb0
>> *
>> @@ -249,15 +251,24 @@ void amdgpu_gmc_sysvm_location(struct amdgpu_device *adev, struct amdgpu_gmc *mc
>> {
>> u64 hive_vram_start = 0;
>> u64 hive_vram_end = mc->xgmi.node_segment_size * mc->xgmi.num_physical_nodes - 1;
>> - mc->vram_start = mc->xgmi.node_segment_size * mc->xgmi.physical_node_id;
>> - mc->vram_end = mc->vram_start + mc->xgmi.node_segment_size - 1;
>> - mc->gart_start = hive_vram_end + 1;
>> +
>> + if (amdgpu_virt_xgmi_migrate_enabled(adev)) {
>> + /* set mc->vram_start to 0 to switch the returned GPU address of
>> + * amdgpu_bo_create_reserved() from FB aperture to GART aperture.
>> + */
>> + amdgpu_gmc_vram_location(adev, mc, 0);
> This function does a lot more than just setting mc->vram_start and mc->vram_end.
>
> You should probably just update the two setting and not call amdgpu_gmc_vram_location() at all.
I tried only setting mc->vram_start and mc->vram_end. But KMD load will
fail with following error logs.
[ 329.314346] amdgpu 0000:09:00.0: amdgpu: VRAM: 196288M
0x0000000000000000 - 0x0000002FEBFFFFFF (196288M used)
[ 329.314348] amdgpu 0000:09:00.0: amdgpu: GART: 512M
0x0000018000000000 - 0x000001801FFFFFFF
[ 329.314385] [drm] Detected VRAM RAM=196288M, BAR=262144M
[ 329.314386] [drm] RAM width 8192bits HBM
[ 329.314546] amdgpu 0000:09:00.0: amdgpu: (-22) failed to allocate
kernel bo
[ 329.315013] [drm:amdgpu_device_init [amdgpu]] *ERROR* sw_init of IP
block <gmc_v9_0> failed -22
[ 329.315846] amdgpu 0000:09:00.0: amdgpu: amdgpu_device_ip_init failed
It seems like setting mc->visible_vram_size and mc->visible_vram_size
fields are also needed. In this case call amdgpu_gmc_vram_location() is
better than inline the logic, I think.
>
>> + } else {
>> + mc->vram_start = mc->xgmi.node_segment_size * mc->xgmi.physical_node_id;
>> + mc->vram_end = mc->vram_start + mc->xgmi.node_segment_size - 1;
>> + dev_info(adev->dev, "VRAM: %lluM 0x%016llX - 0x%016llX (%lluM used)\n",
>> + mc->mc_vram_size >> 20, mc->vram_start,
>> + mc->vram_end, mc->real_vram_size >> 20);
>> + }
>> + /* node_segment_size may not 4GB aligned on SRIOV, align up is needed. */
>> + mc->gart_start = ALIGN(hive_vram_end + 1, four_gb);
>> mc->gart_end = mc->gart_start + mc->gart_size - 1;
>> mc->fb_start = hive_vram_start;
>> mc->fb_end = hive_vram_end;
>> - dev_info(adev->dev, "VRAM: %lluM 0x%016llX - 0x%016llX (%lluM used)\n",
>> - mc->mc_vram_size >> 20, mc->vram_start,
>> - mc->vram_end, mc->real_vram_size >> 20);
>> dev_info(adev->dev, "GART: %lluM 0x%016llX - 0x%016llX\n",
>> mc->gart_size >> 20, mc->gart_start, mc->gart_end);
>> }
>> @@ -276,7 +287,6 @@ void amdgpu_gmc_sysvm_location(struct amdgpu_device *adev, struct amdgpu_gmc *mc
>> void amdgpu_gmc_gart_location(struct amdgpu_device *adev, struct amdgpu_gmc *mc,
>> enum amdgpu_gart_placement gart_placement)
>> {
>> - const uint64_t four_gb = 0x100000000ULL;
>> u64 size_af, size_bf;
>> /*To avoid the hole, limit the max mc address to AMDGPU_GMC_HOLE_START*/
>> u64 max_mc_address = min(adev->gmc.mc_mask, AMDGPU_GMC_HOLE_START - 1);
>> @@ -1068,6 +1078,14 @@ void amdgpu_gmc_init_pdb0(struct amdgpu_device *adev)
>> flags |= AMDGPU_PTE_FRAG((adev->gmc.vmid0_page_table_block_size + 9*1));
>> flags |= AMDGPU_PDE_PTE_FLAG(adev);
>>
>> + if (amdgpu_virt_xgmi_migrate_enabled(adev)) {
>> + /* always start from current device so that the GART address can keep
>> + * consistent when hibernate-resume with different GPUs.
>> + */
>> + vram_addr = adev->vm_manager.vram_base_offset;
>> + vram_end = vram_addr + vram_size;
>> + }
>> +
>> /* The first n PDE0 entries are used as PTE,
>> * pointing to vram
>> */
>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h
>> index bd7fc123b8f9..46fac7ca7dfa 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h
>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h
>> @@ -307,6 +307,7 @@ struct amdgpu_gmc {
>> struct amdgpu_bo *pdb0_bo;
>> /* CPU kmapped address of pdb0*/
>> void *ptr_pdb0;
>> + bool pdb0_enabled;
> This isn't needed, just always check (adev->gmc.xgmi.connected_to_cpu || amdgpu_virt_xgmi_migrate_enabled(adev)), make a function for that if necessary.
Ok, I will update it in the next patch version.
>
>>
>> /* MALL size */
>> u64 mall_size;
>> diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_2.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_2.c
>> index cb25f7f0dfc1..e6165f6d0763 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_2.c
>> +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_2.c
>> @@ -180,7 +180,7 @@ gfxhub_v1_2_xcc_init_system_aperture_regs(struct amdgpu_device *adev,
>> /* In the case squeezing vram into GART aperture, we don't use
>> * FB aperture and AGP aperture. Disable them.
>> */
>> - if (adev->gmc.pdb0_bo) {
>> + if (adev->gmc.pdb0_bo && !amdgpu_virt_xgmi_migrate_enabled(adev)) {
>> WREG32_SOC15(GC, GET_INST(GC, i), regMC_VM_FB_LOCATION_TOP, 0);
>> WREG32_SOC15(GC, GET_INST(GC, i), regMC_VM_FB_LOCATION_BASE, 0x00FFFFFF);
>> WREG32_SOC15(GC, GET_INST(GC, i), regMC_VM_AGP_TOP, 0);
>> diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
>> index 59385da80185..04fb99c64b37 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
>> +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
>> @@ -1682,6 +1682,8 @@ static int gmc_v9_0_early_init(struct amdgpu_ip_block *ip_block)
>> adev->gmc.private_aperture_start + (4ULL << 30) - 1;
>> adev->gmc.noretry_flags = AMDGPU_VM_NORETRY_FLAGS_TF;
>>
>> + adev->gmc.pdb0_enabled = adev->gmc.xgmi.connected_to_cpu ||
>> + amdgpu_virt_xgmi_migrate_enabled(adev);
>> return 0;
>> }
>>
>> @@ -1726,7 +1728,7 @@ static void gmc_v9_0_vram_gtt_location(struct amdgpu_device *adev,
>>
>> /* add the xgmi offset of the physical node */
>> base += adev->gmc.xgmi.physical_node_id * adev->gmc.xgmi.node_segment_size;
>> - if (adev->gmc.xgmi.connected_to_cpu) {
>> + if (adev->gmc.pdb0_enabled) {
>> amdgpu_gmc_sysvm_location(adev, mc);
>> } else {
>> amdgpu_gmc_vram_location(adev, mc, base);
>> @@ -1841,7 +1843,7 @@ static int gmc_v9_0_gart_init(struct amdgpu_device *adev)
>> return 0;
>> }
>>
>> - if (adev->gmc.xgmi.connected_to_cpu) {
>> + if (adev->gmc.pdb0_enabled) {
>> adev->gmc.vmid0_page_table_depth = 1;
>> adev->gmc.vmid0_page_table_block_size = 12;
>> } else {
>> @@ -1867,7 +1869,7 @@ static int gmc_v9_0_gart_init(struct amdgpu_device *adev)
>> if (r)
>> return r;
>>
>> - if (adev->gmc.xgmi.connected_to_cpu)
>> + if (adev->gmc.pdb0_enabled)
>> r = amdgpu_gmc_pdb0_alloc(adev);
>> }
>>
>> @@ -2372,7 +2374,7 @@ static int gmc_v9_0_gart_enable(struct amdgpu_device *adev)
>> {
>> int r;
>>
>> - if (adev->gmc.xgmi.connected_to_cpu)
>> + if (adev->gmc.pdb0_enabled)
>> amdgpu_gmc_init_pdb0(adev);
>>
>> if (adev->gart.bo == NULL) {
>> diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c
>> index 84cde1239ee4..18e80aa78aff 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c
>> +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c
>> @@ -45,8 +45,10 @@ static u64 mmhub_v1_8_get_fb_location(struct amdgpu_device *adev)
>> top &= MC_VM_FB_LOCATION_TOP__FB_TOP_MASK;
>> top <<= 24;
>>
>> - adev->gmc.fb_start = base;
>> - adev->gmc.fb_end = top;
>> + if (!amdgpu_virt_xgmi_migrate_enabled(adev)) {
>> + adev->gmc.fb_start = base;
>> + adev->gmc.fb_end = top;
>> + }
> We should probably avoid calling this in the first place.
>
> The function gmc_v9_0_vram_gtt_location() should probably be adjusted.
mmhub_v1_8_get_fb_location() is called by the new
amdgpu_bo_fb_aper_addr() as well, not just gmc_v9_0_vram_gtt_location().
mmhub_v1_8_get_fb_location() is supposed to be a query api according to
its name. having such side effect is very surprising.
Another approach is set the right fb_start and fb_end in the new
amdgpu_virt_resume(), like updating vram_base_offset.
Which approach do you prefer? Or any better suggestions? Thank you.
Regards
Sam
>
> Regards,
> Christian.
>
>>
>> return base;
>> }
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/amd-gfx/attachments/20250520/a5a2a1cc/attachment-0001.htm>
More information about the amd-gfx
mailing list