diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-22 10:38:37 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-22 10:38:37 -0500 |
commit | fcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch) | |
tree | a57612d1888735a2ec7972891b68c1ac5ec8faea /arch/x86/kernel | |
parent | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff) |
Diffstat (limited to 'arch/x86/kernel')
22 files changed, 1832 insertions, 0 deletions
diff --git a/arch/x86/kernel/acpi/realmode/Makefile b/arch/x86/kernel/acpi/realmode/Makefile new file mode 100644 index 00000000000..6a564ac67ef --- /dev/null +++ b/arch/x86/kernel/acpi/realmode/Makefile | |||
@@ -0,0 +1,59 @@ | |||
1 | # | ||
2 | # arch/x86/kernel/acpi/realmode/Makefile | ||
3 | # | ||
4 | # This file is subject to the terms and conditions of the GNU General Public | ||
5 | # License. See the file "COPYING" in the main directory of this archive | ||
6 | # for more details. | ||
7 | # | ||
8 | |||
9 | always := wakeup.bin | ||
10 | targets := wakeup.elf wakeup.lds | ||
11 | |||
12 | wakeup-y += wakeup.o wakemain.o video-mode.o copy.o bioscall.o regs.o | ||
13 | |||
14 | # The link order of the video-*.o modules can matter. In particular, | ||
15 | # video-vga.o *must* be listed first, followed by video-vesa.o. | ||
16 | # Hardware-specific drivers should follow in the order they should be | ||
17 | # probed, and video-bios.o should typically be last. | ||
18 | wakeup-y += video-vga.o | ||
19 | wakeup-y += video-vesa.o | ||
20 | wakeup-y += video-bios.o | ||
21 | |||
22 | targets += $(wakeup-y) | ||
23 | |||
24 | bootsrc := $(src)/../../../boot | ||
25 | |||
26 | # --------------------------------------------------------------------------- | ||
27 | |||
28 | # How to compile the 16-bit code. Note we always compile for -march=i386, | ||
29 | # that way we can complain to the user if the CPU is insufficient. | ||
30 | # Compile with _SETUP since this is similar to the boot-time setup code. | ||
31 | KBUILD_CFLAGS := $(LINUXINCLUDE) -g -Os -D_SETUP -D_WAKEUP -D__KERNEL__ \ | ||
32 | -I$(srctree)/$(bootsrc) \ | ||
33 | $(cflags-y) \ | ||
34 | -Wall -Wstrict-prototypes \ | ||
35 | -march=i386 -mregparm=3 \ | ||
36 | -include $(srctree)/$(bootsrc)/code16gcc.h \ | ||
37 | -fno-strict-aliasing -fomit-frame-pointer \ | ||
38 | $(call cc-option, -ffreestanding) \ | ||
39 | $(call cc-option, -fno-toplevel-reorder,\ | ||
40 | $(call cc-option, -fno-unit-at-a-time)) \ | ||
41 | $(call cc-option, -fno-stack-protector) \ | ||
42 | $(call cc-option, -mpreferred-stack-boundary=2) | ||
43 | KBUILD_CFLAGS += $(call cc-option, -m32) | ||
44 | KBUILD_AFLAGS := $(KBUILD_CFLAGS) -D__ASSEMBLY__ | ||
45 | GCOV_PROFILE := n | ||
46 | |||
47 | WAKEUP_OBJS = $(addprefix $(obj)/,$(wakeup-y)) | ||
48 | |||
49 | LDFLAGS_wakeup.elf := -T | ||
50 | |||
51 | CPPFLAGS_wakeup.lds += -P -C | ||
52 | |||
53 | $(obj)/wakeup.elf: $(obj)/wakeup.lds $(WAKEUP_OBJS) FORCE | ||
54 | $(call if_changed,ld) | ||
55 | |||
56 | OBJCOPYFLAGS_wakeup.bin := -O binary | ||
57 | |||
58 | $(obj)/wakeup.bin: $(obj)/wakeup.elf FORCE | ||
59 | $(call if_changed,objcopy) | ||
diff --git a/arch/x86/kernel/acpi/realmode/bioscall.S b/arch/x86/kernel/acpi/realmode/bioscall.S new file mode 100644 index 00000000000..f51eb0bb56c --- /dev/null +++ b/arch/x86/kernel/acpi/realmode/bioscall.S | |||
@@ -0,0 +1 @@ | |||
#include "../../../boot/bioscall.S" | |||
diff --git a/arch/x86/kernel/acpi/realmode/copy.S b/arch/x86/kernel/acpi/realmode/copy.S new file mode 100644 index 00000000000..dc59ebee69d --- /dev/null +++ b/arch/x86/kernel/acpi/realmode/copy.S | |||
@@ -0,0 +1 @@ | |||
#include "../../../boot/copy.S" | |||
diff --git a/arch/x86/kernel/acpi/realmode/regs.c b/arch/x86/kernel/acpi/realmode/regs.c new file mode 100644 index 00000000000..6206033ba20 --- /dev/null +++ b/arch/x86/kernel/acpi/realmode/regs.c | |||
@@ -0,0 +1 @@ | |||
#include "../../../boot/regs.c" | |||
diff --git a/arch/x86/kernel/acpi/realmode/video-bios.c b/arch/x86/kernel/acpi/realmode/video-bios.c new file mode 100644 index 00000000000..7deabc144a2 --- /dev/null +++ b/arch/x86/kernel/acpi/realmode/video-bios.c | |||
@@ -0,0 +1 @@ | |||
#include "../../../boot/video-bios.c" | |||
diff --git a/arch/x86/kernel/acpi/realmode/video-mode.c b/arch/x86/kernel/acpi/realmode/video-mode.c new file mode 100644 index 00000000000..328ad209f11 --- /dev/null +++ b/arch/x86/kernel/acpi/realmode/video-mode.c | |||
@@ -0,0 +1 @@ | |||
#include "../../../boot/video-mode.c" | |||
diff --git a/arch/x86/kernel/acpi/realmode/video-vesa.c b/arch/x86/kernel/acpi/realmode/video-vesa.c new file mode 100644 index 00000000000..9dbb9672226 --- /dev/null +++ b/arch/x86/kernel/acpi/realmode/video-vesa.c | |||
@@ -0,0 +1 @@ | |||
#include "../../../boot/video-vesa.c" | |||
diff --git a/arch/x86/kernel/acpi/realmode/video-vga.c b/arch/x86/kernel/acpi/realmode/video-vga.c new file mode 100644 index 00000000000..bcc81255f37 --- /dev/null +++ b/arch/x86/kernel/acpi/realmode/video-vga.c | |||
@@ -0,0 +1 @@ | |||
#include "../../../boot/video-vga.c" | |||
diff --git a/arch/x86/kernel/acpi/realmode/wakemain.c b/arch/x86/kernel/acpi/realmode/wakemain.c new file mode 100644 index 00000000000..883962d9eef --- /dev/null +++ b/arch/x86/kernel/acpi/realmode/wakemain.c | |||
@@ -0,0 +1,81 @@ | |||
1 | #include "wakeup.h" | ||
2 | #include "boot.h" | ||
3 | |||
4 | static void udelay(int loops) | ||
5 | { | ||
6 | while (loops--) | ||
7 | io_delay(); /* Approximately 1 us */ | ||
8 | } | ||
9 | |||
10 | static void beep(unsigned int hz) | ||
11 | { | ||
12 | u8 enable; | ||
13 | |||
14 | if (!hz) { | ||
15 | enable = 0x00; /* Turn off speaker */ | ||
16 | } else { | ||
17 | u16 div = 1193181/hz; | ||
18 | |||
19 | outb(0xb6, 0x43); /* Ctr 2, squarewave, load, binary */ | ||
20 | io_delay(); | ||
21 | outb(div, 0x42); /* LSB of counter */ | ||
22 | io_delay(); | ||
23 | outb(div >> 8, 0x42); /* MSB of counter */ | ||
24 | io_delay(); | ||
25 | |||
26 | enable = 0x03; /* Turn on speaker */ | ||
27 | } | ||
28 | inb(0x61); /* Dummy read of System Control Port B */ | ||
29 | io_delay(); | ||
30 | outb(enable, 0x61); /* Enable timer 2 output to speaker */ | ||
31 | io_delay(); | ||
32 | } | ||
33 | |||
34 | #define DOT_HZ 880 | ||
35 | #define DASH_HZ 587 | ||
36 | #define US_PER_DOT 125000 | ||
37 | |||
38 | /* Okay, this is totally silly, but it's kind of fun. */ | ||
39 | static void send_morse(const char *pattern) | ||
40 | { | ||
41 | char s; | ||
42 | |||
43 | while ((s = *pattern++)) { | ||
44 | switch (s) { | ||
45 | case '.': | ||
46 | beep(DOT_HZ); | ||
47 | udelay(US_PER_DOT); | ||
48 | beep(0); | ||
49 | udelay(US_PER_DOT); | ||
50 | break; | ||
51 | case '-': | ||
52 | beep(DASH_HZ); | ||
53 | udelay(US_PER_DOT * 3); | ||
54 | beep(0); | ||
55 | udelay(US_PER_DOT); | ||
56 | break; | ||
57 | default: /* Assume it's a space */ | ||
58 | udelay(US_PER_DOT * 3); | ||
59 | break; | ||
60 | } | ||
61 | } | ||
62 | } | ||
63 | |||
64 | void main(void) | ||
65 | { | ||
66 | /* Kill machine if structures are wrong */ | ||
67 | if (wakeup_header.real_magic != 0x12345678) | ||
68 | while (1); | ||
69 | |||
70 | if (wakeup_header.realmode_flags & 4) | ||
71 | send_morse("...-"); | ||
72 | |||
73 | if (wakeup_header.realmode_flags & 1) | ||
74 | asm volatile("lcallw $0xc000,$3"); | ||
75 | |||
76 | if (wakeup_header.realmode_flags & 2) { | ||
77 | /* Need to call BIOS */ | ||
78 | probe_cards(0); | ||
79 | set_mode(wakeup_header.video_mode); | ||
80 | } | ||
81 | } | ||
diff --git a/arch/x86/kernel/acpi/realmode/wakeup.S b/arch/x86/kernel/acpi/realmode/wakeup.S new file mode 100644 index 00000000000..b4fd836e405 --- /dev/null +++ b/arch/x86/kernel/acpi/realmode/wakeup.S | |||
@@ -0,0 +1,170 @@ | |||
1 | /* | ||
2 | * ACPI wakeup real mode startup stub | ||
3 | */ | ||
4 | #include <asm/segment.h> | ||
5 | #include <asm/msr-index.h> | ||
6 | #include <asm/page_types.h> | ||
7 | #include <asm/pgtable_types.h> | ||
8 | #include <asm/processor-flags.h> | ||
9 | #include "wakeup.h" | ||
10 | |||
11 | .code16 | ||
12 | .section ".jump", "ax" | ||
13 | .globl _start | ||
14 | _start: | ||
15 | cli | ||
16 | jmp wakeup_code | ||
17 | |||
18 | /* This should match the structure in wakeup.h */ | ||
19 | .section ".header", "a" | ||
20 | .globl wakeup_header | ||
21 | wakeup_header: | ||
22 | video_mode: .short 0 /* Video mode number */ | ||
23 | pmode_return: .byte 0x66, 0xea /* ljmpl */ | ||
24 | .long 0 /* offset goes here */ | ||
25 | .short __KERNEL_CS | ||
26 | pmode_cr0: .long 0 /* Saved %cr0 */ | ||
27 | pmode_cr3: .long 0 /* Saved %cr3 */ | ||
28 | pmode_cr4: .long 0 /* Saved %cr4 */ | ||
29 | pmode_efer: .quad 0 /* Saved EFER */ | ||
30 | pmode_gdt: .quad 0 | ||
31 | pmode_misc_en: .quad 0 /* Saved MISC_ENABLE MSR */ | ||
32 | pmode_behavior: .long 0 /* Wakeup behavior flags */ | ||
33 | realmode_flags: .long 0 | ||
34 | real_magic: .long 0 | ||
35 | trampoline_segment: .word 0 | ||
36 | _pad1: .byte 0 | ||
37 | wakeup_jmp: .byte 0xea /* ljmpw */ | ||
38 | wakeup_jmp_off: .word 3f | ||
39 | wakeup_jmp_seg: .word 0 | ||
40 | wakeup_gdt: .quad 0, 0, 0 | ||
41 | signature: .long WAKEUP_HEADER_SIGNATURE | ||
42 | |||
43 | .text | ||
44 | .code16 | ||
45 | wakeup_code: | ||
46 | cld | ||
47 | |||
48 | /* Apparently some dimwit BIOS programmers don't know how to | ||
49 | program a PM to RM transition, and we might end up here with | ||
50 | junk in the data segment descriptor registers. The only way | ||
51 | to repair that is to go into PM and fix it ourselves... */ | ||
52 | movw $16, %cx | ||
53 | lgdtl %cs:wakeup_gdt | ||
54 | movl %cr0, %eax | ||
55 | orb $X86_CR0_PE, %al | ||
56 | movl %eax, %cr0 | ||
57 | jmp 1f | ||
58 | 1: ljmpw $8, $2f | ||
59 | 2: | ||
60 | movw %cx, %ds | ||
61 | movw %cx, %es | ||
62 | movw %cx, %ss | ||
63 | movw %cx, %fs | ||
64 | movw %cx, %gs | ||
65 | |||
66 | andb $~X86_CR0_PE, %al | ||
67 | movl %eax, %cr0 | ||
68 | jmp wakeup_jmp | ||
69 | 3: | ||
70 | /* Set up segments */ | ||
71 | movw %cs, %ax | ||
72 | movw %ax, %ds | ||
73 | movw %ax, %es | ||
74 | movw %ax, %ss | ||
75 | lidtl wakeup_idt | ||
76 | |||
77 | movl $wakeup_stack_end, %esp | ||
78 | |||
79 | /* Clear the EFLAGS */ | ||
80 | pushl $0 | ||
81 | popfl | ||
82 | |||
83 | /* Check header signature... */ | ||
84 | movl signature, %eax | ||
85 | cmpl $WAKEUP_HEADER_SIGNATURE, %eax | ||
86 | jne bogus_real_magic | ||
87 | |||
88 | /* Check we really have everything... */ | ||
89 | movl end_signature, %eax | ||
90 | cmpl $WAKEUP_END_SIGNATURE, %eax | ||
91 | jne bogus_real_magic | ||
92 | |||
93 | /* Call the C code */ | ||
94 | calll main | ||
95 | |||
96 | /* Restore MISC_ENABLE before entering protected mode, in case | ||
97 | BIOS decided to clear XD_DISABLE during S3. */ | ||
98 | movl pmode_behavior, %eax | ||
99 | btl $WAKEUP_BEHAVIOR_RESTORE_MISC_ENABLE, %eax | ||
100 | jnc 1f | ||
101 | |||
102 | movl pmode_misc_en, %eax | ||
103 | movl pmode_misc_en + 4, %edx | ||
104 | movl $MSR_IA32_MISC_ENABLE, %ecx | ||
105 | wrmsr | ||
106 | 1: | ||
107 | |||
108 | /* Do any other stuff... */ | ||
109 | |||
110 | #ifndef CONFIG_64BIT | ||
111 | /* This could also be done in C code... */ | ||
112 | movl pmode_cr3, %eax | ||
113 | movl %eax, %cr3 | ||
114 | |||
115 | movl pmode_cr4, %ecx | ||
116 | jecxz 1f | ||
117 | movl %ecx, %cr4 | ||
118 | 1: | ||
119 | movl pmode_efer, %eax | ||
120 | movl pmode_efer + 4, %edx | ||
121 | movl %eax, %ecx | ||
122 | orl %edx, %ecx | ||
123 | jz 1f | ||
124 | movl $MSR_EFER, %ecx | ||
125 | wrmsr | ||
126 | 1: | ||
127 | |||
128 | lgdtl pmode_gdt | ||
129 | |||
130 | /* This really couldn't... */ | ||
131 | movl pmode_cr0, %eax | ||
132 | movl %eax, %cr0 | ||
133 | jmp pmode_return | ||
134 | #else | ||
135 | pushw $0 | ||
136 | pushw trampoline_segment | ||
137 | pushw $0 | ||
138 | lret | ||
139 | #endif | ||
140 | |||
141 | bogus_real_magic: | ||
142 | 1: | ||
143 | hlt | ||
144 | jmp 1b | ||
145 | |||
146 | .data | ||
147 | .balign 8 | ||
148 | |||
149 | /* This is the standard real-mode IDT */ | ||
150 | wakeup_idt: | ||
151 | .word 0xffff /* limit */ | ||
152 | .long 0 /* address */ | ||
153 | .word 0 | ||
154 | |||
155 | .globl HEAP, heap_end | ||
156 | HEAP: | ||
157 | .long wakeup_heap | ||
158 | heap_end: | ||
159 | .long wakeup_stack | ||
160 | |||
161 | .bss | ||
162 | wakeup_heap: | ||
163 | .space 2048 | ||
164 | wakeup_stack: | ||
165 | .space 2048 | ||
166 | wakeup_stack_end: | ||
167 | |||
168 | .section ".signature","a" | ||
169 | end_signature: | ||
170 | .long WAKEUP_END_SIGNATURE | ||
diff --git a/arch/x86/kernel/acpi/realmode/wakeup.h b/arch/x86/kernel/acpi/realmode/wakeup.h new file mode 100644 index 00000000000..97a29e1430e --- /dev/null +++ b/arch/x86/kernel/acpi/realmode/wakeup.h | |||
@@ -0,0 +1,48 @@ | |||
1 | /* | ||
2 | * Definitions for the wakeup data structure at the head of the | ||
3 | * wakeup code. | ||
4 | */ | ||
5 | |||
6 | #ifndef ARCH_X86_KERNEL_ACPI_RM_WAKEUP_H | ||
7 | #define ARCH_X86_KERNEL_ACPI_RM_WAKEUP_H | ||
8 | |||
9 | #ifndef __ASSEMBLY__ | ||
10 | #include <linux/types.h> | ||
11 | |||
12 | /* This must match data at wakeup.S */ | ||
13 | struct wakeup_header { | ||
14 | u16 video_mode; /* Video mode number */ | ||
15 | u16 _jmp1; /* ljmpl opcode, 32-bit only */ | ||
16 | u32 pmode_entry; /* Protected mode resume point, 32-bit only */ | ||
17 | u16 _jmp2; /* CS value, 32-bit only */ | ||
18 | u32 pmode_cr0; /* Protected mode cr0 */ | ||
19 | u32 pmode_cr3; /* Protected mode cr3 */ | ||
20 | u32 pmode_cr4; /* Protected mode cr4 */ | ||
21 | u32 pmode_efer_low; /* Protected mode EFER */ | ||
22 | u32 pmode_efer_high; | ||
23 | u64 pmode_gdt; | ||
24 | u32 pmode_misc_en_low; /* Protected mode MISC_ENABLE */ | ||
25 | u32 pmode_misc_en_high; | ||
26 | u32 pmode_behavior; /* Wakeup routine behavior flags */ | ||
27 | u32 realmode_flags; | ||
28 | u32 real_magic; | ||
29 | u16 trampoline_segment; /* segment with trampoline code, 64-bit only */ | ||
30 | u8 _pad1; | ||
31 | u8 wakeup_jmp; | ||
32 | u16 wakeup_jmp_off; | ||
33 | u16 wakeup_jmp_seg; | ||
34 | u64 wakeup_gdt[3]; | ||
35 | u32 signature; /* To check we have correct structure */ | ||
36 | } __attribute__((__packed__)); | ||
37 | |||
38 | extern struct wakeup_header wakeup_header; | ||
39 | #endif | ||
40 | |||
41 | #define WAKEUP_HEADER_OFFSET 8 | ||
42 | #define WAKEUP_HEADER_SIGNATURE 0x51ee1111 | ||
43 | #define WAKEUP_END_SIGNATURE 0x65a22c82 | ||
44 | |||
45 | /* Wakeup behavior bits */ | ||
46 | #define WAKEUP_BEHAVIOR_RESTORE_MISC_ENABLE 0 | ||
47 | |||
48 | #endif /* ARCH_X86_KERNEL_ACPI_RM_WAKEUP_H */ | ||
diff --git a/arch/x86/kernel/acpi/realmode/wakeup.lds.S b/arch/x86/kernel/acpi/realmode/wakeup.lds.S new file mode 100644 index 00000000000..d4f8010a5b1 --- /dev/null +++ b/arch/x86/kernel/acpi/realmode/wakeup.lds.S | |||
@@ -0,0 +1,62 @@ | |||
1 | /* | ||
2 | * wakeup.ld | ||
3 | * | ||
4 | * Linker script for the real-mode wakeup code | ||
5 | */ | ||
6 | #undef i386 | ||
7 | #include "wakeup.h" | ||
8 | |||
9 | OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") | ||
10 | OUTPUT_ARCH(i386) | ||
11 | ENTRY(_start) | ||
12 | |||
13 | SECTIONS | ||
14 | { | ||
15 | . = 0; | ||
16 | .jump : { | ||
17 | *(.jump) | ||
18 | } = 0x90909090 | ||
19 | |||
20 | . = WAKEUP_HEADER_OFFSET; | ||
21 | .header : { | ||
22 | *(.header) | ||
23 | } | ||
24 | |||
25 | . = ALIGN(16); | ||
26 | .text : { | ||
27 | *(.text*) | ||
28 | } = 0x90909090 | ||
29 | |||
30 | . = ALIGN(16); | ||
31 | .rodata : { | ||
32 | *(.rodata*) | ||
33 | } | ||
34 | |||
35 | .videocards : { | ||
36 | video_cards = .; | ||
37 | *(.videocards) | ||
38 | video_cards_end = .; | ||
39 | } | ||
40 | |||
41 | . = ALIGN(16); | ||
42 | .data : { | ||
43 | *(.data*) | ||
44 | } | ||
45 | |||
46 | . = ALIGN(16); | ||
47 | .bss : { | ||
48 | __bss_start = .; | ||
49 | *(.bss) | ||
50 | __bss_end = .; | ||
51 | } | ||
52 | |||
53 | .signature : { | ||
54 | *(.signature) | ||
55 | } | ||
56 | |||
57 | _end = .; | ||
58 | |||
59 | /DISCARD/ : { | ||
60 | *(.note*) | ||
61 | } | ||
62 | } | ||
diff --git a/arch/x86/kernel/acpi/wakeup_rm.S b/arch/x86/kernel/acpi/wakeup_rm.S new file mode 100644 index 00000000000..63b8ab524f2 --- /dev/null +++ b/arch/x86/kernel/acpi/wakeup_rm.S | |||
@@ -0,0 +1,12 @@ | |||
1 | /* | ||
2 | * Wrapper script for the realmode binary as a transport object | ||
3 | * before copying to low memory. | ||
4 | */ | ||
5 | #include <asm/page_types.h> | ||
6 | |||
7 | .section ".x86_trampoline","a" | ||
8 | .balign PAGE_SIZE | ||
9 | .globl acpi_wakeup_code | ||
10 | acpi_wakeup_code: | ||
11 | .incbin "arch/x86/kernel/acpi/realmode/wakeup.bin" | ||
12 | .size acpi_wakeup_code, .-acpi_wakeup_code | ||
diff --git a/arch/x86/kernel/cpu/sched.c b/arch/x86/kernel/cpu/sched.c new file mode 100644 index 00000000000..a640ae5ad20 --- /dev/null +++ b/arch/x86/kernel/cpu/sched.c | |||
@@ -0,0 +1,55 @@ | |||
1 | #include <linux/sched.h> | ||
2 | #include <linux/math64.h> | ||
3 | #include <linux/percpu.h> | ||
4 | #include <linux/irqflags.h> | ||
5 | |||
6 | #include <asm/cpufeature.h> | ||
7 | #include <asm/processor.h> | ||
8 | |||
9 | #ifdef CONFIG_SMP | ||
10 | |||
11 | static DEFINE_PER_CPU(struct aperfmperf, old_perf_sched); | ||
12 | |||
13 | static unsigned long scale_aperfmperf(void) | ||
14 | { | ||
15 | struct aperfmperf val, *old = &__get_cpu_var(old_perf_sched); | ||
16 | unsigned long ratio, flags; | ||
17 | |||
18 | local_irq_save(flags); | ||
19 | get_aperfmperf(&val); | ||
20 | local_irq_restore(flags); | ||
21 | |||
22 | ratio = calc_aperfmperf_ratio(old, &val); | ||
23 | *old = val; | ||
24 | |||
25 | return ratio; | ||
26 | } | ||
27 | |||
28 | unsigned long arch_scale_freq_power(struct sched_domain *sd, int cpu) | ||
29 | { | ||
30 | /* | ||
31 | * do aperf/mperf on the cpu level because it includes things | ||
32 | * like turbo mode, which are relevant to full cores. | ||
33 | */ | ||
34 | if (boot_cpu_has(X86_FEATURE_APERFMPERF)) | ||
35 | return scale_aperfmperf(); | ||
36 | |||
37 | /* | ||
38 | * maybe have something cpufreq here | ||
39 | */ | ||
40 | |||
41 | return default_scale_freq_power(sd, cpu); | ||
42 | } | ||
43 | |||
44 | unsigned long arch_scale_smt_power(struct sched_domain *sd, int cpu) | ||
45 | { | ||
46 | /* | ||
47 | * aperf/mperf already includes the smt gain | ||
48 | */ | ||
49 | if (boot_cpu_has(X86_FEATURE_APERFMPERF)) | ||
50 | return SCHED_LOAD_SCALE; | ||
51 | |||
52 | return default_scale_smt_power(sd, cpu); | ||
53 | } | ||
54 | |||
55 | #endif | ||
diff --git a/arch/x86/kernel/init_task.c b/arch/x86/kernel/init_task.c new file mode 100644 index 00000000000..43e9ccf4494 --- /dev/null +++ b/arch/x86/kernel/init_task.c | |||
@@ -0,0 +1,42 @@ | |||
1 | #include <linux/mm.h> | ||
2 | #include <linux/module.h> | ||
3 | #include <linux/sched.h> | ||
4 | #include <linux/init.h> | ||
5 | #include <linux/init_task.h> | ||
6 | #include <linux/fs.h> | ||
7 | #include <linux/mqueue.h> | ||
8 | |||
9 | #include <asm/uaccess.h> | ||
10 | #include <asm/pgtable.h> | ||
11 | #include <asm/desc.h> | ||
12 | |||
13 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); | ||
14 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); | ||
15 | |||
16 | /* | ||
17 | * Initial thread structure. | ||
18 | * | ||
19 | * We need to make sure that this is THREAD_SIZE aligned due to the | ||
20 | * way process stacks are handled. This is done by having a special | ||
21 | * "init_task" linker map entry.. | ||
22 | */ | ||
23 | union thread_union init_thread_union __init_task_data = | ||
24 | { INIT_THREAD_INFO(init_task) }; | ||
25 | |||
26 | /* | ||
27 | * Initial task structure. | ||
28 | * | ||
29 | * All other task structs will be allocated on slabs in fork.c | ||
30 | */ | ||
31 | struct task_struct init_task = INIT_TASK(init_task); | ||
32 | EXPORT_SYMBOL(init_task); | ||
33 | |||
34 | /* | ||
35 | * per-CPU TSS segments. Threads are completely 'soft' on Linux, | ||
36 | * no more per-task TSS's. The TSS size is kept cacheline-aligned | ||
37 | * so they are allowed to end up in the .data..cacheline_aligned | ||
38 | * section. Since TSS's are completely CPU-local, we want them | ||
39 | * on exact cacheline boundaries, to eliminate cacheline ping-pong. | ||
40 | */ | ||
41 | DEFINE_PER_CPU_SHARED_ALIGNED(struct tss_struct, init_tss) = INIT_TSS; | ||
42 | |||
diff --git a/arch/x86/kernel/mca_32.c b/arch/x86/kernel/mca_32.c new file mode 100644 index 00000000000..177183cbb6a --- /dev/null +++ b/arch/x86/kernel/mca_32.c | |||
@@ -0,0 +1,477 @@ | |||
1 | /* | ||
2 | * Written by Martin Kolinek, February 1996 | ||
3 | * | ||
4 | * Changes: | ||
5 | * | ||
6 | * Chris Beauregard July 28th, 1996 | ||
7 | * - Fixed up integrated SCSI detection | ||
8 | * | ||
9 | * Chris Beauregard August 3rd, 1996 | ||
10 | * - Made mca_info local | ||
11 | * - Made integrated registers accessible through standard function calls | ||
12 | * - Added name field | ||
13 | * - More sanity checking | ||
14 | * | ||
15 | * Chris Beauregard August 9th, 1996 | ||
16 | * - Rewrote /proc/mca | ||
17 | * | ||
18 | * Chris Beauregard January 7th, 1997 | ||
19 | * - Added basic NMI-processing | ||
20 | * - Added more information to mca_info structure | ||
21 | * | ||
22 | * David Weinehall October 12th, 1998 | ||
23 | * - Made a lot of cleaning up in the source | ||
24 | * - Added use of save_flags / restore_flags | ||
25 | * - Added the 'driver_loaded' flag in MCA_adapter | ||
26 | * - Added an alternative implemention of ZP Gu's mca_find_unused_adapter | ||
27 | * | ||
28 | * David Weinehall March 24th, 1999 | ||
29 | * - Fixed the output of 'Driver Installed' in /proc/mca/pos | ||
30 | * - Made the Integrated Video & SCSI show up even if they have id 0000 | ||
31 | * | ||
32 | * Alexander Viro November 9th, 1999 | ||
33 | * - Switched to regular procfs methods | ||
34 | * | ||
35 | * Alfred Arnold & David Weinehall August 23rd, 2000 | ||
36 | * - Added support for Planar POS-registers | ||
37 | */ | ||
38 | |||
39 | #include <linux/module.h> | ||
40 | #include <linux/types.h> | ||
41 | #include <linux/errno.h> | ||
42 | #include <linux/kernel.h> | ||
43 | #include <linux/mca.h> | ||
44 | #include <linux/kprobes.h> | ||
45 | #include <linux/slab.h> | ||
46 | #include <asm/system.h> | ||
47 | #include <asm/io.h> | ||
48 | #include <linux/proc_fs.h> | ||
49 | #include <linux/mman.h> | ||
50 | #include <linux/mm.h> | ||
51 | #include <linux/pagemap.h> | ||
52 | #include <linux/ioport.h> | ||
53 | #include <asm/uaccess.h> | ||
54 | #include <linux/init.h> | ||
55 | |||
56 | static unsigned char which_scsi; | ||
57 | |||
58 | int MCA_bus; | ||
59 | EXPORT_SYMBOL(MCA_bus); | ||
60 | |||
61 | /* | ||
62 | * Motherboard register spinlock. Untested on SMP at the moment, but | ||
63 | * are there any MCA SMP boxes? | ||
64 | * | ||
65 | * Yes - Alan | ||
66 | */ | ||
67 | static DEFINE_SPINLOCK(mca_lock); | ||
68 | |||
69 | /* Build the status info for the adapter */ | ||
70 | |||
71 | static void mca_configure_adapter_status(struct mca_device *mca_dev) | ||
72 | { | ||
73 | mca_dev->status = MCA_ADAPTER_NONE; | ||
74 | |||
75 | mca_dev->pos_id = mca_dev->pos[0] | ||
76 | + (mca_dev->pos[1] << 8); | ||
77 | |||
78 | if (!mca_dev->pos_id && mca_dev->slot < MCA_MAX_SLOT_NR) { | ||
79 | |||
80 | /* | ||
81 | * id = 0x0000 usually indicates hardware failure, | ||
82 | * however, ZP Gu (zpg@castle.net> reports that his 9556 | ||
83 | * has 0x0000 as id and everything still works. There | ||
84 | * also seem to be an adapter with id = 0x0000; the | ||
85 | * NCR Parallel Bus Memory Card. Until this is confirmed, | ||
86 | * however, this code will stay. | ||
87 | */ | ||
88 | |||
89 | mca_dev->status = MCA_ADAPTER_ERROR; | ||
90 | |||
91 | return; | ||
92 | } else if (mca_dev->pos_id != 0xffff) { | ||
93 | |||
94 | /* | ||
95 | * 0xffff usually indicates that there's no adapter, | ||
96 | * however, some integrated adapters may have 0xffff as | ||
97 | * their id and still be valid. Examples are on-board | ||
98 | * VGA of the 55sx, the integrated SCSI of the 56 & 57, | ||
99 | * and possibly also the 95 ULTIMEDIA. | ||
100 | */ | ||
101 | |||
102 | mca_dev->status = MCA_ADAPTER_NORMAL; | ||
103 | } | ||
104 | |||
105 | if ((mca_dev->pos_id == 0xffff || | ||
106 | mca_dev->pos_id == 0x0000) && mca_dev->slot >= MCA_MAX_SLOT_NR) { | ||
107 | int j; | ||
108 | |||
109 | for (j = 2; j < 8; j++) { | ||
110 | if (mca_dev->pos[j] != 0xff) { | ||
111 | mca_dev->status = MCA_ADAPTER_NORMAL; | ||
112 | break; | ||
113 | } | ||
114 | } | ||
115 | } | ||
116 | |||
117 | if (!(mca_dev->pos[2] & MCA_ENABLED)) { | ||
118 | |||
119 | /* enabled bit is in POS 2 */ | ||
120 | |||
121 | mca_dev->status = MCA_ADAPTER_DISABLED; | ||
122 | } | ||
123 | } /* mca_configure_adapter_status */ | ||
124 | |||
125 | /*--------------------------------------------------------------------*/ | ||
126 | |||
127 | static struct resource mca_standard_resources[] = { | ||
128 | { .start = 0x60, .end = 0x60, .name = "system control port B (MCA)" }, | ||
129 | { .start = 0x90, .end = 0x90, .name = "arbitration (MCA)" }, | ||
130 | { .start = 0x91, .end = 0x91, .name = "card Select Feedback (MCA)" }, | ||
131 | { .start = 0x92, .end = 0x92, .name = "system Control port A (MCA)" }, | ||
132 | { .start = 0x94, .end = 0x94, .name = "system board setup (MCA)" }, | ||
133 | { .start = 0x96, .end = 0x97, .name = "POS (MCA)" }, | ||
134 | { .start = 0x100, .end = 0x107, .name = "POS (MCA)" } | ||
135 | }; | ||
136 | |||
137 | #define MCA_STANDARD_RESOURCES ARRAY_SIZE(mca_standard_resources) | ||
138 | |||
139 | /* | ||
140 | * mca_read_and_store_pos - read the POS registers into a memory buffer | ||
141 | * @pos: a char pointer to 8 bytes, contains the POS register value on | ||
142 | * successful return | ||
143 | * | ||
144 | * Returns 1 if a card actually exists (i.e. the pos isn't | ||
145 | * all 0xff) or 0 otherwise | ||
146 | */ | ||
147 | static int mca_read_and_store_pos(unsigned char *pos) | ||
148 | { | ||
149 | int j; | ||
150 | int found = 0; | ||
151 | |||
152 | for (j = 0; j < 8; j++) { | ||
153 | pos[j] = inb_p(MCA_POS_REG(j)); | ||
154 | if (pos[j] != 0xff) { | ||
155 | /* 0xff all across means no device. 0x00 means | ||
156 | * something's broken, but a device is | ||
157 | * probably there. However, if you get 0x00 | ||
158 | * from a motherboard register it won't matter | ||
159 | * what we find. For the record, on the | ||
160 | * 57SLC, the integrated SCSI adapter has | ||
161 | * 0xffff for the adapter ID, but nonzero for | ||
162 | * other registers. */ | ||
163 | |||
164 | found = 1; | ||
165 | } | ||
166 | } | ||
167 | return found; | ||
168 | } | ||
169 | |||
170 | static unsigned char mca_pc_read_pos(struct mca_device *mca_dev, int reg) | ||
171 | { | ||
172 | unsigned char byte; | ||
173 | unsigned long flags; | ||
174 | |||
175 | if (reg < 0 || reg >= 8) | ||
176 | return 0; | ||
177 | |||
178 | spin_lock_irqsave(&mca_lock, flags); | ||
179 | if (mca_dev->pos_register) { | ||
180 | /* Disable adapter setup, enable motherboard setup */ | ||
181 | |||
182 | outb_p(0, MCA_ADAPTER_SETUP_REG); | ||
183 | outb_p(mca_dev->pos_register, MCA_MOTHERBOARD_SETUP_REG); | ||
184 | |||
185 | byte = inb_p(MCA_POS_REG(reg)); | ||
186 | outb_p(0xff, MCA_MOTHERBOARD_SETUP_REG); | ||
187 | } else { | ||
188 | |||
189 | /* Make sure motherboard setup is off */ | ||
190 | |||
191 | outb_p(0xff, MCA_MOTHERBOARD_SETUP_REG); | ||
192 | |||
193 | /* Read the appropriate register */ | ||
194 | |||
195 | outb_p(0x8|(mca_dev->slot & 0xf), MCA_ADAPTER_SETUP_REG); | ||
196 | byte = inb_p(MCA_POS_REG(reg)); | ||
197 | outb_p(0, MCA_ADAPTER_SETUP_REG); | ||
198 | } | ||
199 | spin_unlock_irqrestore(&mca_lock, flags); | ||
200 | |||
201 | mca_dev->pos[reg] = byte; | ||
202 | |||
203 | return byte; | ||
204 | } | ||
205 | |||
206 | static void mca_pc_write_pos(struct mca_device *mca_dev, int reg, | ||
207 | unsigned char byte) | ||
208 | { | ||
209 | unsigned long flags; | ||
210 | |||
211 | if (reg < 0 || reg >= 8) | ||
212 | return; | ||
213 | |||
214 | spin_lock_irqsave(&mca_lock, flags); | ||
215 | |||
216 | /* Make sure motherboard setup is off */ | ||
217 | |||
218 | outb_p(0xff, MCA_MOTHERBOARD_SETUP_REG); | ||
219 | |||
220 | /* Read in the appropriate register */ | ||
221 | |||
222 | outb_p(0x8|(mca_dev->slot&0xf), MCA_ADAPTER_SETUP_REG); | ||
223 | outb_p(byte, MCA_POS_REG(reg)); | ||
224 | outb_p(0, MCA_ADAPTER_SETUP_REG); | ||
225 | |||
226 | spin_unlock_irqrestore(&mca_lock, flags); | ||
227 | |||
228 | /* Update the global register list, while we have the byte */ | ||
229 | |||
230 | mca_dev->pos[reg] = byte; | ||
231 | |||
232 | } | ||
233 | |||
234 | /* for the primary MCA bus, we have identity transforms */ | ||
235 | static int mca_dummy_transform_irq(struct mca_device *mca_dev, int irq) | ||
236 | { | ||
237 | return irq; | ||
238 | } | ||
239 | |||
240 | static int mca_dummy_transform_ioport(struct mca_device *mca_dev, int port) | ||
241 | { | ||
242 | return port; | ||
243 | } | ||
244 | |||
245 | static void *mca_dummy_transform_memory(struct mca_device *mca_dev, void *mem) | ||
246 | { | ||
247 | return mem; | ||
248 | } | ||
249 | |||
250 | |||
251 | static int __init mca_init(void) | ||
252 | { | ||
253 | unsigned int i, j; | ||
254 | struct mca_device *mca_dev; | ||
255 | unsigned char pos[8]; | ||
256 | short mca_builtin_scsi_ports[] = {0xf7, 0xfd, 0x00}; | ||
257 | struct mca_bus *bus; | ||
258 | |||
259 | /* | ||
260 | * WARNING: Be careful when making changes here. Putting an adapter | ||
261 | * and the motherboard simultaneously into setup mode may result in | ||
262 | * damage to chips (according to The Indispensable PC Hardware Book | ||
263 | * by Hans-Peter Messmer). Also, we disable system interrupts (so | ||
264 | * that we are not disturbed in the middle of this). | ||
265 | */ | ||
266 | |||
267 | /* Make sure the MCA bus is present */ | ||
268 | |||
269 | if (mca_system_init()) { | ||
270 | printk(KERN_ERR "MCA bus system initialisation failed\n"); | ||
271 | return -ENODEV; | ||
272 | } | ||
273 | |||
274 | if (!MCA_bus) | ||
275 | return -ENODEV; | ||
276 | |||
277 | printk(KERN_INFO "Micro Channel bus detected.\n"); | ||
278 | |||
279 | /* All MCA systems have at least a primary bus */ | ||
280 | bus = mca_attach_bus(MCA_PRIMARY_BUS); | ||
281 | if (!bus) | ||
282 | goto out_nomem; | ||
283 | bus->default_dma_mask = 0xffffffffLL; | ||
284 | bus->f.mca_write_pos = mca_pc_write_pos; | ||
285 | bus->f.mca_read_pos = mca_pc_read_pos; | ||
286 | bus->f.mca_transform_irq = mca_dummy_transform_irq; | ||
287 | bus->f.mca_transform_ioport = mca_dummy_transform_ioport; | ||
288 | bus->f.mca_transform_memory = mca_dummy_transform_memory; | ||
289 | |||
290 | /* get the motherboard device */ | ||
291 | mca_dev = kzalloc(sizeof(struct mca_device), GFP_KERNEL); | ||
292 | if (unlikely(!mca_dev)) | ||
293 | goto out_nomem; | ||
294 | |||
295 | /* | ||
296 | * We do not expect many MCA interrupts during initialization, | ||
297 | * but let us be safe: | ||
298 | */ | ||
299 | spin_lock_irq(&mca_lock); | ||
300 | |||
301 | /* Make sure adapter setup is off */ | ||
302 | |||
303 | outb_p(0, MCA_ADAPTER_SETUP_REG); | ||
304 | |||
305 | /* Read motherboard POS registers */ | ||
306 | |||
307 | mca_dev->pos_register = 0x7f; | ||
308 | outb_p(mca_dev->pos_register, MCA_MOTHERBOARD_SETUP_REG); | ||
309 | mca_dev->name[0] = 0; | ||
310 | mca_read_and_store_pos(mca_dev->pos); | ||
311 | mca_configure_adapter_status(mca_dev); | ||
312 | /* fake POS and slot for a motherboard */ | ||
313 | mca_dev->pos_id = MCA_MOTHERBOARD_POS; | ||
314 | mca_dev->slot = MCA_MOTHERBOARD; | ||
315 | mca_register_device(MCA_PRIMARY_BUS, mca_dev); | ||
316 | |||
317 | mca_dev = kzalloc(sizeof(struct mca_device), GFP_ATOMIC); | ||
318 | if (unlikely(!mca_dev)) | ||
319 | goto out_unlock_nomem; | ||
320 | |||
321 | /* Put motherboard into video setup mode, read integrated video | ||
322 | * POS registers, and turn motherboard setup off. | ||
323 | */ | ||
324 | |||
325 | mca_dev->pos_register = 0xdf; | ||
326 | outb_p(mca_dev->pos_register, MCA_MOTHERBOARD_SETUP_REG); | ||
327 | mca_dev->name[0] = 0; | ||
328 | mca_read_and_store_pos(mca_dev->pos); | ||
329 | mca_configure_adapter_status(mca_dev); | ||
330 | /* fake POS and slot for the integrated video */ | ||
331 | mca_dev->pos_id = MCA_INTEGVIDEO_POS; | ||
332 | mca_dev->slot = MCA_INTEGVIDEO; | ||
333 | mca_register_device(MCA_PRIMARY_BUS, mca_dev); | ||
334 | |||
335 | /* | ||
336 | * Put motherboard into scsi setup mode, read integrated scsi | ||
337 | * POS registers, and turn motherboard setup off. | ||
338 | * | ||
339 | * It seems there are two possible SCSI registers. Martin says that | ||
340 | * for the 56,57, 0xf7 is the one, but fails on the 76. | ||
341 | * Alfredo (apena@vnet.ibm.com) says | ||
342 | * 0xfd works on his machine. We'll try both of them. I figure it's | ||
343 | * a good bet that only one could be valid at a time. This could | ||
344 | * screw up though if one is used for something else on the other | ||
345 | * machine. | ||
346 | */ | ||
347 | |||
348 | for (i = 0; (which_scsi = mca_builtin_scsi_ports[i]) != 0; i++) { | ||
349 | outb_p(which_scsi, MCA_MOTHERBOARD_SETUP_REG); | ||
350 | if (mca_read_and_store_pos(pos)) | ||
351 | break; | ||
352 | } | ||
353 | if (which_scsi) { | ||
354 | /* found a scsi card */ | ||
355 | mca_dev = kzalloc(sizeof(struct mca_device), GFP_ATOMIC); | ||
356 | if (unlikely(!mca_dev)) | ||
357 | goto out_unlock_nomem; | ||
358 | |||
359 | for (j = 0; j < 8; j++) | ||
360 | mca_dev->pos[j] = pos[j]; | ||
361 | |||
362 | mca_configure_adapter_status(mca_dev); | ||
363 | /* fake POS and slot for integrated SCSI controller */ | ||
364 | mca_dev->pos_id = MCA_INTEGSCSI_POS; | ||
365 | mca_dev->slot = MCA_INTEGSCSI; | ||
366 | mca_dev->pos_register = which_scsi; | ||
367 | mca_register_device(MCA_PRIMARY_BUS, mca_dev); | ||
368 | } | ||
369 | |||
370 | /* Turn off motherboard setup */ | ||
371 | |||
372 | outb_p(0xff, MCA_MOTHERBOARD_SETUP_REG); | ||
373 | |||
374 | /* | ||
375 | * Now loop over MCA slots: put each adapter into setup mode, and | ||
376 | * read its POS registers. Then put adapter setup off. | ||
377 | */ | ||
378 | |||
379 | for (i = 0; i < MCA_MAX_SLOT_NR; i++) { | ||
380 | outb_p(0x8|(i&0xf), MCA_ADAPTER_SETUP_REG); | ||
381 | if (!mca_read_and_store_pos(pos)) | ||
382 | continue; | ||
383 | |||
384 | mca_dev = kzalloc(sizeof(struct mca_device), GFP_ATOMIC); | ||
385 | if (unlikely(!mca_dev)) | ||
386 | goto out_unlock_nomem; | ||
387 | |||
388 | for (j = 0; j < 8; j++) | ||
389 | mca_dev->pos[j] = pos[j]; | ||
390 | |||
391 | mca_dev->driver_loaded = 0; | ||
392 | mca_dev->slot = i; | ||
393 | mca_dev->pos_register = 0; | ||
394 | mca_configure_adapter_status(mca_dev); | ||
395 | mca_register_device(MCA_PRIMARY_BUS, mca_dev); | ||
396 | } | ||
397 | outb_p(0, MCA_ADAPTER_SETUP_REG); | ||
398 | |||
399 | /* Enable interrupts and return memory start */ | ||
400 | spin_unlock_irq(&mca_lock); | ||
401 | |||
402 | for (i = 0; i < MCA_STANDARD_RESOURCES; i++) | ||
403 | request_resource(&ioport_resource, mca_standard_resources + i); | ||
404 | |||
405 | mca_do_proc_init(); | ||
406 | |||
407 | return 0; | ||
408 | |||
409 | out_unlock_nomem: | ||
410 | spin_unlock_irq(&mca_lock); | ||
411 | out_nomem: | ||
412 | printk(KERN_EMERG "Failed memory allocation in MCA setup!\n"); | ||
413 | return -ENOMEM; | ||
414 | } | ||
415 | |||
416 | subsys_initcall(mca_init); | ||
417 | |||
418 | /*--------------------------------------------------------------------*/ | ||
419 | |||
420 | static __kprobes void | ||
421 | mca_handle_nmi_device(struct mca_device *mca_dev, int check_flag) | ||
422 | { | ||
423 | int slot = mca_dev->slot; | ||
424 | |||
425 | if (slot == MCA_INTEGSCSI) { | ||
426 | printk(KERN_CRIT "NMI: caused by MCA integrated SCSI adapter (%s)\n", | ||
427 | mca_dev->name); | ||
428 | } else if (slot == MCA_INTEGVIDEO) { | ||
429 | printk(KERN_CRIT "NMI: caused by MCA integrated video adapter (%s)\n", | ||
430 | mca_dev->name); | ||
431 | } else if (slot == MCA_MOTHERBOARD) { | ||
432 | printk(KERN_CRIT "NMI: caused by motherboard (%s)\n", | ||
433 | mca_dev->name); | ||
434 | } | ||
435 | |||
436 | /* More info available in POS 6 and 7? */ | ||
437 | |||
438 | if (check_flag) { | ||
439 | unsigned char pos6, pos7; | ||
440 | |||
441 | pos6 = mca_device_read_pos(mca_dev, 6); | ||
442 | pos7 = mca_device_read_pos(mca_dev, 7); | ||
443 | |||
444 | printk(KERN_CRIT "NMI: POS 6 = 0x%x, POS 7 = 0x%x\n", pos6, pos7); | ||
445 | } | ||
446 | |||
447 | } /* mca_handle_nmi_slot */ | ||
448 | |||
449 | /*--------------------------------------------------------------------*/ | ||
450 | |||
451 | static int __kprobes mca_handle_nmi_callback(struct device *dev, void *data) | ||
452 | { | ||
453 | struct mca_device *mca_dev = to_mca_device(dev); | ||
454 | unsigned char pos5; | ||
455 | |||
456 | pos5 = mca_device_read_pos(mca_dev, 5); | ||
457 | |||
458 | if (!(pos5 & 0x80)) { | ||
459 | /* | ||
460 | * Bit 7 of POS 5 is reset when this adapter has a hardware | ||
461 | * error. Bit 7 it reset if there's error information | ||
462 | * available in POS 6 and 7. | ||
463 | */ | ||
464 | mca_handle_nmi_device(mca_dev, !(pos5 & 0x40)); | ||
465 | return 1; | ||
466 | } | ||
467 | return 0; | ||
468 | } | ||
469 | |||
470 | void __kprobes mca_handle_nmi(void) | ||
471 | { | ||
472 | /* | ||
473 | * First try - scan the various adapters and see if a specific | ||
474 | * adapter was responsible for the error. | ||
475 | */ | ||
476 | bus_for_each_dev(&mca_bus_type, NULL, NULL, mca_handle_nmi_callback); | ||
477 | } | ||
diff --git a/arch/x86/kernel/reboot_32.S b/arch/x86/kernel/reboot_32.S new file mode 100644 index 00000000000..1d5c46df0d7 --- /dev/null +++ b/arch/x86/kernel/reboot_32.S | |||
@@ -0,0 +1,135 @@ | |||
1 | #include <linux/linkage.h> | ||
2 | #include <linux/init.h> | ||
3 | #include <asm/segment.h> | ||
4 | #include <asm/page_types.h> | ||
5 | |||
6 | /* | ||
7 | * The following code and data reboots the machine by switching to real | ||
8 | * mode and jumping to the BIOS reset entry point, as if the CPU has | ||
9 | * really been reset. The previous version asked the keyboard | ||
10 | * controller to pulse the CPU reset line, which is more thorough, but | ||
11 | * doesn't work with at least one type of 486 motherboard. It is easy | ||
12 | * to stop this code working; hence the copious comments. | ||
13 | * | ||
14 | * This code is called with the restart type (0 = BIOS, 1 = APM) in %eax. | ||
15 | */ | ||
16 | .section ".x86_trampoline","a" | ||
17 | .balign 16 | ||
18 | .code32 | ||
19 | ENTRY(machine_real_restart_asm) | ||
20 | r_base = . | ||
21 | /* Get our own relocated address */ | ||
22 | call 1f | ||
23 | 1: popl %ebx | ||
24 | subl $(1b - r_base), %ebx | ||
25 | |||
26 | /* Compute the equivalent real-mode segment */ | ||
27 | movl %ebx, %ecx | ||
28 | shrl $4, %ecx | ||
29 | |||
30 | /* Patch post-real-mode segment jump */ | ||
31 | movw (dispatch_table - r_base)(%ebx,%eax,2),%ax | ||
32 | movw %ax, (101f - r_base)(%ebx) | ||
33 | movw %cx, (102f - r_base)(%ebx) | ||
34 | |||
35 | /* Set up the IDT for real mode. */ | ||
36 | lidtl (machine_real_restart_idt - r_base)(%ebx) | ||
37 | |||
38 | /* | ||
39 | * Set up a GDT from which we can load segment descriptors for real | ||
40 | * mode. The GDT is not used in real mode; it is just needed here to | ||
41 | * prepare the descriptors. | ||
42 | */ | ||
43 | lgdtl (machine_real_restart_gdt - r_base)(%ebx) | ||
44 | |||
45 | /* | ||
46 | * Load the data segment registers with 16-bit compatible values | ||
47 | */ | ||
48 | movl $16, %ecx | ||
49 | movl %ecx, %ds | ||
50 | movl %ecx, %es | ||
51 | movl %ecx, %fs | ||
52 | movl %ecx, %gs | ||
53 | movl %ecx, %ss | ||
54 | ljmpl $8, $1f - r_base | ||
55 | |||
56 | /* | ||
57 | * This is 16-bit protected mode code to disable paging and the cache, | ||
58 | * switch to real mode and jump to the BIOS reset code. | ||
59 | * | ||
60 | * The instruction that switches to real mode by writing to CR0 must be | ||
61 | * followed immediately by a far jump instruction, which set CS to a | ||
62 | * valid value for real mode, and flushes the prefetch queue to avoid | ||
63 | * running instructions that have already been decoded in protected | ||
64 | * mode. | ||
65 | * | ||
66 | * Clears all the flags except ET, especially PG (paging), PE | ||
67 | * (protected-mode enable) and TS (task switch for coprocessor state | ||
68 | * save). Flushes the TLB after paging has been disabled. Sets CD and | ||
69 | * NW, to disable the cache on a 486, and invalidates the cache. This | ||
70 | * is more like the state of a 486 after reset. I don't know if | ||
71 | * something else should be done for other chips. | ||
72 | * | ||
73 | * More could be done here to set up the registers as if a CPU reset had | ||
74 | * occurred; hopefully real BIOSs don't assume much. This is not the | ||
75 | * actual BIOS entry point, anyway (that is at 0xfffffff0). | ||
76 | * | ||
77 | * Most of this work is probably excessive, but it is what is tested. | ||
78 | */ | ||
79 | .code16 | ||
80 | 1: | ||
81 | xorl %ecx, %ecx | ||
82 | movl %cr0, %eax | ||
83 | andl $0x00000011, %eax | ||
84 | orl $0x60000000, %eax | ||
85 | movl %eax, %cr0 | ||
86 | movl %ecx, %cr3 | ||
87 | movl %cr0, %edx | ||
88 | andl $0x60000000, %edx /* If no cache bits -> no wbinvd */ | ||
89 | jz 2f | ||
90 | wbinvd | ||
91 | 2: | ||
92 | andb $0x10, %al | ||
93 | movl %eax, %cr0 | ||
94 | .byte 0xea /* ljmpw */ | ||
95 | 101: .word 0 /* Offset */ | ||
96 | 102: .word 0 /* Segment */ | ||
97 | |||
98 | bios: | ||
99 | ljmpw $0xf000, $0xfff0 | ||
100 | |||
101 | apm: | ||
102 | movw $0x1000, %ax | ||
103 | movw %ax, %ss | ||
104 | movw $0xf000, %sp | ||
105 | movw $0x5307, %ax | ||
106 | movw $0x0001, %bx | ||
107 | movw $0x0003, %cx | ||
108 | int $0x15 | ||
109 | |||
110 | END(machine_real_restart_asm) | ||
111 | |||
112 | .balign 16 | ||
113 | /* These must match <asm/reboot.h */ | ||
114 | dispatch_table: | ||
115 | .word bios - r_base | ||
116 | .word apm - r_base | ||
117 | END(dispatch_table) | ||
118 | |||
119 | .balign 16 | ||
120 | machine_real_restart_idt: | ||
121 | .word 0xffff /* Length - real mode default value */ | ||
122 | .long 0 /* Base - real mode default value */ | ||
123 | END(machine_real_restart_idt) | ||
124 | |||
125 | .balign 16 | ||
126 | ENTRY(machine_real_restart_gdt) | ||
127 | .quad 0 /* Self-pointer, filled in by PM code */ | ||
128 | .quad 0 /* 16-bit code segment, filled in by PM code */ | ||
129 | /* | ||
130 | * 16-bit data segment with the selector value 16 = 0x10 and | ||
131 | * base value 0x100; since this is consistent with real mode | ||
132 | * semantics we don't have to reload the segments once CR0.PE = 0. | ||
133 | */ | ||
134 | .quad GDT_ENTRY(0x0093, 0x100, 0xffff) | ||
135 | END(machine_real_restart_gdt) | ||
diff --git a/arch/x86/kernel/sys_i386_32.c b/arch/x86/kernel/sys_i386_32.c new file mode 100644 index 00000000000..0b0cb5fede1 --- /dev/null +++ b/arch/x86/kernel/sys_i386_32.c | |||
@@ -0,0 +1,40 @@ | |||
1 | /* | ||
2 | * This file contains various random system calls that | ||
3 | * have a non-standard calling sequence on the Linux/i386 | ||
4 | * platform. | ||
5 | */ | ||
6 | |||
7 | #include <linux/errno.h> | ||
8 | #include <linux/sched.h> | ||
9 | #include <linux/mm.h> | ||
10 | #include <linux/fs.h> | ||
11 | #include <linux/smp.h> | ||
12 | #include <linux/sem.h> | ||
13 | #include <linux/msg.h> | ||
14 | #include <linux/shm.h> | ||
15 | #include <linux/stat.h> | ||
16 | #include <linux/syscalls.h> | ||
17 | #include <linux/mman.h> | ||
18 | #include <linux/file.h> | ||
19 | #include <linux/utsname.h> | ||
20 | #include <linux/ipc.h> | ||
21 | |||
22 | #include <linux/uaccess.h> | ||
23 | #include <linux/unistd.h> | ||
24 | |||
25 | #include <asm/syscalls.h> | ||
26 | |||
27 | /* | ||
28 | * Do a system call from kernel instead of calling sys_execve so we | ||
29 | * end up with proper pt_regs. | ||
30 | */ | ||
31 | int kernel_execve(const char *filename, | ||
32 | const char *const argv[], | ||
33 | const char *const envp[]) | ||
34 | { | ||
35 | long __res; | ||
36 | asm volatile ("int $0x80" | ||
37 | : "=a" (__res) | ||
38 | : "0" (__NR_execve), "b" (filename), "c" (argv), "d" (envp) : "memory"); | ||
39 | return __res; | ||
40 | } | ||
diff --git a/arch/x86/kernel/syscall_table_32.S b/arch/x86/kernel/syscall_table_32.S new file mode 100644 index 00000000000..bc19be332bc --- /dev/null +++ b/arch/x86/kernel/syscall_table_32.S | |||
@@ -0,0 +1,348 @@ | |||
1 | ENTRY(sys_call_table) | ||
2 | .long sys_restart_syscall /* 0 - old "setup()" system call, used for restarting */ | ||
3 | .long sys_exit | ||
4 | .long ptregs_fork | ||
5 | .long sys_read | ||
6 | .long sys_write | ||
7 | .long sys_open /* 5 */ | ||
8 | .long sys_close | ||
9 | .long sys_waitpid | ||
10 | .long sys_creat | ||
11 | .long sys_link | ||
12 | .long sys_unlink /* 10 */ | ||
13 | .long ptregs_execve | ||
14 | .long sys_chdir | ||
15 | .long sys_time | ||
16 | .long sys_mknod | ||
17 | .long sys_chmod /* 15 */ | ||
18 | .long sys_lchown16 | ||
19 | .long sys_ni_syscall /* old break syscall holder */ | ||
20 | .long sys_stat | ||
21 | .long sys_lseek | ||
22 | .long sys_getpid /* 20 */ | ||
23 | .long sys_mount | ||
24 | .long sys_oldumount | ||
25 | .long sys_setuid16 | ||
26 | .long sys_getuid16 | ||
27 | .long sys_stime /* 25 */ | ||
28 | .long sys_ptrace | ||
29 | .long sys_alarm | ||
30 | .long sys_fstat | ||
31 | .long sys_pause | ||
32 | .long sys_utime /* 30 */ | ||
33 | .long sys_ni_syscall /* old stty syscall holder */ | ||
34 | .long sys_ni_syscall /* old gtty syscall holder */ | ||
35 | .long sys_access | ||
36 | .long sys_nice | ||
37 | .long sys_ni_syscall /* 35 - old ftime syscall holder */ | ||
38 | .long sys_sync | ||
39 | .long sys_kill | ||
40 | .long sys_rename | ||
41 | .long sys_mkdir | ||
42 | .long sys_rmdir /* 40 */ | ||
43 | .long sys_dup | ||
44 | .long sys_pipe | ||
45 | .long sys_times | ||
46 | .long sys_ni_syscall /* old prof syscall holder */ | ||
47 | .long sys_brk /* 45 */ | ||
48 | .long sys_setgid16 | ||
49 | .long sys_getgid16 | ||
50 | .long sys_signal | ||
51 | .long sys_geteuid16 | ||
52 | .long sys_getegid16 /* 50 */ | ||
53 | .long sys_acct | ||
54 | .long sys_umount /* recycled never used phys() */ | ||
55 | .long sys_ni_syscall /* old lock syscall holder */ | ||
56 | .long sys_ioctl | ||
57 | .long sys_fcntl /* 55 */ | ||
58 | .long sys_ni_syscall /* old mpx syscall holder */ | ||
59 | .long sys_setpgid | ||
60 | .long sys_ni_syscall /* old ulimit syscall holder */ | ||
61 | .long sys_olduname | ||
62 | .long sys_umask /* 60 */ | ||
63 | .long sys_chroot | ||
64 | .long sys_ustat | ||
65 | .long sys_dup2 | ||
66 | .long sys_getppid | ||
67 | .long sys_getpgrp /* 65 */ | ||
68 | .long sys_setsid | ||
69 | .long sys_sigaction | ||
70 | .long sys_sgetmask | ||
71 | .long sys_ssetmask | ||
72 | .long sys_setreuid16 /* 70 */ | ||
73 | .long sys_setregid16 | ||
74 | .long sys_sigsuspend | ||
75 | .long sys_sigpending | ||
76 | .long sys_sethostname | ||
77 | .long sys_setrlimit /* 75 */ | ||
78 | .long sys_old_getrlimit | ||
79 | .long sys_getrusage | ||
80 | .long sys_gettimeofday | ||
81 | .long sys_settimeofday | ||
82 | .long sys_getgroups16 /* 80 */ | ||
83 | .long sys_setgroups16 | ||
84 | .long sys_old_select | ||
85 | .long sys_symlink | ||
86 | .long sys_lstat | ||
87 | .long sys_readlink /* 85 */ | ||
88 | .long sys_uselib | ||
89 | .long sys_swapon | ||
90 | .long sys_reboot | ||
91 | .long sys_old_readdir | ||
92 | .long sys_old_mmap /* 90 */ | ||
93 | .long sys_munmap | ||
94 | .long sys_truncate | ||
95 | .long sys_ftruncate | ||
96 | .long sys_fchmod | ||
97 | .long sys_fchown16 /* 95 */ | ||
98 | .long sys_getpriority | ||
99 | .long sys_setpriority | ||
100 | .long sys_ni_syscall /* old profil syscall holder */ | ||
101 | .long sys_statfs | ||
102 | .long sys_fstatfs /* 100 */ | ||
103 | .long sys_ioperm | ||
104 | .long sys_socketcall | ||
105 | .long sys_syslog | ||
106 | .long sys_setitimer | ||
107 | .long sys_getitimer /* 105 */ | ||
108 | .long sys_newstat | ||
109 | .long sys_newlstat | ||
110 | .long sys_newfstat | ||
111 | .long sys_uname | ||
112 | .long ptregs_iopl /* 110 */ | ||
113 | .long sys_vhangup | ||
114 | .long sys_ni_syscall /* old "idle" system call */ | ||
115 | .long ptregs_vm86old | ||
116 | .long sys_wait4 | ||
117 | .long sys_swapoff /* 115 */ | ||
118 | .long sys_sysinfo | ||
119 | .long sys_ipc | ||
120 | .long sys_fsync | ||
121 | .long ptregs_sigreturn | ||
122 | .long ptregs_clone /* 120 */ | ||
123 | .long sys_setdomainname | ||
124 | .long sys_newuname | ||
125 | .long sys_modify_ldt | ||
126 | .long sys_adjtimex | ||
127 | .long sys_mprotect /* 125 */ | ||
128 | .long sys_sigprocmask | ||
129 | .long sys_ni_syscall /* old "create_module" */ | ||
130 | .long sys_init_module | ||
131 | .long sys_delete_module | ||
132 | .long sys_ni_syscall /* 130: old "get_kernel_syms" */ | ||
133 | .long sys_quotactl | ||
134 | .long sys_getpgid | ||
135 | .long sys_fchdir | ||
136 | .long sys_bdflush | ||
137 | .long sys_sysfs /* 135 */ | ||
138 | .long sys_personality | ||
139 | .long sys_ni_syscall /* reserved for afs_syscall */ | ||
140 | .long sys_setfsuid16 | ||
141 | .long sys_setfsgid16 | ||
142 | .long sys_llseek /* 140 */ | ||
143 | .long sys_getdents | ||
144 | .long sys_select | ||
145 | .long sys_flock | ||
146 | .long sys_msync | ||
147 | .long sys_readv /* 145 */ | ||
148 | .long sys_writev | ||
149 | .long sys_getsid | ||
150 | .long sys_fdatasync | ||
151 | .long sys_sysctl | ||
152 | .long sys_mlock /* 150 */ | ||
153 | .long sys_munlock | ||
154 | .long sys_mlockall | ||
155 | .long sys_munlockall | ||
156 | .long sys_sched_setparam | ||
157 | .long sys_sched_getparam /* 155 */ | ||
158 | .long sys_sched_setscheduler | ||
159 | .long sys_sched_getscheduler | ||
160 | .long sys_sched_yield | ||
161 | .long sys_sched_get_priority_max | ||
162 | .long sys_sched_get_priority_min /* 160 */ | ||
163 | .long sys_sched_rr_get_interval | ||
164 | .long sys_nanosleep | ||
165 | .long sys_mremap | ||
166 | .long sys_setresuid16 | ||
167 | .long sys_getresuid16 /* 165 */ | ||
168 | .long ptregs_vm86 | ||
169 | .long sys_ni_syscall /* Old sys_query_module */ | ||
170 | .long sys_poll | ||
171 | .long sys_ni_syscall /* Old nfsservctl */ | ||
172 | .long sys_setresgid16 /* 170 */ | ||
173 | .long sys_getresgid16 | ||
174 | .long sys_prctl | ||
175 | .long ptregs_rt_sigreturn | ||
176 | .long sys_rt_sigaction | ||
177 | .long sys_rt_sigprocmask /* 175 */ | ||
178 | .long sys_rt_sigpending | ||
179 | .long sys_rt_sigtimedwait | ||
180 | .long sys_rt_sigqueueinfo | ||
181 | .long sys_rt_sigsuspend | ||
182 | .long sys_pread64 /* 180 */ | ||
183 | .long sys_pwrite64 | ||
184 | .long sys_chown16 | ||
185 | .long sys_getcwd | ||
186 | .long sys_capget | ||
187 | .long sys_capset /* 185 */ | ||
188 | .long ptregs_sigaltstack | ||
189 | .long sys_sendfile | ||
190 | .long sys_ni_syscall /* reserved for streams1 */ | ||
191 | .long sys_ni_syscall /* reserved for streams2 */ | ||
192 | .long ptregs_vfork /* 190 */ | ||
193 | .long sys_getrlimit | ||
194 | .long sys_mmap_pgoff | ||
195 | .long sys_truncate64 | ||
196 | .long sys_ftruncate64 | ||
197 | .long sys_stat64 /* 195 */ | ||
198 | .long sys_lstat64 | ||
199 | .long sys_fstat64 | ||
200 | .long sys_lchown | ||
201 | .long sys_getuid | ||
202 | .long sys_getgid /* 200 */ | ||
203 | .long sys_geteuid | ||
204 | .long sys_getegid | ||
205 | .long sys_setreuid | ||
206 | .long sys_setregid | ||
207 | .long sys_getgroups /* 205 */ | ||
208 | .long sys_setgroups | ||
209 | .long sys_fchown | ||
210 | .long sys_setresuid | ||
211 | .long sys_getresuid | ||
212 | .long sys_setresgid /* 210 */ | ||
213 | .long sys_getresgid | ||
214 | .long sys_chown | ||
215 | .long sys_setuid | ||
216 | .long sys_setgid | ||
217 | .long sys_setfsuid /* 215 */ | ||
218 | .long sys_setfsgid | ||
219 | .long sys_pivot_root | ||
220 | .long sys_mincore | ||
221 | .long sys_madvise | ||
222 | .long sys_getdents64 /* 220 */ | ||
223 | .long sys_fcntl64 | ||
224 | .long sys_ni_syscall /* reserved for TUX */ | ||
225 | .long sys_ni_syscall | ||
226 | .long sys_gettid | ||
227 | .long sys_readahead /* 225 */ | ||
228 | .long sys_setxattr | ||
229 | .long sys_lsetxattr | ||
230 | .long sys_fsetxattr | ||
231 | .long sys_getxattr | ||
232 | .long sys_lgetxattr /* 230 */ | ||
233 | .long sys_fgetxattr | ||
234 | .long sys_listxattr | ||
235 | .long sys_llistxattr | ||
236 | .long sys_flistxattr | ||
237 | .long sys_removexattr /* 235 */ | ||
238 | .long sys_lremovexattr | ||
239 | .long sys_fremovexattr | ||
240 | .long sys_tkill | ||
241 | .long sys_sendfile64 | ||
242 | .long sys_futex /* 240 */ | ||
243 | .long sys_sched_setaffinity | ||
244 | .long sys_sched_getaffinity | ||
245 | .long sys_set_thread_area | ||
246 | .long sys_get_thread_area | ||
247 | .long sys_io_setup /* 245 */ | ||
248 | .long sys_io_destroy | ||
249 | .long sys_io_getevents | ||
250 | .long sys_io_submit | ||
251 | .long sys_io_cancel | ||
252 | .long sys_fadvise64 /* 250 */ | ||
253 | .long sys_ni_syscall | ||
254 | .long sys_exit_group | ||
255 | .long sys_lookup_dcookie | ||
256 | .long sys_epoll_create | ||
257 | .long sys_epoll_ctl /* 255 */ | ||
258 | .long sys_epoll_wait | ||
259 | .long sys_remap_file_pages | ||
260 | .long sys_set_tid_address | ||
261 | .long sys_timer_create | ||
262 | .long sys_timer_settime /* 260 */ | ||
263 | .long sys_timer_gettime | ||
264 | .long sys_timer_getoverrun | ||
265 | .long sys_timer_delete | ||
266 | .long sys_clock_settime | ||
267 | .long sys_clock_gettime /* 265 */ | ||
268 | .long sys_clock_getres | ||
269 | .long sys_clock_nanosleep | ||
270 | .long sys_statfs64 | ||
271 | .long sys_fstatfs64 | ||
272 | .long sys_tgkill /* 270 */ | ||
273 | .long sys_utimes | ||
274 | .long sys_fadvise64_64 | ||
275 | .long sys_ni_syscall /* sys_vserver */ | ||
276 | .long sys_mbind | ||
277 | .long sys_get_mempolicy | ||
278 | .long sys_set_mempolicy | ||
279 | .long sys_mq_open | ||
280 | .long sys_mq_unlink | ||
281 | .long sys_mq_timedsend | ||
282 | .long sys_mq_timedreceive /* 280 */ | ||
283 | .long sys_mq_notify | ||
284 | .long sys_mq_getsetattr | ||
285 | .long sys_kexec_load | ||
286 | .long sys_waitid | ||
287 | .long sys_ni_syscall /* 285 */ /* available */ | ||
288 | .long sys_add_key | ||
289 | .long sys_request_key | ||
290 | .long sys_keyctl | ||
291 | .long sys_ioprio_set | ||
292 | .long sys_ioprio_get /* 290 */ | ||
293 | .long sys_inotify_init | ||
294 | .long sys_inotify_add_watch | ||
295 | .long sys_inotify_rm_watch | ||
296 | .long sys_migrate_pages | ||
297 | .long sys_openat /* 295 */ | ||
298 | .long sys_mkdirat | ||
299 | .long sys_mknodat | ||
300 | .long sys_fchownat | ||
301 | .long sys_futimesat | ||
302 | .long sys_fstatat64 /* 300 */ | ||
303 | .long sys_unlinkat | ||
304 | .long sys_renameat | ||
305 | .long sys_linkat | ||
306 | .long sys_symlinkat | ||
307 | .long sys_readlinkat /* 305 */ | ||
308 | .long sys_fchmodat | ||
309 | .long sys_faccessat | ||
310 | .long sys_pselect6 | ||
311 | .long sys_ppoll | ||
312 | .long sys_unshare /* 310 */ | ||
313 | .long sys_set_robust_list | ||
314 | .long sys_get_robust_list | ||
315 | .long sys_splice | ||
316 | .long sys_sync_file_range | ||
317 | .long sys_tee /* 315 */ | ||
318 | .long sys_vmsplice | ||
319 | .long sys_move_pages | ||
320 | .long sys_getcpu | ||
321 | .long sys_epoll_pwait | ||
322 | .long sys_utimensat /* 320 */ | ||
323 | .long sys_signalfd | ||
324 | .long sys_timerfd_create | ||
325 | .long sys_eventfd | ||
326 | .long sys_fallocate | ||
327 | .long sys_timerfd_settime /* 325 */ | ||
328 | .long sys_timerfd_gettime | ||
329 | .long sys_signalfd4 | ||
330 | .long sys_eventfd2 | ||
331 | .long sys_epoll_create1 | ||
332 | .long sys_dup3 /* 330 */ | ||
333 | .long sys_pipe2 | ||
334 | .long sys_inotify_init1 | ||
335 | .long sys_preadv | ||
336 | .long sys_pwritev | ||
337 | .long sys_rt_tgsigqueueinfo /* 335 */ | ||
338 | .long sys_perf_event_open | ||
339 | .long sys_recvmmsg | ||
340 | .long sys_fanotify_init | ||
341 | .long sys_fanotify_mark | ||
342 | .long sys_prlimit64 /* 340 */ | ||
343 | .long sys_name_to_handle_at | ||
344 | .long sys_open_by_handle_at | ||
345 | .long sys_clock_adjtime | ||
346 | .long sys_syncfs | ||
347 | .long sys_sendmmsg /* 345 */ | ||
348 | .long sys_setns | ||
diff --git a/arch/x86/kernel/trampoline.c b/arch/x86/kernel/trampoline.c new file mode 100644 index 00000000000..a91ae7709b4 --- /dev/null +++ b/arch/x86/kernel/trampoline.c | |||
@@ -0,0 +1,42 @@ | |||
1 | #include <linux/io.h> | ||
2 | #include <linux/memblock.h> | ||
3 | |||
4 | #include <asm/trampoline.h> | ||
5 | #include <asm/cacheflush.h> | ||
6 | #include <asm/pgtable.h> | ||
7 | |||
8 | unsigned char *x86_trampoline_base; | ||
9 | |||
10 | void __init setup_trampolines(void) | ||
11 | { | ||
12 | phys_addr_t mem; | ||
13 | size_t size = PAGE_ALIGN(x86_trampoline_end - x86_trampoline_start); | ||
14 | |||
15 | /* Has to be in very low memory so we can execute real-mode AP code. */ | ||
16 | mem = memblock_find_in_range(0, 1<<20, size, PAGE_SIZE); | ||
17 | if (mem == MEMBLOCK_ERROR) | ||
18 | panic("Cannot allocate trampoline\n"); | ||
19 | |||
20 | x86_trampoline_base = __va(mem); | ||
21 | memblock_x86_reserve_range(mem, mem + size, "TRAMPOLINE"); | ||
22 | |||
23 | printk(KERN_DEBUG "Base memory trampoline at [%p] %llx size %zu\n", | ||
24 | x86_trampoline_base, (unsigned long long)mem, size); | ||
25 | |||
26 | memcpy(x86_trampoline_base, x86_trampoline_start, size); | ||
27 | } | ||
28 | |||
29 | /* | ||
30 | * setup_trampolines() gets called very early, to guarantee the | ||
31 | * availability of low memory. This is before the proper kernel page | ||
32 | * tables are set up, so we cannot set page permissions in that | ||
33 | * function. Thus, we use an arch_initcall instead. | ||
34 | */ | ||
35 | static int __init configure_trampolines(void) | ||
36 | { | ||
37 | size_t size = PAGE_ALIGN(x86_trampoline_end - x86_trampoline_start); | ||
38 | |||
39 | set_memory_x((unsigned long)x86_trampoline_base, size >> PAGE_SHIFT); | ||
40 | return 0; | ||
41 | } | ||
42 | arch_initcall(configure_trampolines); | ||
diff --git a/arch/x86/kernel/trampoline_32.S b/arch/x86/kernel/trampoline_32.S new file mode 100644 index 00000000000..451c0a7ef7f --- /dev/null +++ b/arch/x86/kernel/trampoline_32.S | |||
@@ -0,0 +1,83 @@ | |||
1 | /* | ||
2 | * | ||
3 | * Trampoline.S Derived from Setup.S by Linus Torvalds | ||
4 | * | ||
5 | * 4 Jan 1997 Michael Chastain: changed to gnu as. | ||
6 | * | ||
7 | * This is only used for booting secondary CPUs in SMP machine | ||
8 | * | ||
9 | * Entry: CS:IP point to the start of our code, we are | ||
10 | * in real mode with no stack, but the rest of the | ||
11 | * trampoline page to make our stack and everything else | ||
12 | * is a mystery. | ||
13 | * | ||
14 | * We jump into arch/x86/kernel/head_32.S. | ||
15 | * | ||
16 | * On entry to trampoline_data, the processor is in real mode | ||
17 | * with 16-bit addressing and 16-bit data. CS has some value | ||
18 | * and IP is zero. Thus, data addresses need to be absolute | ||
19 | * (no relocation) and are taken with regard to r_base. | ||
20 | * | ||
21 | * If you work on this file, check the object module with | ||
22 | * objdump --reloc to make sure there are no relocation | ||
23 | * entries except for: | ||
24 | * | ||
25 | * TYPE VALUE | ||
26 | * R_386_32 startup_32_smp | ||
27 | * R_386_32 boot_gdt | ||
28 | */ | ||
29 | |||
30 | #include <linux/linkage.h> | ||
31 | #include <linux/init.h> | ||
32 | #include <asm/segment.h> | ||
33 | #include <asm/page_types.h> | ||
34 | |||
35 | #ifdef CONFIG_SMP | ||
36 | |||
37 | .section ".x86_trampoline","a" | ||
38 | .balign PAGE_SIZE | ||
39 | .code16 | ||
40 | |||
41 | ENTRY(trampoline_data) | ||
42 | r_base = . | ||
43 | wbinvd # Needed for NUMA-Q should be harmless for others | ||
44 | mov %cs, %ax # Code and data in the same place | ||
45 | mov %ax, %ds | ||
46 | |||
47 | cli # We should be safe anyway | ||
48 | |||
49 | movl $0xA5A5A5A5, trampoline_status - r_base | ||
50 | # write marker for master knows we're running | ||
51 | |||
52 | /* GDT tables in non default location kernel can be beyond 16MB and | ||
53 | * lgdt will not be able to load the address as in real mode default | ||
54 | * operand size is 16bit. Use lgdtl instead to force operand size | ||
55 | * to 32 bit. | ||
56 | */ | ||
57 | |||
58 | lidtl boot_idt_descr - r_base # load idt with 0, 0 | ||
59 | lgdtl boot_gdt_descr - r_base # load gdt with whatever is appropriate | ||
60 | |||
61 | xor %ax, %ax | ||
62 | inc %ax # protected mode (PE) bit | ||
63 | lmsw %ax # into protected mode | ||
64 | # flush prefetch and jump to startup_32_smp in arch/i386/kernel/head.S | ||
65 | ljmpl $__BOOT_CS, $(startup_32_smp-__PAGE_OFFSET) | ||
66 | |||
67 | # These need to be in the same 64K segment as the above; | ||
68 | # hence we don't use the boot_gdt_descr defined in head.S | ||
69 | boot_gdt_descr: | ||
70 | .word __BOOT_DS + 7 # gdt limit | ||
71 | .long boot_gdt - __PAGE_OFFSET # gdt base | ||
72 | |||
73 | boot_idt_descr: | ||
74 | .word 0 # idt limit = 0 | ||
75 | .long 0 # idt base = 0L | ||
76 | |||
77 | ENTRY(trampoline_status) | ||
78 | .long 0 | ||
79 | |||
80 | .globl trampoline_end | ||
81 | trampoline_end: | ||
82 | |||
83 | #endif /* CONFIG_SMP */ | ||
diff --git a/arch/x86/kernel/trampoline_64.S b/arch/x86/kernel/trampoline_64.S new file mode 100644 index 00000000000..09ff51799e9 --- /dev/null +++ b/arch/x86/kernel/trampoline_64.S | |||
@@ -0,0 +1,171 @@ | |||
1 | /* | ||
2 | * | ||
3 | * Trampoline.S Derived from Setup.S by Linus Torvalds | ||
4 | * | ||
5 | * 4 Jan 1997 Michael Chastain: changed to gnu as. | ||
6 | * 15 Sept 2005 Eric Biederman: 64bit PIC support | ||
7 | * | ||
8 | * Entry: CS:IP point to the start of our code, we are | ||
9 | * in real mode with no stack, but the rest of the | ||
10 | * trampoline page to make our stack and everything else | ||
11 | * is a mystery. | ||
12 | * | ||
13 | * On entry to trampoline_data, the processor is in real mode | ||
14 | * with 16-bit addressing and 16-bit data. CS has some value | ||
15 | * and IP is zero. Thus, data addresses need to be absolute | ||
16 | * (no relocation) and are taken with regard to r_base. | ||
17 | * | ||
18 | * With the addition of trampoline_level4_pgt this code can | ||
19 | * now enter a 64bit kernel that lives at arbitrary 64bit | ||
20 | * physical addresses. | ||
21 | * | ||
22 | * If you work on this file, check the object module with objdump | ||
23 | * --full-contents --reloc to make sure there are no relocation | ||
24 | * entries. | ||
25 | */ | ||
26 | |||
27 | #include <linux/linkage.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <asm/pgtable_types.h> | ||
30 | #include <asm/page_types.h> | ||
31 | #include <asm/msr.h> | ||
32 | #include <asm/segment.h> | ||
33 | #include <asm/processor-flags.h> | ||
34 | |||
35 | .section ".x86_trampoline","a" | ||
36 | .balign PAGE_SIZE | ||
37 | .code16 | ||
38 | |||
39 | ENTRY(trampoline_data) | ||
40 | r_base = . | ||
41 | cli # We should be safe anyway | ||
42 | wbinvd | ||
43 | mov %cs, %ax # Code and data in the same place | ||
44 | mov %ax, %ds | ||
45 | mov %ax, %es | ||
46 | mov %ax, %ss | ||
47 | |||
48 | |||
49 | movl $0xA5A5A5A5, trampoline_status - r_base | ||
50 | # write marker for master knows we're running | ||
51 | |||
52 | # Setup stack | ||
53 | movw $(trampoline_stack_end - r_base), %sp | ||
54 | |||
55 | call verify_cpu # Verify the cpu supports long mode | ||
56 | testl %eax, %eax # Check for return code | ||
57 | jnz no_longmode | ||
58 | |||
59 | mov %cs, %ax | ||
60 | movzx %ax, %esi # Find the 32bit trampoline location | ||
61 | shll $4, %esi | ||
62 | |||
63 | # Fixup the absolute vectors | ||
64 | leal (startup_32 - r_base)(%esi), %eax | ||
65 | movl %eax, startup_32_vector - r_base | ||
66 | leal (startup_64 - r_base)(%esi), %eax | ||
67 | movl %eax, startup_64_vector - r_base | ||
68 | leal (tgdt - r_base)(%esi), %eax | ||
69 | movl %eax, (tgdt + 2 - r_base) | ||
70 | |||
71 | /* | ||
72 | * GDT tables in non default location kernel can be beyond 16MB and | ||
73 | * lgdt will not be able to load the address as in real mode default | ||
74 | * operand size is 16bit. Use lgdtl instead to force operand size | ||
75 | * to 32 bit. | ||
76 | */ | ||
77 | |||
78 | lidtl tidt - r_base # load idt with 0, 0 | ||
79 | lgdtl tgdt - r_base # load gdt with whatever is appropriate | ||
80 | |||
81 | mov $X86_CR0_PE, %ax # protected mode (PE) bit | ||
82 | lmsw %ax # into protected mode | ||
83 | |||
84 | # flush prefetch and jump to startup_32 | ||
85 | ljmpl *(startup_32_vector - r_base) | ||
86 | |||
87 | .code32 | ||
88 | .balign 4 | ||
89 | startup_32: | ||
90 | movl $__KERNEL_DS, %eax # Initialize the %ds segment register | ||
91 | movl %eax, %ds | ||
92 | |||
93 | movl $X86_CR4_PAE, %eax | ||
94 | movl %eax, %cr4 # Enable PAE mode | ||
95 | |||
96 | # Setup trampoline 4 level pagetables | ||
97 | leal (trampoline_level4_pgt - r_base)(%esi), %eax | ||
98 | movl %eax, %cr3 | ||
99 | |||
100 | movl $MSR_EFER, %ecx | ||
101 | movl $(1 << _EFER_LME), %eax # Enable Long Mode | ||
102 | xorl %edx, %edx | ||
103 | wrmsr | ||
104 | |||
105 | # Enable paging and in turn activate Long Mode | ||
106 | # Enable protected mode | ||
107 | movl $(X86_CR0_PG | X86_CR0_PE), %eax | ||
108 | movl %eax, %cr0 | ||
109 | |||
110 | /* | ||
111 | * At this point we're in long mode but in 32bit compatibility mode | ||
112 | * with EFER.LME = 1, CS.L = 0, CS.D = 1 (and in turn | ||
113 | * EFER.LMA = 1). Now we want to jump in 64bit mode, to do that we use | ||
114 | * the new gdt/idt that has __KERNEL_CS with CS.L = 1. | ||
115 | */ | ||
116 | ljmp *(startup_64_vector - r_base)(%esi) | ||
117 | |||
118 | .code64 | ||
119 | .balign 4 | ||
120 | startup_64: | ||
121 | # Now jump into the kernel using virtual addresses | ||
122 | movq $secondary_startup_64, %rax | ||
123 | jmp *%rax | ||
124 | |||
125 | .code16 | ||
126 | no_longmode: | ||
127 | hlt | ||
128 | jmp no_longmode | ||
129 | #include "verify_cpu.S" | ||
130 | |||
131 | .balign 4 | ||
132 | # Careful these need to be in the same 64K segment as the above; | ||
133 | tidt: | ||
134 | .word 0 # idt limit = 0 | ||
135 | .word 0, 0 # idt base = 0L | ||
136 | |||
137 | # Duplicate the global descriptor table | ||
138 | # so the kernel can live anywhere | ||
139 | .balign 4 | ||
140 | tgdt: | ||
141 | .short tgdt_end - tgdt # gdt limit | ||
142 | .long tgdt - r_base | ||
143 | .short 0 | ||
144 | .quad 0x00cf9b000000ffff # __KERNEL32_CS | ||
145 | .quad 0x00af9b000000ffff # __KERNEL_CS | ||
146 | .quad 0x00cf93000000ffff # __KERNEL_DS | ||
147 | tgdt_end: | ||
148 | |||
149 | .balign 4 | ||
150 | startup_32_vector: | ||
151 | .long startup_32 - r_base | ||
152 | .word __KERNEL32_CS, 0 | ||
153 | |||
154 | .balign 4 | ||
155 | startup_64_vector: | ||
156 | .long startup_64 - r_base | ||
157 | .word __KERNEL_CS, 0 | ||
158 | |||
159 | .balign 4 | ||
160 | ENTRY(trampoline_status) | ||
161 | .long 0 | ||
162 | |||
163 | trampoline_stack: | ||
164 | .org 0x1000 | ||
165 | trampoline_stack_end: | ||
166 | ENTRY(trampoline_level4_pgt) | ||
167 | .quad level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE | ||
168 | .fill 510,8,0 | ||
169 | .quad level3_kernel_pgt - __START_KERNEL_map + _KERNPG_TABLE | ||
170 | |||
171 | ENTRY(trampoline_end) | ||