diff options
author | Chris Metcalf <cmetcalf@ezchip.com> | 2015-03-23 14:23:58 -0400 |
---|---|---|
committer | Chris Metcalf <cmetcalf@ezchip.com> | 2015-04-17 14:01:10 -0400 |
commit | 49e4e15619cd7cd9fc275d460fae2a95c1337fcc (patch) | |
tree | 700e24bb8f72a7662e7d4ae26d847e908d08de92 /arch/tile | |
parent | b340c656af6317e28b466996a72cca019d97b42d (diff) |
tile: support CONTEXT_TRACKING and thus NOHZ_FULL
Add the TIF_NOHZ flag appropriately.
Add call to user_exit() on entry to do_work_pending() and on entry
to syscalls via do_syscall_trace_enter(), and also the top of
do_syscall_trace_exit() just because it's done in x86.
Add call to user_enter() at the bottom of do_work_pending() once we
have no more work to do before returning to userspace.
Wrap all the trap code in exception_enter() / exception_exit().
Signed-off-by: Chris Metcalf <cmetcalf@ezchip.com>
Acked-by: Frederic Weisbecker <fweisbec@gmail.com>
Diffstat (limited to 'arch/tile')
-rw-r--r-- | arch/tile/Kconfig | 1 | ||||
-rw-r--r-- | arch/tile/include/asm/thread_info.h | 9 | ||||
-rw-r--r-- | arch/tile/kernel/process.c | 12 | ||||
-rw-r--r-- | arch/tile/kernel/ptrace.c | 22 | ||||
-rw-r--r-- | arch/tile/kernel/single_step.c | 3 | ||||
-rw-r--r-- | arch/tile/kernel/traps.c | 16 | ||||
-rw-r--r-- | arch/tile/kernel/unaligned.c | 22 | ||||
-rw-r--r-- | arch/tile/mm/fault.c | 10 |
8 files changed, 67 insertions, 28 deletions
diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig index 7cca41842a9e..c3a31f8bb09c 100644 --- a/arch/tile/Kconfig +++ b/arch/tile/Kconfig | |||
@@ -27,6 +27,7 @@ config TILE | |||
27 | select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE | 27 | select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE |
28 | select HAVE_DEBUG_STACKOVERFLOW | 28 | select HAVE_DEBUG_STACKOVERFLOW |
29 | select ARCH_WANT_FRAME_POINTERS | 29 | select ARCH_WANT_FRAME_POINTERS |
30 | select HAVE_CONTEXT_TRACKING | ||
30 | 31 | ||
31 | # FIXME: investigate whether we need/want these options. | 32 | # FIXME: investigate whether we need/want these options. |
32 | # select HAVE_IOREMAP_PROT | 33 | # select HAVE_IOREMAP_PROT |
diff --git a/arch/tile/include/asm/thread_info.h b/arch/tile/include/asm/thread_info.h index 96c14c1430d8..6130a3db505b 100644 --- a/arch/tile/include/asm/thread_info.h +++ b/arch/tile/include/asm/thread_info.h | |||
@@ -126,6 +126,7 @@ extern void _cpu_idle(void); | |||
126 | #define TIF_NOTIFY_RESUME 8 /* callback before returning to user */ | 126 | #define TIF_NOTIFY_RESUME 8 /* callback before returning to user */ |
127 | #define TIF_SYSCALL_TRACEPOINT 9 /* syscall tracepoint instrumentation */ | 127 | #define TIF_SYSCALL_TRACEPOINT 9 /* syscall tracepoint instrumentation */ |
128 | #define TIF_POLLING_NRFLAG 10 /* idle is polling for TIF_NEED_RESCHED */ | 128 | #define TIF_POLLING_NRFLAG 10 /* idle is polling for TIF_NEED_RESCHED */ |
129 | #define TIF_NOHZ 11 /* in adaptive nohz mode */ | ||
129 | 130 | ||
130 | #define _TIF_SIGPENDING (1<<TIF_SIGPENDING) | 131 | #define _TIF_SIGPENDING (1<<TIF_SIGPENDING) |
131 | #define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED) | 132 | #define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED) |
@@ -138,14 +139,16 @@ extern void _cpu_idle(void); | |||
138 | #define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME) | 139 | #define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME) |
139 | #define _TIF_SYSCALL_TRACEPOINT (1<<TIF_SYSCALL_TRACEPOINT) | 140 | #define _TIF_SYSCALL_TRACEPOINT (1<<TIF_SYSCALL_TRACEPOINT) |
140 | #define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG) | 141 | #define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG) |
142 | #define _TIF_NOHZ (1<<TIF_NOHZ) | ||
141 | 143 | ||
142 | /* Work to do on any return to user space. */ | 144 | /* Work to do on any return to user space. */ |
143 | #define _TIF_ALLWORK_MASK \ | 145 | #define _TIF_ALLWORK_MASK \ |
144 | (_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_SINGLESTEP|\ | 146 | (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_SINGLESTEP | \ |
145 | _TIF_ASYNC_TLB|_TIF_NOTIFY_RESUME) | 147 | _TIF_ASYNC_TLB | _TIF_NOTIFY_RESUME | _TIF_NOHZ) |
146 | 148 | ||
147 | /* Work to do at syscall entry. */ | 149 | /* Work to do at syscall entry. */ |
148 | #define _TIF_SYSCALL_ENTRY_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_TRACEPOINT) | 150 | #define _TIF_SYSCALL_ENTRY_WORK \ |
151 | (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_TRACEPOINT | _TIF_NOHZ) | ||
149 | 152 | ||
150 | /* Work to do at syscall exit. */ | 153 | /* Work to do at syscall exit. */ |
151 | #define _TIF_SYSCALL_EXIT_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_TRACEPOINT) | 154 | #define _TIF_SYSCALL_EXIT_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_TRACEPOINT) |
diff --git a/arch/tile/kernel/process.c b/arch/tile/kernel/process.c index 48e5773dd0b7..b403c2e3e263 100644 --- a/arch/tile/kernel/process.c +++ b/arch/tile/kernel/process.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
28 | #include <linux/tracehook.h> | 28 | #include <linux/tracehook.h> |
29 | #include <linux/signal.h> | 29 | #include <linux/signal.h> |
30 | #include <linux/context_tracking.h> | ||
30 | #include <asm/stack.h> | 31 | #include <asm/stack.h> |
31 | #include <asm/switch_to.h> | 32 | #include <asm/switch_to.h> |
32 | #include <asm/homecache.h> | 33 | #include <asm/homecache.h> |
@@ -474,6 +475,8 @@ int do_work_pending(struct pt_regs *regs, u32 thread_info_flags) | |||
474 | if (!user_mode(regs)) | 475 | if (!user_mode(regs)) |
475 | return 0; | 476 | return 0; |
476 | 477 | ||
478 | user_exit(); | ||
479 | |||
477 | /* Enable interrupts; they are disabled again on return to caller. */ | 480 | /* Enable interrupts; they are disabled again on return to caller. */ |
478 | local_irq_enable(); | 481 | local_irq_enable(); |
479 | 482 | ||
@@ -496,11 +499,12 @@ int do_work_pending(struct pt_regs *regs, u32 thread_info_flags) | |||
496 | tracehook_notify_resume(regs); | 499 | tracehook_notify_resume(regs); |
497 | return 1; | 500 | return 1; |
498 | } | 501 | } |
499 | if (thread_info_flags & _TIF_SINGLESTEP) { | 502 | if (thread_info_flags & _TIF_SINGLESTEP) |
500 | single_step_once(regs); | 503 | single_step_once(regs); |
501 | return 0; | 504 | |
502 | } | 505 | user_enter(); |
503 | panic("work_pending: bad flags %#x\n", thread_info_flags); | 506 | |
507 | return 0; | ||
504 | } | 508 | } |
505 | 509 | ||
506 | unsigned long get_wchan(struct task_struct *p) | 510 | unsigned long get_wchan(struct task_struct *p) |
diff --git a/arch/tile/kernel/ptrace.c b/arch/tile/kernel/ptrace.c index de98c6ddf136..f84eed8243da 100644 --- a/arch/tile/kernel/ptrace.c +++ b/arch/tile/kernel/ptrace.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/regset.h> | 22 | #include <linux/regset.h> |
23 | #include <linux/elf.h> | 23 | #include <linux/elf.h> |
24 | #include <linux/tracehook.h> | 24 | #include <linux/tracehook.h> |
25 | #include <linux/context_tracking.h> | ||
25 | #include <asm/traps.h> | 26 | #include <asm/traps.h> |
26 | #include <arch/chip.h> | 27 | #include <arch/chip.h> |
27 | 28 | ||
@@ -252,12 +253,21 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, | |||
252 | 253 | ||
253 | int do_syscall_trace_enter(struct pt_regs *regs) | 254 | int do_syscall_trace_enter(struct pt_regs *regs) |
254 | { | 255 | { |
255 | if (test_thread_flag(TIF_SYSCALL_TRACE)) { | 256 | u32 work = ACCESS_ONCE(current_thread_info()->flags); |
257 | |||
258 | /* | ||
259 | * If TIF_NOHZ is set, we are required to call user_exit() before | ||
260 | * doing anything that could touch RCU. | ||
261 | */ | ||
262 | if (work & _TIF_NOHZ) | ||
263 | user_exit(); | ||
264 | |||
265 | if (work & _TIF_SYSCALL_TRACE) { | ||
256 | if (tracehook_report_syscall_entry(regs)) | 266 | if (tracehook_report_syscall_entry(regs)) |
257 | regs->regs[TREG_SYSCALL_NR] = -1; | 267 | regs->regs[TREG_SYSCALL_NR] = -1; |
258 | } | 268 | } |
259 | 269 | ||
260 | if (test_thread_flag(TIF_SYSCALL_TRACEPOINT)) | 270 | if (work & _TIF_SYSCALL_TRACEPOINT) |
261 | trace_sys_enter(regs, regs->regs[TREG_SYSCALL_NR]); | 271 | trace_sys_enter(regs, regs->regs[TREG_SYSCALL_NR]); |
262 | 272 | ||
263 | return regs->regs[TREG_SYSCALL_NR]; | 273 | return regs->regs[TREG_SYSCALL_NR]; |
@@ -268,6 +278,12 @@ void do_syscall_trace_exit(struct pt_regs *regs) | |||
268 | long errno; | 278 | long errno; |
269 | 279 | ||
270 | /* | 280 | /* |
281 | * We may come here right after calling schedule_user() | ||
282 | * in which case we can be in RCU user mode. | ||
283 | */ | ||
284 | user_exit(); | ||
285 | |||
286 | /* | ||
271 | * The standard tile calling convention returns the value (or negative | 287 | * The standard tile calling convention returns the value (or negative |
272 | * errno) in r0, and zero (or positive errno) in r1. | 288 | * errno) in r0, and zero (or positive errno) in r1. |
273 | * It saves a couple of cycles on the hot path to do this work in | 289 | * It saves a couple of cycles on the hot path to do this work in |
@@ -303,5 +319,7 @@ void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs) | |||
303 | /* Handle synthetic interrupt delivered only by the simulator. */ | 319 | /* Handle synthetic interrupt delivered only by the simulator. */ |
304 | void __kprobes do_breakpoint(struct pt_regs* regs, int fault_num) | 320 | void __kprobes do_breakpoint(struct pt_regs* regs, int fault_num) |
305 | { | 321 | { |
322 | enum ctx_state prev_state = exception_enter(); | ||
306 | send_sigtrap(current, regs); | 323 | send_sigtrap(current, regs); |
324 | exception_exit(prev_state); | ||
307 | } | 325 | } |
diff --git a/arch/tile/kernel/single_step.c b/arch/tile/kernel/single_step.c index 862973074bf9..53f7b9def07b 100644 --- a/arch/tile/kernel/single_step.c +++ b/arch/tile/kernel/single_step.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/types.h> | 23 | #include <linux/types.h> |
24 | #include <linux/err.h> | 24 | #include <linux/err.h> |
25 | #include <linux/prctl.h> | 25 | #include <linux/prctl.h> |
26 | #include <linux/context_tracking.h> | ||
26 | #include <asm/cacheflush.h> | 27 | #include <asm/cacheflush.h> |
27 | #include <asm/traps.h> | 28 | #include <asm/traps.h> |
28 | #include <asm/uaccess.h> | 29 | #include <asm/uaccess.h> |
@@ -738,6 +739,7 @@ static DEFINE_PER_CPU(unsigned long, ss_saved_pc); | |||
738 | 739 | ||
739 | void gx_singlestep_handle(struct pt_regs *regs, int fault_num) | 740 | void gx_singlestep_handle(struct pt_regs *regs, int fault_num) |
740 | { | 741 | { |
742 | enum ctx_state prev_state = exception_enter(); | ||
741 | unsigned long *ss_pc = this_cpu_ptr(&ss_saved_pc); | 743 | unsigned long *ss_pc = this_cpu_ptr(&ss_saved_pc); |
742 | struct thread_info *info = (void *)current_thread_info(); | 744 | struct thread_info *info = (void *)current_thread_info(); |
743 | int is_single_step = test_ti_thread_flag(info, TIF_SINGLESTEP); | 745 | int is_single_step = test_ti_thread_flag(info, TIF_SINGLESTEP); |
@@ -754,6 +756,7 @@ void gx_singlestep_handle(struct pt_regs *regs, int fault_num) | |||
754 | __insn_mtspr(SPR_SINGLE_STEP_CONTROL_K, control); | 756 | __insn_mtspr(SPR_SINGLE_STEP_CONTROL_K, control); |
755 | send_sigtrap(current, regs); | 757 | send_sigtrap(current, regs); |
756 | } | 758 | } |
759 | exception_exit(prev_state); | ||
757 | } | 760 | } |
758 | 761 | ||
759 | 762 | ||
diff --git a/arch/tile/kernel/traps.c b/arch/tile/kernel/traps.c index bf841ca517bb..312fc134c1cb 100644 --- a/arch/tile/kernel/traps.c +++ b/arch/tile/kernel/traps.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/reboot.h> | 20 | #include <linux/reboot.h> |
21 | #include <linux/uaccess.h> | 21 | #include <linux/uaccess.h> |
22 | #include <linux/ptrace.h> | 22 | #include <linux/ptrace.h> |
23 | #include <linux/context_tracking.h> | ||
23 | #include <asm/stack.h> | 24 | #include <asm/stack.h> |
24 | #include <asm/traps.h> | 25 | #include <asm/traps.h> |
25 | #include <asm/setup.h> | 26 | #include <asm/setup.h> |
@@ -253,6 +254,7 @@ static int do_bpt(struct pt_regs *regs) | |||
253 | void __kprobes do_trap(struct pt_regs *regs, int fault_num, | 254 | void __kprobes do_trap(struct pt_regs *regs, int fault_num, |
254 | unsigned long reason) | 255 | unsigned long reason) |
255 | { | 256 | { |
257 | enum ctx_state prev_state = exception_enter(); | ||
256 | siginfo_t info = { 0 }; | 258 | siginfo_t info = { 0 }; |
257 | int signo, code; | 259 | int signo, code; |
258 | unsigned long address = 0; | 260 | unsigned long address = 0; |
@@ -261,7 +263,7 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num, | |||
261 | 263 | ||
262 | /* Handle breakpoints, etc. */ | 264 | /* Handle breakpoints, etc. */ |
263 | if (is_kernel && fault_num == INT_ILL && do_bpt(regs)) | 265 | if (is_kernel && fault_num == INT_ILL && do_bpt(regs)) |
264 | return; | 266 | goto done; |
265 | 267 | ||
266 | /* Re-enable interrupts, if they were previously enabled. */ | 268 | /* Re-enable interrupts, if they were previously enabled. */ |
267 | if (!(regs->flags & PT_FLAGS_DISABLE_IRQ)) | 269 | if (!(regs->flags & PT_FLAGS_DISABLE_IRQ)) |
@@ -275,7 +277,7 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num, | |||
275 | const char *name; | 277 | const char *name; |
276 | char buf[100]; | 278 | char buf[100]; |
277 | if (fixup_exception(regs)) /* ILL_TRANS or UNALIGN_DATA */ | 279 | if (fixup_exception(regs)) /* ILL_TRANS or UNALIGN_DATA */ |
278 | return; | 280 | goto done; |
279 | if (fault_num >= 0 && | 281 | if (fault_num >= 0 && |
280 | fault_num < ARRAY_SIZE(int_name) && | 282 | fault_num < ARRAY_SIZE(int_name) && |
281 | int_name[fault_num] != NULL) | 283 | int_name[fault_num] != NULL) |
@@ -294,7 +296,6 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num, | |||
294 | fault_num, name, regs->pc, buf); | 296 | fault_num, name, regs->pc, buf); |
295 | show_regs(regs); | 297 | show_regs(regs); |
296 | do_exit(SIGKILL); /* FIXME: implement i386 die() */ | 298 | do_exit(SIGKILL); /* FIXME: implement i386 die() */ |
297 | return; | ||
298 | } | 299 | } |
299 | 300 | ||
300 | switch (fault_num) { | 301 | switch (fault_num) { |
@@ -308,7 +309,6 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num, | |||
308 | pr_err("Unreadable instruction for INT_ILL: %#lx\n", | 309 | pr_err("Unreadable instruction for INT_ILL: %#lx\n", |
309 | regs->pc); | 310 | regs->pc); |
310 | do_exit(SIGKILL); | 311 | do_exit(SIGKILL); |
311 | return; | ||
312 | } | 312 | } |
313 | if (!special_ill(instr, &signo, &code)) { | 313 | if (!special_ill(instr, &signo, &code)) { |
314 | signo = SIGILL; | 314 | signo = SIGILL; |
@@ -319,7 +319,7 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num, | |||
319 | case INT_GPV: | 319 | case INT_GPV: |
320 | #if CHIP_HAS_TILE_DMA() | 320 | #if CHIP_HAS_TILE_DMA() |
321 | if (retry_gpv(reason)) | 321 | if (retry_gpv(reason)) |
322 | return; | 322 | goto done; |
323 | #endif | 323 | #endif |
324 | /*FALLTHROUGH*/ | 324 | /*FALLTHROUGH*/ |
325 | case INT_UDN_ACCESS: | 325 | case INT_UDN_ACCESS: |
@@ -346,7 +346,7 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num, | |||
346 | if (!state || | 346 | if (!state || |
347 | (void __user *)(regs->pc) != state->buffer) { | 347 | (void __user *)(regs->pc) != state->buffer) { |
348 | single_step_once(regs); | 348 | single_step_once(regs); |
349 | return; | 349 | goto done; |
350 | } | 350 | } |
351 | } | 351 | } |
352 | #endif | 352 | #endif |
@@ -380,7 +380,6 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num, | |||
380 | #endif | 380 | #endif |
381 | default: | 381 | default: |
382 | panic("Unexpected do_trap interrupt number %d", fault_num); | 382 | panic("Unexpected do_trap interrupt number %d", fault_num); |
383 | return; | ||
384 | } | 383 | } |
385 | 384 | ||
386 | info.si_signo = signo; | 385 | info.si_signo = signo; |
@@ -391,6 +390,9 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num, | |||
391 | if (signo != SIGTRAP) | 390 | if (signo != SIGTRAP) |
392 | trace_unhandled_signal("trap", regs, address, signo); | 391 | trace_unhandled_signal("trap", regs, address, signo); |
393 | force_sig_info(signo, &info, current); | 392 | force_sig_info(signo, &info, current); |
393 | |||
394 | done: | ||
395 | exception_exit(prev_state); | ||
394 | } | 396 | } |
395 | 397 | ||
396 | void kernel_double_fault(int dummy, ulong pc, ulong lr, ulong sp, ulong r52) | 398 | void kernel_double_fault(int dummy, ulong pc, ulong lr, ulong sp, ulong r52) |
diff --git a/arch/tile/kernel/unaligned.c b/arch/tile/kernel/unaligned.c index 7d9a83be0aca..d075f92ccee0 100644 --- a/arch/tile/kernel/unaligned.c +++ b/arch/tile/kernel/unaligned.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | #include <linux/compat.h> | 26 | #include <linux/compat.h> |
27 | #include <linux/prctl.h> | 27 | #include <linux/prctl.h> |
28 | #include <linux/context_tracking.h> | ||
28 | #include <asm/cacheflush.h> | 29 | #include <asm/cacheflush.h> |
29 | #include <asm/traps.h> | 30 | #include <asm/traps.h> |
30 | #include <asm/uaccess.h> | 31 | #include <asm/uaccess.h> |
@@ -1448,6 +1449,7 @@ void jit_bundle_gen(struct pt_regs *regs, tilegx_bundle_bits bundle, | |||
1448 | 1449 | ||
1449 | void do_unaligned(struct pt_regs *regs, int vecnum) | 1450 | void do_unaligned(struct pt_regs *regs, int vecnum) |
1450 | { | 1451 | { |
1452 | enum ctx_state prev_state = exception_enter(); | ||
1451 | tilegx_bundle_bits __user *pc; | 1453 | tilegx_bundle_bits __user *pc; |
1452 | tilegx_bundle_bits bundle; | 1454 | tilegx_bundle_bits bundle; |
1453 | struct thread_info *info = current_thread_info(); | 1455 | struct thread_info *info = current_thread_info(); |
@@ -1487,12 +1489,11 @@ void do_unaligned(struct pt_regs *regs, int vecnum) | |||
1487 | (int)unaligned_fixup, | 1489 | (int)unaligned_fixup, |
1488 | (unsigned long long)regs->ex1, | 1490 | (unsigned long long)regs->ex1, |
1489 | (unsigned long long)regs->pc); | 1491 | (unsigned long long)regs->pc); |
1490 | return; | 1492 | } else { |
1493 | /* Not fixable. Go panic. */ | ||
1494 | panic("Unalign exception in Kernel. pc=%lx", | ||
1495 | regs->pc); | ||
1491 | } | 1496 | } |
1492 | /* Not fixable. Go panic. */ | ||
1493 | panic("Unalign exception in Kernel. pc=%lx", | ||
1494 | regs->pc); | ||
1495 | return; | ||
1496 | } else { | 1497 | } else { |
1497 | /* | 1498 | /* |
1498 | * Try to fix the exception. If we can't, panic the | 1499 | * Try to fix the exception. If we can't, panic the |
@@ -1501,8 +1502,8 @@ void do_unaligned(struct pt_regs *regs, int vecnum) | |||
1501 | bundle = GX_INSN_BSWAP( | 1502 | bundle = GX_INSN_BSWAP( |
1502 | *((tilegx_bundle_bits *)(regs->pc))); | 1503 | *((tilegx_bundle_bits *)(regs->pc))); |
1503 | jit_bundle_gen(regs, bundle, align_ctl); | 1504 | jit_bundle_gen(regs, bundle, align_ctl); |
1504 | return; | ||
1505 | } | 1505 | } |
1506 | goto done; | ||
1506 | } | 1507 | } |
1507 | 1508 | ||
1508 | /* | 1509 | /* |
@@ -1526,7 +1527,7 @@ void do_unaligned(struct pt_regs *regs, int vecnum) | |||
1526 | 1527 | ||
1527 | trace_unhandled_signal("unaligned fixup trap", regs, 0, SIGBUS); | 1528 | trace_unhandled_signal("unaligned fixup trap", regs, 0, SIGBUS); |
1528 | force_sig_info(info.si_signo, &info, current); | 1529 | force_sig_info(info.si_signo, &info, current); |
1529 | return; | 1530 | goto done; |
1530 | } | 1531 | } |
1531 | 1532 | ||
1532 | 1533 | ||
@@ -1543,7 +1544,7 @@ void do_unaligned(struct pt_regs *regs, int vecnum) | |||
1543 | trace_unhandled_signal("segfault in unalign fixup", regs, | 1544 | trace_unhandled_signal("segfault in unalign fixup", regs, |
1544 | (unsigned long)info.si_addr, SIGSEGV); | 1545 | (unsigned long)info.si_addr, SIGSEGV); |
1545 | force_sig_info(info.si_signo, &info, current); | 1546 | force_sig_info(info.si_signo, &info, current); |
1546 | return; | 1547 | goto done; |
1547 | } | 1548 | } |
1548 | 1549 | ||
1549 | if (!info->unalign_jit_base) { | 1550 | if (!info->unalign_jit_base) { |
@@ -1578,7 +1579,7 @@ void do_unaligned(struct pt_regs *regs, int vecnum) | |||
1578 | 1579 | ||
1579 | if (IS_ERR((void __force *)user_page)) { | 1580 | if (IS_ERR((void __force *)user_page)) { |
1580 | pr_err("Out of kernel pages trying do_mmap\n"); | 1581 | pr_err("Out of kernel pages trying do_mmap\n"); |
1581 | return; | 1582 | goto done; |
1582 | } | 1583 | } |
1583 | 1584 | ||
1584 | /* Save the address in the thread_info struct */ | 1585 | /* Save the address in the thread_info struct */ |
@@ -1591,6 +1592,9 @@ void do_unaligned(struct pt_regs *regs, int vecnum) | |||
1591 | 1592 | ||
1592 | /* Generate unalign JIT */ | 1593 | /* Generate unalign JIT */ |
1593 | jit_bundle_gen(regs, GX_INSN_BSWAP(bundle), align_ctl); | 1594 | jit_bundle_gen(regs, GX_INSN_BSWAP(bundle), align_ctl); |
1595 | |||
1596 | done: | ||
1597 | exception_exit(prev_state); | ||
1594 | } | 1598 | } |
1595 | 1599 | ||
1596 | #endif /* __tilegx__ */ | 1600 | #endif /* __tilegx__ */ |
diff --git a/arch/tile/mm/fault.c b/arch/tile/mm/fault.c index 0f61a73534e6..e83cc999da02 100644 --- a/arch/tile/mm/fault.c +++ b/arch/tile/mm/fault.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/syscalls.h> | 35 | #include <linux/syscalls.h> |
36 | #include <linux/uaccess.h> | 36 | #include <linux/uaccess.h> |
37 | #include <linux/kdebug.h> | 37 | #include <linux/kdebug.h> |
38 | #include <linux/context_tracking.h> | ||
38 | 39 | ||
39 | #include <asm/pgalloc.h> | 40 | #include <asm/pgalloc.h> |
40 | #include <asm/sections.h> | 41 | #include <asm/sections.h> |
@@ -702,6 +703,7 @@ void do_page_fault(struct pt_regs *regs, int fault_num, | |||
702 | unsigned long address, unsigned long write) | 703 | unsigned long address, unsigned long write) |
703 | { | 704 | { |
704 | int is_page_fault; | 705 | int is_page_fault; |
706 | enum ctx_state prev_state = exception_enter(); | ||
705 | 707 | ||
706 | #ifdef CONFIG_KPROBES | 708 | #ifdef CONFIG_KPROBES |
707 | /* | 709 | /* |
@@ -711,7 +713,7 @@ void do_page_fault(struct pt_regs *regs, int fault_num, | |||
711 | */ | 713 | */ |
712 | if (notify_die(DIE_PAGE_FAULT, "page fault", regs, -1, | 714 | if (notify_die(DIE_PAGE_FAULT, "page fault", regs, -1, |
713 | regs->faultnum, SIGSEGV) == NOTIFY_STOP) | 715 | regs->faultnum, SIGSEGV) == NOTIFY_STOP) |
714 | return; | 716 | goto done; |
715 | #endif | 717 | #endif |
716 | 718 | ||
717 | #ifdef __tilegx__ | 719 | #ifdef __tilegx__ |
@@ -750,7 +752,6 @@ void do_page_fault(struct pt_regs *regs, int fault_num, | |||
750 | current->comm, current->pid, pc, address); | 752 | current->comm, current->pid, pc, address); |
751 | show_regs(regs); | 753 | show_regs(regs); |
752 | do_group_exit(SIGKILL); | 754 | do_group_exit(SIGKILL); |
753 | return; | ||
754 | } | 755 | } |
755 | } | 756 | } |
756 | #else | 757 | #else |
@@ -834,12 +835,15 @@ void do_page_fault(struct pt_regs *regs, int fault_num, | |||
834 | async->is_fault = is_page_fault; | 835 | async->is_fault = is_page_fault; |
835 | async->is_write = write; | 836 | async->is_write = write; |
836 | async->address = address; | 837 | async->address = address; |
837 | return; | 838 | goto done; |
838 | } | 839 | } |
839 | } | 840 | } |
840 | #endif | 841 | #endif |
841 | 842 | ||
842 | handle_page_fault(regs, fault_num, is_page_fault, address, write); | 843 | handle_page_fault(regs, fault_num, is_page_fault, address, write); |
844 | |||
845 | done: | ||
846 | exception_exit(prev_state); | ||
843 | } | 847 | } |
844 | 848 | ||
845 | 849 | ||