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:
parent
dd092b9c60
commit
37f33084ed
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user