]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
x86/msi: Allow 15-bit MSI dest_id extension ext_dest_id_4.1
authorDavid Woodhouse <dwmw@amazon.co.uk>
Thu, 5 Aug 2021 16:39:23 +0000 (17:39 +0100)
committerDavid Woodhouse <dwmw@amazon.co.uk>
Fri, 6 Aug 2021 17:32:51 +0000 (18:32 +0100)
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 <dwmw@amazon.co.uk>
arch/x86/Kconfig
arch/x86/include/uapi/asm/kvm_para.h
arch/x86/kernel/apic/apic.c
arch/x86/kernel/apic/msi.c

index ffb2cb0495c3282ecf8d6c1fa9addf84ac85523b..f4d8b8563cebc28cbd1fbe0ccd59a6a89e21d53b 100644 (file)
@@ -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.
 
index 94dc8ca434e0863c5170d6bf44afa8860cfbf857..cedd741c16643d3665f30ba38c45580f3c02b9f4 100644 (file)
@@ -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.
index def2e2e523f13823c81c48bb18e4c17d919ccc02..33aba3c48287d0bbaef60281ce7d68ada09b55de 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/acpi_pmtmr.h>
 #include <linux/clockchips.h>
 #include <linux/interrupt.h>
+#include <linux/kvm_para.h>
 #include <linux/bootmem.h>
 #include <linux/ftrace.h>
 #include <linux/ioport.h>
@@ -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();
index d6ba2d660dc52f59945825ef80a66821d5a971a5..6294ebe3ec60b9925b810a79884b3c376581ade5 100644 (file)
@@ -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);