aboutsummaryrefslogtreecommitdiffstats
path: root/arch/tile
diff options
context:
space:
mode:
authorChris Metcalf <cmetcalf@ezchip.com>2015-03-23 14:23:58 -0400
committerChris Metcalf <cmetcalf@ezchip.com>2015-04-17 14:01:10 -0400
commit49e4e15619cd7cd9fc275d460fae2a95c1337fcc (patch)
tree700e24bb8f72a7662e7d4ae26d847e908d08de92 /arch/tile
parentb340c656af6317e28b466996a72cca019d97b42d (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/Kconfig1
-rw-r--r--arch/tile/include/asm/thread_info.h9
-rw-r--r--arch/tile/kernel/process.c12
-rw-r--r--arch/tile/kernel/ptrace.c22
-rw-r--r--arch/tile/kernel/single_step.c3
-rw-r--r--arch/tile/kernel/traps.c16
-rw-r--r--arch/tile/kernel/unaligned.c22
-rw-r--r--arch/tile/mm/fault.c10
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
506unsigned long get_wchan(struct task_struct *p) 510unsigned 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
253int do_syscall_trace_enter(struct pt_regs *regs) 254int 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. */
304void __kprobes do_breakpoint(struct pt_regs* regs, int fault_num) 320void __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
739void gx_singlestep_handle(struct pt_regs *regs, int fault_num) 740void 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)
253void __kprobes do_trap(struct pt_regs *regs, int fault_num, 254void __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
394done:
395 exception_exit(prev_state);
394} 396}
395 397
396void kernel_double_fault(int dummy, ulong pc, ulong lr, ulong sp, ulong r52) 398void 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
1449void do_unaligned(struct pt_regs *regs, int vecnum) 1450void 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
1596done:
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
845done:
846 exception_exit(prev_state);
843} 847}
844 848
845 849