The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* [KEXEC][PATCH] Modified (smaller) x86 kexec hwfixes patch
@ 2003-02-13 10:40 Suparna Bhattacharya
  2003-02-13 15:09 ` Eric W. Biederman
  0 siblings, 1 reply; 10+ messages in thread
From: Suparna Bhattacharya @ 2003-02-13 10:40 UTC (permalink / raw)
  To: Eric W. Biederman; +Cc: fastboot, linux-kernel, mbligh

[-- Attachment #1: Type: text/plain, Size: 1025 bytes --]

Martin Bligh came up with a simple way to fix the kernel
to enable kexec boot from any CPU. 

Rather than picking up boot cpu information from the MP 
tables (which belong to the previous boot in the case of 
kexec), it just sets it to the cpu its starting on.
(See the changes in arch/i386/kernel/smpboot.c)

This simplifies the the kexec-hwfixes patch, since we
no longer need to move to the boot cpu before stopping
other processors. Which removes a lot of the unconditional
patching of reboot.c and makes it less invasive, thanks to 
Martin. Also, at panic time, cpu migration is something 
that is best avoided.

It would be good if someone could test this out (on SMP)
and confirm it works fine (I tried it on a 4way).

Eric, Do these changes look OK to you ? Did you have
something similar in mind, when you were talking about
enabling the kexec'd kernel to not care about which cpu
it was running on ?

Regards
Suparna


-- 
Suparna Bhattacharya (suparna@in.ibm.com)
Linux Technology Center
IBM Software Labs, India


[-- Attachment #2: kexec-hwfixes.patch --]
[-- Type: text/plain, Size: 6752 bytes --]

diff -ur -X ../../dontdiff linux-2.5.59-kexec/arch/i386/kernel/apic.c linux-2.5.59-kexecfixes/arch/i386/kernel/apic.c
--- linux-2.5.59-kexec/arch/i386/kernel/apic.c	Fri Jan 17 07:53:00 2003
+++ linux-2.5.59-kexecfixes/arch/i386/kernel/apic.c	Thu Feb 13 10:14:44 2003
@@ -23,6 +23,7 @@
 #include <linux/interrupt.h>
 #include <linux/mc146818rtc.h>
 #include <linux/kernel_stat.h>
+#include <linux/reboot.h>
 
 #include <asm/atomic.h>
 #include <asm/smp.h>
@@ -155,6 +156,36 @@
 		outb(0x70, 0x22);
 		outb(0x00, 0x23);
 	}
+	else {
+		/* Go back to Virtual Wire compatibility mode */
+		unsigned long value;
+
+		/* For the spurious interrupt use vector F, and enable it */
+		value = apic_read(APIC_SPIV);
+		value &= ~APIC_VECTOR_MASK; 
+		value |= APIC_SPIV_APIC_ENABLED;
+		value |= 0xf;
+		apic_write_around(APIC_SPIV, value);
+
+		/* For LVT0 make it edge triggered, active high, external and enabled */
+		value = apic_read(APIC_LVT0);
+		value &= ~(APIC_MODE_MASK | APIC_SEND_PENDING | 
+			APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR | 
+			APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED );
+		value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING;
+		value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_EXINT);
+		apic_write_around(APIC_LVT0, value);
+		
+		/* For LVT1 make it edge triggered, active high, nmi and enabled */
+		value = apic_read(APIC_LVT1);
+		value &= ~(
+			APIC_MODE_MASK | APIC_SEND_PENDING | 
+			APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR | 
+			APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED);
+		value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING;
+		value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_NMI);
+		apic_write_around(APIC_LVT1, value);
+	}
 }
 
 void disable_local_APIC(void)
@@ -1116,6 +1147,26 @@
 	irq_exit();
 }
 
+void stop_apics(void)
+{
+	/* By resetting the APIC's we disable the nmi watchdog */
+#if CONFIG_SMP
+	/*
+	 * Stop all CPUs and turn off local APICs and the IO-APIC, so
+	 * other OSs see a clean IRQ state.
+	 */
+	smp_send_stop();
+#else
+	disable_local_APIC();
+#endif
+#if defined(CONFIG_X86_IO_APIC)
+	if (smp_found_config) {
+		disable_IO_APIC();
+	}
+#endif
+	disconnect_bsp_APIC();
+}
+
 /*
  * This initializes the IO-APIC and APIC hardware if this is
  * a UP kernel.
diff -ur -X ../../dontdiff linux-2.5.59-kexec/arch/i386/kernel/i8259.c linux-2.5.59-kexecfixes/arch/i386/kernel/i8259.c
--- linux-2.5.59-kexec/arch/i386/kernel/i8259.c	Fri Jan 17 07:52:43 2003
+++ linux-2.5.59-kexecfixes/arch/i386/kernel/i8259.c	Thu Feb 13 10:14:44 2003
@@ -246,10 +246,21 @@
 	return 0;
 }
 
+static void i8259A_shutdown(struct device *dev)
+{   
+	/* Put the i8259A into a quiescent state that
+	 * the kernel initialization code can get it
+	 * out of.
+	 */
+	outb(0xff, 0x21);	/* mask all of 8259A-1 */
+	outb(0xff, 0xA1);	/* mask all of 8259A-1 */
+}
+
 static struct device_driver i8259A_driver = {
 	.name		= "pic",
 	.bus		= &system_bus_type,
 	.resume		= i8259A_resume,
+	.shutdown	= i8259A_shutdown,
 };
 
 static struct sys_device device_i8259A = {
diff -ur -X ../../dontdiff linux-2.5.59-kexec/arch/i386/kernel/io_apic.c linux-2.5.59-kexecfixes/arch/i386/kernel/io_apic.c
--- linux-2.5.59-kexec/arch/i386/kernel/io_apic.c	Fri Jan 17 07:52:00 2003
+++ linux-2.5.59-kexecfixes/arch/i386/kernel/io_apic.c	Thu Feb 13 10:14:44 2003
@@ -1121,8 +1121,6 @@
 	 * Clear the IO-APIC before rebooting:
 	 */
 	clear_IO_APIC();
-
-	disconnect_bsp_APIC();
 }
 
 /*
diff -ur -X ../../dontdiff linux-2.5.59-kexec/arch/i386/kernel/machine_kexec.c linux-2.5.59-kexecfixes/arch/i386/kernel/machine_kexec.c
--- linux-2.5.59-kexec/arch/i386/kernel/machine_kexec.c	Thu Feb 13 10:38:46 2003
+++ linux-2.5.59-kexecfixes/arch/i386/kernel/machine_kexec.c	Thu Feb 13 10:14:44 2003
@@ -82,6 +82,8 @@
 	/* switch to an mm where the reboot_code_buffer is identity mapped */
 	switch_mm(current->active_mm, &init_mm, current, smp_processor_id());
 
+	stop_apics();
+
 	/* Interrupts aren't acceptable while we reboot */
 	local_irq_disable();
 	reboot_code_buffer = page_to_pfn(image->reboot_code_pages) << PAGE_SHIFT;
diff -ur -X ../../dontdiff linux-2.5.59-kexec/arch/i386/kernel/reboot.c linux-2.5.59-kexecfixes/arch/i386/kernel/reboot.c
--- linux-2.5.59-kexec/arch/i386/kernel/reboot.c	Fri Jan 17 07:51:49 2003
+++ linux-2.5.59-kexecfixes/arch/i386/kernel/reboot.c	Thu Feb 13 10:19:57 2003
@@ -8,6 +8,7 @@
 #include <linux/interrupt.h>
 #include <linux/mc146818rtc.h>
 #include <asm/uaccess.h>
+#include <asm/apic.h>
 
 /*
  * Power off function, if any
@@ -252,13 +253,12 @@
 		for (;;)
 		__asm__ __volatile__ ("hlt");
 	}
+#endif
 	/*
 	 * Stop all CPUs and turn off local APICs and the IO-APIC, so
 	 * other OSs see a clean IRQ state.
 	 */
-	smp_send_stop();
-	disable_IO_APIC();
-#endif
+	stop_apics();
 
 	if(!reboot_thru_bios) {
 		/* rebooting needs to touch the page at absolute addr 0 */
@@ -282,10 +282,12 @@
 
 void machine_halt(void)
 {
+	stop_apics();
 }
 
 void machine_power_off(void)
 {
+	stop_apics();
 	if (pm_power_off)
 		pm_power_off();
 }
diff -ur -X ../../dontdiff linux-2.5.59-kexec/arch/i386/kernel/smpboot.c linux-2.5.59-kexecfixes/arch/i386/kernel/smpboot.c
--- linux-2.5.59-kexec/arch/i386/kernel/smpboot.c	Fri Jan 17 07:52:09 2003
+++ linux-2.5.59-kexecfixes/arch/i386/kernel/smpboot.c	Thu Feb 13 10:14:44 2003
@@ -967,6 +967,7 @@
 	printk("CPU%d: ", 0);
 	print_cpu_info(&cpu_data[0]);
 
+	boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID));
 	boot_cpu_logical_apicid = logical_smp_processor_id();
 
 	current_thread_info()->cpu = 0;
@@ -1026,8 +1027,6 @@
 	setup_local_APIC();
 	map_cpu_to_logical_apicid();
 
-	if (GET_APIC_ID(apic_read(APIC_ID)) != boot_cpu_physical_apicid)
-		BUG();
 
 	setup_portio_remap();
 
diff -ur -X ../../dontdiff linux-2.5.59-kexec/include/asm-i386/apic.h linux-2.5.59-kexecfixes/include/asm-i386/apic.h
--- linux-2.5.59-kexec/include/asm-i386/apic.h	Fri Jan 17 07:52:56 2003
+++ linux-2.5.59-kexecfixes/include/asm-i386/apic.h	Thu Feb 13 10:14:44 2003
@@ -96,6 +96,9 @@
 #define NMI_LOCAL_APIC	2
 #define NMI_INVALID	3
 
+extern void stop_apics(void);
+#else
+static inline void stop_apics(void) { }
 #endif /* CONFIG_X86_LOCAL_APIC */
 
 #endif /* __ASM_APIC_H */
diff -ur -X ../../dontdiff linux-2.5.59-kexec/include/asm-i386/apicdef.h linux-2.5.59-kexecfixes/include/asm-i386/apicdef.h
--- linux-2.5.59-kexec/include/asm-i386/apicdef.h	Fri Jan 17 07:52:15 2003
+++ linux-2.5.59-kexecfixes/include/asm-i386/apicdef.h	Thu Feb 13 10:14:44 2003
@@ -93,6 +93,7 @@
 #define			APIC_LVT_REMOTE_IRR		(1<<14)
 #define			APIC_INPUT_POLARITY		(1<<13)
 #define			APIC_SEND_PENDING		(1<<12)
+#define			APIC_MODE_MASK			0x700
 #define			GET_APIC_DELIVERY_MODE(x)	(((x)>>8)&0x7)
 #define			SET_APIC_DELIVERY_MODE(x,y)	(((x)&~0x700)|((y)<<8))
 #define				APIC_MODE_FIXED		0x0

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2003-02-14 15:50 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-02-13 10:40 [KEXEC][PATCH] Modified (smaller) x86 kexec hwfixes patch Suparna Bhattacharya
2003-02-13 15:09 ` Eric W. Biederman
2003-02-14  3:29   ` Suparna Bhattacharya
2003-02-14  4:08     ` Martin J. Bligh
2003-02-14  8:30       ` Eric W. Biederman
2003-02-14  6:47     ` Martin J. Bligh
2003-02-14  8:32       ` Eric W. Biederman
2003-02-14 15:32         ` Martin J. Bligh
2003-02-14 16:00           ` Eric W. Biederman
2003-02-14  8:39     ` Eric W. Biederman

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox