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 #include #include +#include #include #include @@ -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 #include #include +#include /* * 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