}
}
+static int microvm_ioapics(MicrovmMachineState *mms)
+{
+ if (!x86_machine_is_acpi_enabled(X86_MACHINE(mms))) {
+ return 1;
+ }
+ if (mms->ioapic2 == ON_OFF_AUTO_OFF) {
+ return 1;
+ }
+ return 2;
+}
+
static void microvm_devices_init(MicrovmMachineState *mms)
{
X86MachineState *x86ms = X86_MACHINE(mms);
ISABus *isa_bus;
ISADevice *rtc_state;
GSIState *gsi_state;
+ int ioapics;
int i;
/* Core components */
-
+ ioapics = microvm_ioapics(mms);
gsi_state = g_malloc0(sizeof(*gsi_state));
- x86ms->gsi = qemu_allocate_irqs(gsi_handler, gsi_state, GSI_NUM_PINS);
+ x86ms->gsi = qemu_allocate_irqs(gsi_handler, gsi_state,
+ IOAPIC_NUM_PINS * ioapics);
isa_bus = isa_bus_new(NULL, get_system_memory(), get_system_io(),
&error_abort);
isa_bus_irqs(isa_bus, x86ms->gsi);
ioapic_init_gsi(gsi_state, "machine");
+ if (ioapics > 1) {
+ x86ms->ioapic2 = ioapic_init_secondary(gsi_state);
+ }
kvmclock_create(true);
mms->virtio_irq_base = 5;
mms->virtio_num_transports = 8;
- if (x86_machine_is_acpi_enabled(x86ms)) {
- mms->pcie_irq_base = 12;
- mms->virtio_irq_base = 16;
+ if (x86ms->ioapic2) {
+ mms->pcie_irq_base = 16; /* 16 -> 19 */
+ /* use second ioapic (24 -> 47) for virtio-mmio irq lines */
+ mms->virtio_irq_base = IO_APIC_SECONDARY_IRQBASE;
+ mms->virtio_num_transports = IOAPIC_NUM_PINS;
+ } else if (x86_machine_is_acpi_enabled(x86ms)) {
+ mms->pcie_irq_base = 12; /* 12 -> 15 */
+ mms->virtio_irq_base = 16; /* 16 -> 23 */
}
for (i = 0; i < mms->virtio_num_transports; i++) {
visit_type_OnOffAuto(v, name, &mms->pcie, errp);
}
+static void microvm_machine_get_ioapic2(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ MicrovmMachineState *mms = MICROVM_MACHINE(obj);
+ OnOffAuto ioapic2 = mms->ioapic2;
+
+ visit_type_OnOffAuto(v, name, &ioapic2, errp);
+}
+
+static void microvm_machine_set_ioapic2(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ MicrovmMachineState *mms = MICROVM_MACHINE(obj);
+
+ visit_type_OnOffAuto(v, name, &mms->ioapic2, errp);
+}
+
static bool microvm_machine_get_isa_serial(Object *obj, Error **errp)
{
MicrovmMachineState *mms = MICROVM_MACHINE(obj);
mms->pit = ON_OFF_AUTO_AUTO;
mms->rtc = ON_OFF_AUTO_AUTO;
mms->pcie = ON_OFF_AUTO_AUTO;
+ mms->ioapic2 = ON_OFF_AUTO_AUTO;
mms->isa_serial = true;
mms->option_roms = true;
mms->auto_kernel_cmdline = true;
object_class_property_set_description(oc, MICROVM_MACHINE_PCIE,
"Enable PCIe");
+ object_class_property_add(oc, MICROVM_MACHINE_IOAPIC2, "OnOffAuto",
+ microvm_machine_get_ioapic2,
+ microvm_machine_set_ioapic2,
+ NULL, NULL);
+ object_class_property_set_description(oc, MICROVM_MACHINE_IOAPIC2,
+ "Enable second IO-APIC");
+
object_class_property_add_bool(oc, MICROVM_MACHINE_ISA_SERIAL,
microvm_machine_get_isa_serial,
microvm_machine_set_isa_serial);
test_data data;
test_acpi_microvm_prepare(&data);
- test_acpi_one(" -machine microvm,acpi=on,rtc=off",
+ test_acpi_one(" -machine microvm,acpi=on,ioapic2=off,rtc=off",
&data);
free_test_data(&data);
}
test_acpi_microvm_prepare(&data);
data.variant = ".usb";
- test_acpi_one(" -machine microvm,acpi=on,usb=on,rtc=off",
+ test_acpi_one(" -machine microvm,acpi=on,ioapic2=off,usb=on,rtc=off",
&data);
free_test_data(&data);
}
test_acpi_microvm_prepare(&data);
data.variant = ".rtc";
- test_acpi_one(" -machine microvm,acpi=on,rtc=on",
+ test_acpi_one(" -machine microvm,acpi=on,ioapic2=off,rtc=on",
&data);
free_test_data(&data);
}
test_acpi_microvm_prepare(&data);
data.variant = ".pcie";
data.tcg_only = true; /* need constant host-phys-bits */
- test_acpi_one(" -machine microvm,acpi=on,rtc=off,pcie=on",
+ test_acpi_one(" -machine microvm,acpi=on,ioapic2=off,rtc=off,pcie=on",
&data);
free_test_data(&data);
}