acpi: use build_append_int_noprefix() API to compose SRAT table

Drop usage of packed structures and explicit endian conversions
when building SRAT tables for arm/x86 and use endian agnostic
build_append_int_noprefix() API to build it.

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Message-Id: <20210924122802.1455362-18-imammedo@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
Igor Mammedov 2021-09-24 08:27:44 -04:00 committed by Michael S. Tsirkin
parent 255bf20f2e
commit e5b6d55a6e
6 changed files with 80 additions and 106 deletions

View file

@ -1940,15 +1940,25 @@ build_xsdt(GArray *table_data, BIOSLinker *linker, GArray *table_offsets,
acpi_table_end(linker, &table); acpi_table_end(linker, &table);
} }
void build_srat_memory(AcpiSratMemoryAffinity *numamem, uint64_t base, /*
* ACPI spec, Revision 4.0
* 5.2.16.2 Memory Affinity Structure
*/
void build_srat_memory(GArray *table_data, uint64_t base,
uint64_t len, int node, MemoryAffinityFlags flags) uint64_t len, int node, MemoryAffinityFlags flags)
{ {
numamem->type = ACPI_SRAT_MEMORY; build_append_int_noprefix(table_data, 1, 1); /* Type */
numamem->length = sizeof(*numamem); build_append_int_noprefix(table_data, 40, 1); /* Length */
numamem->proximity = cpu_to_le32(node); build_append_int_noprefix(table_data, node, 4); /* Proximity Domain */
numamem->flags = cpu_to_le32(flags); build_append_int_noprefix(table_data, 0, 2); /* Reserved */
numamem->base_addr = cpu_to_le64(base); build_append_int_noprefix(table_data, base, 4); /* Base Address Low */
numamem->range_length = cpu_to_le64(len); /* Base Address High */
build_append_int_noprefix(table_data, base >> 32, 4);
build_append_int_noprefix(table_data, len, 4); /* Length Low */
build_append_int_noprefix(table_data, len >> 32, 4); /* Length High */
build_append_int_noprefix(table_data, 0, 4); /* Reserved */
build_append_int_noprefix(table_data, flags, 4); /* Flags */
build_append_int_noprefix(table_data, 0, 8); /* Reserved */
} }
/* /*

View file

@ -1336,7 +1336,6 @@ void nvdimm_build_srat(GArray *table_data)
GSList *device_list = nvdimm_get_device_list(); GSList *device_list = nvdimm_get_device_list();
for (; device_list; device_list = device_list->next) { for (; device_list; device_list = device_list->next) {
AcpiSratMemoryAffinity *numamem = NULL;
DeviceState *dev = device_list->data; DeviceState *dev = device_list->data;
Object *obj = OBJECT(dev); Object *obj = OBJECT(dev);
uint64_t addr, size; uint64_t addr, size;
@ -1346,8 +1345,7 @@ void nvdimm_build_srat(GArray *table_data)
addr = object_property_get_uint(obj, PC_DIMM_ADDR_PROP, &error_abort); addr = object_property_get_uint(obj, PC_DIMM_ADDR_PROP, &error_abort);
size = object_property_get_uint(obj, PC_DIMM_SIZE_PROP, &error_abort); size = object_property_get_uint(obj, PC_DIMM_SIZE_PROP, &error_abort);
numamem = acpi_data_push(table_data, sizeof *numamem); build_srat_memory(table_data, addr, size, node,
build_srat_memory(numamem, addr, size, node,
MEM_AFFINITY_ENABLED | MEM_AFFINITY_NON_VOLATILE); MEM_AFFINITY_ENABLED | MEM_AFFINITY_NON_VOLATILE);
} }
g_slist_free(device_list); g_slist_free(device_list);

View file

@ -474,11 +474,13 @@ build_spcr(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
vms->oem_table_id); vms->oem_table_id);
} }
/*
* ACPI spec, Revision 5.1
* 5.2.16 System Resource Affinity Table (SRAT)
*/
static void static void
build_srat(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) build_srat(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
{ {
AcpiSratProcessorGiccAffinity *core;
AcpiSratMemoryAffinity *numamem;
int i; int i;
uint64_t mem_base; uint64_t mem_base;
MachineClass *mc = MACHINE_GET_CLASS(vms); MachineClass *mc = MACHINE_GET_CLASS(vms);
@ -492,19 +494,23 @@ build_srat(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
build_append_int_noprefix(table_data, 0, 8); /* Reserved */ build_append_int_noprefix(table_data, 0, 8); /* Reserved */
for (i = 0; i < cpu_list->len; ++i) { for (i = 0; i < cpu_list->len; ++i) {
core = acpi_data_push(table_data, sizeof(*core)); uint32_t nodeid = cpu_list->cpus[i].props.node_id;
core->type = ACPI_SRAT_PROCESSOR_GICC; /*
core->length = sizeof(*core); * 5.2.16.4 GICC Affinity Structure
core->proximity = cpu_to_le32(cpu_list->cpus[i].props.node_id); */
core->acpi_processor_uid = cpu_to_le32(i); build_append_int_noprefix(table_data, 3, 1); /* Type */
core->flags = cpu_to_le32(1); build_append_int_noprefix(table_data, 18, 1); /* Length */
build_append_int_noprefix(table_data, nodeid, 4); /* Proximity Domain */
build_append_int_noprefix(table_data, i, 4); /* ACPI Processor UID */
/* Flags, Table 5-76 */
build_append_int_noprefix(table_data, 1 /* Enabled */, 4);
build_append_int_noprefix(table_data, 0, 4); /* Clock Domain */
} }
mem_base = vms->memmap[VIRT_MEM].base; mem_base = vms->memmap[VIRT_MEM].base;
for (i = 0; i < ms->numa_state->num_nodes; ++i) { for (i = 0; i < ms->numa_state->num_nodes; ++i) {
if (ms->numa_state->nodes[i].node_mem > 0) { if (ms->numa_state->nodes[i].node_mem > 0) {
numamem = acpi_data_push(table_data, sizeof(*numamem)); build_srat_memory(table_data, mem_base,
build_srat_memory(numamem, mem_base,
ms->numa_state->nodes[i].node_mem, i, ms->numa_state->nodes[i].node_mem, i,
MEM_AFFINITY_ENABLED); MEM_AFFINITY_ENABLED);
mem_base += ms->numa_state->nodes[i].node_mem; mem_base += ms->numa_state->nodes[i].node_mem;
@ -516,8 +522,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
} }
if (ms->device_memory) { if (ms->device_memory) {
numamem = acpi_data_push(table_data, sizeof *numamem); build_srat_memory(table_data, ms->device_memory->base,
build_srat_memory(numamem, ms->device_memory->base,
memory_region_size(&ms->device_memory->mr), memory_region_size(&ms->device_memory->mr),
ms->numa_state->num_nodes - 1, ms->numa_state->num_nodes - 1,
MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED); MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED);

View file

@ -1939,13 +1939,15 @@ build_tpm_tcpa(GArray *table_data, BIOSLinker *linker, GArray *tcpalog,
#define HOLE_640K_START (640 * KiB) #define HOLE_640K_START (640 * KiB)
#define HOLE_640K_END (1 * MiB) #define HOLE_640K_END (1 * MiB)
/*
* ACPI spec, Revision 3.0
* 5.2.15 System Resource Affinity Table (SRAT)
*/
static void static void
build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine) build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
{ {
AcpiSratMemoryAffinity *numamem;
int i; int i;
int numa_start, slots; int numa_mem_start, slots;
uint64_t mem_len, mem_base, next_base; uint64_t mem_len, mem_base, next_base;
MachineClass *mc = MACHINE_GET_CLASS(machine); MachineClass *mc = MACHINE_GET_CLASS(machine);
X86MachineState *x86ms = X86_MACHINE(machine); X86MachineState *x86ms = X86_MACHINE(machine);
@ -1968,34 +1970,41 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
uint32_t apic_id = apic_ids->cpus[i].arch_id; uint32_t apic_id = apic_ids->cpus[i].arch_id;
if (apic_id < 255) { if (apic_id < 255) {
AcpiSratProcessorAffinity *core; /* 5.2.15.1 Processor Local APIC/SAPIC Affinity Structure */
build_append_int_noprefix(table_data, 0, 1); /* Type */
core = acpi_data_push(table_data, sizeof *core); build_append_int_noprefix(table_data, 16, 1); /* Length */
core->type = ACPI_SRAT_PROCESSOR_APIC; /* Proximity Domain [7:0] */
core->length = sizeof(*core); build_append_int_noprefix(table_data, node_id, 1);
core->local_apic_id = apic_id; build_append_int_noprefix(table_data, apic_id, 1); /* APIC ID */
core->proximity_lo = node_id; /* Flags, Table 5-36 */
memset(core->proximity_hi, 0, 3); build_append_int_noprefix(table_data, 1, 4);
core->local_sapic_eid = 0; build_append_int_noprefix(table_data, 0, 1); /* Local SAPIC EID */
core->flags = cpu_to_le32(1); /* Proximity Domain [31:8] */
build_append_int_noprefix(table_data, 0, 3);
build_append_int_noprefix(table_data, 0, 4); /* Reserved */
} else { } else {
AcpiSratProcessorX2ApicAffinity *core; /*
* ACPI spec, Revision 4.0
core = acpi_data_push(table_data, sizeof *core); * 5.2.16.3 Processor Local x2APIC Affinity Structure
core->type = ACPI_SRAT_PROCESSOR_x2APIC; */
core->length = sizeof(*core); build_append_int_noprefix(table_data, 2, 1); /* Type */
core->x2apic_id = cpu_to_le32(apic_id); build_append_int_noprefix(table_data, 24, 1); /* Length */
core->proximity_domain = cpu_to_le32(node_id); build_append_int_noprefix(table_data, 0, 2); /* Reserved */
core->flags = cpu_to_le32(1); /* Proximity Domain */
build_append_int_noprefix(table_data, node_id, 4);
build_append_int_noprefix(table_data, apic_id, 4); /* X2APIC ID */
/* Flags, Table 5-39 */
build_append_int_noprefix(table_data, 1 /* Enabled */, 4);
build_append_int_noprefix(table_data, 0, 4); /* Clock Domain */
build_append_int_noprefix(table_data, 0, 4); /* Reserved */
} }
} }
/* the memory map is a bit tricky, it contains at least one hole /* the memory map is a bit tricky, it contains at least one hole
* from 640k-1M and possibly another one from 3.5G-4G. * from 640k-1M and possibly another one from 3.5G-4G.
*/ */
next_base = 0; next_base = 0;
numa_start = table_data->len; numa_mem_start = table_data->len;
for (i = 1; i < nb_numa_nodes + 1; ++i) { for (i = 1; i < nb_numa_nodes + 1; ++i) {
mem_base = next_base; mem_base = next_base;
@ -2007,8 +2016,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
next_base > HOLE_640K_START) { next_base > HOLE_640K_START) {
mem_len -= next_base - HOLE_640K_START; mem_len -= next_base - HOLE_640K_START;
if (mem_len > 0) { if (mem_len > 0) {
numamem = acpi_data_push(table_data, sizeof *numamem); build_srat_memory(table_data, mem_base, mem_len, i - 1,
build_srat_memory(numamem, mem_base, mem_len, i - 1,
MEM_AFFINITY_ENABLED); MEM_AFFINITY_ENABLED);
} }
@ -2026,8 +2034,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
next_base > x86ms->below_4g_mem_size) { next_base > x86ms->below_4g_mem_size) {
mem_len -= next_base - x86ms->below_4g_mem_size; mem_len -= next_base - x86ms->below_4g_mem_size;
if (mem_len > 0) { if (mem_len > 0) {
numamem = acpi_data_push(table_data, sizeof *numamem); build_srat_memory(table_data, mem_base, mem_len, i - 1,
build_srat_memory(numamem, mem_base, mem_len, i - 1,
MEM_AFFINITY_ENABLED); MEM_AFFINITY_ENABLED);
} }
mem_base = 1ULL << 32; mem_base = 1ULL << 32;
@ -2036,8 +2043,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
} }
if (mem_len > 0) { if (mem_len > 0) {
numamem = acpi_data_push(table_data, sizeof *numamem); build_srat_memory(table_data, mem_base, mem_len, i - 1,
build_srat_memory(numamem, mem_base, mem_len, i - 1,
MEM_AFFINITY_ENABLED); MEM_AFFINITY_ENABLED);
} }
} }
@ -2046,10 +2052,15 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
nvdimm_build_srat(table_data); nvdimm_build_srat(table_data);
} }
slots = (table_data->len - numa_start) / sizeof *numamem; /*
* TODO: this part is not in ACPI spec and current linux kernel boots fine
* without these entries. But I recall there were issues the last time I
* tried to remove it with some ancient guest OS, however I can't remember
* what that was so keep this around for now
*/
slots = (table_data->len - numa_mem_start) / 40 /* mem affinity len */;
for (; slots < nb_numa_nodes + 2; slots++) { for (; slots < nb_numa_nodes + 2; slots++) {
numamem = acpi_data_push(table_data, sizeof *numamem); build_srat_memory(table_data, 0, 0, 0, MEM_AFFINITY_NOFLAGS);
build_srat_memory(numamem, 0, 0, 0, MEM_AFFINITY_NOFLAGS);
} }
/* /*
@ -2061,8 +2072,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
* providing _PXM method if necessary. * providing _PXM method if necessary.
*/ */
if (hotpluggable_address_space_size) { if (hotpluggable_address_space_size) {
numamem = acpi_data_push(table_data, sizeof *numamem); build_srat_memory(table_data, machine->device_memory->base,
build_srat_memory(numamem, machine->device_memory->base,
hotpluggable_address_space_size, nb_numa_nodes - 1, hotpluggable_address_space_size, nb_numa_nodes - 1,
MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED); MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED);
} }

View file

@ -358,55 +358,6 @@ struct AcpiGenericTimerTable {
} QEMU_PACKED; } QEMU_PACKED;
typedef struct AcpiGenericTimerTable AcpiGenericTimerTable; typedef struct AcpiGenericTimerTable AcpiGenericTimerTable;
#define ACPI_SRAT_PROCESSOR_APIC 0
#define ACPI_SRAT_MEMORY 1
#define ACPI_SRAT_PROCESSOR_x2APIC 2
#define ACPI_SRAT_PROCESSOR_GICC 3
struct AcpiSratProcessorAffinity {
ACPI_SUB_HEADER_DEF
uint8_t proximity_lo;
uint8_t local_apic_id;
uint32_t flags;
uint8_t local_sapic_eid;
uint8_t proximity_hi[3];
uint32_t reserved;
} QEMU_PACKED;
typedef struct AcpiSratProcessorAffinity AcpiSratProcessorAffinity;
struct AcpiSratProcessorX2ApicAffinity {
ACPI_SUB_HEADER_DEF
uint16_t reserved;
uint32_t proximity_domain;
uint32_t x2apic_id;
uint32_t flags;
uint32_t clk_domain;
uint32_t reserved2;
} QEMU_PACKED;
typedef struct AcpiSratProcessorX2ApicAffinity AcpiSratProcessorX2ApicAffinity;
struct AcpiSratMemoryAffinity {
ACPI_SUB_HEADER_DEF
uint32_t proximity;
uint16_t reserved1;
uint64_t base_addr;
uint64_t range_length;
uint32_t reserved2;
uint32_t flags;
uint32_t reserved3[2];
} QEMU_PACKED;
typedef struct AcpiSratMemoryAffinity AcpiSratMemoryAffinity;
struct AcpiSratProcessorGiccAffinity {
ACPI_SUB_HEADER_DEF
uint32_t proximity;
uint32_t acpi_processor_uid;
uint32_t flags;
uint32_t clock_domain;
} QEMU_PACKED;
typedef struct AcpiSratProcessorGiccAffinity AcpiSratProcessorGiccAffinity;
/* DMAR - DMA Remapping table r2.2 */ /* DMAR - DMA Remapping table r2.2 */
struct AcpiTableDmar { struct AcpiTableDmar {
ACPI_TABLE_HEADER_DEF ACPI_TABLE_HEADER_DEF

View file

@ -487,7 +487,7 @@ Aml *build_crs(PCIHostState *host, CrsRangeSet *range_set, uint32_t io_offset,
uint32_t mmio32_offset, uint64_t mmio64_offset, uint32_t mmio32_offset, uint64_t mmio64_offset,
uint16_t bus_nr_offset); uint16_t bus_nr_offset);
void build_srat_memory(AcpiSratMemoryAffinity *numamem, uint64_t base, void build_srat_memory(GArray *table_data, uint64_t base,
uint64_t len, int node, MemoryAffinityFlags flags); uint64_t len, int node, MemoryAffinityFlags flags);
void build_slit(GArray *table_data, BIOSLinker *linker, MachineState *ms, void build_slit(GArray *table_data, BIOSLinker *linker, MachineState *ms,