aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorGerd Hoffmann <kraxel@redhat.com>2020-12-03 11:54:14 +0100
committerGerd Hoffmann <kraxel@redhat.com>2020-12-10 08:47:44 +0100
commit94c5a606379ddd04beecdb11fb34b51b4b28c7f2 (patch)
tree8da6e8b5c7b6b24b7fe525643d3dab61cd3e1279 /hw
parentceea95cd88c8f90ad93a83bbad4a077590316342 (diff)
x86: add support for second ioapic
Add ioapic_init_secondary to initialize it, wire up in gsi handling and acpi apic table creation. Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Reviewed-by: Igor Mammedov <imammedo@redhat.com> Reviewed-by: Sergio Lopez <slp@redhat.com> Message-id: 20201203105423.10431-4-kraxel@redhat.com
Diffstat (limited to 'hw')
-rw-r--r--hw/i386/acpi-common.c10
-rw-r--r--hw/i386/x86.c21
2 files changed, 31 insertions, 0 deletions
diff --git a/hw/i386/acpi-common.c b/hw/i386/acpi-common.c
index 8a76965406..a6a30e8363 100644
--- a/hw/i386/acpi-common.c
+++ b/hw/i386/acpi-common.c
@@ -103,6 +103,16 @@ void acpi_build_madt(GArray *table_data, BIOSLinker *linker,
io_apic->address = cpu_to_le32(IO_APIC_DEFAULT_ADDRESS);
io_apic->interrupt = cpu_to_le32(0);
+ if (x86ms->ioapic2) {
+ AcpiMadtIoApic *io_apic2;
+ io_apic2 = acpi_data_push(table_data, sizeof *io_apic);
+ io_apic2->type = ACPI_APIC_IO;
+ io_apic2->length = sizeof(*io_apic);
+ io_apic2->io_apic_id = ACPI_BUILD_IOAPIC_ID + 1;
+ io_apic2->address = cpu_to_le32(IO_APIC_SECONDARY_ADDRESS);
+ io_apic2->interrupt = cpu_to_le32(IO_APIC_SECONDARY_IRQBASE);
+ }
+
if (x86ms->apic_xrupt_override) {
intsrcovr = acpi_data_push(table_data, sizeof *intsrcovr);
intsrcovr->type = ACPI_APIC_XRUPT_OVERRIDE;
diff --git a/hw/i386/x86.c b/hw/i386/x86.c
index b67e7b789f..d68a9eaefc 100644
--- a/hw/i386/x86.c
+++ b/hw/i386/x86.c
@@ -598,6 +598,10 @@ void gsi_handler(void *opaque, int n, int level)
case ISA_NUM_IRQS ... IOAPIC_NUM_PINS - 1:
qemu_set_irq(s->ioapic_irq[n], level);
break;
+ case IO_APIC_SECONDARY_IRQBASE
+ ... IO_APIC_SECONDARY_IRQBASE + IOAPIC_NUM_PINS - 1:
+ qemu_set_irq(s->ioapic2_irq[n - IO_APIC_SECONDARY_IRQBASE], level);
+ break;
}
}
@@ -624,6 +628,23 @@ void ioapic_init_gsi(GSIState *gsi_state, const char *parent_name)
}
}
+DeviceState *ioapic_init_secondary(GSIState *gsi_state)
+{
+ DeviceState *dev;
+ SysBusDevice *d;
+ unsigned int i;
+
+ dev = qdev_new(TYPE_IOAPIC);
+ d = SYS_BUS_DEVICE(dev);
+ sysbus_realize_and_unref(d, &error_fatal);
+ sysbus_mmio_map(d, 0, IO_APIC_SECONDARY_ADDRESS);
+
+ for (i = 0; i < IOAPIC_NUM_PINS; i++) {
+ gsi_state->ioapic2_irq[i] = qdev_get_gpio_in(dev, i);
+ }
+ return dev;
+}
+
struct setup_data {
uint64_t next;
uint32_t type;