diff options
Diffstat (limited to 'arch')
28 files changed, 1408 insertions, 269 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index b0a638b4199a..1a3150570785 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -933,6 +933,12 @@ config X86_CPUID | |||
933 | with major 203 and minors 0 to 31 for /dev/cpu/0/cpuid to | 933 | with major 203 and minors 0 to 31 for /dev/cpu/0/cpuid to |
934 | /dev/cpu/31/cpuid. | 934 | /dev/cpu/31/cpuid. |
935 | 935 | ||
936 | config X86_CPU_DEBUG | ||
937 | tristate "/sys/kernel/debug/x86/cpu/* - CPU Debug support" | ||
938 | ---help--- | ||
939 | If you select this option, this will provide various x86 CPUs | ||
940 | information through debugfs. | ||
941 | |||
936 | choice | 942 | choice |
937 | prompt "High Memory Support" | 943 | prompt "High Memory Support" |
938 | default HIGHMEM4G if !X86_NUMAQ | 944 | default HIGHMEM4G if !X86_NUMAQ |
@@ -1433,7 +1439,7 @@ config CRASH_DUMP | |||
1433 | config KEXEC_JUMP | 1439 | config KEXEC_JUMP |
1434 | bool "kexec jump (EXPERIMENTAL)" | 1440 | bool "kexec jump (EXPERIMENTAL)" |
1435 | depends on EXPERIMENTAL | 1441 | depends on EXPERIMENTAL |
1436 | depends on KEXEC && HIBERNATION && X86_32 | 1442 | depends on KEXEC && HIBERNATION |
1437 | ---help--- | 1443 | ---help--- |
1438 | Jump between original kernel and kexeced kernel and invoke | 1444 | Jump between original kernel and kexeced kernel and invoke |
1439 | code in physical address mode via KEXEC | 1445 | code in physical address mode via KEXEC |
diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile index c70eff69a1fb..57a29fecf6bb 100644 --- a/arch/x86/boot/Makefile +++ b/arch/x86/boot/Makefile | |||
@@ -6,26 +6,23 @@ | |||
6 | # for more details. | 6 | # for more details. |
7 | # | 7 | # |
8 | # Copyright (C) 1994 by Linus Torvalds | 8 | # Copyright (C) 1994 by Linus Torvalds |
9 | # Changed by many, many contributors over the years. | ||
9 | # | 10 | # |
10 | 11 | ||
11 | # ROOT_DEV specifies the default root-device when making the image. | 12 | # ROOT_DEV specifies the default root-device when making the image. |
12 | # This can be either FLOPPY, CURRENT, /dev/xxxx or empty, in which case | 13 | # This can be either FLOPPY, CURRENT, /dev/xxxx or empty, in which case |
13 | # the default of FLOPPY is used by 'build'. | 14 | # the default of FLOPPY is used by 'build'. |
14 | 15 | ||
15 | ROOT_DEV := CURRENT | 16 | ROOT_DEV := CURRENT |
16 | 17 | ||
17 | # If you want to preset the SVGA mode, uncomment the next line and | 18 | # If you want to preset the SVGA mode, uncomment the next line and |
18 | # set SVGA_MODE to whatever number you want. | 19 | # set SVGA_MODE to whatever number you want. |
19 | # Set it to -DSVGA_MODE=NORMAL_VGA if you just want the EGA/VGA mode. | 20 | # Set it to -DSVGA_MODE=NORMAL_VGA if you just want the EGA/VGA mode. |
20 | # The number is the same as you would ordinarily press at bootup. | 21 | # The number is the same as you would ordinarily press at bootup. |
21 | 22 | ||
22 | SVGA_MODE := -DSVGA_MODE=NORMAL_VGA | 23 | SVGA_MODE := -DSVGA_MODE=NORMAL_VGA |
23 | 24 | ||
24 | # If you want the RAM disk device, define this to be the size in blocks. | 25 | targets := vmlinux.bin setup.bin setup.elf bzImage |
25 | |||
26 | #RAMDISK := -DRAMDISK=512 | ||
27 | |||
28 | targets := vmlinux.bin setup.bin setup.elf zImage bzImage | ||
29 | subdir- := compressed | 26 | subdir- := compressed |
30 | 27 | ||
31 | setup-y += a20.o cmdline.o copy.o cpu.o cpucheck.o edd.o | 28 | setup-y += a20.o cmdline.o copy.o cpu.o cpucheck.o edd.o |
@@ -71,17 +68,13 @@ KBUILD_CFLAGS := $(LINUXINCLUDE) -g -Os -D_SETUP -D__KERNEL__ \ | |||
71 | KBUILD_CFLAGS += $(call cc-option,-m32) | 68 | KBUILD_CFLAGS += $(call cc-option,-m32) |
72 | KBUILD_AFLAGS := $(KBUILD_CFLAGS) -D__ASSEMBLY__ | 69 | KBUILD_AFLAGS := $(KBUILD_CFLAGS) -D__ASSEMBLY__ |
73 | 70 | ||
74 | $(obj)/zImage: asflags-y := $(SVGA_MODE) $(RAMDISK) | 71 | $(obj)/bzImage: asflags-y := $(SVGA_MODE) |
75 | $(obj)/bzImage: ccflags-y := -D__BIG_KERNEL__ | ||
76 | $(obj)/bzImage: asflags-y := $(SVGA_MODE) $(RAMDISK) -D__BIG_KERNEL__ | ||
77 | $(obj)/bzImage: BUILDFLAGS := -b | ||
78 | 72 | ||
79 | quiet_cmd_image = BUILD $@ | 73 | quiet_cmd_image = BUILD $@ |
80 | cmd_image = $(obj)/tools/build $(BUILDFLAGS) $(obj)/setup.bin \ | 74 | cmd_image = $(obj)/tools/build $(obj)/setup.bin $(obj)/vmlinux.bin \ |
81 | $(obj)/vmlinux.bin $(ROOT_DEV) > $@ | 75 | $(ROOT_DEV) > $@ |
82 | 76 | ||
83 | $(obj)/zImage $(obj)/bzImage: $(obj)/setup.bin \ | 77 | $(obj)/bzImage: $(obj)/setup.bin $(obj)/vmlinux.bin $(obj)/tools/build FORCE |
84 | $(obj)/vmlinux.bin $(obj)/tools/build FORCE | ||
85 | $(call if_changed,image) | 78 | $(call if_changed,image) |
86 | @echo 'Kernel: $@ is ready' ' (#'`cat .version`')' | 79 | @echo 'Kernel: $@ is ready' ' (#'`cat .version`')' |
87 | 80 | ||
diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S index 7ccff4884a23..5d84d1c74e4c 100644 --- a/arch/x86/boot/header.S +++ b/arch/x86/boot/header.S | |||
@@ -24,12 +24,8 @@ | |||
24 | #include "boot.h" | 24 | #include "boot.h" |
25 | #include "offsets.h" | 25 | #include "offsets.h" |
26 | 26 | ||
27 | SETUPSECTS = 4 /* default nr of setup-sectors */ | ||
28 | BOOTSEG = 0x07C0 /* original address of boot-sector */ | 27 | BOOTSEG = 0x07C0 /* original address of boot-sector */ |
29 | SYSSEG = DEF_SYSSEG /* system loaded at 0x10000 (65536) */ | 28 | SYSSEG = 0x1000 /* historical load address >> 4 */ |
30 | SYSSIZE = DEF_SYSSIZE /* system size: # of 16-byte clicks */ | ||
31 | /* to be loaded */ | ||
32 | ROOT_DEV = 0 /* ROOT_DEV is now written by "build" */ | ||
33 | 29 | ||
34 | #ifndef SVGA_MODE | 30 | #ifndef SVGA_MODE |
35 | #define SVGA_MODE ASK_VGA | 31 | #define SVGA_MODE ASK_VGA |
@@ -97,12 +93,12 @@ bugger_off_msg: | |||
97 | .section ".header", "a" | 93 | .section ".header", "a" |
98 | .globl hdr | 94 | .globl hdr |
99 | hdr: | 95 | hdr: |
100 | setup_sects: .byte SETUPSECTS | 96 | setup_sects: .byte 0 /* Filled in by build.c */ |
101 | root_flags: .word ROOT_RDONLY | 97 | root_flags: .word ROOT_RDONLY |
102 | syssize: .long SYSSIZE | 98 | syssize: .long 0 /* Filled in by build.c */ |
103 | ram_size: .word RAMDISK | 99 | ram_size: .word 0 /* Obsolete */ |
104 | vid_mode: .word SVGA_MODE | 100 | vid_mode: .word SVGA_MODE |
105 | root_dev: .word ROOT_DEV | 101 | root_dev: .word 0 /* Filled in by build.c */ |
106 | boot_flag: .word 0xAA55 | 102 | boot_flag: .word 0xAA55 |
107 | 103 | ||
108 | # offset 512, entry point | 104 | # offset 512, entry point |
@@ -123,14 +119,15 @@ _start: | |||
123 | # or else old loadlin-1.5 will fail) | 119 | # or else old loadlin-1.5 will fail) |
124 | .globl realmode_swtch | 120 | .globl realmode_swtch |
125 | realmode_swtch: .word 0, 0 # default_switch, SETUPSEG | 121 | realmode_swtch: .word 0, 0 # default_switch, SETUPSEG |
126 | start_sys_seg: .word SYSSEG | 122 | start_sys_seg: .word SYSSEG # obsolete and meaningless, but just |
123 | # in case something decided to "use" it | ||
127 | .word kernel_version-512 # pointing to kernel version string | 124 | .word kernel_version-512 # pointing to kernel version string |
128 | # above section of header is compatible | 125 | # above section of header is compatible |
129 | # with loadlin-1.5 (header v1.5). Don't | 126 | # with loadlin-1.5 (header v1.5). Don't |
130 | # change it. | 127 | # change it. |
131 | 128 | ||
132 | type_of_loader: .byte 0 # = 0, old one (LILO, Loadlin, | 129 | type_of_loader: .byte 0 # 0 means ancient bootloader, newer |
133 | # Bootlin, SYSLX, bootsect...) | 130 | # bootloaders know to change this. |
134 | # See Documentation/i386/boot.txt for | 131 | # See Documentation/i386/boot.txt for |
135 | # assigned ids | 132 | # assigned ids |
136 | 133 | ||
@@ -142,11 +139,7 @@ CAN_USE_HEAP = 0x80 # If set, the loader also has set | |||
142 | # space behind setup.S can be used for | 139 | # space behind setup.S can be used for |
143 | # heap purposes. | 140 | # heap purposes. |
144 | # Only the loader knows what is free | 141 | # Only the loader knows what is free |
145 | #ifndef __BIG_KERNEL__ | ||
146 | .byte 0 | ||
147 | #else | ||
148 | .byte LOADED_HIGH | 142 | .byte LOADED_HIGH |
149 | #endif | ||
150 | 143 | ||
151 | setup_move_size: .word 0x8000 # size to move, when setup is not | 144 | setup_move_size: .word 0x8000 # size to move, when setup is not |
152 | # loaded at 0x90000. We will move setup | 145 | # loaded at 0x90000. We will move setup |
@@ -157,11 +150,7 @@ setup_move_size: .word 0x8000 # size to move, when setup is not | |||
157 | 150 | ||
158 | code32_start: # here loaders can put a different | 151 | code32_start: # here loaders can put a different |
159 | # start address for 32-bit code. | 152 | # start address for 32-bit code. |
160 | #ifndef __BIG_KERNEL__ | ||
161 | .long 0x1000 # 0x1000 = default for zImage | ||
162 | #else | ||
163 | .long 0x100000 # 0x100000 = default for big kernel | 153 | .long 0x100000 # 0x100000 = default for big kernel |
164 | #endif | ||
165 | 154 | ||
166 | ramdisk_image: .long 0 # address of loaded ramdisk image | 155 | ramdisk_image: .long 0 # address of loaded ramdisk image |
167 | # Here the loader puts the 32-bit | 156 | # Here the loader puts the 32-bit |
diff --git a/arch/x86/boot/pm.c b/arch/x86/boot/pm.c index 85a1cd8a8ff8..8062f8915250 100644 --- a/arch/x86/boot/pm.c +++ b/arch/x86/boot/pm.c | |||
@@ -33,47 +33,6 @@ static void realmode_switch_hook(void) | |||
33 | } | 33 | } |
34 | 34 | ||
35 | /* | 35 | /* |
36 | * A zImage kernel is loaded at 0x10000 but wants to run at 0x1000. | ||
37 | * A bzImage kernel is loaded and runs at 0x100000. | ||
38 | */ | ||
39 | static void move_kernel_around(void) | ||
40 | { | ||
41 | /* Note: rely on the compile-time option here rather than | ||
42 | the LOADED_HIGH flag. The Qemu kernel loader unconditionally | ||
43 | sets the loadflags to zero. */ | ||
44 | #ifndef __BIG_KERNEL__ | ||
45 | u16 dst_seg, src_seg; | ||
46 | u32 syssize; | ||
47 | |||
48 | dst_seg = 0x1000 >> 4; | ||
49 | src_seg = 0x10000 >> 4; | ||
50 | syssize = boot_params.hdr.syssize; /* Size in 16-byte paragraphs */ | ||
51 | |||
52 | while (syssize) { | ||
53 | int paras = (syssize >= 0x1000) ? 0x1000 : syssize; | ||
54 | int dwords = paras << 2; | ||
55 | |||
56 | asm volatile("pushw %%es ; " | ||
57 | "pushw %%ds ; " | ||
58 | "movw %1,%%es ; " | ||
59 | "movw %2,%%ds ; " | ||
60 | "xorw %%di,%%di ; " | ||
61 | "xorw %%si,%%si ; " | ||
62 | "rep;movsl ; " | ||
63 | "popw %%ds ; " | ||
64 | "popw %%es" | ||
65 | : "+c" (dwords) | ||
66 | : "r" (dst_seg), "r" (src_seg) | ||
67 | : "esi", "edi"); | ||
68 | |||
69 | syssize -= paras; | ||
70 | dst_seg += paras; | ||
71 | src_seg += paras; | ||
72 | } | ||
73 | #endif | ||
74 | } | ||
75 | |||
76 | /* | ||
77 | * Disable all interrupts at the legacy PIC. | 36 | * Disable all interrupts at the legacy PIC. |
78 | */ | 37 | */ |
79 | static void mask_all_interrupts(void) | 38 | static void mask_all_interrupts(void) |
@@ -147,9 +106,6 @@ void go_to_protected_mode(void) | |||
147 | /* Hook before leaving real mode, also disables interrupts */ | 106 | /* Hook before leaving real mode, also disables interrupts */ |
148 | realmode_switch_hook(); | 107 | realmode_switch_hook(); |
149 | 108 | ||
150 | /* Move the kernel/setup to their final resting places */ | ||
151 | move_kernel_around(); | ||
152 | |||
153 | /* Enable the A20 gate */ | 109 | /* Enable the A20 gate */ |
154 | if (enable_a20()) { | 110 | if (enable_a20()) { |
155 | puts("A20 gate not responding, unable to boot...\n"); | 111 | puts("A20 gate not responding, unable to boot...\n"); |
diff --git a/arch/x86/boot/tools/build.c b/arch/x86/boot/tools/build.c index 44dc1923c0e3..ee3a4ea923ac 100644 --- a/arch/x86/boot/tools/build.c +++ b/arch/x86/boot/tools/build.c | |||
@@ -130,7 +130,7 @@ static void die(const char * str, ...) | |||
130 | 130 | ||
131 | static void usage(void) | 131 | static void usage(void) |
132 | { | 132 | { |
133 | die("Usage: build [-b] setup system [rootdev] [> image]"); | 133 | die("Usage: build setup system [rootdev] [> image]"); |
134 | } | 134 | } |
135 | 135 | ||
136 | int main(int argc, char ** argv) | 136 | int main(int argc, char ** argv) |
@@ -145,11 +145,6 @@ int main(int argc, char ** argv) | |||
145 | void *kernel; | 145 | void *kernel; |
146 | u32 crc = 0xffffffffUL; | 146 | u32 crc = 0xffffffffUL; |
147 | 147 | ||
148 | if (argc > 2 && !strcmp(argv[1], "-b")) | ||
149 | { | ||
150 | is_big_kernel = 1; | ||
151 | argc--, argv++; | ||
152 | } | ||
153 | if ((argc < 3) || (argc > 4)) | 148 | if ((argc < 3) || (argc > 4)) |
154 | usage(); | 149 | usage(); |
155 | if (argc > 3) { | 150 | if (argc > 3) { |
@@ -216,8 +211,6 @@ int main(int argc, char ** argv) | |||
216 | die("Unable to mmap '%s': %m", argv[2]); | 211 | die("Unable to mmap '%s': %m", argv[2]); |
217 | /* Number of 16-byte paragraphs, including space for a 4-byte CRC */ | 212 | /* Number of 16-byte paragraphs, including space for a 4-byte CRC */ |
218 | sys_size = (sz + 15 + 4) / 16; | 213 | sys_size = (sz + 15 + 4) / 16; |
219 | if (!is_big_kernel && sys_size > DEF_SYSSIZE) | ||
220 | die("System is too big. Try using bzImage or modules."); | ||
221 | 214 | ||
222 | /* Patch the setup code with the appropriate size parameters */ | 215 | /* Patch the setup code with the appropriate size parameters */ |
223 | buf[0x1f1] = setup_sectors-1; | 216 | buf[0x1f1] = setup_sectors-1; |
diff --git a/arch/x86/include/asm/boot.h b/arch/x86/include/asm/boot.h index 6526cf08b0e4..6ba23dd9fc92 100644 --- a/arch/x86/include/asm/boot.h +++ b/arch/x86/include/asm/boot.h | |||
@@ -1,10 +1,6 @@ | |||
1 | #ifndef _ASM_X86_BOOT_H | 1 | #ifndef _ASM_X86_BOOT_H |
2 | #define _ASM_X86_BOOT_H | 2 | #define _ASM_X86_BOOT_H |
3 | 3 | ||
4 | /* Don't touch these, unless you really know what you're doing. */ | ||
5 | #define DEF_SYSSEG 0x1000 | ||
6 | #define DEF_SYSSIZE 0x7F00 | ||
7 | |||
8 | /* Internal svga startup constants */ | 4 | /* Internal svga startup constants */ |
9 | #define NORMAL_VGA 0xffff /* 80x25 mode */ | 5 | #define NORMAL_VGA 0xffff /* 80x25 mode */ |
10 | #define EXTENDED_VGA 0xfffe /* 80x50 mode */ | 6 | #define EXTENDED_VGA 0xfffe /* 80x50 mode */ |
diff --git a/arch/x86/include/asm/cpu_debug.h b/arch/x86/include/asm/cpu_debug.h new file mode 100755 index 000000000000..d24d64fcee04 --- /dev/null +++ b/arch/x86/include/asm/cpu_debug.h | |||
@@ -0,0 +1,193 @@ | |||
1 | #ifndef _ASM_X86_CPU_DEBUG_H | ||
2 | #define _ASM_X86_CPU_DEBUG_H | ||
3 | |||
4 | /* | ||
5 | * CPU x86 architecture debug | ||
6 | * | ||
7 | * Copyright(C) 2009 Jaswinder Singh Rajput | ||
8 | */ | ||
9 | |||
10 | /* Register flags */ | ||
11 | enum cpu_debug_bit { | ||
12 | /* Model Specific Registers (MSRs) */ | ||
13 | CPU_MC_BIT, /* Machine Check */ | ||
14 | CPU_MONITOR_BIT, /* Monitor */ | ||
15 | CPU_TIME_BIT, /* Time */ | ||
16 | CPU_PMC_BIT, /* Performance Monitor */ | ||
17 | CPU_PLATFORM_BIT, /* Platform */ | ||
18 | CPU_APIC_BIT, /* APIC */ | ||
19 | CPU_POWERON_BIT, /* Power-on */ | ||
20 | CPU_CONTROL_BIT, /* Control */ | ||
21 | CPU_FEATURES_BIT, /* Features control */ | ||
22 | CPU_LBRANCH_BIT, /* Last Branch */ | ||
23 | CPU_BIOS_BIT, /* BIOS */ | ||
24 | CPU_FREQ_BIT, /* Frequency */ | ||
25 | CPU_MTTR_BIT, /* MTRR */ | ||
26 | CPU_PERF_BIT, /* Performance */ | ||
27 | CPU_CACHE_BIT, /* Cache */ | ||
28 | CPU_SYSENTER_BIT, /* Sysenter */ | ||
29 | CPU_THERM_BIT, /* Thermal */ | ||
30 | CPU_MISC_BIT, /* Miscellaneous */ | ||
31 | CPU_DEBUG_BIT, /* Debug */ | ||
32 | CPU_PAT_BIT, /* PAT */ | ||
33 | CPU_VMX_BIT, /* VMX */ | ||
34 | CPU_CALL_BIT, /* System Call */ | ||
35 | CPU_BASE_BIT, /* BASE Address */ | ||
36 | CPU_SMM_BIT, /* System mgmt mode */ | ||
37 | CPU_SVM_BIT, /*Secure Virtual Machine*/ | ||
38 | CPU_OSVM_BIT, /* OS-Visible Workaround*/ | ||
39 | /* Standard Registers */ | ||
40 | CPU_TSS_BIT, /* Task Stack Segment */ | ||
41 | CPU_CR_BIT, /* Control Registers */ | ||
42 | CPU_DT_BIT, /* Descriptor Table */ | ||
43 | /* End of Registers flags */ | ||
44 | CPU_REG_ALL_BIT, /* Select all Registers */ | ||
45 | }; | ||
46 | |||
47 | #define CPU_REG_ALL (~0) /* Select all Registers */ | ||
48 | |||
49 | #define CPU_MC (1 << CPU_MC_BIT) | ||
50 | #define CPU_MONITOR (1 << CPU_MONITOR_BIT) | ||
51 | #define CPU_TIME (1 << CPU_TIME_BIT) | ||
52 | #define CPU_PMC (1 << CPU_PMC_BIT) | ||
53 | #define CPU_PLATFORM (1 << CPU_PLATFORM_BIT) | ||
54 | #define CPU_APIC (1 << CPU_APIC_BIT) | ||
55 | #define CPU_POWERON (1 << CPU_POWERON_BIT) | ||
56 | #define CPU_CONTROL (1 << CPU_CONTROL_BIT) | ||
57 | #define CPU_FEATURES (1 << CPU_FEATURES_BIT) | ||
58 | #define CPU_LBRANCH (1 << CPU_LBRANCH_BIT) | ||
59 | #define CPU_BIOS (1 << CPU_BIOS_BIT) | ||
60 | #define CPU_FREQ (1 << CPU_FREQ_BIT) | ||
61 | #define CPU_MTRR (1 << CPU_MTTR_BIT) | ||
62 | #define CPU_PERF (1 << CPU_PERF_BIT) | ||
63 | #define CPU_CACHE (1 << CPU_CACHE_BIT) | ||
64 | #define CPU_SYSENTER (1 << CPU_SYSENTER_BIT) | ||
65 | #define CPU_THERM (1 << CPU_THERM_BIT) | ||
66 | #define CPU_MISC (1 << CPU_MISC_BIT) | ||
67 | #define CPU_DEBUG (1 << CPU_DEBUG_BIT) | ||
68 | #define CPU_PAT (1 << CPU_PAT_BIT) | ||
69 | #define CPU_VMX (1 << CPU_VMX_BIT) | ||
70 | #define CPU_CALL (1 << CPU_CALL_BIT) | ||
71 | #define CPU_BASE (1 << CPU_BASE_BIT) | ||
72 | #define CPU_SMM (1 << CPU_SMM_BIT) | ||
73 | #define CPU_SVM (1 << CPU_SVM_BIT) | ||
74 | #define CPU_OSVM (1 << CPU_OSVM_BIT) | ||
75 | #define CPU_TSS (1 << CPU_TSS_BIT) | ||
76 | #define CPU_CR (1 << CPU_CR_BIT) | ||
77 | #define CPU_DT (1 << CPU_DT_BIT) | ||
78 | |||
79 | /* Register file flags */ | ||
80 | enum cpu_file_bit { | ||
81 | CPU_INDEX_BIT, /* index */ | ||
82 | CPU_VALUE_BIT, /* value */ | ||
83 | }; | ||
84 | |||
85 | #define CPU_FILE_VALUE (1 << CPU_VALUE_BIT) | ||
86 | |||
87 | /* | ||
88 | * DisplayFamily_DisplayModel Processor Families/Processor Number Series | ||
89 | * -------------------------- ------------------------------------------ | ||
90 | * 05_01, 05_02, 05_04 Pentium, Pentium with MMX | ||
91 | * | ||
92 | * 06_01 Pentium Pro | ||
93 | * 06_03, 06_05 Pentium II Xeon, Pentium II | ||
94 | * 06_07, 06_08, 06_0A, 06_0B Pentium III Xeon, Pentum III | ||
95 | * | ||
96 | * 06_09, 060D Pentium M | ||
97 | * | ||
98 | * 06_0E Core Duo, Core Solo | ||
99 | * | ||
100 | * 06_0F Xeon 3000, 3200, 5100, 5300, 7300 series, | ||
101 | * Core 2 Quad, Core 2 Extreme, Core 2 Duo, | ||
102 | * Pentium dual-core | ||
103 | * 06_17 Xeon 5200, 5400 series, Core 2 Quad Q9650 | ||
104 | * | ||
105 | * 06_1C Atom | ||
106 | * | ||
107 | * 0F_00, 0F_01, 0F_02 Xeon, Xeon MP, Pentium 4 | ||
108 | * 0F_03, 0F_04 Xeon, Xeon MP, Pentium 4, Pentium D | ||
109 | * | ||
110 | * 0F_06 Xeon 7100, 5000 Series, Xeon MP, | ||
111 | * Pentium 4, Pentium D | ||
112 | */ | ||
113 | |||
114 | /* Register processors bits */ | ||
115 | enum cpu_processor_bit { | ||
116 | CPU_NONE, | ||
117 | /* Intel */ | ||
118 | CPU_INTEL_PENTIUM_BIT, | ||
119 | CPU_INTEL_P6_BIT, | ||
120 | CPU_INTEL_PENTIUM_M_BIT, | ||
121 | CPU_INTEL_CORE_BIT, | ||
122 | CPU_INTEL_CORE2_BIT, | ||
123 | CPU_INTEL_ATOM_BIT, | ||
124 | CPU_INTEL_XEON_P4_BIT, | ||
125 | CPU_INTEL_XEON_MP_BIT, | ||
126 | }; | ||
127 | |||
128 | #define CPU_ALL (~0) /* Select all CPUs */ | ||
129 | |||
130 | #define CPU_INTEL_PENTIUM (1 << CPU_INTEL_PENTIUM_BIT) | ||
131 | #define CPU_INTEL_P6 (1 << CPU_INTEL_P6_BIT) | ||
132 | #define CPU_INTEL_PENTIUM_M (1 << CPU_INTEL_PENTIUM_M_BIT) | ||
133 | #define CPU_INTEL_CORE (1 << CPU_INTEL_CORE_BIT) | ||
134 | #define CPU_INTEL_CORE2 (1 << CPU_INTEL_CORE2_BIT) | ||
135 | #define CPU_INTEL_ATOM (1 << CPU_INTEL_ATOM_BIT) | ||
136 | #define CPU_INTEL_XEON_P4 (1 << CPU_INTEL_XEON_P4_BIT) | ||
137 | #define CPU_INTEL_XEON_MP (1 << CPU_INTEL_XEON_MP_BIT) | ||
138 | |||
139 | #define CPU_INTEL_PX (CPU_INTEL_P6 | CPU_INTEL_PENTIUM_M) | ||
140 | #define CPU_INTEL_COREX (CPU_INTEL_CORE | CPU_INTEL_CORE2) | ||
141 | #define CPU_INTEL_XEON (CPU_INTEL_XEON_P4 | CPU_INTEL_XEON_MP) | ||
142 | #define CPU_CO_AT (CPU_INTEL_CORE | CPU_INTEL_ATOM) | ||
143 | #define CPU_C2_AT (CPU_INTEL_CORE2 | CPU_INTEL_ATOM) | ||
144 | #define CPU_CX_AT (CPU_INTEL_COREX | CPU_INTEL_ATOM) | ||
145 | #define CPU_CX_XE (CPU_INTEL_COREX | CPU_INTEL_XEON) | ||
146 | #define CPU_P6_XE (CPU_INTEL_P6 | CPU_INTEL_XEON) | ||
147 | #define CPU_PM_CO_AT (CPU_INTEL_PENTIUM_M | CPU_CO_AT) | ||
148 | #define CPU_C2_AT_XE (CPU_C2_AT | CPU_INTEL_XEON) | ||
149 | #define CPU_CX_AT_XE (CPU_CX_AT | CPU_INTEL_XEON) | ||
150 | #define CPU_P6_CX_AT (CPU_INTEL_P6 | CPU_CX_AT) | ||
151 | #define CPU_P6_CX_XE (CPU_P6_XE | CPU_INTEL_COREX) | ||
152 | #define CPU_P6_CX_AT_XE (CPU_INTEL_P6 | CPU_CX_AT_XE) | ||
153 | #define CPU_PM_CX_AT_XE (CPU_INTEL_PENTIUM_M | CPU_CX_AT_XE) | ||
154 | #define CPU_PM_CX_AT (CPU_INTEL_PENTIUM_M | CPU_CX_AT) | ||
155 | #define CPU_PM_CX_XE (CPU_INTEL_PENTIUM_M | CPU_CX_XE) | ||
156 | #define CPU_PX_CX_AT (CPU_INTEL_PX | CPU_CX_AT) | ||
157 | #define CPU_PX_CX_AT_XE (CPU_INTEL_PX | CPU_CX_AT_XE) | ||
158 | |||
159 | /* Select all Intel CPUs*/ | ||
160 | #define CPU_INTEL_ALL (CPU_INTEL_PENTIUM | CPU_PX_CX_AT_XE) | ||
161 | |||
162 | #define MAX_CPU_FILES 512 | ||
163 | |||
164 | struct cpu_private { | ||
165 | unsigned cpu; | ||
166 | unsigned type; | ||
167 | unsigned reg; | ||
168 | unsigned file; | ||
169 | }; | ||
170 | |||
171 | struct cpu_debug_base { | ||
172 | char *name; /* Register name */ | ||
173 | unsigned flag; /* Register flag */ | ||
174 | }; | ||
175 | |||
176 | struct cpu_cpuX_base { | ||
177 | struct dentry *dentry; /* Register dentry */ | ||
178 | int init; /* Register index file */ | ||
179 | }; | ||
180 | |||
181 | struct cpu_file_base { | ||
182 | char *name; /* Register file name */ | ||
183 | unsigned flag; /* Register file flag */ | ||
184 | }; | ||
185 | |||
186 | struct cpu_debug_range { | ||
187 | unsigned min; /* Register range min */ | ||
188 | unsigned max; /* Register range max */ | ||
189 | unsigned flag; /* Supported flags */ | ||
190 | unsigned model; /* Supported models */ | ||
191 | }; | ||
192 | |||
193 | #endif /* _ASM_X86_CPU_DEBUG_H */ | ||
diff --git a/arch/x86/include/asm/desc.h b/arch/x86/include/asm/desc.h index dc27705f5443..5623c50d67b2 100644 --- a/arch/x86/include/asm/desc.h +++ b/arch/x86/include/asm/desc.h | |||
@@ -91,7 +91,6 @@ static inline int desc_empty(const void *ptr) | |||
91 | #define store_gdt(dtr) native_store_gdt(dtr) | 91 | #define store_gdt(dtr) native_store_gdt(dtr) |
92 | #define store_idt(dtr) native_store_idt(dtr) | 92 | #define store_idt(dtr) native_store_idt(dtr) |
93 | #define store_tr(tr) (tr = native_store_tr()) | 93 | #define store_tr(tr) (tr = native_store_tr()) |
94 | #define store_ldt(ldt) asm("sldt %0":"=m" (ldt)) | ||
95 | 94 | ||
96 | #define load_TLS(t, cpu) native_load_tls(t, cpu) | 95 | #define load_TLS(t, cpu) native_load_tls(t, cpu) |
97 | #define set_ldt native_set_ldt | 96 | #define set_ldt native_set_ldt |
@@ -112,6 +111,8 @@ static inline void paravirt_free_ldt(struct desc_struct *ldt, unsigned entries) | |||
112 | } | 111 | } |
113 | #endif /* CONFIG_PARAVIRT */ | 112 | #endif /* CONFIG_PARAVIRT */ |
114 | 113 | ||
114 | #define store_ldt(ldt) asm("sldt %0" : "=m"(ldt)) | ||
115 | |||
115 | static inline void native_write_idt_entry(gate_desc *idt, int entry, | 116 | static inline void native_write_idt_entry(gate_desc *idt, int entry, |
116 | const gate_desc *gate) | 117 | const gate_desc *gate) |
117 | { | 118 | { |
diff --git a/arch/x86/include/asm/highmem.h b/arch/x86/include/asm/highmem.h index bf9276bea660..014c2b85ae45 100644 --- a/arch/x86/include/asm/highmem.h +++ b/arch/x86/include/asm/highmem.h | |||
@@ -63,6 +63,7 @@ void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot); | |||
63 | void *kmap_atomic(struct page *page, enum km_type type); | 63 | void *kmap_atomic(struct page *page, enum km_type type); |
64 | void kunmap_atomic(void *kvaddr, enum km_type type); | 64 | void kunmap_atomic(void *kvaddr, enum km_type type); |
65 | void *kmap_atomic_pfn(unsigned long pfn, enum km_type type); | 65 | void *kmap_atomic_pfn(unsigned long pfn, enum km_type type); |
66 | void *kmap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot); | ||
66 | struct page *kmap_atomic_to_page(void *ptr); | 67 | struct page *kmap_atomic_to_page(void *ptr); |
67 | 68 | ||
68 | #ifndef CONFIG_PARAVIRT | 69 | #ifndef CONFIG_PARAVIRT |
diff --git a/arch/x86/include/asm/kexec.h b/arch/x86/include/asm/kexec.h index 0ceb6d19ed30..317ff1703d0b 100644 --- a/arch/x86/include/asm/kexec.h +++ b/arch/x86/include/asm/kexec.h | |||
@@ -9,13 +9,13 @@ | |||
9 | # define PAGES_NR 4 | 9 | # define PAGES_NR 4 |
10 | #else | 10 | #else |
11 | # define PA_CONTROL_PAGE 0 | 11 | # define PA_CONTROL_PAGE 0 |
12 | # define PA_TABLE_PAGE 1 | 12 | # define VA_CONTROL_PAGE 1 |
13 | # define PAGES_NR 2 | 13 | # define PA_TABLE_PAGE 2 |
14 | # define PA_SWAP_PAGE 3 | ||
15 | # define PAGES_NR 4 | ||
14 | #endif | 16 | #endif |
15 | 17 | ||
16 | #ifdef CONFIG_X86_32 | ||
17 | # define KEXEC_CONTROL_CODE_MAX_SIZE 2048 | 18 | # define KEXEC_CONTROL_CODE_MAX_SIZE 2048 |
18 | #endif | ||
19 | 19 | ||
20 | #ifndef __ASSEMBLY__ | 20 | #ifndef __ASSEMBLY__ |
21 | 21 | ||
@@ -136,10 +136,11 @@ relocate_kernel(unsigned long indirection_page, | |||
136 | unsigned int has_pae, | 136 | unsigned int has_pae, |
137 | unsigned int preserve_context); | 137 | unsigned int preserve_context); |
138 | #else | 138 | #else |
139 | NORET_TYPE void | 139 | unsigned long |
140 | relocate_kernel(unsigned long indirection_page, | 140 | relocate_kernel(unsigned long indirection_page, |
141 | unsigned long page_list, | 141 | unsigned long page_list, |
142 | unsigned long start_address) ATTRIB_NORET; | 142 | unsigned long start_address, |
143 | unsigned int preserve_context); | ||
143 | #endif | 144 | #endif |
144 | 145 | ||
145 | #define ARCH_HAS_KIMAGE_ARCH | 146 | #define ARCH_HAS_KIMAGE_ARCH |
diff --git a/arch/x86/include/asm/linkage.h b/arch/x86/include/asm/linkage.h index a0d70b46c27c..12d55e773eb6 100644 --- a/arch/x86/include/asm/linkage.h +++ b/arch/x86/include/asm/linkage.h | |||
@@ -1,6 +1,8 @@ | |||
1 | #ifndef _ASM_X86_LINKAGE_H | 1 | #ifndef _ASM_X86_LINKAGE_H |
2 | #define _ASM_X86_LINKAGE_H | 2 | #define _ASM_X86_LINKAGE_H |
3 | 3 | ||
4 | #include <linux/stringify.h> | ||
5 | |||
4 | #undef notrace | 6 | #undef notrace |
5 | #define notrace __attribute__((no_instrument_function)) | 7 | #define notrace __attribute__((no_instrument_function)) |
6 | 8 | ||
@@ -53,14 +55,9 @@ | |||
53 | .globl name; \ | 55 | .globl name; \ |
54 | name: | 56 | name: |
55 | 57 | ||
56 | #ifdef CONFIG_X86_64 | 58 | #if defined(CONFIG_X86_64) || defined(CONFIG_X86_ALIGNMENT_16) |
57 | #define __ALIGN .p2align 4,,15 | 59 | #define __ALIGN .p2align 4, 0x90 |
58 | #define __ALIGN_STR ".p2align 4,,15" | 60 | #define __ALIGN_STR __stringify(__ALIGN) |
59 | #endif | ||
60 | |||
61 | #ifdef CONFIG_X86_ALIGNMENT_16 | ||
62 | #define __ALIGN .align 16,0x90 | ||
63 | #define __ALIGN_STR ".align 16,0x90" | ||
64 | #endif | 61 | #endif |
65 | 62 | ||
66 | #endif /* __ASSEMBLY__ */ | 63 | #endif /* __ASSEMBLY__ */ |
diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile index 82db7f45e2de..d4356f8b7522 100644 --- a/arch/x86/kernel/cpu/Makefile +++ b/arch/x86/kernel/cpu/Makefile | |||
@@ -14,6 +14,8 @@ obj-y += vmware.o hypervisor.o | |||
14 | obj-$(CONFIG_X86_32) += bugs.o cmpxchg.o | 14 | obj-$(CONFIG_X86_32) += bugs.o cmpxchg.o |
15 | obj-$(CONFIG_X86_64) += bugs_64.o | 15 | obj-$(CONFIG_X86_64) += bugs_64.o |
16 | 16 | ||
17 | obj-$(CONFIG_X86_CPU_DEBUG) += cpu_debug.o | ||
18 | |||
17 | obj-$(CONFIG_CPU_SUP_INTEL) += intel.o | 19 | obj-$(CONFIG_CPU_SUP_INTEL) += intel.o |
18 | obj-$(CONFIG_CPU_SUP_AMD) += amd.o | 20 | obj-$(CONFIG_CPU_SUP_AMD) += amd.o |
19 | obj-$(CONFIG_CPU_SUP_CYRIX_32) += cyrix.o | 21 | obj-$(CONFIG_CPU_SUP_CYRIX_32) += cyrix.o |
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 826d5c876278..f8869978bbb7 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c | |||
@@ -1078,8 +1078,7 @@ void __cpuinit cpu_init(void) | |||
1078 | 1078 | ||
1079 | atomic_inc(&init_mm.mm_count); | 1079 | atomic_inc(&init_mm.mm_count); |
1080 | me->active_mm = &init_mm; | 1080 | me->active_mm = &init_mm; |
1081 | if (me->mm) | 1081 | BUG_ON(me->mm); |
1082 | BUG(); | ||
1083 | enter_lazy_tlb(&init_mm, me); | 1082 | enter_lazy_tlb(&init_mm, me); |
1084 | 1083 | ||
1085 | load_sp0(t, ¤t->thread); | 1084 | load_sp0(t, ¤t->thread); |
@@ -1145,8 +1144,7 @@ void __cpuinit cpu_init(void) | |||
1145 | */ | 1144 | */ |
1146 | atomic_inc(&init_mm.mm_count); | 1145 | atomic_inc(&init_mm.mm_count); |
1147 | curr->active_mm = &init_mm; | 1146 | curr->active_mm = &init_mm; |
1148 | if (curr->mm) | 1147 | BUG_ON(curr->mm); |
1149 | BUG(); | ||
1150 | enter_lazy_tlb(&init_mm, curr); | 1148 | enter_lazy_tlb(&init_mm, curr); |
1151 | 1149 | ||
1152 | load_sp0(t, thread); | 1150 | load_sp0(t, thread); |
diff --git a/arch/x86/kernel/cpu/cpu_debug.c b/arch/x86/kernel/cpu/cpu_debug.c new file mode 100755 index 000000000000..9abbcbd933cc --- /dev/null +++ b/arch/x86/kernel/cpu/cpu_debug.c | |||
@@ -0,0 +1,785 @@ | |||
1 | /* | ||
2 | * CPU x86 architecture debug code | ||
3 | * | ||
4 | * Copyright(C) 2009 Jaswinder Singh Rajput | ||
5 | * | ||
6 | * For licencing details see kernel-base/COPYING | ||
7 | */ | ||
8 | |||
9 | #include <linux/interrupt.h> | ||
10 | #include <linux/compiler.h> | ||
11 | #include <linux/seq_file.h> | ||
12 | #include <linux/debugfs.h> | ||
13 | #include <linux/kprobes.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/percpu.h> | ||
17 | #include <linux/signal.h> | ||
18 | #include <linux/errno.h> | ||
19 | #include <linux/sched.h> | ||
20 | #include <linux/types.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <linux/smp.h> | ||
24 | |||
25 | #include <asm/cpu_debug.h> | ||
26 | #include <asm/paravirt.h> | ||
27 | #include <asm/system.h> | ||
28 | #include <asm/traps.h> | ||
29 | #include <asm/apic.h> | ||
30 | #include <asm/desc.h> | ||
31 | |||
32 | static DEFINE_PER_CPU(struct cpu_cpuX_base, cpu_arr[CPU_REG_ALL_BIT]); | ||
33 | static DEFINE_PER_CPU(struct cpu_private *, priv_arr[MAX_CPU_FILES]); | ||
34 | static DEFINE_PER_CPU(unsigned, cpu_modelflag); | ||
35 | static DEFINE_PER_CPU(int, cpu_priv_count); | ||
36 | static DEFINE_PER_CPU(unsigned, cpu_model); | ||
37 | |||
38 | static DEFINE_MUTEX(cpu_debug_lock); | ||
39 | |||
40 | static struct dentry *cpu_debugfs_dir; | ||
41 | |||
42 | static struct cpu_debug_base cpu_base[] = { | ||
43 | { "mc", CPU_MC }, /* Machine Check */ | ||
44 | { "monitor", CPU_MONITOR }, /* Monitor */ | ||
45 | { "time", CPU_TIME }, /* Time */ | ||
46 | { "pmc", CPU_PMC }, /* Performance Monitor */ | ||
47 | { "platform", CPU_PLATFORM }, /* Platform */ | ||
48 | { "apic", CPU_APIC }, /* APIC */ | ||
49 | { "poweron", CPU_POWERON }, /* Power-on */ | ||
50 | { "control", CPU_CONTROL }, /* Control */ | ||
51 | { "features", CPU_FEATURES }, /* Features control */ | ||
52 | { "lastbranch", CPU_LBRANCH }, /* Last Branch */ | ||
53 | { "bios", CPU_BIOS }, /* BIOS */ | ||
54 | { "freq", CPU_FREQ }, /* Frequency */ | ||
55 | { "mtrr", CPU_MTRR }, /* MTRR */ | ||
56 | { "perf", CPU_PERF }, /* Performance */ | ||
57 | { "cache", CPU_CACHE }, /* Cache */ | ||
58 | { "sysenter", CPU_SYSENTER }, /* Sysenter */ | ||
59 | { "therm", CPU_THERM }, /* Thermal */ | ||
60 | { "misc", CPU_MISC }, /* Miscellaneous */ | ||
61 | { "debug", CPU_DEBUG }, /* Debug */ | ||
62 | { "pat", CPU_PAT }, /* PAT */ | ||
63 | { "vmx", CPU_VMX }, /* VMX */ | ||
64 | { "call", CPU_CALL }, /* System Call */ | ||
65 | { "base", CPU_BASE }, /* BASE Address */ | ||
66 | { "smm", CPU_SMM }, /* System mgmt mode */ | ||
67 | { "svm", CPU_SVM }, /*Secure Virtial Machine*/ | ||
68 | { "osvm", CPU_OSVM }, /* OS-Visible Workaround*/ | ||
69 | { "tss", CPU_TSS }, /* Task Stack Segment */ | ||
70 | { "cr", CPU_CR }, /* Control Registers */ | ||
71 | { "dt", CPU_DT }, /* Descriptor Table */ | ||
72 | { "registers", CPU_REG_ALL }, /* Select all Registers */ | ||
73 | }; | ||
74 | |||
75 | static struct cpu_file_base cpu_file[] = { | ||
76 | { "index", CPU_REG_ALL }, /* index */ | ||
77 | { "value", CPU_REG_ALL }, /* value */ | ||
78 | }; | ||
79 | |||
80 | /* Intel Registers Range */ | ||
81 | static struct cpu_debug_range cpu_intel_range[] = { | ||
82 | { 0x00000000, 0x00000001, CPU_MC, CPU_INTEL_ALL }, | ||
83 | { 0x00000006, 0x00000007, CPU_MONITOR, CPU_CX_AT_XE }, | ||
84 | { 0x00000010, 0x00000010, CPU_TIME, CPU_INTEL_ALL }, | ||
85 | { 0x00000011, 0x00000013, CPU_PMC, CPU_INTEL_PENTIUM }, | ||
86 | { 0x00000017, 0x00000017, CPU_PLATFORM, CPU_PX_CX_AT_XE }, | ||
87 | { 0x0000001B, 0x0000001B, CPU_APIC, CPU_P6_CX_AT_XE }, | ||
88 | |||
89 | { 0x0000002A, 0x0000002A, CPU_POWERON, CPU_PX_CX_AT_XE }, | ||
90 | { 0x0000002B, 0x0000002B, CPU_POWERON, CPU_INTEL_XEON }, | ||
91 | { 0x0000002C, 0x0000002C, CPU_FREQ, CPU_INTEL_XEON }, | ||
92 | { 0x0000003A, 0x0000003A, CPU_CONTROL, CPU_CX_AT_XE }, | ||
93 | |||
94 | { 0x00000040, 0x00000043, CPU_LBRANCH, CPU_PM_CX_AT_XE }, | ||
95 | { 0x00000044, 0x00000047, CPU_LBRANCH, CPU_PM_CO_AT }, | ||
96 | { 0x00000060, 0x00000063, CPU_LBRANCH, CPU_C2_AT }, | ||
97 | { 0x00000064, 0x00000067, CPU_LBRANCH, CPU_INTEL_ATOM }, | ||
98 | |||
99 | { 0x00000079, 0x00000079, CPU_BIOS, CPU_P6_CX_AT_XE }, | ||
100 | { 0x00000088, 0x0000008A, CPU_CACHE, CPU_INTEL_P6 }, | ||
101 | { 0x0000008B, 0x0000008B, CPU_BIOS, CPU_P6_CX_AT_XE }, | ||
102 | { 0x0000009B, 0x0000009B, CPU_MONITOR, CPU_INTEL_XEON }, | ||
103 | |||
104 | { 0x000000C1, 0x000000C2, CPU_PMC, CPU_P6_CX_AT }, | ||
105 | { 0x000000CD, 0x000000CD, CPU_FREQ, CPU_CX_AT }, | ||
106 | { 0x000000E7, 0x000000E8, CPU_PERF, CPU_CX_AT }, | ||
107 | { 0x000000FE, 0x000000FE, CPU_MTRR, CPU_P6_CX_XE }, | ||
108 | |||
109 | { 0x00000116, 0x00000116, CPU_CACHE, CPU_INTEL_P6 }, | ||
110 | { 0x00000118, 0x00000118, CPU_CACHE, CPU_INTEL_P6 }, | ||
111 | { 0x00000119, 0x00000119, CPU_CACHE, CPU_INTEL_PX }, | ||
112 | { 0x0000011A, 0x0000011B, CPU_CACHE, CPU_INTEL_P6 }, | ||
113 | { 0x0000011E, 0x0000011E, CPU_CACHE, CPU_PX_CX_AT }, | ||
114 | |||
115 | { 0x00000174, 0x00000176, CPU_SYSENTER, CPU_P6_CX_AT_XE }, | ||
116 | { 0x00000179, 0x0000017A, CPU_MC, CPU_PX_CX_AT_XE }, | ||
117 | { 0x0000017B, 0x0000017B, CPU_MC, CPU_P6_XE }, | ||
118 | { 0x00000186, 0x00000187, CPU_PMC, CPU_P6_CX_AT }, | ||
119 | { 0x00000198, 0x00000199, CPU_PERF, CPU_PM_CX_AT_XE }, | ||
120 | { 0x0000019A, 0x0000019A, CPU_TIME, CPU_PM_CX_AT_XE }, | ||
121 | { 0x0000019B, 0x0000019D, CPU_THERM, CPU_PM_CX_AT_XE }, | ||
122 | { 0x000001A0, 0x000001A0, CPU_MISC, CPU_PM_CX_AT_XE }, | ||
123 | |||
124 | { 0x000001C9, 0x000001C9, CPU_LBRANCH, CPU_PM_CX_AT }, | ||
125 | { 0x000001D7, 0x000001D8, CPU_LBRANCH, CPU_INTEL_XEON }, | ||
126 | { 0x000001D9, 0x000001D9, CPU_DEBUG, CPU_CX_AT_XE }, | ||
127 | { 0x000001DA, 0x000001DA, CPU_LBRANCH, CPU_INTEL_XEON }, | ||
128 | { 0x000001DB, 0x000001DB, CPU_LBRANCH, CPU_P6_XE }, | ||
129 | { 0x000001DC, 0x000001DC, CPU_LBRANCH, CPU_INTEL_P6 }, | ||
130 | { 0x000001DD, 0x000001DE, CPU_LBRANCH, CPU_PX_CX_AT_XE }, | ||
131 | { 0x000001E0, 0x000001E0, CPU_LBRANCH, CPU_INTEL_P6 }, | ||
132 | |||
133 | { 0x00000200, 0x0000020F, CPU_MTRR, CPU_P6_CX_XE }, | ||
134 | { 0x00000250, 0x00000250, CPU_MTRR, CPU_P6_CX_XE }, | ||
135 | { 0x00000258, 0x00000259, CPU_MTRR, CPU_P6_CX_XE }, | ||
136 | { 0x00000268, 0x0000026F, CPU_MTRR, CPU_P6_CX_XE }, | ||
137 | { 0x00000277, 0x00000277, CPU_PAT, CPU_C2_AT_XE }, | ||
138 | { 0x000002FF, 0x000002FF, CPU_MTRR, CPU_P6_CX_XE }, | ||
139 | |||
140 | { 0x00000300, 0x00000308, CPU_PMC, CPU_INTEL_XEON }, | ||
141 | { 0x00000309, 0x0000030B, CPU_PMC, CPU_C2_AT_XE }, | ||
142 | { 0x0000030C, 0x00000311, CPU_PMC, CPU_INTEL_XEON }, | ||
143 | { 0x00000345, 0x00000345, CPU_PMC, CPU_C2_AT }, | ||
144 | { 0x00000360, 0x00000371, CPU_PMC, CPU_INTEL_XEON }, | ||
145 | { 0x0000038D, 0x00000390, CPU_PMC, CPU_C2_AT }, | ||
146 | { 0x000003A0, 0x000003BE, CPU_PMC, CPU_INTEL_XEON }, | ||
147 | { 0x000003C0, 0x000003CD, CPU_PMC, CPU_INTEL_XEON }, | ||
148 | { 0x000003E0, 0x000003E1, CPU_PMC, CPU_INTEL_XEON }, | ||
149 | { 0x000003F0, 0x000003F0, CPU_PMC, CPU_INTEL_XEON }, | ||
150 | { 0x000003F1, 0x000003F1, CPU_PMC, CPU_C2_AT_XE }, | ||
151 | { 0x000003F2, 0x000003F2, CPU_PMC, CPU_INTEL_XEON }, | ||
152 | |||
153 | { 0x00000400, 0x00000402, CPU_MC, CPU_PM_CX_AT_XE }, | ||
154 | { 0x00000403, 0x00000403, CPU_MC, CPU_INTEL_XEON }, | ||
155 | { 0x00000404, 0x00000406, CPU_MC, CPU_PM_CX_AT_XE }, | ||
156 | { 0x00000407, 0x00000407, CPU_MC, CPU_INTEL_XEON }, | ||
157 | { 0x00000408, 0x0000040A, CPU_MC, CPU_PM_CX_AT_XE }, | ||
158 | { 0x0000040B, 0x0000040B, CPU_MC, CPU_INTEL_XEON }, | ||
159 | { 0x0000040C, 0x0000040E, CPU_MC, CPU_PM_CX_XE }, | ||
160 | { 0x0000040F, 0x0000040F, CPU_MC, CPU_INTEL_XEON }, | ||
161 | { 0x00000410, 0x00000412, CPU_MC, CPU_PM_CX_AT_XE }, | ||
162 | { 0x00000413, 0x00000417, CPU_MC, CPU_CX_AT_XE }, | ||
163 | { 0x00000480, 0x0000048B, CPU_VMX, CPU_CX_AT_XE }, | ||
164 | |||
165 | { 0x00000600, 0x00000600, CPU_DEBUG, CPU_PM_CX_AT_XE }, | ||
166 | { 0x00000680, 0x0000068F, CPU_LBRANCH, CPU_INTEL_XEON }, | ||
167 | { 0x000006C0, 0x000006CF, CPU_LBRANCH, CPU_INTEL_XEON }, | ||
168 | |||
169 | { 0x000107CC, 0x000107D3, CPU_PMC, CPU_INTEL_XEON_MP }, | ||
170 | |||
171 | { 0xC0000080, 0xC0000080, CPU_FEATURES, CPU_INTEL_XEON }, | ||
172 | { 0xC0000081, 0xC0000082, CPU_CALL, CPU_INTEL_XEON }, | ||
173 | { 0xC0000084, 0xC0000084, CPU_CALL, CPU_INTEL_XEON }, | ||
174 | { 0xC0000100, 0xC0000102, CPU_BASE, CPU_INTEL_XEON }, | ||
175 | }; | ||
176 | |||
177 | /* AMD Registers Range */ | ||
178 | static struct cpu_debug_range cpu_amd_range[] = { | ||
179 | { 0x00000010, 0x00000010, CPU_TIME, CPU_ALL, }, | ||
180 | { 0x0000001B, 0x0000001B, CPU_APIC, CPU_ALL, }, | ||
181 | { 0x000000FE, 0x000000FE, CPU_MTRR, CPU_ALL, }, | ||
182 | |||
183 | { 0x00000174, 0x00000176, CPU_SYSENTER, CPU_ALL, }, | ||
184 | { 0x00000179, 0x0000017A, CPU_MC, CPU_ALL, }, | ||
185 | { 0x0000017B, 0x0000017B, CPU_MC, CPU_ALL, }, | ||
186 | { 0x000001D9, 0x000001D9, CPU_DEBUG, CPU_ALL, }, | ||
187 | { 0x000001DB, 0x000001DE, CPU_LBRANCH, CPU_ALL, }, | ||
188 | |||
189 | { 0x00000200, 0x0000020F, CPU_MTRR, CPU_ALL, }, | ||
190 | { 0x00000250, 0x00000250, CPU_MTRR, CPU_ALL, }, | ||
191 | { 0x00000258, 0x00000259, CPU_MTRR, CPU_ALL, }, | ||
192 | { 0x00000268, 0x0000026F, CPU_MTRR, CPU_ALL, }, | ||
193 | { 0x00000277, 0x00000277, CPU_PAT, CPU_ALL, }, | ||
194 | { 0x000002FF, 0x000002FF, CPU_MTRR, CPU_ALL, }, | ||
195 | |||
196 | { 0x00000400, 0x00000417, CPU_MC, CPU_ALL, }, | ||
197 | |||
198 | { 0xC0000080, 0xC0000080, CPU_FEATURES, CPU_ALL, }, | ||
199 | { 0xC0000081, 0xC0000084, CPU_CALL, CPU_ALL, }, | ||
200 | { 0xC0000100, 0xC0000102, CPU_BASE, CPU_ALL, }, | ||
201 | { 0xC0000103, 0xC0000103, CPU_TIME, CPU_ALL, }, | ||
202 | |||
203 | { 0xC0000408, 0xC000040A, CPU_MC, CPU_ALL, }, | ||
204 | |||
205 | { 0xc0010000, 0xc0010007, CPU_PMC, CPU_ALL, }, | ||
206 | { 0xc0010010, 0xc0010010, CPU_MTRR, CPU_ALL, }, | ||
207 | { 0xc0010016, 0xc001001A, CPU_MTRR, CPU_ALL, }, | ||
208 | { 0xc001001D, 0xc001001D, CPU_MTRR, CPU_ALL, }, | ||
209 | { 0xc0010030, 0xc0010035, CPU_BIOS, CPU_ALL, }, | ||
210 | { 0xc0010056, 0xc0010056, CPU_SMM, CPU_ALL, }, | ||
211 | { 0xc0010061, 0xc0010063, CPU_SMM, CPU_ALL, }, | ||
212 | { 0xc0010074, 0xc0010074, CPU_MC, CPU_ALL, }, | ||
213 | { 0xc0010111, 0xc0010113, CPU_SMM, CPU_ALL, }, | ||
214 | { 0xc0010114, 0xc0010118, CPU_SVM, CPU_ALL, }, | ||
215 | { 0xc0010119, 0xc001011A, CPU_SMM, CPU_ALL, }, | ||
216 | { 0xc0010140, 0xc0010141, CPU_OSVM, CPU_ALL, }, | ||
217 | { 0xc0010156, 0xc0010156, CPU_SMM, CPU_ALL, }, | ||
218 | }; | ||
219 | |||
220 | |||
221 | static int get_cpu_modelflag(unsigned cpu) | ||
222 | { | ||
223 | int flag; | ||
224 | |||
225 | switch (per_cpu(cpu_model, cpu)) { | ||
226 | /* Intel */ | ||
227 | case 0x0501: | ||
228 | case 0x0502: | ||
229 | case 0x0504: | ||
230 | flag = CPU_INTEL_PENTIUM; | ||
231 | break; | ||
232 | case 0x0601: | ||
233 | case 0x0603: | ||
234 | case 0x0605: | ||
235 | case 0x0607: | ||
236 | case 0x0608: | ||
237 | case 0x060A: | ||
238 | case 0x060B: | ||
239 | flag = CPU_INTEL_P6; | ||
240 | break; | ||
241 | case 0x0609: | ||
242 | case 0x060D: | ||
243 | flag = CPU_INTEL_PENTIUM_M; | ||
244 | break; | ||
245 | case 0x060E: | ||
246 | flag = CPU_INTEL_CORE; | ||
247 | break; | ||
248 | case 0x060F: | ||
249 | case 0x0617: | ||
250 | flag = CPU_INTEL_CORE2; | ||
251 | break; | ||
252 | case 0x061C: | ||
253 | flag = CPU_INTEL_ATOM; | ||
254 | break; | ||
255 | case 0x0F00: | ||
256 | case 0x0F01: | ||
257 | case 0x0F02: | ||
258 | case 0x0F03: | ||
259 | case 0x0F04: | ||
260 | flag = CPU_INTEL_XEON_P4; | ||
261 | break; | ||
262 | case 0x0F06: | ||
263 | flag = CPU_INTEL_XEON_MP; | ||
264 | break; | ||
265 | default: | ||
266 | flag = CPU_NONE; | ||
267 | break; | ||
268 | } | ||
269 | |||
270 | return flag; | ||
271 | } | ||
272 | |||
273 | static int get_cpu_range_count(unsigned cpu) | ||
274 | { | ||
275 | int index; | ||
276 | |||
277 | switch (per_cpu(cpu_model, cpu) >> 16) { | ||
278 | case X86_VENDOR_INTEL: | ||
279 | index = ARRAY_SIZE(cpu_intel_range); | ||
280 | break; | ||
281 | case X86_VENDOR_AMD: | ||
282 | index = ARRAY_SIZE(cpu_amd_range); | ||
283 | break; | ||
284 | default: | ||
285 | index = 0; | ||
286 | break; | ||
287 | } | ||
288 | |||
289 | return index; | ||
290 | } | ||
291 | |||
292 | static int is_typeflag_valid(unsigned cpu, unsigned flag) | ||
293 | { | ||
294 | unsigned vendor, modelflag; | ||
295 | int i, index; | ||
296 | |||
297 | /* Standard Registers should be always valid */ | ||
298 | if (flag >= CPU_TSS) | ||
299 | return 1; | ||
300 | |||
301 | modelflag = per_cpu(cpu_modelflag, cpu); | ||
302 | vendor = per_cpu(cpu_model, cpu) >> 16; | ||
303 | index = get_cpu_range_count(cpu); | ||
304 | |||
305 | for (i = 0; i < index; i++) { | ||
306 | switch (vendor) { | ||
307 | case X86_VENDOR_INTEL: | ||
308 | if ((cpu_intel_range[i].model & modelflag) && | ||
309 | (cpu_intel_range[i].flag & flag)) | ||
310 | return 1; | ||
311 | break; | ||
312 | case X86_VENDOR_AMD: | ||
313 | if (cpu_amd_range[i].flag & flag) | ||
314 | return 1; | ||
315 | break; | ||
316 | } | ||
317 | } | ||
318 | |||
319 | /* Invalid */ | ||
320 | return 0; | ||
321 | } | ||
322 | |||
323 | static unsigned get_cpu_range(unsigned cpu, unsigned *min, unsigned *max, | ||
324 | int index, unsigned flag) | ||
325 | { | ||
326 | unsigned modelflag; | ||
327 | |||
328 | modelflag = per_cpu(cpu_modelflag, cpu); | ||
329 | *max = 0; | ||
330 | switch (per_cpu(cpu_model, cpu) >> 16) { | ||
331 | case X86_VENDOR_INTEL: | ||
332 | if ((cpu_intel_range[index].model & modelflag) && | ||
333 | (cpu_intel_range[index].flag & flag)) { | ||
334 | *min = cpu_intel_range[index].min; | ||
335 | *max = cpu_intel_range[index].max; | ||
336 | } | ||
337 | break; | ||
338 | case X86_VENDOR_AMD: | ||
339 | if (cpu_amd_range[index].flag & flag) { | ||
340 | *min = cpu_amd_range[index].min; | ||
341 | *max = cpu_amd_range[index].max; | ||
342 | } | ||
343 | break; | ||
344 | } | ||
345 | |||
346 | return *max; | ||
347 | } | ||
348 | |||
349 | /* This function can also be called with seq = NULL for printk */ | ||
350 | static void print_cpu_data(struct seq_file *seq, unsigned type, | ||
351 | u32 low, u32 high) | ||
352 | { | ||
353 | struct cpu_private *priv; | ||
354 | u64 val = high; | ||
355 | |||
356 | if (seq) { | ||
357 | priv = seq->private; | ||
358 | if (priv->file) { | ||
359 | val = (val << 32) | low; | ||
360 | seq_printf(seq, "0x%llx\n", val); | ||
361 | } else | ||
362 | seq_printf(seq, " %08x: %08x_%08x\n", | ||
363 | type, high, low); | ||
364 | } else | ||
365 | printk(KERN_INFO " %08x: %08x_%08x\n", type, high, low); | ||
366 | } | ||
367 | |||
368 | /* This function can also be called with seq = NULL for printk */ | ||
369 | static void print_msr(struct seq_file *seq, unsigned cpu, unsigned flag) | ||
370 | { | ||
371 | unsigned msr, msr_min, msr_max; | ||
372 | struct cpu_private *priv; | ||
373 | u32 low, high; | ||
374 | int i, range; | ||
375 | |||
376 | if (seq) { | ||
377 | priv = seq->private; | ||
378 | if (priv->file) { | ||
379 | if (!rdmsr_safe_on_cpu(priv->cpu, priv->reg, | ||
380 | &low, &high)) | ||
381 | print_cpu_data(seq, priv->reg, low, high); | ||
382 | return; | ||
383 | } | ||
384 | } | ||
385 | |||
386 | range = get_cpu_range_count(cpu); | ||
387 | |||
388 | for (i = 0; i < range; i++) { | ||
389 | if (!get_cpu_range(cpu, &msr_min, &msr_max, i, flag)) | ||
390 | continue; | ||
391 | |||
392 | for (msr = msr_min; msr <= msr_max; msr++) { | ||
393 | if (rdmsr_safe_on_cpu(cpu, msr, &low, &high)) | ||
394 | continue; | ||
395 | print_cpu_data(seq, msr, low, high); | ||
396 | } | ||
397 | } | ||
398 | } | ||
399 | |||
400 | static void print_tss(void *arg) | ||
401 | { | ||
402 | struct pt_regs *regs = task_pt_regs(current); | ||
403 | struct seq_file *seq = arg; | ||
404 | unsigned int seg; | ||
405 | |||
406 | seq_printf(seq, " RAX\t: %016lx\n", regs->ax); | ||
407 | seq_printf(seq, " RBX\t: %016lx\n", regs->bx); | ||
408 | seq_printf(seq, " RCX\t: %016lx\n", regs->cx); | ||
409 | seq_printf(seq, " RDX\t: %016lx\n", regs->dx); | ||
410 | |||
411 | seq_printf(seq, " RSI\t: %016lx\n", regs->si); | ||
412 | seq_printf(seq, " RDI\t: %016lx\n", regs->di); | ||
413 | seq_printf(seq, " RBP\t: %016lx\n", regs->bp); | ||
414 | seq_printf(seq, " ESP\t: %016lx\n", regs->sp); | ||
415 | |||
416 | #ifdef CONFIG_X86_64 | ||
417 | seq_printf(seq, " R08\t: %016lx\n", regs->r8); | ||
418 | seq_printf(seq, " R09\t: %016lx\n", regs->r9); | ||
419 | seq_printf(seq, " R10\t: %016lx\n", regs->r10); | ||
420 | seq_printf(seq, " R11\t: %016lx\n", regs->r11); | ||
421 | seq_printf(seq, " R12\t: %016lx\n", regs->r12); | ||
422 | seq_printf(seq, " R13\t: %016lx\n", regs->r13); | ||
423 | seq_printf(seq, " R14\t: %016lx\n", regs->r14); | ||
424 | seq_printf(seq, " R15\t: %016lx\n", regs->r15); | ||
425 | #endif | ||
426 | |||
427 | asm("movl %%cs,%0" : "=r" (seg)); | ||
428 | seq_printf(seq, " CS\t: %04x\n", seg); | ||
429 | asm("movl %%ds,%0" : "=r" (seg)); | ||
430 | seq_printf(seq, " DS\t: %04x\n", seg); | ||
431 | seq_printf(seq, " SS\t: %04lx\n", regs->ss & 0xffff); | ||
432 | asm("movl %%es,%0" : "=r" (seg)); | ||
433 | seq_printf(seq, " ES\t: %04x\n", seg); | ||
434 | asm("movl %%fs,%0" : "=r" (seg)); | ||
435 | seq_printf(seq, " FS\t: %04x\n", seg); | ||
436 | asm("movl %%gs,%0" : "=r" (seg)); | ||
437 | seq_printf(seq, " GS\t: %04x\n", seg); | ||
438 | |||
439 | seq_printf(seq, " EFLAGS\t: %016lx\n", regs->flags); | ||
440 | |||
441 | seq_printf(seq, " EIP\t: %016lx\n", regs->ip); | ||
442 | } | ||
443 | |||
444 | static void print_cr(void *arg) | ||
445 | { | ||
446 | struct seq_file *seq = arg; | ||
447 | |||
448 | seq_printf(seq, " cr0\t: %016lx\n", read_cr0()); | ||
449 | seq_printf(seq, " cr2\t: %016lx\n", read_cr2()); | ||
450 | seq_printf(seq, " cr3\t: %016lx\n", read_cr3()); | ||
451 | seq_printf(seq, " cr4\t: %016lx\n", read_cr4_safe()); | ||
452 | #ifdef CONFIG_X86_64 | ||
453 | seq_printf(seq, " cr8\t: %016lx\n", read_cr8()); | ||
454 | #endif | ||
455 | } | ||
456 | |||
457 | static void print_desc_ptr(char *str, struct seq_file *seq, struct desc_ptr dt) | ||
458 | { | ||
459 | seq_printf(seq, " %s\t: %016llx\n", str, (u64)(dt.address | dt.size)); | ||
460 | } | ||
461 | |||
462 | static void print_dt(void *seq) | ||
463 | { | ||
464 | struct desc_ptr dt; | ||
465 | unsigned long ldt; | ||
466 | |||
467 | /* IDT */ | ||
468 | store_idt((struct desc_ptr *)&dt); | ||
469 | print_desc_ptr("IDT", seq, dt); | ||
470 | |||
471 | /* GDT */ | ||
472 | store_gdt((struct desc_ptr *)&dt); | ||
473 | print_desc_ptr("GDT", seq, dt); | ||
474 | |||
475 | /* LDT */ | ||
476 | store_ldt(ldt); | ||
477 | seq_printf(seq, " LDT\t: %016lx\n", ldt); | ||
478 | |||
479 | /* TR */ | ||
480 | store_tr(ldt); | ||
481 | seq_printf(seq, " TR\t: %016lx\n", ldt); | ||
482 | } | ||
483 | |||
484 | static void print_dr(void *arg) | ||
485 | { | ||
486 | struct seq_file *seq = arg; | ||
487 | unsigned long dr; | ||
488 | int i; | ||
489 | |||
490 | for (i = 0; i < 8; i++) { | ||
491 | /* Ignore db4, db5 */ | ||
492 | if ((i == 4) || (i == 5)) | ||
493 | continue; | ||
494 | get_debugreg(dr, i); | ||
495 | seq_printf(seq, " dr%d\t: %016lx\n", i, dr); | ||
496 | } | ||
497 | |||
498 | seq_printf(seq, "\n MSR\t:\n"); | ||
499 | } | ||
500 | |||
501 | static void print_apic(void *arg) | ||
502 | { | ||
503 | struct seq_file *seq = arg; | ||
504 | |||
505 | #ifdef CONFIG_X86_LOCAL_APIC | ||
506 | seq_printf(seq, " LAPIC\t:\n"); | ||
507 | seq_printf(seq, " ID\t\t: %08x\n", apic_read(APIC_ID) >> 24); | ||
508 | seq_printf(seq, " LVR\t\t: %08x\n", apic_read(APIC_LVR)); | ||
509 | seq_printf(seq, " TASKPRI\t: %08x\n", apic_read(APIC_TASKPRI)); | ||
510 | seq_printf(seq, " ARBPRI\t\t: %08x\n", apic_read(APIC_ARBPRI)); | ||
511 | seq_printf(seq, " PROCPRI\t: %08x\n", apic_read(APIC_PROCPRI)); | ||
512 | seq_printf(seq, " LDR\t\t: %08x\n", apic_read(APIC_LDR)); | ||
513 | seq_printf(seq, " DFR\t\t: %08x\n", apic_read(APIC_DFR)); | ||
514 | seq_printf(seq, " SPIV\t\t: %08x\n", apic_read(APIC_SPIV)); | ||
515 | seq_printf(seq, " ISR\t\t: %08x\n", apic_read(APIC_ISR)); | ||
516 | seq_printf(seq, " ESR\t\t: %08x\n", apic_read(APIC_ESR)); | ||
517 | seq_printf(seq, " ICR\t\t: %08x\n", apic_read(APIC_ICR)); | ||
518 | seq_printf(seq, " ICR2\t\t: %08x\n", apic_read(APIC_ICR2)); | ||
519 | seq_printf(seq, " LVTT\t\t: %08x\n", apic_read(APIC_LVTT)); | ||
520 | seq_printf(seq, " LVTTHMR\t: %08x\n", apic_read(APIC_LVTTHMR)); | ||
521 | seq_printf(seq, " LVTPC\t\t: %08x\n", apic_read(APIC_LVTPC)); | ||
522 | seq_printf(seq, " LVT0\t\t: %08x\n", apic_read(APIC_LVT0)); | ||
523 | seq_printf(seq, " LVT1\t\t: %08x\n", apic_read(APIC_LVT1)); | ||
524 | seq_printf(seq, " LVTERR\t\t: %08x\n", apic_read(APIC_LVTERR)); | ||
525 | seq_printf(seq, " TMICT\t\t: %08x\n", apic_read(APIC_TMICT)); | ||
526 | seq_printf(seq, " TMCCT\t\t: %08x\n", apic_read(APIC_TMCCT)); | ||
527 | seq_printf(seq, " TDCR\t\t: %08x\n", apic_read(APIC_TDCR)); | ||
528 | #endif /* CONFIG_X86_LOCAL_APIC */ | ||
529 | |||
530 | seq_printf(seq, "\n MSR\t:\n"); | ||
531 | } | ||
532 | |||
533 | static int cpu_seq_show(struct seq_file *seq, void *v) | ||
534 | { | ||
535 | struct cpu_private *priv = seq->private; | ||
536 | |||
537 | if (priv == NULL) | ||
538 | return -EINVAL; | ||
539 | |||
540 | switch (cpu_base[priv->type].flag) { | ||
541 | case CPU_TSS: | ||
542 | smp_call_function_single(priv->cpu, print_tss, seq, 1); | ||
543 | break; | ||
544 | case CPU_CR: | ||
545 | smp_call_function_single(priv->cpu, print_cr, seq, 1); | ||
546 | break; | ||
547 | case CPU_DT: | ||
548 | smp_call_function_single(priv->cpu, print_dt, seq, 1); | ||
549 | break; | ||
550 | case CPU_DEBUG: | ||
551 | if (priv->file == CPU_INDEX_BIT) | ||
552 | smp_call_function_single(priv->cpu, print_dr, seq, 1); | ||
553 | print_msr(seq, priv->cpu, cpu_base[priv->type].flag); | ||
554 | break; | ||
555 | case CPU_APIC: | ||
556 | if (priv->file == CPU_INDEX_BIT) | ||
557 | smp_call_function_single(priv->cpu, print_apic, seq, 1); | ||
558 | print_msr(seq, priv->cpu, cpu_base[priv->type].flag); | ||
559 | break; | ||
560 | |||
561 | default: | ||
562 | print_msr(seq, priv->cpu, cpu_base[priv->type].flag); | ||
563 | break; | ||
564 | } | ||
565 | seq_printf(seq, "\n"); | ||
566 | |||
567 | return 0; | ||
568 | } | ||
569 | |||
570 | static void *cpu_seq_start(struct seq_file *seq, loff_t *pos) | ||
571 | { | ||
572 | if (*pos == 0) /* One time is enough ;-) */ | ||
573 | return seq; | ||
574 | |||
575 | return NULL; | ||
576 | } | ||
577 | |||
578 | static void *cpu_seq_next(struct seq_file *seq, void *v, loff_t *pos) | ||
579 | { | ||
580 | (*pos)++; | ||
581 | |||
582 | return cpu_seq_start(seq, pos); | ||
583 | } | ||
584 | |||
585 | static void cpu_seq_stop(struct seq_file *seq, void *v) | ||
586 | { | ||
587 | } | ||
588 | |||
589 | static const struct seq_operations cpu_seq_ops = { | ||
590 | .start = cpu_seq_start, | ||
591 | .next = cpu_seq_next, | ||
592 | .stop = cpu_seq_stop, | ||
593 | .show = cpu_seq_show, | ||
594 | }; | ||
595 | |||
596 | static int cpu_seq_open(struct inode *inode, struct file *file) | ||
597 | { | ||
598 | struct cpu_private *priv = inode->i_private; | ||
599 | struct seq_file *seq; | ||
600 | int err; | ||
601 | |||
602 | err = seq_open(file, &cpu_seq_ops); | ||
603 | if (!err) { | ||
604 | seq = file->private_data; | ||
605 | seq->private = priv; | ||
606 | } | ||
607 | |||
608 | return err; | ||
609 | } | ||
610 | |||
611 | static const struct file_operations cpu_fops = { | ||
612 | .open = cpu_seq_open, | ||
613 | .read = seq_read, | ||
614 | .llseek = seq_lseek, | ||
615 | .release = seq_release, | ||
616 | }; | ||
617 | |||
618 | static int cpu_create_file(unsigned cpu, unsigned type, unsigned reg, | ||
619 | unsigned file, struct dentry *dentry) | ||
620 | { | ||
621 | struct cpu_private *priv = NULL; | ||
622 | |||
623 | /* Already intialized */ | ||
624 | if (file == CPU_INDEX_BIT) | ||
625 | if (per_cpu(cpu_arr[type].init, cpu)) | ||
626 | return 0; | ||
627 | |||
628 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
629 | if (priv == NULL) | ||
630 | return -ENOMEM; | ||
631 | |||
632 | priv->cpu = cpu; | ||
633 | priv->type = type; | ||
634 | priv->reg = reg; | ||
635 | priv->file = file; | ||
636 | mutex_lock(&cpu_debug_lock); | ||
637 | per_cpu(priv_arr[type], cpu) = priv; | ||
638 | per_cpu(cpu_priv_count, cpu)++; | ||
639 | mutex_unlock(&cpu_debug_lock); | ||
640 | |||
641 | if (file) | ||
642 | debugfs_create_file(cpu_file[file].name, S_IRUGO, | ||
643 | dentry, (void *)priv, &cpu_fops); | ||
644 | else { | ||
645 | debugfs_create_file(cpu_base[type].name, S_IRUGO, | ||
646 | per_cpu(cpu_arr[type].dentry, cpu), | ||
647 | (void *)priv, &cpu_fops); | ||
648 | mutex_lock(&cpu_debug_lock); | ||
649 | per_cpu(cpu_arr[type].init, cpu) = 1; | ||
650 | mutex_unlock(&cpu_debug_lock); | ||
651 | } | ||
652 | |||
653 | return 0; | ||
654 | } | ||
655 | |||
656 | static int cpu_init_regfiles(unsigned cpu, unsigned int type, unsigned reg, | ||
657 | struct dentry *dentry) | ||
658 | { | ||
659 | unsigned file; | ||
660 | int err = 0; | ||
661 | |||
662 | for (file = 0; file < ARRAY_SIZE(cpu_file); file++) { | ||
663 | err = cpu_create_file(cpu, type, reg, file, dentry); | ||
664 | if (err) | ||
665 | return err; | ||
666 | } | ||
667 | |||
668 | return err; | ||
669 | } | ||
670 | |||
671 | static int cpu_init_msr(unsigned cpu, unsigned type, struct dentry *dentry) | ||
672 | { | ||
673 | struct dentry *cpu_dentry = NULL; | ||
674 | unsigned reg, reg_min, reg_max; | ||
675 | int i, range, err = 0; | ||
676 | char reg_dir[12]; | ||
677 | u32 low, high; | ||
678 | |||
679 | range = get_cpu_range_count(cpu); | ||
680 | |||
681 | for (i = 0; i < range; i++) { | ||
682 | if (!get_cpu_range(cpu, ®_min, ®_max, i, | ||
683 | cpu_base[type].flag)) | ||
684 | continue; | ||
685 | |||
686 | for (reg = reg_min; reg <= reg_max; reg++) { | ||
687 | if (rdmsr_safe_on_cpu(cpu, reg, &low, &high)) | ||
688 | continue; | ||
689 | |||
690 | sprintf(reg_dir, "0x%x", reg); | ||
691 | cpu_dentry = debugfs_create_dir(reg_dir, dentry); | ||
692 | err = cpu_init_regfiles(cpu, type, reg, cpu_dentry); | ||
693 | if (err) | ||
694 | return err; | ||
695 | } | ||
696 | } | ||
697 | |||
698 | return err; | ||
699 | } | ||
700 | |||
701 | static int cpu_init_allreg(unsigned cpu, struct dentry *dentry) | ||
702 | { | ||
703 | struct dentry *cpu_dentry = NULL; | ||
704 | unsigned type; | ||
705 | int err = 0; | ||
706 | |||
707 | for (type = 0; type < ARRAY_SIZE(cpu_base) - 1; type++) { | ||
708 | if (!is_typeflag_valid(cpu, cpu_base[type].flag)) | ||
709 | continue; | ||
710 | cpu_dentry = debugfs_create_dir(cpu_base[type].name, dentry); | ||
711 | per_cpu(cpu_arr[type].dentry, cpu) = cpu_dentry; | ||
712 | |||
713 | if (type < CPU_TSS_BIT) | ||
714 | err = cpu_init_msr(cpu, type, cpu_dentry); | ||
715 | else | ||
716 | err = cpu_create_file(cpu, type, 0, CPU_INDEX_BIT, | ||
717 | cpu_dentry); | ||
718 | if (err) | ||
719 | return err; | ||
720 | } | ||
721 | |||
722 | return err; | ||
723 | } | ||
724 | |||
725 | static int cpu_init_cpu(void) | ||
726 | { | ||
727 | struct dentry *cpu_dentry = NULL; | ||
728 | struct cpuinfo_x86 *cpui; | ||
729 | char cpu_dir[12]; | ||
730 | unsigned cpu; | ||
731 | int err = 0; | ||
732 | |||
733 | for (cpu = 0; cpu < nr_cpu_ids; cpu++) { | ||
734 | cpui = &cpu_data(cpu); | ||
735 | if (!cpu_has(cpui, X86_FEATURE_MSR)) | ||
736 | continue; | ||
737 | per_cpu(cpu_model, cpu) = ((cpui->x86_vendor << 16) | | ||
738 | (cpui->x86 << 8) | | ||
739 | (cpui->x86_model)); | ||
740 | per_cpu(cpu_modelflag, cpu) = get_cpu_modelflag(cpu); | ||
741 | |||
742 | sprintf(cpu_dir, "cpu%d", cpu); | ||
743 | cpu_dentry = debugfs_create_dir(cpu_dir, cpu_debugfs_dir); | ||
744 | err = cpu_init_allreg(cpu, cpu_dentry); | ||
745 | |||
746 | pr_info("cpu%d(%d) debug files %d\n", | ||
747 | cpu, nr_cpu_ids, per_cpu(cpu_priv_count, cpu)); | ||
748 | if (per_cpu(cpu_priv_count, cpu) > MAX_CPU_FILES) { | ||
749 | pr_err("Register files count %d exceeds limit %d\n", | ||
750 | per_cpu(cpu_priv_count, cpu), MAX_CPU_FILES); | ||
751 | per_cpu(cpu_priv_count, cpu) = MAX_CPU_FILES; | ||
752 | err = -ENFILE; | ||
753 | } | ||
754 | if (err) | ||
755 | return err; | ||
756 | } | ||
757 | |||
758 | return err; | ||
759 | } | ||
760 | |||
761 | static int __init cpu_debug_init(void) | ||
762 | { | ||
763 | cpu_debugfs_dir = debugfs_create_dir("cpu", arch_debugfs_dir); | ||
764 | |||
765 | return cpu_init_cpu(); | ||
766 | } | ||
767 | |||
768 | static void __exit cpu_debug_exit(void) | ||
769 | { | ||
770 | int i, cpu; | ||
771 | |||
772 | if (cpu_debugfs_dir) | ||
773 | debugfs_remove_recursive(cpu_debugfs_dir); | ||
774 | |||
775 | for (cpu = 0; cpu < nr_cpu_ids; cpu++) | ||
776 | for (i = 0; i < per_cpu(cpu_priv_count, cpu); i++) | ||
777 | kfree(per_cpu(priv_arr[i], cpu)); | ||
778 | } | ||
779 | |||
780 | module_init(cpu_debug_init); | ||
781 | module_exit(cpu_debug_exit); | ||
782 | |||
783 | MODULE_AUTHOR("Jaswinder Singh Rajput"); | ||
784 | MODULE_DESCRIPTION("CPU Debug module"); | ||
785 | MODULE_LICENSE("GPL"); | ||
diff --git a/arch/x86/kernel/cpu/mcheck/mce_64.c b/arch/x86/kernel/cpu/mcheck/mce_64.c index bfbd5323a635..ca14604611ec 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_64.c +++ b/arch/x86/kernel/cpu/mcheck/mce_64.c | |||
@@ -639,7 +639,7 @@ static void mce_init_timer(void) | |||
639 | if (!next_interval) | 639 | if (!next_interval) |
640 | return; | 640 | return; |
641 | setup_timer(t, mcheck_timer, smp_processor_id()); | 641 | setup_timer(t, mcheck_timer, smp_processor_id()); |
642 | t->expires = round_jiffies_relative(jiffies + next_interval); | 642 | t->expires = round_jiffies(jiffies + next_interval); |
643 | add_timer(t); | 643 | add_timer(t); |
644 | } | 644 | } |
645 | 645 | ||
@@ -1110,7 +1110,7 @@ static int __cpuinit mce_cpu_callback(struct notifier_block *nfb, | |||
1110 | break; | 1110 | break; |
1111 | case CPU_DOWN_FAILED: | 1111 | case CPU_DOWN_FAILED: |
1112 | case CPU_DOWN_FAILED_FROZEN: | 1112 | case CPU_DOWN_FAILED_FROZEN: |
1113 | t->expires = round_jiffies_relative(jiffies + next_interval); | 1113 | t->expires = round_jiffies(jiffies + next_interval); |
1114 | add_timer_on(t, cpu); | 1114 | add_timer_on(t, cpu); |
1115 | smp_call_function_single(cpu, mce_reenable_cpu, &action, 1); | 1115 | smp_call_function_single(cpu, mce_reenable_cpu, &action, 1); |
1116 | break; | 1116 | break; |
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S index 899e8938e79f..c929add475c9 100644 --- a/arch/x86/kernel/entry_32.S +++ b/arch/x86/kernel/entry_32.S | |||
@@ -442,8 +442,7 @@ sysenter_past_esp: | |||
442 | 442 | ||
443 | GET_THREAD_INFO(%ebp) | 443 | GET_THREAD_INFO(%ebp) |
444 | 444 | ||
445 | /* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not testb */ | 445 | testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp) |
446 | testw $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp) | ||
447 | jnz sysenter_audit | 446 | jnz sysenter_audit |
448 | sysenter_do_call: | 447 | sysenter_do_call: |
449 | cmpl $(nr_syscalls), %eax | 448 | cmpl $(nr_syscalls), %eax |
@@ -454,7 +453,7 @@ sysenter_do_call: | |||
454 | DISABLE_INTERRUPTS(CLBR_ANY) | 453 | DISABLE_INTERRUPTS(CLBR_ANY) |
455 | TRACE_IRQS_OFF | 454 | TRACE_IRQS_OFF |
456 | movl TI_flags(%ebp), %ecx | 455 | movl TI_flags(%ebp), %ecx |
457 | testw $_TIF_ALLWORK_MASK, %cx | 456 | testl $_TIF_ALLWORK_MASK, %ecx |
458 | jne sysexit_audit | 457 | jne sysexit_audit |
459 | sysenter_exit: | 458 | sysenter_exit: |
460 | /* if something modifies registers it must also disable sysexit */ | 459 | /* if something modifies registers it must also disable sysexit */ |
@@ -468,7 +467,7 @@ sysenter_exit: | |||
468 | 467 | ||
469 | #ifdef CONFIG_AUDITSYSCALL | 468 | #ifdef CONFIG_AUDITSYSCALL |
470 | sysenter_audit: | 469 | sysenter_audit: |
471 | testw $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags(%ebp) | 470 | testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags(%ebp) |
472 | jnz syscall_trace_entry | 471 | jnz syscall_trace_entry |
473 | addl $4,%esp | 472 | addl $4,%esp |
474 | CFI_ADJUST_CFA_OFFSET -4 | 473 | CFI_ADJUST_CFA_OFFSET -4 |
@@ -485,7 +484,7 @@ sysenter_audit: | |||
485 | jmp sysenter_do_call | 484 | jmp sysenter_do_call |
486 | 485 | ||
487 | sysexit_audit: | 486 | sysexit_audit: |
488 | testw $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT), %cx | 487 | testl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT), %ecx |
489 | jne syscall_exit_work | 488 | jne syscall_exit_work |
490 | TRACE_IRQS_ON | 489 | TRACE_IRQS_ON |
491 | ENABLE_INTERRUPTS(CLBR_ANY) | 490 | ENABLE_INTERRUPTS(CLBR_ANY) |
@@ -498,7 +497,7 @@ sysexit_audit: | |||
498 | DISABLE_INTERRUPTS(CLBR_ANY) | 497 | DISABLE_INTERRUPTS(CLBR_ANY) |
499 | TRACE_IRQS_OFF | 498 | TRACE_IRQS_OFF |
500 | movl TI_flags(%ebp), %ecx | 499 | movl TI_flags(%ebp), %ecx |
501 | testw $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT), %cx | 500 | testl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT), %ecx |
502 | jne syscall_exit_work | 501 | jne syscall_exit_work |
503 | movl PT_EAX(%esp),%eax /* reload syscall return value */ | 502 | movl PT_EAX(%esp),%eax /* reload syscall return value */ |
504 | jmp sysenter_exit | 503 | jmp sysenter_exit |
@@ -523,8 +522,7 @@ ENTRY(system_call) | |||
523 | SAVE_ALL | 522 | SAVE_ALL |
524 | GET_THREAD_INFO(%ebp) | 523 | GET_THREAD_INFO(%ebp) |
525 | # system call tracing in operation / emulation | 524 | # system call tracing in operation / emulation |
526 | /* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not testb */ | 525 | testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp) |
527 | testw $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp) | ||
528 | jnz syscall_trace_entry | 526 | jnz syscall_trace_entry |
529 | cmpl $(nr_syscalls), %eax | 527 | cmpl $(nr_syscalls), %eax |
530 | jae syscall_badsys | 528 | jae syscall_badsys |
@@ -538,7 +536,7 @@ syscall_exit: | |||
538 | # between sampling and the iret | 536 | # between sampling and the iret |
539 | TRACE_IRQS_OFF | 537 | TRACE_IRQS_OFF |
540 | movl TI_flags(%ebp), %ecx | 538 | movl TI_flags(%ebp), %ecx |
541 | testw $_TIF_ALLWORK_MASK, %cx # current->work | 539 | testl $_TIF_ALLWORK_MASK, %ecx # current->work |
542 | jne syscall_exit_work | 540 | jne syscall_exit_work |
543 | 541 | ||
544 | restore_all: | 542 | restore_all: |
@@ -673,7 +671,7 @@ END(syscall_trace_entry) | |||
673 | # perform syscall exit tracing | 671 | # perform syscall exit tracing |
674 | ALIGN | 672 | ALIGN |
675 | syscall_exit_work: | 673 | syscall_exit_work: |
676 | testb $_TIF_WORK_SYSCALL_EXIT, %cl | 674 | testl $_TIF_WORK_SYSCALL_EXIT, %ecx |
677 | jz work_pending | 675 | jz work_pending |
678 | TRACE_IRQS_ON | 676 | TRACE_IRQS_ON |
679 | ENABLE_INTERRUPTS(CLBR_ANY) # could let syscall_trace_leave() call | 677 | ENABLE_INTERRUPTS(CLBR_ANY) # could let syscall_trace_leave() call |
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index 7ba4621c0dfa..a331ec38af9e 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S | |||
@@ -368,6 +368,7 @@ ENTRY(save_rest) | |||
368 | END(save_rest) | 368 | END(save_rest) |
369 | 369 | ||
370 | /* save complete stack frame */ | 370 | /* save complete stack frame */ |
371 | .pushsection .kprobes.text, "ax" | ||
371 | ENTRY(save_paranoid) | 372 | ENTRY(save_paranoid) |
372 | XCPT_FRAME 1 RDI+8 | 373 | XCPT_FRAME 1 RDI+8 |
373 | cld | 374 | cld |
@@ -396,6 +397,7 @@ ENTRY(save_paranoid) | |||
396 | 1: ret | 397 | 1: ret |
397 | CFI_ENDPROC | 398 | CFI_ENDPROC |
398 | END(save_paranoid) | 399 | END(save_paranoid) |
400 | .popsection | ||
399 | 401 | ||
400 | /* | 402 | /* |
401 | * A newly forked process directly context switches into this address. | 403 | * A newly forked process directly context switches into this address. |
@@ -416,7 +418,6 @@ ENTRY(ret_from_fork) | |||
416 | 418 | ||
417 | GET_THREAD_INFO(%rcx) | 419 | GET_THREAD_INFO(%rcx) |
418 | 420 | ||
419 | CFI_REMEMBER_STATE | ||
420 | RESTORE_REST | 421 | RESTORE_REST |
421 | 422 | ||
422 | testl $3, CS-ARGOFFSET(%rsp) # from kernel_thread? | 423 | testl $3, CS-ARGOFFSET(%rsp) # from kernel_thread? |
@@ -428,7 +429,6 @@ ENTRY(ret_from_fork) | |||
428 | RESTORE_TOP_OF_STACK %rdi, -ARGOFFSET | 429 | RESTORE_TOP_OF_STACK %rdi, -ARGOFFSET |
429 | jmp ret_from_sys_call # go to the SYSRET fastpath | 430 | jmp ret_from_sys_call # go to the SYSRET fastpath |
430 | 431 | ||
431 | CFI_RESTORE_STATE | ||
432 | CFI_ENDPROC | 432 | CFI_ENDPROC |
433 | END(ret_from_fork) | 433 | END(ret_from_fork) |
434 | 434 | ||
diff --git a/arch/x86/kernel/machine_kexec_32.c b/arch/x86/kernel/machine_kexec_32.c index f5fc8c781a62..e7368c1da01d 100644 --- a/arch/x86/kernel/machine_kexec_32.c +++ b/arch/x86/kernel/machine_kexec_32.c | |||
@@ -14,12 +14,12 @@ | |||
14 | #include <linux/ftrace.h> | 14 | #include <linux/ftrace.h> |
15 | #include <linux/suspend.h> | 15 | #include <linux/suspend.h> |
16 | #include <linux/gfp.h> | 16 | #include <linux/gfp.h> |
17 | #include <linux/io.h> | ||
17 | 18 | ||
18 | #include <asm/pgtable.h> | 19 | #include <asm/pgtable.h> |
19 | #include <asm/pgalloc.h> | 20 | #include <asm/pgalloc.h> |
20 | #include <asm/tlbflush.h> | 21 | #include <asm/tlbflush.h> |
21 | #include <asm/mmu_context.h> | 22 | #include <asm/mmu_context.h> |
22 | #include <asm/io.h> | ||
23 | #include <asm/apic.h> | 23 | #include <asm/apic.h> |
24 | #include <asm/cpufeature.h> | 24 | #include <asm/cpufeature.h> |
25 | #include <asm/desc.h> | 25 | #include <asm/desc.h> |
@@ -63,7 +63,7 @@ static void load_segments(void) | |||
63 | "\tmovl %%eax,%%fs\n" | 63 | "\tmovl %%eax,%%fs\n" |
64 | "\tmovl %%eax,%%gs\n" | 64 | "\tmovl %%eax,%%gs\n" |
65 | "\tmovl %%eax,%%ss\n" | 65 | "\tmovl %%eax,%%ss\n" |
66 | ::: "eax", "memory"); | 66 | : : : "eax", "memory"); |
67 | #undef STR | 67 | #undef STR |
68 | #undef __STR | 68 | #undef __STR |
69 | } | 69 | } |
@@ -205,7 +205,8 @@ void machine_kexec(struct kimage *image) | |||
205 | 205 | ||
206 | if (image->preserve_context) { | 206 | if (image->preserve_context) { |
207 | #ifdef CONFIG_X86_IO_APIC | 207 | #ifdef CONFIG_X86_IO_APIC |
208 | /* We need to put APICs in legacy mode so that we can | 208 | /* |
209 | * We need to put APICs in legacy mode so that we can | ||
209 | * get timer interrupts in second kernel. kexec/kdump | 210 | * get timer interrupts in second kernel. kexec/kdump |
210 | * paths already have calls to disable_IO_APIC() in | 211 | * paths already have calls to disable_IO_APIC() in |
211 | * one form or other. kexec jump path also need | 212 | * one form or other. kexec jump path also need |
@@ -227,7 +228,8 @@ void machine_kexec(struct kimage *image) | |||
227 | page_list[PA_SWAP_PAGE] = (page_to_pfn(image->swap_page) | 228 | page_list[PA_SWAP_PAGE] = (page_to_pfn(image->swap_page) |
228 | << PAGE_SHIFT); | 229 | << PAGE_SHIFT); |
229 | 230 | ||
230 | /* The segment registers are funny things, they have both a | 231 | /* |
232 | * The segment registers are funny things, they have both a | ||
231 | * visible and an invisible part. Whenever the visible part is | 233 | * visible and an invisible part. Whenever the visible part is |
232 | * set to a specific selector, the invisible part is loaded | 234 | * set to a specific selector, the invisible part is loaded |
233 | * with from a table in memory. At no other time is the | 235 | * with from a table in memory. At no other time is the |
@@ -237,11 +239,12 @@ void machine_kexec(struct kimage *image) | |||
237 | * segments, before I zap the gdt with an invalid value. | 239 | * segments, before I zap the gdt with an invalid value. |
238 | */ | 240 | */ |
239 | load_segments(); | 241 | load_segments(); |
240 | /* The gdt & idt are now invalid. | 242 | /* |
243 | * The gdt & idt are now invalid. | ||
241 | * If you want to load them you must set up your own idt & gdt. | 244 | * If you want to load them you must set up your own idt & gdt. |
242 | */ | 245 | */ |
243 | set_gdt(phys_to_virt(0),0); | 246 | set_gdt(phys_to_virt(0), 0); |
244 | set_idt(phys_to_virt(0),0); | 247 | set_idt(phys_to_virt(0), 0); |
245 | 248 | ||
246 | /* now call it */ | 249 | /* now call it */ |
247 | image->start = relocate_kernel_ptr((unsigned long)image->head, | 250 | image->start = relocate_kernel_ptr((unsigned long)image->head, |
diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c index 6993d51b7fd8..89cea4d44679 100644 --- a/arch/x86/kernel/machine_kexec_64.c +++ b/arch/x86/kernel/machine_kexec_64.c | |||
@@ -12,11 +12,47 @@ | |||
12 | #include <linux/reboot.h> | 12 | #include <linux/reboot.h> |
13 | #include <linux/numa.h> | 13 | #include <linux/numa.h> |
14 | #include <linux/ftrace.h> | 14 | #include <linux/ftrace.h> |
15 | #include <linux/io.h> | ||
16 | #include <linux/suspend.h> | ||
15 | 17 | ||
16 | #include <asm/pgtable.h> | 18 | #include <asm/pgtable.h> |
17 | #include <asm/tlbflush.h> | 19 | #include <asm/tlbflush.h> |
18 | #include <asm/mmu_context.h> | 20 | #include <asm/mmu_context.h> |
19 | #include <asm/io.h> | 21 | |
22 | static int init_one_level2_page(struct kimage *image, pgd_t *pgd, | ||
23 | unsigned long addr) | ||
24 | { | ||
25 | pud_t *pud; | ||
26 | pmd_t *pmd; | ||
27 | struct page *page; | ||
28 | int result = -ENOMEM; | ||
29 | |||
30 | addr &= PMD_MASK; | ||
31 | pgd += pgd_index(addr); | ||
32 | if (!pgd_present(*pgd)) { | ||
33 | page = kimage_alloc_control_pages(image, 0); | ||
34 | if (!page) | ||
35 | goto out; | ||
36 | pud = (pud_t *)page_address(page); | ||
37 | memset(pud, 0, PAGE_SIZE); | ||
38 | set_pgd(pgd, __pgd(__pa(pud) | _KERNPG_TABLE)); | ||
39 | } | ||
40 | pud = pud_offset(pgd, addr); | ||
41 | if (!pud_present(*pud)) { | ||
42 | page = kimage_alloc_control_pages(image, 0); | ||
43 | if (!page) | ||
44 | goto out; | ||
45 | pmd = (pmd_t *)page_address(page); | ||
46 | memset(pmd, 0, PAGE_SIZE); | ||
47 | set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE)); | ||
48 | } | ||
49 | pmd = pmd_offset(pud, addr); | ||
50 | if (!pmd_present(*pmd)) | ||
51 | set_pmd(pmd, __pmd(addr | __PAGE_KERNEL_LARGE_EXEC)); | ||
52 | result = 0; | ||
53 | out: | ||
54 | return result; | ||
55 | } | ||
20 | 56 | ||
21 | static void init_level2_page(pmd_t *level2p, unsigned long addr) | 57 | static void init_level2_page(pmd_t *level2p, unsigned long addr) |
22 | { | 58 | { |
@@ -83,9 +119,8 @@ static int init_level4_page(struct kimage *image, pgd_t *level4p, | |||
83 | } | 119 | } |
84 | level3p = (pud_t *)page_address(page); | 120 | level3p = (pud_t *)page_address(page); |
85 | result = init_level3_page(image, level3p, addr, last_addr); | 121 | result = init_level3_page(image, level3p, addr, last_addr); |
86 | if (result) { | 122 | if (result) |
87 | goto out; | 123 | goto out; |
88 | } | ||
89 | set_pgd(level4p++, __pgd(__pa(level3p) | _KERNPG_TABLE)); | 124 | set_pgd(level4p++, __pgd(__pa(level3p) | _KERNPG_TABLE)); |
90 | addr += PGDIR_SIZE; | 125 | addr += PGDIR_SIZE; |
91 | } | 126 | } |
@@ -156,6 +191,13 @@ static int init_pgtable(struct kimage *image, unsigned long start_pgtable) | |||
156 | result = init_level4_page(image, level4p, 0, max_pfn << PAGE_SHIFT); | 191 | result = init_level4_page(image, level4p, 0, max_pfn << PAGE_SHIFT); |
157 | if (result) | 192 | if (result) |
158 | return result; | 193 | return result; |
194 | /* | ||
195 | * image->start may be outside 0 ~ max_pfn, for example when | ||
196 | * jump back to original kernel from kexeced kernel | ||
197 | */ | ||
198 | result = init_one_level2_page(image, level4p, image->start); | ||
199 | if (result) | ||
200 | return result; | ||
159 | return init_transition_pgtable(image, level4p); | 201 | return init_transition_pgtable(image, level4p); |
160 | } | 202 | } |
161 | 203 | ||
@@ -229,20 +271,45 @@ void machine_kexec(struct kimage *image) | |||
229 | { | 271 | { |
230 | unsigned long page_list[PAGES_NR]; | 272 | unsigned long page_list[PAGES_NR]; |
231 | void *control_page; | 273 | void *control_page; |
274 | int save_ftrace_enabled; | ||
232 | 275 | ||
233 | tracer_disable(); | 276 | #ifdef CONFIG_KEXEC_JUMP |
277 | if (kexec_image->preserve_context) | ||
278 | save_processor_state(); | ||
279 | #endif | ||
280 | |||
281 | save_ftrace_enabled = __ftrace_enabled_save(); | ||
234 | 282 | ||
235 | /* Interrupts aren't acceptable while we reboot */ | 283 | /* Interrupts aren't acceptable while we reboot */ |
236 | local_irq_disable(); | 284 | local_irq_disable(); |
237 | 285 | ||
286 | if (image->preserve_context) { | ||
287 | #ifdef CONFIG_X86_IO_APIC | ||
288 | /* | ||
289 | * We need to put APICs in legacy mode so that we can | ||
290 | * get timer interrupts in second kernel. kexec/kdump | ||
291 | * paths already have calls to disable_IO_APIC() in | ||
292 | * one form or other. kexec jump path also need | ||
293 | * one. | ||
294 | */ | ||
295 | disable_IO_APIC(); | ||
296 | #endif | ||
297 | } | ||
298 | |||
238 | control_page = page_address(image->control_code_page) + PAGE_SIZE; | 299 | control_page = page_address(image->control_code_page) + PAGE_SIZE; |
239 | memcpy(control_page, relocate_kernel, PAGE_SIZE); | 300 | memcpy(control_page, relocate_kernel, KEXEC_CONTROL_CODE_MAX_SIZE); |
240 | 301 | ||
241 | page_list[PA_CONTROL_PAGE] = virt_to_phys(control_page); | 302 | page_list[PA_CONTROL_PAGE] = virt_to_phys(control_page); |
303 | page_list[VA_CONTROL_PAGE] = (unsigned long)control_page; | ||
242 | page_list[PA_TABLE_PAGE] = | 304 | page_list[PA_TABLE_PAGE] = |
243 | (unsigned long)__pa(page_address(image->control_code_page)); | 305 | (unsigned long)__pa(page_address(image->control_code_page)); |
244 | 306 | ||
245 | /* The segment registers are funny things, they have both a | 307 | if (image->type == KEXEC_TYPE_DEFAULT) |
308 | page_list[PA_SWAP_PAGE] = (page_to_pfn(image->swap_page) | ||
309 | << PAGE_SHIFT); | ||
310 | |||
311 | /* | ||
312 | * The segment registers are funny things, they have both a | ||
246 | * visible and an invisible part. Whenever the visible part is | 313 | * visible and an invisible part. Whenever the visible part is |
247 | * set to a specific selector, the invisible part is loaded | 314 | * set to a specific selector, the invisible part is loaded |
248 | * with from a table in memory. At no other time is the | 315 | * with from a table in memory. At no other time is the |
@@ -252,15 +319,25 @@ void machine_kexec(struct kimage *image) | |||
252 | * segments, before I zap the gdt with an invalid value. | 319 | * segments, before I zap the gdt with an invalid value. |
253 | */ | 320 | */ |
254 | load_segments(); | 321 | load_segments(); |
255 | /* The gdt & idt are now invalid. | 322 | /* |
323 | * The gdt & idt are now invalid. | ||
256 | * If you want to load them you must set up your own idt & gdt. | 324 | * If you want to load them you must set up your own idt & gdt. |
257 | */ | 325 | */ |
258 | set_gdt(phys_to_virt(0),0); | 326 | set_gdt(phys_to_virt(0), 0); |
259 | set_idt(phys_to_virt(0),0); | 327 | set_idt(phys_to_virt(0), 0); |
260 | 328 | ||
261 | /* now call it */ | 329 | /* now call it */ |
262 | relocate_kernel((unsigned long)image->head, (unsigned long)page_list, | 330 | image->start = relocate_kernel((unsigned long)image->head, |
263 | image->start); | 331 | (unsigned long)page_list, |
332 | image->start, | ||
333 | image->preserve_context); | ||
334 | |||
335 | #ifdef CONFIG_KEXEC_JUMP | ||
336 | if (kexec_image->preserve_context) | ||
337 | restore_processor_state(); | ||
338 | #endif | ||
339 | |||
340 | __ftrace_enabled_restore(save_ftrace_enabled); | ||
264 | } | 341 | } |
265 | 342 | ||
266 | void arch_crash_save_vmcoreinfo(void) | 343 | void arch_crash_save_vmcoreinfo(void) |
diff --git a/arch/x86/kernel/quirks.c b/arch/x86/kernel/quirks.c index 309949e9e1c1..6a5a2970f4c5 100644 --- a/arch/x86/kernel/quirks.c +++ b/arch/x86/kernel/quirks.c | |||
@@ -74,8 +74,7 @@ static void ich_force_hpet_resume(void) | |||
74 | if (!force_hpet_address) | 74 | if (!force_hpet_address) |
75 | return; | 75 | return; |
76 | 76 | ||
77 | if (rcba_base == NULL) | 77 | BUG_ON(rcba_base == NULL); |
78 | BUG(); | ||
79 | 78 | ||
80 | /* read the Function Disable register, dword mode only */ | 79 | /* read the Function Disable register, dword mode only */ |
81 | val = readl(rcba_base + 0x3404); | 80 | val = readl(rcba_base + 0x3404); |
diff --git a/arch/x86/kernel/relocate_kernel_32.S b/arch/x86/kernel/relocate_kernel_32.S index 2064d0aa8d28..41235531b11c 100644 --- a/arch/x86/kernel/relocate_kernel_32.S +++ b/arch/x86/kernel/relocate_kernel_32.S | |||
@@ -17,7 +17,8 @@ | |||
17 | 17 | ||
18 | #define PTR(x) (x << 2) | 18 | #define PTR(x) (x << 2) |
19 | 19 | ||
20 | /* control_page + KEXEC_CONTROL_CODE_MAX_SIZE | 20 | /* |
21 | * control_page + KEXEC_CONTROL_CODE_MAX_SIZE | ||
21 | * ~ control_page + PAGE_SIZE are used as data storage and stack for | 22 | * ~ control_page + PAGE_SIZE are used as data storage and stack for |
22 | * jumping back | 23 | * jumping back |
23 | */ | 24 | */ |
@@ -76,8 +77,10 @@ relocate_kernel: | |||
76 | movl %eax, CP_PA_SWAP_PAGE(%edi) | 77 | movl %eax, CP_PA_SWAP_PAGE(%edi) |
77 | movl %ebx, CP_PA_BACKUP_PAGES_MAP(%edi) | 78 | movl %ebx, CP_PA_BACKUP_PAGES_MAP(%edi) |
78 | 79 | ||
79 | /* get physical address of control page now */ | 80 | /* |
80 | /* this is impossible after page table switch */ | 81 | * get physical address of control page now |
82 | * this is impossible after page table switch | ||
83 | */ | ||
81 | movl PTR(PA_CONTROL_PAGE)(%ebp), %edi | 84 | movl PTR(PA_CONTROL_PAGE)(%ebp), %edi |
82 | 85 | ||
83 | /* switch to new set of page tables */ | 86 | /* switch to new set of page tables */ |
@@ -97,7 +100,8 @@ identity_mapped: | |||
97 | /* store the start address on the stack */ | 100 | /* store the start address on the stack */ |
98 | pushl %edx | 101 | pushl %edx |
99 | 102 | ||
100 | /* Set cr0 to a known state: | 103 | /* |
104 | * Set cr0 to a known state: | ||
101 | * - Paging disabled | 105 | * - Paging disabled |
102 | * - Alignment check disabled | 106 | * - Alignment check disabled |
103 | * - Write protect disabled | 107 | * - Write protect disabled |
@@ -113,7 +117,8 @@ identity_mapped: | |||
113 | /* clear cr4 if applicable */ | 117 | /* clear cr4 if applicable */ |
114 | testl %ecx, %ecx | 118 | testl %ecx, %ecx |
115 | jz 1f | 119 | jz 1f |
116 | /* Set cr4 to a known state: | 120 | /* |
121 | * Set cr4 to a known state: | ||
117 | * Setting everything to zero seems safe. | 122 | * Setting everything to zero seems safe. |
118 | */ | 123 | */ |
119 | xorl %eax, %eax | 124 | xorl %eax, %eax |
@@ -132,15 +137,18 @@ identity_mapped: | |||
132 | call swap_pages | 137 | call swap_pages |
133 | addl $8, %esp | 138 | addl $8, %esp |
134 | 139 | ||
135 | /* To be certain of avoiding problems with self-modifying code | 140 | /* |
141 | * To be certain of avoiding problems with self-modifying code | ||
136 | * I need to execute a serializing instruction here. | 142 | * I need to execute a serializing instruction here. |
137 | * So I flush the TLB, it's handy, and not processor dependent. | 143 | * So I flush the TLB, it's handy, and not processor dependent. |
138 | */ | 144 | */ |
139 | xorl %eax, %eax | 145 | xorl %eax, %eax |
140 | movl %eax, %cr3 | 146 | movl %eax, %cr3 |
141 | 147 | ||
142 | /* set all of the registers to known values */ | 148 | /* |
143 | /* leave %esp alone */ | 149 | * set all of the registers to known values |
150 | * leave %esp alone | ||
151 | */ | ||
144 | 152 | ||
145 | testl %esi, %esi | 153 | testl %esi, %esi |
146 | jnz 1f | 154 | jnz 1f |
diff --git a/arch/x86/kernel/relocate_kernel_64.S b/arch/x86/kernel/relocate_kernel_64.S index d32cfb27a479..4de8f5b3d476 100644 --- a/arch/x86/kernel/relocate_kernel_64.S +++ b/arch/x86/kernel/relocate_kernel_64.S | |||
@@ -19,29 +19,77 @@ | |||
19 | #define PTR(x) (x << 3) | 19 | #define PTR(x) (x << 3) |
20 | #define PAGE_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY) | 20 | #define PAGE_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY) |
21 | 21 | ||
22 | /* | ||
23 | * control_page + KEXEC_CONTROL_CODE_MAX_SIZE | ||
24 | * ~ control_page + PAGE_SIZE are used as data storage and stack for | ||
25 | * jumping back | ||
26 | */ | ||
27 | #define DATA(offset) (KEXEC_CONTROL_CODE_MAX_SIZE+(offset)) | ||
28 | |||
29 | /* Minimal CPU state */ | ||
30 | #define RSP DATA(0x0) | ||
31 | #define CR0 DATA(0x8) | ||
32 | #define CR3 DATA(0x10) | ||
33 | #define CR4 DATA(0x18) | ||
34 | |||
35 | /* other data */ | ||
36 | #define CP_PA_TABLE_PAGE DATA(0x20) | ||
37 | #define CP_PA_SWAP_PAGE DATA(0x28) | ||
38 | #define CP_PA_BACKUP_PAGES_MAP DATA(0x30) | ||
39 | |||
22 | .text | 40 | .text |
23 | .align PAGE_SIZE | 41 | .align PAGE_SIZE |
24 | .code64 | 42 | .code64 |
25 | .globl relocate_kernel | 43 | .globl relocate_kernel |
26 | relocate_kernel: | 44 | relocate_kernel: |
27 | /* %rdi indirection_page | 45 | /* |
46 | * %rdi indirection_page | ||
28 | * %rsi page_list | 47 | * %rsi page_list |
29 | * %rdx start address | 48 | * %rdx start address |
49 | * %rcx preserve_context | ||
30 | */ | 50 | */ |
31 | 51 | ||
52 | /* Save the CPU context, used for jumping back */ | ||
53 | pushq %rbx | ||
54 | pushq %rbp | ||
55 | pushq %r12 | ||
56 | pushq %r13 | ||
57 | pushq %r14 | ||
58 | pushq %r15 | ||
59 | pushf | ||
60 | |||
61 | movq PTR(VA_CONTROL_PAGE)(%rsi), %r11 | ||
62 | movq %rsp, RSP(%r11) | ||
63 | movq %cr0, %rax | ||
64 | movq %rax, CR0(%r11) | ||
65 | movq %cr3, %rax | ||
66 | movq %rax, CR3(%r11) | ||
67 | movq %cr4, %rax | ||
68 | movq %rax, CR4(%r11) | ||
69 | |||
32 | /* zero out flags, and disable interrupts */ | 70 | /* zero out flags, and disable interrupts */ |
33 | pushq $0 | 71 | pushq $0 |
34 | popfq | 72 | popfq |
35 | 73 | ||
36 | /* get physical address of control page now */ | 74 | /* |
37 | /* this is impossible after page table switch */ | 75 | * get physical address of control page now |
76 | * this is impossible after page table switch | ||
77 | */ | ||
38 | movq PTR(PA_CONTROL_PAGE)(%rsi), %r8 | 78 | movq PTR(PA_CONTROL_PAGE)(%rsi), %r8 |
39 | 79 | ||
40 | /* get physical address of page table now too */ | 80 | /* get physical address of page table now too */ |
41 | movq PTR(PA_TABLE_PAGE)(%rsi), %rcx | 81 | movq PTR(PA_TABLE_PAGE)(%rsi), %r9 |
82 | |||
83 | /* get physical address of swap page now */ | ||
84 | movq PTR(PA_SWAP_PAGE)(%rsi), %r10 | ||
85 | |||
86 | /* save some information for jumping back */ | ||
87 | movq %r9, CP_PA_TABLE_PAGE(%r11) | ||
88 | movq %r10, CP_PA_SWAP_PAGE(%r11) | ||
89 | movq %rdi, CP_PA_BACKUP_PAGES_MAP(%r11) | ||
42 | 90 | ||
43 | /* Switch to the identity mapped page tables */ | 91 | /* Switch to the identity mapped page tables */ |
44 | movq %rcx, %cr3 | 92 | movq %r9, %cr3 |
45 | 93 | ||
46 | /* setup a new stack at the end of the physical control page */ | 94 | /* setup a new stack at the end of the physical control page */ |
47 | lea PAGE_SIZE(%r8), %rsp | 95 | lea PAGE_SIZE(%r8), %rsp |
@@ -55,7 +103,8 @@ identity_mapped: | |||
55 | /* store the start address on the stack */ | 103 | /* store the start address on the stack */ |
56 | pushq %rdx | 104 | pushq %rdx |
57 | 105 | ||
58 | /* Set cr0 to a known state: | 106 | /* |
107 | * Set cr0 to a known state: | ||
59 | * - Paging enabled | 108 | * - Paging enabled |
60 | * - Alignment check disabled | 109 | * - Alignment check disabled |
61 | * - Write protect disabled | 110 | * - Write protect disabled |
@@ -68,7 +117,8 @@ identity_mapped: | |||
68 | orl $(X86_CR0_PG | X86_CR0_PE), %eax | 117 | orl $(X86_CR0_PG | X86_CR0_PE), %eax |
69 | movq %rax, %cr0 | 118 | movq %rax, %cr0 |
70 | 119 | ||
71 | /* Set cr4 to a known state: | 120 | /* |
121 | * Set cr4 to a known state: | ||
72 | * - physical address extension enabled | 122 | * - physical address extension enabled |
73 | */ | 123 | */ |
74 | movq $X86_CR4_PAE, %rax | 124 | movq $X86_CR4_PAE, %rax |
@@ -78,9 +128,87 @@ identity_mapped: | |||
78 | 1: | 128 | 1: |
79 | 129 | ||
80 | /* Flush the TLB (needed?) */ | 130 | /* Flush the TLB (needed?) */ |
81 | movq %rcx, %cr3 | 131 | movq %r9, %cr3 |
132 | |||
133 | movq %rcx, %r11 | ||
134 | call swap_pages | ||
135 | |||
136 | /* | ||
137 | * To be certain of avoiding problems with self-modifying code | ||
138 | * I need to execute a serializing instruction here. | ||
139 | * So I flush the TLB by reloading %cr3 here, it's handy, | ||
140 | * and not processor dependent. | ||
141 | */ | ||
142 | movq %cr3, %rax | ||
143 | movq %rax, %cr3 | ||
144 | |||
145 | /* | ||
146 | * set all of the registers to known values | ||
147 | * leave %rsp alone | ||
148 | */ | ||
149 | |||
150 | testq %r11, %r11 | ||
151 | jnz 1f | ||
152 | xorq %rax, %rax | ||
153 | xorq %rbx, %rbx | ||
154 | xorq %rcx, %rcx | ||
155 | xorq %rdx, %rdx | ||
156 | xorq %rsi, %rsi | ||
157 | xorq %rdi, %rdi | ||
158 | xorq %rbp, %rbp | ||
159 | xorq %r8, %r8 | ||
160 | xorq %r9, %r9 | ||
161 | xorq %r10, %r9 | ||
162 | xorq %r11, %r11 | ||
163 | xorq %r12, %r12 | ||
164 | xorq %r13, %r13 | ||
165 | xorq %r14, %r14 | ||
166 | xorq %r15, %r15 | ||
167 | |||
168 | ret | ||
169 | |||
170 | 1: | ||
171 | popq %rdx | ||
172 | leaq PAGE_SIZE(%r10), %rsp | ||
173 | call *%rdx | ||
174 | |||
175 | /* get the re-entry point of the peer system */ | ||
176 | movq 0(%rsp), %rbp | ||
177 | call 1f | ||
178 | 1: | ||
179 | popq %r8 | ||
180 | subq $(1b - relocate_kernel), %r8 | ||
181 | movq CP_PA_SWAP_PAGE(%r8), %r10 | ||
182 | movq CP_PA_BACKUP_PAGES_MAP(%r8), %rdi | ||
183 | movq CP_PA_TABLE_PAGE(%r8), %rax | ||
184 | movq %rax, %cr3 | ||
185 | lea PAGE_SIZE(%r8), %rsp | ||
186 | call swap_pages | ||
187 | movq $virtual_mapped, %rax | ||
188 | pushq %rax | ||
189 | ret | ||
190 | |||
191 | virtual_mapped: | ||
192 | movq RSP(%r8), %rsp | ||
193 | movq CR4(%r8), %rax | ||
194 | movq %rax, %cr4 | ||
195 | movq CR3(%r8), %rax | ||
196 | movq CR0(%r8), %r8 | ||
197 | movq %rax, %cr3 | ||
198 | movq %r8, %cr0 | ||
199 | movq %rbp, %rax | ||
200 | |||
201 | popf | ||
202 | popq %r15 | ||
203 | popq %r14 | ||
204 | popq %r13 | ||
205 | popq %r12 | ||
206 | popq %rbp | ||
207 | popq %rbx | ||
208 | ret | ||
82 | 209 | ||
83 | /* Do the copies */ | 210 | /* Do the copies */ |
211 | swap_pages: | ||
84 | movq %rdi, %rcx /* Put the page_list in %rcx */ | 212 | movq %rdi, %rcx /* Put the page_list in %rcx */ |
85 | xorq %rdi, %rdi | 213 | xorq %rdi, %rdi |
86 | xorq %rsi, %rsi | 214 | xorq %rsi, %rsi |
@@ -112,36 +240,27 @@ identity_mapped: | |||
112 | movq %rcx, %rsi /* For ever source page do a copy */ | 240 | movq %rcx, %rsi /* For ever source page do a copy */ |
113 | andq $0xfffffffffffff000, %rsi | 241 | andq $0xfffffffffffff000, %rsi |
114 | 242 | ||
243 | movq %rdi, %rdx | ||
244 | movq %rsi, %rax | ||
245 | |||
246 | movq %r10, %rdi | ||
115 | movq $512, %rcx | 247 | movq $512, %rcx |
116 | rep ; movsq | 248 | rep ; movsq |
117 | jmp 0b | ||
118 | 3: | ||
119 | |||
120 | /* To be certain of avoiding problems with self-modifying code | ||
121 | * I need to execute a serializing instruction here. | ||
122 | * So I flush the TLB by reloading %cr3 here, it's handy, | ||
123 | * and not processor dependent. | ||
124 | */ | ||
125 | movq %cr3, %rax | ||
126 | movq %rax, %cr3 | ||
127 | 249 | ||
128 | /* set all of the registers to known values */ | 250 | movq %rax, %rdi |
129 | /* leave %rsp alone */ | 251 | movq %rdx, %rsi |
252 | movq $512, %rcx | ||
253 | rep ; movsq | ||
130 | 254 | ||
131 | xorq %rax, %rax | 255 | movq %rdx, %rdi |
132 | xorq %rbx, %rbx | 256 | movq %r10, %rsi |
133 | xorq %rcx, %rcx | 257 | movq $512, %rcx |
134 | xorq %rdx, %rdx | 258 | rep ; movsq |
135 | xorq %rsi, %rsi | ||
136 | xorq %rdi, %rdi | ||
137 | xorq %rbp, %rbp | ||
138 | xorq %r8, %r8 | ||
139 | xorq %r9, %r9 | ||
140 | xorq %r10, %r9 | ||
141 | xorq %r11, %r11 | ||
142 | xorq %r12, %r12 | ||
143 | xorq %r13, %r13 | ||
144 | xorq %r14, %r14 | ||
145 | xorq %r15, %r15 | ||
146 | 259 | ||
260 | lea PAGE_SIZE(%rax), %rsi | ||
261 | jmp 0b | ||
262 | 3: | ||
147 | ret | 263 | ret |
264 | |||
265 | .globl kexec_control_code_size | ||
266 | .set kexec_control_code_size, . - relocate_kernel | ||
diff --git a/arch/x86/kernel/visws_quirks.c b/arch/x86/kernel/visws_quirks.c index 191a876e9e87..31ffc24eec4d 100644 --- a/arch/x86/kernel/visws_quirks.c +++ b/arch/x86/kernel/visws_quirks.c | |||
@@ -578,7 +578,7 @@ static struct irq_chip piix4_virtual_irq_type = { | |||
578 | static irqreturn_t piix4_master_intr(int irq, void *dev_id) | 578 | static irqreturn_t piix4_master_intr(int irq, void *dev_id) |
579 | { | 579 | { |
580 | int realirq; | 580 | int realirq; |
581 | irq_desc_t *desc; | 581 | struct irq_desc *desc; |
582 | unsigned long flags; | 582 | unsigned long flags; |
583 | 583 | ||
584 | spin_lock_irqsave(&i8259A_lock, flags); | 584 | spin_lock_irqsave(&i8259A_lock, flags); |
diff --git a/arch/x86/kernel/vmlinux_64.lds.S b/arch/x86/kernel/vmlinux_64.lds.S index fbfced6f6800..5bf54e40c6ef 100644 --- a/arch/x86/kernel/vmlinux_64.lds.S +++ b/arch/x86/kernel/vmlinux_64.lds.S | |||
@@ -275,3 +275,10 @@ ASSERT((_end - _text <= KERNEL_IMAGE_SIZE), | |||
275 | ASSERT((per_cpu__irq_stack_union == 0), | 275 | ASSERT((per_cpu__irq_stack_union == 0), |
276 | "irq_stack_union is not at start of per-cpu area"); | 276 | "irq_stack_union is not at start of per-cpu area"); |
277 | #endif | 277 | #endif |
278 | |||
279 | #ifdef CONFIG_KEXEC | ||
280 | #include <asm/kexec.h> | ||
281 | |||
282 | ASSERT(kexec_control_code_size <= KEXEC_CONTROL_CODE_MAX_SIZE, | ||
283 | "kexec control code size is too big") | ||
284 | #endif | ||
diff --git a/arch/x86/lib/memcpy_64.S b/arch/x86/lib/memcpy_64.S index c22981fa2f3a..ad5441ed1b57 100644 --- a/arch/x86/lib/memcpy_64.S +++ b/arch/x86/lib/memcpy_64.S | |||
@@ -1,30 +1,38 @@ | |||
1 | /* Copyright 2002 Andi Kleen */ | 1 | /* Copyright 2002 Andi Kleen */ |
2 | 2 | ||
3 | #include <linux/linkage.h> | 3 | #include <linux/linkage.h> |
4 | #include <asm/dwarf2.h> | 4 | |
5 | #include <asm/cpufeature.h> | 5 | #include <asm/cpufeature.h> |
6 | #include <asm/dwarf2.h> | ||
6 | 7 | ||
7 | /* | 8 | /* |
8 | * memcpy - Copy a memory block. | 9 | * memcpy - Copy a memory block. |
9 | * | 10 | * |
10 | * Input: | 11 | * Input: |
11 | * rdi destination | 12 | * rdi destination |
12 | * rsi source | 13 | * rsi source |
13 | * rdx count | 14 | * rdx count |
14 | * | 15 | * |
15 | * Output: | 16 | * Output: |
16 | * rax original destination | 17 | * rax original destination |
17 | */ | 18 | */ |
18 | 19 | ||
20 | /* | ||
21 | * memcpy_c() - fast string ops (REP MOVSQ) based variant. | ||
22 | * | ||
23 | * Calls to this get patched into the kernel image via the | ||
24 | * alternative instructions framework: | ||
25 | */ | ||
19 | ALIGN | 26 | ALIGN |
20 | memcpy_c: | 27 | memcpy_c: |
21 | CFI_STARTPROC | 28 | CFI_STARTPROC |
22 | movq %rdi,%rax | 29 | movq %rdi, %rax |
23 | movl %edx,%ecx | 30 | |
24 | shrl $3,%ecx | 31 | movl %edx, %ecx |
25 | andl $7,%edx | 32 | shrl $3, %ecx |
33 | andl $7, %edx | ||
26 | rep movsq | 34 | rep movsq |
27 | movl %edx,%ecx | 35 | movl %edx, %ecx |
28 | rep movsb | 36 | rep movsb |
29 | ret | 37 | ret |
30 | CFI_ENDPROC | 38 | CFI_ENDPROC |
@@ -33,99 +41,110 @@ ENDPROC(memcpy_c) | |||
33 | ENTRY(__memcpy) | 41 | ENTRY(__memcpy) |
34 | ENTRY(memcpy) | 42 | ENTRY(memcpy) |
35 | CFI_STARTPROC | 43 | CFI_STARTPROC |
36 | pushq %rbx | ||
37 | CFI_ADJUST_CFA_OFFSET 8 | ||
38 | CFI_REL_OFFSET rbx, 0 | ||
39 | movq %rdi,%rax | ||
40 | 44 | ||
41 | movl %edx,%ecx | 45 | /* |
42 | shrl $6,%ecx | 46 | * Put the number of full 64-byte blocks into %ecx. |
47 | * Tail portion is handled at the end: | ||
48 | */ | ||
49 | movq %rdi, %rax | ||
50 | movl %edx, %ecx | ||
51 | shrl $6, %ecx | ||
43 | jz .Lhandle_tail | 52 | jz .Lhandle_tail |
44 | 53 | ||
45 | .p2align 4 | 54 | .p2align 4 |
46 | .Lloop_64: | 55 | .Lloop_64: |
56 | /* | ||
57 | * We decrement the loop index here - and the zero-flag is | ||
58 | * checked at the end of the loop (instructions inbetween do | ||
59 | * not change the zero flag): | ||
60 | */ | ||
47 | decl %ecx | 61 | decl %ecx |
48 | 62 | ||
49 | movq (%rsi),%r11 | 63 | /* |
50 | movq 8(%rsi),%r8 | 64 | * Move in blocks of 4x16 bytes: |
65 | */ | ||
66 | movq 0*8(%rsi), %r11 | ||
67 | movq 1*8(%rsi), %r8 | ||
68 | movq %r11, 0*8(%rdi) | ||
69 | movq %r8, 1*8(%rdi) | ||
51 | 70 | ||
52 | movq %r11,(%rdi) | 71 | movq 2*8(%rsi), %r9 |
53 | movq %r8,1*8(%rdi) | 72 | movq 3*8(%rsi), %r10 |
73 | movq %r9, 2*8(%rdi) | ||
74 | movq %r10, 3*8(%rdi) | ||
54 | 75 | ||
55 | movq 2*8(%rsi),%r9 | 76 | movq 4*8(%rsi), %r11 |
56 | movq 3*8(%rsi),%r10 | 77 | movq 5*8(%rsi), %r8 |
78 | movq %r11, 4*8(%rdi) | ||
79 | movq %r8, 5*8(%rdi) | ||
57 | 80 | ||
58 | movq %r9,2*8(%rdi) | 81 | movq 6*8(%rsi), %r9 |
59 | movq %r10,3*8(%rdi) | 82 | movq 7*8(%rsi), %r10 |
83 | movq %r9, 6*8(%rdi) | ||
84 | movq %r10, 7*8(%rdi) | ||
60 | 85 | ||
61 | movq 4*8(%rsi),%r11 | 86 | leaq 64(%rsi), %rsi |
62 | movq 5*8(%rsi),%r8 | 87 | leaq 64(%rdi), %rdi |
63 | 88 | ||
64 | movq %r11,4*8(%rdi) | ||
65 | movq %r8,5*8(%rdi) | ||
66 | |||
67 | movq 6*8(%rsi),%r9 | ||
68 | movq 7*8(%rsi),%r10 | ||
69 | |||
70 | movq %r9,6*8(%rdi) | ||
71 | movq %r10,7*8(%rdi) | ||
72 | |||
73 | leaq 64(%rsi),%rsi | ||
74 | leaq 64(%rdi),%rdi | ||
75 | jnz .Lloop_64 | 89 | jnz .Lloop_64 |
76 | 90 | ||
77 | .Lhandle_tail: | 91 | .Lhandle_tail: |
78 | movl %edx,%ecx | 92 | movl %edx, %ecx |
79 | andl $63,%ecx | 93 | andl $63, %ecx |
80 | shrl $3,%ecx | 94 | shrl $3, %ecx |
81 | jz .Lhandle_7 | 95 | jz .Lhandle_7 |
96 | |||
82 | .p2align 4 | 97 | .p2align 4 |
83 | .Lloop_8: | 98 | .Lloop_8: |
84 | decl %ecx | 99 | decl %ecx |
85 | movq (%rsi),%r8 | 100 | movq (%rsi), %r8 |
86 | movq %r8,(%rdi) | 101 | movq %r8, (%rdi) |
87 | leaq 8(%rdi),%rdi | 102 | leaq 8(%rdi), %rdi |
88 | leaq 8(%rsi),%rsi | 103 | leaq 8(%rsi), %rsi |
89 | jnz .Lloop_8 | 104 | jnz .Lloop_8 |
90 | 105 | ||
91 | .Lhandle_7: | 106 | .Lhandle_7: |
92 | movl %edx,%ecx | 107 | movl %edx, %ecx |
93 | andl $7,%ecx | 108 | andl $7, %ecx |
94 | jz .Lende | 109 | jz .Lend |
110 | |||
95 | .p2align 4 | 111 | .p2align 4 |
96 | .Lloop_1: | 112 | .Lloop_1: |
97 | movb (%rsi),%r8b | 113 | movb (%rsi), %r8b |
98 | movb %r8b,(%rdi) | 114 | movb %r8b, (%rdi) |
99 | incq %rdi | 115 | incq %rdi |
100 | incq %rsi | 116 | incq %rsi |
101 | decl %ecx | 117 | decl %ecx |
102 | jnz .Lloop_1 | 118 | jnz .Lloop_1 |
103 | 119 | ||
104 | .Lende: | 120 | .Lend: |
105 | popq %rbx | ||
106 | CFI_ADJUST_CFA_OFFSET -8 | ||
107 | CFI_RESTORE rbx | ||
108 | ret | 121 | ret |
109 | .Lfinal: | ||
110 | CFI_ENDPROC | 122 | CFI_ENDPROC |
111 | ENDPROC(memcpy) | 123 | ENDPROC(memcpy) |
112 | ENDPROC(__memcpy) | 124 | ENDPROC(__memcpy) |
113 | 125 | ||
114 | /* Some CPUs run faster using the string copy instructions. | 126 | /* |
115 | It is also a lot simpler. Use this when possible */ | 127 | * Some CPUs run faster using the string copy instructions. |
128 | * It is also a lot simpler. Use this when possible: | ||
129 | */ | ||
116 | 130 | ||
117 | .section .altinstr_replacement,"ax" | 131 | .section .altinstr_replacement, "ax" |
118 | 1: .byte 0xeb /* jmp <disp8> */ | 132 | 1: .byte 0xeb /* jmp <disp8> */ |
119 | .byte (memcpy_c - memcpy) - (2f - 1b) /* offset */ | 133 | .byte (memcpy_c - memcpy) - (2f - 1b) /* offset */ |
120 | 2: | 134 | 2: |
121 | .previous | 135 | .previous |
122 | .section .altinstructions,"a" | 136 | |
137 | .section .altinstructions, "a" | ||
123 | .align 8 | 138 | .align 8 |
124 | .quad memcpy | 139 | .quad memcpy |
125 | .quad 1b | 140 | .quad 1b |
126 | .byte X86_FEATURE_REP_GOOD | 141 | .byte X86_FEATURE_REP_GOOD |
127 | /* Replace only beginning, memcpy is used to apply alternatives, so it | 142 | |
128 | * is silly to overwrite itself with nops - reboot is only outcome... */ | 143 | /* |
144 | * Replace only beginning, memcpy is used to apply alternatives, | ||
145 | * so it is silly to overwrite itself with nops - reboot is the | ||
146 | * only outcome... | ||
147 | */ | ||
129 | .byte 2b - 1b | 148 | .byte 2b - 1b |
130 | .byte 2b - 1b | 149 | .byte 2b - 1b |
131 | .previous | 150 | .previous |
diff --git a/arch/x86/mm/highmem_32.c b/arch/x86/mm/highmem_32.c index d11745334a67..f256e73542d7 100644 --- a/arch/x86/mm/highmem_32.c +++ b/arch/x86/mm/highmem_32.c | |||
@@ -121,23 +121,30 @@ void kunmap_atomic(void *kvaddr, enum km_type type) | |||
121 | pagefault_enable(); | 121 | pagefault_enable(); |
122 | } | 122 | } |
123 | 123 | ||
124 | /* This is the same as kmap_atomic() but can map memory that doesn't | 124 | void *kmap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot) |
125 | * have a struct page associated with it. | ||
126 | */ | ||
127 | void *kmap_atomic_pfn(unsigned long pfn, enum km_type type) | ||
128 | { | 125 | { |
129 | enum fixed_addresses idx; | 126 | enum fixed_addresses idx; |
130 | unsigned long vaddr; | 127 | unsigned long vaddr; |
131 | 128 | ||
132 | pagefault_disable(); | 129 | pagefault_disable(); |
133 | 130 | ||
134 | idx = type + KM_TYPE_NR*smp_processor_id(); | 131 | debug_kmap_atomic_prot(type); |
132 | |||
133 | idx = type + KM_TYPE_NR * smp_processor_id(); | ||
135 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); | 134 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); |
136 | set_pte(kmap_pte-idx, pfn_pte(pfn, kmap_prot)); | 135 | set_pte(kmap_pte - idx, pfn_pte(pfn, prot)); |
137 | arch_flush_lazy_mmu_mode(); | 136 | arch_flush_lazy_mmu_mode(); |
138 | 137 | ||
139 | return (void*) vaddr; | 138 | return (void*) vaddr; |
140 | } | 139 | } |
140 | |||
141 | /* This is the same as kmap_atomic() but can map memory that doesn't | ||
142 | * have a struct page associated with it. | ||
143 | */ | ||
144 | void *kmap_atomic_pfn(unsigned long pfn, enum km_type type) | ||
145 | { | ||
146 | return kmap_atomic_prot_pfn(pfn, type, kmap_prot); | ||
147 | } | ||
141 | EXPORT_SYMBOL_GPL(kmap_atomic_pfn); /* temporarily in use by i915 GEM until vmap */ | 148 | EXPORT_SYMBOL_GPL(kmap_atomic_pfn); /* temporarily in use by i915 GEM until vmap */ |
142 | 149 | ||
143 | struct page *kmap_atomic_to_page(void *ptr) | 150 | struct page *kmap_atomic_to_page(void *ptr) |
diff --git a/arch/x86/mm/iomap_32.c b/arch/x86/mm/iomap_32.c index 04102d42ff42..592984e5496b 100644 --- a/arch/x86/mm/iomap_32.c +++ b/arch/x86/mm/iomap_32.c | |||
@@ -18,6 +18,7 @@ | |||
18 | 18 | ||
19 | #include <asm/iomap.h> | 19 | #include <asm/iomap.h> |
20 | #include <asm/pat.h> | 20 | #include <asm/pat.h> |
21 | #include <asm/highmem.h> | ||
21 | #include <linux/module.h> | 22 | #include <linux/module.h> |
22 | 23 | ||
23 | int is_io_mapping_possible(resource_size_t base, unsigned long size) | 24 | int is_io_mapping_possible(resource_size_t base, unsigned long size) |
@@ -36,11 +37,6 @@ EXPORT_SYMBOL_GPL(is_io_mapping_possible); | |||
36 | void * | 37 | void * |
37 | iomap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot) | 38 | iomap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot) |
38 | { | 39 | { |
39 | enum fixed_addresses idx; | ||
40 | unsigned long vaddr; | ||
41 | |||
42 | pagefault_disable(); | ||
43 | |||
44 | /* | 40 | /* |
45 | * For non-PAT systems, promote PAGE_KERNEL_WC to PAGE_KERNEL_UC_MINUS. | 41 | * For non-PAT systems, promote PAGE_KERNEL_WC to PAGE_KERNEL_UC_MINUS. |
46 | * PAGE_KERNEL_WC maps to PWT, which translates to uncached if the | 42 | * PAGE_KERNEL_WC maps to PWT, which translates to uncached if the |
@@ -50,12 +46,7 @@ iomap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot) | |||
50 | if (!pat_enabled && pgprot_val(prot) == pgprot_val(PAGE_KERNEL_WC)) | 46 | if (!pat_enabled && pgprot_val(prot) == pgprot_val(PAGE_KERNEL_WC)) |
51 | prot = PAGE_KERNEL_UC_MINUS; | 47 | prot = PAGE_KERNEL_UC_MINUS; |
52 | 48 | ||
53 | idx = type + KM_TYPE_NR*smp_processor_id(); | 49 | return kmap_atomic_prot_pfn(pfn, type, prot); |
54 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); | ||
55 | set_pte(kmap_pte-idx, pfn_pte(pfn, prot)); | ||
56 | arch_flush_lazy_mmu_mode(); | ||
57 | |||
58 | return (void*) vaddr; | ||
59 | } | 50 | } |
60 | EXPORT_SYMBOL_GPL(iomap_atomic_prot_pfn); | 51 | EXPORT_SYMBOL_GPL(iomap_atomic_prot_pfn); |
61 | 52 | ||
diff --git a/arch/x86/mm/kmmio.c b/arch/x86/mm/kmmio.c index 6a518dd08a36..4f115e00486b 100644 --- a/arch/x86/mm/kmmio.c +++ b/arch/x86/mm/kmmio.c | |||
@@ -310,7 +310,7 @@ static int post_kmmio_handler(unsigned long condition, struct pt_regs *regs) | |||
310 | struct kmmio_context *ctx = &get_cpu_var(kmmio_ctx); | 310 | struct kmmio_context *ctx = &get_cpu_var(kmmio_ctx); |
311 | 311 | ||
312 | if (!ctx->active) { | 312 | if (!ctx->active) { |
313 | pr_warning("kmmio: spurious debug trap on CPU %d.\n", | 313 | pr_debug("kmmio: spurious debug trap on CPU %d.\n", |
314 | smp_processor_id()); | 314 | smp_processor_id()); |
315 | goto out; | 315 | goto out; |
316 | } | 316 | } |