x86/apic/ipi: Tidy up the code and fixup comments
authorThomas Gleixner <tglx@linutronix.de>
Tue, 8 Aug 2023 22:04:03 +0000 (15:04 -0700)
committerDave Hansen <dave.hansen@linux.intel.com>
Wed, 9 Aug 2023 18:58:27 +0000 (11:58 -0700)
Replace the undecodable comment on top of the function, replace the space
consuming zero content comments with useful ones and tidy up the
implementation to prevent further eye bleed.

Make __default_send_IPI_shortcut() static as it has no other users.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Tested-by: Michael Kelley <mikelley@microsoft.com>
Tested-by: Sohil Mehta <sohil.mehta@intel.com>
Tested-by: Juergen Gross <jgross@suse.com> # Xen PV (dom0 and unpriv. guest)
arch/x86/kernel/apic/ipi.c
arch/x86/kernel/apic/local.h

index 2ff9cf9aa2efb3de1222dfb2aaea957cde405ee7..614ac557f5e4e2c90d3f8a63a1bbc9b2c8db94f7 100644 (file)
@@ -108,68 +108,58 @@ static inline void __xapic_wait_icr_idle(void)
                cpu_relax();
 }
 
-void __default_send_IPI_shortcut(unsigned int shortcut, int vector)
+/*
+ * This is safe against interruption because it only writes the lower 32
+ * bits of the APIC_ICR register. The destination field is ignored for
+ * short hand IPIs.
+ *
+ *  wait_icr_idle()
+ *  write(ICR2, dest)
+ *  NMI
+ *     wait_icr_idle()
+ *     write(ICR)
+ *     wait_icr_idle()
+ *  write(ICR)
+ *
+ * This function does not need to disable interrupts as there is no ICR2
+ * interaction. The memory write is direct except when the machine is
+ * affected by the 11AP Pentium erratum, which turns the plain write into
+ * an XCHG operation.
+ */
+static void __default_send_IPI_shortcut(unsigned int shortcut, int vector)
 {
        /*
-        * Subtle. In the case of the 'never do double writes' workaround
-        * we have to lock out interrupts to be safe.  As we don't care
-        * of the value read we use an atomic rmw access to avoid costly
-        * cli/sti.  Otherwise we use an even cheaper single atomic write
-        * to the APIC.
-        */
-       unsigned int cfg;
-
-       /*
-        * Wait for idle.
+        * Wait for the previous ICR command to complete.  Use
+        * safe_apic_wait_icr_idle() for the NMI vector as there have been
+        * issues where otherwise the system hangs when the panic CPU tries
+        * to stop the others before launching the kdump kernel.
         */
        if (unlikely(vector == NMI_VECTOR))
                safe_apic_wait_icr_idle();
        else
                __xapic_wait_icr_idle();
 
-       /*
-        * No need to touch the target chip field. Also the destination
-        * mode is ignored when a shorthand is used.
-        */
-       cfg = __prepare_ICR(shortcut, vector, 0);
-
-       /*
-        * Send the IPI. The write to APIC_ICR fires this off.
-        */
-       native_apic_mem_write(APIC_ICR, cfg);
+       /* Destination field (ICR2) and the destination mode are ignored */
+       native_apic_mem_write(APIC_ICR, __prepare_ICR(shortcut, vector, 0));
 }
 
 /*
  * This is used to send an IPI with no shorthand notation (the destination is
  * specified in bits 56 to 63 of the ICR).
  */
-void __default_send_IPI_dest_field(unsigned int mask, int vector, unsigned int dest)
+void __default_send_IPI_dest_field(unsigned int dest_mask, int vector,
+                                  unsigned int dest_mode)
 {
-       unsigned long cfg;
-
-       /*
-        * Wait for idle.
-        */
+       /* See comment in __default_send_IPI_shortcut() */
        if (unlikely(vector == NMI_VECTOR))
                safe_apic_wait_icr_idle();
        else
                __xapic_wait_icr_idle();
 
-       /*
-        * prepare target chip field
-        */
-       cfg = __prepare_ICR2(mask);
-       native_apic_mem_write(APIC_ICR2, cfg);
-
-       /*
-        * program the ICR
-        */
-       cfg = __prepare_ICR(0, vector, dest);
-
-       /*
-        * Send the IPI. The write to APIC_ICR fires this off.
-        */
-       native_apic_mem_write(APIC_ICR, cfg);
+       /* Set the IPI destination field in the ICR */
+       native_apic_mem_write(APIC_ICR2, __prepare_ICR2(dest_mask));
+       /* Send it with the proper destination mode */
+       native_apic_mem_write(APIC_ICR, __prepare_ICR(0, vector, dest_mode));
 }
 
 void default_send_IPI_single_phys(int cpu, int vector)
index 0c477110baaf8eea2bedd8fa2d9972704df9e2fc..5b0a0e78ba6ce97475dbb7c6cdca8b0b65ee5fda 100644 (file)
@@ -44,8 +44,6 @@ static inline unsigned int __prepare_ICR(unsigned int shortcut, int vector,
 
 void default_init_apic_ldr(void);
 
-void __default_send_IPI_shortcut(unsigned int shortcut, int vector);
-
 /*
  * This is used to send an IPI with no shorthand notation (the destination is
  * specified in bits 56 to 63 of the ICR).