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


Reply via email to