diff options
| -rw-r--r-- | arch/x86/include/asm/desc.h | 57 | ||||
| -rw-r--r-- | arch/x86/include/asm/hw_irq.h | 3 | ||||
| -rw-r--r-- | arch/x86/include/asm/segment.h | 3 | ||||
| -rw-r--r-- | arch/x86/include/asm/trace/exceptions.h | 52 | ||||
| -rw-r--r-- | arch/x86/include/asm/traps.h | 20 | ||||
| -rw-r--r-- | arch/x86/kernel/entry_32.S | 10 | ||||
| -rw-r--r-- | arch/x86/kernel/entry_64.S | 13 | ||||
| -rw-r--r-- | arch/x86/kernel/head64.c | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/kvm.c | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/traps.c | 28 | ||||
| -rw-r--r-- | arch/x86/mm/Makefile | 2 | ||||
| -rw-r--r-- | arch/x86/mm/fault.c | 23 |
12 files changed, 165 insertions, 50 deletions
diff --git a/arch/x86/include/asm/desc.h b/arch/x86/include/asm/desc.h index b90e5dfeee46..50d033a8947d 100644 --- a/arch/x86/include/asm/desc.h +++ b/arch/x86/include/asm/desc.h | |||
| @@ -327,10 +327,25 @@ static inline void write_trace_idt_entry(int entry, const gate_desc *gate) | |||
| 327 | { | 327 | { |
| 328 | write_idt_entry(trace_idt_table, entry, gate); | 328 | write_idt_entry(trace_idt_table, entry, gate); |
| 329 | } | 329 | } |
| 330 | |||
| 331 | static inline void _trace_set_gate(int gate, unsigned type, void *addr, | ||
| 332 | unsigned dpl, unsigned ist, unsigned seg) | ||
| 333 | { | ||
| 334 | gate_desc s; | ||
| 335 | |||
| 336 | pack_gate(&s, type, (unsigned long)addr, dpl, ist, seg); | ||
| 337 | /* | ||
| 338 | * does not need to be atomic because it is only done once at | ||
| 339 | * setup time | ||
| 340 | */ | ||
| 341 | write_trace_idt_entry(gate, &s); | ||
| 342 | } | ||
| 330 | #else | 343 | #else |
| 331 | static inline void write_trace_idt_entry(int entry, const gate_desc *gate) | 344 | static inline void write_trace_idt_entry(int entry, const gate_desc *gate) |
| 332 | { | 345 | { |
| 333 | } | 346 | } |
| 347 | |||
| 348 | #define _trace_set_gate(gate, type, addr, dpl, ist, seg) | ||
| 334 | #endif | 349 | #endif |
| 335 | 350 | ||
| 336 | static inline void _set_gate(int gate, unsigned type, void *addr, | 351 | static inline void _set_gate(int gate, unsigned type, void *addr, |
| @@ -353,11 +368,14 @@ static inline void _set_gate(int gate, unsigned type, void *addr, | |||
| 353 | * Pentium F0 0F bugfix can have resulted in the mapped | 368 | * Pentium F0 0F bugfix can have resulted in the mapped |
| 354 | * IDT being write-protected. | 369 | * IDT being write-protected. |
| 355 | */ | 370 | */ |
| 356 | static inline void set_intr_gate(unsigned int n, void *addr) | 371 | #define set_intr_gate(n, addr) \ |
| 357 | { | 372 | do { \ |
| 358 | BUG_ON((unsigned)n > 0xFF); | 373 | BUG_ON((unsigned)n > 0xFF); \ |
| 359 | _set_gate(n, GATE_INTERRUPT, addr, 0, 0, __KERNEL_CS); | 374 | _set_gate(n, GATE_INTERRUPT, (void *)addr, 0, 0, \ |
| 360 | } | 375 | __KERNEL_CS); \ |
| 376 | _trace_set_gate(n, GATE_INTERRUPT, (void *)trace_##addr,\ | ||
| 377 | 0, 0, __KERNEL_CS); \ | ||
| 378 | } while (0) | ||
| 361 | 379 | ||
| 362 | extern int first_system_vector; | 380 | extern int first_system_vector; |
| 363 | /* used_vectors is BITMAP for irq is not managed by percpu vector_irq */ | 381 | /* used_vectors is BITMAP for irq is not managed by percpu vector_irq */ |
| @@ -374,37 +392,10 @@ static inline void alloc_system_vector(int vector) | |||
| 374 | } | 392 | } |
| 375 | } | 393 | } |
| 376 | 394 | ||
| 377 | #ifdef CONFIG_TRACING | ||
| 378 | static inline void trace_set_intr_gate(unsigned int gate, void *addr) | ||
| 379 | { | ||
| 380 | gate_desc s; | ||
| 381 | |||
| 382 | pack_gate(&s, GATE_INTERRUPT, (unsigned long)addr, 0, 0, __KERNEL_CS); | ||
| 383 | write_idt_entry(trace_idt_table, gate, &s); | ||
| 384 | } | ||
| 385 | |||
| 386 | static inline void __trace_alloc_intr_gate(unsigned int n, void *addr) | ||
| 387 | { | ||
| 388 | trace_set_intr_gate(n, addr); | ||
| 389 | } | ||
| 390 | #else | ||
| 391 | static inline void trace_set_intr_gate(unsigned int gate, void *addr) | ||
| 392 | { | ||
| 393 | } | ||
| 394 | |||
| 395 | #define __trace_alloc_intr_gate(n, addr) | ||
| 396 | #endif | ||
| 397 | |||
| 398 | static inline void __alloc_intr_gate(unsigned int n, void *addr) | ||
| 399 | { | ||
| 400 | set_intr_gate(n, addr); | ||
| 401 | } | ||
| 402 | |||
| 403 | #define alloc_intr_gate(n, addr) \ | 395 | #define alloc_intr_gate(n, addr) \ |
| 404 | do { \ | 396 | do { \ |
| 405 | alloc_system_vector(n); \ | 397 | alloc_system_vector(n); \ |
| 406 | __alloc_intr_gate(n, addr); \ | 398 | set_intr_gate(n, addr); \ |
| 407 | __trace_alloc_intr_gate(n, trace_##addr); \ | ||
| 408 | } while (0) | 399 | } while (0) |
| 409 | 400 | ||
| 410 | /* | 401 | /* |
diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h index 92b3bae08b74..cba45d99ac1a 100644 --- a/arch/x86/include/asm/hw_irq.h +++ b/arch/x86/include/asm/hw_irq.h | |||
| @@ -187,6 +187,9 @@ extern __visible void smp_invalidate_interrupt(struct pt_regs *); | |||
| 187 | #endif | 187 | #endif |
| 188 | 188 | ||
| 189 | extern void (*__initconst interrupt[NR_VECTORS-FIRST_EXTERNAL_VECTOR])(void); | 189 | extern void (*__initconst interrupt[NR_VECTORS-FIRST_EXTERNAL_VECTOR])(void); |
| 190 | #ifdef CONFIG_TRACING | ||
| 191 | #define trace_interrupt interrupt | ||
| 192 | #endif | ||
| 190 | 193 | ||
| 191 | typedef int vector_irq_t[NR_VECTORS]; | 194 | typedef int vector_irq_t[NR_VECTORS]; |
| 192 | DECLARE_PER_CPU(vector_irq_t, vector_irq); | 195 | DECLARE_PER_CPU(vector_irq_t, vector_irq); |
diff --git a/arch/x86/include/asm/segment.h b/arch/x86/include/asm/segment.h index c48a95035a77..6f1c3a8a33ab 100644 --- a/arch/x86/include/asm/segment.h +++ b/arch/x86/include/asm/segment.h | |||
| @@ -214,6 +214,9 @@ | |||
| 214 | #ifdef __KERNEL__ | 214 | #ifdef __KERNEL__ |
| 215 | #ifndef __ASSEMBLY__ | 215 | #ifndef __ASSEMBLY__ |
| 216 | extern const char early_idt_handlers[NUM_EXCEPTION_VECTORS][2+2+5]; | 216 | extern const char early_idt_handlers[NUM_EXCEPTION_VECTORS][2+2+5]; |
| 217 | #ifdef CONFIG_TRACING | ||
| 218 | #define trace_early_idt_handlers early_idt_handlers | ||
| 219 | #endif | ||
| 217 | 220 | ||
| 218 | /* | 221 | /* |
| 219 | * Load a segment. Fall back on loading the zero | 222 | * Load a segment. Fall back on loading the zero |
diff --git a/arch/x86/include/asm/trace/exceptions.h b/arch/x86/include/asm/trace/exceptions.h new file mode 100644 index 000000000000..2fbc66c7885b --- /dev/null +++ b/arch/x86/include/asm/trace/exceptions.h | |||
| @@ -0,0 +1,52 @@ | |||
| 1 | #undef TRACE_SYSTEM | ||
| 2 | #define TRACE_SYSTEM exceptions | ||
| 3 | |||
| 4 | #if !defined(_TRACE_PAGE_FAULT_H) || defined(TRACE_HEADER_MULTI_READ) | ||
| 5 | #define _TRACE_PAGE_FAULT_H | ||
| 6 | |||
| 7 | #include <linux/tracepoint.h> | ||
| 8 | |||
| 9 | extern void trace_irq_vector_regfunc(void); | ||
| 10 | extern void trace_irq_vector_unregfunc(void); | ||
| 11 | |||
| 12 | DECLARE_EVENT_CLASS(x86_exceptions, | ||
| 13 | |||
| 14 | TP_PROTO(unsigned long address, struct pt_regs *regs, | ||
| 15 | unsigned long error_code), | ||
| 16 | |||
| 17 | TP_ARGS(address, regs, error_code), | ||
| 18 | |||
| 19 | TP_STRUCT__entry( | ||
| 20 | __field( unsigned long, address ) | ||
| 21 | __field( unsigned long, ip ) | ||
| 22 | __field( unsigned long, error_code ) | ||
| 23 | ), | ||
| 24 | |||
| 25 | TP_fast_assign( | ||
| 26 | __entry->address = address; | ||
| 27 | __entry->ip = regs->ip; | ||
| 28 | __entry->error_code = error_code; | ||
| 29 | ), | ||
| 30 | |||
| 31 | TP_printk("address=%pf ip=%pf error_code=0x%lx", | ||
| 32 | (void *)__entry->address, (void *)__entry->ip, | ||
| 33 | __entry->error_code) ); | ||
| 34 | |||
| 35 | #define DEFINE_PAGE_FAULT_EVENT(name) \ | ||
| 36 | DEFINE_EVENT_FN(x86_exceptions, name, \ | ||
| 37 | TP_PROTO(unsigned long address, struct pt_regs *regs, \ | ||
| 38 | unsigned long error_code), \ | ||
| 39 | TP_ARGS(address, regs, error_code), \ | ||
| 40 | trace_irq_vector_regfunc, \ | ||
| 41 | trace_irq_vector_unregfunc); | ||
| 42 | |||
| 43 | DEFINE_PAGE_FAULT_EVENT(page_fault_user); | ||
| 44 | DEFINE_PAGE_FAULT_EVENT(page_fault_kernel); | ||
| 45 | |||
| 46 | #undef TRACE_INCLUDE_PATH | ||
| 47 | #define TRACE_INCLUDE_PATH . | ||
| 48 | #define TRACE_INCLUDE_FILE exceptions | ||
| 49 | #endif /* _TRACE_PAGE_FAULT_H */ | ||
| 50 | |||
| 51 | /* This part must be outside protection */ | ||
| 52 | #include <trace/define_trace.h> | ||
diff --git a/arch/x86/include/asm/traps.h b/arch/x86/include/asm/traps.h index 7036cb60cd87..58d66fe06b61 100644 --- a/arch/x86/include/asm/traps.h +++ b/arch/x86/include/asm/traps.h | |||
| @@ -37,6 +37,23 @@ asmlinkage void machine_check(void); | |||
| 37 | #endif /* CONFIG_X86_MCE */ | 37 | #endif /* CONFIG_X86_MCE */ |
| 38 | asmlinkage void simd_coprocessor_error(void); | 38 | asmlinkage void simd_coprocessor_error(void); |
| 39 | 39 | ||
| 40 | #ifdef CONFIG_TRACING | ||
| 41 | asmlinkage void trace_page_fault(void); | ||
| 42 | #define trace_divide_error divide_error | ||
| 43 | #define trace_bounds bounds | ||
| 44 | #define trace_invalid_op invalid_op | ||
| 45 | #define trace_device_not_available device_not_available | ||
| 46 | #define trace_coprocessor_segment_overrun coprocessor_segment_overrun | ||
| 47 | #define trace_invalid_TSS invalid_TSS | ||
| 48 | #define trace_segment_not_present segment_not_present | ||
| 49 | #define trace_general_protection general_protection | ||
| 50 | #define trace_spurious_interrupt_bug spurious_interrupt_bug | ||
| 51 | #define trace_coprocessor_error coprocessor_error | ||
| 52 | #define trace_alignment_check alignment_check | ||
| 53 | #define trace_simd_coprocessor_error simd_coprocessor_error | ||
| 54 | #define trace_async_page_fault async_page_fault | ||
| 55 | #endif | ||
| 56 | |||
| 40 | dotraplinkage void do_divide_error(struct pt_regs *, long); | 57 | dotraplinkage void do_divide_error(struct pt_regs *, long); |
| 41 | dotraplinkage void do_debug(struct pt_regs *, long); | 58 | dotraplinkage void do_debug(struct pt_regs *, long); |
| 42 | dotraplinkage void do_nmi(struct pt_regs *, long); | 59 | dotraplinkage void do_nmi(struct pt_regs *, long); |
| @@ -55,6 +72,9 @@ asmlinkage __kprobes struct pt_regs *sync_regs(struct pt_regs *); | |||
| 55 | #endif | 72 | #endif |
| 56 | dotraplinkage void do_general_protection(struct pt_regs *, long); | 73 | dotraplinkage void do_general_protection(struct pt_regs *, long); |
| 57 | dotraplinkage void do_page_fault(struct pt_regs *, unsigned long); | 74 | dotraplinkage void do_page_fault(struct pt_regs *, unsigned long); |
| 75 | #ifdef CONFIG_TRACING | ||
| 76 | dotraplinkage void trace_do_page_fault(struct pt_regs *, unsigned long); | ||
| 77 | #endif | ||
| 58 | dotraplinkage void do_spurious_interrupt_bug(struct pt_regs *, long); | 78 | dotraplinkage void do_spurious_interrupt_bug(struct pt_regs *, long); |
| 59 | dotraplinkage void do_coprocessor_error(struct pt_regs *, long); | 79 | dotraplinkage void do_coprocessor_error(struct pt_regs *, long); |
| 60 | dotraplinkage void do_alignment_check(struct pt_regs *, long); | 80 | dotraplinkage void do_alignment_check(struct pt_regs *, long); |
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S index fd1bc1b15e6d..51e2988c5728 100644 --- a/arch/x86/kernel/entry_32.S +++ b/arch/x86/kernel/entry_32.S | |||
| @@ -1244,6 +1244,16 @@ return_to_handler: | |||
| 1244 | */ | 1244 | */ |
| 1245 | .pushsection .kprobes.text, "ax" | 1245 | .pushsection .kprobes.text, "ax" |
| 1246 | 1246 | ||
| 1247 | #ifdef CONFIG_TRACING | ||
| 1248 | ENTRY(trace_page_fault) | ||
| 1249 | RING0_EC_FRAME | ||
| 1250 | ASM_CLAC | ||
| 1251 | pushl_cfi $trace_do_page_fault | ||
| 1252 | jmp error_code | ||
| 1253 | CFI_ENDPROC | ||
| 1254 | END(trace_page_fault) | ||
| 1255 | #endif | ||
| 1256 | |||
| 1247 | ENTRY(page_fault) | 1257 | ENTRY(page_fault) |
| 1248 | RING0_EC_FRAME | 1258 | RING0_EC_FRAME |
| 1249 | ASM_CLAC | 1259 | ASM_CLAC |
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index 603be7c70675..e21b0785a85b 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S | |||
| @@ -1278,6 +1278,17 @@ ENTRY(\sym) | |||
| 1278 | END(\sym) | 1278 | END(\sym) |
| 1279 | .endm | 1279 | .endm |
| 1280 | 1280 | ||
| 1281 | #ifdef CONFIG_TRACING | ||
| 1282 | .macro trace_errorentry sym do_sym | ||
| 1283 | errorentry trace(\sym) trace(\do_sym) | ||
| 1284 | errorentry \sym \do_sym | ||
| 1285 | .endm | ||
| 1286 | #else | ||
| 1287 | .macro trace_errorentry sym do_sym | ||
| 1288 | errorentry \sym \do_sym | ||
| 1289 | .endm | ||
| 1290 | #endif | ||
| 1291 | |||
| 1281 | /* error code is on the stack already */ | 1292 | /* error code is on the stack already */ |
| 1282 | .macro paranoiderrorentry sym do_sym | 1293 | .macro paranoiderrorentry sym do_sym |
| 1283 | ENTRY(\sym) | 1294 | ENTRY(\sym) |
| @@ -1480,7 +1491,7 @@ zeroentry xen_int3 do_int3 | |||
| 1480 | errorentry xen_stack_segment do_stack_segment | 1491 | errorentry xen_stack_segment do_stack_segment |
| 1481 | #endif | 1492 | #endif |
| 1482 | errorentry general_protection do_general_protection | 1493 | errorentry general_protection do_general_protection |
| 1483 | errorentry page_fault do_page_fault | 1494 | trace_errorentry page_fault do_page_fault |
| 1484 | #ifdef CONFIG_KVM_GUEST | 1495 | #ifdef CONFIG_KVM_GUEST |
| 1485 | errorentry async_page_fault do_async_page_fault | 1496 | errorentry async_page_fault do_async_page_fault |
| 1486 | #endif | 1497 | #endif |
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c index 1be8e43b669e..85126ccbdf6b 100644 --- a/arch/x86/kernel/head64.c +++ b/arch/x86/kernel/head64.c | |||
| @@ -162,7 +162,7 @@ asmlinkage void __init x86_64_start_kernel(char * real_mode_data) | |||
| 162 | clear_bss(); | 162 | clear_bss(); |
| 163 | 163 | ||
| 164 | for (i = 0; i < NUM_EXCEPTION_VECTORS; i++) | 164 | for (i = 0; i < NUM_EXCEPTION_VECTORS; i++) |
| 165 | set_intr_gate(i, &early_idt_handlers[i]); | 165 | set_intr_gate(i, early_idt_handlers[i]); |
| 166 | load_idt((const struct desc_ptr *)&idt_descr); | 166 | load_idt((const struct desc_ptr *)&idt_descr); |
| 167 | 167 | ||
| 168 | copy_bootdata(__va(real_mode_data)); | 168 | copy_bootdata(__va(real_mode_data)); |
diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c index b2046e4d0b59..6dd802c6d780 100644 --- a/arch/x86/kernel/kvm.c +++ b/arch/x86/kernel/kvm.c | |||
| @@ -464,7 +464,7 @@ static struct notifier_block kvm_cpu_notifier = { | |||
| 464 | 464 | ||
| 465 | static void __init kvm_apf_trap_init(void) | 465 | static void __init kvm_apf_trap_init(void) |
| 466 | { | 466 | { |
| 467 | set_intr_gate(14, &async_page_fault); | 467 | set_intr_gate(14, async_page_fault); |
| 468 | } | 468 | } |
| 469 | 469 | ||
| 470 | void __init kvm_guest_init(void) | 470 | void __init kvm_guest_init(void) |
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 996ce2313ce6..b857ed890b4c 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c | |||
| @@ -713,7 +713,7 @@ void __init early_trap_init(void) | |||
| 713 | /* int3 can be called from all */ | 713 | /* int3 can be called from all */ |
| 714 | set_system_intr_gate_ist(X86_TRAP_BP, &int3, DEBUG_STACK); | 714 | set_system_intr_gate_ist(X86_TRAP_BP, &int3, DEBUG_STACK); |
| 715 | #ifdef CONFIG_X86_32 | 715 | #ifdef CONFIG_X86_32 |
| 716 | set_intr_gate(X86_TRAP_PF, &page_fault); | 716 | set_intr_gate(X86_TRAP_PF, page_fault); |
| 717 | #endif | 717 | #endif |
| 718 | load_idt(&idt_descr); | 718 | load_idt(&idt_descr); |
| 719 | } | 719 | } |
| @@ -721,7 +721,7 @@ void __init early_trap_init(void) | |||
| 721 | void __init early_trap_pf_init(void) | 721 | void __init early_trap_pf_init(void) |
| 722 | { | 722 | { |
| 723 | #ifdef CONFIG_X86_64 | 723 | #ifdef CONFIG_X86_64 |
| 724 | set_intr_gate(X86_TRAP_PF, &page_fault); | 724 | set_intr_gate(X86_TRAP_PF, page_fault); |
| 725 | #endif | 725 | #endif |
| 726 | } | 726 | } |
| 727 | 727 | ||
| @@ -737,30 +737,30 @@ void __init trap_init(void) | |||
| 737 | early_iounmap(p, 4); | 737 | early_iounmap(p, 4); |
| 738 | #endif | 738 | #endif |
| 739 | 739 | ||
| 740 | set_intr_gate(X86_TRAP_DE, ÷_error); | 740 | set_intr_gate(X86_TRAP_DE, divide_error); |
| 741 | set_intr_gate_ist(X86_TRAP_NMI, &nmi, NMI_STACK); | 741 | set_intr_gate_ist(X86_TRAP_NMI, &nmi, NMI_STACK); |
| 742 | /* int4 can be called from all */ | 742 | /* int4 can be called from all */ |
| 743 | set_system_intr_gate(X86_TRAP_OF, &overflow); | 743 | set_system_intr_gate(X86_TRAP_OF, &overflow); |
| 744 | set_intr_gate(X86_TRAP_BR, &bounds); | 744 | set_intr_gate(X86_TRAP_BR, bounds); |
| 745 | set_intr_gate(X86_TRAP_UD, &invalid_op); | 745 | set_intr_gate(X86_TRAP_UD, invalid_op); |
| 746 | set_intr_gate(X86_TRAP_NM, &device_not_available); | 746 | set_intr_gate(X86_TRAP_NM, device_not_available); |
| 747 | #ifdef CONFIG_X86_32 | 747 | #ifdef CONFIG_X86_32 |
| 748 | set_task_gate(X86_TRAP_DF, GDT_ENTRY_DOUBLEFAULT_TSS); | 748 | set_task_gate(X86_TRAP_DF, GDT_ENTRY_DOUBLEFAULT_TSS); |
| 749 | #else | 749 | #else |
| 750 | set_intr_gate_ist(X86_TRAP_DF, &double_fault, DOUBLEFAULT_STACK); | 750 | set_intr_gate_ist(X86_TRAP_DF, &double_fault, DOUBLEFAULT_STACK); |
| 751 | #endif | 751 | #endif |
| 752 | set_intr_gate(X86_TRAP_OLD_MF, &coprocessor_segment_overrun); | 752 | set_intr_gate(X86_TRAP_OLD_MF, coprocessor_segment_overrun); |
| 753 | set_intr_gate(X86_TRAP_TS, &invalid_TSS); | 753 | set_intr_gate(X86_TRAP_TS, invalid_TSS); |
| 754 | set_intr_gate(X86_TRAP_NP, &segment_not_present); | 754 | set_intr_gate(X86_TRAP_NP, segment_not_present); |
| 755 | set_intr_gate_ist(X86_TRAP_SS, &stack_segment, STACKFAULT_STACK); | 755 | set_intr_gate_ist(X86_TRAP_SS, &stack_segment, STACKFAULT_STACK); |
| 756 | set_intr_gate(X86_TRAP_GP, &general_protection); | 756 | set_intr_gate(X86_TRAP_GP, general_protection); |
| 757 | set_intr_gate(X86_TRAP_SPURIOUS, &spurious_interrupt_bug); | 757 | set_intr_gate(X86_TRAP_SPURIOUS, spurious_interrupt_bug); |
| 758 | set_intr_gate(X86_TRAP_MF, &coprocessor_error); | 758 | set_intr_gate(X86_TRAP_MF, coprocessor_error); |
| 759 | set_intr_gate(X86_TRAP_AC, &alignment_check); | 759 | set_intr_gate(X86_TRAP_AC, alignment_check); |
| 760 | #ifdef CONFIG_X86_MCE | 760 | #ifdef CONFIG_X86_MCE |
| 761 | set_intr_gate_ist(X86_TRAP_MC, &machine_check, MCE_STACK); | 761 | set_intr_gate_ist(X86_TRAP_MC, &machine_check, MCE_STACK); |
| 762 | #endif | 762 | #endif |
| 763 | set_intr_gate(X86_TRAP_XF, &simd_coprocessor_error); | 763 | set_intr_gate(X86_TRAP_XF, simd_coprocessor_error); |
| 764 | 764 | ||
| 765 | /* Reserve all the builtin and the syscall vector: */ | 765 | /* Reserve all the builtin and the syscall vector: */ |
| 766 | for (i = 0; i < FIRST_EXTERNAL_VECTOR; i++) | 766 | for (i = 0; i < FIRST_EXTERNAL_VECTOR; i++) |
diff --git a/arch/x86/mm/Makefile b/arch/x86/mm/Makefile index 23d8e5fecf76..6a19ad9f370d 100644 --- a/arch/x86/mm/Makefile +++ b/arch/x86/mm/Makefile | |||
| @@ -6,6 +6,8 @@ nostackp := $(call cc-option, -fno-stack-protector) | |||
| 6 | CFLAGS_physaddr.o := $(nostackp) | 6 | CFLAGS_physaddr.o := $(nostackp) |
| 7 | CFLAGS_setup_nx.o := $(nostackp) | 7 | CFLAGS_setup_nx.o := $(nostackp) |
| 8 | 8 | ||
| 9 | CFLAGS_fault.o := -I$(src)/../include/asm/trace | ||
| 10 | |||
| 9 | obj-$(CONFIG_X86_PAT) += pat_rbtree.o | 11 | obj-$(CONFIG_X86_PAT) += pat_rbtree.o |
| 10 | obj-$(CONFIG_SMP) += tlb.o | 12 | obj-$(CONFIG_SMP) += tlb.o |
| 11 | 13 | ||
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 7a517bb41060..1560a5de1ce0 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c | |||
| @@ -20,6 +20,9 @@ | |||
| 20 | #include <asm/kmemcheck.h> /* kmemcheck_*(), ... */ | 20 | #include <asm/kmemcheck.h> /* kmemcheck_*(), ... */ |
| 21 | #include <asm/fixmap.h> /* VSYSCALL_START */ | 21 | #include <asm/fixmap.h> /* VSYSCALL_START */ |
| 22 | 22 | ||
| 23 | #define CREATE_TRACE_POINTS | ||
| 24 | #include <asm/trace/exceptions.h> | ||
| 25 | |||
| 23 | /* | 26 | /* |
| 24 | * Page fault error code bits: | 27 | * Page fault error code bits: |
| 25 | * | 28 | * |
| @@ -1232,3 +1235,23 @@ do_page_fault(struct pt_regs *regs, unsigned long error_code) | |||
| 1232 | __do_page_fault(regs, error_code); | 1235 | __do_page_fault(regs, error_code); |
| 1233 | exception_exit(prev_state); | 1236 | exception_exit(prev_state); |
| 1234 | } | 1237 | } |
| 1238 | |||
| 1239 | static void trace_page_fault_entries(struct pt_regs *regs, | ||
| 1240 | unsigned long error_code) | ||
| 1241 | { | ||
| 1242 | if (user_mode(regs)) | ||
| 1243 | trace_page_fault_user(read_cr2(), regs, error_code); | ||
| 1244 | else | ||
| 1245 | trace_page_fault_kernel(read_cr2(), regs, error_code); | ||
| 1246 | } | ||
| 1247 | |||
| 1248 | dotraplinkage void __kprobes | ||
| 1249 | trace_do_page_fault(struct pt_regs *regs, unsigned long error_code) | ||
| 1250 | { | ||
| 1251 | enum ctx_state prev_state; | ||
| 1252 | |||
| 1253 | prev_state = exception_enter(); | ||
| 1254 | trace_page_fault_entries(regs, error_code); | ||
| 1255 | __do_page_fault(regs, error_code); | ||
| 1256 | exception_exit(prev_state); | ||
| 1257 | } | ||
