We need a way to pass 32 bit APIC ID. Intel® Virtualization Technology for Directed I/O, 5.1.8 Programming in Intel® 64 x2APIC Mode, specifies that Remapping Hardware is configured with APIC ID 31:8 in Upper Address Register 31:8. This patch adopts that method and applies it to KVM_SIGNAL_MSI and GSI routes. Signed-off-by: Radim Krčmář <rkrcmar@xxxxxxxxxx> --- Documentation/virtual/kvm/api.txt | 11 ++++++++++- arch/x86/kvm/irq_comm.c | 9 +++++++-- arch/x86/kvm/vmx.c | 3 ++- arch/x86/kvm/x86.c | 1 + include/uapi/linux/kvm.h | 5 +++++ virt/kvm/irqchip.c | 6 +++++- 6 files changed, 30 insertions(+), 5 deletions(-) diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt index 4d0542c5206b..07bcedc0ba09 100644 --- a/Documentation/virtual/kvm/api.txt +++ b/Documentation/virtual/kvm/api.txt @@ -1461,6 +1461,7 @@ struct kvm_irq_routing_entry { #define KVM_IRQ_ROUTING_MSI 2 #define KVM_IRQ_ROUTING_S390_ADAPTER 3 #define KVM_IRQ_ROUTING_HV_SINT 4 +#define KVM_IRQ_ROUTING_MSI_X2APIC 5 No flags are specified so far, the corresponding field must be set to zero. @@ -1489,6 +1490,11 @@ struct kvm_irq_routing_hv_sint { __u32 sint; }; +KVM_IRQ_ROUTING_MSI_X2APIC can be used if KVM_CAP_MSI_X2APIC is present. +The entry uses struct kvm_irq_routing_msi and stores APIC ID bits 8-31 in +address_hi bits 8-31. + + 4.53 KVM_ASSIGN_SET_MSIX_NR (deprecated) Capability: none @@ -2166,7 +2172,10 @@ struct kvm_msi { __u8 pad[16]; }; -No flags are defined so far. The corresponding field must be 0. +Valid flags are 0 and bitwise OR of any following: +* KVM_SIGNAL_MSI_X2APIC + - valid with capability KVM_CAP_MSI_X2APIC + - address_hi bits 8-31 contain APIC ID bits 8-31 4.71 KVM_CREATE_PIT2 diff --git a/arch/x86/kvm/irq_comm.c b/arch/x86/kvm/irq_comm.c index 3d17eee0987b..b9595251834b 100644 --- a/arch/x86/kvm/irq_comm.c +++ b/arch/x86/kvm/irq_comm.c @@ -117,6 +117,8 @@ void kvm_set_msi_irq(struct kvm_kernel_irq_routing_entry *e, irq->dest_id = (e->msi.address_lo & MSI_ADDR_DEST_ID_MASK) >> MSI_ADDR_DEST_ID_SHIFT; + if (e->type == KVM_IRQ_ROUTING_MSI_X2APIC) + irq->dest_id |= MSI_ADDR_EXT_DEST_ID(e->msi.address_hi); irq->vector = (e->msi.data & MSI_DATA_VECTOR_MASK) >> MSI_DATA_VECTOR_SHIFT; irq->dest_mode = (1 << MSI_ADDR_DEST_MODE_SHIFT) & e->msi.address_lo; @@ -150,7 +152,8 @@ int kvm_arch_set_irq_inatomic(struct kvm_kernel_irq_routing_entry *e, struct kvm_lapic_irq irq; int r; - if (unlikely(e->type != KVM_IRQ_ROUTING_MSI)) + if (unlikely(e->type != KVM_IRQ_ROUTING_MSI && + e->type != KVM_IRQ_ROUTING_MSI_X2APIC)) return -EWOULDBLOCK; kvm_set_msi_irq(e, &irq); @@ -281,6 +284,7 @@ int kvm_set_routing_entry(struct kvm_kernel_irq_routing_entry *e, goto out; break; case KVM_IRQ_ROUTING_MSI: + case KVM_IRQ_ROUTING_MSI_X2APIC: e->set = kvm_set_msi; e->msi.address_lo = ue->u.msi.address_lo; e->msi.address_hi = ue->u.msi.address_hi; @@ -393,7 +397,8 @@ void kvm_scan_ioapic_routes(struct kvm_vcpu *vcpu, hlist_for_each_entry(entry, &table->map[i], link) { struct kvm_lapic_irq irq; - if (entry->type != KVM_IRQ_ROUTING_MSI) + if (entry->type != KVM_IRQ_ROUTING_MSI && + entry->type != KVM_IRQ_ROUTING_MSI_X2APIC) continue; kvm_set_msi_irq(entry, &irq); diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 133679d520af..35df8d757d1d 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -10829,7 +10829,8 @@ static int vmx_update_pi_irte(struct kvm *kvm, unsigned int host_irq, BUG_ON(guest_irq >= irq_rt->nr_rt_entries); hlist_for_each_entry(e, &irq_rt->map[guest_irq], link) { - if (e->type != KVM_IRQ_ROUTING_MSI) + if (e->type != KVM_IRQ_ROUTING_MSI && + e->type != KVM_IRQ_ROUTING_MSI_X2APIC) continue; /* * VT-d PI cannot support posting multicast/broadcast diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 9b7798c7b210..86d1eb1c9d8b 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -2567,6 +2567,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) case KVM_CAP_DISABLE_QUIRKS: case KVM_CAP_SET_BOOT_CPU_ID: case KVM_CAP_SPLIT_IRQCHIP: + case KVM_CAP_MSI_X2APIC: #ifdef CONFIG_KVM_DEVICE_ASSIGNMENT case KVM_CAP_ASSIGN_DEV_IRQ: case KVM_CAP_PCI_2_3: diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index a7f1f8032ec1..af1abec5f41d 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -865,6 +865,7 @@ struct kvm_ppc_smmu_info { #define KVM_CAP_SPAPR_TCE_64 125 #define KVM_CAP_ARM_PMU_V3 126 #define KVM_CAP_VCPU_ATTRIBUTES 127 +#define KVM_CAP_MSI_X2APIC 128 #ifdef KVM_CAP_IRQ_ROUTING @@ -898,6 +899,7 @@ struct kvm_irq_routing_hv_sint { #define KVM_IRQ_ROUTING_MSI 2 #define KVM_IRQ_ROUTING_S390_ADAPTER 3 #define KVM_IRQ_ROUTING_HV_SINT 4 +#define KVM_IRQ_ROUTING_MSI_X2APIC 5 /* KVM_CAP_MSI_X2APIC */ struct kvm_irq_routing_entry { __u32 gsi; @@ -1023,6 +1025,9 @@ struct kvm_one_reg { __u64 addr; }; +#define KVM_SIGNAL_MSI_X2APIC (1 << 0) /* KVM_CAP_X2APIC */ +#define KVM_SIGNAL_MSI_FLAGS KVM_SIGNAL_MSI_X2APIC + struct kvm_msi { __u32 address_lo; __u32 address_hi; diff --git a/virt/kvm/irqchip.c b/virt/kvm/irqchip.c index fe84e1a95dd5..39b38b1a2156 100644 --- a/virt/kvm/irqchip.c +++ b/virt/kvm/irqchip.c @@ -62,9 +62,13 @@ int kvm_send_userspace_msi(struct kvm *kvm, struct kvm_msi *msi) { struct kvm_kernel_irq_routing_entry route; - if (!irqchip_in_kernel(kvm) || msi->flags != 0) + if (!irqchip_in_kernel(kvm) || + (msi->flags & ~KVM_SIGNAL_MSI_FLAGS) != 0) return -EINVAL; + /* assignment must copy kvm_set_routing_entry() */ + route.type = msi->flags & KVM_SIGNAL_MSI_X2APIC ? + KVM_IRQ_ROUTING_MSI_X2APIC : KVM_IRQ_ROUTING_MSI; route.msi.address_lo = msi->address_lo; route.msi.address_hi = msi->address_hi; route.msi.data = msi->data; -- 2.8.2 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html