mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-03 07:43:54 -06:00
kvm: x86: add support for KVM_CAP_SPLIT_IRQCHIP
This patch adds support for split IRQ chip mode. When KVM_CAP_SPLIT_IRQCHIP is enabled: 1.) The PIC, PIT, and IOAPIC are implemented in userspace while the LAPIC is implemented by KVM. 2.) The software IOAPIC delivers interrupts to the KVM LAPIC via kvm_set_irq. Interrupt delivery is configured via the MSI routing table, for which routes are reserved in target-i386/kvm.c then configured in hw/intc/ioapic.c 3.) KVM delivers IOAPIC EOIs via a new exit KVM_EXIT_IOAPIC_EOI, which is handled in target-i386/kvm.c and relayed to the software IOAPIC via ioapic_eoi_broadcast. Signed-off-by: Matt Gingell <gingell@google.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
32c18a2dba
commit
15eafc2e60
11 changed files with 148 additions and 14 deletions
|
@ -39,6 +39,7 @@
|
|||
#include "exec/ioport.h"
|
||||
#include "standard-headers/asm-x86/hyperv.h"
|
||||
#include "hw/pci/pci.h"
|
||||
#include "hw/pci/msi.h"
|
||||
#include "migration/migration.h"
|
||||
#include "exec/memattrs.h"
|
||||
|
||||
|
@ -2597,7 +2598,7 @@ void kvm_arch_pre_run(CPUState *cpu, struct kvm_run *run)
|
|||
}
|
||||
}
|
||||
|
||||
if (!kvm_irqchip_in_kernel()) {
|
||||
if (!kvm_pic_in_kernel()) {
|
||||
qemu_mutex_lock_iothread();
|
||||
}
|
||||
|
||||
|
@ -2615,7 +2616,7 @@ void kvm_arch_pre_run(CPUState *cpu, struct kvm_run *run)
|
|||
}
|
||||
}
|
||||
|
||||
if (!kvm_irqchip_in_kernel()) {
|
||||
if (!kvm_pic_in_kernel()) {
|
||||
/* Try to inject an interrupt if the guest can accept it */
|
||||
if (run->ready_for_interrupt_injection &&
|
||||
(cpu->interrupt_request & CPU_INTERRUPT_HARD) &&
|
||||
|
@ -3017,6 +3018,10 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
|
|||
case KVM_EXIT_HYPERV:
|
||||
ret = kvm_hv_handle_exit(cpu, &run->hyperv);
|
||||
break;
|
||||
case KVM_EXIT_IOAPIC_EOI:
|
||||
ioapic_eoi_broadcast(run->eoi.vector);
|
||||
ret = 0;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason);
|
||||
ret = -1;
|
||||
|
@ -3051,6 +3056,39 @@ void kvm_arch_init_irq_routing(KVMState *s)
|
|||
*/
|
||||
kvm_msi_via_irqfd_allowed = true;
|
||||
kvm_gsi_routing_allowed = true;
|
||||
|
||||
if (kvm_irqchip_is_split()) {
|
||||
int i;
|
||||
|
||||
/* If the ioapic is in QEMU and the lapics are in KVM, reserve
|
||||
MSI routes for signaling interrupts to the local apics. */
|
||||
for (i = 0; i < IOAPIC_NUM_PINS; i++) {
|
||||
struct MSIMessage msg = { 0x0, 0x0 };
|
||||
if (kvm_irqchip_add_msi_route(s, msg, NULL) < 0) {
|
||||
error_report("Could not enable split IRQ mode.");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int kvm_arch_irqchip_create(MachineState *ms, KVMState *s)
|
||||
{
|
||||
int ret;
|
||||
if (machine_kernel_irqchip_split(ms)) {
|
||||
ret = kvm_vm_enable_cap(s, KVM_CAP_SPLIT_IRQCHIP, 0, 24);
|
||||
if (ret) {
|
||||
error_report("Could not enable split irqchip mode: %s\n",
|
||||
strerror(-ret));
|
||||
exit(1);
|
||||
} else {
|
||||
DPRINTF("Enabled KVM_CAP_SPLIT_IRQCHIP\n");
|
||||
kvm_split_irqchip = true;
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Classic KVM device assignment interface. Will remain x86 only. */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue