diff options
Diffstat (limited to 'target-i386')
-rw-r--r-- | target-i386/cpu.c | 2 | ||||
-rw-r--r-- | target-i386/kvm.c | 42 | ||||
-rw-r--r-- | target-i386/kvm_i386.h | 2 |
3 files changed, 43 insertions, 3 deletions
diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 92f7cc1f7d..0d447b5690 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -2743,7 +2743,7 @@ static void x86_cpu_apic_create(X86CPU *cpu, Error **errp) APICCommonState *apic; const char *apic_type = "apic"; - if (kvm_irqchip_in_kernel()) { + if (kvm_apic_in_kernel()) { apic_type = "kvm-apic"; } else if (xen_enabled()) { apic_type = "xen-apic"; diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 7692b5984d..7b01328ffe 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -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. */ diff --git a/target-i386/kvm_i386.h b/target-i386/kvm_i386.h index c1b312ba2a..42b00af1b1 100644 --- a/target-i386/kvm_i386.h +++ b/target-i386/kvm_i386.h @@ -13,6 +13,8 @@ #include "sysemu/kvm.h" +#define kvm_apic_in_kernel() (kvm_irqchip_in_kernel()) + bool kvm_allows_irq0_override(void); bool kvm_has_smm(void); void kvm_synchronize_all_tsc(void); |