On Fri, 5 Jun 2026 18:46:07 +0800
fanhuang <[email protected]> wrote:

> Restructure the device_memory SRAT umbrella entry into a per-kind
> partition: each TYPE_SP_MEM device gets an ENABLED entry at its own
> proximity_domain; the remaining sub-ranges get HOTPLUGGABLE | ENABLED
> placeholders at the highest PXM, preserving the existing umbrella
> convention.
> 
> Signed-off-by: FangSheng Huang <[email protected]>
> ---
>  hw/i386/acpi-build.c | 98 +++++++++++++++++++++++++++++++++++++++++---
>  1 file changed, 92 insertions(+), 6 deletions(-)
> 
> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> index 0d7c83d5e9..76efa83808 100644
> --- a/hw/i386/acpi-build.c
> +++ b/hw/i386/acpi-build.c
> @@ -52,6 +52,7 @@
>  #include "migration/vmstate.h"
>  #include "hw/mem/memory-device.h"
>  #include "hw/mem/nvdimm.h"
> +#include "hw/mem/sp-mem.h"
>  #include "system/numa.h"
>  #include "system/reset.h"
>  #include "hw/hyperv/vmbus-bridge.h"
> @@ -1346,6 +1347,96 @@ build_tpm_tcpa(GArray *table_data, BIOSLinker *linker, 
> GArray *tcpalog,
>  }
>  #endif
>  
> +typedef struct {
> +    uint64_t addr;
> +    uint64_t size;
> +    uint32_t node;
> +} SpMemRange;
> +
> +static int collect_sp_mem_ranges_cb(Object *obj, void *opaque)
sp_mem_collect... maybe

> +{
> +    GArray *ranges = opaque;
> +    SpMemDevice *spm;
> +    MemoryDeviceClass *mdc;
> +    SpMemRange r;
> +
> +    if (!object_dynamic_cast(obj, TYPE_SP_MEM)) {
> +        return 0;
> +    }
> +    spm = SP_MEM(obj);
> +    mdc = MEMORY_DEVICE_GET_CLASS(MEMORY_DEVICE(spm));
> +    r.addr = mdc->get_addr(MEMORY_DEVICE(spm));
> +    r.size = memory_region_size(
> +                 host_memory_backend_get_memory(spm->hostmem));
> +    r.node = spm->node;
> +    g_array_append_val(ranges, r);
> +    return 0;
> +}
> +
> +static gint sp_mem_range_compare(gconstpointer a, gconstpointer b)
> +{
> +    const SpMemRange *range_a = a;
> +    const SpMemRange *range_b = b;
> +
> +    if (range_a->addr < range_b->addr) {
> +        return -1;
> +    }
> +    if (range_a->addr > range_b->addr) {
> +        return 1;
> +    }
> +    return 0;
> +}
> +
> +/*
> + * Emit SRAT memory-affinity entries covering the device_memory region.
> + *
> + * For each plugged TYPE_SP_MEM device, emit an ENABLED entry at the
> + * device's own proximity_domain.  All remaining sub-ranges (gaps
> + * between sp-mem devices, leading and trailing padding, and ranges
> + * occupied by other memory devices) are covered by HOTPLUGGABLE |
> + * ENABLED placeholder entries at PXM = nb_numa_nodes - 1.
> + */
> +static void build_srat_device_memory(GArray *table_data, MachineState *ms)
> +{
> +    g_autoptr(GArray) ranges = g_array_new(FALSE, TRUE, sizeof(SpMemRange));
> +    uint64_t cursor, end;
region_start, region_end

> +    int nb_nodes = ms->numa_state ? ms->numa_state->num_nodes : 0;
> +    uint32_t hotplug_pxm = nb_nodes > 0 ? nb_nodes - 1 : 0;

when function is called ms->numa_state->num_nodes is always > 0, isn't it?

> +    guint i;
> +
> +    if (!ms->device_memory) {
> +        return;
> +    }
> +
> +    cursor = ms->device_memory->base;
> +    end = cursor + memory_region_size(&ms->device_memory->mr);
> +
> +    object_child_foreach_recursive(qdev_get_machine(),
> +                                   collect_sp_mem_ranges_cb, ranges);
> +    g_array_sort(ranges, sp_mem_range_compare);
> +
> +    for (i = 0; i < ranges->len; i++) {
> +        SpMemRange *r = &g_array_index(ranges, SpMemRange, i);
> +
> +        if (cursor < r->addr) {
> +            build_srat_memory(table_data, cursor, r->addr - cursor,
> +                              hotplug_pxm,
> +                              MEM_AFFINITY_HOTPLUGGABLE |
> +                              MEM_AFFINITY_ENABLED);
> +        }
> +        build_srat_memory(table_data, r->addr, r->size, r->node,
> +                          MEM_AFFINITY_ENABLED);
> +        cursor = r->addr + r->size;
> +    }
> +
> +    if (cursor < end) {
> +        build_srat_memory(table_data, cursor, end - cursor,
> +                          hotplug_pxm,
> +                          MEM_AFFINITY_HOTPLUGGABLE |
> +                          MEM_AFFINITY_ENABLED);
> +    }
> +}
> +
>  #define HOLE_640K_START  (640 * KiB)
>  #define HOLE_640K_END   (1 * MiB)
>  
> @@ -1481,12 +1572,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, 
> MachineState *machine)
>       * Memory devices may override proximity set by this entry,
>       * providing _PXM method if necessary.
>       */
> -    if (machine->device_memory) {
keep it here, and drop one in build_srat_device_memory()

> -        build_srat_memory(table_data, machine->device_memory->base,
> -                          memory_region_size(&machine->device_memory->mr),
> -                          nb_numa_nodes - 1,
> -                          MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED);
> -    }
> +    build_srat_device_memory(table_data, machine);
>  
>      acpi_table_end(linker, &table);
>  }


Reply via email to