diff options
Diffstat (limited to 'arch/x86/kernel')
-rw-r--r-- | arch/x86/kernel/Makefile | 1 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/common.c | 6 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/intel.c | 4 | ||||
-rw-r--r-- | arch/x86/kernel/entry_32.S | 3 | ||||
-rw-r--r-- | arch/x86/kernel/entry_64.S | 3 | ||||
-rw-r--r-- | arch/x86/kernel/head_32.S | 3 | ||||
-rw-r--r-- | arch/x86/kernel/head_64.S | 4 | ||||
-rw-r--r-- | arch/x86/kernel/kprobes/core.c | 54 | ||||
-rw-r--r-- | arch/x86/kernel/kprobes/opt.c | 2 | ||||
-rw-r--r-- | arch/x86/kernel/process_64.c | 2 | ||||
-rw-r--r-- | arch/x86/kernel/ptrace.c | 10 | ||||
-rw-r--r-- | arch/x86/kernel/syscall_32.c | 16 | ||||
-rw-r--r-- | arch/x86/kernel/traps.c | 21 |
13 files changed, 95 insertions, 34 deletions
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index cdb1b70ddad0..c887cd944f0c 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile | |||
@@ -32,6 +32,7 @@ obj-$(CONFIG_X86_32) += i386_ksyms_32.o | |||
32 | obj-$(CONFIG_X86_64) += sys_x86_64.o x8664_ksyms_64.o | 32 | obj-$(CONFIG_X86_64) += sys_x86_64.o x8664_ksyms_64.o |
33 | obj-$(CONFIG_X86_64) += mcount_64.o | 33 | obj-$(CONFIG_X86_64) += mcount_64.o |
34 | obj-y += syscall_$(BITS).o vsyscall_gtod.o | 34 | obj-y += syscall_$(BITS).o vsyscall_gtod.o |
35 | obj-$(CONFIG_IA32_EMULATION) += syscall_32.o | ||
35 | obj-$(CONFIG_X86_VSYSCALL_EMULATION) += vsyscall_64.o vsyscall_emu_64.o | 36 | obj-$(CONFIG_X86_VSYSCALL_EMULATION) += vsyscall_64.o vsyscall_emu_64.o |
36 | obj-$(CONFIG_X86_ESPFIX64) += espfix_64.o | 37 | obj-$(CONFIG_X86_ESPFIX64) += espfix_64.o |
37 | obj-$(CONFIG_SYSFS) += ksysfs.o | 38 | obj-$(CONFIG_SYSFS) += ksysfs.o |
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index b5c8ff5e9dfc..2346c95c6ab1 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c | |||
@@ -1396,6 +1396,12 @@ void cpu_init(void) | |||
1396 | 1396 | ||
1397 | wait_for_master_cpu(cpu); | 1397 | wait_for_master_cpu(cpu); |
1398 | 1398 | ||
1399 | /* | ||
1400 | * Initialize the CR4 shadow before doing anything that could | ||
1401 | * try to read it. | ||
1402 | */ | ||
1403 | cr4_init_shadow(); | ||
1404 | |||
1399 | show_ucode_info_early(); | 1405 | show_ucode_info_early(); |
1400 | 1406 | ||
1401 | printk(KERN_INFO "Initializing CPU#%d\n", cpu); | 1407 | printk(KERN_INFO "Initializing CPU#%d\n", cpu); |
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index 94d7dcb12145..50163fa9034f 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c | |||
@@ -565,8 +565,8 @@ static const struct _tlb_table intel_tlb_table[] = { | |||
565 | { 0xb2, TLB_INST_4K, 64, " TLB_INST 4KByte pages, 4-way set associative" }, | 565 | { 0xb2, TLB_INST_4K, 64, " TLB_INST 4KByte pages, 4-way set associative" }, |
566 | { 0xb3, TLB_DATA_4K, 128, " TLB_DATA 4 KByte pages, 4-way set associative" }, | 566 | { 0xb3, TLB_DATA_4K, 128, " TLB_DATA 4 KByte pages, 4-way set associative" }, |
567 | { 0xb4, TLB_DATA_4K, 256, " TLB_DATA 4 KByte pages, 4-way associative" }, | 567 | { 0xb4, TLB_DATA_4K, 256, " TLB_DATA 4 KByte pages, 4-way associative" }, |
568 | { 0xb5, TLB_INST_4K, 64, " TLB_INST 4 KByte pages, 8-way set ssociative" }, | 568 | { 0xb5, TLB_INST_4K, 64, " TLB_INST 4 KByte pages, 8-way set associative" }, |
569 | { 0xb6, TLB_INST_4K, 128, " TLB_INST 4 KByte pages, 8-way set ssociative" }, | 569 | { 0xb6, TLB_INST_4K, 128, " TLB_INST 4 KByte pages, 8-way set associative" }, |
570 | { 0xba, TLB_DATA_4K, 64, " TLB_DATA 4 KByte pages, 4-way associative" }, | 570 | { 0xba, TLB_DATA_4K, 64, " TLB_DATA 4 KByte pages, 4-way associative" }, |
571 | { 0xc0, TLB_DATA_4K_4M, 8, " TLB_DATA 4 KByte and 4 MByte pages, 4-way associative" }, | 571 | { 0xc0, TLB_DATA_4K_4M, 8, " TLB_DATA 4 KByte and 4 MByte pages, 4-way associative" }, |
572 | { 0xc1, STLB_4K_2M, 1024, " STLB 4 KByte and 2 MByte pages, 8-way associative" }, | 572 | { 0xc1, STLB_4K_2M, 1024, " STLB 4 KByte and 2 MByte pages, 8-way associative" }, |
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S index b910577d1ff9..7e0323cc0b7d 100644 --- a/arch/x86/kernel/entry_32.S +++ b/arch/x86/kernel/entry_32.S | |||
@@ -976,6 +976,9 @@ ENTRY(xen_hypervisor_callback) | |||
976 | ENTRY(xen_do_upcall) | 976 | ENTRY(xen_do_upcall) |
977 | 1: mov %esp, %eax | 977 | 1: mov %esp, %eax |
978 | call xen_evtchn_do_upcall | 978 | call xen_evtchn_do_upcall |
979 | #ifndef CONFIG_PREEMPT | ||
980 | call xen_maybe_preempt_hcall | ||
981 | #endif | ||
979 | jmp ret_from_intr | 982 | jmp ret_from_intr |
980 | CFI_ENDPROC | 983 | CFI_ENDPROC |
981 | ENDPROC(xen_hypervisor_callback) | 984 | ENDPROC(xen_hypervisor_callback) |
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index db13655c3a2a..10074ad9ebf8 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S | |||
@@ -1208,6 +1208,9 @@ ENTRY(xen_do_hypervisor_callback) # do_hypervisor_callback(struct *pt_regs) | |||
1208 | popq %rsp | 1208 | popq %rsp |
1209 | CFI_DEF_CFA_REGISTER rsp | 1209 | CFI_DEF_CFA_REGISTER rsp |
1210 | decl PER_CPU_VAR(irq_count) | 1210 | decl PER_CPU_VAR(irq_count) |
1211 | #ifndef CONFIG_PREEMPT | ||
1212 | call xen_maybe_preempt_hcall | ||
1213 | #endif | ||
1211 | jmp error_exit | 1214 | jmp error_exit |
1212 | CFI_ENDPROC | 1215 | CFI_ENDPROC |
1213 | END(xen_do_hypervisor_callback) | 1216 | END(xen_do_hypervisor_callback) |
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S index f36bd42d6f0c..d031bad9e07e 100644 --- a/arch/x86/kernel/head_32.S +++ b/arch/x86/kernel/head_32.S | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <asm/cpufeature.h> | 22 | #include <asm/cpufeature.h> |
23 | #include <asm/percpu.h> | 23 | #include <asm/percpu.h> |
24 | #include <asm/nops.h> | 24 | #include <asm/nops.h> |
25 | #include <asm/bootparam.h> | ||
25 | 26 | ||
26 | /* Physical address */ | 27 | /* Physical address */ |
27 | #define pa(X) ((X) - __PAGE_OFFSET) | 28 | #define pa(X) ((X) - __PAGE_OFFSET) |
@@ -90,7 +91,7 @@ ENTRY(startup_32) | |||
90 | 91 | ||
91 | /* test KEEP_SEGMENTS flag to see if the bootloader is asking | 92 | /* test KEEP_SEGMENTS flag to see if the bootloader is asking |
92 | us to not reload segments */ | 93 | us to not reload segments */ |
93 | testb $(1<<6), BP_loadflags(%esi) | 94 | testb $KEEP_SEGMENTS, BP_loadflags(%esi) |
94 | jnz 2f | 95 | jnz 2f |
95 | 96 | ||
96 | /* | 97 | /* |
diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S index 6fd514d9f69a..9a0919678f97 100644 --- a/arch/x86/kernel/head_64.S +++ b/arch/x86/kernel/head_64.S | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/x86_64/kernel/head.S -- start in 32bit and switch to 64bit | 2 | * linux/arch/x86/kernel/head_64.S -- start in 32bit and switch to 64bit |
3 | * | 3 | * |
4 | * Copyright (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE | 4 | * Copyright (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE |
5 | * Copyright (C) 2000 Pavel Machek <pavel@suse.cz> | 5 | * Copyright (C) 2000 Pavel Machek <pavel@suse.cz> |
@@ -56,7 +56,7 @@ startup_64: | |||
56 | * %rsi holds a physical pointer to real_mode_data. | 56 | * %rsi holds a physical pointer to real_mode_data. |
57 | * | 57 | * |
58 | * We come here either directly from a 64bit bootloader, or from | 58 | * We come here either directly from a 64bit bootloader, or from |
59 | * arch/x86_64/boot/compressed/head.S. | 59 | * arch/x86/boot/compressed/head_64.S. |
60 | * | 60 | * |
61 | * We only come here initially at boot nothing else comes here. | 61 | * We only come here initially at boot nothing else comes here. |
62 | * | 62 | * |
diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c index 6a1146ea4d4d..4e3d5a9621fe 100644 --- a/arch/x86/kernel/kprobes/core.c +++ b/arch/x86/kernel/kprobes/core.c | |||
@@ -223,27 +223,48 @@ static unsigned long | |||
223 | __recover_probed_insn(kprobe_opcode_t *buf, unsigned long addr) | 223 | __recover_probed_insn(kprobe_opcode_t *buf, unsigned long addr) |
224 | { | 224 | { |
225 | struct kprobe *kp; | 225 | struct kprobe *kp; |
226 | unsigned long faddr; | ||
226 | 227 | ||
227 | kp = get_kprobe((void *)addr); | 228 | kp = get_kprobe((void *)addr); |
228 | /* There is no probe, return original address */ | 229 | faddr = ftrace_location(addr); |
229 | if (!kp) | 230 | /* |
231 | * Addresses inside the ftrace location are refused by | ||
232 | * arch_check_ftrace_location(). Something went terribly wrong | ||
233 | * if such an address is checked here. | ||
234 | */ | ||
235 | if (WARN_ON(faddr && faddr != addr)) | ||
236 | return 0UL; | ||
237 | /* | ||
238 | * Use the current code if it is not modified by Kprobe | ||
239 | * and it cannot be modified by ftrace. | ||
240 | */ | ||
241 | if (!kp && !faddr) | ||
230 | return addr; | 242 | return addr; |
231 | 243 | ||
232 | /* | 244 | /* |
233 | * Basically, kp->ainsn.insn has an original instruction. | 245 | * Basically, kp->ainsn.insn has an original instruction. |
234 | * However, RIP-relative instruction can not do single-stepping | 246 | * However, RIP-relative instruction can not do single-stepping |
235 | * at different place, __copy_instruction() tweaks the displacement of | 247 | * at different place, __copy_instruction() tweaks the displacement of |
236 | * that instruction. In that case, we can't recover the instruction | 248 | * that instruction. In that case, we can't recover the instruction |
237 | * from the kp->ainsn.insn. | 249 | * from the kp->ainsn.insn. |
238 | * | 250 | * |
239 | * On the other hand, kp->opcode has a copy of the first byte of | 251 | * On the other hand, in case on normal Kprobe, kp->opcode has a copy |
240 | * the probed instruction, which is overwritten by int3. And | 252 | * of the first byte of the probed instruction, which is overwritten |
241 | * the instruction at kp->addr is not modified by kprobes except | 253 | * by int3. And the instruction at kp->addr is not modified by kprobes |
242 | * for the first byte, we can recover the original instruction | 254 | * except for the first byte, we can recover the original instruction |
243 | * from it and kp->opcode. | 255 | * from it and kp->opcode. |
256 | * | ||
257 | * In case of Kprobes using ftrace, we do not have a copy of | ||
258 | * the original instruction. In fact, the ftrace location might | ||
259 | * be modified at anytime and even could be in an inconsistent state. | ||
260 | * Fortunately, we know that the original code is the ideal 5-byte | ||
261 | * long NOP. | ||
244 | */ | 262 | */ |
245 | memcpy(buf, kp->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); | 263 | memcpy(buf, (void *)addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); |
246 | buf[0] = kp->opcode; | 264 | if (faddr) |
265 | memcpy(buf, ideal_nops[NOP_ATOMIC5], 5); | ||
266 | else | ||
267 | buf[0] = kp->opcode; | ||
247 | return (unsigned long)buf; | 268 | return (unsigned long)buf; |
248 | } | 269 | } |
249 | 270 | ||
@@ -251,6 +272,7 @@ __recover_probed_insn(kprobe_opcode_t *buf, unsigned long addr) | |||
251 | * Recover the probed instruction at addr for further analysis. | 272 | * Recover the probed instruction at addr for further analysis. |
252 | * Caller must lock kprobes by kprobe_mutex, or disable preemption | 273 | * Caller must lock kprobes by kprobe_mutex, or disable preemption |
253 | * for preventing to release referencing kprobes. | 274 | * for preventing to release referencing kprobes. |
275 | * Returns zero if the instruction can not get recovered. | ||
254 | */ | 276 | */ |
255 | unsigned long recover_probed_instruction(kprobe_opcode_t *buf, unsigned long addr) | 277 | unsigned long recover_probed_instruction(kprobe_opcode_t *buf, unsigned long addr) |
256 | { | 278 | { |
@@ -285,6 +307,8 @@ static int can_probe(unsigned long paddr) | |||
285 | * normally used, we just go through if there is no kprobe. | 307 | * normally used, we just go through if there is no kprobe. |
286 | */ | 308 | */ |
287 | __addr = recover_probed_instruction(buf, addr); | 309 | __addr = recover_probed_instruction(buf, addr); |
310 | if (!__addr) | ||
311 | return 0; | ||
288 | kernel_insn_init(&insn, (void *)__addr, MAX_INSN_SIZE); | 312 | kernel_insn_init(&insn, (void *)__addr, MAX_INSN_SIZE); |
289 | insn_get_length(&insn); | 313 | insn_get_length(&insn); |
290 | 314 | ||
@@ -333,6 +357,8 @@ int __copy_instruction(u8 *dest, u8 *src) | |||
333 | unsigned long recovered_insn = | 357 | unsigned long recovered_insn = |
334 | recover_probed_instruction(buf, (unsigned long)src); | 358 | recover_probed_instruction(buf, (unsigned long)src); |
335 | 359 | ||
360 | if (!recovered_insn) | ||
361 | return 0; | ||
336 | kernel_insn_init(&insn, (void *)recovered_insn, MAX_INSN_SIZE); | 362 | kernel_insn_init(&insn, (void *)recovered_insn, MAX_INSN_SIZE); |
337 | insn_get_length(&insn); | 363 | insn_get_length(&insn); |
338 | /* Another subsystem puts a breakpoint, failed to recover */ | 364 | /* Another subsystem puts a breakpoint, failed to recover */ |
diff --git a/arch/x86/kernel/kprobes/opt.c b/arch/x86/kernel/kprobes/opt.c index 0dd8d089c315..7b3b9d15c47a 100644 --- a/arch/x86/kernel/kprobes/opt.c +++ b/arch/x86/kernel/kprobes/opt.c | |||
@@ -259,6 +259,8 @@ static int can_optimize(unsigned long paddr) | |||
259 | */ | 259 | */ |
260 | return 0; | 260 | return 0; |
261 | recovered_insn = recover_probed_instruction(buf, addr); | 261 | recovered_insn = recover_probed_instruction(buf, addr); |
262 | if (!recovered_insn) | ||
263 | return 0; | ||
262 | kernel_insn_init(&insn, (void *)recovered_insn, MAX_INSN_SIZE); | 264 | kernel_insn_init(&insn, (void *)recovered_insn, MAX_INSN_SIZE); |
263 | insn_get_length(&insn); | 265 | insn_get_length(&insn); |
264 | /* Another subsystem puts a breakpoint */ | 266 | /* Another subsystem puts a breakpoint */ |
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 67fcc43577d2..854b5981b327 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c | |||
@@ -207,7 +207,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, | |||
207 | */ | 207 | */ |
208 | if (clone_flags & CLONE_SETTLS) { | 208 | if (clone_flags & CLONE_SETTLS) { |
209 | #ifdef CONFIG_IA32_EMULATION | 209 | #ifdef CONFIG_IA32_EMULATION |
210 | if (test_thread_flag(TIF_IA32)) | 210 | if (is_ia32_task()) |
211 | err = do_set_thread_area(p, -1, | 211 | err = do_set_thread_area(p, -1, |
212 | (struct user_desc __user *)childregs->si, 0); | 212 | (struct user_desc __user *)childregs->si, 0); |
213 | else | 213 | else |
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index e510618b2e91..1e125817cf9f 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c | |||
@@ -364,18 +364,12 @@ static int set_segment_reg(struct task_struct *task, | |||
364 | case offsetof(struct user_regs_struct,cs): | 364 | case offsetof(struct user_regs_struct,cs): |
365 | if (unlikely(value == 0)) | 365 | if (unlikely(value == 0)) |
366 | return -EIO; | 366 | return -EIO; |
367 | #ifdef CONFIG_IA32_EMULATION | 367 | task_pt_regs(task)->cs = value; |
368 | if (test_tsk_thread_flag(task, TIF_IA32)) | ||
369 | task_pt_regs(task)->cs = value; | ||
370 | #endif | ||
371 | break; | 368 | break; |
372 | case offsetof(struct user_regs_struct,ss): | 369 | case offsetof(struct user_regs_struct,ss): |
373 | if (unlikely(value == 0)) | 370 | if (unlikely(value == 0)) |
374 | return -EIO; | 371 | return -EIO; |
375 | #ifdef CONFIG_IA32_EMULATION | 372 | task_pt_regs(task)->ss = value; |
376 | if (test_tsk_thread_flag(task, TIF_IA32)) | ||
377 | task_pt_regs(task)->ss = value; | ||
378 | #endif | ||
379 | break; | 373 | break; |
380 | } | 374 | } |
381 | 375 | ||
diff --git a/arch/x86/kernel/syscall_32.c b/arch/x86/kernel/syscall_32.c index e9bcd57d8a9e..3777189c4a19 100644 --- a/arch/x86/kernel/syscall_32.c +++ b/arch/x86/kernel/syscall_32.c | |||
@@ -5,21 +5,29 @@ | |||
5 | #include <linux/cache.h> | 5 | #include <linux/cache.h> |
6 | #include <asm/asm-offsets.h> | 6 | #include <asm/asm-offsets.h> |
7 | 7 | ||
8 | #define __SYSCALL_I386(nr, sym, compat) extern asmlinkage void sym(void) ; | 8 | #ifdef CONFIG_IA32_EMULATION |
9 | #define SYM(sym, compat) compat | ||
10 | #else | ||
11 | #define SYM(sym, compat) sym | ||
12 | #define ia32_sys_call_table sys_call_table | ||
13 | #define __NR_ia32_syscall_max __NR_syscall_max | ||
14 | #endif | ||
15 | |||
16 | #define __SYSCALL_I386(nr, sym, compat) extern asmlinkage void SYM(sym, compat)(void) ; | ||
9 | #include <asm/syscalls_32.h> | 17 | #include <asm/syscalls_32.h> |
10 | #undef __SYSCALL_I386 | 18 | #undef __SYSCALL_I386 |
11 | 19 | ||
12 | #define __SYSCALL_I386(nr, sym, compat) [nr] = sym, | 20 | #define __SYSCALL_I386(nr, sym, compat) [nr] = SYM(sym, compat), |
13 | 21 | ||
14 | typedef asmlinkage void (*sys_call_ptr_t)(void); | 22 | typedef asmlinkage void (*sys_call_ptr_t)(void); |
15 | 23 | ||
16 | extern asmlinkage void sys_ni_syscall(void); | 24 | extern asmlinkage void sys_ni_syscall(void); |
17 | 25 | ||
18 | __visible const sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = { | 26 | __visible const sys_call_ptr_t ia32_sys_call_table[__NR_ia32_syscall_max+1] = { |
19 | /* | 27 | /* |
20 | * Smells like a compiler bug -- it doesn't work | 28 | * Smells like a compiler bug -- it doesn't work |
21 | * when the & below is removed. | 29 | * when the & below is removed. |
22 | */ | 30 | */ |
23 | [0 ... __NR_syscall_max] = &sys_ni_syscall, | 31 | [0 ... __NR_ia32_syscall_max] = &sys_ni_syscall, |
24 | #include <asm/syscalls_32.h> | 32 | #include <asm/syscalls_32.h> |
25 | }; | 33 | }; |
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 9d2073e2ecc9..42819886be0c 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c | |||
@@ -925,9 +925,17 @@ dotraplinkage void do_iret_error(struct pt_regs *regs, long error_code) | |||
925 | /* Set of traps needed for early debugging. */ | 925 | /* Set of traps needed for early debugging. */ |
926 | void __init early_trap_init(void) | 926 | void __init early_trap_init(void) |
927 | { | 927 | { |
928 | set_intr_gate_ist(X86_TRAP_DB, &debug, DEBUG_STACK); | 928 | /* |
929 | * Don't set ist to DEBUG_STACK as it doesn't work until TSS is | ||
930 | * ready in cpu_init() <-- trap_init(). Before trap_init(), CPU | ||
931 | * runs at ring 0 so it is impossible to hit an invalid stack. | ||
932 | * Using the original stack works well enough at this early | ||
933 | * stage. DEBUG_STACK will be equipped after cpu_init() in | ||
934 | * trap_init(). | ||
935 | */ | ||
936 | set_intr_gate_ist(X86_TRAP_DB, &debug, 0); | ||
929 | /* int3 can be called from all */ | 937 | /* int3 can be called from all */ |
930 | set_system_intr_gate_ist(X86_TRAP_BP, &int3, DEBUG_STACK); | 938 | set_system_intr_gate_ist(X86_TRAP_BP, &int3, 0); |
931 | #ifdef CONFIG_X86_32 | 939 | #ifdef CONFIG_X86_32 |
932 | set_intr_gate(X86_TRAP_PF, page_fault); | 940 | set_intr_gate(X86_TRAP_PF, page_fault); |
933 | #endif | 941 | #endif |
@@ -1005,6 +1013,15 @@ void __init trap_init(void) | |||
1005 | */ | 1013 | */ |
1006 | cpu_init(); | 1014 | cpu_init(); |
1007 | 1015 | ||
1016 | /* | ||
1017 | * X86_TRAP_DB and X86_TRAP_BP have been set | ||
1018 | * in early_trap_init(). However, DEBUG_STACK works only after | ||
1019 | * cpu_init() loads TSS. See comments in early_trap_init(). | ||
1020 | */ | ||
1021 | set_intr_gate_ist(X86_TRAP_DB, &debug, DEBUG_STACK); | ||
1022 | /* int3 can be called from all */ | ||
1023 | set_system_intr_gate_ist(X86_TRAP_BP, &int3, DEBUG_STACK); | ||
1024 | |||
1008 | x86_init.irqs.trap_init(); | 1025 | x86_init.irqs.trap_init(); |
1009 | 1026 | ||
1010 | #ifdef CONFIG_X86_64 | 1027 | #ifdef CONFIG_X86_64 |