@samitouri / QOSamiQemu / commits / 78f08a0f47

i386/acpi-build: partition device_memory SRAT umbrella for sp-mem

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 <FangSheng.Huang@amd.com> Reviewed-by: Igor Mammedov <imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Message-ID: <20260623075051.3797975-4-FangSheng.Huang@amd.com>

fanhuang committed Jun 23, 2026 at 15:50 UTC 78f08a0f47e787921d8beb78a5bade9a8a64400b
1 file changed +92 -4
hw/i386/acpi-build.c
+92 -4
@@ -52,6 +52,7 @@
52 #include "migration/vmstate.h"
53 #include "hw/mem/memory-device.h"
54 #include "hw/mem/nvdimm.h"
55 +#include "hw/mem/sp-mem.h"
56 #include "system/numa.h"
57 #include "system/reset.h"
58 #include "hw/hyperv/vmbus-bridge.h"
@@ -1351,6 +1352,96 @@ build_tpm_tcpa(GArray *table_data, BIOSLinker *linker, GArray *tcpalog,
1352 }
1353 #endif
1354
1355 +typedef struct {
1356 + uint64_t addr;
1357 + uint64_t size;
1358 + uint32_t node;
1359 +} SpMemRange;
1360 +
1361 +static int sp_mem_collect_ranges_cb(Object *obj, void *opaque)
1362 +{
1363 + GArray *ranges = opaque;
1364 + SpMemDevice *spm;
1365 + MemoryDeviceClass *mdc;
1366 + SpMemRange r;
1367 +
1368 + if (!object_dynamic_cast(obj, TYPE_SP_MEM)) {
1369 + return 0;
1370 + }
1371 + spm = SP_MEM(obj);
1372 + mdc = MEMORY_DEVICE_GET_CLASS(MEMORY_DEVICE(spm));
1373 + r.addr = mdc->get_addr(MEMORY_DEVICE(spm));
1374 + r.size = memory_region_size(
1375 + host_memory_backend_get_memory(spm->hostmem));
1376 + r.node = spm->node;
1377 + g_array_append_val(ranges, r);
1378 + return 0;
1379 +}
1380 +
1381 +static gint sp_mem_range_compare(gconstpointer a, gconstpointer b)
1382 +{
1383 + const SpMemRange *range_a = a;
1384 + const SpMemRange *range_b = b;
1385 +
1386 + if (range_a->addr < range_b->addr) {
1387 + return -1;
1388 + }
1389 + if (range_a->addr > range_b->addr) {
1390 + return 1;
1391 + }
1392 + return 0;
1393 +}
1394 +
1395 +/*
1396 + * Emit SRAT memory-affinity entries covering the device_memory region.
1397 + *
1398 + * For each plugged TYPE_SP_MEM device, emit an ENABLED entry at the
1399 + * device's own proximity_domain. All remaining sub-ranges (gaps
1400 + * between sp-mem devices, leading and trailing padding, and ranges
1401 + * occupied by other memory devices) are covered by HOTPLUGGABLE |
1402 + * ENABLED placeholder entries at PXM = nb_numa_nodes - 1.
1403 + */
1404 +static void build_srat_device_memory(GArray *table_data, MachineState *ms)
1405 +{
1406 + g_autoptr(GArray) ranges = g_array_new(FALSE, TRUE, sizeof(SpMemRange));
1407 + uint32_t hotplug_pxm = ms->numa_state->num_nodes - 1;
1408 + uint64_t region_start, region_end;
1409 + guint i;
1410 +
1411 + region_start = ms->device_memory->base;
1412 + region_end = region_start + memory_region_size(&ms->device_memory->mr);
1413 +
1414 + object_child_foreach_recursive(qdev_get_machine(),
1415 + sp_mem_collect_ranges_cb, ranges);
1416 + g_array_sort(ranges, sp_mem_range_compare);
1417 +
1418 + for (i = 0; i < ranges->len; i++) {
1419 + SpMemRange *r = &g_array_index(ranges, SpMemRange, i);
1420 +
1421 + if (region_start < r->addr) {
1422 + build_srat_memory(table_data, region_start, r->addr - region_start,
1423 + hotplug_pxm,
1424 + MEM_AFFINITY_HOTPLUGGABLE |
1425 + MEM_AFFINITY_ENABLED);
1426 + }
1427 + build_srat_memory(table_data, r->addr, r->size, r->node,
1428 + MEM_AFFINITY_ENABLED);
1429 + region_start = r->addr + r->size;
1430 + }
1431 +
1432 + /*
1433 + * Cover the rest of the device_memory window that no sp-mem device
1434 + * occupies. Keeping it HOTPLUGGABLE preserves the umbrella entry's
1435 + * role for future pc-dimm / virtio-mem hot-add into this window.
1436 + */
1437 + if (region_start < region_end) {
1438 + build_srat_memory(table_data, region_start, region_end - region_start,
1439 + hotplug_pxm,
1440 + MEM_AFFINITY_HOTPLUGGABLE |
1441 + MEM_AFFINITY_ENABLED);
1442 + }
1443 +}
1444 +
1445 #define HOLE_640K_START (640 * KiB)
1446 #define HOLE_640K_END (1 * MiB)
1447
@@ -1487,10 +1578,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
1578 * providing _PXM method if necessary.
1579 */
1580 if (machine->device_memory) {
1490 - build_srat_memory(table_data, machine->device_memory->base,
1491 - memory_region_size(&machine->device_memory->mr),
1492 - nb_numa_nodes - 1,
1493 - MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED);
1581 + build_srat_device_memory(table_data, machine);
1582 }
1583
1584 acpi_table_end(linker, &table);