diff options
author | Kirill Tkhai <tkhai@yandex.ru> | 2013-09-14 08:02:11 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-11-14 17:57:21 -0500 |
commit | 812cb83a56a908729c453a7db3fb2c262119bc9d (patch) | |
tree | 3fdf3df047276db7de85558ff6caff006c3b1cc4 /arch/sparc | |
parent | 1a36265bf7d7e16b35fab5ae7f2f5d499bd0c14d (diff) |
sparc64: Implement HAVE_CONTEXT_TRACKING
Mark the places when the system are in user or are in kernel.
This is used to make full dynticks system (tickless) --
CONFIG_NO_HZ_FULL dependence.
Signed-off-by: Kirill Tkhai <tkhai@yandex.ru>
CC: David Miller <davem@davemloft.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc')
-rw-r--r-- | arch/sparc/Kconfig | 1 | ||||
-rw-r--r-- | arch/sparc/include/asm/thread_info_64.h | 3 | ||||
-rw-r--r-- | arch/sparc/kernel/entry.h | 1 | ||||
-rw-r--r-- | arch/sparc/kernel/kgdb_64.c | 5 | ||||
-rw-r--r-- | arch/sparc/kernel/kprobes.c | 7 | ||||
-rw-r--r-- | arch/sparc/kernel/process_64.c | 2 | ||||
-rw-r--r-- | arch/sparc/kernel/ptrace_64.c | 10 | ||||
-rw-r--r-- | arch/sparc/kernel/rtrap_64.S | 8 | ||||
-rw-r--r-- | arch/sparc/kernel/signal_64.c | 13 | ||||
-rw-r--r-- | arch/sparc/kernel/sys_sparc_64.c | 3 | ||||
-rw-r--r-- | arch/sparc/kernel/syscalls.S | 8 | ||||
-rw-r--r-- | arch/sparc/kernel/traps_64.c | 85 | ||||
-rw-r--r-- | arch/sparc/kernel/unaligned_64.c | 16 | ||||
-rw-r--r-- | arch/sparc/mm/fault_64.c | 14 |
14 files changed, 137 insertions, 39 deletions
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 78c4fdb91bc5..01d77d78cd32 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig | |||
@@ -64,6 +64,7 @@ config SPARC64 | |||
64 | select HAVE_DYNAMIC_FTRACE | 64 | select HAVE_DYNAMIC_FTRACE |
65 | select HAVE_FTRACE_MCOUNT_RECORD | 65 | select HAVE_FTRACE_MCOUNT_RECORD |
66 | select HAVE_SYSCALL_TRACEPOINTS | 66 | select HAVE_SYSCALL_TRACEPOINTS |
67 | select HAVE_CONTEXT_TRACKING | ||
67 | select HAVE_DEBUG_KMEMLEAK | 68 | select HAVE_DEBUG_KMEMLEAK |
68 | select RTC_DRV_CMOS | 69 | select RTC_DRV_CMOS |
69 | select RTC_DRV_BQ4802 | 70 | select RTC_DRV_BQ4802 |
diff --git a/arch/sparc/include/asm/thread_info_64.h b/arch/sparc/include/asm/thread_info_64.h index d5e504251079..5d9292ab1077 100644 --- a/arch/sparc/include/asm/thread_info_64.h +++ b/arch/sparc/include/asm/thread_info_64.h | |||
@@ -192,7 +192,7 @@ register struct thread_info *current_thread_info_reg asm("g6"); | |||
192 | #define TIF_UNALIGNED 5 /* allowed to do unaligned accesses */ | 192 | #define TIF_UNALIGNED 5 /* allowed to do unaligned accesses */ |
193 | /* flag bit 6 is available */ | 193 | /* flag bit 6 is available */ |
194 | #define TIF_32BIT 7 /* 32-bit binary */ | 194 | #define TIF_32BIT 7 /* 32-bit binary */ |
195 | /* flag bit 8 is available */ | 195 | #define TIF_NOHZ 8 /* in adaptive nohz mode */ |
196 | #define TIF_SECCOMP 9 /* secure computing */ | 196 | #define TIF_SECCOMP 9 /* secure computing */ |
197 | #define TIF_SYSCALL_AUDIT 10 /* syscall auditing active */ | 197 | #define TIF_SYSCALL_AUDIT 10 /* syscall auditing active */ |
198 | #define TIF_SYSCALL_TRACEPOINT 11 /* syscall tracepoint instrumentation */ | 198 | #define TIF_SYSCALL_TRACEPOINT 11 /* syscall tracepoint instrumentation */ |
@@ -210,6 +210,7 @@ register struct thread_info *current_thread_info_reg asm("g6"); | |||
210 | #define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED) | 210 | #define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED) |
211 | #define _TIF_UNALIGNED (1<<TIF_UNALIGNED) | 211 | #define _TIF_UNALIGNED (1<<TIF_UNALIGNED) |
212 | #define _TIF_32BIT (1<<TIF_32BIT) | 212 | #define _TIF_32BIT (1<<TIF_32BIT) |
213 | #define _TIF_NOHZ (1<<TIF_NOHZ) | ||
213 | #define _TIF_SECCOMP (1<<TIF_SECCOMP) | 214 | #define _TIF_SECCOMP (1<<TIF_SECCOMP) |
214 | #define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT) | 215 | #define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT) |
215 | #define _TIF_SYSCALL_TRACEPOINT (1<<TIF_SYSCALL_TRACEPOINT) | 216 | #define _TIF_SYSCALL_TRACEPOINT (1<<TIF_SYSCALL_TRACEPOINT) |
diff --git a/arch/sparc/kernel/entry.h b/arch/sparc/kernel/entry.h index 9c179fbfb219..140966fbd303 100644 --- a/arch/sparc/kernel/entry.h +++ b/arch/sparc/kernel/entry.h | |||
@@ -88,7 +88,6 @@ extern asmlinkage void syscall_trace_leave(struct pt_regs *regs); | |||
88 | 88 | ||
89 | extern void bad_trap_tl1(struct pt_regs *regs, long lvl); | 89 | extern void bad_trap_tl1(struct pt_regs *regs, long lvl); |
90 | 90 | ||
91 | extern void do_fpe_common(struct pt_regs *regs); | ||
92 | extern void do_fpieee(struct pt_regs *regs); | 91 | extern void do_fpieee(struct pt_regs *regs); |
93 | extern void do_fpother(struct pt_regs *regs); | 92 | extern void do_fpother(struct pt_regs *regs); |
94 | extern void do_tof(struct pt_regs *regs); | 93 | extern void do_tof(struct pt_regs *regs); |
diff --git a/arch/sparc/kernel/kgdb_64.c b/arch/sparc/kernel/kgdb_64.c index 53c0a82e6030..60b19f50c80a 100644 --- a/arch/sparc/kernel/kgdb_64.c +++ b/arch/sparc/kernel/kgdb_64.c | |||
@@ -159,11 +159,12 @@ int kgdb_arch_handle_exception(int e_vector, int signo, int err_code, | |||
159 | 159 | ||
160 | asmlinkage void kgdb_trap(unsigned long trap_level, struct pt_regs *regs) | 160 | asmlinkage void kgdb_trap(unsigned long trap_level, struct pt_regs *regs) |
161 | { | 161 | { |
162 | enum ctx_state prev_state = exception_enter(); | ||
162 | unsigned long flags; | 163 | unsigned long flags; |
163 | 164 | ||
164 | if (user_mode(regs)) { | 165 | if (user_mode(regs)) { |
165 | bad_trap(regs, trap_level); | 166 | bad_trap(regs, trap_level); |
166 | return; | 167 | goto out; |
167 | } | 168 | } |
168 | 169 | ||
169 | flushw_all(); | 170 | flushw_all(); |
@@ -171,6 +172,8 @@ asmlinkage void kgdb_trap(unsigned long trap_level, struct pt_regs *regs) | |||
171 | local_irq_save(flags); | 172 | local_irq_save(flags); |
172 | kgdb_handle_exception(0x172, SIGTRAP, 0, regs); | 173 | kgdb_handle_exception(0x172, SIGTRAP, 0, regs); |
173 | local_irq_restore(flags); | 174 | local_irq_restore(flags); |
175 | out: | ||
176 | exception_exit(prev_state); | ||
174 | } | 177 | } |
175 | 178 | ||
176 | int kgdb_arch_init(void) | 179 | int kgdb_arch_init(void) |
diff --git a/arch/sparc/kernel/kprobes.c b/arch/sparc/kernel/kprobes.c index e72212148d2a..5a09fd315e5f 100644 --- a/arch/sparc/kernel/kprobes.c +++ b/arch/sparc/kernel/kprobes.c | |||
@@ -8,6 +8,7 @@ | |||
8 | #include <linux/module.h> | 8 | #include <linux/module.h> |
9 | #include <linux/kdebug.h> | 9 | #include <linux/kdebug.h> |
10 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
11 | #include <linux/context_tracking.h> | ||
11 | #include <asm/signal.h> | 12 | #include <asm/signal.h> |
12 | #include <asm/cacheflush.h> | 13 | #include <asm/cacheflush.h> |
13 | #include <asm/uaccess.h> | 14 | #include <asm/uaccess.h> |
@@ -418,12 +419,14 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, | |||
418 | asmlinkage void __kprobes kprobe_trap(unsigned long trap_level, | 419 | asmlinkage void __kprobes kprobe_trap(unsigned long trap_level, |
419 | struct pt_regs *regs) | 420 | struct pt_regs *regs) |
420 | { | 421 | { |
422 | enum ctx_state prev_state = exception_enter(); | ||
423 | |||
421 | BUG_ON(trap_level != 0x170 && trap_level != 0x171); | 424 | BUG_ON(trap_level != 0x170 && trap_level != 0x171); |
422 | 425 | ||
423 | if (user_mode(regs)) { | 426 | if (user_mode(regs)) { |
424 | local_irq_enable(); | 427 | local_irq_enable(); |
425 | bad_trap(regs, trap_level); | 428 | bad_trap(regs, trap_level); |
426 | return; | 429 | goto out; |
427 | } | 430 | } |
428 | 431 | ||
429 | /* trap_level == 0x170 --> ta 0x70 | 432 | /* trap_level == 0x170 --> ta 0x70 |
@@ -433,6 +436,8 @@ asmlinkage void __kprobes kprobe_trap(unsigned long trap_level, | |||
433 | (trap_level == 0x170) ? "debug" : "debug_2", | 436 | (trap_level == 0x170) ? "debug" : "debug_2", |
434 | regs, 0, trap_level, SIGTRAP) != NOTIFY_STOP) | 437 | regs, 0, trap_level, SIGTRAP) != NOTIFY_STOP) |
435 | bad_trap(regs, trap_level); | 438 | bad_trap(regs, trap_level); |
439 | out: | ||
440 | exception_exit(prev_state); | ||
436 | } | 441 | } |
437 | 442 | ||
438 | /* Jprobes support. */ | 443 | /* Jprobes support. */ |
diff --git a/arch/sparc/kernel/process_64.c b/arch/sparc/kernel/process_64.c index baebab215492..32a280ec38c1 100644 --- a/arch/sparc/kernel/process_64.c +++ b/arch/sparc/kernel/process_64.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/elfcore.h> | 31 | #include <linux/elfcore.h> |
32 | #include <linux/sysrq.h> | 32 | #include <linux/sysrq.h> |
33 | #include <linux/nmi.h> | 33 | #include <linux/nmi.h> |
34 | #include <linux/context_tracking.h> | ||
34 | 35 | ||
35 | #include <asm/uaccess.h> | 36 | #include <asm/uaccess.h> |
36 | #include <asm/page.h> | 37 | #include <asm/page.h> |
@@ -557,6 +558,7 @@ void fault_in_user_windows(void) | |||
557 | 558 | ||
558 | barf: | 559 | barf: |
559 | set_thread_wsaved(window + 1); | 560 | set_thread_wsaved(window + 1); |
561 | user_exit(); | ||
560 | do_exit(SIGILL); | 562 | do_exit(SIGILL); |
561 | } | 563 | } |
562 | 564 | ||
diff --git a/arch/sparc/kernel/ptrace_64.c b/arch/sparc/kernel/ptrace_64.c index 773c1f2983ce..c13c9f25d83a 100644 --- a/arch/sparc/kernel/ptrace_64.c +++ b/arch/sparc/kernel/ptrace_64.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <trace/syscall.h> | 27 | #include <trace/syscall.h> |
28 | #include <linux/compat.h> | 28 | #include <linux/compat.h> |
29 | #include <linux/elf.h> | 29 | #include <linux/elf.h> |
30 | #include <linux/context_tracking.h> | ||
30 | 31 | ||
31 | #include <asm/asi.h> | 32 | #include <asm/asi.h> |
32 | #include <asm/pgtable.h> | 33 | #include <asm/pgtable.h> |
@@ -1066,6 +1067,9 @@ asmlinkage int syscall_trace_enter(struct pt_regs *regs) | |||
1066 | /* do the secure computing check first */ | 1067 | /* do the secure computing check first */ |
1067 | secure_computing_strict(regs->u_regs[UREG_G1]); | 1068 | secure_computing_strict(regs->u_regs[UREG_G1]); |
1068 | 1069 | ||
1070 | if (test_thread_flag(TIF_NOHZ)) | ||
1071 | user_exit(); | ||
1072 | |||
1069 | if (test_thread_flag(TIF_SYSCALL_TRACE)) | 1073 | if (test_thread_flag(TIF_SYSCALL_TRACE)) |
1070 | ret = tracehook_report_syscall_entry(regs); | 1074 | ret = tracehook_report_syscall_entry(regs); |
1071 | 1075 | ||
@@ -1086,6 +1090,9 @@ asmlinkage int syscall_trace_enter(struct pt_regs *regs) | |||
1086 | 1090 | ||
1087 | asmlinkage void syscall_trace_leave(struct pt_regs *regs) | 1091 | asmlinkage void syscall_trace_leave(struct pt_regs *regs) |
1088 | { | 1092 | { |
1093 | if (test_thread_flag(TIF_NOHZ)) | ||
1094 | user_exit(); | ||
1095 | |||
1089 | audit_syscall_exit(regs); | 1096 | audit_syscall_exit(regs); |
1090 | 1097 | ||
1091 | if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) | 1098 | if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) |
@@ -1093,4 +1100,7 @@ asmlinkage void syscall_trace_leave(struct pt_regs *regs) | |||
1093 | 1100 | ||
1094 | if (test_thread_flag(TIF_SYSCALL_TRACE)) | 1101 | if (test_thread_flag(TIF_SYSCALL_TRACE)) |
1095 | tracehook_report_syscall_exit(regs, 0); | 1102 | tracehook_report_syscall_exit(regs, 0); |
1103 | |||
1104 | if (test_thread_flag(TIF_NOHZ)) | ||
1105 | user_enter(); | ||
1096 | } | 1106 | } |
diff --git a/arch/sparc/kernel/rtrap_64.S b/arch/sparc/kernel/rtrap_64.S index afa2a9e3d0a0..a954eb81881b 100644 --- a/arch/sparc/kernel/rtrap_64.S +++ b/arch/sparc/kernel/rtrap_64.S | |||
@@ -18,10 +18,16 @@ | |||
18 | #define RTRAP_PSTATE_IRQOFF (PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV) | 18 | #define RTRAP_PSTATE_IRQOFF (PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV) |
19 | #define RTRAP_PSTATE_AG_IRQOFF (PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV|PSTATE_AG) | 19 | #define RTRAP_PSTATE_AG_IRQOFF (PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV|PSTATE_AG) |
20 | 20 | ||
21 | #ifdef CONFIG_CONTEXT_TRACKING | ||
22 | # define SCHEDULE_USER schedule_user | ||
23 | #else | ||
24 | # define SCHEDULE_USER schedule | ||
25 | #endif | ||
26 | |||
21 | .text | 27 | .text |
22 | .align 32 | 28 | .align 32 |
23 | __handle_preemption: | 29 | __handle_preemption: |
24 | call schedule | 30 | call SCHEDULE_USER |
25 | wrpr %g0, RTRAP_PSTATE, %pstate | 31 | wrpr %g0, RTRAP_PSTATE, %pstate |
26 | ba,pt %xcc, __handle_preemption_continue | 32 | ba,pt %xcc, __handle_preemption_continue |
27 | wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate | 33 | wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate |
diff --git a/arch/sparc/kernel/signal_64.c b/arch/sparc/kernel/signal_64.c index 35923e8abd82..cd91d010e6d3 100644 --- a/arch/sparc/kernel/signal_64.c +++ b/arch/sparc/kernel/signal_64.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/tty.h> | 23 | #include <linux/tty.h> |
24 | #include <linux/binfmts.h> | 24 | #include <linux/binfmts.h> |
25 | #include <linux/bitops.h> | 25 | #include <linux/bitops.h> |
26 | #include <linux/context_tracking.h> | ||
26 | 27 | ||
27 | #include <asm/uaccess.h> | 28 | #include <asm/uaccess.h> |
28 | #include <asm/ptrace.h> | 29 | #include <asm/ptrace.h> |
@@ -43,6 +44,7 @@ asmlinkage void sparc64_set_context(struct pt_regs *regs) | |||
43 | { | 44 | { |
44 | struct ucontext __user *ucp = (struct ucontext __user *) | 45 | struct ucontext __user *ucp = (struct ucontext __user *) |
45 | regs->u_regs[UREG_I0]; | 46 | regs->u_regs[UREG_I0]; |
47 | enum ctx_state prev_state = exception_enter(); | ||
46 | mc_gregset_t __user *grp; | 48 | mc_gregset_t __user *grp; |
47 | unsigned long pc, npc, tstate; | 49 | unsigned long pc, npc, tstate; |
48 | unsigned long fp, i7; | 50 | unsigned long fp, i7; |
@@ -129,16 +131,19 @@ asmlinkage void sparc64_set_context(struct pt_regs *regs) | |||
129 | } | 131 | } |
130 | if (err) | 132 | if (err) |
131 | goto do_sigsegv; | 133 | goto do_sigsegv; |
132 | 134 | out: | |
135 | exception_exit(prev_state); | ||
133 | return; | 136 | return; |
134 | do_sigsegv: | 137 | do_sigsegv: |
135 | force_sig(SIGSEGV, current); | 138 | force_sig(SIGSEGV, current); |
139 | goto out; | ||
136 | } | 140 | } |
137 | 141 | ||
138 | asmlinkage void sparc64_get_context(struct pt_regs *regs) | 142 | asmlinkage void sparc64_get_context(struct pt_regs *regs) |
139 | { | 143 | { |
140 | struct ucontext __user *ucp = (struct ucontext __user *) | 144 | struct ucontext __user *ucp = (struct ucontext __user *) |
141 | regs->u_regs[UREG_I0]; | 145 | regs->u_regs[UREG_I0]; |
146 | enum ctx_state prev_state = exception_enter(); | ||
142 | mc_gregset_t __user *grp; | 147 | mc_gregset_t __user *grp; |
143 | mcontext_t __user *mcp; | 148 | mcontext_t __user *mcp; |
144 | unsigned long fp, i7; | 149 | unsigned long fp, i7; |
@@ -220,10 +225,12 @@ asmlinkage void sparc64_get_context(struct pt_regs *regs) | |||
220 | } | 225 | } |
221 | if (err) | 226 | if (err) |
222 | goto do_sigsegv; | 227 | goto do_sigsegv; |
223 | 228 | out: | |
229 | exception_exit(prev_state); | ||
224 | return; | 230 | return; |
225 | do_sigsegv: | 231 | do_sigsegv: |
226 | force_sig(SIGSEGV, current); | 232 | force_sig(SIGSEGV, current); |
233 | goto out; | ||
227 | } | 234 | } |
228 | 235 | ||
229 | struct rt_signal_frame { | 236 | struct rt_signal_frame { |
@@ -528,11 +535,13 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) | |||
528 | 535 | ||
529 | void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, unsigned long thread_info_flags) | 536 | void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, unsigned long thread_info_flags) |
530 | { | 537 | { |
538 | user_exit(); | ||
531 | if (thread_info_flags & _TIF_SIGPENDING) | 539 | if (thread_info_flags & _TIF_SIGPENDING) |
532 | do_signal(regs, orig_i0); | 540 | do_signal(regs, orig_i0); |
533 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { | 541 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { |
534 | clear_thread_flag(TIF_NOTIFY_RESUME); | 542 | clear_thread_flag(TIF_NOTIFY_RESUME); |
535 | tracehook_notify_resume(regs); | 543 | tracehook_notify_resume(regs); |
536 | } | 544 | } |
545 | user_enter(); | ||
537 | } | 546 | } |
538 | 547 | ||
diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c index d05eb9c1d846..beb0b5a5f21f 100644 --- a/arch/sparc/kernel/sys_sparc_64.c +++ b/arch/sparc/kernel/sys_sparc_64.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/personality.h> | 24 | #include <linux/personality.h> |
25 | #include <linux/random.h> | 25 | #include <linux/random.h> |
26 | #include <linux/export.h> | 26 | #include <linux/export.h> |
27 | #include <linux/context_tracking.h> | ||
27 | 28 | ||
28 | #include <asm/uaccess.h> | 29 | #include <asm/uaccess.h> |
29 | #include <asm/utrap.h> | 30 | #include <asm/utrap.h> |
@@ -496,6 +497,7 @@ asmlinkage unsigned long c_sys_nis_syscall(struct pt_regs *regs) | |||
496 | 497 | ||
497 | asmlinkage void sparc_breakpoint(struct pt_regs *regs) | 498 | asmlinkage void sparc_breakpoint(struct pt_regs *regs) |
498 | { | 499 | { |
500 | enum ctx_state prev_state = exception_enter(); | ||
499 | siginfo_t info; | 501 | siginfo_t info; |
500 | 502 | ||
501 | if (test_thread_flag(TIF_32BIT)) { | 503 | if (test_thread_flag(TIF_32BIT)) { |
@@ -514,6 +516,7 @@ asmlinkage void sparc_breakpoint(struct pt_regs *regs) | |||
514 | #ifdef DEBUG_SPARC_BREAKPOINT | 516 | #ifdef DEBUG_SPARC_BREAKPOINT |
515 | printk ("TRAP: Returning to space: PC=%lx nPC=%lx\n", regs->tpc, regs->tnpc); | 517 | printk ("TRAP: Returning to space: PC=%lx nPC=%lx\n", regs->tpc, regs->tnpc); |
516 | #endif | 518 | #endif |
519 | exception_exit(prev_state); | ||
517 | } | 520 | } |
518 | 521 | ||
519 | extern void check_pending(int signum); | 522 | extern void check_pending(int signum); |
diff --git a/arch/sparc/kernel/syscalls.S b/arch/sparc/kernel/syscalls.S index d950197a17e1..87729fff13b9 100644 --- a/arch/sparc/kernel/syscalls.S +++ b/arch/sparc/kernel/syscalls.S | |||
@@ -52,7 +52,7 @@ sys32_rt_sigreturn: | |||
52 | #endif | 52 | #endif |
53 | .align 32 | 53 | .align 32 |
54 | 1: ldx [%g6 + TI_FLAGS], %l5 | 54 | 1: ldx [%g6 + TI_FLAGS], %l5 |
55 | andcc %l5, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %g0 | 55 | andcc %l5, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT|_TIF_NOHZ), %g0 |
56 | be,pt %icc, rtrap | 56 | be,pt %icc, rtrap |
57 | nop | 57 | nop |
58 | call syscall_trace_leave | 58 | call syscall_trace_leave |
@@ -184,7 +184,7 @@ linux_sparc_syscall32: | |||
184 | 184 | ||
185 | srl %i3, 0, %o3 ! IEU0 | 185 | srl %i3, 0, %o3 ! IEU0 |
186 | srl %i2, 0, %o2 ! IEU0 Group | 186 | srl %i2, 0, %o2 ! IEU0 Group |
187 | andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %g0 | 187 | andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT|_TIF_NOHZ), %g0 |
188 | bne,pn %icc, linux_syscall_trace32 ! CTI | 188 | bne,pn %icc, linux_syscall_trace32 ! CTI |
189 | mov %i0, %l5 ! IEU1 | 189 | mov %i0, %l5 ! IEU1 |
190 | 5: call %l7 ! CTI Group brk forced | 190 | 5: call %l7 ! CTI Group brk forced |
@@ -207,7 +207,7 @@ linux_sparc_syscall: | |||
207 | 207 | ||
208 | mov %i3, %o3 ! IEU1 | 208 | mov %i3, %o3 ! IEU1 |
209 | mov %i4, %o4 ! IEU0 Group | 209 | mov %i4, %o4 ! IEU0 Group |
210 | andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %g0 | 210 | andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT|_TIF_NOHZ), %g0 |
211 | bne,pn %icc, linux_syscall_trace ! CTI Group | 211 | bne,pn %icc, linux_syscall_trace ! CTI Group |
212 | mov %i0, %l5 ! IEU0 | 212 | mov %i0, %l5 ! IEU0 |
213 | 2: call %l7 ! CTI Group brk forced | 213 | 2: call %l7 ! CTI Group brk forced |
@@ -223,7 +223,7 @@ ret_sys_call: | |||
223 | 223 | ||
224 | cmp %o0, -ERESTART_RESTARTBLOCK | 224 | cmp %o0, -ERESTART_RESTARTBLOCK |
225 | bgeu,pn %xcc, 1f | 225 | bgeu,pn %xcc, 1f |
226 | andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %g0 | 226 | andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT|_TIF_NOHZ), %g0 |
227 | ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc | 227 | ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc |
228 | 228 | ||
229 | 2: | 229 | 2: |
diff --git a/arch/sparc/kernel/traps_64.c b/arch/sparc/kernel/traps_64.c index b3f833ab90eb..4ced92f05358 100644 --- a/arch/sparc/kernel/traps_64.c +++ b/arch/sparc/kernel/traps_64.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/ftrace.h> | 20 | #include <linux/ftrace.h> |
21 | #include <linux/reboot.h> | 21 | #include <linux/reboot.h> |
22 | #include <linux/gfp.h> | 22 | #include <linux/gfp.h> |
23 | #include <linux/context_tracking.h> | ||
23 | 24 | ||
24 | #include <asm/smp.h> | 25 | #include <asm/smp.h> |
25 | #include <asm/delay.h> | 26 | #include <asm/delay.h> |
@@ -186,11 +187,12 @@ EXPORT_SYMBOL_GPL(unregister_dimm_printer); | |||
186 | 187 | ||
187 | void spitfire_insn_access_exception(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar) | 188 | void spitfire_insn_access_exception(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar) |
188 | { | 189 | { |
190 | enum ctx_state prev_state = exception_enter(); | ||
189 | siginfo_t info; | 191 | siginfo_t info; |
190 | 192 | ||
191 | if (notify_die(DIE_TRAP, "instruction access exception", regs, | 193 | if (notify_die(DIE_TRAP, "instruction access exception", regs, |
192 | 0, 0x8, SIGTRAP) == NOTIFY_STOP) | 194 | 0, 0x8, SIGTRAP) == NOTIFY_STOP) |
193 | return; | 195 | goto out; |
194 | 196 | ||
195 | if (regs->tstate & TSTATE_PRIV) { | 197 | if (regs->tstate & TSTATE_PRIV) { |
196 | printk("spitfire_insn_access_exception: SFSR[%016lx] " | 198 | printk("spitfire_insn_access_exception: SFSR[%016lx] " |
@@ -207,6 +209,8 @@ void spitfire_insn_access_exception(struct pt_regs *regs, unsigned long sfsr, un | |||
207 | info.si_addr = (void __user *)regs->tpc; | 209 | info.si_addr = (void __user *)regs->tpc; |
208 | info.si_trapno = 0; | 210 | info.si_trapno = 0; |
209 | force_sig_info(SIGSEGV, &info, current); | 211 | force_sig_info(SIGSEGV, &info, current); |
212 | out: | ||
213 | exception_exit(prev_state); | ||
210 | } | 214 | } |
211 | 215 | ||
212 | void spitfire_insn_access_exception_tl1(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar) | 216 | void spitfire_insn_access_exception_tl1(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar) |
@@ -260,11 +264,12 @@ void sun4v_insn_access_exception_tl1(struct pt_regs *regs, unsigned long addr, u | |||
260 | 264 | ||
261 | void spitfire_data_access_exception(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar) | 265 | void spitfire_data_access_exception(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar) |
262 | { | 266 | { |
267 | enum ctx_state prev_state = exception_enter(); | ||
263 | siginfo_t info; | 268 | siginfo_t info; |
264 | 269 | ||
265 | if (notify_die(DIE_TRAP, "data access exception", regs, | 270 | if (notify_die(DIE_TRAP, "data access exception", regs, |
266 | 0, 0x30, SIGTRAP) == NOTIFY_STOP) | 271 | 0, 0x30, SIGTRAP) == NOTIFY_STOP) |
267 | return; | 272 | goto out; |
268 | 273 | ||
269 | if (regs->tstate & TSTATE_PRIV) { | 274 | if (regs->tstate & TSTATE_PRIV) { |
270 | /* Test if this comes from uaccess places. */ | 275 | /* Test if this comes from uaccess places. */ |
@@ -280,7 +285,7 @@ void spitfire_data_access_exception(struct pt_regs *regs, unsigned long sfsr, un | |||
280 | #endif | 285 | #endif |
281 | regs->tpc = entry->fixup; | 286 | regs->tpc = entry->fixup; |
282 | regs->tnpc = regs->tpc + 4; | 287 | regs->tnpc = regs->tpc + 4; |
283 | return; | 288 | goto out; |
284 | } | 289 | } |
285 | /* Shit... */ | 290 | /* Shit... */ |
286 | printk("spitfire_data_access_exception: SFSR[%016lx] " | 291 | printk("spitfire_data_access_exception: SFSR[%016lx] " |
@@ -294,6 +299,8 @@ void spitfire_data_access_exception(struct pt_regs *regs, unsigned long sfsr, un | |||
294 | info.si_addr = (void __user *)sfar; | 299 | info.si_addr = (void __user *)sfar; |
295 | info.si_trapno = 0; | 300 | info.si_trapno = 0; |
296 | force_sig_info(SIGSEGV, &info, current); | 301 | force_sig_info(SIGSEGV, &info, current); |
302 | out: | ||
303 | exception_exit(prev_state); | ||
297 | } | 304 | } |
298 | 305 | ||
299 | void spitfire_data_access_exception_tl1(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar) | 306 | void spitfire_data_access_exception_tl1(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar) |
@@ -1994,6 +2001,7 @@ static void sun4v_log_error(struct pt_regs *regs, struct sun4v_error_entry *ent, | |||
1994 | */ | 2001 | */ |
1995 | void sun4v_resum_error(struct pt_regs *regs, unsigned long offset) | 2002 | void sun4v_resum_error(struct pt_regs *regs, unsigned long offset) |
1996 | { | 2003 | { |
2004 | enum ctx_state prev_state = exception_enter(); | ||
1997 | struct sun4v_error_entry *ent, local_copy; | 2005 | struct sun4v_error_entry *ent, local_copy; |
1998 | struct trap_per_cpu *tb; | 2006 | struct trap_per_cpu *tb; |
1999 | unsigned long paddr; | 2007 | unsigned long paddr; |
@@ -2022,12 +2030,14 @@ void sun4v_resum_error(struct pt_regs *regs, unsigned long offset) | |||
2022 | pr_info("Shutdown request, %u seconds...\n", | 2030 | pr_info("Shutdown request, %u seconds...\n", |
2023 | local_copy.err_secs); | 2031 | local_copy.err_secs); |
2024 | orderly_poweroff(true); | 2032 | orderly_poweroff(true); |
2025 | return; | 2033 | goto out; |
2026 | } | 2034 | } |
2027 | 2035 | ||
2028 | sun4v_log_error(regs, &local_copy, cpu, | 2036 | sun4v_log_error(regs, &local_copy, cpu, |
2029 | KERN_ERR "RESUMABLE ERROR", | 2037 | KERN_ERR "RESUMABLE ERROR", |
2030 | &sun4v_resum_oflow_cnt); | 2038 | &sun4v_resum_oflow_cnt); |
2039 | out: | ||
2040 | exception_exit(prev_state); | ||
2031 | } | 2041 | } |
2032 | 2042 | ||
2033 | /* If we try to printk() we'll probably make matters worse, by trying | 2043 | /* If we try to printk() we'll probably make matters worse, by trying |
@@ -2152,7 +2162,7 @@ void hypervisor_tlbop_error_xcall(unsigned long err, unsigned long op) | |||
2152 | err, op); | 2162 | err, op); |
2153 | } | 2163 | } |
2154 | 2164 | ||
2155 | void do_fpe_common(struct pt_regs *regs) | 2165 | static void do_fpe_common(struct pt_regs *regs) |
2156 | { | 2166 | { |
2157 | if (regs->tstate & TSTATE_PRIV) { | 2167 | if (regs->tstate & TSTATE_PRIV) { |
2158 | regs->tpc = regs->tnpc; | 2168 | regs->tpc = regs->tnpc; |
@@ -2188,23 +2198,28 @@ void do_fpe_common(struct pt_regs *regs) | |||
2188 | 2198 | ||
2189 | void do_fpieee(struct pt_regs *regs) | 2199 | void do_fpieee(struct pt_regs *regs) |
2190 | { | 2200 | { |
2201 | enum ctx_state prev_state = exception_enter(); | ||
2202 | |||
2191 | if (notify_die(DIE_TRAP, "fpu exception ieee", regs, | 2203 | if (notify_die(DIE_TRAP, "fpu exception ieee", regs, |
2192 | 0, 0x24, SIGFPE) == NOTIFY_STOP) | 2204 | 0, 0x24, SIGFPE) == NOTIFY_STOP) |
2193 | return; | 2205 | goto out; |
2194 | 2206 | ||
2195 | do_fpe_common(regs); | 2207 | do_fpe_common(regs); |
2208 | out: | ||
2209 | exception_exit(prev_state); | ||
2196 | } | 2210 | } |
2197 | 2211 | ||
2198 | extern int do_mathemu(struct pt_regs *, struct fpustate *, bool); | 2212 | extern int do_mathemu(struct pt_regs *, struct fpustate *, bool); |
2199 | 2213 | ||
2200 | void do_fpother(struct pt_regs *regs) | 2214 | void do_fpother(struct pt_regs *regs) |
2201 | { | 2215 | { |
2216 | enum ctx_state prev_state = exception_enter(); | ||
2202 | struct fpustate *f = FPUSTATE; | 2217 | struct fpustate *f = FPUSTATE; |
2203 | int ret = 0; | 2218 | int ret = 0; |
2204 | 2219 | ||
2205 | if (notify_die(DIE_TRAP, "fpu exception other", regs, | 2220 | if (notify_die(DIE_TRAP, "fpu exception other", regs, |
2206 | 0, 0x25, SIGFPE) == NOTIFY_STOP) | 2221 | 0, 0x25, SIGFPE) == NOTIFY_STOP) |
2207 | return; | 2222 | goto out; |
2208 | 2223 | ||
2209 | switch ((current_thread_info()->xfsr[0] & 0x1c000)) { | 2224 | switch ((current_thread_info()->xfsr[0] & 0x1c000)) { |
2210 | case (2 << 14): /* unfinished_FPop */ | 2225 | case (2 << 14): /* unfinished_FPop */ |
@@ -2213,17 +2228,20 @@ void do_fpother(struct pt_regs *regs) | |||
2213 | break; | 2228 | break; |
2214 | } | 2229 | } |
2215 | if (ret) | 2230 | if (ret) |
2216 | return; | 2231 | goto out; |
2217 | do_fpe_common(regs); | 2232 | do_fpe_common(regs); |
2233 | out: | ||
2234 | exception_exit(prev_state); | ||
2218 | } | 2235 | } |
2219 | 2236 | ||
2220 | void do_tof(struct pt_regs *regs) | 2237 | void do_tof(struct pt_regs *regs) |
2221 | { | 2238 | { |
2239 | enum ctx_state prev_state = exception_enter(); | ||
2222 | siginfo_t info; | 2240 | siginfo_t info; |
2223 | 2241 | ||
2224 | if (notify_die(DIE_TRAP, "tagged arithmetic overflow", regs, | 2242 | if (notify_die(DIE_TRAP, "tagged arithmetic overflow", regs, |
2225 | 0, 0x26, SIGEMT) == NOTIFY_STOP) | 2243 | 0, 0x26, SIGEMT) == NOTIFY_STOP) |
2226 | return; | 2244 | goto out; |
2227 | 2245 | ||
2228 | if (regs->tstate & TSTATE_PRIV) | 2246 | if (regs->tstate & TSTATE_PRIV) |
2229 | die_if_kernel("Penguin overflow trap from kernel mode", regs); | 2247 | die_if_kernel("Penguin overflow trap from kernel mode", regs); |
@@ -2237,15 +2255,18 @@ void do_tof(struct pt_regs *regs) | |||
2237 | info.si_addr = (void __user *)regs->tpc; | 2255 | info.si_addr = (void __user *)regs->tpc; |
2238 | info.si_trapno = 0; | 2256 | info.si_trapno = 0; |
2239 | force_sig_info(SIGEMT, &info, current); | 2257 | force_sig_info(SIGEMT, &info, current); |
2258 | out: | ||
2259 | exception_exit(prev_state); | ||
2240 | } | 2260 | } |
2241 | 2261 | ||
2242 | void do_div0(struct pt_regs *regs) | 2262 | void do_div0(struct pt_regs *regs) |
2243 | { | 2263 | { |
2264 | enum ctx_state prev_state = exception_enter(); | ||
2244 | siginfo_t info; | 2265 | siginfo_t info; |
2245 | 2266 | ||
2246 | if (notify_die(DIE_TRAP, "integer division by zero", regs, | 2267 | if (notify_die(DIE_TRAP, "integer division by zero", regs, |
2247 | 0, 0x28, SIGFPE) == NOTIFY_STOP) | 2268 | 0, 0x28, SIGFPE) == NOTIFY_STOP) |
2248 | return; | 2269 | goto out; |
2249 | 2270 | ||
2250 | if (regs->tstate & TSTATE_PRIV) | 2271 | if (regs->tstate & TSTATE_PRIV) |
2251 | die_if_kernel("TL0: Kernel divide by zero.", regs); | 2272 | die_if_kernel("TL0: Kernel divide by zero.", regs); |
@@ -2259,6 +2280,8 @@ void do_div0(struct pt_regs *regs) | |||
2259 | info.si_addr = (void __user *)regs->tpc; | 2280 | info.si_addr = (void __user *)regs->tpc; |
2260 | info.si_trapno = 0; | 2281 | info.si_trapno = 0; |
2261 | force_sig_info(SIGFPE, &info, current); | 2282 | force_sig_info(SIGFPE, &info, current); |
2283 | out: | ||
2284 | exception_exit(prev_state); | ||
2262 | } | 2285 | } |
2263 | 2286 | ||
2264 | static void instruction_dump(unsigned int *pc) | 2287 | static void instruction_dump(unsigned int *pc) |
@@ -2415,6 +2438,7 @@ extern int handle_ldf_stq(u32 insn, struct pt_regs *regs); | |||
2415 | 2438 | ||
2416 | void do_illegal_instruction(struct pt_regs *regs) | 2439 | void do_illegal_instruction(struct pt_regs *regs) |
2417 | { | 2440 | { |
2441 | enum ctx_state prev_state = exception_enter(); | ||
2418 | unsigned long pc = regs->tpc; | 2442 | unsigned long pc = regs->tpc; |
2419 | unsigned long tstate = regs->tstate; | 2443 | unsigned long tstate = regs->tstate; |
2420 | u32 insn; | 2444 | u32 insn; |
@@ -2422,7 +2446,7 @@ void do_illegal_instruction(struct pt_regs *regs) | |||
2422 | 2446 | ||
2423 | if (notify_die(DIE_TRAP, "illegal instruction", regs, | 2447 | if (notify_die(DIE_TRAP, "illegal instruction", regs, |
2424 | 0, 0x10, SIGILL) == NOTIFY_STOP) | 2448 | 0, 0x10, SIGILL) == NOTIFY_STOP) |
2425 | return; | 2449 | goto out; |
2426 | 2450 | ||
2427 | if (tstate & TSTATE_PRIV) | 2451 | if (tstate & TSTATE_PRIV) |
2428 | die_if_kernel("Kernel illegal instruction", regs); | 2452 | die_if_kernel("Kernel illegal instruction", regs); |
@@ -2431,14 +2455,14 @@ void do_illegal_instruction(struct pt_regs *regs) | |||
2431 | if (get_user(insn, (u32 __user *) pc) != -EFAULT) { | 2455 | if (get_user(insn, (u32 __user *) pc) != -EFAULT) { |
2432 | if ((insn & 0xc1ffc000) == 0x81700000) /* POPC */ { | 2456 | if ((insn & 0xc1ffc000) == 0x81700000) /* POPC */ { |
2433 | if (handle_popc(insn, regs)) | 2457 | if (handle_popc(insn, regs)) |
2434 | return; | 2458 | goto out; |
2435 | } else if ((insn & 0xc1580000) == 0xc1100000) /* LDQ/STQ */ { | 2459 | } else if ((insn & 0xc1580000) == 0xc1100000) /* LDQ/STQ */ { |
2436 | if (handle_ldf_stq(insn, regs)) | 2460 | if (handle_ldf_stq(insn, regs)) |
2437 | return; | 2461 | goto out; |
2438 | } else if (tlb_type == hypervisor) { | 2462 | } else if (tlb_type == hypervisor) { |
2439 | if ((insn & VIS_OPCODE_MASK) == VIS_OPCODE_VAL) { | 2463 | if ((insn & VIS_OPCODE_MASK) == VIS_OPCODE_VAL) { |
2440 | if (!vis_emul(regs, insn)) | 2464 | if (!vis_emul(regs, insn)) |
2441 | return; | 2465 | goto out; |
2442 | } else { | 2466 | } else { |
2443 | struct fpustate *f = FPUSTATE; | 2467 | struct fpustate *f = FPUSTATE; |
2444 | 2468 | ||
@@ -2448,7 +2472,7 @@ void do_illegal_instruction(struct pt_regs *regs) | |||
2448 | * Trap in the %fsr to unimplemented_FPop. | 2472 | * Trap in the %fsr to unimplemented_FPop. |
2449 | */ | 2473 | */ |
2450 | if (do_mathemu(regs, f, true)) | 2474 | if (do_mathemu(regs, f, true)) |
2451 | return; | 2475 | goto out; |
2452 | } | 2476 | } |
2453 | } | 2477 | } |
2454 | } | 2478 | } |
@@ -2458,21 +2482,24 @@ void do_illegal_instruction(struct pt_regs *regs) | |||
2458 | info.si_addr = (void __user *)pc; | 2482 | info.si_addr = (void __user *)pc; |
2459 | info.si_trapno = 0; | 2483 | info.si_trapno = 0; |
2460 | force_sig_info(SIGILL, &info, current); | 2484 | force_sig_info(SIGILL, &info, current); |
2485 | out: | ||
2486 | exception_exit(prev_state); | ||
2461 | } | 2487 | } |
2462 | 2488 | ||
2463 | extern void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn); | 2489 | extern void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn); |
2464 | 2490 | ||
2465 | void mem_address_unaligned(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr) | 2491 | void mem_address_unaligned(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr) |
2466 | { | 2492 | { |
2493 | enum ctx_state prev_state = exception_enter(); | ||
2467 | siginfo_t info; | 2494 | siginfo_t info; |
2468 | 2495 | ||
2469 | if (notify_die(DIE_TRAP, "memory address unaligned", regs, | 2496 | if (notify_die(DIE_TRAP, "memory address unaligned", regs, |
2470 | 0, 0x34, SIGSEGV) == NOTIFY_STOP) | 2497 | 0, 0x34, SIGSEGV) == NOTIFY_STOP) |
2471 | return; | 2498 | goto out; |
2472 | 2499 | ||
2473 | if (regs->tstate & TSTATE_PRIV) { | 2500 | if (regs->tstate & TSTATE_PRIV) { |
2474 | kernel_unaligned_trap(regs, *((unsigned int *)regs->tpc)); | 2501 | kernel_unaligned_trap(regs, *((unsigned int *)regs->tpc)); |
2475 | return; | 2502 | goto out; |
2476 | } | 2503 | } |
2477 | info.si_signo = SIGBUS; | 2504 | info.si_signo = SIGBUS; |
2478 | info.si_errno = 0; | 2505 | info.si_errno = 0; |
@@ -2480,6 +2507,8 @@ void mem_address_unaligned(struct pt_regs *regs, unsigned long sfar, unsigned lo | |||
2480 | info.si_addr = (void __user *)sfar; | 2507 | info.si_addr = (void __user *)sfar; |
2481 | info.si_trapno = 0; | 2508 | info.si_trapno = 0; |
2482 | force_sig_info(SIGBUS, &info, current); | 2509 | force_sig_info(SIGBUS, &info, current); |
2510 | out: | ||
2511 | exception_exit(prev_state); | ||
2483 | } | 2512 | } |
2484 | 2513 | ||
2485 | void sun4v_do_mna(struct pt_regs *regs, unsigned long addr, unsigned long type_ctx) | 2514 | void sun4v_do_mna(struct pt_regs *regs, unsigned long addr, unsigned long type_ctx) |
@@ -2504,11 +2533,12 @@ void sun4v_do_mna(struct pt_regs *regs, unsigned long addr, unsigned long type_c | |||
2504 | 2533 | ||
2505 | void do_privop(struct pt_regs *regs) | 2534 | void do_privop(struct pt_regs *regs) |
2506 | { | 2535 | { |
2536 | enum ctx_state prev_state = exception_enter(); | ||
2507 | siginfo_t info; | 2537 | siginfo_t info; |
2508 | 2538 | ||
2509 | if (notify_die(DIE_TRAP, "privileged operation", regs, | 2539 | if (notify_die(DIE_TRAP, "privileged operation", regs, |
2510 | 0, 0x11, SIGILL) == NOTIFY_STOP) | 2540 | 0, 0x11, SIGILL) == NOTIFY_STOP) |
2511 | return; | 2541 | goto out; |
2512 | 2542 | ||
2513 | if (test_thread_flag(TIF_32BIT)) { | 2543 | if (test_thread_flag(TIF_32BIT)) { |
2514 | regs->tpc &= 0xffffffff; | 2544 | regs->tpc &= 0xffffffff; |
@@ -2520,6 +2550,8 @@ void do_privop(struct pt_regs *regs) | |||
2520 | info.si_addr = (void __user *)regs->tpc; | 2550 | info.si_addr = (void __user *)regs->tpc; |
2521 | info.si_trapno = 0; | 2551 | info.si_trapno = 0; |
2522 | force_sig_info(SIGILL, &info, current); | 2552 | force_sig_info(SIGILL, &info, current); |
2553 | out: | ||
2554 | exception_exit(prev_state); | ||
2523 | } | 2555 | } |
2524 | 2556 | ||
2525 | void do_privact(struct pt_regs *regs) | 2557 | void do_privact(struct pt_regs *regs) |
@@ -2530,99 +2562,116 @@ void do_privact(struct pt_regs *regs) | |||
2530 | /* Trap level 1 stuff or other traps we should never see... */ | 2562 | /* Trap level 1 stuff or other traps we should never see... */ |
2531 | void do_cee(struct pt_regs *regs) | 2563 | void do_cee(struct pt_regs *regs) |
2532 | { | 2564 | { |
2565 | exception_enter(); | ||
2533 | die_if_kernel("TL0: Cache Error Exception", regs); | 2566 | die_if_kernel("TL0: Cache Error Exception", regs); |
2534 | } | 2567 | } |
2535 | 2568 | ||
2536 | void do_cee_tl1(struct pt_regs *regs) | 2569 | void do_cee_tl1(struct pt_regs *regs) |
2537 | { | 2570 | { |
2571 | exception_enter(); | ||
2538 | dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); | 2572 | dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); |
2539 | die_if_kernel("TL1: Cache Error Exception", regs); | 2573 | die_if_kernel("TL1: Cache Error Exception", regs); |
2540 | } | 2574 | } |
2541 | 2575 | ||
2542 | void do_dae_tl1(struct pt_regs *regs) | 2576 | void do_dae_tl1(struct pt_regs *regs) |
2543 | { | 2577 | { |
2578 | exception_enter(); | ||
2544 | dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); | 2579 | dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); |
2545 | die_if_kernel("TL1: Data Access Exception", regs); | 2580 | die_if_kernel("TL1: Data Access Exception", regs); |
2546 | } | 2581 | } |
2547 | 2582 | ||
2548 | void do_iae_tl1(struct pt_regs *regs) | 2583 | void do_iae_tl1(struct pt_regs *regs) |
2549 | { | 2584 | { |
2585 | exception_enter(); | ||
2550 | dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); | 2586 | dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); |
2551 | die_if_kernel("TL1: Instruction Access Exception", regs); | 2587 | die_if_kernel("TL1: Instruction Access Exception", regs); |
2552 | } | 2588 | } |
2553 | 2589 | ||
2554 | void do_div0_tl1(struct pt_regs *regs) | 2590 | void do_div0_tl1(struct pt_regs *regs) |
2555 | { | 2591 | { |
2592 | exception_enter(); | ||
2556 | dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); | 2593 | dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); |
2557 | die_if_kernel("TL1: DIV0 Exception", regs); | 2594 | die_if_kernel("TL1: DIV0 Exception", regs); |
2558 | } | 2595 | } |
2559 | 2596 | ||
2560 | void do_fpdis_tl1(struct pt_regs *regs) | 2597 | void do_fpdis_tl1(struct pt_regs *regs) |
2561 | { | 2598 | { |
2599 | exception_enter(); | ||
2562 | dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); | 2600 | dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); |
2563 | die_if_kernel("TL1: FPU Disabled", regs); | 2601 | die_if_kernel("TL1: FPU Disabled", regs); |
2564 | } | 2602 | } |
2565 | 2603 | ||
2566 | void do_fpieee_tl1(struct pt_regs *regs) | 2604 | void do_fpieee_tl1(struct pt_regs *regs) |
2567 | { | 2605 | { |
2606 | exception_enter(); | ||
2568 | dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); | 2607 | dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); |
2569 | die_if_kernel("TL1: FPU IEEE Exception", regs); | 2608 | die_if_kernel("TL1: FPU IEEE Exception", regs); |
2570 | } | 2609 | } |
2571 | 2610 | ||
2572 | void do_fpother_tl1(struct pt_regs *regs) | 2611 | void do_fpother_tl1(struct pt_regs *regs) |
2573 | { | 2612 | { |
2613 | exception_enter(); | ||
2574 | dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); | 2614 | dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); |
2575 | die_if_kernel("TL1: FPU Other Exception", regs); | 2615 | die_if_kernel("TL1: FPU Other Exception", regs); |
2576 | } | 2616 | } |
2577 | 2617 | ||
2578 | void do_ill_tl1(struct pt_regs *regs) | 2618 | void do_ill_tl1(struct pt_regs *regs) |
2579 | { | 2619 | { |
2620 | exception_enter(); | ||
2580 | dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); | 2621 | dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); |
2581 | die_if_kernel("TL1: Illegal Instruction Exception", regs); | 2622 | die_if_kernel("TL1: Illegal Instruction Exception", regs); |
2582 | } | 2623 | } |
2583 | 2624 | ||
2584 | void do_irq_tl1(struct pt_regs *regs) | 2625 | void do_irq_tl1(struct pt_regs *regs) |
2585 | { | 2626 | { |
2627 | exception_enter(); | ||
2586 | dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); | 2628 | dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); |
2587 | die_if_kernel("TL1: IRQ Exception", regs); | 2629 | die_if_kernel("TL1: IRQ Exception", regs); |
2588 | } | 2630 | } |
2589 | 2631 | ||
2590 | void do_lddfmna_tl1(struct pt_regs *regs) | 2632 | void do_lddfmna_tl1(struct pt_regs *regs) |
2591 | { | 2633 | { |
2634 | exception_enter(); | ||
2592 | dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); | 2635 | dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); |
2593 | die_if_kernel("TL1: LDDF Exception", regs); | 2636 | die_if_kernel("TL1: LDDF Exception", regs); |
2594 | } | 2637 | } |
2595 | 2638 | ||
2596 | void do_stdfmna_tl1(struct pt_regs *regs) | 2639 | void do_stdfmna_tl1(struct pt_regs *regs) |
2597 | { | 2640 | { |
2641 | exception_enter(); | ||
2598 | dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); | 2642 | dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); |
2599 | die_if_kernel("TL1: STDF Exception", regs); | 2643 | die_if_kernel("TL1: STDF Exception", regs); |
2600 | } | 2644 | } |
2601 | 2645 | ||
2602 | void do_paw(struct pt_regs *regs) | 2646 | void do_paw(struct pt_regs *regs) |
2603 | { | 2647 | { |
2648 | exception_enter(); | ||
2604 | die_if_kernel("TL0: Phys Watchpoint Exception", regs); | 2649 | die_if_kernel("TL0: Phys Watchpoint Exception", regs); |
2605 | } | 2650 | } |
2606 | 2651 | ||
2607 | void do_paw_tl1(struct pt_regs *regs) | 2652 | void do_paw_tl1(struct pt_regs *regs) |
2608 | { | 2653 | { |
2654 | exception_enter(); | ||
2609 | dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); | 2655 | dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); |
2610 | die_if_kernel("TL1: Phys Watchpoint Exception", regs); | 2656 | die_if_kernel("TL1: Phys Watchpoint Exception", regs); |
2611 | } | 2657 | } |
2612 | 2658 | ||
2613 | void do_vaw(struct pt_regs *regs) | 2659 | void do_vaw(struct pt_regs *regs) |
2614 | { | 2660 | { |
2661 | exception_enter(); | ||
2615 | die_if_kernel("TL0: Virt Watchpoint Exception", regs); | 2662 | die_if_kernel("TL0: Virt Watchpoint Exception", regs); |
2616 | } | 2663 | } |
2617 | 2664 | ||
2618 | void do_vaw_tl1(struct pt_regs *regs) | 2665 | void do_vaw_tl1(struct pt_regs *regs) |
2619 | { | 2666 | { |
2667 | exception_enter(); | ||
2620 | dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); | 2668 | dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); |
2621 | die_if_kernel("TL1: Virt Watchpoint Exception", regs); | 2669 | die_if_kernel("TL1: Virt Watchpoint Exception", regs); |
2622 | } | 2670 | } |
2623 | 2671 | ||
2624 | void do_tof_tl1(struct pt_regs *regs) | 2672 | void do_tof_tl1(struct pt_regs *regs) |
2625 | { | 2673 | { |
2674 | exception_enter(); | ||
2626 | dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); | 2675 | dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); |
2627 | die_if_kernel("TL1: Tag Overflow Exception", regs); | 2676 | die_if_kernel("TL1: Tag Overflow Exception", regs); |
2628 | } | 2677 | } |
diff --git a/arch/sparc/kernel/unaligned_64.c b/arch/sparc/kernel/unaligned_64.c index 8201c25e7669..3c1a7cb31579 100644 --- a/arch/sparc/kernel/unaligned_64.c +++ b/arch/sparc/kernel/unaligned_64.c | |||
@@ -21,9 +21,12 @@ | |||
21 | #include <linux/bitops.h> | 21 | #include <linux/bitops.h> |
22 | #include <linux/perf_event.h> | 22 | #include <linux/perf_event.h> |
23 | #include <linux/ratelimit.h> | 23 | #include <linux/ratelimit.h> |
24 | #include <linux/context_tracking.h> | ||
24 | #include <asm/fpumacro.h> | 25 | #include <asm/fpumacro.h> |
25 | #include <asm/cacheflush.h> | 26 | #include <asm/cacheflush.h> |
26 | 27 | ||
28 | #include "entry.h" | ||
29 | |||
27 | enum direction { | 30 | enum direction { |
28 | load, /* ld, ldd, ldh, ldsh */ | 31 | load, /* ld, ldd, ldh, ldsh */ |
29 | store, /* st, std, sth, stsh */ | 32 | store, /* st, std, sth, stsh */ |
@@ -418,9 +421,6 @@ int handle_popc(u32 insn, struct pt_regs *regs) | |||
418 | 421 | ||
419 | extern void do_fpother(struct pt_regs *regs); | 422 | extern void do_fpother(struct pt_regs *regs); |
420 | extern void do_privact(struct pt_regs *regs); | 423 | extern void do_privact(struct pt_regs *regs); |
421 | extern void spitfire_data_access_exception(struct pt_regs *regs, | ||
422 | unsigned long sfsr, | ||
423 | unsigned long sfar); | ||
424 | extern void sun4v_data_access_exception(struct pt_regs *regs, | 424 | extern void sun4v_data_access_exception(struct pt_regs *regs, |
425 | unsigned long addr, | 425 | unsigned long addr, |
426 | unsigned long type_ctx); | 426 | unsigned long type_ctx); |
@@ -578,6 +578,7 @@ void handle_ld_nf(u32 insn, struct pt_regs *regs) | |||
578 | 578 | ||
579 | void handle_lddfmna(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr) | 579 | void handle_lddfmna(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr) |
580 | { | 580 | { |
581 | enum ctx_state prev_state = exception_enter(); | ||
581 | unsigned long pc = regs->tpc; | 582 | unsigned long pc = regs->tpc; |
582 | unsigned long tstate = regs->tstate; | 583 | unsigned long tstate = regs->tstate; |
583 | u32 insn; | 584 | u32 insn; |
@@ -632,13 +633,16 @@ daex: | |||
632 | sun4v_data_access_exception(regs, sfar, sfsr); | 633 | sun4v_data_access_exception(regs, sfar, sfsr); |
633 | else | 634 | else |
634 | spitfire_data_access_exception(regs, sfsr, sfar); | 635 | spitfire_data_access_exception(regs, sfsr, sfar); |
635 | return; | 636 | goto out; |
636 | } | 637 | } |
637 | advance(regs); | 638 | advance(regs); |
639 | out: | ||
640 | exception_exit(prev_state); | ||
638 | } | 641 | } |
639 | 642 | ||
640 | void handle_stdfmna(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr) | 643 | void handle_stdfmna(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr) |
641 | { | 644 | { |
645 | enum ctx_state prev_state = exception_enter(); | ||
642 | unsigned long pc = regs->tpc; | 646 | unsigned long pc = regs->tpc; |
643 | unsigned long tstate = regs->tstate; | 647 | unsigned long tstate = regs->tstate; |
644 | u32 insn; | 648 | u32 insn; |
@@ -680,7 +684,9 @@ daex: | |||
680 | sun4v_data_access_exception(regs, sfar, sfsr); | 684 | sun4v_data_access_exception(regs, sfar, sfsr); |
681 | else | 685 | else |
682 | spitfire_data_access_exception(regs, sfsr, sfar); | 686 | spitfire_data_access_exception(regs, sfsr, sfar); |
683 | return; | 687 | goto out; |
684 | } | 688 | } |
685 | advance(regs); | 689 | advance(regs); |
690 | out: | ||
691 | exception_exit(prev_state); | ||
686 | } | 692 | } |
diff --git a/arch/sparc/mm/fault_64.c b/arch/sparc/mm/fault_64.c index 2ebec263d685..69bb818fdd79 100644 --- a/arch/sparc/mm/fault_64.c +++ b/arch/sparc/mm/fault_64.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/kprobes.h> | 21 | #include <linux/kprobes.h> |
22 | #include <linux/kdebug.h> | 22 | #include <linux/kdebug.h> |
23 | #include <linux/percpu.h> | 23 | #include <linux/percpu.h> |
24 | #include <linux/context_tracking.h> | ||
24 | 25 | ||
25 | #include <asm/page.h> | 26 | #include <asm/page.h> |
26 | #include <asm/pgtable.h> | 27 | #include <asm/pgtable.h> |
@@ -272,6 +273,7 @@ static void noinline __kprobes bogus_32bit_fault_address(struct pt_regs *regs, | |||
272 | 273 | ||
273 | asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) | 274 | asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) |
274 | { | 275 | { |
276 | enum ctx_state prev_state = exception_enter(); | ||
275 | struct mm_struct *mm = current->mm; | 277 | struct mm_struct *mm = current->mm; |
276 | struct vm_area_struct *vma; | 278 | struct vm_area_struct *vma; |
277 | unsigned int insn = 0; | 279 | unsigned int insn = 0; |
@@ -282,7 +284,7 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) | |||
282 | fault_code = get_thread_fault_code(); | 284 | fault_code = get_thread_fault_code(); |
283 | 285 | ||
284 | if (notify_page_fault(regs)) | 286 | if (notify_page_fault(regs)) |
285 | return; | 287 | goto exit_exception; |
286 | 288 | ||
287 | si_code = SEGV_MAPERR; | 289 | si_code = SEGV_MAPERR; |
288 | address = current_thread_info()->fault_address; | 290 | address = current_thread_info()->fault_address; |
@@ -313,7 +315,7 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) | |||
313 | /* Valid, no problems... */ | 315 | /* Valid, no problems... */ |
314 | } else { | 316 | } else { |
315 | bad_kernel_pc(regs, address); | 317 | bad_kernel_pc(regs, address); |
316 | return; | 318 | goto exit_exception; |
317 | } | 319 | } |
318 | } else | 320 | } else |
319 | flags |= FAULT_FLAG_USER; | 321 | flags |= FAULT_FLAG_USER; |
@@ -430,7 +432,7 @@ good_area: | |||
430 | fault = handle_mm_fault(mm, vma, address, flags); | 432 | fault = handle_mm_fault(mm, vma, address, flags); |
431 | 433 | ||
432 | if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) | 434 | if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) |
433 | return; | 435 | goto exit_exception; |
434 | 436 | ||
435 | if (unlikely(fault & VM_FAULT_ERROR)) { | 437 | if (unlikely(fault & VM_FAULT_ERROR)) { |
436 | if (fault & VM_FAULT_OOM) | 438 | if (fault & VM_FAULT_OOM) |
@@ -482,6 +484,8 @@ good_area: | |||
482 | 484 | ||
483 | } | 485 | } |
484 | #endif | 486 | #endif |
487 | exit_exception: | ||
488 | exception_exit(prev_state); | ||
485 | return; | 489 | return; |
486 | 490 | ||
487 | /* | 491 | /* |
@@ -494,7 +498,7 @@ bad_area: | |||
494 | 498 | ||
495 | handle_kernel_fault: | 499 | handle_kernel_fault: |
496 | do_kernel_fault(regs, si_code, fault_code, insn, address); | 500 | do_kernel_fault(regs, si_code, fault_code, insn, address); |
497 | return; | 501 | goto exit_exception; |
498 | 502 | ||
499 | /* | 503 | /* |
500 | * We ran out of memory, or some other thing happened to us that made | 504 | * We ran out of memory, or some other thing happened to us that made |
@@ -505,7 +509,7 @@ out_of_memory: | |||
505 | up_read(&mm->mmap_sem); | 509 | up_read(&mm->mmap_sem); |
506 | if (!(regs->tstate & TSTATE_PRIV)) { | 510 | if (!(regs->tstate & TSTATE_PRIV)) { |
507 | pagefault_out_of_memory(); | 511 | pagefault_out_of_memory(); |
508 | return; | 512 | goto exit_exception; |
509 | } | 513 | } |
510 | goto handle_kernel_fault; | 514 | goto handle_kernel_fault; |
511 | 515 | ||