aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSeiji Aguchi <seiji.aguchi@hds.com>2013-10-30 16:37:00 -0400
committerH. Peter Anvin <hpa@linux.intel.com>2013-11-08 17:15:45 -0500
commit25c74b10bacead867478480170083f69cfc0db48 (patch)
tree750066787398c55825485341988e19af9776b562
parent959c071f0974cda7702d7574647de7ad9259eb57 (diff)
x86, trace: Register exception handler to trace IDT
This patch registers exception handlers for tracing to a trace IDT. To implemented it in set_intr_gate(), this patch does followings. - Register the exception handlers to the trace IDT by prepending "trace_" to the handler's names. - Also, newly introduce trace_page_fault() to add tracepoints in a subsequent patch. Signed-off-by: Seiji Aguchi <seiji.aguchi@hds.com> Link: http://lkml.kernel.org/r/52716DEC.5050204@hds.com Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
-rw-r--r--arch/x86/include/asm/desc.h28
-rw-r--r--arch/x86/include/asm/hw_irq.h3
-rw-r--r--arch/x86/include/asm/segment.h3
-rw-r--r--arch/x86/include/asm/traps.h20
-rw-r--r--arch/x86/kernel/entry_32.S10
-rw-r--r--arch/x86/kernel/entry_64.S13
-rw-r--r--arch/x86/kernel/head64.c2
-rw-r--r--arch/x86/kernel/kvm.c2
-rw-r--r--arch/x86/kernel/traps.c28
-rw-r--r--arch/x86/mm/fault.c10
10 files changed, 97 insertions, 22 deletions
diff --git a/arch/x86/include/asm/desc.h b/arch/x86/include/asm/desc.h
index d93956744cfd..3d73437600d7 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
331static 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
331static inline void write_trace_idt_entry(int entry, const gate_desc *gate) 344static 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
336static inline void _set_gate(int gate, unsigned type, void *addr, 351static 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 */
356static 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
362extern int first_system_vector; 380extern 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 */
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
189extern void (*__initconst interrupt[NR_VECTORS-FIRST_EXTERNAL_VECTOR])(void); 189extern void (*__initconst interrupt[NR_VECTORS-FIRST_EXTERNAL_VECTOR])(void);
190#ifdef CONFIG_TRACING
191#define trace_interrupt interrupt
192#endif
190 193
191typedef int vector_irq_t[NR_VECTORS]; 194typedef int vector_irq_t[NR_VECTORS];
192DECLARE_PER_CPU(vector_irq_t, vector_irq); 195DECLARE_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__
216extern const char early_idt_handlers[NUM_EXCEPTION_VECTORS][2+2+5]; 216extern 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/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 */
38asmlinkage void simd_coprocessor_error(void); 38asmlinkage void simd_coprocessor_error(void);
39 39
40#ifdef CONFIG_TRACING
41asmlinkage 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
40dotraplinkage void do_divide_error(struct pt_regs *, long); 57dotraplinkage void do_divide_error(struct pt_regs *, long);
41dotraplinkage void do_debug(struct pt_regs *, long); 58dotraplinkage void do_debug(struct pt_regs *, long);
42dotraplinkage void do_nmi(struct pt_regs *, long); 59dotraplinkage 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
56dotraplinkage void do_general_protection(struct pt_regs *, long); 73dotraplinkage void do_general_protection(struct pt_regs *, long);
57dotraplinkage void do_page_fault(struct pt_regs *, unsigned long); 74dotraplinkage void do_page_fault(struct pt_regs *, unsigned long);
75#ifdef CONFIG_TRACING
76dotraplinkage void trace_do_page_fault(struct pt_regs *, unsigned long);
77#endif
58dotraplinkage void do_spurious_interrupt_bug(struct pt_regs *, long); 78dotraplinkage void do_spurious_interrupt_bug(struct pt_regs *, long);
59dotraplinkage void do_coprocessor_error(struct pt_regs *, long); 79dotraplinkage void do_coprocessor_error(struct pt_regs *, long);
60dotraplinkage void do_alignment_check(struct pt_regs *, long); 80dotraplinkage 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 f0dcb0ceb6a2..0661abe1c395 100644
--- a/arch/x86/kernel/entry_32.S
+++ b/arch/x86/kernel/entry_32.S
@@ -1247,6 +1247,16 @@ return_to_handler:
1247 */ 1247 */
1248 .pushsection .kprobes.text, "ax" 1248 .pushsection .kprobes.text, "ax"
1249 1249
1250#ifdef CONFIG_TRACING
1251ENTRY(trace_page_fault)
1252 RING0_EC_FRAME
1253 ASM_CLAC
1254 pushl_cfi $trace_do_page_fault
1255 jmp error_code
1256 CFI_ENDPROC
1257END(trace_page_fault)
1258#endif
1259
1250ENTRY(page_fault) 1260ENTRY(page_fault)
1251 RING0_EC_FRAME 1261 RING0_EC_FRAME
1252 ASM_CLAC 1262 ASM_CLAC
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index b077f4cc225a..8b7b1698510d 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -1280,6 +1280,17 @@ ENTRY(\sym)
1280END(\sym) 1280END(\sym)
1281.endm 1281.endm
1282 1282
1283#ifdef CONFIG_TRACING
1284.macro trace_errorentry sym do_sym
1285errorentry trace(\sym) trace(\do_sym)
1286errorentry \sym \do_sym
1287.endm
1288#else
1289.macro trace_errorentry sym do_sym
1290errorentry \sym \do_sym
1291.endm
1292#endif
1293
1283 /* error code is on the stack already */ 1294 /* error code is on the stack already */
1284.macro paranoiderrorentry sym do_sym 1295.macro paranoiderrorentry sym do_sym
1285ENTRY(\sym) 1296ENTRY(\sym)
@@ -1482,7 +1493,7 @@ zeroentry xen_int3 do_int3
1482errorentry xen_stack_segment do_stack_segment 1493errorentry xen_stack_segment do_stack_segment
1483#endif 1494#endif
1484errorentry general_protection do_general_protection 1495errorentry general_protection do_general_protection
1485errorentry page_fault do_page_fault 1496trace_errorentry page_fault do_page_fault
1486#ifdef CONFIG_KVM_GUEST 1497#ifdef CONFIG_KVM_GUEST
1487errorentry async_page_fault do_async_page_fault 1498errorentry async_page_fault do_async_page_fault
1488#endif 1499#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
465static void __init kvm_apf_trap_init(void) 465static 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
470void __init kvm_guest_init(void) 470void __init kvm_guest_init(void)
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index 8c8093b146ca..1c9d0ad5a193 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)
721void __init early_trap_pf_init(void) 721void __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, &divide_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/fault.c b/arch/x86/mm/fault.c
index 3aaeffcfd67a..fd3e281fbc70 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -1231,3 +1231,13 @@ do_page_fault(struct pt_regs *regs, unsigned long error_code)
1231 __do_page_fault(regs, error_code); 1231 __do_page_fault(regs, error_code);
1232 exception_exit(prev_state); 1232 exception_exit(prev_state);
1233} 1233}
1234
1235dotraplinkage void __kprobes
1236trace_do_page_fault(struct pt_regs *regs, unsigned long error_code)
1237{
1238 enum ctx_state prev_state;
1239
1240 prev_state = exception_enter();
1241 __do_page_fault(regs, error_code);
1242 exception_exit(prev_state);
1243}