Re: [PATCH v2 7/9] hw/i386: Reserve AMD IOMMU HT GPA range for Hygon

Zhao Liu <[email protected]>
Newsgroups org.nongnu.qemu-devel,org.kernel.vger.kvm
Message-ID <[email protected]>
On Mon, Aug 10, 2026 at 04:29:54PM +0800, Tina Zhang wrote:
> Date: Mon, 10 Aug 2026 16:29:54 +0800
> From: Tina Zhang <[email protected]>
> Subject: [PATCH v2 7/9] hw/i386: Reserve AMD IOMMU HT GPA range for Hygon
> X-Mailer: git-send-email 2.43.7
> 
> pc_memory_init() avoids the AMD IOMMU HyperTransport range below 1 TiB
> only for AMD vCPUs.  Dhyana therefore allows RAM, hotplug address space,
> or 64-bit PCI MMIO to overlap 0xfd00000000-0xffffffffff.
> 
> Linux supports Dhyana platforms in the AMD IOMMU driver.  The driver
> reports this range as reserved unless the IOMMU advertises
> FEATURE_HT_RANGE_IGNORE.  A VFIO device cannot DMA to guest addresses
> that QEMU places in the reserved range: VFIO_DMA_MAP may fail with
> -EINVAL, or the IOMMU may report an INVALID_DEVICE_REQUEST fault.
> 
> Apply the AMD IOMMU HT GPA layout to Hygon vCPUs.  When the possible
> address space reaches the reserved range, move RAM above 4 GiB to 1 TiB;
> also expose the range as reserved in E820 when the vCPU can address it.
> 
> Changing the GPA layout affects migration, so enable the Hygon behavior
> through x-hygon-vendor-abi-fixes.  pc-11.0 and older machine types retain
> their previous Hygon layout.  The existing enforce_amd_1tb_hole setting
> continues to preserve the AMD layout of pc/q35 machine types through 7.0.
> 
> Add functional tests for Dhyana with the current q35 machine type and
> with pc-q35-11.0 compatibility.
> 
> Signed-off-by: Yanjing Zhou <[email protected]>
> Signed-off-by: Tina Zhang <[email protected]>
> ---
>  hw/i386/pc.c                                  | 18 ++++++---
>  .../functional/x86_64/test_mem_addr_space.py  | 37 +++++++++++++++++++
>  2 files changed, 50 insertions(+), 5 deletions(-)
> 
> diff --git a/hw/i386/pc.c b/hw/i386/pc.c
> index 2b4e322b2f..04aef6c267 100644
> --- a/hw/i386/pc.c
> +++ b/hw/i386/pc.c
> @@ -738,6 +738,12 @@ static hwaddr pc_max_used_gpa(PCMachineState *pcms, uint64_t pci_hole64_size)
>  #define AMD_ABOVE_1TB_START  (AMD_HT_END + 1)
>  #define AMD_HT_SIZE          (AMD_ABOVE_1TB_START - AMD_HT_START)
>  
> +static bool x86_cpu_has_amd_iommu_ht_gpa_hole(const X86CPU *cpu)
> +{
> +    return IS_AMD_CPU(&cpu->env) ||
> +           (IS_HYGON_CPU(&cpu->env) && cpu->hygon_vendor_abi_fixes);
> +}
> +
>  void pc_memory_init(PCMachineState *pcms,
>                      MemoryRegion *system_memory,
>                      MemoryRegion *rom_memory,
> @@ -762,12 +768,14 @@ void pc_memory_init(PCMachineState *pcms,
>      linux_boot = (machine->kernel_filename != NULL);
>  
>      /*
> -     * The HyperTransport range close to the 1T boundary is unique to AMD
> -     * hosts with IOMMUs enabled. Restrict the ram-above-4g relocation
> -     * to above 1T to AMD vCPUs only. @enforce_amd_1tb_hole is only false in
> -     * older machine types (<= 7.0) for compatibility purposes.
> +     * The HyperTransport range close to the 1T boundary is reserved by the
> +     * AMD IOMMU GPA layout.  Apply the ram-above-4g relocation only to vCPUs
> +     * that use that layout. @enforce_amd_1tb_hole preserves older AMD
> +     * machine types (<= 7.0), and x-hygon-vendor-abi-fixes preserves older
> +     * Hygon machine types (<= 11.0).
                               ^^^^^^^

nit: <= 11.1.

>       */

And x-hygon-vendor-abi-fixes is not here, or maybe we can palce all checks
in a single helper...

> -    if (IS_AMD_CPU(&cpu->env) && pcmc->enforce_amd_1tb_hole) {
> +    if (x86_cpu_has_amd_iommu_ht_gpa_hole(cpu) &&
> +        pcmc->enforce_amd_1tb_hole) {

...for example:

/*
 * The HyperTransport range close to the 1T boundary is unique to AMD &
 * Hygon hosts with IOMMUs enabled. Restrict the ram-above-4g relocation
 * to above 1T to AMD & Hygon vCPUs only. @enforce_amd_1tb_hole is only false
 * in older machine types (<= 7.0) and @x-hygon-vendor-abi-fixes is false in
 * machine types (<= 11.1), for compatibility purposes.
 */
static inline bool x86_cpu_has_iommu_ht_gpa_hole(PCMachineState *pcms,
                                                 const X86CPU *cpu)
{
    if (!pcmc->enforce_amd_1tb_hole) {
        return false;
    }

    return IS_AMD_CPU(&cpu->env) ||
           (IS_HYGON_CPU(&cpu->env) && cpu->hygon_vendor_abi_fixes);
}

>          /* Bail out if max possible address does not cross HT range */
>          if (pc_max_used_gpa(pcms, pci_hole64_size) >= AMD_HT_START) {
>              x86ms->above_4g_mem_start = AMD_ABOVE_1TB_START;
> diff --git a/tests/functional/x86_64/test_mem_addr_space.py b/tests/functional/x86_64/test_mem_addr_space.py
> index 61b4a190b4..b80f9acd99 100755
> --- a/tests/functional/x86_64/test_mem_addr_space.py
> +++ b/tests/functional/x86_64/test_mem_addr_space.py
> @@ -208,6 +208,25 @@ def test_phybits_low_tcg_q35_71_amd(self):
>          self.assertEqual(self.vm.exitcode(), 1, "QEMU exit code should be 1")
>          self.assertRegex(self.vm.get_log(), r'phys-bits too low')
>  
> +    def test_phybits_low_tcg_q35_hygon(self):

like q35-7.1 AMD case, I think it's better to record the version in test
name:

def test_phybits_low_tcg_q35_112_hygon(self):

> +        """
> +        Same as q35-7.1 AMD case except that here we check that Dhyana
> +        follows the same AMD IOMMU HT reserved GPA range on new machine
> +        types.
> +        """
> +        self.ensure_64bit_binary()
> +        self.set_machine('q35')

For compatibility checks, it's better to explicitly specify the version:

self.set_machine('pc-q35-11.2')

> +        self.vm.add_args('-S', '-cpu', 'Dhyana,phys-bits=40',
> +                         '-m', '512,slots=1,maxmem=976G',
> +                         '-display', 'none',
> +                         '-object', 'memory-backend-ram,id=mem1,size=1G',
> +                         '-device', 'pc-dimm,id=vm0,memdev=mem1')
> +        self.vm.set_qmp_monitor(enabled=False)
> +        self.vm.launch()
> +        self.vm.wait()
> +        self.assertEqual(self.vm.exitcode(), 1, "QEMU exit code should be 1")
> +        self.assertRegex(self.vm.get_log(), r'phys-bits too low')
> +
>      def test_phybits_ok_tcg_q35_70_amd(self):
>          """
>          Same as q35-7.0 AMD case except that here we check that QEMU can
> @@ -225,6 +244,24 @@ def test_phybits_ok_tcg_q35_70_amd(self):
>          self.vm.shutdown()
>          self.assertNotRegex(self.vm.get_log(), r'phys-bits too low')
>  
> +    def test_phybits_ok_tcg_q35_110_hygon(self):

test_phybits_ok_tcg_q35_111_hygon?

> +        """
> +        Same as q35-7.1 Dhyana case except that here we check that the
> +        q35-11.0 compatibility setting keeps the old memory layout.

q35-11.1.

> +        """
> +        self.ensure_64bit_binary()
> +        self.set_machine('pc-q35-11.0')

self.set_machine('pc-q35-11.1')?

Thanks,
Zhao
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.