x86/irq: Set up per host CPU posted interrupt descriptors
authorJacob Pan <jacob.jun.pan@linux.intel.com>
Tue, 23 Apr 2024 17:41:08 +0000 (10:41 -0700)
committerThomas Gleixner <tglx@linutronix.de>
Mon, 29 Apr 2024 22:54:42 +0000 (00:54 +0200)
To support posted MSIs, create a posted interrupt descriptor (PID) for each
host CPU. Later on, when setting up interrupt affinity, the IOMMU's
interrupt remapping table entry (IRTE) will point to the physical address
of the matching CPU's PID.

Each PID is initialized with the owner CPU's physical APICID as the
destination.

Originally-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Jacob Pan <jacob.jun.pan@linux.intel.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lore.kernel.org/r/20240423174114.526704-7-jacob.jun.pan@linux.intel.com
arch/x86/include/asm/hardirq.h
arch/x86/include/asm/posted_intr.h
arch/x86/kernel/cpu/common.c
arch/x86/kernel/irq.c

index fbc7722b87d1fd40f244d697fde2692a464df69f..e7ab594b3a7a09d66be7e60bdab61d6fe908510f 100644 (file)
@@ -48,6 +48,9 @@ typedef struct {
 
 DECLARE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat);
 
+#ifdef CONFIG_X86_POSTED_MSI
+DECLARE_PER_CPU_ALIGNED(struct pi_desc, posted_msi_pi_desc);
+#endif
 #define __ARCH_IRQ_STAT
 
 #define inc_irq_stat(member)   this_cpu_inc(irq_stat.member)
index 20e31891de15f7bd55c69ec4cdd4320aee71648c..6f84f6739d9977641bc63e22d4247dc0e237b6b0 100644 (file)
@@ -91,4 +91,10 @@ static inline void __pi_clear_sn(struct pi_desc *pi_desc)
        pi_desc->notifications &= ~BIT(POSTED_INTR_SN);
 }
 
+#ifdef CONFIG_X86_POSTED_MSI
+extern void intel_posted_msi_init(void);
+#else
+static inline void intel_posted_msi_init(void) {};
+#endif /* X86_POSTED_MSI */
+
 #endif /* _X86_POSTED_INTR_H */
index 605c26c009c8ac61c8560231ea6b35d2381ff2aa..25ef145586c62ac807b5b593c75ec51ce09b9bb0 100644 (file)
@@ -68,6 +68,7 @@
 #include <asm/traps.h>
 #include <asm/sev.h>
 #include <asm/tdx.h>
+#include <asm/posted_intr.h>
 
 #include "cpu.h"
 
@@ -2227,6 +2228,8 @@ void cpu_init(void)
                barrier();
 
                x2apic_setup();
+
+               intel_posted_msi_init();
        }
 
        mmgrab(&init_mm);
index 35fde0107901d61f58dd08af4988f7ce7b2530b3..dbb3a19b3004da344baac744a1cec4cef492f3ff 100644 (file)
@@ -22,6 +22,8 @@
 #include <asm/desc.h>
 #include <asm/traps.h>
 #include <asm/thermal.h>
+#include <asm/posted_intr.h>
+#include <asm/irq_remapping.h>
 
 #define CREATE_TRACE_POINTS
 #include <asm/trace/irq_vectors.h>
@@ -334,6 +336,27 @@ DEFINE_IDTENTRY_SYSVEC_SIMPLE(sysvec_kvm_posted_intr_nested_ipi)
 }
 #endif
 
+#ifdef CONFIG_X86_POSTED_MSI
+
+/* Posted Interrupt Descriptors for coalesced MSIs to be posted */
+DEFINE_PER_CPU_ALIGNED(struct pi_desc, posted_msi_pi_desc);
+
+void intel_posted_msi_init(void)
+{
+       u32 destination;
+       u32 apic_id;
+
+       this_cpu_write(posted_msi_pi_desc.nv, POSTED_MSI_NOTIFICATION_VECTOR);
+
+       /*
+        * APIC destination ID is stored in bit 8:15 while in XAPIC mode.
+        * VT-d spec. CH 9.11
+        */
+       apic_id = this_cpu_read(x86_cpu_to_apicid);
+       destination = x2apic_enabled() ? apic_id : apic_id << 8;
+       this_cpu_write(posted_msi_pi_desc.ndst, destination);
+}
+#endif /* X86_POSTED_MSI */
 
 #ifdef CONFIG_HOTPLUG_CPU
 /* A cpu has been removed from cpu_online_mask.  Reset irq affinities. */