aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKirill Tkhai <tkhai@yandex.ru>2013-09-14 08:02:11 -0400
committerDavid S. Miller <davem@davemloft.net>2013-11-14 17:57:21 -0500
commit812cb83a56a908729c453a7db3fb2c262119bc9d (patch)
tree3fdf3df047276db7de85558ff6caff006c3b1cc4
parent1a36265bf7d7e16b35fab5ae7f2f5d499bd0c14d (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>
-rw-r--r--arch/sparc/Kconfig1
-rw-r--r--arch/sparc/include/asm/thread_info_64.h3
-rw-r--r--arch/sparc/kernel/entry.h1
-rw-r--r--arch/sparc/kernel/kgdb_64.c5
-rw-r--r--arch/sparc/kernel/kprobes.c7
-rw-r--r--arch/sparc/kernel/process_64.c2
-rw-r--r--arch/sparc/kernel/ptrace_64.c10
-rw-r--r--arch/sparc/kernel/rtrap_64.S8
-rw-r--r--arch/sparc/kernel/signal_64.c13
-rw-r--r--arch/sparc/kernel/sys_sparc_64.c3
-rw-r--r--arch/sparc/kernel/syscalls.S8
-rw-r--r--arch/sparc/kernel/traps_64.c85
-rw-r--r--arch/sparc/kernel/unaligned_64.c16
-rw-r--r--arch/sparc/mm/fault_64.c14
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
89extern void bad_trap_tl1(struct pt_regs *regs, long lvl); 89extern void bad_trap_tl1(struct pt_regs *regs, long lvl);
90 90
91extern void do_fpe_common(struct pt_regs *regs);
92extern void do_fpieee(struct pt_regs *regs); 91extern void do_fpieee(struct pt_regs *regs);
93extern void do_fpother(struct pt_regs *regs); 92extern void do_fpother(struct pt_regs *regs);
94extern void do_tof(struct pt_regs *regs); 93extern 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
160asmlinkage void kgdb_trap(unsigned long trap_level, struct pt_regs *regs) 160asmlinkage 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);
175out:
176 exception_exit(prev_state);
174} 177}
175 178
176int kgdb_arch_init(void) 179int 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,
418asmlinkage void __kprobes kprobe_trap(unsigned long trap_level, 419asmlinkage 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);
439out:
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
558barf: 559barf:
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
1087asmlinkage void syscall_trace_leave(struct pt_regs *regs) 1091asmlinkage 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 134out:
135 exception_exit(prev_state);
133 return; 136 return;
134do_sigsegv: 137do_sigsegv:
135 force_sig(SIGSEGV, current); 138 force_sig(SIGSEGV, current);
139 goto out;
136} 140}
137 141
138asmlinkage void sparc64_get_context(struct pt_regs *regs) 142asmlinkage 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 228out:
229 exception_exit(prev_state);
224 return; 230 return;
225do_sigsegv: 231do_sigsegv:
226 force_sig(SIGSEGV, current); 232 force_sig(SIGSEGV, current);
233 goto out;
227} 234}
228 235
229struct rt_signal_frame { 236struct rt_signal_frame {
@@ -528,11 +535,13 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
528 535
529void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, unsigned long thread_info_flags) 536void 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
497asmlinkage void sparc_breakpoint(struct pt_regs *regs) 498asmlinkage 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
519extern void check_pending(int signum); 522extern 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
541: ldx [%g6 + TI_FLAGS], %l5 541: 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
1905: call %l7 ! CTI Group brk forced 1905: 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
2132: call %l7 ! CTI Group brk forced 2132: 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
2292: 2292:
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
187void spitfire_insn_access_exception(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar) 188void 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);
212out:
213 exception_exit(prev_state);
210} 214}
211 215
212void spitfire_insn_access_exception_tl1(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar) 216void 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
261void spitfire_data_access_exception(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar) 265void 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);
302out:
303 exception_exit(prev_state);
297} 304}
298 305
299void spitfire_data_access_exception_tl1(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar) 306void 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 */
1995void sun4v_resum_error(struct pt_regs *regs, unsigned long offset) 2002void 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);
2039out:
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
2155void do_fpe_common(struct pt_regs *regs) 2165static 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
2189void do_fpieee(struct pt_regs *regs) 2199void 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);
2208out:
2209 exception_exit(prev_state);
2196} 2210}
2197 2211
2198extern int do_mathemu(struct pt_regs *, struct fpustate *, bool); 2212extern int do_mathemu(struct pt_regs *, struct fpustate *, bool);
2199 2213
2200void do_fpother(struct pt_regs *regs) 2214void 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);
2233out:
2234 exception_exit(prev_state);
2218} 2235}
2219 2236
2220void do_tof(struct pt_regs *regs) 2237void 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);
2258out:
2259 exception_exit(prev_state);
2240} 2260}
2241 2261
2242void do_div0(struct pt_regs *regs) 2262void 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);
2283out:
2284 exception_exit(prev_state);
2262} 2285}
2263 2286
2264static void instruction_dump(unsigned int *pc) 2287static void instruction_dump(unsigned int *pc)
@@ -2415,6 +2438,7 @@ extern int handle_ldf_stq(u32 insn, struct pt_regs *regs);
2415 2438
2416void do_illegal_instruction(struct pt_regs *regs) 2439void 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);
2485out:
2486 exception_exit(prev_state);
2461} 2487}
2462 2488
2463extern void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn); 2489extern void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn);
2464 2490
2465void mem_address_unaligned(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr) 2491void 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);
2510out:
2511 exception_exit(prev_state);
2483} 2512}
2484 2513
2485void sun4v_do_mna(struct pt_regs *regs, unsigned long addr, unsigned long type_ctx) 2514void 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
2505void do_privop(struct pt_regs *regs) 2534void 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);
2553out:
2554 exception_exit(prev_state);
2523} 2555}
2524 2556
2525void do_privact(struct pt_regs *regs) 2557void 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... */
2531void do_cee(struct pt_regs *regs) 2563void 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
2536void do_cee_tl1(struct pt_regs *regs) 2569void 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
2542void do_dae_tl1(struct pt_regs *regs) 2576void 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
2548void do_iae_tl1(struct pt_regs *regs) 2583void 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
2554void do_div0_tl1(struct pt_regs *regs) 2590void 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
2560void do_fpdis_tl1(struct pt_regs *regs) 2597void 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
2566void do_fpieee_tl1(struct pt_regs *regs) 2604void 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
2572void do_fpother_tl1(struct pt_regs *regs) 2611void 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
2578void do_ill_tl1(struct pt_regs *regs) 2618void 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
2584void do_irq_tl1(struct pt_regs *regs) 2625void 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
2590void do_lddfmna_tl1(struct pt_regs *regs) 2632void 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
2596void do_stdfmna_tl1(struct pt_regs *regs) 2639void 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
2602void do_paw(struct pt_regs *regs) 2646void 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
2607void do_paw_tl1(struct pt_regs *regs) 2652void 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
2613void do_vaw(struct pt_regs *regs) 2659void 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
2618void do_vaw_tl1(struct pt_regs *regs) 2665void 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
2624void do_tof_tl1(struct pt_regs *regs) 2672void 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
27enum direction { 30enum 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
419extern void do_fpother(struct pt_regs *regs); 422extern void do_fpother(struct pt_regs *regs);
420extern void do_privact(struct pt_regs *regs); 423extern void do_privact(struct pt_regs *regs);
421extern void spitfire_data_access_exception(struct pt_regs *regs,
422 unsigned long sfsr,
423 unsigned long sfar);
424extern void sun4v_data_access_exception(struct pt_regs *regs, 424extern 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
579void handle_lddfmna(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr) 579void 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);
639out:
640 exception_exit(prev_state);
638} 641}
639 642
640void handle_stdfmna(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr) 643void 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);
690out:
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
273asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) 274asmlinkage 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
487exit_exception:
488 exception_exit(prev_state);
485 return; 489 return;
486 490
487 /* 491 /*
@@ -494,7 +498,7 @@ bad_area:
494 498
495handle_kernel_fault: 499handle_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