RE: [PATCH v2] PCI: hv: Allocate MMIO from above 4GB for the config window
From: Michael Kelley
Date: Thu Apr 23 2026 - 13:40:24 EST
From: Dexuan Cui <DECUI@xxxxxxxxxxxxx> Sent: Wednesday, April 15, 2026 8:31 AM
>
> > From: Michael Kelley <mhklinux@xxxxxxxxxxx> Sent: Wednesday, April 8, 2026 6:54 AM
[snip]
>
> Another example is: for a Gen2 VM with the below commands:
> Set-VM -LowMemoryMappedIoSpace 1GB \
> -VMName decui-u2204-gen2-fb
> // i.e. the default setting on Azure. Let's ignore CVMs here.
FWIW, I'm seeing that in Gen2 VMs in Azure, the low_mmio_size
is 3 GiB. I'm looking at a D16ds_v5, and a D16lds_v6. The v5 VM
is newly created, while the v6 has been around for a few months.
In a CVM, the low_mmio_size should be 1 GiB. This overall example
is still correct -- it's just the comment that I have doubts about. Or
maybe you are looking at a different VM size that has a different
default?
Some years back, I had gotten into a discussion with Azure about
this size because the swiotlb memory wants to be allocated below
the 4 GiB line, and reserving 3 GiB for low mmio limited the size
of the swiotlb. CVMs were changed to have only 1 GiB for low
mmio because they need a larger swiotlb.
> Set-VMVideo -VMName decui-u2204-gen2-fb \
> -HorizontalResolution 4834 \
> -VerticalResolution 3622 \
> -ResolutionType Single
> we have:
> max_fb_size = round_up_to_2MB(4834*3622*4) = 68 MB
> excess_fb_size = 4MB
> low_mmio_base = 4GB - 128MB - 4MB * 2
> = 4GB - 136 MB = 0xf7800000
> but 4GB - target_low_mmio_size = 4GB - 1GB, which is
> smaller than low_mmio_base, so low_mmio_base and
> fb_mmio_base are both set to 4GB - 1GB = 0xc0000000,
> and low_mmio_size = 1GB.
> In this case, we'd like to reserve
> min(low_mmio_size/2, 128MB) = 128MB for the framebuffer
> mmio, since the max possible framebuffer so far is 128MB.
>
> ************************************
>
> On an ARM64 lab host, I also tested Gen2 VMs (there is no Gen1 VM
> for ARM VMs):
>
> By default:
> low_mmio_base = 4GB - 512MB, i.e. 0xe0000000
> low_mmio_size = 512MB
> fb_mmio_base = low_mmio_base
> The default framebuffer size is 3MB
> (i.e. screen.lfb_size = 3MB) but hyperv_drm:
> mmio_megabytes = 8 MB, which supports up to 1920 * 1080.
>
> With the below commands:
> Set-VM -LowMemoryMappedIoSpace 512MB \
> -VMName decui-u2204-gen2-fb
> // the command only accepts a value between 512MB and 3.5GB.
> Set-VMVideo -VMName decui-u2204-gen2-fb \
> -HorizontalResolution 4834 \
> -VerticalResolution 3622 \
> -ResolutionType Single
> I thought we would have:
> max_fb_size = round_up_to_2MB(4834*3622*4) = 68 MB
> excess_fb_size = 4MB
> low_mmio_base = 4GB - 512MB - 4MB * 2
> = 4GB - 520MB
> fb_mmio_base = low_mmio_base
> low_mmio_size = 4GB - low_mmio_base = 520MB
>
> Since 4GB - target_low_mmio_size = 4GB - 512MB, which is
> smaller than low_mmio_base, so low_mmio_base and
> fb_mmio_base would be both set to 4GB - 520MB, and
> low_mmio_size would be 520MB.
>
> However, the actual result is:
> max_fb_size is indeed 68MB.
> but fb_mmio_base = low_mmio_base = 4GB - 512MB, and
> low_mmio_size = 512MB, i.e. the 'excess_fb_size' is not
> considered on ARM64!
>
> In this case, we'd like to reserve
> min(low_mmio_size/2, 128MB) = 128MB for the framebuffer
> mmio, since the max possible framebuffer so far is 128MB.
>
> With the below command:
> Set-VM -LowMemoryMappedIoSpace 3GB \
> -VMName decui-u2204-gen2-fb
> // i.e. the default setting on Azure. Unlike x86-64, an ARM64
> // VM on Azure has 3GB of mmio below 4GB.
See my previous comment on the same topic. I think arm64
and x86/x64 are the same.
> Set-VMVideo -VMName decui-u2204-gen2-fb \
> -HorizontalResolution 4834 \
> -VerticalResolution 3622 \
> -ResolutionType Single
> we have:
> max_fb_size = round_up_to_2MB(4834*3622*4) = 68 MB
> low_mmio_base = 4GB - 3GB = 1GB = 0x40000000
> low_mmio_size = 3GB
> fb_mmio_base = low_mmio_base = 1GB
>
> In this case, we'd like to reserve
> min(low_mmio_size/2, 128MB) = 128MB for the framebuffer
> mmio, since the max possible framebuffer so far is 128MB.
>
> ************************************
>
> To recap, I think the bottom line is:
>
> a) For Gen2 VMs, we can safely reserve a mmio range starting at
> sysfb_primary_display.screen.lfb_base with a size of
> min(low_mmio_size/2, 128MB).
>
> If sysfb_primary_display.screen.lfb_base is 0, i.e. in the case
> of kdump kernel, we use low_mmio_base instead.
> This should fix the mmio conflict in the kdump kernel.
>
> b) For Gen1 VMs, let's still only reserve a mmio range starting at
> 4GB - 128MB with a size of 64MB, because when we are in
> vmbus_reserve_fb(), we still don't know the exact size of the
> max_fb_size, and we don't want to reserve too much as we would
> want to reserve some low mmio space for PCI devices with 32-bit
> BARs (if any).
>
> If the user runs Set-VMVideo and needs a framebuffer size
> bigger than 64MB (IMO this is not a typical scenario in
> practice), we have to use high mmio for hyperv_drm in the first
> kernel, and the kdump kernel still suffers from the mmio
> conflict between hyperv_drm and hv_pci. We encourage Gen1 VM
> users to upgrade to Gen2 VMs to resolve the issue. Anyway, the
> mmio conflict is inevitable for Gen1 VMs, if the max required
> framebuffer size is bigger than 108MB (Note:
> 128MB - VTPM_BASE_ADDRESS = 109.25, and the required framebuffer
> size is always rounded up to 2MB).
Question about Gen 1 VMs: If the Linux frame buffer driver moves
the frame buffer somewhere other than the default location, and
then the VM does a kexec/kdump, what does the legacy PCI graphic
device BAR report as the frame buffer location? Does it *always*
report 4G-128MB, or does it report the new location? I can run
an experiment to find out, but maybe you've already done so and
not reported that detail here.
Michael