diff options
author | Anton Altaparmakov <aia21@cantab.net> | 2005-06-26 17:19:40 -0400 |
---|---|---|
committer | Anton Altaparmakov <aia21@cantab.net> | 2005-06-26 17:19:40 -0400 |
commit | 2a322e4c08be4e7cb0c04b427ddaaa679fd88863 (patch) | |
tree | ad8cc17bfd3b5e57e36f07a249028667d72f0b96 /arch/i386 | |
parent | ba6d2377c85c9b8a793f455d8c9b6cf31985d70f (diff) | |
parent | 8678887e7fb43cd6c9be6c9807b05e77848e0920 (diff) |
Automatic merge with /usr/src/ntfs-2.6.git.
Diffstat (limited to 'arch/i386')
58 files changed, 1781 insertions, 678 deletions
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig index d4ae5f9ceae6..6c02336fe2e4 100644 --- a/arch/i386/Kconfig +++ b/arch/i386/Kconfig | |||
@@ -510,28 +510,7 @@ config SCHED_SMT | |||
510 | cost of slightly increased overhead in some places. If unsure say | 510 | cost of slightly increased overhead in some places. If unsure say |
511 | N here. | 511 | N here. |
512 | 512 | ||
513 | config PREEMPT | 513 | source "kernel/Kconfig.preempt" |
514 | bool "Preemptible Kernel" | ||
515 | help | ||
516 | This option reduces the latency of the kernel when reacting to | ||
517 | real-time or interactive events by allowing a low priority process to | ||
518 | be preempted even if it is in kernel mode executing a system call. | ||
519 | This allows applications to run more reliably even when the system is | ||
520 | under load. | ||
521 | |||
522 | Say Y here if you are building a kernel for a desktop, embedded | ||
523 | or real-time system. Say N if you are unsure. | ||
524 | |||
525 | config PREEMPT_BKL | ||
526 | bool "Preempt The Big Kernel Lock" | ||
527 | depends on PREEMPT | ||
528 | default y | ||
529 | help | ||
530 | This option reduces the latency of the kernel by making the | ||
531 | big kernel lock preemptible. | ||
532 | |||
533 | Say Y here if you are building a kernel for a desktop system. | ||
534 | Say N if you are unsure. | ||
535 | 514 | ||
536 | config X86_UP_APIC | 515 | config X86_UP_APIC |
537 | bool "Local APIC support on uniprocessors" | 516 | bool "Local APIC support on uniprocessors" |
@@ -963,6 +942,41 @@ config SECCOMP | |||
963 | 942 | ||
964 | source kernel/Kconfig.hz | 943 | source kernel/Kconfig.hz |
965 | 944 | ||
945 | config PHYSICAL_START | ||
946 | hex "Physical address where the kernel is loaded" if EMBEDDED | ||
947 | default "0x100000" | ||
948 | help | ||
949 | This gives the physical address where the kernel is loaded. | ||
950 | Primarily used in the case of kexec on panic where the | ||
951 | fail safe kernel needs to run at a different address than | ||
952 | the panic-ed kernel. | ||
953 | |||
954 | Don't change this unless you know what you are doing. | ||
955 | |||
956 | config KEXEC | ||
957 | bool "kexec system call (EXPERIMENTAL)" | ||
958 | depends on EXPERIMENTAL | ||
959 | help | ||
960 | kexec is a system call that implements the ability to shutdown your | ||
961 | current kernel, and to start another kernel. It is like a reboot | ||
962 | but it is indepedent of the system firmware. And like a reboot | ||
963 | you can start any kernel with it, not just Linux. | ||
964 | |||
965 | The name comes from the similiarity to the exec system call. | ||
966 | |||
967 | It is an ongoing process to be certain the hardware in a machine | ||
968 | is properly shutdown, so do not be surprised if this code does not | ||
969 | initially work for you. It may help to enable device hotplugging | ||
970 | support. As of this writing the exact hardware interface is | ||
971 | strongly in flux, so no good recommendation can be made. | ||
972 | |||
973 | config CRASH_DUMP | ||
974 | bool "kernel crash dumps (EXPERIMENTAL)" | ||
975 | depends on EMBEDDED | ||
976 | depends on EXPERIMENTAL | ||
977 | depends on HIGHMEM | ||
978 | help | ||
979 | Generate crash dump after being started by kexec. | ||
966 | endmenu | 980 | endmenu |
967 | 981 | ||
968 | 982 | ||
@@ -1250,6 +1264,15 @@ config SCx200 | |||
1250 | This support is also available as a module. If compiled as a | 1264 | This support is also available as a module. If compiled as a |
1251 | module, it will be called scx200. | 1265 | module, it will be called scx200. |
1252 | 1266 | ||
1267 | config HOTPLUG_CPU | ||
1268 | bool "Support for hot-pluggable CPUs (EXPERIMENTAL)" | ||
1269 | depends on SMP && HOTPLUG && EXPERIMENTAL | ||
1270 | ---help--- | ||
1271 | Say Y here to experiment with turning CPUs off and on. CPUs | ||
1272 | can be controlled through /sys/devices/system/cpu. | ||
1273 | |||
1274 | Say N. | ||
1275 | |||
1253 | source "drivers/pcmcia/Kconfig" | 1276 | source "drivers/pcmcia/Kconfig" |
1254 | 1277 | ||
1255 | source "drivers/pci/hotplug/Kconfig" | 1278 | source "drivers/pci/hotplug/Kconfig" |
diff --git a/arch/i386/boot/Makefile b/arch/i386/boot/Makefile index 43cd6220ee49..1e71382d413a 100644 --- a/arch/i386/boot/Makefile +++ b/arch/i386/boot/Makefile | |||
@@ -25,8 +25,8 @@ SVGA_MODE := -DSVGA_MODE=NORMAL_VGA | |||
25 | 25 | ||
26 | #RAMDISK := -DRAMDISK=512 | 26 | #RAMDISK := -DRAMDISK=512 |
27 | 27 | ||
28 | targets := vmlinux.bin bootsect bootsect.o setup setup.o \ | 28 | targets := vmlinux.bin bootsect bootsect.o \ |
29 | zImage bzImage | 29 | setup setup.o zImage bzImage |
30 | subdir- := compressed | 30 | subdir- := compressed |
31 | 31 | ||
32 | hostprogs-y := tools/build | 32 | hostprogs-y := tools/build |
diff --git a/arch/i386/boot/compressed/head.S b/arch/i386/boot/compressed/head.S index c5e80b69e7d4..b5893e4ecd37 100644 --- a/arch/i386/boot/compressed/head.S +++ b/arch/i386/boot/compressed/head.S | |||
@@ -25,6 +25,7 @@ | |||
25 | 25 | ||
26 | #include <linux/linkage.h> | 26 | #include <linux/linkage.h> |
27 | #include <asm/segment.h> | 27 | #include <asm/segment.h> |
28 | #include <asm/page.h> | ||
28 | 29 | ||
29 | .globl startup_32 | 30 | .globl startup_32 |
30 | 31 | ||
@@ -74,7 +75,7 @@ startup_32: | |||
74 | popl %esi # discard address | 75 | popl %esi # discard address |
75 | popl %esi # real mode pointer | 76 | popl %esi # real mode pointer |
76 | xorl %ebx,%ebx | 77 | xorl %ebx,%ebx |
77 | ljmp $(__BOOT_CS), $0x100000 | 78 | ljmp $(__BOOT_CS), $__PHYSICAL_START |
78 | 79 | ||
79 | /* | 80 | /* |
80 | * We come here, if we were loaded high. | 81 | * We come here, if we were loaded high. |
@@ -99,7 +100,7 @@ startup_32: | |||
99 | popl %ecx # lcount | 100 | popl %ecx # lcount |
100 | popl %edx # high_buffer_start | 101 | popl %edx # high_buffer_start |
101 | popl %eax # hcount | 102 | popl %eax # hcount |
102 | movl $0x100000,%edi | 103 | movl $__PHYSICAL_START,%edi |
103 | cli # make sure we don't get interrupted | 104 | cli # make sure we don't get interrupted |
104 | ljmp $(__BOOT_CS), $0x1000 # and jump to the move routine | 105 | ljmp $(__BOOT_CS), $0x1000 # and jump to the move routine |
105 | 106 | ||
@@ -124,5 +125,5 @@ move_routine_start: | |||
124 | movsl | 125 | movsl |
125 | movl %ebx,%esi # Restore setup pointer | 126 | movl %ebx,%esi # Restore setup pointer |
126 | xorl %ebx,%ebx | 127 | xorl %ebx,%ebx |
127 | ljmp $(__BOOT_CS), $0x100000 | 128 | ljmp $(__BOOT_CS), $__PHYSICAL_START |
128 | move_routine_end: | 129 | move_routine_end: |
diff --git a/arch/i386/boot/compressed/misc.c b/arch/i386/boot/compressed/misc.c index cedc55cc47de..82a807f9f5e6 100644 --- a/arch/i386/boot/compressed/misc.c +++ b/arch/i386/boot/compressed/misc.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/vmalloc.h> | 13 | #include <linux/vmalloc.h> |
14 | #include <linux/tty.h> | 14 | #include <linux/tty.h> |
15 | #include <asm/io.h> | 15 | #include <asm/io.h> |
16 | #include <asm/page.h> | ||
16 | 17 | ||
17 | /* | 18 | /* |
18 | * gzip declarations | 19 | * gzip declarations |
@@ -308,7 +309,7 @@ static void setup_normal_output_buffer(void) | |||
308 | #else | 309 | #else |
309 | if ((RM_ALT_MEM_K > RM_EXT_MEM_K ? RM_ALT_MEM_K : RM_EXT_MEM_K) < 1024) error("Less than 2MB of memory"); | 310 | if ((RM_ALT_MEM_K > RM_EXT_MEM_K ? RM_ALT_MEM_K : RM_EXT_MEM_K) < 1024) error("Less than 2MB of memory"); |
310 | #endif | 311 | #endif |
311 | output_data = (char *)0x100000; /* Points to 1M */ | 312 | output_data = (char *)__PHYSICAL_START; /* Normally Points to 1M */ |
312 | free_mem_end_ptr = (long)real_mode; | 313 | free_mem_end_ptr = (long)real_mode; |
313 | } | 314 | } |
314 | 315 | ||
@@ -333,8 +334,8 @@ static void setup_output_buffer_if_we_run_high(struct moveparams *mv) | |||
333 | low_buffer_size = low_buffer_end - LOW_BUFFER_START; | 334 | low_buffer_size = low_buffer_end - LOW_BUFFER_START; |
334 | high_loaded = 1; | 335 | high_loaded = 1; |
335 | free_mem_end_ptr = (long)high_buffer_start; | 336 | free_mem_end_ptr = (long)high_buffer_start; |
336 | if ( (0x100000 + low_buffer_size) > ((ulg)high_buffer_start)) { | 337 | if ( (__PHYSICAL_START + low_buffer_size) > ((ulg)high_buffer_start)) { |
337 | high_buffer_start = (uch *)(0x100000 + low_buffer_size); | 338 | high_buffer_start = (uch *)(__PHYSICAL_START + low_buffer_size); |
338 | mv->hcount = 0; /* say: we need not to move high_buffer */ | 339 | mv->hcount = 0; /* say: we need not to move high_buffer */ |
339 | } | 340 | } |
340 | else mv->hcount = -1; | 341 | else mv->hcount = -1; |
@@ -353,7 +354,6 @@ static void close_output_buffer_if_we_run_high(struct moveparams *mv) | |||
353 | } | 354 | } |
354 | } | 355 | } |
355 | 356 | ||
356 | |||
357 | asmlinkage int decompress_kernel(struct moveparams *mv, void *rmode) | 357 | asmlinkage int decompress_kernel(struct moveparams *mv, void *rmode) |
358 | { | 358 | { |
359 | real_mode = rmode; | 359 | real_mode = rmode; |
diff --git a/arch/i386/boot/edd.S b/arch/i386/boot/edd.S index 027d6b354ffb..d8d69f2b911d 100644 --- a/arch/i386/boot/edd.S +++ b/arch/i386/boot/edd.S | |||
@@ -6,7 +6,7 @@ | |||
6 | * projects 1572D, 1484D, 1386D, 1226DT | 6 | * projects 1572D, 1484D, 1386D, 1226DT |
7 | * disk signature read by Matt Domsch <Matt_Domsch@dell.com> | 7 | * disk signature read by Matt Domsch <Matt_Domsch@dell.com> |
8 | * and Andrew Wilks <Andrew_Wilks@dell.com> September 2003, June 2004 | 8 | * and Andrew Wilks <Andrew_Wilks@dell.com> September 2003, June 2004 |
9 | * legacy CHS retreival by Patrick J. LoPresti <patl@users.sourceforge.net> | 9 | * legacy CHS retrieval by Patrick J. LoPresti <patl@users.sourceforge.net> |
10 | * March 2004 | 10 | * March 2004 |
11 | * Command line option parsing, Matt Domsch, November 2004 | 11 | * Command line option parsing, Matt Domsch, November 2004 |
12 | */ | 12 | */ |
diff --git a/arch/i386/boot/setup.S b/arch/i386/boot/setup.S index caa1fde6904e..8cb420f40c58 100644 --- a/arch/i386/boot/setup.S +++ b/arch/i386/boot/setup.S | |||
@@ -33,7 +33,7 @@ | |||
33 | * Transcribed from Intel (as86) -> AT&T (gas) by Chris Noe, May 1999. | 33 | * Transcribed from Intel (as86) -> AT&T (gas) by Chris Noe, May 1999. |
34 | * <stiker@northlink.com> | 34 | * <stiker@northlink.com> |
35 | * | 35 | * |
36 | * Fix to work around buggy BIOSes which dont use carry bit correctly | 36 | * Fix to work around buggy BIOSes which don't use carry bit correctly |
37 | * and/or report extended memory in CX/DX for e801h memory size detection | 37 | * and/or report extended memory in CX/DX for e801h memory size detection |
38 | * call. As a result the kernel got wrong figures. The int15/e801h docs | 38 | * call. As a result the kernel got wrong figures. The int15/e801h docs |
39 | * from Ralf Brown interrupt list seem to indicate AX/BX should be used | 39 | * from Ralf Brown interrupt list seem to indicate AX/BX should be used |
@@ -357,7 +357,7 @@ bail820: | |||
357 | 357 | ||
358 | meme801: | 358 | meme801: |
359 | stc # fix to work around buggy | 359 | stc # fix to work around buggy |
360 | xorw %cx,%cx # BIOSes which dont clear/set | 360 | xorw %cx,%cx # BIOSes which don't clear/set |
361 | xorw %dx,%dx # carry on pass/error of | 361 | xorw %dx,%dx # carry on pass/error of |
362 | # e801h memory size call | 362 | # e801h memory size call |
363 | # or merely pass cx,dx though | 363 | # or merely pass cx,dx though |
@@ -847,7 +847,7 @@ flush_instr: | |||
847 | # | 847 | # |
848 | # but we yet haven't reloaded the CS register, so the default size | 848 | # but we yet haven't reloaded the CS register, so the default size |
849 | # of the target offset still is 16 bit. | 849 | # of the target offset still is 16 bit. |
850 | # However, using an operand prefix (0x66), the CPU will properly | 850 | # However, using an operand prefix (0x66), the CPU will properly |
851 | # take our 48 bit far pointer. (INTeL 80386 Programmer's Reference | 851 | # take our 48 bit far pointer. (INTeL 80386 Programmer's Reference |
852 | # Manual, Mixing 16-bit and 32-bit code, page 16-6) | 852 | # Manual, Mixing 16-bit and 32-bit code, page 16-6) |
853 | 853 | ||
diff --git a/arch/i386/boot/tools/build.c b/arch/i386/boot/tools/build.c index 26509b826aed..4a17956512e1 100644 --- a/arch/i386/boot/tools/build.c +++ b/arch/i386/boot/tools/build.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * $Id: build.c,v 1.5 1997/05/19 12:29:58 mj Exp $ | ||
3 | * | ||
4 | * Copyright (C) 1991, 1992 Linus Torvalds | 2 | * Copyright (C) 1991, 1992 Linus Torvalds |
5 | * Copyright (C) 1997 Martin Mares | 3 | * Copyright (C) 1997 Martin Mares |
6 | */ | 4 | */ |
@@ -8,7 +6,8 @@ | |||
8 | /* | 6 | /* |
9 | * This file builds a disk-image from three different files: | 7 | * This file builds a disk-image from three different files: |
10 | * | 8 | * |
11 | * - bootsect: exactly 512 bytes of 8086 machine code, loads the rest | 9 | * - bootsect: compatibility mbr which prints an error message if |
10 | * someone tries to boot the kernel directly. | ||
12 | * - setup: 8086 machine code, sets up system parm | 11 | * - setup: 8086 machine code, sets up system parm |
13 | * - system: 80386 code for actual system | 12 | * - system: 80386 code for actual system |
14 | * | 13 | * |
diff --git a/arch/i386/crypto/aes.c b/arch/i386/crypto/aes.c index 1019430fc1f1..88ee85c3b43b 100644 --- a/arch/i386/crypto/aes.c +++ b/arch/i386/crypto/aes.c | |||
@@ -59,7 +59,7 @@ struct aes_ctx { | |||
59 | }; | 59 | }; |
60 | 60 | ||
61 | #define WPOLY 0x011b | 61 | #define WPOLY 0x011b |
62 | #define u32_in(x) le32_to_cpu(*(const u32 *)(x)) | 62 | #define u32_in(x) le32_to_cpup((const __le32 *)(x)) |
63 | #define bytes2word(b0, b1, b2, b3) \ | 63 | #define bytes2word(b0, b1, b2, b3) \ |
64 | (((u32)(b3) << 24) | ((u32)(b2) << 16) | ((u32)(b1) << 8) | (b0)) | 64 | (((u32)(b3) << 24) | ((u32)(b2) << 16) | ((u32)(b1) << 8) | (b0)) |
65 | 65 | ||
diff --git a/arch/i386/defconfig b/arch/i386/defconfig index 28e620383799..ca07b95c06b8 100644 --- a/arch/i386/defconfig +++ b/arch/i386/defconfig | |||
@@ -126,7 +126,6 @@ CONFIG_HAVE_DEC_LOCK=y | |||
126 | # | 126 | # |
127 | CONFIG_PM=y | 127 | CONFIG_PM=y |
128 | CONFIG_SOFTWARE_SUSPEND=y | 128 | CONFIG_SOFTWARE_SUSPEND=y |
129 | # CONFIG_PM_DISK is not set | ||
130 | 129 | ||
131 | # | 130 | # |
132 | # ACPI (Advanced Configuration and Power Interface) Support | 131 | # ACPI (Advanced Configuration and Power Interface) Support |
diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile index 51ecd512603d..4cc83b322b36 100644 --- a/arch/i386/kernel/Makefile +++ b/arch/i386/kernel/Makefile | |||
@@ -24,6 +24,7 @@ obj-$(CONFIG_X86_MPPARSE) += mpparse.o | |||
24 | obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o | 24 | obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o |
25 | obj-$(CONFIG_X86_IO_APIC) += io_apic.o | 25 | obj-$(CONFIG_X86_IO_APIC) += io_apic.o |
26 | obj-$(CONFIG_X86_REBOOTFIXUPS) += reboot_fixups.o | 26 | obj-$(CONFIG_X86_REBOOTFIXUPS) += reboot_fixups.o |
27 | obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o crash.o | ||
27 | obj-$(CONFIG_X86_NUMAQ) += numaq.o | 28 | obj-$(CONFIG_X86_NUMAQ) += numaq.o |
28 | obj-$(CONFIG_X86_SUMMIT_NUMA) += summit.o | 29 | obj-$(CONFIG_X86_SUMMIT_NUMA) += summit.o |
29 | obj-$(CONFIG_KPROBES) += kprobes.o | 30 | obj-$(CONFIG_KPROBES) += kprobes.o |
diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c index 848bb97af7ca..9f63ae0f404b 100644 --- a/arch/i386/kernel/acpi/boot.c +++ b/arch/i386/kernel/acpi/boot.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/efi.h> | 29 | #include <linux/efi.h> |
30 | #include <linux/irq.h> | 30 | #include <linux/irq.h> |
31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
32 | #include <linux/dmi.h> | ||
32 | 33 | ||
33 | #include <asm/pgtable.h> | 34 | #include <asm/pgtable.h> |
34 | #include <asm/io_apic.h> | 35 | #include <asm/io_apic.h> |
@@ -815,6 +816,219 @@ acpi_process_madt(void) | |||
815 | return; | 816 | return; |
816 | } | 817 | } |
817 | 818 | ||
819 | extern int acpi_force; | ||
820 | |||
821 | #ifdef __i386__ | ||
822 | |||
823 | #ifdef CONFIG_ACPI_PCI | ||
824 | static int __init disable_acpi_irq(struct dmi_system_id *d) | ||
825 | { | ||
826 | if (!acpi_force) { | ||
827 | printk(KERN_NOTICE "%s detected: force use of acpi=noirq\n", | ||
828 | d->ident); | ||
829 | acpi_noirq_set(); | ||
830 | } | ||
831 | return 0; | ||
832 | } | ||
833 | |||
834 | static int __init disable_acpi_pci(struct dmi_system_id *d) | ||
835 | { | ||
836 | if (!acpi_force) { | ||
837 | printk(KERN_NOTICE "%s detected: force use of pci=noacpi\n", | ||
838 | d->ident); | ||
839 | acpi_disable_pci(); | ||
840 | } | ||
841 | return 0; | ||
842 | } | ||
843 | #endif | ||
844 | |||
845 | static int __init dmi_disable_acpi(struct dmi_system_id *d) | ||
846 | { | ||
847 | if (!acpi_force) { | ||
848 | printk(KERN_NOTICE "%s detected: acpi off\n",d->ident); | ||
849 | disable_acpi(); | ||
850 | } else { | ||
851 | printk(KERN_NOTICE | ||
852 | "Warning: DMI blacklist says broken, but acpi forced\n"); | ||
853 | } | ||
854 | return 0; | ||
855 | } | ||
856 | |||
857 | /* | ||
858 | * Limit ACPI to CPU enumeration for HT | ||
859 | */ | ||
860 | static int __init force_acpi_ht(struct dmi_system_id *d) | ||
861 | { | ||
862 | if (!acpi_force) { | ||
863 | printk(KERN_NOTICE "%s detected: force use of acpi=ht\n", d->ident); | ||
864 | disable_acpi(); | ||
865 | acpi_ht = 1; | ||
866 | } else { | ||
867 | printk(KERN_NOTICE | ||
868 | "Warning: acpi=force overrules DMI blacklist: acpi=ht\n"); | ||
869 | } | ||
870 | return 0; | ||
871 | } | ||
872 | |||
873 | /* | ||
874 | * If your system is blacklisted here, but you find that acpi=force | ||
875 | * works for you, please contact acpi-devel@sourceforge.net | ||
876 | */ | ||
877 | static struct dmi_system_id __initdata acpi_dmi_table[] = { | ||
878 | /* | ||
879 | * Boxes that need ACPI disabled | ||
880 | */ | ||
881 | { | ||
882 | .callback = dmi_disable_acpi, | ||
883 | .ident = "IBM Thinkpad", | ||
884 | .matches = { | ||
885 | DMI_MATCH(DMI_BOARD_VENDOR, "IBM"), | ||
886 | DMI_MATCH(DMI_BOARD_NAME, "2629H1G"), | ||
887 | }, | ||
888 | }, | ||
889 | |||
890 | /* | ||
891 | * Boxes that need acpi=ht | ||
892 | */ | ||
893 | { | ||
894 | .callback = force_acpi_ht, | ||
895 | .ident = "FSC Primergy T850", | ||
896 | .matches = { | ||
897 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), | ||
898 | DMI_MATCH(DMI_PRODUCT_NAME, "PRIMERGY T850"), | ||
899 | }, | ||
900 | }, | ||
901 | { | ||
902 | .callback = force_acpi_ht, | ||
903 | .ident = "DELL GX240", | ||
904 | .matches = { | ||
905 | DMI_MATCH(DMI_BOARD_VENDOR, "Dell Computer Corporation"), | ||
906 | DMI_MATCH(DMI_BOARD_NAME, "OptiPlex GX240"), | ||
907 | }, | ||
908 | }, | ||
909 | { | ||
910 | .callback = force_acpi_ht, | ||
911 | .ident = "HP VISUALIZE NT Workstation", | ||
912 | .matches = { | ||
913 | DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"), | ||
914 | DMI_MATCH(DMI_PRODUCT_NAME, "HP VISUALIZE NT Workstation"), | ||
915 | }, | ||
916 | }, | ||
917 | { | ||
918 | .callback = force_acpi_ht, | ||
919 | .ident = "Compaq Workstation W8000", | ||
920 | .matches = { | ||
921 | DMI_MATCH(DMI_SYS_VENDOR, "Compaq"), | ||
922 | DMI_MATCH(DMI_PRODUCT_NAME, "Workstation W8000"), | ||
923 | }, | ||
924 | }, | ||
925 | { | ||
926 | .callback = force_acpi_ht, | ||
927 | .ident = "ASUS P4B266", | ||
928 | .matches = { | ||
929 | DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), | ||
930 | DMI_MATCH(DMI_BOARD_NAME, "P4B266"), | ||
931 | }, | ||
932 | }, | ||
933 | { | ||
934 | .callback = force_acpi_ht, | ||
935 | .ident = "ASUS P2B-DS", | ||
936 | .matches = { | ||
937 | DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), | ||
938 | DMI_MATCH(DMI_BOARD_NAME, "P2B-DS"), | ||
939 | }, | ||
940 | }, | ||
941 | { | ||
942 | .callback = force_acpi_ht, | ||
943 | .ident = "ASUS CUR-DLS", | ||
944 | .matches = { | ||
945 | DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), | ||
946 | DMI_MATCH(DMI_BOARD_NAME, "CUR-DLS"), | ||
947 | }, | ||
948 | }, | ||
949 | { | ||
950 | .callback = force_acpi_ht, | ||
951 | .ident = "ABIT i440BX-W83977", | ||
952 | .matches = { | ||
953 | DMI_MATCH(DMI_BOARD_VENDOR, "ABIT <http://www.abit.com>"), | ||
954 | DMI_MATCH(DMI_BOARD_NAME, "i440BX-W83977 (BP6)"), | ||
955 | }, | ||
956 | }, | ||
957 | { | ||
958 | .callback = force_acpi_ht, | ||
959 | .ident = "IBM Bladecenter", | ||
960 | .matches = { | ||
961 | DMI_MATCH(DMI_BOARD_VENDOR, "IBM"), | ||
962 | DMI_MATCH(DMI_BOARD_NAME, "IBM eServer BladeCenter HS20"), | ||
963 | }, | ||
964 | }, | ||
965 | { | ||
966 | .callback = force_acpi_ht, | ||
967 | .ident = "IBM eServer xSeries 360", | ||
968 | .matches = { | ||
969 | DMI_MATCH(DMI_BOARD_VENDOR, "IBM"), | ||
970 | DMI_MATCH(DMI_BOARD_NAME, "eServer xSeries 360"), | ||
971 | }, | ||
972 | }, | ||
973 | { | ||
974 | .callback = force_acpi_ht, | ||
975 | .ident = "IBM eserver xSeries 330", | ||
976 | .matches = { | ||
977 | DMI_MATCH(DMI_BOARD_VENDOR, "IBM"), | ||
978 | DMI_MATCH(DMI_BOARD_NAME, "eserver xSeries 330"), | ||
979 | }, | ||
980 | }, | ||
981 | { | ||
982 | .callback = force_acpi_ht, | ||
983 | .ident = "IBM eserver xSeries 440", | ||
984 | .matches = { | ||
985 | DMI_MATCH(DMI_BOARD_VENDOR, "IBM"), | ||
986 | DMI_MATCH(DMI_PRODUCT_NAME, "eserver xSeries 440"), | ||
987 | }, | ||
988 | }, | ||
989 | |||
990 | #ifdef CONFIG_ACPI_PCI | ||
991 | /* | ||
992 | * Boxes that need ACPI PCI IRQ routing disabled | ||
993 | */ | ||
994 | { | ||
995 | .callback = disable_acpi_irq, | ||
996 | .ident = "ASUS A7V", | ||
997 | .matches = { | ||
998 | DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC"), | ||
999 | DMI_MATCH(DMI_BOARD_NAME, "<A7V>"), | ||
1000 | /* newer BIOS, Revision 1011, does work */ | ||
1001 | DMI_MATCH(DMI_BIOS_VERSION, "ASUS A7V ACPI BIOS Revision 1007"), | ||
1002 | }, | ||
1003 | }, | ||
1004 | |||
1005 | /* | ||
1006 | * Boxes that need ACPI PCI IRQ routing and PCI scan disabled | ||
1007 | */ | ||
1008 | { /* _BBN 0 bug */ | ||
1009 | .callback = disable_acpi_pci, | ||
1010 | .ident = "ASUS PR-DLS", | ||
1011 | .matches = { | ||
1012 | DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), | ||
1013 | DMI_MATCH(DMI_BOARD_NAME, "PR-DLS"), | ||
1014 | DMI_MATCH(DMI_BIOS_VERSION, "ASUS PR-DLS ACPI BIOS Revision 1010"), | ||
1015 | DMI_MATCH(DMI_BIOS_DATE, "03/21/2003") | ||
1016 | }, | ||
1017 | }, | ||
1018 | { | ||
1019 | .callback = disable_acpi_pci, | ||
1020 | .ident = "Acer TravelMate 36x Laptop", | ||
1021 | .matches = { | ||
1022 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | ||
1023 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"), | ||
1024 | }, | ||
1025 | }, | ||
1026 | #endif | ||
1027 | { } | ||
1028 | }; | ||
1029 | |||
1030 | #endif /* __i386__ */ | ||
1031 | |||
818 | /* | 1032 | /* |
819 | * acpi_boot_table_init() and acpi_boot_init() | 1033 | * acpi_boot_table_init() and acpi_boot_init() |
820 | * called from setup_arch(), always. | 1034 | * called from setup_arch(), always. |
@@ -843,6 +1057,10 @@ acpi_boot_table_init(void) | |||
843 | { | 1057 | { |
844 | int error; | 1058 | int error; |
845 | 1059 | ||
1060 | #ifdef __i386__ | ||
1061 | dmi_check_system(acpi_dmi_table); | ||
1062 | #endif | ||
1063 | |||
846 | /* | 1064 | /* |
847 | * If acpi_disabled, bail out | 1065 | * If acpi_disabled, bail out |
848 | * One exception: acpi=ht continues far enough to enumerate LAPICs | 1066 | * One exception: acpi=ht continues far enough to enumerate LAPICs |
@@ -870,8 +1088,6 @@ acpi_boot_table_init(void) | |||
870 | */ | 1088 | */ |
871 | error = acpi_blacklisted(); | 1089 | error = acpi_blacklisted(); |
872 | if (error) { | 1090 | if (error) { |
873 | extern int acpi_force; | ||
874 | |||
875 | if (acpi_force) { | 1091 | if (acpi_force) { |
876 | printk(KERN_WARNING PREFIX "acpi=force override\n"); | 1092 | printk(KERN_WARNING PREFIX "acpi=force override\n"); |
877 | } else { | 1093 | } else { |
diff --git a/arch/i386/kernel/acpi/sleep.c b/arch/i386/kernel/acpi/sleep.c index 28bb0514bb6e..c1af93032ff3 100644 --- a/arch/i386/kernel/acpi/sleep.c +++ b/arch/i386/kernel/acpi/sleep.c | |||
@@ -7,6 +7,7 @@ | |||
7 | 7 | ||
8 | #include <linux/acpi.h> | 8 | #include <linux/acpi.h> |
9 | #include <linux/bootmem.h> | 9 | #include <linux/bootmem.h> |
10 | #include <linux/dmi.h> | ||
10 | #include <asm/smp.h> | 11 | #include <asm/smp.h> |
11 | #include <asm/tlbflush.h> | 12 | #include <asm/tlbflush.h> |
12 | 13 | ||
@@ -91,3 +92,29 @@ static int __init acpi_sleep_setup(char *str) | |||
91 | 92 | ||
92 | 93 | ||
93 | __setup("acpi_sleep=", acpi_sleep_setup); | 94 | __setup("acpi_sleep=", acpi_sleep_setup); |
95 | |||
96 | |||
97 | static __init int reset_videomode_after_s3(struct dmi_system_id *d) | ||
98 | { | ||
99 | acpi_video_flags |= 2; | ||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | static __initdata struct dmi_system_id acpisleep_dmi_table[] = { | ||
104 | { /* Reset video mode after returning from ACPI S3 sleep */ | ||
105 | .callback = reset_videomode_after_s3, | ||
106 | .ident = "Toshiba Satellite 4030cdt", | ||
107 | .matches = { | ||
108 | DMI_MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"), | ||
109 | }, | ||
110 | }, | ||
111 | { } | ||
112 | }; | ||
113 | |||
114 | static int __init acpisleep_dmi_init(void) | ||
115 | { | ||
116 | dmi_check_system(acpisleep_dmi_table); | ||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | core_initcall(acpisleep_dmi_init); | ||
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c index 8d993fa71754..93df90bbb87e 100644 --- a/arch/i386/kernel/apic.c +++ b/arch/i386/kernel/apic.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/mc146818rtc.h> | 26 | #include <linux/mc146818rtc.h> |
27 | #include <linux/kernel_stat.h> | 27 | #include <linux/kernel_stat.h> |
28 | #include <linux/sysdev.h> | 28 | #include <linux/sysdev.h> |
29 | #include <linux/cpu.h> | ||
29 | 30 | ||
30 | #include <asm/atomic.h> | 31 | #include <asm/atomic.h> |
31 | #include <asm/smp.h> | 32 | #include <asm/smp.h> |
@@ -40,6 +41,11 @@ | |||
40 | #include "io_ports.h" | 41 | #include "io_ports.h" |
41 | 42 | ||
42 | /* | 43 | /* |
44 | * Knob to control our willingness to enable the local APIC. | ||
45 | */ | ||
46 | int enable_local_apic __initdata = 0; /* -1=force-disable, +1=force-enable */ | ||
47 | |||
48 | /* | ||
43 | * Debug level | 49 | * Debug level |
44 | */ | 50 | */ |
45 | int apic_verbosity; | 51 | int apic_verbosity; |
@@ -205,7 +211,7 @@ void __init connect_bsp_APIC(void) | |||
205 | enable_apic_mode(); | 211 | enable_apic_mode(); |
206 | } | 212 | } |
207 | 213 | ||
208 | void disconnect_bsp_APIC(void) | 214 | void disconnect_bsp_APIC(int virt_wire_setup) |
209 | { | 215 | { |
210 | if (pic_mode) { | 216 | if (pic_mode) { |
211 | /* | 217 | /* |
@@ -219,6 +225,42 @@ void disconnect_bsp_APIC(void) | |||
219 | outb(0x70, 0x22); | 225 | outb(0x70, 0x22); |
220 | outb(0x00, 0x23); | 226 | outb(0x00, 0x23); |
221 | } | 227 | } |
228 | else { | ||
229 | /* Go back to Virtual Wire compatibility mode */ | ||
230 | unsigned long value; | ||
231 | |||
232 | /* For the spurious interrupt use vector F, and enable it */ | ||
233 | value = apic_read(APIC_SPIV); | ||
234 | value &= ~APIC_VECTOR_MASK; | ||
235 | value |= APIC_SPIV_APIC_ENABLED; | ||
236 | value |= 0xf; | ||
237 | apic_write_around(APIC_SPIV, value); | ||
238 | |||
239 | if (!virt_wire_setup) { | ||
240 | /* For LVT0 make it edge triggered, active high, external and enabled */ | ||
241 | value = apic_read(APIC_LVT0); | ||
242 | value &= ~(APIC_MODE_MASK | APIC_SEND_PENDING | | ||
243 | APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR | | ||
244 | APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED ); | ||
245 | value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING; | ||
246 | value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_EXTINT); | ||
247 | apic_write_around(APIC_LVT0, value); | ||
248 | } | ||
249 | else { | ||
250 | /* Disable LVT0 */ | ||
251 | apic_write_around(APIC_LVT0, APIC_LVT_MASKED); | ||
252 | } | ||
253 | |||
254 | /* For LVT1 make it edge triggered, active high, nmi and enabled */ | ||
255 | value = apic_read(APIC_LVT1); | ||
256 | value &= ~( | ||
257 | APIC_MODE_MASK | APIC_SEND_PENDING | | ||
258 | APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR | | ||
259 | APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED); | ||
260 | value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING; | ||
261 | value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_NMI); | ||
262 | apic_write_around(APIC_LVT1, value); | ||
263 | } | ||
222 | } | 264 | } |
223 | 265 | ||
224 | void disable_local_APIC(void) | 266 | void disable_local_APIC(void) |
@@ -363,7 +405,7 @@ void __init init_bsp_APIC(void) | |||
363 | apic_write_around(APIC_LVT1, value); | 405 | apic_write_around(APIC_LVT1, value); |
364 | } | 406 | } |
365 | 407 | ||
366 | void __init setup_local_APIC (void) | 408 | void __devinit setup_local_APIC(void) |
367 | { | 409 | { |
368 | unsigned long oldvalue, value, ver, maxlvt; | 410 | unsigned long oldvalue, value, ver, maxlvt; |
369 | 411 | ||
@@ -634,7 +676,7 @@ static struct sys_device device_lapic = { | |||
634 | .cls = &lapic_sysclass, | 676 | .cls = &lapic_sysclass, |
635 | }; | 677 | }; |
636 | 678 | ||
637 | static void __init apic_pm_activate(void) | 679 | static void __devinit apic_pm_activate(void) |
638 | { | 680 | { |
639 | apic_pm_state.active = 1; | 681 | apic_pm_state.active = 1; |
640 | } | 682 | } |
@@ -665,26 +707,6 @@ static void apic_pm_activate(void) { } | |||
665 | * Original code written by Keir Fraser. | 707 | * Original code written by Keir Fraser. |
666 | */ | 708 | */ |
667 | 709 | ||
668 | /* | ||
669 | * Knob to control our willingness to enable the local APIC. | ||
670 | */ | ||
671 | int enable_local_apic __initdata = 0; /* -1=force-disable, +1=force-enable */ | ||
672 | |||
673 | static int __init lapic_disable(char *str) | ||
674 | { | ||
675 | enable_local_apic = -1; | ||
676 | clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability); | ||
677 | return 0; | ||
678 | } | ||
679 | __setup("nolapic", lapic_disable); | ||
680 | |||
681 | static int __init lapic_enable(char *str) | ||
682 | { | ||
683 | enable_local_apic = 1; | ||
684 | return 0; | ||
685 | } | ||
686 | __setup("lapic", lapic_enable); | ||
687 | |||
688 | static int __init apic_set_verbosity(char *str) | 710 | static int __init apic_set_verbosity(char *str) |
689 | { | 711 | { |
690 | if (strcmp("debug", str) == 0) | 712 | if (strcmp("debug", str) == 0) |
@@ -855,7 +877,7 @@ fake_ioapic_page: | |||
855 | * but we do not accept timer interrupts yet. We only allow the BP | 877 | * but we do not accept timer interrupts yet. We only allow the BP |
856 | * to calibrate. | 878 | * to calibrate. |
857 | */ | 879 | */ |
858 | static unsigned int __init get_8254_timer_count(void) | 880 | static unsigned int __devinit get_8254_timer_count(void) |
859 | { | 881 | { |
860 | extern spinlock_t i8253_lock; | 882 | extern spinlock_t i8253_lock; |
861 | unsigned long flags; | 883 | unsigned long flags; |
@@ -874,7 +896,7 @@ static unsigned int __init get_8254_timer_count(void) | |||
874 | } | 896 | } |
875 | 897 | ||
876 | /* next tick in 8254 can be caught by catching timer wraparound */ | 898 | /* next tick in 8254 can be caught by catching timer wraparound */ |
877 | static void __init wait_8254_wraparound(void) | 899 | static void __devinit wait_8254_wraparound(void) |
878 | { | 900 | { |
879 | unsigned int curr_count, prev_count; | 901 | unsigned int curr_count, prev_count; |
880 | 902 | ||
@@ -894,7 +916,7 @@ static void __init wait_8254_wraparound(void) | |||
894 | * Default initialization for 8254 timers. If we use other timers like HPET, | 916 | * Default initialization for 8254 timers. If we use other timers like HPET, |
895 | * we override this later | 917 | * we override this later |
896 | */ | 918 | */ |
897 | void (*wait_timer_tick)(void) __initdata = wait_8254_wraparound; | 919 | void (*wait_timer_tick)(void) __devinitdata = wait_8254_wraparound; |
898 | 920 | ||
899 | /* | 921 | /* |
900 | * This function sets up the local APIC timer, with a timeout of | 922 | * This function sets up the local APIC timer, with a timeout of |
@@ -930,7 +952,7 @@ static void __setup_APIC_LVTT(unsigned int clocks) | |||
930 | apic_write_around(APIC_TMICT, clocks/APIC_DIVISOR); | 952 | apic_write_around(APIC_TMICT, clocks/APIC_DIVISOR); |
931 | } | 953 | } |
932 | 954 | ||
933 | static void __init setup_APIC_timer(unsigned int clocks) | 955 | static void __devinit setup_APIC_timer(unsigned int clocks) |
934 | { | 956 | { |
935 | unsigned long flags; | 957 | unsigned long flags; |
936 | 958 | ||
@@ -1043,12 +1065,12 @@ void __init setup_boot_APIC_clock(void) | |||
1043 | local_irq_enable(); | 1065 | local_irq_enable(); |
1044 | } | 1066 | } |
1045 | 1067 | ||
1046 | void __init setup_secondary_APIC_clock(void) | 1068 | void __devinit setup_secondary_APIC_clock(void) |
1047 | { | 1069 | { |
1048 | setup_APIC_timer(calibration_result); | 1070 | setup_APIC_timer(calibration_result); |
1049 | } | 1071 | } |
1050 | 1072 | ||
1051 | void __init disable_APIC_timer(void) | 1073 | void __devinit disable_APIC_timer(void) |
1052 | { | 1074 | { |
1053 | if (using_apic_timer) { | 1075 | if (using_apic_timer) { |
1054 | unsigned long v; | 1076 | unsigned long v; |
diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c index 0ff65abcd56c..d48ce9290963 100644 --- a/arch/i386/kernel/apm.c +++ b/arch/i386/kernel/apm.c | |||
@@ -346,10 +346,10 @@ extern int (*console_blank_hook)(int); | |||
346 | struct apm_user { | 346 | struct apm_user { |
347 | int magic; | 347 | int magic; |
348 | struct apm_user * next; | 348 | struct apm_user * next; |
349 | int suser: 1; | 349 | unsigned int suser: 1; |
350 | int writer: 1; | 350 | unsigned int writer: 1; |
351 | int reader: 1; | 351 | unsigned int reader: 1; |
352 | int suspend_wait: 1; | 352 | unsigned int suspend_wait: 1; |
353 | int suspend_result; | 353 | int suspend_result; |
354 | int suspends_pending; | 354 | int suspends_pending; |
355 | int standbys_pending; | 355 | int standbys_pending; |
diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c index b9954248d0aa..2203a9d20212 100644 --- a/arch/i386/kernel/cpu/common.c +++ b/arch/i386/kernel/cpu/common.c | |||
@@ -24,9 +24,9 @@ EXPORT_PER_CPU_SYMBOL(cpu_gdt_table); | |||
24 | DEFINE_PER_CPU(unsigned char, cpu_16bit_stack[CPU_16BIT_STACK_SIZE]); | 24 | DEFINE_PER_CPU(unsigned char, cpu_16bit_stack[CPU_16BIT_STACK_SIZE]); |
25 | EXPORT_PER_CPU_SYMBOL(cpu_16bit_stack); | 25 | EXPORT_PER_CPU_SYMBOL(cpu_16bit_stack); |
26 | 26 | ||
27 | static int cachesize_override __initdata = -1; | 27 | static int cachesize_override __devinitdata = -1; |
28 | static int disable_x86_fxsr __initdata = 0; | 28 | static int disable_x86_fxsr __devinitdata = 0; |
29 | static int disable_x86_serial_nr __initdata = 1; | 29 | static int disable_x86_serial_nr __devinitdata = 1; |
30 | 30 | ||
31 | struct cpu_dev * cpu_devs[X86_VENDOR_NUM] = {}; | 31 | struct cpu_dev * cpu_devs[X86_VENDOR_NUM] = {}; |
32 | 32 | ||
@@ -59,7 +59,7 @@ static int __init cachesize_setup(char *str) | |||
59 | } | 59 | } |
60 | __setup("cachesize=", cachesize_setup); | 60 | __setup("cachesize=", cachesize_setup); |
61 | 61 | ||
62 | int __init get_model_name(struct cpuinfo_x86 *c) | 62 | int __devinit get_model_name(struct cpuinfo_x86 *c) |
63 | { | 63 | { |
64 | unsigned int *v; | 64 | unsigned int *v; |
65 | char *p, *q; | 65 | char *p, *q; |
@@ -89,7 +89,7 @@ int __init get_model_name(struct cpuinfo_x86 *c) | |||
89 | } | 89 | } |
90 | 90 | ||
91 | 91 | ||
92 | void __init display_cacheinfo(struct cpuinfo_x86 *c) | 92 | void __devinit display_cacheinfo(struct cpuinfo_x86 *c) |
93 | { | 93 | { |
94 | unsigned int n, dummy, ecx, edx, l2size; | 94 | unsigned int n, dummy, ecx, edx, l2size; |
95 | 95 | ||
@@ -130,7 +130,7 @@ void __init display_cacheinfo(struct cpuinfo_x86 *c) | |||
130 | /* in particular, if CPUID levels 0x80000002..4 are supported, this isn't used */ | 130 | /* in particular, if CPUID levels 0x80000002..4 are supported, this isn't used */ |
131 | 131 | ||
132 | /* Look up CPU names by table lookup. */ | 132 | /* Look up CPU names by table lookup. */ |
133 | static char __init *table_lookup_model(struct cpuinfo_x86 *c) | 133 | static char __devinit *table_lookup_model(struct cpuinfo_x86 *c) |
134 | { | 134 | { |
135 | struct cpu_model_info *info; | 135 | struct cpu_model_info *info; |
136 | 136 | ||
@@ -151,7 +151,7 @@ static char __init *table_lookup_model(struct cpuinfo_x86 *c) | |||
151 | } | 151 | } |
152 | 152 | ||
153 | 153 | ||
154 | void __init get_cpu_vendor(struct cpuinfo_x86 *c, int early) | 154 | void __devinit get_cpu_vendor(struct cpuinfo_x86 *c, int early) |
155 | { | 155 | { |
156 | char *v = c->x86_vendor_id; | 156 | char *v = c->x86_vendor_id; |
157 | int i; | 157 | int i; |
@@ -202,7 +202,7 @@ static inline int flag_is_changeable_p(u32 flag) | |||
202 | 202 | ||
203 | 203 | ||
204 | /* Probe for the CPUID instruction */ | 204 | /* Probe for the CPUID instruction */ |
205 | static int __init have_cpuid_p(void) | 205 | static int __devinit have_cpuid_p(void) |
206 | { | 206 | { |
207 | return flag_is_changeable_p(X86_EFLAGS_ID); | 207 | return flag_is_changeable_p(X86_EFLAGS_ID); |
208 | } | 208 | } |
@@ -249,7 +249,7 @@ static void __init early_cpu_detect(void) | |||
249 | #endif | 249 | #endif |
250 | } | 250 | } |
251 | 251 | ||
252 | void __init generic_identify(struct cpuinfo_x86 * c) | 252 | void __devinit generic_identify(struct cpuinfo_x86 * c) |
253 | { | 253 | { |
254 | u32 tfms, xlvl; | 254 | u32 tfms, xlvl; |
255 | int junk; | 255 | int junk; |
@@ -296,7 +296,7 @@ void __init generic_identify(struct cpuinfo_x86 * c) | |||
296 | } | 296 | } |
297 | } | 297 | } |
298 | 298 | ||
299 | static void __init squash_the_stupid_serial_number(struct cpuinfo_x86 *c) | 299 | static void __devinit squash_the_stupid_serial_number(struct cpuinfo_x86 *c) |
300 | { | 300 | { |
301 | if (cpu_has(c, X86_FEATURE_PN) && disable_x86_serial_nr ) { | 301 | if (cpu_has(c, X86_FEATURE_PN) && disable_x86_serial_nr ) { |
302 | /* Disable processor serial number */ | 302 | /* Disable processor serial number */ |
@@ -324,7 +324,7 @@ __setup("serialnumber", x86_serial_nr_setup); | |||
324 | /* | 324 | /* |
325 | * This does the hard work of actually picking apart the CPU stuff... | 325 | * This does the hard work of actually picking apart the CPU stuff... |
326 | */ | 326 | */ |
327 | void __init identify_cpu(struct cpuinfo_x86 *c) | 327 | void __devinit identify_cpu(struct cpuinfo_x86 *c) |
328 | { | 328 | { |
329 | int i; | 329 | int i; |
330 | 330 | ||
@@ -432,10 +432,13 @@ void __init identify_cpu(struct cpuinfo_x86 *c) | |||
432 | #ifdef CONFIG_X86_MCE | 432 | #ifdef CONFIG_X86_MCE |
433 | mcheck_init(c); | 433 | mcheck_init(c); |
434 | #endif | 434 | #endif |
435 | if (c == &boot_cpu_data) | ||
436 | sysenter_setup(); | ||
437 | enable_sep_cpu(); | ||
435 | } | 438 | } |
436 | 439 | ||
437 | #ifdef CONFIG_X86_HT | 440 | #ifdef CONFIG_X86_HT |
438 | void __init detect_ht(struct cpuinfo_x86 *c) | 441 | void __devinit detect_ht(struct cpuinfo_x86 *c) |
439 | { | 442 | { |
440 | u32 eax, ebx, ecx, edx; | 443 | u32 eax, ebx, ecx, edx; |
441 | int index_msb, tmp; | 444 | int index_msb, tmp; |
@@ -490,7 +493,7 @@ void __init detect_ht(struct cpuinfo_x86 *c) | |||
490 | } | 493 | } |
491 | #endif | 494 | #endif |
492 | 495 | ||
493 | void __init print_cpu_info(struct cpuinfo_x86 *c) | 496 | void __devinit print_cpu_info(struct cpuinfo_x86 *c) |
494 | { | 497 | { |
495 | char *vendor = NULL; | 498 | char *vendor = NULL; |
496 | 499 | ||
@@ -513,7 +516,7 @@ void __init print_cpu_info(struct cpuinfo_x86 *c) | |||
513 | printk("\n"); | 516 | printk("\n"); |
514 | } | 517 | } |
515 | 518 | ||
516 | cpumask_t cpu_initialized __initdata = CPU_MASK_NONE; | 519 | cpumask_t cpu_initialized __devinitdata = CPU_MASK_NONE; |
517 | 520 | ||
518 | /* This is hacky. :) | 521 | /* This is hacky. :) |
519 | * We're emulating future behavior. | 522 | * We're emulating future behavior. |
@@ -560,7 +563,7 @@ void __init early_cpu_init(void) | |||
560 | * and IDT. We reload them nevertheless, this function acts as a | 563 | * and IDT. We reload them nevertheless, this function acts as a |
561 | * 'CPU state barrier', nothing should get across. | 564 | * 'CPU state barrier', nothing should get across. |
562 | */ | 565 | */ |
563 | void __init cpu_init (void) | 566 | void __devinit cpu_init(void) |
564 | { | 567 | { |
565 | int cpu = smp_processor_id(); | 568 | int cpu = smp_processor_id(); |
566 | struct tss_struct * t = &per_cpu(init_tss, cpu); | 569 | struct tss_struct * t = &per_cpu(init_tss, cpu); |
@@ -648,3 +651,15 @@ void __init cpu_init (void) | |||
648 | clear_used_math(); | 651 | clear_used_math(); |
649 | mxcsr_feature_mask_init(); | 652 | mxcsr_feature_mask_init(); |
650 | } | 653 | } |
654 | |||
655 | #ifdef CONFIG_HOTPLUG_CPU | ||
656 | void __devinit cpu_uninit(void) | ||
657 | { | ||
658 | int cpu = raw_smp_processor_id(); | ||
659 | cpu_clear(cpu, cpu_initialized); | ||
660 | |||
661 | /* lazy TLB state */ | ||
662 | per_cpu(cpu_tlbstate, cpu).state = 0; | ||
663 | per_cpu(cpu_tlbstate, cpu).active_mm = &init_mm; | ||
664 | } | ||
665 | #endif | ||
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c index 5c530064eb74..73a5dc5b26b8 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c | |||
@@ -648,9 +648,7 @@ static int powernow_cpu_exit (struct cpufreq_policy *policy) { | |||
648 | } | 648 | } |
649 | #endif | 649 | #endif |
650 | 650 | ||
651 | if (powernow_table) | 651 | kfree(powernow_table); |
652 | kfree(powernow_table); | ||
653 | |||
654 | return 0; | 652 | return 0; |
655 | } | 653 | } |
656 | 654 | ||
diff --git a/arch/i386/kernel/cpu/intel.c b/arch/i386/kernel/cpu/intel.c index 121aa2176e69..96a75d045835 100644 --- a/arch/i386/kernel/cpu/intel.c +++ b/arch/i386/kernel/cpu/intel.c | |||
@@ -28,7 +28,7 @@ extern int trap_init_f00f_bug(void); | |||
28 | struct movsl_mask movsl_mask; | 28 | struct movsl_mask movsl_mask; |
29 | #endif | 29 | #endif |
30 | 30 | ||
31 | void __init early_intel_workaround(struct cpuinfo_x86 *c) | 31 | void __devinit early_intel_workaround(struct cpuinfo_x86 *c) |
32 | { | 32 | { |
33 | if (c->x86_vendor != X86_VENDOR_INTEL) | 33 | if (c->x86_vendor != X86_VENDOR_INTEL) |
34 | return; | 34 | return; |
@@ -43,7 +43,7 @@ void __init early_intel_workaround(struct cpuinfo_x86 *c) | |||
43 | * This is called before we do cpu ident work | 43 | * This is called before we do cpu ident work |
44 | */ | 44 | */ |
45 | 45 | ||
46 | int __init ppro_with_ram_bug(void) | 46 | int __devinit ppro_with_ram_bug(void) |
47 | { | 47 | { |
48 | /* Uses data from early_cpu_detect now */ | 48 | /* Uses data from early_cpu_detect now */ |
49 | if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && | 49 | if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && |
@@ -61,7 +61,7 @@ int __init ppro_with_ram_bug(void) | |||
61 | * P4 Xeon errata 037 workaround. | 61 | * P4 Xeon errata 037 workaround. |
62 | * Hardware prefetcher may cause stale data to be loaded into the cache. | 62 | * Hardware prefetcher may cause stale data to be loaded into the cache. |
63 | */ | 63 | */ |
64 | static void __init Intel_errata_workarounds(struct cpuinfo_x86 *c) | 64 | static void __devinit Intel_errata_workarounds(struct cpuinfo_x86 *c) |
65 | { | 65 | { |
66 | unsigned long lo, hi; | 66 | unsigned long lo, hi; |
67 | 67 | ||
@@ -80,7 +80,7 @@ static void __init Intel_errata_workarounds(struct cpuinfo_x86 *c) | |||
80 | /* | 80 | /* |
81 | * find out the number of processor cores on the die | 81 | * find out the number of processor cores on the die |
82 | */ | 82 | */ |
83 | static int __init num_cpu_cores(struct cpuinfo_x86 *c) | 83 | static int __devinit num_cpu_cores(struct cpuinfo_x86 *c) |
84 | { | 84 | { |
85 | unsigned int eax; | 85 | unsigned int eax; |
86 | 86 | ||
@@ -98,7 +98,7 @@ static int __init num_cpu_cores(struct cpuinfo_x86 *c) | |||
98 | return 1; | 98 | return 1; |
99 | } | 99 | } |
100 | 100 | ||
101 | static void __init init_intel(struct cpuinfo_x86 *c) | 101 | static void __devinit init_intel(struct cpuinfo_x86 *c) |
102 | { | 102 | { |
103 | unsigned int l2 = 0; | 103 | unsigned int l2 = 0; |
104 | char *p = NULL; | 104 | char *p = NULL; |
@@ -204,7 +204,7 @@ static unsigned int intel_size_cache(struct cpuinfo_x86 * c, unsigned int size) | |||
204 | return size; | 204 | return size; |
205 | } | 205 | } |
206 | 206 | ||
207 | static struct cpu_dev intel_cpu_dev __initdata = { | 207 | static struct cpu_dev intel_cpu_dev __devinitdata = { |
208 | .c_vendor = "Intel", | 208 | .c_vendor = "Intel", |
209 | .c_ident = { "GenuineIntel" }, | 209 | .c_ident = { "GenuineIntel" }, |
210 | .c_models = { | 210 | .c_models = { |
diff --git a/arch/i386/kernel/cpu/intel_cacheinfo.c b/arch/i386/kernel/cpu/intel_cacheinfo.c index a710dc4eb20e..1d768b263269 100644 --- a/arch/i386/kernel/cpu/intel_cacheinfo.c +++ b/arch/i386/kernel/cpu/intel_cacheinfo.c | |||
@@ -28,7 +28,7 @@ struct _cache_table | |||
28 | }; | 28 | }; |
29 | 29 | ||
30 | /* all the cache descriptor types we care about (no TLB or trace cache entries) */ | 30 | /* all the cache descriptor types we care about (no TLB or trace cache entries) */ |
31 | static struct _cache_table cache_table[] __initdata = | 31 | static struct _cache_table cache_table[] __devinitdata = |
32 | { | 32 | { |
33 | { 0x06, LVL_1_INST, 8 }, /* 4-way set assoc, 32 byte line size */ | 33 | { 0x06, LVL_1_INST, 8 }, /* 4-way set assoc, 32 byte line size */ |
34 | { 0x08, LVL_1_INST, 16 }, /* 4-way set assoc, 32 byte line size */ | 34 | { 0x08, LVL_1_INST, 16 }, /* 4-way set assoc, 32 byte line size */ |
@@ -160,7 +160,7 @@ static int __init find_num_cache_leaves(void) | |||
160 | return retval; | 160 | return retval; |
161 | } | 161 | } |
162 | 162 | ||
163 | unsigned int __init init_intel_cacheinfo(struct cpuinfo_x86 *c) | 163 | unsigned int __devinit init_intel_cacheinfo(struct cpuinfo_x86 *c) |
164 | { | 164 | { |
165 | unsigned int trace = 0, l1i = 0, l1d = 0, l2 = 0, l3 = 0; /* Cache sizes */ | 165 | unsigned int trace = 0, l1i = 0, l1d = 0, l2 = 0, l3 = 0; /* Cache sizes */ |
166 | unsigned int new_l1d = 0, new_l1i = 0; /* Cache sizes from cpuid(4) */ | 166 | unsigned int new_l1d = 0, new_l1i = 0; /* Cache sizes from cpuid(4) */ |
diff --git a/arch/i386/kernel/cpu/mcheck/k7.c b/arch/i386/kernel/cpu/mcheck/k7.c index 8df52e86c4d2..c4abe7657397 100644 --- a/arch/i386/kernel/cpu/mcheck/k7.c +++ b/arch/i386/kernel/cpu/mcheck/k7.c | |||
@@ -69,7 +69,7 @@ static fastcall void k7_machine_check(struct pt_regs * regs, long error_code) | |||
69 | 69 | ||
70 | 70 | ||
71 | /* AMD K7 machine check is Intel like */ | 71 | /* AMD K7 machine check is Intel like */ |
72 | void __init amd_mcheck_init(struct cpuinfo_x86 *c) | 72 | void __devinit amd_mcheck_init(struct cpuinfo_x86 *c) |
73 | { | 73 | { |
74 | u32 l, h; | 74 | u32 l, h; |
75 | int i; | 75 | int i; |
diff --git a/arch/i386/kernel/cpu/mcheck/mce.c b/arch/i386/kernel/cpu/mcheck/mce.c index bf6d1aefafc0..2cf25d2ba0f1 100644 --- a/arch/i386/kernel/cpu/mcheck/mce.c +++ b/arch/i386/kernel/cpu/mcheck/mce.c | |||
@@ -16,7 +16,7 @@ | |||
16 | 16 | ||
17 | #include "mce.h" | 17 | #include "mce.h" |
18 | 18 | ||
19 | int mce_disabled __initdata = 0; | 19 | int mce_disabled __devinitdata = 0; |
20 | int nr_mce_banks; | 20 | int nr_mce_banks; |
21 | 21 | ||
22 | EXPORT_SYMBOL_GPL(nr_mce_banks); /* non-fatal.o */ | 22 | EXPORT_SYMBOL_GPL(nr_mce_banks); /* non-fatal.o */ |
@@ -31,7 +31,7 @@ static fastcall void unexpected_machine_check(struct pt_regs * regs, long error_ | |||
31 | void fastcall (*machine_check_vector)(struct pt_regs *, long error_code) = unexpected_machine_check; | 31 | void fastcall (*machine_check_vector)(struct pt_regs *, long error_code) = unexpected_machine_check; |
32 | 32 | ||
33 | /* This has to be run for each processor */ | 33 | /* This has to be run for each processor */ |
34 | void __init mcheck_init(struct cpuinfo_x86 *c) | 34 | void __devinit mcheck_init(struct cpuinfo_x86 *c) |
35 | { | 35 | { |
36 | if (mce_disabled==1) | 36 | if (mce_disabled==1) |
37 | return; | 37 | return; |
diff --git a/arch/i386/kernel/cpu/mcheck/p4.c b/arch/i386/kernel/cpu/mcheck/p4.c index 8b16ceb929b4..0abccb6fdf9e 100644 --- a/arch/i386/kernel/cpu/mcheck/p4.c +++ b/arch/i386/kernel/cpu/mcheck/p4.c | |||
@@ -78,7 +78,7 @@ fastcall void smp_thermal_interrupt(struct pt_regs *regs) | |||
78 | } | 78 | } |
79 | 79 | ||
80 | /* P4/Xeon Thermal regulation detect and init */ | 80 | /* P4/Xeon Thermal regulation detect and init */ |
81 | static void __init intel_init_thermal(struct cpuinfo_x86 *c) | 81 | static void __devinit intel_init_thermal(struct cpuinfo_x86 *c) |
82 | { | 82 | { |
83 | u32 l, h; | 83 | u32 l, h; |
84 | unsigned int cpu = smp_processor_id(); | 84 | unsigned int cpu = smp_processor_id(); |
@@ -232,7 +232,7 @@ static fastcall void intel_machine_check(struct pt_regs * regs, long error_code) | |||
232 | } | 232 | } |
233 | 233 | ||
234 | 234 | ||
235 | void __init intel_p4_mcheck_init(struct cpuinfo_x86 *c) | 235 | void __devinit intel_p4_mcheck_init(struct cpuinfo_x86 *c) |
236 | { | 236 | { |
237 | u32 l, h; | 237 | u32 l, h; |
238 | int i; | 238 | int i; |
diff --git a/arch/i386/kernel/cpu/mcheck/p5.c b/arch/i386/kernel/cpu/mcheck/p5.c index c45a1b485c80..ec0614cd2925 100644 --- a/arch/i386/kernel/cpu/mcheck/p5.c +++ b/arch/i386/kernel/cpu/mcheck/p5.c | |||
@@ -29,7 +29,7 @@ static fastcall void pentium_machine_check(struct pt_regs * regs, long error_cod | |||
29 | } | 29 | } |
30 | 30 | ||
31 | /* Set up machine check reporting for processors with Intel style MCE */ | 31 | /* Set up machine check reporting for processors with Intel style MCE */ |
32 | void __init intel_p5_mcheck_init(struct cpuinfo_x86 *c) | 32 | void __devinit intel_p5_mcheck_init(struct cpuinfo_x86 *c) |
33 | { | 33 | { |
34 | u32 l, h; | 34 | u32 l, h; |
35 | 35 | ||
diff --git a/arch/i386/kernel/cpu/mcheck/p6.c b/arch/i386/kernel/cpu/mcheck/p6.c index 46640f8c2494..f01b73f947e1 100644 --- a/arch/i386/kernel/cpu/mcheck/p6.c +++ b/arch/i386/kernel/cpu/mcheck/p6.c | |||
@@ -80,7 +80,7 @@ static fastcall void intel_machine_check(struct pt_regs * regs, long error_code) | |||
80 | } | 80 | } |
81 | 81 | ||
82 | /* Set up machine check reporting for processors with Intel style MCE */ | 82 | /* Set up machine check reporting for processors with Intel style MCE */ |
83 | void __init intel_p6_mcheck_init(struct cpuinfo_x86 *c) | 83 | void __devinit intel_p6_mcheck_init(struct cpuinfo_x86 *c) |
84 | { | 84 | { |
85 | u32 l, h; | 85 | u32 l, h; |
86 | int i; | 86 | int i; |
diff --git a/arch/i386/kernel/cpu/mcheck/winchip.c b/arch/i386/kernel/cpu/mcheck/winchip.c index 753fa7acb984..7bae68fa168f 100644 --- a/arch/i386/kernel/cpu/mcheck/winchip.c +++ b/arch/i386/kernel/cpu/mcheck/winchip.c | |||
@@ -23,7 +23,7 @@ static fastcall void winchip_machine_check(struct pt_regs * regs, long error_cod | |||
23 | } | 23 | } |
24 | 24 | ||
25 | /* Set up machine check reporting on the Winchip C6 series */ | 25 | /* Set up machine check reporting on the Winchip C6 series */ |
26 | void __init winchip_mcheck_init(struct cpuinfo_x86 *c) | 26 | void __devinit winchip_mcheck_init(struct cpuinfo_x86 *c) |
27 | { | 27 | { |
28 | u32 lo, hi; | 28 | u32 lo, hi; |
29 | machine_check_vector = winchip_machine_check; | 29 | machine_check_vector = winchip_machine_check; |
diff --git a/arch/i386/kernel/cpu/mtrr/generic.c b/arch/i386/kernel/cpu/mtrr/generic.c index f468a979e9aa..64d91f73a0a4 100644 --- a/arch/i386/kernel/cpu/mtrr/generic.c +++ b/arch/i386/kernel/cpu/mtrr/generic.c | |||
@@ -70,8 +70,7 @@ void __init get_mtrr_state(void) | |||
70 | /* Free resources associated with a struct mtrr_state */ | 70 | /* Free resources associated with a struct mtrr_state */ |
71 | void __init finalize_mtrr_state(void) | 71 | void __init finalize_mtrr_state(void) |
72 | { | 72 | { |
73 | if (mtrr_state.var_ranges) | 73 | kfree(mtrr_state.var_ranges); |
74 | kfree(mtrr_state.var_ranges); | ||
75 | mtrr_state.var_ranges = NULL; | 74 | mtrr_state.var_ranges = NULL; |
76 | } | 75 | } |
77 | 76 | ||
diff --git a/arch/i386/kernel/crash.c b/arch/i386/kernel/crash.c new file mode 100644 index 000000000000..e5fab12f7926 --- /dev/null +++ b/arch/i386/kernel/crash.c | |||
@@ -0,0 +1,223 @@ | |||
1 | /* | ||
2 | * Architecture specific (i386) functions for kexec based crash dumps. | ||
3 | * | ||
4 | * Created by: Hariprasad Nellitheertha (hari@in.ibm.com) | ||
5 | * | ||
6 | * Copyright (C) IBM Corporation, 2004. All rights reserved. | ||
7 | * | ||
8 | */ | ||
9 | |||
10 | #include <linux/init.h> | ||
11 | #include <linux/types.h> | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/smp.h> | ||
14 | #include <linux/irq.h> | ||
15 | #include <linux/reboot.h> | ||
16 | #include <linux/kexec.h> | ||
17 | #include <linux/irq.h> | ||
18 | #include <linux/delay.h> | ||
19 | #include <linux/elf.h> | ||
20 | #include <linux/elfcore.h> | ||
21 | |||
22 | #include <asm/processor.h> | ||
23 | #include <asm/hardirq.h> | ||
24 | #include <asm/nmi.h> | ||
25 | #include <asm/hw_irq.h> | ||
26 | #include <asm/apic.h> | ||
27 | #include <mach_ipi.h> | ||
28 | |||
29 | |||
30 | note_buf_t crash_notes[NR_CPUS]; | ||
31 | /* This keeps a track of which one is crashing cpu. */ | ||
32 | static int crashing_cpu; | ||
33 | |||
34 | static u32 *append_elf_note(u32 *buf, char *name, unsigned type, void *data, | ||
35 | size_t data_len) | ||
36 | { | ||
37 | struct elf_note note; | ||
38 | |||
39 | note.n_namesz = strlen(name) + 1; | ||
40 | note.n_descsz = data_len; | ||
41 | note.n_type = type; | ||
42 | memcpy(buf, ¬e, sizeof(note)); | ||
43 | buf += (sizeof(note) +3)/4; | ||
44 | memcpy(buf, name, note.n_namesz); | ||
45 | buf += (note.n_namesz + 3)/4; | ||
46 | memcpy(buf, data, note.n_descsz); | ||
47 | buf += (note.n_descsz + 3)/4; | ||
48 | |||
49 | return buf; | ||
50 | } | ||
51 | |||
52 | static void final_note(u32 *buf) | ||
53 | { | ||
54 | struct elf_note note; | ||
55 | |||
56 | note.n_namesz = 0; | ||
57 | note.n_descsz = 0; | ||
58 | note.n_type = 0; | ||
59 | memcpy(buf, ¬e, sizeof(note)); | ||
60 | } | ||
61 | |||
62 | static void crash_save_this_cpu(struct pt_regs *regs, int cpu) | ||
63 | { | ||
64 | struct elf_prstatus prstatus; | ||
65 | u32 *buf; | ||
66 | |||
67 | if ((cpu < 0) || (cpu >= NR_CPUS)) | ||
68 | return; | ||
69 | |||
70 | /* Using ELF notes here is opportunistic. | ||
71 | * I need a well defined structure format | ||
72 | * for the data I pass, and I need tags | ||
73 | * on the data to indicate what information I have | ||
74 | * squirrelled away. ELF notes happen to provide | ||
75 | * all of that that no need to invent something new. | ||
76 | */ | ||
77 | buf = &crash_notes[cpu][0]; | ||
78 | memset(&prstatus, 0, sizeof(prstatus)); | ||
79 | prstatus.pr_pid = current->pid; | ||
80 | elf_core_copy_regs(&prstatus.pr_reg, regs); | ||
81 | buf = append_elf_note(buf, "CORE", NT_PRSTATUS, &prstatus, | ||
82 | sizeof(prstatus)); | ||
83 | final_note(buf); | ||
84 | } | ||
85 | |||
86 | static void crash_get_current_regs(struct pt_regs *regs) | ||
87 | { | ||
88 | __asm__ __volatile__("movl %%ebx,%0" : "=m"(regs->ebx)); | ||
89 | __asm__ __volatile__("movl %%ecx,%0" : "=m"(regs->ecx)); | ||
90 | __asm__ __volatile__("movl %%edx,%0" : "=m"(regs->edx)); | ||
91 | __asm__ __volatile__("movl %%esi,%0" : "=m"(regs->esi)); | ||
92 | __asm__ __volatile__("movl %%edi,%0" : "=m"(regs->edi)); | ||
93 | __asm__ __volatile__("movl %%ebp,%0" : "=m"(regs->ebp)); | ||
94 | __asm__ __volatile__("movl %%eax,%0" : "=m"(regs->eax)); | ||
95 | __asm__ __volatile__("movl %%esp,%0" : "=m"(regs->esp)); | ||
96 | __asm__ __volatile__("movw %%ss, %%ax;" :"=a"(regs->xss)); | ||
97 | __asm__ __volatile__("movw %%cs, %%ax;" :"=a"(regs->xcs)); | ||
98 | __asm__ __volatile__("movw %%ds, %%ax;" :"=a"(regs->xds)); | ||
99 | __asm__ __volatile__("movw %%es, %%ax;" :"=a"(regs->xes)); | ||
100 | __asm__ __volatile__("pushfl; popl %0" :"=m"(regs->eflags)); | ||
101 | |||
102 | regs->eip = (unsigned long)current_text_addr(); | ||
103 | } | ||
104 | |||
105 | /* CPU does not save ss and esp on stack if execution is already | ||
106 | * running in kernel mode at the time of NMI occurrence. This code | ||
107 | * fixes it. | ||
108 | */ | ||
109 | static void crash_setup_regs(struct pt_regs *newregs, struct pt_regs *oldregs) | ||
110 | { | ||
111 | memcpy(newregs, oldregs, sizeof(*newregs)); | ||
112 | newregs->esp = (unsigned long)&(oldregs->esp); | ||
113 | __asm__ __volatile__("xorl %eax, %eax;"); | ||
114 | __asm__ __volatile__ ("movw %%ss, %%ax;" :"=a"(newregs->xss)); | ||
115 | } | ||
116 | |||
117 | /* We may have saved_regs from where the error came from | ||
118 | * or it is NULL if via a direct panic(). | ||
119 | */ | ||
120 | static void crash_save_self(struct pt_regs *saved_regs) | ||
121 | { | ||
122 | struct pt_regs regs; | ||
123 | int cpu; | ||
124 | |||
125 | cpu = smp_processor_id(); | ||
126 | if (saved_regs) | ||
127 | crash_setup_regs(®s, saved_regs); | ||
128 | else | ||
129 | crash_get_current_regs(®s); | ||
130 | crash_save_this_cpu(®s, cpu); | ||
131 | } | ||
132 | |||
133 | #ifdef CONFIG_SMP | ||
134 | static atomic_t waiting_for_crash_ipi; | ||
135 | |||
136 | static int crash_nmi_callback(struct pt_regs *regs, int cpu) | ||
137 | { | ||
138 | struct pt_regs fixed_regs; | ||
139 | |||
140 | /* Don't do anything if this handler is invoked on crashing cpu. | ||
141 | * Otherwise, system will completely hang. Crashing cpu can get | ||
142 | * an NMI if system was initially booted with nmi_watchdog parameter. | ||
143 | */ | ||
144 | if (cpu == crashing_cpu) | ||
145 | return 1; | ||
146 | local_irq_disable(); | ||
147 | |||
148 | if (!user_mode(regs)) { | ||
149 | crash_setup_regs(&fixed_regs, regs); | ||
150 | regs = &fixed_regs; | ||
151 | } | ||
152 | crash_save_this_cpu(regs, cpu); | ||
153 | disable_local_APIC(); | ||
154 | atomic_dec(&waiting_for_crash_ipi); | ||
155 | /* Assume hlt works */ | ||
156 | __asm__("hlt"); | ||
157 | for(;;); | ||
158 | |||
159 | return 1; | ||
160 | } | ||
161 | |||
162 | /* | ||
163 | * By using the NMI code instead of a vector we just sneak thru the | ||
164 | * word generator coming out with just what we want. AND it does | ||
165 | * not matter if clustered_apic_mode is set or not. | ||
166 | */ | ||
167 | static void smp_send_nmi_allbutself(void) | ||
168 | { | ||
169 | send_IPI_allbutself(APIC_DM_NMI); | ||
170 | } | ||
171 | |||
172 | static void nmi_shootdown_cpus(void) | ||
173 | { | ||
174 | unsigned long msecs; | ||
175 | |||
176 | atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1); | ||
177 | /* Would it be better to replace the trap vector here? */ | ||
178 | set_nmi_callback(crash_nmi_callback); | ||
179 | /* Ensure the new callback function is set before sending | ||
180 | * out the NMI | ||
181 | */ | ||
182 | wmb(); | ||
183 | |||
184 | smp_send_nmi_allbutself(); | ||
185 | |||
186 | msecs = 1000; /* Wait at most a second for the other cpus to stop */ | ||
187 | while ((atomic_read(&waiting_for_crash_ipi) > 0) && msecs) { | ||
188 | mdelay(1); | ||
189 | msecs--; | ||
190 | } | ||
191 | |||
192 | /* Leave the nmi callback set */ | ||
193 | disable_local_APIC(); | ||
194 | } | ||
195 | #else | ||
196 | static void nmi_shootdown_cpus(void) | ||
197 | { | ||
198 | /* There are no cpus to shootdown */ | ||
199 | } | ||
200 | #endif | ||
201 | |||
202 | void machine_crash_shutdown(struct pt_regs *regs) | ||
203 | { | ||
204 | /* This function is only called after the system | ||
205 | * has paniced or is otherwise in a critical state. | ||
206 | * The minimum amount of code to allow a kexec'd kernel | ||
207 | * to run successfully needs to happen here. | ||
208 | * | ||
209 | * In practice this means shooting down the other cpus in | ||
210 | * an SMP system. | ||
211 | */ | ||
212 | /* The kernel is broken so disable interrupts */ | ||
213 | local_irq_disable(); | ||
214 | |||
215 | /* Make a note of crashing cpu. Will be used in NMI callback.*/ | ||
216 | crashing_cpu = smp_processor_id(); | ||
217 | nmi_shootdown_cpus(); | ||
218 | lapic_shutdown(); | ||
219 | #if defined(CONFIG_X86_IO_APIC) | ||
220 | disable_IO_APIC(); | ||
221 | #endif | ||
222 | crash_save_self(regs); | ||
223 | } | ||
diff --git a/arch/i386/kernel/dmi_scan.c b/arch/i386/kernel/dmi_scan.c index 6ed7e28f306c..a3cdf894302b 100644 --- a/arch/i386/kernel/dmi_scan.c +++ b/arch/i386/kernel/dmi_scan.c | |||
@@ -1,22 +1,15 @@ | |||
1 | #include <linux/types.h> | 1 | #include <linux/types.h> |
2 | #include <linux/kernel.h> | ||
3 | #include <linux/string.h> | 2 | #include <linux/string.h> |
4 | #include <linux/init.h> | 3 | #include <linux/init.h> |
5 | #include <linux/module.h> | 4 | #include <linux/module.h> |
6 | #include <linux/slab.h> | ||
7 | #include <linux/acpi.h> | ||
8 | #include <asm/io.h> | ||
9 | #include <linux/pm.h> | ||
10 | #include <asm/system.h> | ||
11 | #include <linux/dmi.h> | 5 | #include <linux/dmi.h> |
12 | #include <linux/bootmem.h> | 6 | #include <linux/bootmem.h> |
13 | 7 | ||
14 | 8 | ||
15 | struct dmi_header | 9 | struct dmi_header { |
16 | { | 10 | u8 type; |
17 | u8 type; | 11 | u8 length; |
18 | u8 length; | 12 | u16 handle; |
19 | u16 handle; | ||
20 | }; | 13 | }; |
21 | 14 | ||
22 | #undef DMI_DEBUG | 15 | #undef DMI_DEBUG |
@@ -29,15 +22,13 @@ struct dmi_header | |||
29 | 22 | ||
30 | static char * __init dmi_string(struct dmi_header *dm, u8 s) | 23 | static char * __init dmi_string(struct dmi_header *dm, u8 s) |
31 | { | 24 | { |
32 | u8 *bp=(u8 *)dm; | 25 | u8 *bp = ((u8 *) dm) + dm->length; |
33 | bp+=dm->length; | 26 | |
34 | if(!s) | 27 | if (!s) |
35 | return ""; | 28 | return ""; |
36 | s--; | 29 | s--; |
37 | while(s>0 && *bp) | 30 | while (s > 0 && *bp) { |
38 | { | 31 | bp += strlen(bp) + 1; |
39 | bp+=strlen(bp); | ||
40 | bp++; | ||
41 | s--; | 32 | s--; |
42 | } | 33 | } |
43 | return bp; | 34 | return bp; |
@@ -47,16 +38,14 @@ static char * __init dmi_string(struct dmi_header *dm, u8 s) | |||
47 | * We have to be cautious here. We have seen BIOSes with DMI pointers | 38 | * We have to be cautious here. We have seen BIOSes with DMI pointers |
48 | * pointing to completely the wrong place for example | 39 | * pointing to completely the wrong place for example |
49 | */ | 40 | */ |
50 | 41 | static int __init dmi_table(u32 base, int len, int num, | |
51 | static int __init dmi_table(u32 base, int len, int num, void (*decode)(struct dmi_header *)) | 42 | void (*decode)(struct dmi_header *)) |
52 | { | 43 | { |
53 | u8 *buf; | 44 | u8 *buf, *data; |
54 | struct dmi_header *dm; | 45 | int i = 0; |
55 | u8 *data; | ||
56 | int i=0; | ||
57 | 46 | ||
58 | buf = bt_ioremap(base, len); | 47 | buf = bt_ioremap(base, len); |
59 | if(buf==NULL) | 48 | if (buf == NULL) |
60 | return -1; | 49 | return -1; |
61 | 50 | ||
62 | data = buf; | 51 | data = buf; |
@@ -65,36 +54,34 @@ static int __init dmi_table(u32 base, int len, int num, void (*decode)(struct dm | |||
65 | * Stop when we see all the items the table claimed to have | 54 | * Stop when we see all the items the table claimed to have |
66 | * OR we run off the end of the table (also happens) | 55 | * OR we run off the end of the table (also happens) |
67 | */ | 56 | */ |
68 | 57 | while ((i < num) && (data - buf + sizeof(struct dmi_header)) <= len) { | |
69 | while(i<num && data-buf+sizeof(struct dmi_header)<=len) | 58 | struct dmi_header *dm = (struct dmi_header *)data; |
70 | { | ||
71 | dm=(struct dmi_header *)data; | ||
72 | /* | 59 | /* |
73 | * We want to know the total length (formated area and strings) | 60 | * We want to know the total length (formated area and strings) |
74 | * before decoding to make sure we won't run off the table in | 61 | * before decoding to make sure we won't run off the table in |
75 | * dmi_decode or dmi_string | 62 | * dmi_decode or dmi_string |
76 | */ | 63 | */ |
77 | data+=dm->length; | 64 | data += dm->length; |
78 | while(data-buf<len-1 && (data[0] || data[1])) | 65 | while ((data - buf < len - 1) && (data[0] || data[1])) |
79 | data++; | 66 | data++; |
80 | if(data-buf<len-1) | 67 | if (data - buf < len - 1) |
81 | decode(dm); | 68 | decode(dm); |
82 | data+=2; | 69 | data += 2; |
83 | i++; | 70 | i++; |
84 | } | 71 | } |
85 | bt_iounmap(buf, len); | 72 | bt_iounmap(buf, len); |
86 | return 0; | 73 | return 0; |
87 | } | 74 | } |
88 | 75 | ||
89 | 76 | static int __init dmi_checksum(u8 *buf) | |
90 | inline static int __init dmi_checksum(u8 *buf) | ||
91 | { | 77 | { |
92 | u8 sum=0; | 78 | u8 sum = 0; |
93 | int a; | 79 | int a; |
94 | 80 | ||
95 | for(a=0; a<15; a++) | 81 | for (a = 0; a < 15; a++) |
96 | sum+=buf[a]; | 82 | sum += buf[a]; |
97 | return (sum==0); | 83 | |
84 | return sum == 0; | ||
98 | } | 85 | } |
99 | 86 | ||
100 | static int __init dmi_iterate(void (*decode)(struct dmi_header *)) | 87 | static int __init dmi_iterate(void (*decode)(struct dmi_header *)) |
@@ -110,28 +97,30 @@ static int __init dmi_iterate(void (*decode)(struct dmi_header *)) | |||
110 | p = ioremap(0xF0000, 0x10000); | 97 | p = ioremap(0xF0000, 0x10000); |
111 | if (p == NULL) | 98 | if (p == NULL) |
112 | return -1; | 99 | return -1; |
100 | |||
113 | for (q = p; q < p + 0x10000; q += 16) { | 101 | for (q = p; q < p + 0x10000; q += 16) { |
114 | memcpy_fromio(buf, q, 15); | 102 | memcpy_fromio(buf, q, 15); |
115 | if(memcmp(buf, "_DMI_", 5)==0 && dmi_checksum(buf)) | 103 | if ((memcmp(buf, "_DMI_", 5) == 0) && dmi_checksum(buf)) { |
116 | { | 104 | u16 num = (buf[13] << 8) | buf[12]; |
117 | u16 num=buf[13]<<8|buf[12]; | 105 | u16 len = (buf[7] << 8) | buf[6]; |
118 | u16 len=buf[7]<<8|buf[6]; | 106 | u32 base = (buf[11] << 24) | (buf[10] << 16) | |
119 | u32 base=buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8]; | 107 | (buf[9] << 8) | buf[8]; |
120 | 108 | ||
121 | /* | 109 | /* |
122 | * DMI version 0.0 means that the real version is taken from | 110 | * DMI version 0.0 means that the real version is taken from |
123 | * the SMBIOS version, which we don't know at this point. | 111 | * the SMBIOS version, which we don't know at this point. |
124 | */ | 112 | */ |
125 | if(buf[14]!=0) | 113 | if (buf[14] != 0) |
126 | printk(KERN_INFO "DMI %d.%d present.\n", | 114 | printk(KERN_INFO "DMI %d.%d present.\n", |
127 | buf[14]>>4, buf[14]&0x0F); | 115 | buf[14] >> 4, buf[14] & 0xF); |
128 | else | 116 | else |
129 | printk(KERN_INFO "DMI present.\n"); | 117 | printk(KERN_INFO "DMI present.\n"); |
118 | |||
130 | dmi_printk((KERN_INFO "%d structures occupying %d bytes.\n", | 119 | dmi_printk((KERN_INFO "%d structures occupying %d bytes.\n", |
131 | num, len)); | 120 | num, len)); |
132 | dmi_printk((KERN_INFO "DMI table at 0x%08X.\n", | 121 | dmi_printk((KERN_INFO "DMI table at 0x%08X.\n", base)); |
133 | base)); | 122 | |
134 | if(dmi_table(base,len, num, decode)==0) | 123 | if (dmi_table(base,len, num, decode) == 0) |
135 | return 0; | 124 | return 0; |
136 | } | 125 | } |
137 | } | 126 | } |
@@ -143,16 +132,17 @@ static char *dmi_ident[DMI_STRING_MAX]; | |||
143 | /* | 132 | /* |
144 | * Save a DMI string | 133 | * Save a DMI string |
145 | */ | 134 | */ |
146 | |||
147 | static void __init dmi_save_ident(struct dmi_header *dm, int slot, int string) | 135 | static void __init dmi_save_ident(struct dmi_header *dm, int slot, int string) |
148 | { | 136 | { |
149 | char *d = (char*)dm; | 137 | char *d = (char*)dm; |
150 | char *p = dmi_string(dm, d[string]); | 138 | char *p = dmi_string(dm, d[string]); |
151 | if(p==NULL || *p == 0) | 139 | |
140 | if (p == NULL || *p == 0) | ||
152 | return; | 141 | return; |
153 | if (dmi_ident[slot]) | 142 | if (dmi_ident[slot]) |
154 | return; | 143 | return; |
155 | dmi_ident[slot] = alloc_bootmem(strlen(p)+1); | 144 | |
145 | dmi_ident[slot] = alloc_bootmem(strlen(p) + 1); | ||
156 | if(dmi_ident[slot]) | 146 | if(dmi_ident[slot]) |
157 | strcpy(dmi_ident[slot], p); | 147 | strcpy(dmi_ident[slot], p); |
158 | else | 148 | else |
@@ -160,281 +150,47 @@ static void __init dmi_save_ident(struct dmi_header *dm, int slot, int string) | |||
160 | } | 150 | } |
161 | 151 | ||
162 | /* | 152 | /* |
163 | * Ugly compatibility crap. | ||
164 | */ | ||
165 | #define dmi_blacklist dmi_system_id | ||
166 | #define NO_MATCH { DMI_NONE, NULL} | ||
167 | #define MATCH DMI_MATCH | ||
168 | |||
169 | /* | ||
170 | * Toshiba keyboard likes to repeat keys when they are not repeated. | ||
171 | */ | ||
172 | |||
173 | static __init int broken_toshiba_keyboard(struct dmi_blacklist *d) | ||
174 | { | ||
175 | printk(KERN_WARNING "Toshiba with broken keyboard detected. If your keyboard sometimes generates 3 keypresses instead of one, see http://davyd.ucc.asn.au/projects/toshiba/README\n"); | ||
176 | return 0; | ||
177 | } | ||
178 | |||
179 | |||
180 | #ifdef CONFIG_ACPI_SLEEP | ||
181 | static __init int reset_videomode_after_s3(struct dmi_blacklist *d) | ||
182 | { | ||
183 | /* See acpi_wakeup.S */ | ||
184 | extern long acpi_video_flags; | ||
185 | acpi_video_flags |= 2; | ||
186 | return 0; | ||
187 | } | ||
188 | #endif | ||
189 | |||
190 | |||
191 | #ifdef CONFIG_ACPI_BOOT | ||
192 | extern int acpi_force; | ||
193 | |||
194 | static __init __attribute__((unused)) int dmi_disable_acpi(struct dmi_blacklist *d) | ||
195 | { | ||
196 | if (!acpi_force) { | ||
197 | printk(KERN_NOTICE "%s detected: acpi off\n",d->ident); | ||
198 | disable_acpi(); | ||
199 | } else { | ||
200 | printk(KERN_NOTICE | ||
201 | "Warning: DMI blacklist says broken, but acpi forced\n"); | ||
202 | } | ||
203 | return 0; | ||
204 | } | ||
205 | |||
206 | /* | ||
207 | * Limit ACPI to CPU enumeration for HT | ||
208 | */ | ||
209 | static __init __attribute__((unused)) int force_acpi_ht(struct dmi_blacklist *d) | ||
210 | { | ||
211 | if (!acpi_force) { | ||
212 | printk(KERN_NOTICE "%s detected: force use of acpi=ht\n", d->ident); | ||
213 | disable_acpi(); | ||
214 | acpi_ht = 1; | ||
215 | } else { | ||
216 | printk(KERN_NOTICE | ||
217 | "Warning: acpi=force overrules DMI blacklist: acpi=ht\n"); | ||
218 | } | ||
219 | return 0; | ||
220 | } | ||
221 | #endif | ||
222 | |||
223 | #ifdef CONFIG_ACPI_PCI | ||
224 | static __init int disable_acpi_irq(struct dmi_blacklist *d) | ||
225 | { | ||
226 | if (!acpi_force) { | ||
227 | printk(KERN_NOTICE "%s detected: force use of acpi=noirq\n", | ||
228 | d->ident); | ||
229 | acpi_noirq_set(); | ||
230 | } | ||
231 | return 0; | ||
232 | } | ||
233 | static __init int disable_acpi_pci(struct dmi_blacklist *d) | ||
234 | { | ||
235 | if (!acpi_force) { | ||
236 | printk(KERN_NOTICE "%s detected: force use of pci=noacpi\n", | ||
237 | d->ident); | ||
238 | acpi_disable_pci(); | ||
239 | } | ||
240 | return 0; | ||
241 | } | ||
242 | #endif | ||
243 | |||
244 | /* | ||
245 | * Process the DMI blacklists | ||
246 | */ | ||
247 | |||
248 | |||
249 | /* | ||
250 | * This will be expanded over time to force things like the APM | ||
251 | * interrupt mask settings according to the laptop | ||
252 | */ | ||
253 | |||
254 | static __initdata struct dmi_blacklist dmi_blacklist[]={ | ||
255 | |||
256 | { broken_toshiba_keyboard, "Toshiba Satellite 4030cdt", { /* Keyboard generates spurious repeats */ | ||
257 | MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"), | ||
258 | NO_MATCH, NO_MATCH, NO_MATCH | ||
259 | } }, | ||
260 | #ifdef CONFIG_ACPI_SLEEP | ||
261 | { reset_videomode_after_s3, "Toshiba Satellite 4030cdt", { /* Reset video mode after returning from ACPI S3 sleep */ | ||
262 | MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"), | ||
263 | NO_MATCH, NO_MATCH, NO_MATCH | ||
264 | } }, | ||
265 | #endif | ||
266 | |||
267 | #ifdef CONFIG_ACPI_BOOT | ||
268 | /* | ||
269 | * If your system is blacklisted here, but you find that acpi=force | ||
270 | * works for you, please contact acpi-devel@sourceforge.net | ||
271 | */ | ||
272 | |||
273 | /* | ||
274 | * Boxes that need ACPI disabled | ||
275 | */ | ||
276 | |||
277 | { dmi_disable_acpi, "IBM Thinkpad", { | ||
278 | MATCH(DMI_BOARD_VENDOR, "IBM"), | ||
279 | MATCH(DMI_BOARD_NAME, "2629H1G"), | ||
280 | NO_MATCH, NO_MATCH }}, | ||
281 | |||
282 | /* | ||
283 | * Boxes that need acpi=ht | ||
284 | */ | ||
285 | |||
286 | { force_acpi_ht, "FSC Primergy T850", { | ||
287 | MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), | ||
288 | MATCH(DMI_PRODUCT_NAME, "PRIMERGY T850"), | ||
289 | NO_MATCH, NO_MATCH }}, | ||
290 | |||
291 | { force_acpi_ht, "DELL GX240", { | ||
292 | MATCH(DMI_BOARD_VENDOR, "Dell Computer Corporation"), | ||
293 | MATCH(DMI_BOARD_NAME, "OptiPlex GX240"), | ||
294 | NO_MATCH, NO_MATCH }}, | ||
295 | |||
296 | { force_acpi_ht, "HP VISUALIZE NT Workstation", { | ||
297 | MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"), | ||
298 | MATCH(DMI_PRODUCT_NAME, "HP VISUALIZE NT Workstation"), | ||
299 | NO_MATCH, NO_MATCH }}, | ||
300 | |||
301 | { force_acpi_ht, "Compaq Workstation W8000", { | ||
302 | MATCH(DMI_SYS_VENDOR, "Compaq"), | ||
303 | MATCH(DMI_PRODUCT_NAME, "Workstation W8000"), | ||
304 | NO_MATCH, NO_MATCH }}, | ||
305 | |||
306 | { force_acpi_ht, "ASUS P4B266", { | ||
307 | MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), | ||
308 | MATCH(DMI_BOARD_NAME, "P4B266"), | ||
309 | NO_MATCH, NO_MATCH }}, | ||
310 | |||
311 | { force_acpi_ht, "ASUS P2B-DS", { | ||
312 | MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), | ||
313 | MATCH(DMI_BOARD_NAME, "P2B-DS"), | ||
314 | NO_MATCH, NO_MATCH }}, | ||
315 | |||
316 | { force_acpi_ht, "ASUS CUR-DLS", { | ||
317 | MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), | ||
318 | MATCH(DMI_BOARD_NAME, "CUR-DLS"), | ||
319 | NO_MATCH, NO_MATCH }}, | ||
320 | |||
321 | { force_acpi_ht, "ABIT i440BX-W83977", { | ||
322 | MATCH(DMI_BOARD_VENDOR, "ABIT <http://www.abit.com>"), | ||
323 | MATCH(DMI_BOARD_NAME, "i440BX-W83977 (BP6)"), | ||
324 | NO_MATCH, NO_MATCH }}, | ||
325 | |||
326 | { force_acpi_ht, "IBM Bladecenter", { | ||
327 | MATCH(DMI_BOARD_VENDOR, "IBM"), | ||
328 | MATCH(DMI_BOARD_NAME, "IBM eServer BladeCenter HS20"), | ||
329 | NO_MATCH, NO_MATCH }}, | ||
330 | |||
331 | { force_acpi_ht, "IBM eServer xSeries 360", { | ||
332 | MATCH(DMI_BOARD_VENDOR, "IBM"), | ||
333 | MATCH(DMI_BOARD_NAME, "eServer xSeries 360"), | ||
334 | NO_MATCH, NO_MATCH }}, | ||
335 | |||
336 | { force_acpi_ht, "IBM eserver xSeries 330", { | ||
337 | MATCH(DMI_BOARD_VENDOR, "IBM"), | ||
338 | MATCH(DMI_BOARD_NAME, "eserver xSeries 330"), | ||
339 | NO_MATCH, NO_MATCH }}, | ||
340 | |||
341 | { force_acpi_ht, "IBM eserver xSeries 440", { | ||
342 | MATCH(DMI_BOARD_VENDOR, "IBM"), | ||
343 | MATCH(DMI_PRODUCT_NAME, "eserver xSeries 440"), | ||
344 | NO_MATCH, NO_MATCH }}, | ||
345 | |||
346 | #endif // CONFIG_ACPI_BOOT | ||
347 | |||
348 | #ifdef CONFIG_ACPI_PCI | ||
349 | /* | ||
350 | * Boxes that need ACPI PCI IRQ routing disabled | ||
351 | */ | ||
352 | |||
353 | { disable_acpi_irq, "ASUS A7V", { | ||
354 | MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC"), | ||
355 | MATCH(DMI_BOARD_NAME, "<A7V>"), | ||
356 | /* newer BIOS, Revision 1011, does work */ | ||
357 | MATCH(DMI_BIOS_VERSION, "ASUS A7V ACPI BIOS Revision 1007"), | ||
358 | NO_MATCH }}, | ||
359 | |||
360 | /* | ||
361 | * Boxes that need ACPI PCI IRQ routing and PCI scan disabled | ||
362 | */ | ||
363 | { disable_acpi_pci, "ASUS PR-DLS", { /* _BBN 0 bug */ | ||
364 | MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), | ||
365 | MATCH(DMI_BOARD_NAME, "PR-DLS"), | ||
366 | MATCH(DMI_BIOS_VERSION, "ASUS PR-DLS ACPI BIOS Revision 1010"), | ||
367 | MATCH(DMI_BIOS_DATE, "03/21/2003") }}, | ||
368 | |||
369 | { disable_acpi_pci, "Acer TravelMate 36x Laptop", { | ||
370 | MATCH(DMI_SYS_VENDOR, "Acer"), | ||
371 | MATCH(DMI_PRODUCT_NAME, "TravelMate 360"), | ||
372 | NO_MATCH, NO_MATCH | ||
373 | } }, | ||
374 | |||
375 | #endif | ||
376 | |||
377 | { NULL, } | ||
378 | }; | ||
379 | |||
380 | /* | ||
381 | * Process a DMI table entry. Right now all we care about are the BIOS | 153 | * Process a DMI table entry. Right now all we care about are the BIOS |
382 | * and machine entries. For 2.5 we should pull the smbus controller info | 154 | * and machine entries. For 2.5 we should pull the smbus controller info |
383 | * out of here. | 155 | * out of here. |
384 | */ | 156 | */ |
385 | |||
386 | static void __init dmi_decode(struct dmi_header *dm) | 157 | static void __init dmi_decode(struct dmi_header *dm) |
387 | { | 158 | { |
388 | #ifdef DMI_DEBUG | 159 | u8 *data __attribute__((__unused__)) = (u8 *)dm; |
389 | u8 *data = (u8 *)dm; | ||
390 | #endif | ||
391 | 160 | ||
392 | switch(dm->type) | 161 | switch(dm->type) { |
393 | { | 162 | case 0: |
394 | case 0: | 163 | dmi_printk(("BIOS Vendor: %s\n", dmi_string(dm, data[4]))); |
395 | dmi_printk(("BIOS Vendor: %s\n", | 164 | dmi_save_ident(dm, DMI_BIOS_VENDOR, 4); |
396 | dmi_string(dm, data[4]))); | 165 | dmi_printk(("BIOS Version: %s\n", dmi_string(dm, data[5]))); |
397 | dmi_save_ident(dm, DMI_BIOS_VENDOR, 4); | 166 | dmi_save_ident(dm, DMI_BIOS_VERSION, 5); |
398 | dmi_printk(("BIOS Version: %s\n", | 167 | dmi_printk(("BIOS Release: %s\n", dmi_string(dm, data[8]))); |
399 | dmi_string(dm, data[5]))); | 168 | dmi_save_ident(dm, DMI_BIOS_DATE, 8); |
400 | dmi_save_ident(dm, DMI_BIOS_VERSION, 5); | 169 | break; |
401 | dmi_printk(("BIOS Release: %s\n", | 170 | case 1: |
402 | dmi_string(dm, data[8]))); | 171 | dmi_printk(("System Vendor: %s\n", dmi_string(dm, data[4]))); |
403 | dmi_save_ident(dm, DMI_BIOS_DATE, 8); | 172 | dmi_save_ident(dm, DMI_SYS_VENDOR, 4); |
404 | break; | 173 | dmi_printk(("Product Name: %s\n", dmi_string(dm, data[5]))); |
405 | case 1: | 174 | dmi_save_ident(dm, DMI_PRODUCT_NAME, 5); |
406 | dmi_printk(("System Vendor: %s\n", | 175 | dmi_printk(("Version: %s\n", dmi_string(dm, data[6]))); |
407 | dmi_string(dm, data[4]))); | 176 | dmi_save_ident(dm, DMI_PRODUCT_VERSION, 6); |
408 | dmi_save_ident(dm, DMI_SYS_VENDOR, 4); | 177 | dmi_printk(("Serial Number: %s\n", dmi_string(dm, data[7]))); |
409 | dmi_printk(("Product Name: %s\n", | 178 | dmi_save_ident(dm, DMI_PRODUCT_SERIAL, 7); |
410 | dmi_string(dm, data[5]))); | 179 | break; |
411 | dmi_save_ident(dm, DMI_PRODUCT_NAME, 5); | 180 | case 2: |
412 | dmi_printk(("Version: %s\n", | 181 | dmi_printk(("Board Vendor: %s\n", dmi_string(dm, data[4]))); |
413 | dmi_string(dm, data[6]))); | 182 | dmi_save_ident(dm, DMI_BOARD_VENDOR, 4); |
414 | dmi_save_ident(dm, DMI_PRODUCT_VERSION, 6); | 183 | dmi_printk(("Board Name: %s\n", dmi_string(dm, data[5]))); |
415 | dmi_printk(("Serial Number: %s\n", | 184 | dmi_save_ident(dm, DMI_BOARD_NAME, 5); |
416 | dmi_string(dm, data[7]))); | 185 | dmi_printk(("Board Version: %s\n", dmi_string(dm, data[6]))); |
417 | break; | 186 | dmi_save_ident(dm, DMI_BOARD_VERSION, 6); |
418 | case 2: | 187 | break; |
419 | dmi_printk(("Board Vendor: %s\n", | ||
420 | dmi_string(dm, data[4]))); | ||
421 | dmi_save_ident(dm, DMI_BOARD_VENDOR, 4); | ||
422 | dmi_printk(("Board Name: %s\n", | ||
423 | dmi_string(dm, data[5]))); | ||
424 | dmi_save_ident(dm, DMI_BOARD_NAME, 5); | ||
425 | dmi_printk(("Board Version: %s\n", | ||
426 | dmi_string(dm, data[6]))); | ||
427 | dmi_save_ident(dm, DMI_BOARD_VERSION, 6); | ||
428 | break; | ||
429 | } | 188 | } |
430 | } | 189 | } |
431 | 190 | ||
432 | void __init dmi_scan_machine(void) | 191 | void __init dmi_scan_machine(void) |
433 | { | 192 | { |
434 | int err = dmi_iterate(dmi_decode); | 193 | if (dmi_iterate(dmi_decode)) |
435 | if(err == 0) | ||
436 | dmi_check_system(dmi_blacklist); | ||
437 | else | ||
438 | printk(KERN_INFO "DMI not present.\n"); | 194 | printk(KERN_INFO "DMI not present.\n"); |
439 | } | 195 | } |
440 | 196 | ||
@@ -470,7 +226,6 @@ fail: d++; | |||
470 | 226 | ||
471 | return count; | 227 | return count; |
472 | } | 228 | } |
473 | |||
474 | EXPORT_SYMBOL(dmi_check_system); | 229 | EXPORT_SYMBOL(dmi_check_system); |
475 | 230 | ||
476 | /** | 231 | /** |
@@ -480,8 +235,8 @@ EXPORT_SYMBOL(dmi_check_system); | |||
480 | * Returns one DMI data value, can be used to perform | 235 | * Returns one DMI data value, can be used to perform |
481 | * complex DMI data checks. | 236 | * complex DMI data checks. |
482 | */ | 237 | */ |
483 | char * dmi_get_system_info(int field) | 238 | char *dmi_get_system_info(int field) |
484 | { | 239 | { |
485 | return dmi_ident[field]; | 240 | return dmi_ident[field]; |
486 | } | 241 | } |
487 | 242 | EXPORT_SYMBOL(dmi_get_system_info); | |
diff --git a/arch/i386/kernel/efi.c b/arch/i386/kernel/efi.c index f732f427b418..385883ea8c19 100644 --- a/arch/i386/kernel/efi.c +++ b/arch/i386/kernel/efi.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/ioport.h> | 30 | #include <linux/ioport.h> |
31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
32 | #include <linux/efi.h> | 32 | #include <linux/efi.h> |
33 | #include <linux/kexec.h> | ||
33 | 34 | ||
34 | #include <asm/setup.h> | 35 | #include <asm/setup.h> |
35 | #include <asm/io.h> | 36 | #include <asm/io.h> |
@@ -598,6 +599,9 @@ efi_initialize_iomem_resources(struct resource *code_resource, | |||
598 | if (md->type == EFI_CONVENTIONAL_MEMORY) { | 599 | if (md->type == EFI_CONVENTIONAL_MEMORY) { |
599 | request_resource(res, code_resource); | 600 | request_resource(res, code_resource); |
600 | request_resource(res, data_resource); | 601 | request_resource(res, data_resource); |
602 | #ifdef CONFIG_KEXEC | ||
603 | request_resource(res, &crashk_res); | ||
604 | #endif | ||
601 | } | 605 | } |
602 | } | 606 | } |
603 | } | 607 | } |
diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S index e966fc8c44c4..4477bb107098 100644 --- a/arch/i386/kernel/head.S +++ b/arch/i386/kernel/head.S | |||
@@ -299,7 +299,6 @@ is386: movl $2,%ecx # set MP | |||
299 | movl %eax,%cr0 | 299 | movl %eax,%cr0 |
300 | 300 | ||
301 | call check_x87 | 301 | call check_x87 |
302 | incb ready | ||
303 | lgdt cpu_gdt_descr | 302 | lgdt cpu_gdt_descr |
304 | lidt idt_descr | 303 | lidt idt_descr |
305 | ljmp $(__KERNEL_CS),$1f | 304 | ljmp $(__KERNEL_CS),$1f |
@@ -316,8 +315,9 @@ is386: movl $2,%ecx # set MP | |||
316 | lldt %ax | 315 | lldt %ax |
317 | cld # gcc2 wants the direction flag cleared at all times | 316 | cld # gcc2 wants the direction flag cleared at all times |
318 | #ifdef CONFIG_SMP | 317 | #ifdef CONFIG_SMP |
319 | movb ready, %cl | 318 | movb ready, %cl |
320 | cmpb $1,%cl | 319 | movb $1, ready |
320 | cmpb $0,%cl | ||
321 | je 1f # the first CPU calls start_kernel | 321 | je 1f # the first CPU calls start_kernel |
322 | # all other CPUs call initialize_secondary | 322 | # all other CPUs call initialize_secondary |
323 | call initialize_secondary | 323 | call initialize_secondary |
diff --git a/arch/i386/kernel/i8259.c b/arch/i386/kernel/i8259.c index 2c4813b47e57..178f4e9bac9d 100644 --- a/arch/i386/kernel/i8259.c +++ b/arch/i386/kernel/i8259.c | |||
@@ -268,10 +268,22 @@ static int i8259A_suspend(struct sys_device *dev, pm_message_t state) | |||
268 | return 0; | 268 | return 0; |
269 | } | 269 | } |
270 | 270 | ||
271 | static int i8259A_shutdown(struct sys_device *dev) | ||
272 | { | ||
273 | /* Put the i8259A into a quiescent state that | ||
274 | * the kernel initialization code can get it | ||
275 | * out of. | ||
276 | */ | ||
277 | outb(0xff, 0x21); /* mask all of 8259A-1 */ | ||
278 | outb(0xff, 0xA1); /* mask all of 8259A-1 */ | ||
279 | return 0; | ||
280 | } | ||
281 | |||
271 | static struct sysdev_class i8259_sysdev_class = { | 282 | static struct sysdev_class i8259_sysdev_class = { |
272 | set_kset_name("i8259"), | 283 | set_kset_name("i8259"), |
273 | .suspend = i8259A_suspend, | 284 | .suspend = i8259A_suspend, |
274 | .resume = i8259A_resume, | 285 | .resume = i8259A_resume, |
286 | .shutdown = i8259A_shutdown, | ||
275 | }; | 287 | }; |
276 | 288 | ||
277 | static struct sys_device device_i8259A = { | 289 | static struct sys_device device_i8259A = { |
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c index 08540bc4ba3e..35eb8e29c485 100644 --- a/arch/i386/kernel/io_apic.c +++ b/arch/i386/kernel/io_apic.c | |||
@@ -573,12 +573,14 @@ static int balanced_irq(void *unused) | |||
573 | for ( ; ; ) { | 573 | for ( ; ; ) { |
574 | set_current_state(TASK_INTERRUPTIBLE); | 574 | set_current_state(TASK_INTERRUPTIBLE); |
575 | time_remaining = schedule_timeout(time_remaining); | 575 | time_remaining = schedule_timeout(time_remaining); |
576 | try_to_freeze(PF_FREEZE); | 576 | try_to_freeze(); |
577 | if (time_after(jiffies, | 577 | if (time_after(jiffies, |
578 | prev_balance_time+balanced_irq_interval)) { | 578 | prev_balance_time+balanced_irq_interval)) { |
579 | preempt_disable(); | ||
579 | do_irq_balance(); | 580 | do_irq_balance(); |
580 | prev_balance_time = jiffies; | 581 | prev_balance_time = jiffies; |
581 | time_remaining = balanced_irq_interval; | 582 | time_remaining = balanced_irq_interval; |
583 | preempt_enable(); | ||
582 | } | 584 | } |
583 | } | 585 | } |
584 | return 0; | 586 | return 0; |
@@ -630,10 +632,8 @@ static int __init balanced_irq_init(void) | |||
630 | printk(KERN_ERR "balanced_irq_init: failed to spawn balanced_irq"); | 632 | printk(KERN_ERR "balanced_irq_init: failed to spawn balanced_irq"); |
631 | failed: | 633 | failed: |
632 | for (i = 0; i < NR_CPUS; i++) { | 634 | for (i = 0; i < NR_CPUS; i++) { |
633 | if(irq_cpu_data[i].irq_delta) | 635 | kfree(irq_cpu_data[i].irq_delta); |
634 | kfree(irq_cpu_data[i].irq_delta); | 636 | kfree(irq_cpu_data[i].last_irq); |
635 | if(irq_cpu_data[i].last_irq) | ||
636 | kfree(irq_cpu_data[i].last_irq); | ||
637 | } | 637 | } |
638 | return 0; | 638 | return 0; |
639 | } | 639 | } |
@@ -1634,12 +1634,43 @@ static void __init enable_IO_APIC(void) | |||
1634 | */ | 1634 | */ |
1635 | void disable_IO_APIC(void) | 1635 | void disable_IO_APIC(void) |
1636 | { | 1636 | { |
1637 | int pin; | ||
1637 | /* | 1638 | /* |
1638 | * Clear the IO-APIC before rebooting: | 1639 | * Clear the IO-APIC before rebooting: |
1639 | */ | 1640 | */ |
1640 | clear_IO_APIC(); | 1641 | clear_IO_APIC(); |
1641 | 1642 | ||
1642 | disconnect_bsp_APIC(); | 1643 | /* |
1644 | * If the i82559 is routed through an IOAPIC | ||
1645 | * Put that IOAPIC in virtual wire mode | ||
1646 | * so legacy interrups can be delivered. | ||
1647 | */ | ||
1648 | pin = find_isa_irq_pin(0, mp_ExtINT); | ||
1649 | if (pin != -1) { | ||
1650 | struct IO_APIC_route_entry entry; | ||
1651 | unsigned long flags; | ||
1652 | |||
1653 | memset(&entry, 0, sizeof(entry)); | ||
1654 | entry.mask = 0; /* Enabled */ | ||
1655 | entry.trigger = 0; /* Edge */ | ||
1656 | entry.irr = 0; | ||
1657 | entry.polarity = 0; /* High */ | ||
1658 | entry.delivery_status = 0; | ||
1659 | entry.dest_mode = 0; /* Physical */ | ||
1660 | entry.delivery_mode = 7; /* ExtInt */ | ||
1661 | entry.vector = 0; | ||
1662 | entry.dest.physical.physical_dest = 0; | ||
1663 | |||
1664 | |||
1665 | /* | ||
1666 | * Add it to the IO-APIC irq-routing table: | ||
1667 | */ | ||
1668 | spin_lock_irqsave(&ioapic_lock, flags); | ||
1669 | io_apic_write(0, 0x11+2*pin, *(((int *)&entry)+1)); | ||
1670 | io_apic_write(0, 0x10+2*pin, *(((int *)&entry)+0)); | ||
1671 | spin_unlock_irqrestore(&ioapic_lock, flags); | ||
1672 | } | ||
1673 | disconnect_bsp_APIC(pin != -1); | ||
1643 | } | 1674 | } |
1644 | 1675 | ||
1645 | /* | 1676 | /* |
diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c index 73945a3c53c4..ce66dcc26d90 100644 --- a/arch/i386/kernel/irq.c +++ b/arch/i386/kernel/irq.c | |||
@@ -15,6 +15,9 @@ | |||
15 | #include <linux/seq_file.h> | 15 | #include <linux/seq_file.h> |
16 | #include <linux/interrupt.h> | 16 | #include <linux/interrupt.h> |
17 | #include <linux/kernel_stat.h> | 17 | #include <linux/kernel_stat.h> |
18 | #include <linux/notifier.h> | ||
19 | #include <linux/cpu.h> | ||
20 | #include <linux/delay.h> | ||
18 | 21 | ||
19 | DEFINE_PER_CPU(irq_cpustat_t, irq_stat) ____cacheline_maxaligned_in_smp; | 22 | DEFINE_PER_CPU(irq_cpustat_t, irq_stat) ____cacheline_maxaligned_in_smp; |
20 | EXPORT_PER_CPU_SYMBOL(irq_stat); | 23 | EXPORT_PER_CPU_SYMBOL(irq_stat); |
@@ -153,6 +156,11 @@ void irq_ctx_init(int cpu) | |||
153 | cpu,hardirq_ctx[cpu],softirq_ctx[cpu]); | 156 | cpu,hardirq_ctx[cpu],softirq_ctx[cpu]); |
154 | } | 157 | } |
155 | 158 | ||
159 | void irq_ctx_exit(int cpu) | ||
160 | { | ||
161 | hardirq_ctx[cpu] = NULL; | ||
162 | } | ||
163 | |||
156 | extern asmlinkage void __do_softirq(void); | 164 | extern asmlinkage void __do_softirq(void); |
157 | 165 | ||
158 | asmlinkage void do_softirq(void) | 166 | asmlinkage void do_softirq(void) |
@@ -210,9 +218,8 @@ int show_interrupts(struct seq_file *p, void *v) | |||
210 | 218 | ||
211 | if (i == 0) { | 219 | if (i == 0) { |
212 | seq_printf(p, " "); | 220 | seq_printf(p, " "); |
213 | for (j=0; j<NR_CPUS; j++) | 221 | for_each_cpu(j) |
214 | if (cpu_online(j)) | 222 | seq_printf(p, "CPU%d ",j); |
215 | seq_printf(p, "CPU%d ",j); | ||
216 | seq_putc(p, '\n'); | 223 | seq_putc(p, '\n'); |
217 | } | 224 | } |
218 | 225 | ||
@@ -225,9 +232,8 @@ int show_interrupts(struct seq_file *p, void *v) | |||
225 | #ifndef CONFIG_SMP | 232 | #ifndef CONFIG_SMP |
226 | seq_printf(p, "%10u ", kstat_irqs(i)); | 233 | seq_printf(p, "%10u ", kstat_irqs(i)); |
227 | #else | 234 | #else |
228 | for (j = 0; j < NR_CPUS; j++) | 235 | for_each_cpu(j) |
229 | if (cpu_online(j)) | 236 | seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); |
230 | seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); | ||
231 | #endif | 237 | #endif |
232 | seq_printf(p, " %14s", irq_desc[i].handler->typename); | 238 | seq_printf(p, " %14s", irq_desc[i].handler->typename); |
233 | seq_printf(p, " %s", action->name); | 239 | seq_printf(p, " %s", action->name); |
@@ -240,16 +246,14 @@ skip: | |||
240 | spin_unlock_irqrestore(&irq_desc[i].lock, flags); | 246 | spin_unlock_irqrestore(&irq_desc[i].lock, flags); |
241 | } else if (i == NR_IRQS) { | 247 | } else if (i == NR_IRQS) { |
242 | seq_printf(p, "NMI: "); | 248 | seq_printf(p, "NMI: "); |
243 | for (j = 0; j < NR_CPUS; j++) | 249 | for_each_cpu(j) |
244 | if (cpu_online(j)) | 250 | seq_printf(p, "%10u ", nmi_count(j)); |
245 | seq_printf(p, "%10u ", nmi_count(j)); | ||
246 | seq_putc(p, '\n'); | 251 | seq_putc(p, '\n'); |
247 | #ifdef CONFIG_X86_LOCAL_APIC | 252 | #ifdef CONFIG_X86_LOCAL_APIC |
248 | seq_printf(p, "LOC: "); | 253 | seq_printf(p, "LOC: "); |
249 | for (j = 0; j < NR_CPUS; j++) | 254 | for_each_cpu(j) |
250 | if (cpu_online(j)) | 255 | seq_printf(p, "%10u ", |
251 | seq_printf(p, "%10u ", | 256 | per_cpu(irq_stat,j).apic_timer_irqs); |
252 | per_cpu(irq_stat,j).apic_timer_irqs); | ||
253 | seq_putc(p, '\n'); | 257 | seq_putc(p, '\n'); |
254 | #endif | 258 | #endif |
255 | seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count)); | 259 | seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count)); |
@@ -259,3 +263,45 @@ skip: | |||
259 | } | 263 | } |
260 | return 0; | 264 | return 0; |
261 | } | 265 | } |
266 | |||
267 | #ifdef CONFIG_HOTPLUG_CPU | ||
268 | #include <mach_apic.h> | ||
269 | |||
270 | void fixup_irqs(cpumask_t map) | ||
271 | { | ||
272 | unsigned int irq; | ||
273 | static int warned; | ||
274 | |||
275 | for (irq = 0; irq < NR_IRQS; irq++) { | ||
276 | cpumask_t mask; | ||
277 | if (irq == 2) | ||
278 | continue; | ||
279 | |||
280 | cpus_and(mask, irq_affinity[irq], map); | ||
281 | if (any_online_cpu(mask) == NR_CPUS) { | ||
282 | printk("Breaking affinity for irq %i\n", irq); | ||
283 | mask = map; | ||
284 | } | ||
285 | if (irq_desc[irq].handler->set_affinity) | ||
286 | irq_desc[irq].handler->set_affinity(irq, mask); | ||
287 | else if (irq_desc[irq].action && !(warned++)) | ||
288 | printk("Cannot set affinity for irq %i\n", irq); | ||
289 | } | ||
290 | |||
291 | #if 0 | ||
292 | barrier(); | ||
293 | /* Ingo Molnar says: "after the IO-APIC masks have been redirected | ||
294 | [note the nop - the interrupt-enable boundary on x86 is two | ||
295 | instructions from sti] - to flush out pending hardirqs and | ||
296 | IPIs. After this point nothing is supposed to reach this CPU." */ | ||
297 | __asm__ __volatile__("sti; nop; cli"); | ||
298 | barrier(); | ||
299 | #else | ||
300 | /* That doesn't seem sufficient. Give it 1ms. */ | ||
301 | local_irq_enable(); | ||
302 | mdelay(1); | ||
303 | local_irq_disable(); | ||
304 | #endif | ||
305 | } | ||
306 | #endif | ||
307 | |||
diff --git a/arch/i386/kernel/machine_kexec.c b/arch/i386/kernel/machine_kexec.c new file mode 100644 index 000000000000..52ed18d8b511 --- /dev/null +++ b/arch/i386/kernel/machine_kexec.c | |||
@@ -0,0 +1,226 @@ | |||
1 | /* | ||
2 | * machine_kexec.c - handle transition of Linux booting another kernel | ||
3 | * Copyright (C) 2002-2005 Eric Biederman <ebiederm@xmission.com> | ||
4 | * | ||
5 | * This source code is licensed under the GNU General Public License, | ||
6 | * Version 2. See the file COPYING for more details. | ||
7 | */ | ||
8 | |||
9 | #include <linux/mm.h> | ||
10 | #include <linux/kexec.h> | ||
11 | #include <linux/delay.h> | ||
12 | #include <asm/pgtable.h> | ||
13 | #include <asm/pgalloc.h> | ||
14 | #include <asm/tlbflush.h> | ||
15 | #include <asm/mmu_context.h> | ||
16 | #include <asm/io.h> | ||
17 | #include <asm/apic.h> | ||
18 | #include <asm/cpufeature.h> | ||
19 | |||
20 | static inline unsigned long read_cr3(void) | ||
21 | { | ||
22 | unsigned long cr3; | ||
23 | asm volatile("movl %%cr3,%0": "=r"(cr3)); | ||
24 | return cr3; | ||
25 | } | ||
26 | |||
27 | #define PAGE_ALIGNED __attribute__ ((__aligned__(PAGE_SIZE))) | ||
28 | |||
29 | #define L0_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY) | ||
30 | #define L1_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY) | ||
31 | #define L2_ATTR (_PAGE_PRESENT) | ||
32 | |||
33 | #define LEVEL0_SIZE (1UL << 12UL) | ||
34 | |||
35 | #ifndef CONFIG_X86_PAE | ||
36 | #define LEVEL1_SIZE (1UL << 22UL) | ||
37 | static u32 pgtable_level1[1024] PAGE_ALIGNED; | ||
38 | |||
39 | static void identity_map_page(unsigned long address) | ||
40 | { | ||
41 | unsigned long level1_index, level2_index; | ||
42 | u32 *pgtable_level2; | ||
43 | |||
44 | /* Find the current page table */ | ||
45 | pgtable_level2 = __va(read_cr3()); | ||
46 | |||
47 | /* Find the indexes of the physical address to identity map */ | ||
48 | level1_index = (address % LEVEL1_SIZE)/LEVEL0_SIZE; | ||
49 | level2_index = address / LEVEL1_SIZE; | ||
50 | |||
51 | /* Identity map the page table entry */ | ||
52 | pgtable_level1[level1_index] = address | L0_ATTR; | ||
53 | pgtable_level2[level2_index] = __pa(pgtable_level1) | L1_ATTR; | ||
54 | |||
55 | /* Flush the tlb so the new mapping takes effect. | ||
56 | * Global tlb entries are not flushed but that is not an issue. | ||
57 | */ | ||
58 | load_cr3(pgtable_level2); | ||
59 | } | ||
60 | |||
61 | #else | ||
62 | #define LEVEL1_SIZE (1UL << 21UL) | ||
63 | #define LEVEL2_SIZE (1UL << 30UL) | ||
64 | static u64 pgtable_level1[512] PAGE_ALIGNED; | ||
65 | static u64 pgtable_level2[512] PAGE_ALIGNED; | ||
66 | |||
67 | static void identity_map_page(unsigned long address) | ||
68 | { | ||
69 | unsigned long level1_index, level2_index, level3_index; | ||
70 | u64 *pgtable_level3; | ||
71 | |||
72 | /* Find the current page table */ | ||
73 | pgtable_level3 = __va(read_cr3()); | ||
74 | |||
75 | /* Find the indexes of the physical address to identity map */ | ||
76 | level1_index = (address % LEVEL1_SIZE)/LEVEL0_SIZE; | ||
77 | level2_index = (address % LEVEL2_SIZE)/LEVEL1_SIZE; | ||
78 | level3_index = address / LEVEL2_SIZE; | ||
79 | |||
80 | /* Identity map the page table entry */ | ||
81 | pgtable_level1[level1_index] = address | L0_ATTR; | ||
82 | pgtable_level2[level2_index] = __pa(pgtable_level1) | L1_ATTR; | ||
83 | set_64bit(&pgtable_level3[level3_index], | ||
84 | __pa(pgtable_level2) | L2_ATTR); | ||
85 | |||
86 | /* Flush the tlb so the new mapping takes effect. | ||
87 | * Global tlb entries are not flushed but that is not an issue. | ||
88 | */ | ||
89 | load_cr3(pgtable_level3); | ||
90 | } | ||
91 | #endif | ||
92 | |||
93 | |||
94 | static void set_idt(void *newidt, __u16 limit) | ||
95 | { | ||
96 | unsigned char curidt[6]; | ||
97 | |||
98 | /* ia32 supports unaliged loads & stores */ | ||
99 | (*(__u16 *)(curidt)) = limit; | ||
100 | (*(__u32 *)(curidt +2)) = (unsigned long)(newidt); | ||
101 | |||
102 | __asm__ __volatile__ ( | ||
103 | "lidt %0\n" | ||
104 | : "=m" (curidt) | ||
105 | ); | ||
106 | }; | ||
107 | |||
108 | |||
109 | static void set_gdt(void *newgdt, __u16 limit) | ||
110 | { | ||
111 | unsigned char curgdt[6]; | ||
112 | |||
113 | /* ia32 supports unaligned loads & stores */ | ||
114 | (*(__u16 *)(curgdt)) = limit; | ||
115 | (*(__u32 *)(curgdt +2)) = (unsigned long)(newgdt); | ||
116 | |||
117 | __asm__ __volatile__ ( | ||
118 | "lgdt %0\n" | ||
119 | : "=m" (curgdt) | ||
120 | ); | ||
121 | }; | ||
122 | |||
123 | static void load_segments(void) | ||
124 | { | ||
125 | #define __STR(X) #X | ||
126 | #define STR(X) __STR(X) | ||
127 | |||
128 | __asm__ __volatile__ ( | ||
129 | "\tljmp $"STR(__KERNEL_CS)",$1f\n" | ||
130 | "\t1:\n" | ||
131 | "\tmovl $"STR(__KERNEL_DS)",%eax\n" | ||
132 | "\tmovl %eax,%ds\n" | ||
133 | "\tmovl %eax,%es\n" | ||
134 | "\tmovl %eax,%fs\n" | ||
135 | "\tmovl %eax,%gs\n" | ||
136 | "\tmovl %eax,%ss\n" | ||
137 | ); | ||
138 | #undef STR | ||
139 | #undef __STR | ||
140 | } | ||
141 | |||
142 | typedef asmlinkage NORET_TYPE void (*relocate_new_kernel_t)( | ||
143 | unsigned long indirection_page, | ||
144 | unsigned long reboot_code_buffer, | ||
145 | unsigned long start_address, | ||
146 | unsigned int has_pae) ATTRIB_NORET; | ||
147 | |||
148 | const extern unsigned char relocate_new_kernel[]; | ||
149 | extern void relocate_new_kernel_end(void); | ||
150 | const extern unsigned int relocate_new_kernel_size; | ||
151 | |||
152 | /* | ||
153 | * A architecture hook called to validate the | ||
154 | * proposed image and prepare the control pages | ||
155 | * as needed. The pages for KEXEC_CONTROL_CODE_SIZE | ||
156 | * have been allocated, but the segments have yet | ||
157 | * been copied into the kernel. | ||
158 | * | ||
159 | * Do what every setup is needed on image and the | ||
160 | * reboot code buffer to allow us to avoid allocations | ||
161 | * later. | ||
162 | * | ||
163 | * Currently nothing. | ||
164 | */ | ||
165 | int machine_kexec_prepare(struct kimage *image) | ||
166 | { | ||
167 | return 0; | ||
168 | } | ||
169 | |||
170 | /* | ||
171 | * Undo anything leftover by machine_kexec_prepare | ||
172 | * when an image is freed. | ||
173 | */ | ||
174 | void machine_kexec_cleanup(struct kimage *image) | ||
175 | { | ||
176 | } | ||
177 | |||
178 | /* | ||
179 | * Do not allocate memory (or fail in any way) in machine_kexec(). | ||
180 | * We are past the point of no return, committed to rebooting now. | ||
181 | */ | ||
182 | NORET_TYPE void machine_kexec(struct kimage *image) | ||
183 | { | ||
184 | unsigned long page_list; | ||
185 | unsigned long reboot_code_buffer; | ||
186 | |||
187 | relocate_new_kernel_t rnk; | ||
188 | |||
189 | /* Interrupts aren't acceptable while we reboot */ | ||
190 | local_irq_disable(); | ||
191 | |||
192 | /* Compute some offsets */ | ||
193 | reboot_code_buffer = page_to_pfn(image->control_code_page) | ||
194 | << PAGE_SHIFT; | ||
195 | page_list = image->head; | ||
196 | |||
197 | /* Set up an identity mapping for the reboot_code_buffer */ | ||
198 | identity_map_page(reboot_code_buffer); | ||
199 | |||
200 | /* copy it out */ | ||
201 | memcpy((void *)reboot_code_buffer, relocate_new_kernel, | ||
202 | relocate_new_kernel_size); | ||
203 | |||
204 | /* The segment registers are funny things, they are | ||
205 | * automatically loaded from a table, in memory wherever you | ||
206 | * set them to a specific selector, but this table is never | ||
207 | * accessed again you set the segment to a different selector. | ||
208 | * | ||
209 | * The more common model is are caches where the behide | ||
210 | * the scenes work is done, but is also dropped at arbitrary | ||
211 | * times. | ||
212 | * | ||
213 | * I take advantage of this here by force loading the | ||
214 | * segments, before I zap the gdt with an invalid value. | ||
215 | */ | ||
216 | load_segments(); | ||
217 | /* The gdt & idt are now invalid. | ||
218 | * If you want to load them you must set up your own idt & gdt. | ||
219 | */ | ||
220 | set_gdt(phys_to_virt(0),0); | ||
221 | set_idt(phys_to_virt(0),0); | ||
222 | |||
223 | /* now call it */ | ||
224 | rnk = (relocate_new_kernel_t) reboot_code_buffer; | ||
225 | (*rnk)(page_list, reboot_code_buffer, image->start, cpu_has_pae); | ||
226 | } | ||
diff --git a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c index 383a11600d2c..af917f609c7d 100644 --- a/arch/i386/kernel/mpparse.c +++ b/arch/i386/kernel/mpparse.c | |||
@@ -67,7 +67,6 @@ unsigned long mp_lapic_addr; | |||
67 | 67 | ||
68 | /* Processor that is doing the boot up */ | 68 | /* Processor that is doing the boot up */ |
69 | unsigned int boot_cpu_physical_apicid = -1U; | 69 | unsigned int boot_cpu_physical_apicid = -1U; |
70 | unsigned int boot_cpu_logical_apicid = -1U; | ||
71 | /* Internal processor count */ | 70 | /* Internal processor count */ |
72 | static unsigned int __initdata num_processors; | 71 | static unsigned int __initdata num_processors; |
73 | 72 | ||
@@ -180,7 +179,6 @@ static void __init MP_processor_info (struct mpc_config_processor *m) | |||
180 | if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) { | 179 | if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) { |
181 | Dprintk(" Bootup CPU\n"); | 180 | Dprintk(" Bootup CPU\n"); |
182 | boot_cpu_physical_apicid = m->mpc_apicid; | 181 | boot_cpu_physical_apicid = m->mpc_apicid; |
183 | boot_cpu_logical_apicid = apicid; | ||
184 | } | 182 | } |
185 | 183 | ||
186 | if (num_processors >= NR_CPUS) { | 184 | if (num_processors >= NR_CPUS) { |
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index aea2ce1145df..5f8cfa6b7940 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c | |||
@@ -13,6 +13,7 @@ | |||
13 | 13 | ||
14 | #include <stdarg.h> | 14 | #include <stdarg.h> |
15 | 15 | ||
16 | #include <linux/cpu.h> | ||
16 | #include <linux/errno.h> | 17 | #include <linux/errno.h> |
17 | #include <linux/sched.h> | 18 | #include <linux/sched.h> |
18 | #include <linux/fs.h> | 19 | #include <linux/fs.h> |
@@ -55,6 +56,9 @@ | |||
55 | #include <linux/irq.h> | 56 | #include <linux/irq.h> |
56 | #include <linux/err.h> | 57 | #include <linux/err.h> |
57 | 58 | ||
59 | #include <asm/tlbflush.h> | ||
60 | #include <asm/cpu.h> | ||
61 | |||
58 | asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); | 62 | asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); |
59 | 63 | ||
60 | static int hlt_counter; | 64 | static int hlt_counter; |
@@ -143,14 +147,42 @@ static void poll_idle (void) | |||
143 | } | 147 | } |
144 | } | 148 | } |
145 | 149 | ||
150 | #ifdef CONFIG_HOTPLUG_CPU | ||
151 | #include <asm/nmi.h> | ||
152 | /* We don't actually take CPU down, just spin without interrupts. */ | ||
153 | static inline void play_dead(void) | ||
154 | { | ||
155 | /* This must be done before dead CPU ack */ | ||
156 | cpu_exit_clear(); | ||
157 | wbinvd(); | ||
158 | mb(); | ||
159 | /* Ack it */ | ||
160 | __get_cpu_var(cpu_state) = CPU_DEAD; | ||
161 | |||
162 | /* | ||
163 | * With physical CPU hotplug, we should halt the cpu | ||
164 | */ | ||
165 | local_irq_disable(); | ||
166 | while (1) | ||
167 | __asm__ __volatile__("hlt":::"memory"); | ||
168 | } | ||
169 | #else | ||
170 | static inline void play_dead(void) | ||
171 | { | ||
172 | BUG(); | ||
173 | } | ||
174 | #endif /* CONFIG_HOTPLUG_CPU */ | ||
175 | |||
146 | /* | 176 | /* |
147 | * The idle thread. There's no useful work to be | 177 | * The idle thread. There's no useful work to be |
148 | * done, so just try to conserve power and have a | 178 | * done, so just try to conserve power and have a |
149 | * low exit latency (ie sit in a loop waiting for | 179 | * low exit latency (ie sit in a loop waiting for |
150 | * somebody to say that they'd like to reschedule) | 180 | * somebody to say that they'd like to reschedule) |
151 | */ | 181 | */ |
152 | void cpu_idle (void) | 182 | void cpu_idle(void) |
153 | { | 183 | { |
184 | int cpu = raw_smp_processor_id(); | ||
185 | |||
154 | /* endless idle loop with no priority at all */ | 186 | /* endless idle loop with no priority at all */ |
155 | while (1) { | 187 | while (1) { |
156 | while (!need_resched()) { | 188 | while (!need_resched()) { |
@@ -165,6 +197,9 @@ void cpu_idle (void) | |||
165 | if (!idle) | 197 | if (!idle) |
166 | idle = default_idle; | 198 | idle = default_idle; |
167 | 199 | ||
200 | if (cpu_is_offline(cpu)) | ||
201 | play_dead(); | ||
202 | |||
168 | __get_cpu_var(irq_stat).idle_timestamp = jiffies; | 203 | __get_cpu_var(irq_stat).idle_timestamp = jiffies; |
169 | idle(); | 204 | idle(); |
170 | } | 205 | } |
@@ -223,7 +258,7 @@ static void mwait_idle(void) | |||
223 | } | 258 | } |
224 | } | 259 | } |
225 | 260 | ||
226 | void __init select_idle_routine(const struct cpuinfo_x86 *c) | 261 | void __devinit select_idle_routine(const struct cpuinfo_x86 *c) |
227 | { | 262 | { |
228 | if (cpu_has(c, X86_FEATURE_MWAIT)) { | 263 | if (cpu_has(c, X86_FEATURE_MWAIT)) { |
229 | printk("monitor/mwait feature present.\n"); | 264 | printk("monitor/mwait feature present.\n"); |
diff --git a/arch/i386/kernel/reboot.c b/arch/i386/kernel/reboot.c index db912209a8d3..b3e584849961 100644 --- a/arch/i386/kernel/reboot.c +++ b/arch/i386/kernel/reboot.c | |||
@@ -26,7 +26,6 @@ static int reboot_mode; | |||
26 | static int reboot_thru_bios; | 26 | static int reboot_thru_bios; |
27 | 27 | ||
28 | #ifdef CONFIG_SMP | 28 | #ifdef CONFIG_SMP |
29 | int reboot_smp = 0; | ||
30 | static int reboot_cpu = -1; | 29 | static int reboot_cpu = -1; |
31 | /* shamelessly grabbed from lib/vsprintf.c for readability */ | 30 | /* shamelessly grabbed from lib/vsprintf.c for readability */ |
32 | #define is_digit(c) ((c) >= '0' && (c) <= '9') | 31 | #define is_digit(c) ((c) >= '0' && (c) <= '9') |
@@ -49,7 +48,6 @@ static int __init reboot_setup(char *str) | |||
49 | break; | 48 | break; |
50 | #ifdef CONFIG_SMP | 49 | #ifdef CONFIG_SMP |
51 | case 's': /* "smp" reboot by executing reset on BSP or other CPU*/ | 50 | case 's': /* "smp" reboot by executing reset on BSP or other CPU*/ |
52 | reboot_smp = 1; | ||
53 | if (is_digit(*(str+1))) { | 51 | if (is_digit(*(str+1))) { |
54 | reboot_cpu = (int) (*(str+1) - '0'); | 52 | reboot_cpu = (int) (*(str+1) - '0'); |
55 | if (is_digit(*(str+2))) | 53 | if (is_digit(*(str+2))) |
@@ -88,33 +86,9 @@ static int __init set_bios_reboot(struct dmi_system_id *d) | |||
88 | return 0; | 86 | return 0; |
89 | } | 87 | } |
90 | 88 | ||
91 | /* | ||
92 | * Some machines require the "reboot=s" commandline option, this quirk makes that automatic. | ||
93 | */ | ||
94 | static int __init set_smp_reboot(struct dmi_system_id *d) | ||
95 | { | ||
96 | #ifdef CONFIG_SMP | ||
97 | if (!reboot_smp) { | ||
98 | reboot_smp = 1; | ||
99 | printk(KERN_INFO "%s series board detected. Selecting SMP-method for reboots.\n", d->ident); | ||
100 | } | ||
101 | #endif | ||
102 | return 0; | ||
103 | } | ||
104 | |||
105 | /* | ||
106 | * Some machines require the "reboot=b,s" commandline option, this quirk makes that automatic. | ||
107 | */ | ||
108 | static int __init set_smp_bios_reboot(struct dmi_system_id *d) | ||
109 | { | ||
110 | set_smp_reboot(d); | ||
111 | set_bios_reboot(d); | ||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | static struct dmi_system_id __initdata reboot_dmi_table[] = { | 89 | static struct dmi_system_id __initdata reboot_dmi_table[] = { |
116 | { /* Handle problems with rebooting on Dell 1300's */ | 90 | { /* Handle problems with rebooting on Dell 1300's */ |
117 | .callback = set_smp_bios_reboot, | 91 | .callback = set_bios_reboot, |
118 | .ident = "Dell PowerEdge 1300", | 92 | .ident = "Dell PowerEdge 1300", |
119 | .matches = { | 93 | .matches = { |
120 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"), | 94 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"), |
@@ -301,41 +275,32 @@ void machine_real_restart(unsigned char *code, int length) | |||
301 | EXPORT_SYMBOL(machine_real_restart); | 275 | EXPORT_SYMBOL(machine_real_restart); |
302 | #endif | 276 | #endif |
303 | 277 | ||
304 | void machine_restart(char * __unused) | 278 | void machine_shutdown(void) |
305 | { | 279 | { |
306 | #ifdef CONFIG_SMP | 280 | #ifdef CONFIG_SMP |
307 | int cpuid; | 281 | int reboot_cpu_id; |
308 | 282 | ||
309 | cpuid = GET_APIC_ID(apic_read(APIC_ID)); | 283 | /* The boot cpu is always logical cpu 0 */ |
310 | 284 | reboot_cpu_id = 0; | |
311 | if (reboot_smp) { | 285 | |
312 | 286 | /* See if there has been given a command line override */ | |
313 | /* check to see if reboot_cpu is valid | 287 | if ((reboot_cpu_id != -1) && (reboot_cpu < NR_CPUS) && |
314 | if its not, default to the BSP */ | 288 | cpu_isset(reboot_cpu, cpu_online_map)) { |
315 | if ((reboot_cpu == -1) || | 289 | reboot_cpu_id = reboot_cpu; |
316 | (reboot_cpu > (NR_CPUS -1)) || | ||
317 | !physid_isset(cpuid, phys_cpu_present_map)) | ||
318 | reboot_cpu = boot_cpu_physical_apicid; | ||
319 | |||
320 | reboot_smp = 0; /* use this as a flag to only go through this once*/ | ||
321 | /* re-run this function on the other CPUs | ||
322 | it will fall though this section since we have | ||
323 | cleared reboot_smp, and do the reboot if it is the | ||
324 | correct CPU, otherwise it halts. */ | ||
325 | if (reboot_cpu != cpuid) | ||
326 | smp_call_function((void *)machine_restart , NULL, 1, 0); | ||
327 | } | 290 | } |
328 | 291 | ||
329 | /* if reboot_cpu is still -1, then we want a tradional reboot, | 292 | /* Make certain the cpu I'm rebooting on is online */ |
330 | and if we are not running on the reboot_cpu,, halt */ | 293 | if (!cpu_isset(reboot_cpu_id, cpu_online_map)) { |
331 | if ((reboot_cpu != -1) && (cpuid != reboot_cpu)) { | 294 | reboot_cpu_id = smp_processor_id(); |
332 | for (;;) | ||
333 | __asm__ __volatile__ ("hlt"); | ||
334 | } | 295 | } |
335 | /* | 296 | |
336 | * Stop all CPUs and turn off local APICs and the IO-APIC, so | 297 | /* Make certain I only run on the appropriate processor */ |
337 | * other OSs see a clean IRQ state. | 298 | set_cpus_allowed(current, cpumask_of_cpu(reboot_cpu_id)); |
299 | |||
300 | /* O.K. Now that I'm on the appropriate processor, stop | ||
301 | * all of the others, and disable their local APICs. | ||
338 | */ | 302 | */ |
303 | |||
339 | smp_send_stop(); | 304 | smp_send_stop(); |
340 | #endif /* CONFIG_SMP */ | 305 | #endif /* CONFIG_SMP */ |
341 | 306 | ||
@@ -344,6 +309,11 @@ void machine_restart(char * __unused) | |||
344 | #ifdef CONFIG_X86_IO_APIC | 309 | #ifdef CONFIG_X86_IO_APIC |
345 | disable_IO_APIC(); | 310 | disable_IO_APIC(); |
346 | #endif | 311 | #endif |
312 | } | ||
313 | |||
314 | void machine_restart(char * __unused) | ||
315 | { | ||
316 | machine_shutdown(); | ||
347 | 317 | ||
348 | if (!reboot_thru_bios) { | 318 | if (!reboot_thru_bios) { |
349 | if (efi_enabled) { | 319 | if (efi_enabled) { |
diff --git a/arch/i386/kernel/relocate_kernel.S b/arch/i386/kernel/relocate_kernel.S new file mode 100644 index 000000000000..d312616effa1 --- /dev/null +++ b/arch/i386/kernel/relocate_kernel.S | |||
@@ -0,0 +1,120 @@ | |||
1 | /* | ||
2 | * relocate_kernel.S - put the kernel image in place to boot | ||
3 | * Copyright (C) 2002-2004 Eric Biederman <ebiederm@xmission.com> | ||
4 | * | ||
5 | * This source code is licensed under the GNU General Public License, | ||
6 | * Version 2. See the file COPYING for more details. | ||
7 | */ | ||
8 | |||
9 | #include <linux/linkage.h> | ||
10 | |||
11 | /* | ||
12 | * Must be relocatable PIC code callable as a C function, that once | ||
13 | * it starts can not use the previous processes stack. | ||
14 | */ | ||
15 | .globl relocate_new_kernel | ||
16 | relocate_new_kernel: | ||
17 | /* read the arguments and say goodbye to the stack */ | ||
18 | movl 4(%esp), %ebx /* page_list */ | ||
19 | movl 8(%esp), %ebp /* reboot_code_buffer */ | ||
20 | movl 12(%esp), %edx /* start address */ | ||
21 | movl 16(%esp), %ecx /* cpu_has_pae */ | ||
22 | |||
23 | /* zero out flags, and disable interrupts */ | ||
24 | pushl $0 | ||
25 | popfl | ||
26 | |||
27 | /* set a new stack at the bottom of our page... */ | ||
28 | lea 4096(%ebp), %esp | ||
29 | |||
30 | /* store the parameters back on the stack */ | ||
31 | pushl %edx /* store the start address */ | ||
32 | |||
33 | /* Set cr0 to a known state: | ||
34 | * 31 0 == Paging disabled | ||
35 | * 18 0 == Alignment check disabled | ||
36 | * 16 0 == Write protect disabled | ||
37 | * 3 0 == No task switch | ||
38 | * 2 0 == Don't do FP software emulation. | ||
39 | * 0 1 == Proctected mode enabled | ||
40 | */ | ||
41 | movl %cr0, %eax | ||
42 | andl $~((1<<31)|(1<<18)|(1<<16)|(1<<3)|(1<<2)), %eax | ||
43 | orl $(1<<0), %eax | ||
44 | movl %eax, %cr0 | ||
45 | |||
46 | /* clear cr4 if applicable */ | ||
47 | testl %ecx, %ecx | ||
48 | jz 1f | ||
49 | /* Set cr4 to a known state: | ||
50 | * Setting everything to zero seems safe. | ||
51 | */ | ||
52 | movl %cr4, %eax | ||
53 | andl $0, %eax | ||
54 | movl %eax, %cr4 | ||
55 | |||
56 | jmp 1f | ||
57 | 1: | ||
58 | |||
59 | /* Flush the TLB (needed?) */ | ||
60 | xorl %eax, %eax | ||
61 | movl %eax, %cr3 | ||
62 | |||
63 | /* Do the copies */ | ||
64 | movl %ebx, %ecx | ||
65 | jmp 1f | ||
66 | |||
67 | 0: /* top, read another word from the indirection page */ | ||
68 | movl (%ebx), %ecx | ||
69 | addl $4, %ebx | ||
70 | 1: | ||
71 | testl $0x1, %ecx /* is it a destination page */ | ||
72 | jz 2f | ||
73 | movl %ecx, %edi | ||
74 | andl $0xfffff000, %edi | ||
75 | jmp 0b | ||
76 | 2: | ||
77 | testl $0x2, %ecx /* is it an indirection page */ | ||
78 | jz 2f | ||
79 | movl %ecx, %ebx | ||
80 | andl $0xfffff000, %ebx | ||
81 | jmp 0b | ||
82 | 2: | ||
83 | testl $0x4, %ecx /* is it the done indicator */ | ||
84 | jz 2f | ||
85 | jmp 3f | ||
86 | 2: | ||
87 | testl $0x8, %ecx /* is it the source indicator */ | ||
88 | jz 0b /* Ignore it otherwise */ | ||
89 | movl %ecx, %esi /* For every source page do a copy */ | ||
90 | andl $0xfffff000, %esi | ||
91 | |||
92 | movl $1024, %ecx | ||
93 | rep ; movsl | ||
94 | jmp 0b | ||
95 | |||
96 | 3: | ||
97 | |||
98 | /* To be certain of avoiding problems with self-modifying code | ||
99 | * I need to execute a serializing instruction here. | ||
100 | * So I flush the TLB, it's handy, and not processor dependent. | ||
101 | */ | ||
102 | xorl %eax, %eax | ||
103 | movl %eax, %cr3 | ||
104 | |||
105 | /* set all of the registers to known values */ | ||
106 | /* leave %esp alone */ | ||
107 | |||
108 | xorl %eax, %eax | ||
109 | xorl %ebx, %ebx | ||
110 | xorl %ecx, %ecx | ||
111 | xorl %edx, %edx | ||
112 | xorl %esi, %esi | ||
113 | xorl %edi, %edi | ||
114 | xorl %ebp, %ebp | ||
115 | ret | ||
116 | relocate_new_kernel_end: | ||
117 | |||
118 | .globl relocate_new_kernel_size | ||
119 | relocate_new_kernel_size: | ||
120 | .long relocate_new_kernel_end - relocate_new_kernel | ||
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index 30406fd0b64c..7306353c520e 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c | |||
@@ -43,7 +43,12 @@ | |||
43 | #include <linux/init.h> | 43 | #include <linux/init.h> |
44 | #include <linux/edd.h> | 44 | #include <linux/edd.h> |
45 | #include <linux/nodemask.h> | 45 | #include <linux/nodemask.h> |
46 | #include <linux/kexec.h> | ||
47 | #include <linux/crash_dump.h> | ||
48 | |||
46 | #include <video/edid.h> | 49 | #include <video/edid.h> |
50 | |||
51 | #include <asm/apic.h> | ||
47 | #include <asm/e820.h> | 52 | #include <asm/e820.h> |
48 | #include <asm/mpspec.h> | 53 | #include <asm/mpspec.h> |
49 | #include <asm/setup.h> | 54 | #include <asm/setup.h> |
@@ -55,12 +60,15 @@ | |||
55 | #include "setup_arch_pre.h" | 60 | #include "setup_arch_pre.h" |
56 | #include <bios_ebda.h> | 61 | #include <bios_ebda.h> |
57 | 62 | ||
63 | /* Forward Declaration. */ | ||
64 | void __init find_max_pfn(void); | ||
65 | |||
58 | /* This value is set up by the early boot code to point to the value | 66 | /* This value is set up by the early boot code to point to the value |
59 | immediately after the boot time page tables. It contains a *physical* | 67 | immediately after the boot time page tables. It contains a *physical* |
60 | address, and must not be in the .bss segment! */ | 68 | address, and must not be in the .bss segment! */ |
61 | unsigned long init_pg_tables_end __initdata = ~0UL; | 69 | unsigned long init_pg_tables_end __initdata = ~0UL; |
62 | 70 | ||
63 | int disable_pse __initdata = 0; | 71 | int disable_pse __devinitdata = 0; |
64 | 72 | ||
65 | /* | 73 | /* |
66 | * Machine setup.. | 74 | * Machine setup.. |
@@ -732,6 +740,15 @@ static void __init parse_cmdline_early (char ** cmdline_p) | |||
732 | if (to != command_line) | 740 | if (to != command_line) |
733 | to--; | 741 | to--; |
734 | if (!memcmp(from+7, "exactmap", 8)) { | 742 | if (!memcmp(from+7, "exactmap", 8)) { |
743 | #ifdef CONFIG_CRASH_DUMP | ||
744 | /* If we are doing a crash dump, we | ||
745 | * still need to know the real mem | ||
746 | * size before original memory map is | ||
747 | * reset. | ||
748 | */ | ||
749 | find_max_pfn(); | ||
750 | saved_max_pfn = max_pfn; | ||
751 | #endif | ||
735 | from += 8+7; | 752 | from += 8+7; |
736 | e820.nr_map = 0; | 753 | e820.nr_map = 0; |
737 | userdef = 1; | 754 | userdef = 1; |
@@ -835,6 +852,44 @@ static void __init parse_cmdline_early (char ** cmdline_p) | |||
835 | #endif /* CONFIG_X86_LOCAL_APIC */ | 852 | #endif /* CONFIG_X86_LOCAL_APIC */ |
836 | #endif /* CONFIG_ACPI_BOOT */ | 853 | #endif /* CONFIG_ACPI_BOOT */ |
837 | 854 | ||
855 | #ifdef CONFIG_X86_LOCAL_APIC | ||
856 | /* enable local APIC */ | ||
857 | else if (!memcmp(from, "lapic", 5)) | ||
858 | lapic_enable(); | ||
859 | |||
860 | /* disable local APIC */ | ||
861 | else if (!memcmp(from, "nolapic", 6)) | ||
862 | lapic_disable(); | ||
863 | #endif /* CONFIG_X86_LOCAL_APIC */ | ||
864 | |||
865 | #ifdef CONFIG_KEXEC | ||
866 | /* crashkernel=size@addr specifies the location to reserve for | ||
867 | * a crash kernel. By reserving this memory we guarantee | ||
868 | * that linux never set's it up as a DMA target. | ||
869 | * Useful for holding code to do something appropriate | ||
870 | * after a kernel panic. | ||
871 | */ | ||
872 | else if (!memcmp(from, "crashkernel=", 12)) { | ||
873 | unsigned long size, base; | ||
874 | size = memparse(from+12, &from); | ||
875 | if (*from == '@') { | ||
876 | base = memparse(from+1, &from); | ||
877 | /* FIXME: Do I want a sanity check | ||
878 | * to validate the memory range? | ||
879 | */ | ||
880 | crashk_res.start = base; | ||
881 | crashk_res.end = base + size - 1; | ||
882 | } | ||
883 | } | ||
884 | #endif | ||
885 | #ifdef CONFIG_CRASH_DUMP | ||
886 | /* elfcorehdr= specifies the location of elf core header | ||
887 | * stored by the crashed kernel. | ||
888 | */ | ||
889 | else if (!memcmp(from, "elfcorehdr=", 11)) | ||
890 | elfcorehdr_addr = memparse(from+11, &from); | ||
891 | #endif | ||
892 | |||
838 | /* | 893 | /* |
839 | * highmem=size forces highmem to be exactly 'size' bytes. | 894 | * highmem=size forces highmem to be exactly 'size' bytes. |
840 | * This works even on boxes that have no highmem otherwise. | 895 | * This works even on boxes that have no highmem otherwise. |
@@ -1113,8 +1168,8 @@ void __init setup_bootmem_allocator(void) | |||
1113 | * the (very unlikely) case of us accidentally initializing the | 1168 | * the (very unlikely) case of us accidentally initializing the |
1114 | * bootmem allocator with an invalid RAM area. | 1169 | * bootmem allocator with an invalid RAM area. |
1115 | */ | 1170 | */ |
1116 | reserve_bootmem(HIGH_MEMORY, (PFN_PHYS(min_low_pfn) + | 1171 | reserve_bootmem(__PHYSICAL_START, (PFN_PHYS(min_low_pfn) + |
1117 | bootmap_size + PAGE_SIZE-1) - (HIGH_MEMORY)); | 1172 | bootmap_size + PAGE_SIZE-1) - (__PHYSICAL_START)); |
1118 | 1173 | ||
1119 | /* | 1174 | /* |
1120 | * reserve physical page 0 - it's a special BIOS page on many boxes, | 1175 | * reserve physical page 0 - it's a special BIOS page on many boxes, |
@@ -1170,6 +1225,11 @@ void __init setup_bootmem_allocator(void) | |||
1170 | } | 1225 | } |
1171 | } | 1226 | } |
1172 | #endif | 1227 | #endif |
1228 | #ifdef CONFIG_KEXEC | ||
1229 | if (crashk_res.start != crashk_res.end) | ||
1230 | reserve_bootmem(crashk_res.start, | ||
1231 | crashk_res.end - crashk_res.start + 1); | ||
1232 | #endif | ||
1173 | } | 1233 | } |
1174 | 1234 | ||
1175 | /* | 1235 | /* |
@@ -1223,6 +1283,9 @@ legacy_init_iomem_resources(struct resource *code_resource, struct resource *dat | |||
1223 | */ | 1283 | */ |
1224 | request_resource(res, code_resource); | 1284 | request_resource(res, code_resource); |
1225 | request_resource(res, data_resource); | 1285 | request_resource(res, data_resource); |
1286 | #ifdef CONFIG_KEXEC | ||
1287 | request_resource(res, &crashk_res); | ||
1288 | #endif | ||
1226 | } | 1289 | } |
1227 | } | 1290 | } |
1228 | } | 1291 | } |
diff --git a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c index b9b8f4e20fad..89ef7adc63a4 100644 --- a/arch/i386/kernel/signal.c +++ b/arch/i386/kernel/signal.c | |||
@@ -608,10 +608,8 @@ int fastcall do_signal(struct pt_regs *regs, sigset_t *oldset) | |||
608 | if (!user_mode(regs)) | 608 | if (!user_mode(regs)) |
609 | return 1; | 609 | return 1; |
610 | 610 | ||
611 | if (current->flags & PF_FREEZE) { | 611 | if (try_to_freeze()) |
612 | refrigerator(0); | ||
613 | goto no_signal; | 612 | goto no_signal; |
614 | } | ||
615 | 613 | ||
616 | if (!oldset) | 614 | if (!oldset) |
617 | oldset = ¤t->blocked; | 615 | oldset = ¤t->blocked; |
diff --git a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c index 68be7d0c7238..cec4bde67161 100644 --- a/arch/i386/kernel/smp.c +++ b/arch/i386/kernel/smp.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/mc146818rtc.h> | 19 | #include <linux/mc146818rtc.h> |
20 | #include <linux/cache.h> | 20 | #include <linux/cache.h> |
21 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
22 | #include <linux/cpu.h> | ||
22 | #include <linux/module.h> | 23 | #include <linux/module.h> |
23 | 24 | ||
24 | #include <asm/mtrr.h> | 25 | #include <asm/mtrr.h> |
@@ -164,7 +165,7 @@ void send_IPI_mask_bitmask(cpumask_t cpumask, int vector) | |||
164 | unsigned long flags; | 165 | unsigned long flags; |
165 | 166 | ||
166 | local_irq_save(flags); | 167 | local_irq_save(flags); |
167 | 168 | WARN_ON(mask & ~cpus_addr(cpu_online_map)[0]); | |
168 | /* | 169 | /* |
169 | * Wait for idle. | 170 | * Wait for idle. |
170 | */ | 171 | */ |
@@ -346,21 +347,21 @@ out: | |||
346 | static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm, | 347 | static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm, |
347 | unsigned long va) | 348 | unsigned long va) |
348 | { | 349 | { |
349 | cpumask_t tmp; | ||
350 | /* | 350 | /* |
351 | * A couple of (to be removed) sanity checks: | 351 | * A couple of (to be removed) sanity checks: |
352 | * | 352 | * |
353 | * - we do not send IPIs to not-yet booted CPUs. | ||
354 | * - current CPU must not be in mask | 353 | * - current CPU must not be in mask |
355 | * - mask must exist :) | 354 | * - mask must exist :) |
356 | */ | 355 | */ |
357 | BUG_ON(cpus_empty(cpumask)); | 356 | BUG_ON(cpus_empty(cpumask)); |
358 | |||
359 | cpus_and(tmp, cpumask, cpu_online_map); | ||
360 | BUG_ON(!cpus_equal(cpumask, tmp)); | ||
361 | BUG_ON(cpu_isset(smp_processor_id(), cpumask)); | 357 | BUG_ON(cpu_isset(smp_processor_id(), cpumask)); |
362 | BUG_ON(!mm); | 358 | BUG_ON(!mm); |
363 | 359 | ||
360 | /* If a CPU which we ran on has gone down, OK. */ | ||
361 | cpus_and(cpumask, cpumask, cpu_online_map); | ||
362 | if (cpus_empty(cpumask)) | ||
363 | return; | ||
364 | |||
364 | /* | 365 | /* |
365 | * i'm not happy about this global shared spinlock in the | 366 | * i'm not happy about this global shared spinlock in the |
366 | * MM hot path, but we'll see how contended it is. | 367 | * MM hot path, but we'll see how contended it is. |
@@ -476,6 +477,7 @@ void flush_tlb_all(void) | |||
476 | */ | 477 | */ |
477 | void smp_send_reschedule(int cpu) | 478 | void smp_send_reschedule(int cpu) |
478 | { | 479 | { |
480 | WARN_ON(cpu_is_offline(cpu)); | ||
479 | send_IPI_mask(cpumask_of_cpu(cpu), RESCHEDULE_VECTOR); | 481 | send_IPI_mask(cpumask_of_cpu(cpu), RESCHEDULE_VECTOR); |
480 | } | 482 | } |
481 | 483 | ||
@@ -493,6 +495,16 @@ struct call_data_struct { | |||
493 | int wait; | 495 | int wait; |
494 | }; | 496 | }; |
495 | 497 | ||
498 | void lock_ipi_call_lock(void) | ||
499 | { | ||
500 | spin_lock_irq(&call_lock); | ||
501 | } | ||
502 | |||
503 | void unlock_ipi_call_lock(void) | ||
504 | { | ||
505 | spin_unlock_irq(&call_lock); | ||
506 | } | ||
507 | |||
496 | static struct call_data_struct * call_data; | 508 | static struct call_data_struct * call_data; |
497 | 509 | ||
498 | /* | 510 | /* |
@@ -516,10 +528,15 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic, | |||
516 | */ | 528 | */ |
517 | { | 529 | { |
518 | struct call_data_struct data; | 530 | struct call_data_struct data; |
519 | int cpus = num_online_cpus()-1; | 531 | int cpus; |
520 | 532 | ||
521 | if (!cpus) | 533 | /* Holding any lock stops cpus from going down. */ |
534 | spin_lock(&call_lock); | ||
535 | cpus = num_online_cpus() - 1; | ||
536 | if (!cpus) { | ||
537 | spin_unlock(&call_lock); | ||
522 | return 0; | 538 | return 0; |
539 | } | ||
523 | 540 | ||
524 | /* Can deadlock when called with interrupts disabled */ | 541 | /* Can deadlock when called with interrupts disabled */ |
525 | WARN_ON(irqs_disabled()); | 542 | WARN_ON(irqs_disabled()); |
@@ -531,7 +548,6 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic, | |||
531 | if (wait) | 548 | if (wait) |
532 | atomic_set(&data.finished, 0); | 549 | atomic_set(&data.finished, 0); |
533 | 550 | ||
534 | spin_lock(&call_lock); | ||
535 | call_data = &data; | 551 | call_data = &data; |
536 | mb(); | 552 | mb(); |
537 | 553 | ||
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index c20d96d5c15c..d66bf489a2e9 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c | |||
@@ -44,6 +44,9 @@ | |||
44 | #include <linux/smp_lock.h> | 44 | #include <linux/smp_lock.h> |
45 | #include <linux/irq.h> | 45 | #include <linux/irq.h> |
46 | #include <linux/bootmem.h> | 46 | #include <linux/bootmem.h> |
47 | #include <linux/notifier.h> | ||
48 | #include <linux/cpu.h> | ||
49 | #include <linux/percpu.h> | ||
47 | 50 | ||
48 | #include <linux/delay.h> | 51 | #include <linux/delay.h> |
49 | #include <linux/mc146818rtc.h> | 52 | #include <linux/mc146818rtc.h> |
@@ -56,18 +59,28 @@ | |||
56 | #include <smpboot_hooks.h> | 59 | #include <smpboot_hooks.h> |
57 | 60 | ||
58 | /* Set if we find a B stepping CPU */ | 61 | /* Set if we find a B stepping CPU */ |
59 | static int __initdata smp_b_stepping; | 62 | static int __devinitdata smp_b_stepping; |
60 | 63 | ||
61 | /* Number of siblings per CPU package */ | 64 | /* Number of siblings per CPU package */ |
62 | int smp_num_siblings = 1; | 65 | int smp_num_siblings = 1; |
63 | #ifdef CONFIG_X86_HT | 66 | #ifdef CONFIG_X86_HT |
64 | EXPORT_SYMBOL(smp_num_siblings); | 67 | EXPORT_SYMBOL(smp_num_siblings); |
65 | #endif | 68 | #endif |
66 | int phys_proc_id[NR_CPUS]; /* Package ID of each logical CPU */ | 69 | |
70 | /* Package ID of each logical CPU */ | ||
71 | int phys_proc_id[NR_CPUS] = {[0 ... NR_CPUS-1] = BAD_APICID}; | ||
67 | EXPORT_SYMBOL(phys_proc_id); | 72 | EXPORT_SYMBOL(phys_proc_id); |
68 | int cpu_core_id[NR_CPUS]; /* Core ID of each logical CPU */ | 73 | |
74 | /* Core ID of each logical CPU */ | ||
75 | int cpu_core_id[NR_CPUS] = {[0 ... NR_CPUS-1] = BAD_APICID}; | ||
69 | EXPORT_SYMBOL(cpu_core_id); | 76 | EXPORT_SYMBOL(cpu_core_id); |
70 | 77 | ||
78 | cpumask_t cpu_sibling_map[NR_CPUS]; | ||
79 | EXPORT_SYMBOL(cpu_sibling_map); | ||
80 | |||
81 | cpumask_t cpu_core_map[NR_CPUS]; | ||
82 | EXPORT_SYMBOL(cpu_core_map); | ||
83 | |||
71 | /* bitmap of online cpus */ | 84 | /* bitmap of online cpus */ |
72 | cpumask_t cpu_online_map; | 85 | cpumask_t cpu_online_map; |
73 | EXPORT_SYMBOL(cpu_online_map); | 86 | EXPORT_SYMBOL(cpu_online_map); |
@@ -77,6 +90,12 @@ cpumask_t cpu_callout_map; | |||
77 | EXPORT_SYMBOL(cpu_callout_map); | 90 | EXPORT_SYMBOL(cpu_callout_map); |
78 | static cpumask_t smp_commenced_mask; | 91 | static cpumask_t smp_commenced_mask; |
79 | 92 | ||
93 | /* TSC's upper 32 bits can't be written in eariler CPU (before prescott), there | ||
94 | * is no way to resync one AP against BP. TBD: for prescott and above, we | ||
95 | * should use IA64's algorithm | ||
96 | */ | ||
97 | static int __devinitdata tsc_sync_disabled; | ||
98 | |||
80 | /* Per CPU bogomips and other parameters */ | 99 | /* Per CPU bogomips and other parameters */ |
81 | struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned; | 100 | struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned; |
82 | EXPORT_SYMBOL(cpu_data); | 101 | EXPORT_SYMBOL(cpu_data); |
@@ -96,13 +115,16 @@ static int trampoline_exec; | |||
96 | 115 | ||
97 | static void map_cpu_to_logical_apicid(void); | 116 | static void map_cpu_to_logical_apicid(void); |
98 | 117 | ||
118 | /* State of each CPU. */ | ||
119 | DEFINE_PER_CPU(int, cpu_state) = { 0 }; | ||
120 | |||
99 | /* | 121 | /* |
100 | * Currently trivial. Write the real->protected mode | 122 | * Currently trivial. Write the real->protected mode |
101 | * bootstrap into the page concerned. The caller | 123 | * bootstrap into the page concerned. The caller |
102 | * has made sure it's suitably aligned. | 124 | * has made sure it's suitably aligned. |
103 | */ | 125 | */ |
104 | 126 | ||
105 | static unsigned long __init setup_trampoline(void) | 127 | static unsigned long __devinit setup_trampoline(void) |
106 | { | 128 | { |
107 | memcpy(trampoline_base, trampoline_data, trampoline_end - trampoline_data); | 129 | memcpy(trampoline_base, trampoline_data, trampoline_end - trampoline_data); |
108 | return virt_to_phys(trampoline_base); | 130 | return virt_to_phys(trampoline_base); |
@@ -132,7 +154,7 @@ void __init smp_alloc_memory(void) | |||
132 | * a given CPU | 154 | * a given CPU |
133 | */ | 155 | */ |
134 | 156 | ||
135 | static void __init smp_store_cpu_info(int id) | 157 | static void __devinit smp_store_cpu_info(int id) |
136 | { | 158 | { |
137 | struct cpuinfo_x86 *c = cpu_data + id; | 159 | struct cpuinfo_x86 *c = cpu_data + id; |
138 | 160 | ||
@@ -326,7 +348,7 @@ extern void calibrate_delay(void); | |||
326 | 348 | ||
327 | static atomic_t init_deasserted; | 349 | static atomic_t init_deasserted; |
328 | 350 | ||
329 | static void __init smp_callin(void) | 351 | static void __devinit smp_callin(void) |
330 | { | 352 | { |
331 | int cpuid, phys_id; | 353 | int cpuid, phys_id; |
332 | unsigned long timeout; | 354 | unsigned long timeout; |
@@ -411,16 +433,48 @@ static void __init smp_callin(void) | |||
411 | /* | 433 | /* |
412 | * Synchronize the TSC with the BP | 434 | * Synchronize the TSC with the BP |
413 | */ | 435 | */ |
414 | if (cpu_has_tsc && cpu_khz) | 436 | if (cpu_has_tsc && cpu_khz && !tsc_sync_disabled) |
415 | synchronize_tsc_ap(); | 437 | synchronize_tsc_ap(); |
416 | } | 438 | } |
417 | 439 | ||
418 | static int cpucount; | 440 | static int cpucount; |
419 | 441 | ||
442 | static inline void | ||
443 | set_cpu_sibling_map(int cpu) | ||
444 | { | ||
445 | int i; | ||
446 | |||
447 | if (smp_num_siblings > 1) { | ||
448 | for (i = 0; i < NR_CPUS; i++) { | ||
449 | if (!cpu_isset(i, cpu_callout_map)) | ||
450 | continue; | ||
451 | if (cpu_core_id[cpu] == cpu_core_id[i]) { | ||
452 | cpu_set(i, cpu_sibling_map[cpu]); | ||
453 | cpu_set(cpu, cpu_sibling_map[i]); | ||
454 | } | ||
455 | } | ||
456 | } else { | ||
457 | cpu_set(cpu, cpu_sibling_map[cpu]); | ||
458 | } | ||
459 | |||
460 | if (current_cpu_data.x86_num_cores > 1) { | ||
461 | for (i = 0; i < NR_CPUS; i++) { | ||
462 | if (!cpu_isset(i, cpu_callout_map)) | ||
463 | continue; | ||
464 | if (phys_proc_id[cpu] == phys_proc_id[i]) { | ||
465 | cpu_set(i, cpu_core_map[cpu]); | ||
466 | cpu_set(cpu, cpu_core_map[i]); | ||
467 | } | ||
468 | } | ||
469 | } else { | ||
470 | cpu_core_map[cpu] = cpu_sibling_map[cpu]; | ||
471 | } | ||
472 | } | ||
473 | |||
420 | /* | 474 | /* |
421 | * Activate a secondary processor. | 475 | * Activate a secondary processor. |
422 | */ | 476 | */ |
423 | static void __init start_secondary(void *unused) | 477 | static void __devinit start_secondary(void *unused) |
424 | { | 478 | { |
425 | /* | 479 | /* |
426 | * Dont put anything before smp_callin(), SMP | 480 | * Dont put anything before smp_callin(), SMP |
@@ -443,7 +497,23 @@ static void __init start_secondary(void *unused) | |||
443 | * the local TLBs too. | 497 | * the local TLBs too. |
444 | */ | 498 | */ |
445 | local_flush_tlb(); | 499 | local_flush_tlb(); |
500 | |||
501 | /* This must be done before setting cpu_online_map */ | ||
502 | set_cpu_sibling_map(raw_smp_processor_id()); | ||
503 | wmb(); | ||
504 | |||
505 | /* | ||
506 | * We need to hold call_lock, so there is no inconsistency | ||
507 | * between the time smp_call_function() determines number of | ||
508 | * IPI receipients, and the time when the determination is made | ||
509 | * for which cpus receive the IPI. Holding this | ||
510 | * lock helps us to not include this cpu in a currently in progress | ||
511 | * smp_call_function(). | ||
512 | */ | ||
513 | lock_ipi_call_lock(); | ||
446 | cpu_set(smp_processor_id(), cpu_online_map); | 514 | cpu_set(smp_processor_id(), cpu_online_map); |
515 | unlock_ipi_call_lock(); | ||
516 | per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE; | ||
447 | 517 | ||
448 | /* We can take interrupts now: we're officially "up". */ | 518 | /* We can take interrupts now: we're officially "up". */ |
449 | local_irq_enable(); | 519 | local_irq_enable(); |
@@ -458,7 +528,7 @@ static void __init start_secondary(void *unused) | |||
458 | * from the task structure | 528 | * from the task structure |
459 | * This function must not return. | 529 | * This function must not return. |
460 | */ | 530 | */ |
461 | void __init initialize_secondary(void) | 531 | void __devinit initialize_secondary(void) |
462 | { | 532 | { |
463 | /* | 533 | /* |
464 | * We don't actually need to load the full TSS, | 534 | * We don't actually need to load the full TSS, |
@@ -572,7 +642,7 @@ static inline void __inquire_remote_apic(int apicid) | |||
572 | * INIT, INIT, STARTUP sequence will reset the chip hard for us, and this | 642 | * INIT, INIT, STARTUP sequence will reset the chip hard for us, and this |
573 | * won't ... remember to clear down the APIC, etc later. | 643 | * won't ... remember to clear down the APIC, etc later. |
574 | */ | 644 | */ |
575 | static int __init | 645 | static int __devinit |
576 | wakeup_secondary_cpu(int logical_apicid, unsigned long start_eip) | 646 | wakeup_secondary_cpu(int logical_apicid, unsigned long start_eip) |
577 | { | 647 | { |
578 | unsigned long send_status = 0, accept_status = 0; | 648 | unsigned long send_status = 0, accept_status = 0; |
@@ -618,7 +688,7 @@ wakeup_secondary_cpu(int logical_apicid, unsigned long start_eip) | |||
618 | #endif /* WAKE_SECONDARY_VIA_NMI */ | 688 | #endif /* WAKE_SECONDARY_VIA_NMI */ |
619 | 689 | ||
620 | #ifdef WAKE_SECONDARY_VIA_INIT | 690 | #ifdef WAKE_SECONDARY_VIA_INIT |
621 | static int __init | 691 | static int __devinit |
622 | wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip) | 692 | wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip) |
623 | { | 693 | { |
624 | unsigned long send_status = 0, accept_status = 0; | 694 | unsigned long send_status = 0, accept_status = 0; |
@@ -753,8 +823,43 @@ wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip) | |||
753 | #endif /* WAKE_SECONDARY_VIA_INIT */ | 823 | #endif /* WAKE_SECONDARY_VIA_INIT */ |
754 | 824 | ||
755 | extern cpumask_t cpu_initialized; | 825 | extern cpumask_t cpu_initialized; |
826 | static inline int alloc_cpu_id(void) | ||
827 | { | ||
828 | cpumask_t tmp_map; | ||
829 | int cpu; | ||
830 | cpus_complement(tmp_map, cpu_present_map); | ||
831 | cpu = first_cpu(tmp_map); | ||
832 | if (cpu >= NR_CPUS) | ||
833 | return -ENODEV; | ||
834 | return cpu; | ||
835 | } | ||
836 | |||
837 | #ifdef CONFIG_HOTPLUG_CPU | ||
838 | static struct task_struct * __devinitdata cpu_idle_tasks[NR_CPUS]; | ||
839 | static inline struct task_struct * alloc_idle_task(int cpu) | ||
840 | { | ||
841 | struct task_struct *idle; | ||
842 | |||
843 | if ((idle = cpu_idle_tasks[cpu]) != NULL) { | ||
844 | /* initialize thread_struct. we really want to avoid destroy | ||
845 | * idle tread | ||
846 | */ | ||
847 | idle->thread.esp = (unsigned long)(((struct pt_regs *) | ||
848 | (THREAD_SIZE + (unsigned long) idle->thread_info)) - 1); | ||
849 | init_idle(idle, cpu); | ||
850 | return idle; | ||
851 | } | ||
852 | idle = fork_idle(cpu); | ||
853 | |||
854 | if (!IS_ERR(idle)) | ||
855 | cpu_idle_tasks[cpu] = idle; | ||
856 | return idle; | ||
857 | } | ||
858 | #else | ||
859 | #define alloc_idle_task(cpu) fork_idle(cpu) | ||
860 | #endif | ||
756 | 861 | ||
757 | static int __init do_boot_cpu(int apicid) | 862 | static int __devinit do_boot_cpu(int apicid, int cpu) |
758 | /* | 863 | /* |
759 | * NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad | 864 | * NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad |
760 | * (ie clustered apic addressing mode), this is a LOGICAL apic ID. | 865 | * (ie clustered apic addressing mode), this is a LOGICAL apic ID. |
@@ -763,16 +868,17 @@ static int __init do_boot_cpu(int apicid) | |||
763 | { | 868 | { |
764 | struct task_struct *idle; | 869 | struct task_struct *idle; |
765 | unsigned long boot_error; | 870 | unsigned long boot_error; |
766 | int timeout, cpu; | 871 | int timeout; |
767 | unsigned long start_eip; | 872 | unsigned long start_eip; |
768 | unsigned short nmi_high = 0, nmi_low = 0; | 873 | unsigned short nmi_high = 0, nmi_low = 0; |
769 | 874 | ||
770 | cpu = ++cpucount; | 875 | ++cpucount; |
876 | |||
771 | /* | 877 | /* |
772 | * We can't use kernel_thread since we must avoid to | 878 | * We can't use kernel_thread since we must avoid to |
773 | * reschedule the child. | 879 | * reschedule the child. |
774 | */ | 880 | */ |
775 | idle = fork_idle(cpu); | 881 | idle = alloc_idle_task(cpu); |
776 | if (IS_ERR(idle)) | 882 | if (IS_ERR(idle)) |
777 | panic("failed fork for CPU %d", cpu); | 883 | panic("failed fork for CPU %d", cpu); |
778 | idle->thread.eip = (unsigned long) start_secondary; | 884 | idle->thread.eip = (unsigned long) start_secondary; |
@@ -839,13 +945,16 @@ static int __init do_boot_cpu(int apicid) | |||
839 | inquire_remote_apic(apicid); | 945 | inquire_remote_apic(apicid); |
840 | } | 946 | } |
841 | } | 947 | } |
842 | x86_cpu_to_apicid[cpu] = apicid; | 948 | |
843 | if (boot_error) { | 949 | if (boot_error) { |
844 | /* Try to put things back the way they were before ... */ | 950 | /* Try to put things back the way they were before ... */ |
845 | unmap_cpu_to_logical_apicid(cpu); | 951 | unmap_cpu_to_logical_apicid(cpu); |
846 | cpu_clear(cpu, cpu_callout_map); /* was set here (do_boot_cpu()) */ | 952 | cpu_clear(cpu, cpu_callout_map); /* was set here (do_boot_cpu()) */ |
847 | cpu_clear(cpu, cpu_initialized); /* was set by cpu_init() */ | 953 | cpu_clear(cpu, cpu_initialized); /* was set by cpu_init() */ |
848 | cpucount--; | 954 | cpucount--; |
955 | } else { | ||
956 | x86_cpu_to_apicid[cpu] = apicid; | ||
957 | cpu_set(cpu, cpu_present_map); | ||
849 | } | 958 | } |
850 | 959 | ||
851 | /* mark "stuck" area as not stuck */ | 960 | /* mark "stuck" area as not stuck */ |
@@ -854,6 +963,75 @@ static int __init do_boot_cpu(int apicid) | |||
854 | return boot_error; | 963 | return boot_error; |
855 | } | 964 | } |
856 | 965 | ||
966 | #ifdef CONFIG_HOTPLUG_CPU | ||
967 | void cpu_exit_clear(void) | ||
968 | { | ||
969 | int cpu = raw_smp_processor_id(); | ||
970 | |||
971 | idle_task_exit(); | ||
972 | |||
973 | cpucount --; | ||
974 | cpu_uninit(); | ||
975 | irq_ctx_exit(cpu); | ||
976 | |||
977 | cpu_clear(cpu, cpu_callout_map); | ||
978 | cpu_clear(cpu, cpu_callin_map); | ||
979 | cpu_clear(cpu, cpu_present_map); | ||
980 | |||
981 | cpu_clear(cpu, smp_commenced_mask); | ||
982 | unmap_cpu_to_logical_apicid(cpu); | ||
983 | } | ||
984 | |||
985 | struct warm_boot_cpu_info { | ||
986 | struct completion *complete; | ||
987 | int apicid; | ||
988 | int cpu; | ||
989 | }; | ||
990 | |||
991 | static void __devinit do_warm_boot_cpu(void *p) | ||
992 | { | ||
993 | struct warm_boot_cpu_info *info = p; | ||
994 | do_boot_cpu(info->apicid, info->cpu); | ||
995 | complete(info->complete); | ||
996 | } | ||
997 | |||
998 | int __devinit smp_prepare_cpu(int cpu) | ||
999 | { | ||
1000 | DECLARE_COMPLETION(done); | ||
1001 | struct warm_boot_cpu_info info; | ||
1002 | struct work_struct task; | ||
1003 | int apicid, ret; | ||
1004 | |||
1005 | lock_cpu_hotplug(); | ||
1006 | apicid = x86_cpu_to_apicid[cpu]; | ||
1007 | if (apicid == BAD_APICID) { | ||
1008 | ret = -ENODEV; | ||
1009 | goto exit; | ||
1010 | } | ||
1011 | |||
1012 | info.complete = &done; | ||
1013 | info.apicid = apicid; | ||
1014 | info.cpu = cpu; | ||
1015 | INIT_WORK(&task, do_warm_boot_cpu, &info); | ||
1016 | |||
1017 | tsc_sync_disabled = 1; | ||
1018 | |||
1019 | /* init low mem mapping */ | ||
1020 | memcpy(swapper_pg_dir, swapper_pg_dir + USER_PGD_PTRS, | ||
1021 | sizeof(swapper_pg_dir[0]) * KERNEL_PGD_PTRS); | ||
1022 | flush_tlb_all(); | ||
1023 | schedule_work(&task); | ||
1024 | wait_for_completion(&done); | ||
1025 | |||
1026 | tsc_sync_disabled = 0; | ||
1027 | zap_low_mappings(); | ||
1028 | ret = 0; | ||
1029 | exit: | ||
1030 | unlock_cpu_hotplug(); | ||
1031 | return ret; | ||
1032 | } | ||
1033 | #endif | ||
1034 | |||
857 | static void smp_tune_scheduling (void) | 1035 | static void smp_tune_scheduling (void) |
858 | { | 1036 | { |
859 | unsigned long cachesize; /* kB */ | 1037 | unsigned long cachesize; /* kB */ |
@@ -895,13 +1073,6 @@ void *xquad_portio; | |||
895 | EXPORT_SYMBOL(xquad_portio); | 1073 | EXPORT_SYMBOL(xquad_portio); |
896 | #endif | 1074 | #endif |
897 | 1075 | ||
898 | cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned; | ||
899 | #ifdef CONFIG_X86_HT | ||
900 | EXPORT_SYMBOL(cpu_sibling_map); | ||
901 | #endif | ||
902 | cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned; | ||
903 | EXPORT_SYMBOL(cpu_core_map); | ||
904 | |||
905 | static void __init smp_boot_cpus(unsigned int max_cpus) | 1076 | static void __init smp_boot_cpus(unsigned int max_cpus) |
906 | { | 1077 | { |
907 | int apicid, cpu, bit, kicked; | 1078 | int apicid, cpu, bit, kicked; |
@@ -1013,7 +1184,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus) | |||
1013 | if (max_cpus <= cpucount+1) | 1184 | if (max_cpus <= cpucount+1) |
1014 | continue; | 1185 | continue; |
1015 | 1186 | ||
1016 | if (do_boot_cpu(apicid)) | 1187 | if (((cpu = alloc_cpu_id()) <= 0) || do_boot_cpu(apicid, cpu)) |
1017 | printk("CPU #%d not responding - cannot use it.\n", | 1188 | printk("CPU #%d not responding - cannot use it.\n", |
1018 | apicid); | 1189 | apicid); |
1019 | else | 1190 | else |
@@ -1065,44 +1236,8 @@ static void __init smp_boot_cpus(unsigned int max_cpus) | |||
1065 | cpus_clear(cpu_core_map[cpu]); | 1236 | cpus_clear(cpu_core_map[cpu]); |
1066 | } | 1237 | } |
1067 | 1238 | ||
1068 | for (cpu = 0; cpu < NR_CPUS; cpu++) { | 1239 | cpu_set(0, cpu_sibling_map[0]); |
1069 | struct cpuinfo_x86 *c = cpu_data + cpu; | 1240 | cpu_set(0, cpu_core_map[0]); |
1070 | int siblings = 0; | ||
1071 | int i; | ||
1072 | if (!cpu_isset(cpu, cpu_callout_map)) | ||
1073 | continue; | ||
1074 | |||
1075 | if (smp_num_siblings > 1) { | ||
1076 | for (i = 0; i < NR_CPUS; i++) { | ||
1077 | if (!cpu_isset(i, cpu_callout_map)) | ||
1078 | continue; | ||
1079 | if (cpu_core_id[cpu] == cpu_core_id[i]) { | ||
1080 | siblings++; | ||
1081 | cpu_set(i, cpu_sibling_map[cpu]); | ||
1082 | } | ||
1083 | } | ||
1084 | } else { | ||
1085 | siblings++; | ||
1086 | cpu_set(cpu, cpu_sibling_map[cpu]); | ||
1087 | } | ||
1088 | |||
1089 | if (siblings != smp_num_siblings) { | ||
1090 | printk(KERN_WARNING "WARNING: %d siblings found for CPU%d, should be %d\n", siblings, cpu, smp_num_siblings); | ||
1091 | smp_num_siblings = siblings; | ||
1092 | } | ||
1093 | |||
1094 | if (c->x86_num_cores > 1) { | ||
1095 | for (i = 0; i < NR_CPUS; i++) { | ||
1096 | if (!cpu_isset(i, cpu_callout_map)) | ||
1097 | continue; | ||
1098 | if (phys_proc_id[cpu] == phys_proc_id[i]) { | ||
1099 | cpu_set(i, cpu_core_map[cpu]); | ||
1100 | } | ||
1101 | } | ||
1102 | } else { | ||
1103 | cpu_core_map[cpu] = cpu_sibling_map[cpu]; | ||
1104 | } | ||
1105 | } | ||
1106 | 1241 | ||
1107 | smpboot_setup_io_apic(); | 1242 | smpboot_setup_io_apic(); |
1108 | 1243 | ||
@@ -1119,6 +1254,9 @@ static void __init smp_boot_cpus(unsigned int max_cpus) | |||
1119 | who understands all this stuff should rewrite it properly. --RR 15/Jul/02 */ | 1254 | who understands all this stuff should rewrite it properly. --RR 15/Jul/02 */ |
1120 | void __init smp_prepare_cpus(unsigned int max_cpus) | 1255 | void __init smp_prepare_cpus(unsigned int max_cpus) |
1121 | { | 1256 | { |
1257 | smp_commenced_mask = cpumask_of_cpu(0); | ||
1258 | cpu_callin_map = cpumask_of_cpu(0); | ||
1259 | mb(); | ||
1122 | smp_boot_cpus(max_cpus); | 1260 | smp_boot_cpus(max_cpus); |
1123 | } | 1261 | } |
1124 | 1262 | ||
@@ -1126,23 +1264,98 @@ void __devinit smp_prepare_boot_cpu(void) | |||
1126 | { | 1264 | { |
1127 | cpu_set(smp_processor_id(), cpu_online_map); | 1265 | cpu_set(smp_processor_id(), cpu_online_map); |
1128 | cpu_set(smp_processor_id(), cpu_callout_map); | 1266 | cpu_set(smp_processor_id(), cpu_callout_map); |
1267 | cpu_set(smp_processor_id(), cpu_present_map); | ||
1268 | per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE; | ||
1129 | } | 1269 | } |
1130 | 1270 | ||
1131 | int __devinit __cpu_up(unsigned int cpu) | 1271 | #ifdef CONFIG_HOTPLUG_CPU |
1272 | static void | ||
1273 | remove_siblinginfo(int cpu) | ||
1132 | { | 1274 | { |
1133 | /* This only works at boot for x86. See "rewrite" above. */ | 1275 | int sibling; |
1134 | if (cpu_isset(cpu, smp_commenced_mask)) { | 1276 | |
1135 | local_irq_enable(); | 1277 | for_each_cpu_mask(sibling, cpu_sibling_map[cpu]) |
1136 | return -ENOSYS; | 1278 | cpu_clear(cpu, cpu_sibling_map[sibling]); |
1279 | for_each_cpu_mask(sibling, cpu_core_map[cpu]) | ||
1280 | cpu_clear(cpu, cpu_core_map[sibling]); | ||
1281 | cpus_clear(cpu_sibling_map[cpu]); | ||
1282 | cpus_clear(cpu_core_map[cpu]); | ||
1283 | phys_proc_id[cpu] = BAD_APICID; | ||
1284 | cpu_core_id[cpu] = BAD_APICID; | ||
1285 | } | ||
1286 | |||
1287 | int __cpu_disable(void) | ||
1288 | { | ||
1289 | cpumask_t map = cpu_online_map; | ||
1290 | int cpu = smp_processor_id(); | ||
1291 | |||
1292 | /* | ||
1293 | * Perhaps use cpufreq to drop frequency, but that could go | ||
1294 | * into generic code. | ||
1295 | * | ||
1296 | * We won't take down the boot processor on i386 due to some | ||
1297 | * interrupts only being able to be serviced by the BSP. | ||
1298 | * Especially so if we're not using an IOAPIC -zwane | ||
1299 | */ | ||
1300 | if (cpu == 0) | ||
1301 | return -EBUSY; | ||
1302 | |||
1303 | /* We enable the timer again on the exit path of the death loop */ | ||
1304 | disable_APIC_timer(); | ||
1305 | /* Allow any queued timer interrupts to get serviced */ | ||
1306 | local_irq_enable(); | ||
1307 | mdelay(1); | ||
1308 | local_irq_disable(); | ||
1309 | |||
1310 | remove_siblinginfo(cpu); | ||
1311 | |||
1312 | cpu_clear(cpu, map); | ||
1313 | fixup_irqs(map); | ||
1314 | /* It's now safe to remove this processor from the online map */ | ||
1315 | cpu_clear(cpu, cpu_online_map); | ||
1316 | return 0; | ||
1317 | } | ||
1318 | |||
1319 | void __cpu_die(unsigned int cpu) | ||
1320 | { | ||
1321 | /* We don't do anything here: idle task is faking death itself. */ | ||
1322 | unsigned int i; | ||
1323 | |||
1324 | for (i = 0; i < 10; i++) { | ||
1325 | /* They ack this in play_dead by setting CPU_DEAD */ | ||
1326 | if (per_cpu(cpu_state, cpu) == CPU_DEAD) { | ||
1327 | printk ("CPU %d is now offline\n", cpu); | ||
1328 | return; | ||
1329 | } | ||
1330 | current->state = TASK_UNINTERRUPTIBLE; | ||
1331 | schedule_timeout(HZ/10); | ||
1137 | } | 1332 | } |
1333 | printk(KERN_ERR "CPU %u didn't die...\n", cpu); | ||
1334 | } | ||
1335 | #else /* ... !CONFIG_HOTPLUG_CPU */ | ||
1336 | int __cpu_disable(void) | ||
1337 | { | ||
1338 | return -ENOSYS; | ||
1339 | } | ||
1340 | |||
1341 | void __cpu_die(unsigned int cpu) | ||
1342 | { | ||
1343 | /* We said "no" in __cpu_disable */ | ||
1344 | BUG(); | ||
1345 | } | ||
1346 | #endif /* CONFIG_HOTPLUG_CPU */ | ||
1138 | 1347 | ||
1348 | int __devinit __cpu_up(unsigned int cpu) | ||
1349 | { | ||
1139 | /* In case one didn't come up */ | 1350 | /* In case one didn't come up */ |
1140 | if (!cpu_isset(cpu, cpu_callin_map)) { | 1351 | if (!cpu_isset(cpu, cpu_callin_map)) { |
1352 | printk(KERN_DEBUG "skipping cpu%d, didn't come online\n", cpu); | ||
1141 | local_irq_enable(); | 1353 | local_irq_enable(); |
1142 | return -EIO; | 1354 | return -EIO; |
1143 | } | 1355 | } |
1144 | 1356 | ||
1145 | local_irq_enable(); | 1357 | local_irq_enable(); |
1358 | per_cpu(cpu_state, cpu) = CPU_UP_PREPARE; | ||
1146 | /* Unleash the CPU! */ | 1359 | /* Unleash the CPU! */ |
1147 | cpu_set(cpu, smp_commenced_mask); | 1360 | cpu_set(cpu, smp_commenced_mask); |
1148 | while (!cpu_isset(cpu, cpu_online_map)) | 1361 | while (!cpu_isset(cpu, cpu_online_map)) |
@@ -1156,10 +1369,12 @@ void __init smp_cpus_done(unsigned int max_cpus) | |||
1156 | setup_ioapic_dest(); | 1369 | setup_ioapic_dest(); |
1157 | #endif | 1370 | #endif |
1158 | zap_low_mappings(); | 1371 | zap_low_mappings(); |
1372 | #ifndef CONFIG_HOTPLUG_CPU | ||
1159 | /* | 1373 | /* |
1160 | * Disable executability of the SMP trampoline: | 1374 | * Disable executability of the SMP trampoline: |
1161 | */ | 1375 | */ |
1162 | set_kernel_exec((unsigned long)trampoline_base, trampoline_exec); | 1376 | set_kernel_exec((unsigned long)trampoline_base, trampoline_exec); |
1377 | #endif | ||
1163 | } | 1378 | } |
1164 | 1379 | ||
1165 | void __init smp_intr_init(void) | 1380 | void __init smp_intr_init(void) |
diff --git a/arch/i386/kernel/syscall_table.S b/arch/i386/kernel/syscall_table.S index d408afaf6495..442a6e937b19 100644 --- a/arch/i386/kernel/syscall_table.S +++ b/arch/i386/kernel/syscall_table.S | |||
@@ -283,7 +283,7 @@ ENTRY(sys_call_table) | |||
283 | .long sys_mq_timedreceive /* 280 */ | 283 | .long sys_mq_timedreceive /* 280 */ |
284 | .long sys_mq_notify | 284 | .long sys_mq_notify |
285 | .long sys_mq_getsetattr | 285 | .long sys_mq_getsetattr |
286 | .long sys_ni_syscall /* reserved for kexec */ | 286 | .long sys_kexec_load |
287 | .long sys_waitid | 287 | .long sys_waitid |
288 | .long sys_ni_syscall /* 285 */ /* available */ | 288 | .long sys_ni_syscall /* 285 */ /* available */ |
289 | .long sys_add_key | 289 | .long sys_add_key |
diff --git a/arch/i386/kernel/sysenter.c b/arch/i386/kernel/sysenter.c index 960d8bd137d0..0bada1870bdf 100644 --- a/arch/i386/kernel/sysenter.c +++ b/arch/i386/kernel/sysenter.c | |||
@@ -21,11 +21,16 @@ | |||
21 | 21 | ||
22 | extern asmlinkage void sysenter_entry(void); | 22 | extern asmlinkage void sysenter_entry(void); |
23 | 23 | ||
24 | void enable_sep_cpu(void *info) | 24 | void enable_sep_cpu(void) |
25 | { | 25 | { |
26 | int cpu = get_cpu(); | 26 | int cpu = get_cpu(); |
27 | struct tss_struct *tss = &per_cpu(init_tss, cpu); | 27 | struct tss_struct *tss = &per_cpu(init_tss, cpu); |
28 | 28 | ||
29 | if (!boot_cpu_has(X86_FEATURE_SEP)) { | ||
30 | put_cpu(); | ||
31 | return; | ||
32 | } | ||
33 | |||
29 | tss->ss1 = __KERNEL_CS; | 34 | tss->ss1 = __KERNEL_CS; |
30 | tss->esp1 = sizeof(struct tss_struct) + (unsigned long) tss; | 35 | tss->esp1 = sizeof(struct tss_struct) + (unsigned long) tss; |
31 | wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0); | 36 | wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0); |
@@ -41,7 +46,7 @@ void enable_sep_cpu(void *info) | |||
41 | extern const char vsyscall_int80_start, vsyscall_int80_end; | 46 | extern const char vsyscall_int80_start, vsyscall_int80_end; |
42 | extern const char vsyscall_sysenter_start, vsyscall_sysenter_end; | 47 | extern const char vsyscall_sysenter_start, vsyscall_sysenter_end; |
43 | 48 | ||
44 | static int __init sysenter_setup(void) | 49 | int __init sysenter_setup(void) |
45 | { | 50 | { |
46 | void *page = (void *)get_zeroed_page(GFP_ATOMIC); | 51 | void *page = (void *)get_zeroed_page(GFP_ATOMIC); |
47 | 52 | ||
@@ -58,8 +63,5 @@ static int __init sysenter_setup(void) | |||
58 | &vsyscall_sysenter_start, | 63 | &vsyscall_sysenter_start, |
59 | &vsyscall_sysenter_end - &vsyscall_sysenter_start); | 64 | &vsyscall_sysenter_end - &vsyscall_sysenter_start); |
60 | 65 | ||
61 | on_each_cpu(enable_sep_cpu, NULL, 1, 1); | ||
62 | return 0; | 66 | return 0; |
63 | } | 67 | } |
64 | |||
65 | __initcall(sysenter_setup); | ||
diff --git a/arch/i386/kernel/time_hpet.c b/arch/i386/kernel/time_hpet.c index 10a0cbb88e75..658c0629ba6a 100644 --- a/arch/i386/kernel/time_hpet.c +++ b/arch/i386/kernel/time_hpet.c | |||
@@ -50,7 +50,7 @@ static void hpet_writel(unsigned long d, unsigned long a) | |||
50 | * comparator value and continue. Next tick can be caught by checking | 50 | * comparator value and continue. Next tick can be caught by checking |
51 | * for a change in the comparator value. Used in apic.c. | 51 | * for a change in the comparator value. Used in apic.c. |
52 | */ | 52 | */ |
53 | static void __init wait_hpet_tick(void) | 53 | static void __devinit wait_hpet_tick(void) |
54 | { | 54 | { |
55 | unsigned int start_cmp_val, end_cmp_val; | 55 | unsigned int start_cmp_val, end_cmp_val; |
56 | 56 | ||
diff --git a/arch/i386/kernel/timers/common.c b/arch/i386/kernel/timers/common.c index 37353bd31803..8163fe0cf1f0 100644 --- a/arch/i386/kernel/timers/common.c +++ b/arch/i386/kernel/timers/common.c | |||
@@ -86,7 +86,7 @@ bad_ctc: | |||
86 | #define CALIBRATE_CNT_HPET (5 * hpet_tick) | 86 | #define CALIBRATE_CNT_HPET (5 * hpet_tick) |
87 | #define CALIBRATE_TIME_HPET (5 * KERNEL_TICK_USEC) | 87 | #define CALIBRATE_TIME_HPET (5 * KERNEL_TICK_USEC) |
88 | 88 | ||
89 | unsigned long __init calibrate_tsc_hpet(unsigned long *tsc_hpet_quotient_ptr) | 89 | unsigned long __devinit calibrate_tsc_hpet(unsigned long *tsc_hpet_quotient_ptr) |
90 | { | 90 | { |
91 | unsigned long tsc_startlow, tsc_starthigh; | 91 | unsigned long tsc_startlow, tsc_starthigh; |
92 | unsigned long tsc_endlow, tsc_endhigh; | 92 | unsigned long tsc_endlow, tsc_endhigh; |
diff --git a/arch/i386/kernel/timers/timer_tsc.c b/arch/i386/kernel/timers/timer_tsc.c index 54c36b182021..f46e625bab67 100644 --- a/arch/i386/kernel/timers/timer_tsc.c +++ b/arch/i386/kernel/timers/timer_tsc.c | |||
@@ -33,7 +33,7 @@ static struct timer_opts timer_tsc; | |||
33 | 33 | ||
34 | static inline void cpufreq_delayed_get(void); | 34 | static inline void cpufreq_delayed_get(void); |
35 | 35 | ||
36 | int tsc_disable __initdata = 0; | 36 | int tsc_disable __devinitdata = 0; |
37 | 37 | ||
38 | extern spinlock_t i8253_lock; | 38 | extern spinlock_t i8253_lock; |
39 | 39 | ||
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index e4d4e2162c7a..a61f33d06ea3 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/ptrace.h> | 27 | #include <linux/ptrace.h> |
28 | #include <linux/utsname.h> | 28 | #include <linux/utsname.h> |
29 | #include <linux/kprobes.h> | 29 | #include <linux/kprobes.h> |
30 | #include <linux/kexec.h> | ||
30 | 31 | ||
31 | #ifdef CONFIG_EISA | 32 | #ifdef CONFIG_EISA |
32 | #include <linux/ioport.h> | 33 | #include <linux/ioport.h> |
@@ -234,22 +235,22 @@ void show_registers(struct pt_regs *regs) | |||
234 | * time of the fault.. | 235 | * time of the fault.. |
235 | */ | 236 | */ |
236 | if (in_kernel) { | 237 | if (in_kernel) { |
237 | u8 *eip; | 238 | u8 __user *eip; |
238 | 239 | ||
239 | printk("\nStack: "); | 240 | printk("\nStack: "); |
240 | show_stack(NULL, (unsigned long*)esp); | 241 | show_stack(NULL, (unsigned long*)esp); |
241 | 242 | ||
242 | printk("Code: "); | 243 | printk("Code: "); |
243 | 244 | ||
244 | eip = (u8 *)regs->eip - 43; | 245 | eip = (u8 __user *)regs->eip - 43; |
245 | for (i = 0; i < 64; i++, eip++) { | 246 | for (i = 0; i < 64; i++, eip++) { |
246 | unsigned char c; | 247 | unsigned char c; |
247 | 248 | ||
248 | if (eip < (u8 *)PAGE_OFFSET || __get_user(c, eip)) { | 249 | if (eip < (u8 __user *)PAGE_OFFSET || __get_user(c, eip)) { |
249 | printk(" Bad EIP value."); | 250 | printk(" Bad EIP value."); |
250 | break; | 251 | break; |
251 | } | 252 | } |
252 | if (eip == (u8 *)regs->eip) | 253 | if (eip == (u8 __user *)regs->eip) |
253 | printk("<%02x> ", c); | 254 | printk("<%02x> ", c); |
254 | else | 255 | else |
255 | printk("%02x ", c); | 256 | printk("%02x ", c); |
@@ -273,13 +274,13 @@ static void handle_BUG(struct pt_regs *regs) | |||
273 | 274 | ||
274 | if (eip < PAGE_OFFSET) | 275 | if (eip < PAGE_OFFSET) |
275 | goto no_bug; | 276 | goto no_bug; |
276 | if (__get_user(ud2, (unsigned short *)eip)) | 277 | if (__get_user(ud2, (unsigned short __user *)eip)) |
277 | goto no_bug; | 278 | goto no_bug; |
278 | if (ud2 != 0x0b0f) | 279 | if (ud2 != 0x0b0f) |
279 | goto no_bug; | 280 | goto no_bug; |
280 | if (__get_user(line, (unsigned short *)(eip + 2))) | 281 | if (__get_user(line, (unsigned short __user *)(eip + 2))) |
281 | goto bug; | 282 | goto bug; |
282 | if (__get_user(file, (char **)(eip + 4)) || | 283 | if (__get_user(file, (char * __user *)(eip + 4)) || |
283 | (unsigned long)file < PAGE_OFFSET || __get_user(c, file)) | 284 | (unsigned long)file < PAGE_OFFSET || __get_user(c, file)) |
284 | file = "<bad filename>"; | 285 | file = "<bad filename>"; |
285 | 286 | ||
@@ -294,6 +295,9 @@ bug: | |||
294 | printk("Kernel BUG\n"); | 295 | printk("Kernel BUG\n"); |
295 | } | 296 | } |
296 | 297 | ||
298 | /* This is gone through when something in the kernel | ||
299 | * has done something bad and is about to be terminated. | ||
300 | */ | ||
297 | void die(const char * str, struct pt_regs * regs, long err) | 301 | void die(const char * str, struct pt_regs * regs, long err) |
298 | { | 302 | { |
299 | static struct { | 303 | static struct { |
@@ -341,6 +345,10 @@ void die(const char * str, struct pt_regs * regs, long err) | |||
341 | bust_spinlocks(0); | 345 | bust_spinlocks(0); |
342 | die.lock_owner = -1; | 346 | die.lock_owner = -1; |
343 | spin_unlock_irq(&die.lock); | 347 | spin_unlock_irq(&die.lock); |
348 | |||
349 | if (kexec_should_crash(current)) | ||
350 | crash_kexec(regs); | ||
351 | |||
344 | if (in_interrupt()) | 352 | if (in_interrupt()) |
345 | panic("Fatal exception in interrupt"); | 353 | panic("Fatal exception in interrupt"); |
346 | 354 | ||
@@ -361,6 +369,10 @@ static inline void die_if_kernel(const char * str, struct pt_regs * regs, long e | |||
361 | static void do_trap(int trapnr, int signr, char *str, int vm86, | 369 | static void do_trap(int trapnr, int signr, char *str, int vm86, |
362 | struct pt_regs * regs, long error_code, siginfo_t *info) | 370 | struct pt_regs * regs, long error_code, siginfo_t *info) |
363 | { | 371 | { |
372 | struct task_struct *tsk = current; | ||
373 | tsk->thread.error_code = error_code; | ||
374 | tsk->thread.trap_no = trapnr; | ||
375 | |||
364 | if (regs->eflags & VM_MASK) { | 376 | if (regs->eflags & VM_MASK) { |
365 | if (vm86) | 377 | if (vm86) |
366 | goto vm86_trap; | 378 | goto vm86_trap; |
@@ -371,9 +383,6 @@ static void do_trap(int trapnr, int signr, char *str, int vm86, | |||
371 | goto kernel_trap; | 383 | goto kernel_trap; |
372 | 384 | ||
373 | trap_signal: { | 385 | trap_signal: { |
374 | struct task_struct *tsk = current; | ||
375 | tsk->thread.error_code = error_code; | ||
376 | tsk->thread.trap_no = trapnr; | ||
377 | if (info) | 386 | if (info) |
378 | force_sig_info(signr, info, tsk); | 387 | force_sig_info(signr, info, tsk); |
379 | else | 388 | else |
@@ -486,6 +495,9 @@ fastcall void do_general_protection(struct pt_regs * regs, long error_code) | |||
486 | } | 495 | } |
487 | put_cpu(); | 496 | put_cpu(); |
488 | 497 | ||
498 | current->thread.error_code = error_code; | ||
499 | current->thread.trap_no = 13; | ||
500 | |||
489 | if (regs->eflags & VM_MASK) | 501 | if (regs->eflags & VM_MASK) |
490 | goto gp_in_vm86; | 502 | goto gp_in_vm86; |
491 | 503 | ||
@@ -570,6 +582,15 @@ void die_nmi (struct pt_regs *regs, const char *msg) | |||
570 | console_silent(); | 582 | console_silent(); |
571 | spin_unlock(&nmi_print_lock); | 583 | spin_unlock(&nmi_print_lock); |
572 | bust_spinlocks(0); | 584 | bust_spinlocks(0); |
585 | |||
586 | /* If we are in kernel we are probably nested up pretty bad | ||
587 | * and might aswell get out now while we still can. | ||
588 | */ | ||
589 | if (!user_mode(regs)) { | ||
590 | current->thread.trap_no = 2; | ||
591 | crash_kexec(regs); | ||
592 | } | ||
593 | |||
573 | do_exit(SIGSEGV); | 594 | do_exit(SIGSEGV); |
574 | } | 595 | } |
575 | 596 | ||
@@ -625,6 +646,14 @@ fastcall void do_nmi(struct pt_regs * regs, long error_code) | |||
625 | nmi_enter(); | 646 | nmi_enter(); |
626 | 647 | ||
627 | cpu = smp_processor_id(); | 648 | cpu = smp_processor_id(); |
649 | |||
650 | #ifdef CONFIG_HOTPLUG_CPU | ||
651 | if (!cpu_online(cpu)) { | ||
652 | nmi_exit(); | ||
653 | return; | ||
654 | } | ||
655 | #endif | ||
656 | |||
628 | ++nmi_count(cpu); | 657 | ++nmi_count(cpu); |
629 | 658 | ||
630 | if (!nmi_callback(regs, cpu)) | 659 | if (!nmi_callback(regs, cpu)) |
@@ -872,9 +901,9 @@ fastcall void do_simd_coprocessor_error(struct pt_regs * regs, | |||
872 | error_code); | 901 | error_code); |
873 | return; | 902 | return; |
874 | } | 903 | } |
875 | die_if_kernel("cache flush denied", regs, error_code); | ||
876 | current->thread.trap_no = 19; | 904 | current->thread.trap_no = 19; |
877 | current->thread.error_code = error_code; | 905 | current->thread.error_code = error_code; |
906 | die_if_kernel("cache flush denied", regs, error_code); | ||
878 | force_sig(SIGSEGV, current); | 907 | force_sig(SIGSEGV, current); |
879 | } | 908 | } |
880 | } | 909 | } |
diff --git a/arch/i386/kernel/vmlinux.lds.S b/arch/i386/kernel/vmlinux.lds.S index e0512cc8bea7..7e01a528a83a 100644 --- a/arch/i386/kernel/vmlinux.lds.S +++ b/arch/i386/kernel/vmlinux.lds.S | |||
@@ -2,20 +2,23 @@ | |||
2 | * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>; | 2 | * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>; |
3 | */ | 3 | */ |
4 | 4 | ||
5 | #define LOAD_OFFSET __PAGE_OFFSET | ||
6 | |||
5 | #include <asm-generic/vmlinux.lds.h> | 7 | #include <asm-generic/vmlinux.lds.h> |
6 | #include <asm/thread_info.h> | 8 | #include <asm/thread_info.h> |
7 | #include <asm/page.h> | 9 | #include <asm/page.h> |
8 | 10 | ||
9 | OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") | 11 | OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") |
10 | OUTPUT_ARCH(i386) | 12 | OUTPUT_ARCH(i386) |
11 | ENTRY(startup_32) | 13 | ENTRY(phys_startup_32) |
12 | jiffies = jiffies_64; | 14 | jiffies = jiffies_64; |
13 | SECTIONS | 15 | SECTIONS |
14 | { | 16 | { |
15 | . = __PAGE_OFFSET + 0x100000; | 17 | . = __KERNEL_START; |
18 | phys_startup_32 = startup_32 - LOAD_OFFSET; | ||
16 | /* read-only */ | 19 | /* read-only */ |
17 | _text = .; /* Text and read-only data */ | 20 | _text = .; /* Text and read-only data */ |
18 | .text : { | 21 | .text : AT(ADDR(.text) - LOAD_OFFSET) { |
19 | *(.text) | 22 | *(.text) |
20 | SCHED_TEXT | 23 | SCHED_TEXT |
21 | LOCK_TEXT | 24 | LOCK_TEXT |
@@ -27,49 +30,55 @@ SECTIONS | |||
27 | 30 | ||
28 | . = ALIGN(16); /* Exception table */ | 31 | . = ALIGN(16); /* Exception table */ |
29 | __start___ex_table = .; | 32 | __start___ex_table = .; |
30 | __ex_table : { *(__ex_table) } | 33 | __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { *(__ex_table) } |
31 | __stop___ex_table = .; | 34 | __stop___ex_table = .; |
32 | 35 | ||
33 | RODATA | 36 | RODATA |
34 | 37 | ||
35 | /* writeable */ | 38 | /* writeable */ |
36 | .data : { /* Data */ | 39 | .data : AT(ADDR(.data) - LOAD_OFFSET) { /* Data */ |
37 | *(.data) | 40 | *(.data) |
38 | CONSTRUCTORS | 41 | CONSTRUCTORS |
39 | } | 42 | } |
40 | 43 | ||
41 | . = ALIGN(4096); | 44 | . = ALIGN(4096); |
42 | __nosave_begin = .; | 45 | __nosave_begin = .; |
43 | .data_nosave : { *(.data.nosave) } | 46 | .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) { *(.data.nosave) } |
44 | . = ALIGN(4096); | 47 | . = ALIGN(4096); |
45 | __nosave_end = .; | 48 | __nosave_end = .; |
46 | 49 | ||
47 | . = ALIGN(4096); | 50 | . = ALIGN(4096); |
48 | .data.page_aligned : { *(.data.idt) } | 51 | .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) { |
52 | *(.data.idt) | ||
53 | } | ||
49 | 54 | ||
50 | . = ALIGN(32); | 55 | . = ALIGN(32); |
51 | .data.cacheline_aligned : { *(.data.cacheline_aligned) } | 56 | .data.cacheline_aligned : AT(ADDR(.data.cacheline_aligned) - LOAD_OFFSET) { |
57 | *(.data.cacheline_aligned) | ||
58 | } | ||
52 | 59 | ||
53 | _edata = .; /* End of data section */ | 60 | _edata = .; /* End of data section */ |
54 | 61 | ||
55 | . = ALIGN(THREAD_SIZE); /* init_task */ | 62 | . = ALIGN(THREAD_SIZE); /* init_task */ |
56 | .data.init_task : { *(.data.init_task) } | 63 | .data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) { |
64 | *(.data.init_task) | ||
65 | } | ||
57 | 66 | ||
58 | /* will be freed after init */ | 67 | /* will be freed after init */ |
59 | . = ALIGN(4096); /* Init code and data */ | 68 | . = ALIGN(4096); /* Init code and data */ |
60 | __init_begin = .; | 69 | __init_begin = .; |
61 | .init.text : { | 70 | .init.text : AT(ADDR(.init.text) - LOAD_OFFSET) { |
62 | _sinittext = .; | 71 | _sinittext = .; |
63 | *(.init.text) | 72 | *(.init.text) |
64 | _einittext = .; | 73 | _einittext = .; |
65 | } | 74 | } |
66 | .init.data : { *(.init.data) } | 75 | .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) { *(.init.data) } |
67 | . = ALIGN(16); | 76 | . = ALIGN(16); |
68 | __setup_start = .; | 77 | __setup_start = .; |
69 | .init.setup : { *(.init.setup) } | 78 | .init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET) { *(.init.setup) } |
70 | __setup_end = .; | 79 | __setup_end = .; |
71 | __initcall_start = .; | 80 | __initcall_start = .; |
72 | .initcall.init : { | 81 | .initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET) { |
73 | *(.initcall1.init) | 82 | *(.initcall1.init) |
74 | *(.initcall2.init) | 83 | *(.initcall2.init) |
75 | *(.initcall3.init) | 84 | *(.initcall3.init) |
@@ -80,33 +89,41 @@ SECTIONS | |||
80 | } | 89 | } |
81 | __initcall_end = .; | 90 | __initcall_end = .; |
82 | __con_initcall_start = .; | 91 | __con_initcall_start = .; |
83 | .con_initcall.init : { *(.con_initcall.init) } | 92 | .con_initcall.init : AT(ADDR(.con_initcall.init) - LOAD_OFFSET) { |
93 | *(.con_initcall.init) | ||
94 | } | ||
84 | __con_initcall_end = .; | 95 | __con_initcall_end = .; |
85 | SECURITY_INIT | 96 | SECURITY_INIT |
86 | . = ALIGN(4); | 97 | . = ALIGN(4); |
87 | __alt_instructions = .; | 98 | __alt_instructions = .; |
88 | .altinstructions : { *(.altinstructions) } | 99 | .altinstructions : AT(ADDR(.altinstructions) - LOAD_OFFSET) { |
100 | *(.altinstructions) | ||
101 | } | ||
89 | __alt_instructions_end = .; | 102 | __alt_instructions_end = .; |
90 | .altinstr_replacement : { *(.altinstr_replacement) } | 103 | .altinstr_replacement : AT(ADDR(.altinstr_replacement) - LOAD_OFFSET) { |
104 | *(.altinstr_replacement) | ||
105 | } | ||
91 | /* .exit.text is discard at runtime, not link time, to deal with references | 106 | /* .exit.text is discard at runtime, not link time, to deal with references |
92 | from .altinstructions and .eh_frame */ | 107 | from .altinstructions and .eh_frame */ |
93 | .exit.text : { *(.exit.text) } | 108 | .exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET) { *(.exit.text) } |
94 | .exit.data : { *(.exit.data) } | 109 | .exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) { *(.exit.data) } |
95 | . = ALIGN(4096); | 110 | . = ALIGN(4096); |
96 | __initramfs_start = .; | 111 | __initramfs_start = .; |
97 | .init.ramfs : { *(.init.ramfs) } | 112 | .init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) { *(.init.ramfs) } |
98 | __initramfs_end = .; | 113 | __initramfs_end = .; |
99 | . = ALIGN(32); | 114 | . = ALIGN(32); |
100 | __per_cpu_start = .; | 115 | __per_cpu_start = .; |
101 | .data.percpu : { *(.data.percpu) } | 116 | .data.percpu : AT(ADDR(.data.percpu) - LOAD_OFFSET) { *(.data.percpu) } |
102 | __per_cpu_end = .; | 117 | __per_cpu_end = .; |
103 | . = ALIGN(4096); | 118 | . = ALIGN(4096); |
104 | __init_end = .; | 119 | __init_end = .; |
105 | /* freed after init ends here */ | 120 | /* freed after init ends here */ |
106 | 121 | ||
107 | __bss_start = .; /* BSS */ | 122 | __bss_start = .; /* BSS */ |
108 | .bss : { | 123 | .bss.page_aligned : AT(ADDR(.bss.page_aligned) - LOAD_OFFSET) { |
109 | *(.bss.page_aligned) | 124 | *(.bss.page_aligned) |
125 | } | ||
126 | .bss : AT(ADDR(.bss) - LOAD_OFFSET) { | ||
110 | *(.bss) | 127 | *(.bss) |
111 | } | 128 | } |
112 | . = ALIGN(4); | 129 | . = ALIGN(4); |
diff --git a/arch/i386/mach-default/setup.c b/arch/i386/mach-default/setup.c index 0aa08eaa8932..e5a1a83d09ef 100644 --- a/arch/i386/mach-default/setup.c +++ b/arch/i386/mach-default/setup.c | |||
@@ -10,6 +10,14 @@ | |||
10 | #include <asm/acpi.h> | 10 | #include <asm/acpi.h> |
11 | #include <asm/arch_hooks.h> | 11 | #include <asm/arch_hooks.h> |
12 | 12 | ||
13 | #ifdef CONFIG_HOTPLUG_CPU | ||
14 | #define DEFAULT_SEND_IPI (1) | ||
15 | #else | ||
16 | #define DEFAULT_SEND_IPI (0) | ||
17 | #endif | ||
18 | |||
19 | int no_broadcast=DEFAULT_SEND_IPI; | ||
20 | |||
13 | /** | 21 | /** |
14 | * pre_intr_init_hook - initialisation prior to setting up interrupt vectors | 22 | * pre_intr_init_hook - initialisation prior to setting up interrupt vectors |
15 | * | 23 | * |
@@ -104,3 +112,22 @@ void __init mca_nmi_hook(void) | |||
104 | printk("NMI generated from unknown source!\n"); | 112 | printk("NMI generated from unknown source!\n"); |
105 | } | 113 | } |
106 | #endif | 114 | #endif |
115 | |||
116 | static __init int no_ipi_broadcast(char *str) | ||
117 | { | ||
118 | get_option(&str, &no_broadcast); | ||
119 | printk ("Using %s mode\n", no_broadcast ? "No IPI Broadcast" : | ||
120 | "IPI Broadcast"); | ||
121 | return 1; | ||
122 | } | ||
123 | |||
124 | __setup("no_ipi_broadcast", no_ipi_broadcast); | ||
125 | |||
126 | static int __init print_ipi_mode(void) | ||
127 | { | ||
128 | printk ("Using IPI %s mode\n", no_broadcast ? "No-Shortcut" : | ||
129 | "Shortcut"); | ||
130 | return 0; | ||
131 | } | ||
132 | |||
133 | late_initcall(print_ipi_mode); | ||
diff --git a/arch/i386/mach-default/topology.c b/arch/i386/mach-default/topology.c index 5b3e8817dae8..23395fff35d1 100644 --- a/arch/i386/mach-default/topology.c +++ b/arch/i386/mach-default/topology.c | |||
@@ -73,12 +73,11 @@ static int __init topology_init(void) | |||
73 | { | 73 | { |
74 | int i; | 74 | int i; |
75 | 75 | ||
76 | for (i = 0; i < MAX_NUMNODES; i++) { | 76 | for_each_online_node(i) |
77 | if (node_online(i)) | 77 | arch_register_node(i); |
78 | arch_register_node(i); | 78 | |
79 | } | 79 | for_each_cpu(i) |
80 | for (i = 0; i < NR_CPUS; i++) | 80 | arch_register_cpu(i); |
81 | if (cpu_possible(i)) arch_register_cpu(i); | ||
82 | return 0; | 81 | return 0; |
83 | } | 82 | } |
84 | 83 | ||
@@ -88,8 +87,8 @@ static int __init topology_init(void) | |||
88 | { | 87 | { |
89 | int i; | 88 | int i; |
90 | 89 | ||
91 | for (i = 0; i < NR_CPUS; i++) | 90 | for_each_cpu(i) |
92 | if (cpu_possible(i)) arch_register_cpu(i); | 91 | arch_register_cpu(i); |
93 | return 0; | 92 | return 0; |
94 | } | 93 | } |
95 | 94 | ||
diff --git a/arch/i386/mach-visws/mpparse.c b/arch/i386/mach-visws/mpparse.c index 5a22082147f4..5f3d7e6de37b 100644 --- a/arch/i386/mach-visws/mpparse.c +++ b/arch/i386/mach-visws/mpparse.c | |||
@@ -23,7 +23,6 @@ unsigned long mp_lapic_addr; | |||
23 | 23 | ||
24 | /* Processor that is doing the boot up */ | 24 | /* Processor that is doing the boot up */ |
25 | unsigned int boot_cpu_physical_apicid = -1U; | 25 | unsigned int boot_cpu_physical_apicid = -1U; |
26 | unsigned int boot_cpu_logical_apicid = -1U; | ||
27 | 26 | ||
28 | /* Bitmask of physically existing CPUs */ | 27 | /* Bitmask of physically existing CPUs */ |
29 | physid_mask_t phys_cpu_present_map; | 28 | physid_mask_t phys_cpu_present_map; |
@@ -52,10 +51,8 @@ static void __init MP_processor_info (struct mpc_config_processor *m) | |||
52 | (m->mpc_cpufeature & CPU_MODEL_MASK) >> 4, | 51 | (m->mpc_cpufeature & CPU_MODEL_MASK) >> 4, |
53 | m->mpc_apicver); | 52 | m->mpc_apicver); |
54 | 53 | ||
55 | if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) { | 54 | if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) |
56 | boot_cpu_physical_apicid = m->mpc_apicid; | 55 | boot_cpu_physical_apicid = m->mpc_apicid; |
57 | boot_cpu_logical_apicid = logical_apicid; | ||
58 | } | ||
59 | 56 | ||
60 | ver = m->mpc_apicver; | 57 | ver = m->mpc_apicver; |
61 | if ((ver >= 0x14 && m->mpc_apicid >= 0xff) || m->mpc_apicid >= 0xf) { | 58 | if ((ver >= 0x14 && m->mpc_apicid >= 0xff) || m->mpc_apicid >= 0xf) { |
diff --git a/arch/i386/mm/discontig.c b/arch/i386/mm/discontig.c index f429c871e845..b358f0702a44 100644 --- a/arch/i386/mm/discontig.c +++ b/arch/i386/mm/discontig.c | |||
@@ -30,6 +30,8 @@ | |||
30 | #include <linux/initrd.h> | 30 | #include <linux/initrd.h> |
31 | #include <linux/nodemask.h> | 31 | #include <linux/nodemask.h> |
32 | #include <linux/module.h> | 32 | #include <linux/module.h> |
33 | #include <linux/kexec.h> | ||
34 | |||
33 | #include <asm/e820.h> | 35 | #include <asm/e820.h> |
34 | #include <asm/setup.h> | 36 | #include <asm/setup.h> |
35 | #include <asm/mmzone.h> | 37 | #include <asm/mmzone.h> |
diff --git a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c index a509237c4815..8e90339d6eaa 100644 --- a/arch/i386/mm/fault.c +++ b/arch/i386/mm/fault.c | |||
@@ -146,7 +146,7 @@ static int __is_prefetch(struct pt_regs *regs, unsigned long addr) | |||
146 | 146 | ||
147 | if (instr > limit) | 147 | if (instr > limit) |
148 | break; | 148 | break; |
149 | if (__get_user(opcode, (unsigned char *) instr)) | 149 | if (__get_user(opcode, (unsigned char __user *) instr)) |
150 | break; | 150 | break; |
151 | 151 | ||
152 | instr_hi = opcode & 0xf0; | 152 | instr_hi = opcode & 0xf0; |
@@ -173,7 +173,7 @@ static int __is_prefetch(struct pt_regs *regs, unsigned long addr) | |||
173 | scan_more = 0; | 173 | scan_more = 0; |
174 | if (instr > limit) | 174 | if (instr > limit) |
175 | break; | 175 | break; |
176 | if (__get_user(opcode, (unsigned char *) instr)) | 176 | if (__get_user(opcode, (unsigned char __user *) instr)) |
177 | break; | 177 | break; |
178 | prefetch = (instr_lo == 0xF) && | 178 | prefetch = (instr_lo == 0xF) && |
179 | (opcode == 0x0D || opcode == 0x18); | 179 | (opcode == 0x0D || opcode == 0x18); |
@@ -463,6 +463,9 @@ no_context: | |||
463 | printk(KERN_ALERT "*pte = %08lx\n", page); | 463 | printk(KERN_ALERT "*pte = %08lx\n", page); |
464 | } | 464 | } |
465 | #endif | 465 | #endif |
466 | tsk->thread.cr2 = address; | ||
467 | tsk->thread.trap_no = 14; | ||
468 | tsk->thread.error_code = error_code; | ||
466 | die("Oops", regs, error_code); | 469 | die("Oops", regs, error_code); |
467 | bust_spinlocks(0); | 470 | bust_spinlocks(0); |
468 | do_exit(SIGKILL); | 471 | do_exit(SIGKILL); |
diff --git a/arch/i386/mm/highmem.c b/arch/i386/mm/highmem.c index 4b7aaf99d7ea..b6eb4dcb8777 100644 --- a/arch/i386/mm/highmem.c +++ b/arch/i386/mm/highmem.c | |||
@@ -75,6 +75,24 @@ void kunmap_atomic(void *kvaddr, enum km_type type) | |||
75 | preempt_check_resched(); | 75 | preempt_check_resched(); |
76 | } | 76 | } |
77 | 77 | ||
78 | /* This is the same as kmap_atomic() but can map memory that doesn't | ||
79 | * have a struct page associated with it. | ||
80 | */ | ||
81 | void *kmap_atomic_pfn(unsigned long pfn, enum km_type type) | ||
82 | { | ||
83 | enum fixed_addresses idx; | ||
84 | unsigned long vaddr; | ||
85 | |||
86 | inc_preempt_count(); | ||
87 | |||
88 | idx = type + KM_TYPE_NR*smp_processor_id(); | ||
89 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); | ||
90 | set_pte(kmap_pte-idx, pfn_pte(pfn, kmap_prot)); | ||
91 | __flush_tlb_one(vaddr); | ||
92 | |||
93 | return (void*) vaddr; | ||
94 | } | ||
95 | |||
78 | struct page *kmap_atomic_to_page(void *ptr) | 96 | struct page *kmap_atomic_to_page(void *ptr) |
79 | { | 97 | { |
80 | unsigned long idx, vaddr = (unsigned long)ptr; | 98 | unsigned long idx, vaddr = (unsigned long)ptr; |
diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c index 3672e2ef51ae..12216b52e28b 100644 --- a/arch/i386/mm/init.c +++ b/arch/i386/mm/init.c | |||
@@ -352,7 +352,7 @@ static void __init pagetable_init (void) | |||
352 | #endif | 352 | #endif |
353 | } | 353 | } |
354 | 354 | ||
355 | #if defined(CONFIG_PM_DISK) || defined(CONFIG_SOFTWARE_SUSPEND) | 355 | #ifdef CONFIG_SOFTWARE_SUSPEND |
356 | /* | 356 | /* |
357 | * Swap suspend & friends need this for resume because things like the intel-agp | 357 | * Swap suspend & friends need this for resume because things like the intel-agp |
358 | * driver might have split up a kernel 4MB mapping. | 358 | * driver might have split up a kernel 4MB mapping. |
diff --git a/arch/i386/mm/ioremap.c b/arch/i386/mm/ioremap.c index d393eefc7052..6b25afc933b6 100644 --- a/arch/i386/mm/ioremap.c +++ b/arch/i386/mm/ioremap.c | |||
@@ -243,7 +243,7 @@ void iounmap(volatile void __iomem *addr) | |||
243 | write_lock(&vmlist_lock); | 243 | write_lock(&vmlist_lock); |
244 | p = __remove_vm_area((void *) (PAGE_MASK & (unsigned long __force) addr)); | 244 | p = __remove_vm_area((void *) (PAGE_MASK & (unsigned long __force) addr)); |
245 | if (!p) { | 245 | if (!p) { |
246 | printk("iounmap: bad address %p\n", addr); | 246 | printk(KERN_WARNING "iounmap: bad address %p\n", addr); |
247 | goto out_unlock; | 247 | goto out_unlock; |
248 | } | 248 | } |
249 | 249 | ||
diff --git a/arch/i386/mm/pgtable.c b/arch/i386/mm/pgtable.c index 270c59f099a4..bd2f7afc7a2a 100644 --- a/arch/i386/mm/pgtable.c +++ b/arch/i386/mm/pgtable.c | |||
@@ -32,9 +32,9 @@ void show_mem(void) | |||
32 | unsigned long i; | 32 | unsigned long i; |
33 | struct page_state ps; | 33 | struct page_state ps; |
34 | 34 | ||
35 | printk("Mem-info:\n"); | 35 | printk(KERN_INFO "Mem-info:\n"); |
36 | show_free_areas(); | 36 | show_free_areas(); |
37 | printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10)); | 37 | printk(KERN_INFO "Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10)); |
38 | for_each_pgdat(pgdat) { | 38 | for_each_pgdat(pgdat) { |
39 | for (i = 0; i < pgdat->node_spanned_pages; ++i) { | 39 | for (i = 0; i < pgdat->node_spanned_pages; ++i) { |
40 | page = pgdat_page_nr(pgdat, i); | 40 | page = pgdat_page_nr(pgdat, i); |
@@ -49,18 +49,18 @@ void show_mem(void) | |||
49 | shared += page_count(page) - 1; | 49 | shared += page_count(page) - 1; |
50 | } | 50 | } |
51 | } | 51 | } |
52 | printk("%d pages of RAM\n", total); | 52 | printk(KERN_INFO "%d pages of RAM\n", total); |
53 | printk("%d pages of HIGHMEM\n",highmem); | 53 | printk(KERN_INFO "%d pages of HIGHMEM\n", highmem); |
54 | printk("%d reserved pages\n",reserved); | 54 | printk(KERN_INFO "%d reserved pages\n", reserved); |
55 | printk("%d pages shared\n",shared); | 55 | printk(KERN_INFO "%d pages shared\n", shared); |
56 | printk("%d pages swap cached\n",cached); | 56 | printk(KERN_INFO "%d pages swap cached\n", cached); |
57 | 57 | ||
58 | get_page_state(&ps); | 58 | get_page_state(&ps); |
59 | printk("%lu pages dirty\n", ps.nr_dirty); | 59 | printk(KERN_INFO "%lu pages dirty\n", ps.nr_dirty); |
60 | printk("%lu pages writeback\n", ps.nr_writeback); | 60 | printk(KERN_INFO "%lu pages writeback\n", ps.nr_writeback); |
61 | printk("%lu pages mapped\n", ps.nr_mapped); | 61 | printk(KERN_INFO "%lu pages mapped\n", ps.nr_mapped); |
62 | printk("%lu pages slab\n", ps.nr_slab); | 62 | printk(KERN_INFO "%lu pages slab\n", ps.nr_slab); |
63 | printk("%lu pages pagetables\n", ps.nr_page_table_pages); | 63 | printk(KERN_INFO "%lu pages pagetables\n", ps.nr_page_table_pages); |
64 | } | 64 | } |
65 | 65 | ||
66 | /* | 66 | /* |
@@ -113,16 +113,16 @@ void set_pmd_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags) | |||
113 | pmd_t *pmd; | 113 | pmd_t *pmd; |
114 | 114 | ||
115 | if (vaddr & (PMD_SIZE-1)) { /* vaddr is misaligned */ | 115 | if (vaddr & (PMD_SIZE-1)) { /* vaddr is misaligned */ |
116 | printk ("set_pmd_pfn: vaddr misaligned\n"); | 116 | printk(KERN_WARNING "set_pmd_pfn: vaddr misaligned\n"); |
117 | return; /* BUG(); */ | 117 | return; /* BUG(); */ |
118 | } | 118 | } |
119 | if (pfn & (PTRS_PER_PTE-1)) { /* pfn is misaligned */ | 119 | if (pfn & (PTRS_PER_PTE-1)) { /* pfn is misaligned */ |
120 | printk ("set_pmd_pfn: pfn misaligned\n"); | 120 | printk(KERN_WARNING "set_pmd_pfn: pfn misaligned\n"); |
121 | return; /* BUG(); */ | 121 | return; /* BUG(); */ |
122 | } | 122 | } |
123 | pgd = swapper_pg_dir + pgd_index(vaddr); | 123 | pgd = swapper_pg_dir + pgd_index(vaddr); |
124 | if (pgd_none(*pgd)) { | 124 | if (pgd_none(*pgd)) { |
125 | printk ("set_pmd_pfn: pgd_none\n"); | 125 | printk(KERN_WARNING "set_pmd_pfn: pgd_none\n"); |
126 | return; /* BUG(); */ | 126 | return; /* BUG(); */ |
127 | } | 127 | } |
128 | pud = pud_offset(pgd, vaddr); | 128 | pud = pud_offset(pgd, vaddr); |
diff --git a/arch/i386/power/cpu.c b/arch/i386/power/cpu.c index 6f521cf19a13..0e6b45b61251 100644 --- a/arch/i386/power/cpu.c +++ b/arch/i386/power/cpu.c | |||
@@ -22,9 +22,11 @@ | |||
22 | #include <linux/device.h> | 22 | #include <linux/device.h> |
23 | #include <linux/suspend.h> | 23 | #include <linux/suspend.h> |
24 | #include <linux/acpi.h> | 24 | #include <linux/acpi.h> |
25 | |||
25 | #include <asm/uaccess.h> | 26 | #include <asm/uaccess.h> |
26 | #include <asm/acpi.h> | 27 | #include <asm/acpi.h> |
27 | #include <asm/tlbflush.h> | 28 | #include <asm/tlbflush.h> |
29 | #include <asm/processor.h> | ||
28 | 30 | ||
29 | static struct saved_context saved_context; | 31 | static struct saved_context saved_context; |
30 | 32 | ||
@@ -33,8 +35,6 @@ unsigned long saved_context_esp, saved_context_ebp; | |||
33 | unsigned long saved_context_esi, saved_context_edi; | 35 | unsigned long saved_context_esi, saved_context_edi; |
34 | unsigned long saved_context_eflags; | 36 | unsigned long saved_context_eflags; |
35 | 37 | ||
36 | extern void enable_sep_cpu(void *); | ||
37 | |||
38 | void __save_processor_state(struct saved_context *ctxt) | 38 | void __save_processor_state(struct saved_context *ctxt) |
39 | { | 39 | { |
40 | kernel_fpu_begin(); | 40 | kernel_fpu_begin(); |
@@ -44,7 +44,6 @@ void __save_processor_state(struct saved_context *ctxt) | |||
44 | */ | 44 | */ |
45 | asm volatile ("sgdt %0" : "=m" (ctxt->gdt_limit)); | 45 | asm volatile ("sgdt %0" : "=m" (ctxt->gdt_limit)); |
46 | asm volatile ("sidt %0" : "=m" (ctxt->idt_limit)); | 46 | asm volatile ("sidt %0" : "=m" (ctxt->idt_limit)); |
47 | asm volatile ("sldt %0" : "=m" (ctxt->ldt)); | ||
48 | asm volatile ("str %0" : "=m" (ctxt->tr)); | 47 | asm volatile ("str %0" : "=m" (ctxt->tr)); |
49 | 48 | ||
50 | /* | 49 | /* |
@@ -107,7 +106,6 @@ static void fix_processor_context(void) | |||
107 | 106 | ||
108 | void __restore_processor_state(struct saved_context *ctxt) | 107 | void __restore_processor_state(struct saved_context *ctxt) |
109 | { | 108 | { |
110 | |||
111 | /* | 109 | /* |
112 | * control registers | 110 | * control registers |
113 | */ | 111 | */ |
@@ -117,6 +115,13 @@ void __restore_processor_state(struct saved_context *ctxt) | |||
117 | asm volatile ("movl %0, %%cr0" :: "r" (ctxt->cr0)); | 115 | asm volatile ("movl %0, %%cr0" :: "r" (ctxt->cr0)); |
118 | 116 | ||
119 | /* | 117 | /* |
118 | * now restore the descriptor tables to their proper values | ||
119 | * ltr is done i fix_processor_context(). | ||
120 | */ | ||
121 | asm volatile ("lgdt %0" :: "m" (ctxt->gdt_limit)); | ||
122 | asm volatile ("lidt %0" :: "m" (ctxt->idt_limit)); | ||
123 | |||
124 | /* | ||
120 | * segment registers | 125 | * segment registers |
121 | */ | 126 | */ |
122 | asm volatile ("movw %0, %%es" :: "r" (ctxt->es)); | 127 | asm volatile ("movw %0, %%es" :: "r" (ctxt->es)); |
@@ -125,18 +130,10 @@ void __restore_processor_state(struct saved_context *ctxt) | |||
125 | asm volatile ("movw %0, %%ss" :: "r" (ctxt->ss)); | 130 | asm volatile ("movw %0, %%ss" :: "r" (ctxt->ss)); |
126 | 131 | ||
127 | /* | 132 | /* |
128 | * now restore the descriptor tables to their proper values | ||
129 | * ltr is done i fix_processor_context(). | ||
130 | */ | ||
131 | asm volatile ("lgdt %0" :: "m" (ctxt->gdt_limit)); | ||
132 | asm volatile ("lidt %0" :: "m" (ctxt->idt_limit)); | ||
133 | asm volatile ("lldt %0" :: "m" (ctxt->ldt)); | ||
134 | |||
135 | /* | ||
136 | * sysenter MSRs | 133 | * sysenter MSRs |
137 | */ | 134 | */ |
138 | if (boot_cpu_has(X86_FEATURE_SEP)) | 135 | if (boot_cpu_has(X86_FEATURE_SEP)) |
139 | enable_sep_cpu(NULL); | 136 | enable_sep_cpu(); |
140 | 137 | ||
141 | fix_processor_context(); | 138 | fix_processor_context(); |
142 | do_fpu_end(); | 139 | do_fpu_end(); |