diff options
author | David Woodhouse <dwmw2@infradead.org> | 2020-10-05 15:18:19 +0100 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2020-12-10 12:15:00 -0500 |
commit | c1bb5418e32ec70c72af332354b5963eab7a5579 (patch) | |
tree | 5450a1ff1d4fcf48602f1c21e49852c4f9bb7e73 /hw/i386 | |
parent | 75b208c28316095c4685e8596ceb9e3f656592e2 (diff) |
target/i386: Support up to 32768 CPUs without IRQ remapping
The IOAPIC has an 'Extended Destination ID' field in its RTE, which maps
to bits 11-4 of the MSI address. Since those address bits fall within a
given 4KiB page they were historically non-trivial to use on real hardware.
The Intel IOMMU uses the lowest bit to indicate a remappable format MSI,
and then the remaining 7 bits are part of the index.
Where the remappable format bit isn't set, we can actually use the other
seven to allow external (IOAPIC and MSI) interrupts to reach up to 32768
CPUs instead of just the 255 permitted on bare metal.
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
Message-Id: <78097f9218300e63e751e077a0a5ca029b56ba46.camel@infradead.org>
[Fix UBSAN warning. - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Diffstat (limited to 'hw/i386')
-rw-r--r-- | hw/i386/kvm/apic.c | 7 | ||||
-rw-r--r-- | hw/i386/pc.c | 16 |
2 files changed, 13 insertions, 10 deletions
diff --git a/hw/i386/kvm/apic.c b/hw/i386/kvm/apic.c index dd29906061..b226b674e8 100644 --- a/hw/i386/kvm/apic.c +++ b/hw/i386/kvm/apic.c @@ -183,6 +183,13 @@ static void kvm_send_msi(MSIMessage *msg) { int ret; + /* + * The message has already passed through interrupt remapping if enabled, + * but the legacy extended destination ID in low bits still needs to be + * handled. + */ + msg->address = kvm_swizzle_msi_ext_dest_id(msg->address); + ret = kvm_irqchip_send_msi(kvm_state, *msg); if (ret < 0) { fprintf(stderr, "KVM: injection failed, MSI lost (%s)\n", diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 9e29f3792b..640fb5b0b7 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -104,6 +104,7 @@ const size_t pc_compat_5_2_len = G_N_ELEMENTS(pc_compat_5_2); GlobalProperty pc_compat_5_1[] = { { "ICH9-LPC", "x-smi-cpu-hotplug", "off" }, + { TYPE_X86_CPU, "kvm-msi-ext-dest-id", "off" }, }; const size_t pc_compat_5_1_len = G_N_ELEMENTS(pc_compat_5_1); @@ -796,17 +797,12 @@ void pc_machine_done(Notifier *notifier, void *data) fw_cfg_modify_i16(x86ms->fw_cfg, FW_CFG_NB_CPUS, x86ms->boot_cpus); } - if (x86ms->apic_id_limit > 255 && !xen_enabled()) { - IntelIOMMUState *iommu = INTEL_IOMMU_DEVICE(x86_iommu_get_default()); - if (!iommu || !x86_iommu_ir_supported(X86_IOMMU_DEVICE(iommu)) || - iommu->intr_eim != ON_OFF_AUTO_ON) { - error_report("current -smp configuration requires " - "Extended Interrupt Mode enabled. " - "You can add an IOMMU using: " - "-device intel-iommu,intremap=on,eim=on"); - exit(EXIT_FAILURE); - } + if (x86ms->apic_id_limit > 255 && !xen_enabled() && + !kvm_irqchip_in_kernel()) { + error_report("current -smp configuration requires kernel " + "irqchip support."); + exit(EXIT_FAILURE); } } |