build_madt(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info) { int madt_start = table_data->len; const MemMapEntry *memmap = guest_info->memmap; const int *irqmap = guest_info->irqmap; AcpiMultipleApicTable *madt; AcpiMadtGenericDistributor *gicd; AcpiMadtGenericMsiFrame *gic_msi; int i; madt = acpi_data_push(table_data, sizeof *madt); 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; gicd->version = guest_info->gic_version; for (i = 0; i < guest_info->smp_cpus; i++) { AcpiMadtGenericInterrupt *gicc = acpi_data_push(table_data, sizeof *gicc); ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(i)); gicc->type = ACPI_APIC_GENERIC_INTERRUPT; gicc->length = sizeof(*gicc); if (guest_info->gic_version == 2) { gicc->base_address = memmap[VIRT_GIC_CPU].base; } gicc->cpu_interface_number = i; gicc->arm_mpidr = armcpu->mp_affinity; gicc->uid = i; gicc->flags = cpu_to_le32(ACPI_GICC_ENABLED); if (armcpu->has_pmu) { gicc->performance_interrupt = cpu_to_le32(PPI(VIRTUAL_PMU_IRQ)); } } if (guest_info->gic_version == 3) { AcpiMadtGenericTranslator *gic_its; AcpiMadtGenericRedistributor *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_GIC_REDIST].base); gicr->range_length = cpu_to_le32(memmap[VIRT_GIC_REDIST].size); if (its_class_name()) { gic_its = acpi_data_push(table_data, sizeof *gic_its); gic_its->type = ACPI_APIC_GENERIC_TRANSLATOR; gic_its->length = sizeof(*gic_its); gic_its->translation_id = 0; gic_its->base_address = cpu_to_le64(memmap[VIRT_GIC_ITS].base); } } else { gic_msi = acpi_data_push(table_data, sizeof *gic_msi); gic_msi->type = ACPI_APIC_GENERIC_MSI_FRAME; gic_msi->length = sizeof(*gic_msi); gic_msi->gic_msi_frame_id = 0; gic_msi->base_address = cpu_to_le64(memmap[VIRT_GIC_V2M].base); gic_msi->flags = cpu_to_le32(1); gic_msi->spi_count = cpu_to_le16(NUM_GICV2M_SPIS); gic_msi->spi_base = cpu_to_le16(irqmap[VIRT_GIC_V2M] + ARM_SPI_BASE); } build_header(linker, table_data, (void *)(table_data->data + madt_start), "APIC", table_data->len - madt_start, 3, NULL, NULL); }