[PATCH 2/3] x86/apic: Clean up the names of legacy irq mode setting related functions

Baoquan He bhe at redhat.com
Tue Jul 19 19:58:02 PDT 2016


X86 MP spec defines 3 different interrupt modes:
  1) PIC Mode—bypasses all APIC components and forces the system to
     operate in single-processor mode.
  2) Virtual Wire Mode—uses an APIC as a virtual wire, but otherwise
     operates the same as PIC Mode.
  3) Symmetric I/O Mode—enables the system to operate with more than
     one processor.

The current disconnect_bsp_APIC includes two parts: one is to set system
as PIC mode if it's available, the other is to change system back to
Virtual Wire mode. Only PIC mode will detach the APIC from the interrupt
system, Virtual Wire mode doesn't.

Besides Virutal Wire mode has two kinds: one is only setting Local APIC
as Virtual Wire mode and interrupts are delivered from the PIC to the
CPU which Local APIC connected to, the other is both Loca APIC and IO-APIC
need be set as Virtual Wire mode.

So based on above knowledge, take IO-APIC Virtual Wire mode setting code
out and wrap it inot a new function ioapic_set_virtual_wire_mode. Meanwhile
change the name of disconnect_bsp_APIC as lapic_set_legacy_irq_mode. These
makes the legacy irq mode setting more understandable.

Signed-off-by: Baoquan He <bhe at redhat.com>
---
 arch/x86/include/asm/apic.h    |  2 +-
 arch/x86/include/asm/io_apic.h |  5 ++---
 arch/x86/kernel/apic/apic.c    | 11 ++++++-----
 arch/x86/kernel/apic/io_apic.c | 17 ++++++++++-------
 arch/x86/kernel/x86_init.c     |  2 +-
 drivers/iommu/irq_remapping.c  |  2 +-
 6 files changed, 21 insertions(+), 18 deletions(-)

diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index bc27611..dfe4598 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -125,7 +125,7 @@ extern int get_physical_broadcast(void);
 
 extern int lapic_get_maxlvt(void);
 extern void clear_local_APIC(void);
-extern void disconnect_bsp_APIC(int virt_wire_setup);
+extern void lapic_set_legacy_irq_mode(int virt_wire_setup);
 extern void disable_local_APIC(void);
 extern void lapic_shutdown(void);
 extern void sync_Arb_IDs(void);
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index d15192e..1aed995 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -182,7 +182,7 @@ extern void disable_ioapic_support(void);
 
 extern void __init io_apic_init_mappings(void);
 extern unsigned int native_io_apic_read(unsigned int apic, unsigned int reg);
-extern void native_disable_io_apic(void);
+extern void switch_to_legacy_irq_mode(void);
 
 static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg)
 {
@@ -192,7 +192,6 @@ static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg)
 extern void setup_IO_APIC(void);
 extern void enable_IO_APIC(void);
 extern void clear_IO_APIC (void);
-extern void switch_to_legacy_irq_mode(void);
 extern void setup_ioapic_dest(void);
 extern int IO_APIC_get_PCI_irq_vector(int bus, int devfn, int pin);
 extern void print_IO_APICs(void);
@@ -229,7 +228,7 @@ static inline void mp_save_irq(struct mpc_intsrc *m) { }
 static inline void disable_ioapic_support(void) { }
 static inline void io_apic_init_mappings(void) { }
 #define native_io_apic_read		NULL
-#define native_disable_io_apic		NULL
+#define switch_to_legacy_irq_mode	NULL
 
 static inline void setup_IO_APIC(void) { }
 static inline void enable_IO_APIC(void) { }
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index 60078a6..9bb2770 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -1934,13 +1934,14 @@ static void __init connect_bsp_APIC(void)
 }
 
 /**
- * disconnect_bsp_APIC - detach the APIC from the interrupt system
- * @virt_wire_setup:	indicates, whether virtual wire mode is selected
+ * lapic_set_legacy_irq_mode - switch Local APIC back to be legacy irq mode.
+ * @virt_wire_setup:   indicates, whether virtual wire mode is selected
  *
- * Virtual wire mode is necessary to deliver legacy interrupts even when the
- * APIC is disabled.
+ * If PIC mode is available, LAPIC need be disconnected with CPU. Otherwise
+ * enable LAPIC and set it to be virtual wire mode. However if IO-APIC has
+ * been virtual wire mode, LVT0 of LAPIC need be masked.
  */
-void disconnect_bsp_APIC(int virt_wire_setup)
+void lapic_set_legacy_irq_mode(int virt_wire_setup)
 {
 	unsigned int value;
 
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index d8f5cbe..f3f3abe 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -1430,7 +1430,7 @@ void __init enable_IO_APIC(void)
 	clear_IO_APIC();
 }
 
-void native_disable_io_apic(void)
+static void ioapic_set_virtual_wire_mode(void)
 {
 	/*
 	 * If the i8259 is routed through an IOAPIC
@@ -1453,21 +1453,24 @@ void native_disable_io_apic(void)
 		 */
 		ioapic_write_entry(ioapic_i8259.apic, ioapic_i8259.pin, entry);
 	}
-
-	if (boot_cpu_has(X86_FEATURE_APIC) || apic_from_smp_config())
-		disconnect_bsp_APIC(ioapic_i8259.pin != -1);
 }
 
 /*
- * Not an __init, needed by kexec/kdump code.
- * For safety IO-APIC and Local APIC need be cleared before this.
+ * In legacy irq mode, full DOS compatibility with the uniprocessor PC/AT is
+ * provided by using the APICs in conjunction with standard 8259A-equivalent
+ * programmable interrupt controllers (PICs). It's necessary to deliver legacy
+ * interrupts even when APIC mode is not enabled. This is required by kexec/
+ * kdump before enter into the 2nd kernel.
  */
 void switch_to_legacy_irq_mode(void)
 {
 	if (!nr_legacy_irqs())
 		return;
 
-	x86_io_apic_ops.disable();
+	ioapic_set_virtual_wire_mode();
+
+	if (boot_cpu_has(X86_FEATURE_APIC) || apic_from_smp_config())
+		lapic_set_legacy_irq_mode(ioapic_i8259.pin != -1);
 }
 
 #ifdef CONFIG_X86_32
diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c
index dad5fe9..1177c64 100644
--- a/arch/x86/kernel/x86_init.c
+++ b/arch/x86/kernel/x86_init.c
@@ -138,5 +138,5 @@ void arch_restore_msi_irqs(struct pci_dev *dev)
 
 struct x86_io_apic_ops x86_io_apic_ops = {
 	.read			= native_io_apic_read,
-	.disable		= native_disable_io_apic,
+	.disable		= switch_to_legacy_irq_mode,
 };
diff --git a/drivers/iommu/irq_remapping.c b/drivers/iommu/irq_remapping.c
index 49721b4..751472d 100644
--- a/drivers/iommu/irq_remapping.c
+++ b/drivers/iommu/irq_remapping.c
@@ -37,7 +37,7 @@ static void irq_remapping_disable_io_apic(void)
 	 * now.
 	 */
 	if (boot_cpu_has(X86_FEATURE_APIC) || apic_from_smp_config())
-		disconnect_bsp_APIC(0);
+		lapic_set_legacy_irq_mode(0);
 }
 
 static void __init irq_remapping_modify_x86_ops(void)
-- 
2.5.5




More information about the kexec mailing list