The capability alows us to express x2APIC destinations. Signed-off-by: Radim Krčmář <rkrc...@redhat.com> --- include/sysemu/kvm.h | 1 + kvm-all.c | 14 +++++++++++++- target-i386/kvm.c | 4 ++++ 3 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h index b7a20eb6ae69..e356438fdf5f 100644 --- a/include/sysemu/kvm.h +++ b/include/sysemu/kvm.h @@ -213,6 +213,7 @@ int kvm_has_pit_state2(void); int kvm_has_many_ioeventfds(void); int kvm_has_gsi_routing(void); int kvm_has_intx_set_mask(void); +bool kvm_has_msi_x2apic(void); int kvm_init_vcpu(CPUState *cpu); int kvm_cpu_exec(CPUState *cpu); diff --git a/kvm-all.c b/kvm-all.c index 8106efb19519..270152615fc2 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -81,6 +81,7 @@ struct KVMState #endif int many_ioeventfds; int intx_set_mask; + bool msi_x2apic; /* The man page (and posix) say ioctl numbers are signed int, but * they're not. Linux, glibc and *BSD all treat ioctl numbers as * unsigned, and treating them as signed here can break things */ @@ -1143,6 +1144,9 @@ int kvm_irqchip_send_msi(KVMState *s, MSIMessage msg) msi.address_hi = msg.address >> 32; msi.data = le32_to_cpu(msg.data); msi.flags = 0; + if (kvm_has_msi_x2apic()) { + msi.flags |= KVM_SIGNAL_MSI_X2APIC; + } memset(msi.pad, 0, sizeof(msi.pad)); return kvm_vm_ioctl(s, KVM_SIGNAL_MSI, &msi); @@ -1159,7 +1163,8 @@ int kvm_irqchip_send_msi(KVMState *s, MSIMessage msg) route = g_malloc0(sizeof(KVMMSIRoute)); route->kroute.gsi = virq; - route->kroute.type = KVM_IRQ_ROUTING_MSI; + route->kroute.type = kvm_has_msi_x2apic() ? KVM_IRQ_ROUTING_MSI_X2APIC + : KVM_IRQ_ROUTING_MSI; route->kroute.flags = 0; route->kroute.u.msi.address_lo = (uint32_t)msg.address; route->kroute.u.msi.address_hi = msg.address >> 32; @@ -1623,6 +1628,8 @@ static int kvm_init(MachineState *ms) s->intx_set_mask = kvm_check_extension(s, KVM_CAP_PCI_2_3); + s->msi_x2apic = kvm_check_extension(s, KVM_CAP_MSI_X2APIC); + s->irq_set_ioctl = KVM_IRQ_LINE; if (kvm_check_extension(s, KVM_CAP_IRQ_INJECT_STATUS)) { s->irq_set_ioctl = KVM_IRQ_LINE_STATUS; @@ -2104,6 +2111,11 @@ int kvm_has_intx_set_mask(void) return kvm_state->intx_set_mask; } +bool kvm_has_msi_x2apic(void) +{ + return kvm_state->msi_x2apic; +} + void kvm_setup_guest_memory(void *start, size_t size) { if (!kvm_has_sync_mmu()) { diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 80b325146a5e..4c9c53ad3e76 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -3351,6 +3351,10 @@ int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, route->u.msi.address_hi = dst.address >> VTD_MSI_ADDR_HI_SHIFT; route->u.msi.address_lo = dst.address & VTD_MSI_ADDR_LO_MASK; route->u.msi.data = dst.data; + + if (kvm_has_msi_x2apic()) { + route->type = KVM_IRQ_ROUTING_MSI_X2APIC; + } } return 0; -- 2.8.2