diff options
author | Shannon Zhao <shannon.zhao@linaro.org> | 2015-05-29 11:28:56 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2015-05-29 11:28:56 +0100 |
commit | 982d06c561a62cf7d2a8d31e8a8c107fb3477419 (patch) | |
tree | 1a12a0e5779f48e65706a928a61e978d598a2e34 /hw/arm/virt-acpi-build.c | |
parent | c2f7c0c306dcd56725b506d3743eed421e6d0994 (diff) | |
download | qemu-982d06c561a62cf7d2a8d31e8a8c107fb3477419.tar.gz qemu-982d06c561a62cf7d2a8d31e8a8c107fb3477419.tar.bz2 qemu-982d06c561a62cf7d2a8d31e8a8c107fb3477419.zip |
hw/arm/virt-acpi-build: Generate MADT table
MADT describes GIC enabled ARM platforms. The GICC and GICD
subtables are used to define the GIC regions.
Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Message-id: 1432522520-8068-10-git-send-email-zhaoshenglong@huawei.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/arm/virt-acpi-build.c')
-rw-r--r-- | hw/arm/virt-acpi-build.c | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 079150103c..29ad53534c 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -42,6 +42,20 @@ #define ARM_SPI_BASE 32 +typedef struct VirtAcpiCpuInfo { + DECLARE_BITMAP(found_cpus, VIRT_ACPI_CPU_ID_LIMIT); +} VirtAcpiCpuInfo; + +static void virt_acpi_get_cpu_info(VirtAcpiCpuInfo *cpuinfo) +{ + CPUState *cpu; + + memset(cpuinfo->found_cpus, 0, sizeof cpuinfo->found_cpus); + CPU_FOREACH(cpu) { + set_bit(cpu->cpu_index, cpuinfo->found_cpus); + } +} + static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus) { uint16_t i; @@ -137,6 +151,43 @@ static void acpi_dsdt_add_virtio(Aml *scope, } } +/* MADT */ +static void +build_madt(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info, + VirtAcpiCpuInfo *cpuinfo) +{ + int madt_start = table_data->len; + const MemMapEntry *memmap = guest_info->memmap; + AcpiMultipleApicTable *madt; + AcpiMadtGenericDistributor *gicd; + int i; + + madt = acpi_data_push(table_data, sizeof *madt); + + for (i = 0; i < guest_info->smp_cpus; i++) { + AcpiMadtGenericInterrupt *gicc = acpi_data_push(table_data, + sizeof *gicc); + gicc->type = ACPI_APIC_GENERIC_INTERRUPT; + gicc->length = sizeof(*gicc); + gicc->base_address = memmap[VIRT_GIC_CPU].base; + gicc->cpu_interface_number = i; + gicc->arm_mpidr = i; + gicc->uid = i; + if (test_bit(i, cpuinfo->found_cpus)) { + gicc->flags = cpu_to_le32(ACPI_GICC_ENABLED); + } + } + + gicd = acpi_data_push(table_data, sizeof *gicd); + gicd->type = ACPI_APIC_GENERIC_DISTRIBUTOR; + gicd->length = sizeof(*gicd); + gicd->base_address = memmap[VIRT_GIC_DIST].base; + + build_header(linker, table_data, + (void *)(table_data->data + madt_start), "APIC", + table_data->len - madt_start, 5); +} + /* FADT */ static void build_fadt(GArray *table_data, GArray *linker, unsigned dsdt) @@ -209,8 +260,11 @@ void virt_acpi_build(VirtGuestInfo *guest_info, AcpiBuildTables *tables) { GArray *table_offsets; unsigned dsdt; + VirtAcpiCpuInfo cpuinfo; GArray *tables_blob = tables->table_data; + virt_acpi_get_cpu_info(&cpuinfo); + table_offsets = g_array_new(false, true /* clear */, sizeof(uint32_t)); @@ -235,6 +289,9 @@ void virt_acpi_build(VirtGuestInfo *guest_info, AcpiBuildTables *tables) acpi_add_table(table_offsets, tables_blob); build_fadt(tables_blob, tables->linker, dsdt); + acpi_add_table(table_offsets, tables_blob); + build_madt(tables_blob, tables->linker, guest_info, &cpuinfo); + /* Cleanup memory that's no longer used. */ g_array_free(table_offsets, true); } |