acpi: arm/virt: madt: use build_append_int_noprefix() API to compose MADT table

Drop usage of packed structures and explicit endian conversions
when building MADT table 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-26-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:52 -04:00 committed by Michael S. Tsirkin
parent dd092b9c60
commit 37f33084ed
2 changed files with 89 additions and 143 deletions

View File

@ -568,94 +568,124 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
} }
/* /*
* ACPI spec, Revision 5.0 * ACPI spec, Revision 5.1 Errata A
* 5.2.12 Multiple APIC Description Table (MADT) * 5.2.12 Multiple APIC Description Table (MADT)
*/ */
static void build_append_gicr(GArray *table_data, uint64_t base, uint32_t size)
{
build_append_int_noprefix(table_data, 0xE, 1); /* Type */
build_append_int_noprefix(table_data, 16, 1); /* Length */
build_append_int_noprefix(table_data, 0, 2); /* Reserved */
/* Discovery Range Base Addres */
build_append_int_noprefix(table_data, base, 8);
build_append_int_noprefix(table_data, size, 4); /* Discovery Range Length */
}
static void static void
build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
{ {
int i;
VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms); VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
const MemMapEntry *memmap = vms->memmap; const MemMapEntry *memmap = vms->memmap;
const int *irqmap = vms->irqmap;
AcpiMadtGenericDistributor *gicd;
AcpiMadtGenericMsiFrame *gic_msi;
int i;
AcpiTable table = { .sig = "APIC", .rev = 3, .oem_id = vms->oem_id, AcpiTable table = { .sig = "APIC", .rev = 3, .oem_id = vms->oem_id,
.oem_table_id = vms->oem_table_id }; .oem_table_id = vms->oem_table_id };
acpi_table_begin(&table, table_data); acpi_table_begin(&table, table_data);
/* Local Interrupt Controller Address */ /* Local Interrupt Controller Address */
build_append_int_noprefix(table_data, 0, 4); build_append_int_noprefix(table_data, 0, 4);
build_append_int_noprefix(table_data, 0, 4); /* Flags */ build_append_int_noprefix(table_data, 0, 4); /* Flags */
gicd = acpi_data_push(table_data, sizeof *gicd); /* 5.2.12.15 GIC Distributor Structure */
gicd->type = ACPI_APIC_GENERIC_DISTRIBUTOR; build_append_int_noprefix(table_data, 0xC, 1); /* Type */
gicd->length = sizeof(*gicd); build_append_int_noprefix(table_data, 24, 1); /* Length */
gicd->base_address = cpu_to_le64(memmap[VIRT_GIC_DIST].base); build_append_int_noprefix(table_data, 0, 2); /* Reserved */
gicd->version = vms->gic_version; build_append_int_noprefix(table_data, 0, 4); /* GIC ID */
/* Physical Base Address */
build_append_int_noprefix(table_data, memmap[VIRT_GIC_DIST].base, 8);
build_append_int_noprefix(table_data, 0, 4); /* System Vector Base */
/* GIC version */
build_append_int_noprefix(table_data, vms->gic_version, 1);
build_append_int_noprefix(table_data, 0, 3); /* Reserved */
for (i = 0; i < MACHINE(vms)->smp.cpus; i++) { for (i = 0; i < MACHINE(vms)->smp.cpus; i++) {
AcpiMadtGenericCpuInterface *gicc = acpi_data_push(table_data,
sizeof(*gicc));
ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(i)); ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(i));
uint64_t physical_base_address = 0, gich = 0, gicv = 0;
uint32_t vgic_interrupt = vms->virt ? PPI(ARCH_GIC_MAINT_IRQ) : 0;
uint32_t pmu_interrupt = arm_feature(&armcpu->env, ARM_FEATURE_PMU) ?
PPI(VIRTUAL_PMU_IRQ) : 0;
gicc->type = ACPI_APIC_GENERIC_CPU_INTERFACE;
gicc->length = sizeof(*gicc);
if (vms->gic_version == 2) { if (vms->gic_version == 2) {
gicc->base_address = cpu_to_le64(memmap[VIRT_GIC_CPU].base); physical_base_address = memmap[VIRT_GIC_CPU].base;
gicc->gich_base_address = cpu_to_le64(memmap[VIRT_GIC_HYP].base); gicv = memmap[VIRT_GIC_VCPU].base;
gicc->gicv_base_address = cpu_to_le64(memmap[VIRT_GIC_VCPU].base); gich = memmap[VIRT_GIC_HYP].base;
} }
gicc->cpu_interface_number = cpu_to_le32(i);
gicc->arm_mpidr = cpu_to_le64(armcpu->mp_affinity);
gicc->uid = cpu_to_le32(i);
gicc->flags = cpu_to_le32(ACPI_MADT_GICC_ENABLED);
if (arm_feature(&armcpu->env, ARM_FEATURE_PMU)) { /* 5.2.12.14 GIC Structure */
gicc->performance_interrupt = cpu_to_le32(PPI(VIRTUAL_PMU_IRQ)); build_append_int_noprefix(table_data, 0xB, 1); /* Type */
} build_append_int_noprefix(table_data, 76, 1); /* Length */
if (vms->virt) { build_append_int_noprefix(table_data, 0, 2); /* Reserved */
gicc->vgic_interrupt = cpu_to_le32(PPI(ARCH_GIC_MAINT_IRQ)); build_append_int_noprefix(table_data, i, 4); /* GIC ID */
} build_append_int_noprefix(table_data, i, 4); /* ACPI Processor UID */
/* Flags */
build_append_int_noprefix(table_data, 1, 4); /* Enabled */
/* Parking Protocol Version */
build_append_int_noprefix(table_data, 0, 4);
/* Performance Interrupt GSIV */
build_append_int_noprefix(table_data, pmu_interrupt, 4);
build_append_int_noprefix(table_data, 0, 8); /* Parked Address */
/* Physical Base Address */
build_append_int_noprefix(table_data, physical_base_address, 8);
build_append_int_noprefix(table_data, gicv, 8); /* GICV */
build_append_int_noprefix(table_data, gich, 8); /* GICH */
/* VGIC Maintenance interrupt */
build_append_int_noprefix(table_data, vgic_interrupt, 4);
build_append_int_noprefix(table_data, 0, 8); /* GICR Base Address*/
/* MPIDR */
build_append_int_noprefix(table_data, armcpu->mp_affinity, 8);
} }
if (vms->gic_version == 3) { if (vms->gic_version == 3) {
AcpiMadtGenericTranslator *gic_its; build_append_gicr(table_data, memmap[VIRT_GIC_REDIST].base,
int nb_redist_regions = virt_gicv3_redist_region_count(vms); memmap[VIRT_GIC_REDIST].size);
AcpiMadtGenericRedistributor *gicr = acpi_data_push(table_data, if (virt_gicv3_redist_region_count(vms) == 2) {
sizeof *gicr); build_append_gicr(table_data, memmap[VIRT_HIGH_GIC_REDIST2].base,
memmap[VIRT_HIGH_GIC_REDIST2].size);
gicr->type = ACPI_APIC_GENERIC_REDISTRIBUTOR;
gicr->length = sizeof(*gicr);
gicr->base_address = cpu_to_le64(memmap[VIRT_GIC_REDIST].base);
gicr->range_length = cpu_to_le32(memmap[VIRT_GIC_REDIST].size);
if (nb_redist_regions == 2) {
gicr = acpi_data_push(table_data, sizeof(*gicr));
gicr->type = ACPI_APIC_GENERIC_REDISTRIBUTOR;
gicr->length = sizeof(*gicr);
gicr->base_address =
cpu_to_le64(memmap[VIRT_HIGH_GIC_REDIST2].base);
gicr->range_length =
cpu_to_le32(memmap[VIRT_HIGH_GIC_REDIST2].size);
} }
if (its_class_name() && !vmc->no_its) { if (its_class_name() && !vmc->no_its) {
gic_its = acpi_data_push(table_data, sizeof *gic_its); /*
gic_its->type = ACPI_APIC_GENERIC_TRANSLATOR; * FIXME: Structure is from Revision 6.0 where 'GIC Structure'
gic_its->length = sizeof(*gic_its); * has additional fields on top of implemented 5.1 Errata A,
gic_its->translation_id = 0; * to make it consistent with v6.0 we need to bump everything
gic_its->base_address = cpu_to_le64(memmap[VIRT_GIC_ITS].base); * to v6.0
*/
/*
* ACPI spec, Revision 6.0 Errata A
* (original 6.0 definition has invalid Length)
* 5.2.12.18 GIC ITS Structure
*/
build_append_int_noprefix(table_data, 0xF, 1); /* Type */
build_append_int_noprefix(table_data, 20, 1); /* Length */
build_append_int_noprefix(table_data, 0, 2); /* Reserved */
build_append_int_noprefix(table_data, 0, 4); /* GIC ITS ID */
/* Physical Base Address */
build_append_int_noprefix(table_data, memmap[VIRT_GIC_ITS].base, 8);
build_append_int_noprefix(table_data, 0, 4); /* Reserved */
} }
} else { } else {
gic_msi = acpi_data_push(table_data, sizeof *gic_msi); const uint16_t spi_base = vms->irqmap[VIRT_GIC_V2M] + ARM_SPI_BASE;
gic_msi->type = ACPI_APIC_GENERIC_MSI_FRAME;
gic_msi->length = sizeof(*gic_msi); /* 5.2.12.16 GIC MSI Frame Structure */
gic_msi->gic_msi_frame_id = 0; build_append_int_noprefix(table_data, 0xD, 1); /* Type */
gic_msi->base_address = cpu_to_le64(memmap[VIRT_GIC_V2M].base); build_append_int_noprefix(table_data, 24, 1); /* Length */
gic_msi->flags = cpu_to_le32(1); build_append_int_noprefix(table_data, 0, 2); /* Reserved */
gic_msi->spi_count = cpu_to_le16(NUM_GICV2M_SPIS); build_append_int_noprefix(table_data, 0, 4); /* GIC MSI Frame ID */
gic_msi->spi_base = cpu_to_le16(irqmap[VIRT_GIC_V2M] + ARM_SPI_BASE); /* Physical Base Address */
build_append_int_noprefix(table_data, memmap[VIRT_GIC_V2M].base, 8);
build_append_int_noprefix(table_data, 1, 4); /* Flags */
/* SPI Count */
build_append_int_noprefix(table_data, NUM_GICV2M_SPIS, 2);
build_append_int_noprefix(table_data, spi_base, 2); /* SPI Base */
} }
acpi_table_end(linker, &table); acpi_table_end(linker, &table);
} }

View File

@ -163,90 +163,6 @@ struct AcpiFacsDescriptorRev1 {
} QEMU_PACKED; } QEMU_PACKED;
typedef struct AcpiFacsDescriptorRev1 AcpiFacsDescriptorRev1; typedef struct AcpiFacsDescriptorRev1 AcpiFacsDescriptorRev1;
/* Values for Type in APIC sub-headers */
#define ACPI_APIC_GENERIC_CPU_INTERFACE 11
#define ACPI_APIC_GENERIC_DISTRIBUTOR 12
#define ACPI_APIC_GENERIC_MSI_FRAME 13
#define ACPI_APIC_GENERIC_REDISTRIBUTOR 14
#define ACPI_APIC_GENERIC_TRANSLATOR 15
#define ACPI_APIC_RESERVED 16 /* 16 and greater are reserved */
/*
* MADT sub-structures (Follow MULTIPLE_APIC_DESCRIPTION_TABLE)
*/
#define ACPI_SUB_HEADER_DEF /* Common ACPI sub-structure header */\
uint8_t type; \
uint8_t length;
/* Sub-structures for MADT */
struct AcpiMadtGenericCpuInterface {
ACPI_SUB_HEADER_DEF
uint16_t reserved;
uint32_t cpu_interface_number;
uint32_t uid;
uint32_t flags;
uint32_t parking_version;
uint32_t performance_interrupt;
uint64_t parked_address;
uint64_t base_address;
uint64_t gicv_base_address;
uint64_t gich_base_address;
uint32_t vgic_interrupt;
uint64_t gicr_base_address;
uint64_t arm_mpidr;
} QEMU_PACKED;
typedef struct AcpiMadtGenericCpuInterface AcpiMadtGenericCpuInterface;
/* GICC CPU Interface Flags */
#define ACPI_MADT_GICC_ENABLED 1
struct AcpiMadtGenericDistributor {
ACPI_SUB_HEADER_DEF
uint16_t reserved;
uint32_t gic_id;
uint64_t base_address;
uint32_t global_irq_base;
/* ACPI 5.1 Errata 1228 Present GIC version in MADT table */
uint8_t version;
uint8_t reserved2[3];
} QEMU_PACKED;
typedef struct AcpiMadtGenericDistributor AcpiMadtGenericDistributor;
struct AcpiMadtGenericMsiFrame {
ACPI_SUB_HEADER_DEF
uint16_t reserved;
uint32_t gic_msi_frame_id;
uint64_t base_address;
uint32_t flags;
uint16_t spi_count;
uint16_t spi_base;
} QEMU_PACKED;
typedef struct AcpiMadtGenericMsiFrame AcpiMadtGenericMsiFrame;
struct AcpiMadtGenericRedistributor {
ACPI_SUB_HEADER_DEF
uint16_t reserved;
uint64_t base_address;
uint32_t range_length;
} QEMU_PACKED;
typedef struct AcpiMadtGenericRedistributor AcpiMadtGenericRedistributor;
struct AcpiMadtGenericTranslator {
ACPI_SUB_HEADER_DEF
uint16_t reserved;
uint32_t translation_id;
uint64_t base_address;
uint32_t reserved2;
} QEMU_PACKED;
typedef struct AcpiMadtGenericTranslator AcpiMadtGenericTranslator;
/* /*
* Generic Timer Description Table (GTDT) * Generic Timer Description Table (GTDT)
*/ */