From: David Woodhouse Date: Thu, 5 Aug 2021 16:39:23 +0000 (+0100) Subject: x86/msi: Allow 15-bit MSI dest_id extension X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=766082a96ac7e55f877b696caa19f587744a357b;p=users%2Fdwmw2%2Flinux.git x86/msi: Allow 15-bit MSI dest_id extension This is a minimal adaptation and backport of commits: • 47bea873cf ("x86/msi: Only use high bits of MSI address for DMAR unit") • ab0f59c6f1 ("x86/apic: Support 15 bits of APIC ID in MSI where available") • 5a169bf04c ("x86/kvm: Reserve KVM_FEATURE_MSI_EXT_DEST_ID") • 2e008ffe42 ("x86/kvm: Enable 15-bit extension when KVM_FEATURE_MSI_EXT_DEST_ID detected") • 19e3d60d49 ("x86: Let x2APIC support depend on interrupt remapping or guest support") This allows APIC IDs up to 32767 and uses the ext dest ID bits in MSI messages if the KVM hypervisor advertises the capability. Signed-off-by: David Woodhouse --- diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index ffb2cb0495c32..f4d8b8563cebc 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -341,7 +341,7 @@ config X86_FEATURE_NAMES config X86_X2APIC bool "Support x2apic" - depends on X86_LOCAL_APIC && X86_64 && IRQ_REMAP + depends on X86_LOCAL_APIC && X86_64 ---help--- This enables x2apic support on CPUs that have this feature. diff --git a/arch/x86/include/uapi/asm/kvm_para.h b/arch/x86/include/uapi/asm/kvm_para.h index 94dc8ca434e08..cedd741c16643 100644 --- a/arch/x86/include/uapi/asm/kvm_para.h +++ b/arch/x86/include/uapi/asm/kvm_para.h @@ -24,6 +24,7 @@ #define KVM_FEATURE_STEAL_TIME 5 #define KVM_FEATURE_PV_EOI 6 #define KVM_FEATURE_PV_UNHALT 7 +#define KVM_FEATURE_MSI_EXT_DEST_ID 15 /* The last 8 bits are used to indicate how to interpret the flags field * in pvclock structure. If no bits are set, all flags are ignored. diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index def2e2e523f13..33aba3c48287d 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -1525,7 +1526,12 @@ static __init void try_to_enable_x2apic(int remap_mode) /* IR is required if there is APIC ID > 255 even when running * under KVM */ - if (max_physical_apicid > 255 || + unsigned int max_apic = 255; +#ifdef CONFIG_KVM_GUEST + if (kvm_para_has_feature(KVM_FEATURE_MSI_EXT_DEST_ID)) + max_apic = 32767; +#endif + if (max_physical_apicid > max_apic || !hypervisor_x2apic_available()) { pr_info("x2apic: IRQ remapping doesn't support X2APIC mode\n"); x2apic_disable(); diff --git a/arch/x86/kernel/apic/msi.c b/arch/x86/kernel/apic/msi.c index d6ba2d660dc52..6294ebe3ec60b 100644 --- a/arch/x86/kernel/apic/msi.c +++ b/arch/x86/kernel/apic/msi.c @@ -28,9 +28,6 @@ void native_compose_msi_msg(struct pci_dev *pdev, msg->address_hi = MSI_ADDR_BASE_HI; - if (x2apic_enabled()) - msg->address_hi |= MSI_ADDR_EXT_DEST_ID(dest); - msg->address_lo = MSI_ADDR_BASE_LO | ((apic->irq_dest_mode == 0) ? @@ -48,6 +45,13 @@ void native_compose_msi_msg(struct pci_dev *pdev, MSI_DATA_DELIVERY_FIXED : MSI_DATA_DELIVERY_LOWPRI) | MSI_DATA_VECTOR(cfg->vector); + + if (x2apic_enabled()) { + if (hpet_id == -2) /* DMAR puts it in the high 32 bits */ + msg->address_hi |= MSI_ADDR_EXT_DEST_ID(dest); + else /* With KVM_FEATURE_MSI_EXT_DEST_ID we use the extended dest_id bits */ + msg->address_lo |= MSI_ADDR_EXT_DEST_ID(dest) >> 3; + } } static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, @@ -93,6 +97,8 @@ msi_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force) msg.data |= MSI_DATA_VECTOR(cfg->vector); msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK; msg.address_lo |= MSI_ADDR_DEST_ID(dest); + if (x2apic_enabled()) + msg.address_lo |= MSI_ADDR_EXT_DEST_ID(dest) >> 3; __pci_write_msi_msg(data->msi_desc, &msg); @@ -217,7 +223,7 @@ int arch_setup_dmar_msi(unsigned int irq) int ret; struct msi_msg msg; - ret = msi_compose_msg(NULL, irq, &msg, -1); + ret = msi_compose_msg(NULL, irq, &msg, -2); if (ret < 0) return ret; dmar_msi_write(irq, &msg); @@ -250,6 +256,8 @@ static int hpet_msi_set_affinity(struct irq_data *data, msg.data |= MSI_DATA_VECTOR(cfg->vector); msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK; msg.address_lo |= MSI_ADDR_DEST_ID(dest); + if (x2apic_enabled()) + msg.address_lo |= MSI_ADDR_EXT_DEST_ID(dest) >> 3; hpet_msi_write(data->handler_data, &msg);