diff options
author | Stafford Horne <shorne@gmail.com> | 2017-07-24 08:55:16 -0400 |
---|---|---|
committer | Stafford Horne <shorne@gmail.com> | 2017-11-03 01:01:16 -0400 |
commit | 78cdfb5cf15e0f9fb4c2a9176a13a907a1d024f0 (patch) | |
tree | aba15bb0ca2fab3ec50d75d48944bc209589ac99 | |
parent | eecac38b0423a69715073ecbde581dafd1abb28b (diff) |
openrisc: enable LOCKDEP_SUPPORT and irqflags tracing
Lockdep is needed for proving the spinlocks and rwlocks work fine on our
platform. It also requires calling the trace_hardirqs_off() and
trace_hardirqs_on() pair of routines when entering and exiting an
interrupt.
For OpenRISC the interrupt stack frame does not support frame pointers,
so to call trace_hardirqs_on() and trace_hardirqs_off() here the macro's
build up a stack frame each time.
There is one necessary small change in _sys_call_handler to move
interrupt enabling later so they can get re-enabled during syscall
restart. This was done to fix lockdep warnings that are now possible due
to this
patch.
Signed-off-by: Stafford Horne <shorne@gmail.com>
-rw-r--r-- | arch/openrisc/Kconfig | 3 | ||||
-rw-r--r-- | arch/openrisc/kernel/entry.S | 74 |
2 files changed, 74 insertions, 3 deletions
diff --git a/arch/openrisc/Kconfig b/arch/openrisc/Kconfig index 399f55e82dcb..f8cfb3ba9e89 100644 --- a/arch/openrisc/Kconfig +++ b/arch/openrisc/Kconfig | |||
@@ -64,6 +64,9 @@ config GENERIC_CSUM | |||
64 | config STACKTRACE_SUPPORT | 64 | config STACKTRACE_SUPPORT |
65 | def_bool y | 65 | def_bool y |
66 | 66 | ||
67 | config LOCKDEP_SUPPORT | ||
68 | def_bool y | ||
69 | |||
67 | source "init/Kconfig" | 70 | source "init/Kconfig" |
68 | 71 | ||
69 | source "kernel/Kconfig.freezer" | 72 | source "kernel/Kconfig.freezer" |
diff --git a/arch/openrisc/kernel/entry.S b/arch/openrisc/kernel/entry.S index 1b7160c79646..690d55272ba6 100644 --- a/arch/openrisc/kernel/entry.S +++ b/arch/openrisc/kernel/entry.S | |||
@@ -42,6 +42,61 @@ | |||
42 | 42 | ||
43 | /* =========================================================[ macros ]=== */ | 43 | /* =========================================================[ macros ]=== */ |
44 | 44 | ||
45 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
46 | /* | ||
47 | * Trace irq on/off creating a stack frame. | ||
48 | */ | ||
49 | #define TRACE_IRQS_OP(trace_op) \ | ||
50 | l.sw -8(r1),r2 /* store frame pointer */ ;\ | ||
51 | l.sw -4(r1),r9 /* store return address */ ;\ | ||
52 | l.addi r2,r1,0 /* move sp to fp */ ;\ | ||
53 | l.jal trace_op ;\ | ||
54 | l.addi r1,r1,-8 ;\ | ||
55 | l.ori r1,r2,0 /* restore sp */ ;\ | ||
56 | l.lwz r9,-4(r1) /* restore return address */ ;\ | ||
57 | l.lwz r2,-8(r1) /* restore fp */ ;\ | ||
58 | /* | ||
59 | * Trace irq on/off and save registers we need that would otherwise be | ||
60 | * clobbered. | ||
61 | */ | ||
62 | #define TRACE_IRQS_SAVE(t1,trace_op) \ | ||
63 | l.sw -12(r1),t1 /* save extra reg */ ;\ | ||
64 | l.sw -8(r1),r2 /* store frame pointer */ ;\ | ||
65 | l.sw -4(r1),r9 /* store return address */ ;\ | ||
66 | l.addi r2,r1,0 /* move sp to fp */ ;\ | ||
67 | l.jal trace_op ;\ | ||
68 | l.addi r1,r1,-12 ;\ | ||
69 | l.ori r1,r2,0 /* restore sp */ ;\ | ||
70 | l.lwz r9,-4(r1) /* restore return address */ ;\ | ||
71 | l.lwz r2,-8(r1) /* restore fp */ ;\ | ||
72 | l.lwz t1,-12(r1) /* restore extra reg */ | ||
73 | |||
74 | #define TRACE_IRQS_OFF TRACE_IRQS_OP(trace_hardirqs_off) | ||
75 | #define TRACE_IRQS_ON TRACE_IRQS_OP(trace_hardirqs_on) | ||
76 | #define TRACE_IRQS_ON_SYSCALL \ | ||
77 | TRACE_IRQS_SAVE(r10,trace_hardirqs_on) ;\ | ||
78 | l.lwz r3,PT_GPR3(r1) ;\ | ||
79 | l.lwz r4,PT_GPR4(r1) ;\ | ||
80 | l.lwz r5,PT_GPR5(r1) ;\ | ||
81 | l.lwz r6,PT_GPR6(r1) ;\ | ||
82 | l.lwz r7,PT_GPR7(r1) ;\ | ||
83 | l.lwz r8,PT_GPR8(r1) ;\ | ||
84 | l.lwz r11,PT_GPR11(r1) | ||
85 | #define TRACE_IRQS_OFF_ENTRY \ | ||
86 | l.lwz r5,PT_SR(r1) ;\ | ||
87 | l.andi r3,r5,(SPR_SR_IEE|SPR_SR_TEE) ;\ | ||
88 | l.sfeq r5,r0 /* skip trace if irqs were already off */;\ | ||
89 | l.bf 1f ;\ | ||
90 | l.nop ;\ | ||
91 | TRACE_IRQS_SAVE(r4,trace_hardirqs_off) ;\ | ||
92 | 1: | ||
93 | #else | ||
94 | #define TRACE_IRQS_OFF | ||
95 | #define TRACE_IRQS_ON | ||
96 | #define TRACE_IRQS_OFF_ENTRY | ||
97 | #define TRACE_IRQS_ON_SYSCALL | ||
98 | #endif | ||
99 | |||
45 | /* | 100 | /* |
46 | * We need to disable interrupts at beginning of RESTORE_ALL | 101 | * We need to disable interrupts at beginning of RESTORE_ALL |
47 | * since interrupt might come in after we've loaded EPC return address | 102 | * since interrupt might come in after we've loaded EPC return address |
@@ -124,6 +179,7 @@ handler: ;\ | |||
124 | /* r30 already save */ ;\ | 179 | /* r30 already save */ ;\ |
125 | /* l.sw PT_GPR30(r1),r30*/ ;\ | 180 | /* l.sw PT_GPR30(r1),r30*/ ;\ |
126 | l.sw PT_GPR31(r1),r31 ;\ | 181 | l.sw PT_GPR31(r1),r31 ;\ |
182 | TRACE_IRQS_OFF_ENTRY ;\ | ||
127 | /* Store -1 in orig_gpr11 for non-syscall exceptions */ ;\ | 183 | /* Store -1 in orig_gpr11 for non-syscall exceptions */ ;\ |
128 | l.addi r30,r0,-1 ;\ | 184 | l.addi r30,r0,-1 ;\ |
129 | l.sw PT_ORIG_GPR11(r1),r30 | 185 | l.sw PT_ORIG_GPR11(r1),r30 |
@@ -557,9 +613,6 @@ _string_syscall_return: | |||
557 | .align 4 | 613 | .align 4 |
558 | 614 | ||
559 | ENTRY(_sys_call_handler) | 615 | ENTRY(_sys_call_handler) |
560 | /* syscalls run with interrupts enabled */ | ||
561 | ENABLE_INTERRUPTS(r29) // enable interrupts, r29 is temp | ||
562 | |||
563 | /* r1, EPCR, ESR a already saved */ | 616 | /* r1, EPCR, ESR a already saved */ |
564 | l.sw PT_GPR2(r1),r2 | 617 | l.sw PT_GPR2(r1),r2 |
565 | /* r3-r8 must be saved because syscall restart relies | 618 | /* r3-r8 must be saved because syscall restart relies |
@@ -597,6 +650,10 @@ ENTRY(_sys_call_handler) | |||
597 | /* l.sw PT_GPR30(r1),r30 */ | 650 | /* l.sw PT_GPR30(r1),r30 */ |
598 | 651 | ||
599 | _syscall_check_trace_enter: | 652 | _syscall_check_trace_enter: |
653 | /* syscalls run with interrupts enabled */ | ||
654 | TRACE_IRQS_ON_SYSCALL | ||
655 | ENABLE_INTERRUPTS(r29) // enable interrupts, r29 is temp | ||
656 | |||
600 | /* If TIF_SYSCALL_TRACE is set, then we want to do syscall tracing */ | 657 | /* If TIF_SYSCALL_TRACE is set, then we want to do syscall tracing */ |
601 | l.lwz r30,TI_FLAGS(r10) | 658 | l.lwz r30,TI_FLAGS(r10) |
602 | l.andi r30,r30,_TIF_SYSCALL_TRACE | 659 | l.andi r30,r30,_TIF_SYSCALL_TRACE |
@@ -657,6 +714,7 @@ _syscall_check_trace_leave: | |||
657 | _syscall_check_work: | 714 | _syscall_check_work: |
658 | /* Here we need to disable interrupts */ | 715 | /* Here we need to disable interrupts */ |
659 | DISABLE_INTERRUPTS(r27,r29) | 716 | DISABLE_INTERRUPTS(r27,r29) |
717 | TRACE_IRQS_OFF | ||
660 | l.lwz r30,TI_FLAGS(r10) | 718 | l.lwz r30,TI_FLAGS(r10) |
661 | l.andi r30,r30,_TIF_WORK_MASK | 719 | l.andi r30,r30,_TIF_WORK_MASK |
662 | l.sfne r30,r0 | 720 | l.sfne r30,r0 |
@@ -871,6 +929,7 @@ UNHANDLED_EXCEPTION(_vector_0x1f00,0x1f00) | |||
871 | 929 | ||
872 | _resume_userspace: | 930 | _resume_userspace: |
873 | DISABLE_INTERRUPTS(r3,r4) | 931 | DISABLE_INTERRUPTS(r3,r4) |
932 | TRACE_IRQS_OFF | ||
874 | l.lwz r4,TI_FLAGS(r10) | 933 | l.lwz r4,TI_FLAGS(r10) |
875 | l.andi r13,r4,_TIF_WORK_MASK | 934 | l.andi r13,r4,_TIF_WORK_MASK |
876 | l.sfeqi r13,0 | 935 | l.sfeqi r13,0 |
@@ -909,6 +968,15 @@ _work_pending: | |||
909 | l.lwz r8,PT_GPR8(r1) | 968 | l.lwz r8,PT_GPR8(r1) |
910 | 969 | ||
911 | _restore_all: | 970 | _restore_all: |
971 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
972 | l.lwz r4,PT_SR(r1) | ||
973 | l.andi r3,r4,(SPR_SR_IEE|SPR_SR_TEE) | ||
974 | l.sfeq r3,r0 /* skip trace if irqs were off */ | ||
975 | l.bf skip_hardirqs_on | ||
976 | l.nop | ||
977 | TRACE_IRQS_ON | ||
978 | skip_hardirqs_on: | ||
979 | #endif | ||
912 | RESTORE_ALL | 980 | RESTORE_ALL |
913 | /* This returns to userspace code */ | 981 | /* This returns to userspace code */ |
914 | 982 | ||