diff options
| author | Frederic Weisbecker <fweisbec@gmail.com> | 2012-07-11 14:26:35 -0400 |
|---|---|---|
| committer | Frederic Weisbecker <fweisbec@gmail.com> | 2012-09-26 09:47:07 -0400 |
| commit | 6ba3c97a38803883c2eee489505796cb0a727122 (patch) | |
| tree | b6400bf2e10bf8d55b63eae35ddb93f3a9e9b270 | |
| parent | ef3f628872c838933a279d0d7e63e707783c9710 (diff) | |
x86: Exception hooks for userspace RCU extended QS
Add necessary hooks to x86 exception for userspace
RCU extended quiescent state support.
This includes traps, page fault, debug exceptions, etc...
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Alessio Igor Bogani <abogani@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Avi Kivity <avi@redhat.com>
Cc: Chris Metcalf <cmetcalf@tilera.com>
Cc: Christoph Lameter <cl@linux.com>
Cc: Geoff Levand <geoff@infradead.org>
Cc: Gilad Ben Yossef <gilad@benyossef.com>
Cc: Hakan Akkan <hakanakkan@gmail.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Josh Triplett <josh@joshtriplett.org>
Cc: Kevin Hilman <khilman@ti.com>
Cc: Max Krasnyansky <maxk@qualcomm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephen Hemminger <shemminger@vyatta.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Sven-Thorsten Dietrich <thebigcorporation@gmail.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
| -rw-r--r-- | arch/x86/include/asm/rcu.h | 20 | ||||
| -rw-r--r-- | arch/x86/kernel/traps.c | 81 | ||||
| -rw-r--r-- | arch/x86/mm/fault.c | 13 |
3 files changed, 86 insertions, 28 deletions
diff --git a/arch/x86/include/asm/rcu.h b/arch/x86/include/asm/rcu.h new file mode 100644 index 000000000000..439815b35ced --- /dev/null +++ b/arch/x86/include/asm/rcu.h | |||
| @@ -0,0 +1,20 @@ | |||
| 1 | #ifndef _ASM_X86_RCU_H | ||
| 2 | #define _ASM_X86_RCU_H | ||
| 3 | |||
| 4 | #include <linux/rcupdate.h> | ||
| 5 | #include <asm/ptrace.h> | ||
| 6 | |||
| 7 | static inline void exception_enter(struct pt_regs *regs) | ||
| 8 | { | ||
| 9 | rcu_user_exit(); | ||
| 10 | } | ||
| 11 | |||
| 12 | static inline void exception_exit(struct pt_regs *regs) | ||
| 13 | { | ||
| 14 | #ifdef CONFIG_RCU_USER_QS | ||
| 15 | if (user_mode(regs)) | ||
| 16 | rcu_user_enter(); | ||
| 17 | #endif | ||
| 18 | } | ||
| 19 | |||
| 20 | #endif | ||
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 74850e559449..378967578f22 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c | |||
| @@ -55,6 +55,7 @@ | |||
| 55 | #include <asm/i387.h> | 55 | #include <asm/i387.h> |
| 56 | #include <asm/fpu-internal.h> | 56 | #include <asm/fpu-internal.h> |
| 57 | #include <asm/mce.h> | 57 | #include <asm/mce.h> |
| 58 | #include <asm/rcu.h> | ||
| 58 | 59 | ||
| 59 | #include <asm/mach_traps.h> | 60 | #include <asm/mach_traps.h> |
| 60 | 61 | ||
| @@ -180,11 +181,15 @@ vm86_trap: | |||
| 180 | #define DO_ERROR(trapnr, signr, str, name) \ | 181 | #define DO_ERROR(trapnr, signr, str, name) \ |
| 181 | dotraplinkage void do_##name(struct pt_regs *regs, long error_code) \ | 182 | dotraplinkage void do_##name(struct pt_regs *regs, long error_code) \ |
| 182 | { \ | 183 | { \ |
| 183 | if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \ | 184 | exception_enter(regs); \ |
| 184 | == NOTIFY_STOP) \ | 185 | if (notify_die(DIE_TRAP, str, regs, error_code, \ |
| 186 | trapnr, signr) == NOTIFY_STOP) { \ | ||
| 187 | exception_exit(regs); \ | ||
| 185 | return; \ | 188 | return; \ |
| 189 | } \ | ||
| 186 | conditional_sti(regs); \ | 190 | conditional_sti(regs); \ |
| 187 | do_trap(trapnr, signr, str, regs, error_code, NULL); \ | 191 | do_trap(trapnr, signr, str, regs, error_code, NULL); \ |
| 192 | exception_exit(regs); \ | ||
| 188 | } | 193 | } |
| 189 | 194 | ||
| 190 | #define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \ | 195 | #define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \ |
| @@ -195,11 +200,15 @@ dotraplinkage void do_##name(struct pt_regs *regs, long error_code) \ | |||
| 195 | info.si_errno = 0; \ | 200 | info.si_errno = 0; \ |
| 196 | info.si_code = sicode; \ | 201 | info.si_code = sicode; \ |
| 197 | info.si_addr = (void __user *)siaddr; \ | 202 | info.si_addr = (void __user *)siaddr; \ |
| 198 | if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \ | 203 | exception_enter(regs); \ |
| 199 | == NOTIFY_STOP) \ | 204 | if (notify_die(DIE_TRAP, str, regs, error_code, \ |
| 205 | trapnr, signr) == NOTIFY_STOP) { \ | ||
| 206 | exception_exit(regs); \ | ||
| 200 | return; \ | 207 | return; \ |
| 208 | } \ | ||
| 201 | conditional_sti(regs); \ | 209 | conditional_sti(regs); \ |
| 202 | do_trap(trapnr, signr, str, regs, error_code, &info); \ | 210 | do_trap(trapnr, signr, str, regs, error_code, &info); \ |
| 211 | exception_exit(regs); \ | ||
| 203 | } | 212 | } |
| 204 | 213 | ||
| 205 | DO_ERROR_INFO(X86_TRAP_DE, SIGFPE, "divide error", divide_error, FPE_INTDIV, | 214 | DO_ERROR_INFO(X86_TRAP_DE, SIGFPE, "divide error", divide_error, FPE_INTDIV, |
| @@ -222,12 +231,14 @@ DO_ERROR_INFO(X86_TRAP_AC, SIGBUS, "alignment check", alignment_check, | |||
| 222 | /* Runs on IST stack */ | 231 | /* Runs on IST stack */ |
| 223 | dotraplinkage void do_stack_segment(struct pt_regs *regs, long error_code) | 232 | dotraplinkage void do_stack_segment(struct pt_regs *regs, long error_code) |
| 224 | { | 233 | { |
| 234 | exception_enter(regs); | ||
| 225 | if (notify_die(DIE_TRAP, "stack segment", regs, error_code, | 235 | if (notify_die(DIE_TRAP, "stack segment", regs, error_code, |
| 226 | X86_TRAP_SS, SIGBUS) == NOTIFY_STOP) | 236 | X86_TRAP_SS, SIGBUS) != NOTIFY_STOP) { |
| 227 | return; | 237 | preempt_conditional_sti(regs); |
| 228 | preempt_conditional_sti(regs); | 238 | do_trap(X86_TRAP_SS, SIGBUS, "stack segment", regs, error_code, NULL); |
| 229 | do_trap(X86_TRAP_SS, SIGBUS, "stack segment", regs, error_code, NULL); | 239 | preempt_conditional_cli(regs); |
| 230 | preempt_conditional_cli(regs); | 240 | } |
| 241 | exception_exit(regs); | ||
| 231 | } | 242 | } |
| 232 | 243 | ||
| 233 | dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code) | 244 | dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code) |
| @@ -235,6 +246,7 @@ dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code) | |||
| 235 | static const char str[] = "double fault"; | 246 | static const char str[] = "double fault"; |
| 236 | struct task_struct *tsk = current; | 247 | struct task_struct *tsk = current; |
| 237 | 248 | ||
| 249 | exception_enter(regs); | ||
| 238 | /* Return not checked because double check cannot be ignored */ | 250 | /* Return not checked because double check cannot be ignored */ |
| 239 | notify_die(DIE_TRAP, str, regs, error_code, X86_TRAP_DF, SIGSEGV); | 251 | notify_die(DIE_TRAP, str, regs, error_code, X86_TRAP_DF, SIGSEGV); |
| 240 | 252 | ||
| @@ -255,27 +267,28 @@ do_general_protection(struct pt_regs *regs, long error_code) | |||
| 255 | { | 267 | { |
| 256 | struct task_struct *tsk; | 268 | struct task_struct *tsk; |
| 257 | 269 | ||
| 270 | exception_enter(regs); | ||
| 258 | conditional_sti(regs); | 271 | conditional_sti(regs); |
| 259 | 272 | ||
| 260 | #ifdef CONFIG_X86_32 | 273 | #ifdef CONFIG_X86_32 |
| 261 | if (regs->flags & X86_VM_MASK) { | 274 | if (regs->flags & X86_VM_MASK) { |
| 262 | local_irq_enable(); | 275 | local_irq_enable(); |
| 263 | handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code); | 276 | handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code); |
| 264 | return; | 277 | goto exit; |
| 265 | } | 278 | } |
| 266 | #endif | 279 | #endif |
| 267 | 280 | ||
| 268 | tsk = current; | 281 | tsk = current; |
| 269 | if (!user_mode(regs)) { | 282 | if (!user_mode(regs)) { |
| 270 | if (fixup_exception(regs)) | 283 | if (fixup_exception(regs)) |
| 271 | return; | 284 | goto exit; |
| 272 | 285 | ||
| 273 | tsk->thread.error_code = error_code; | 286 | tsk->thread.error_code = error_code; |
| 274 | tsk->thread.trap_nr = X86_TRAP_GP; | 287 | tsk->thread.trap_nr = X86_TRAP_GP; |
| 275 | if (!notify_die(DIE_GPF, "general protection fault", regs, error_code, | 288 | if (notify_die(DIE_GPF, "general protection fault", regs, error_code, |
| 276 | X86_TRAP_GP, SIGSEGV) == NOTIFY_STOP) | 289 | X86_TRAP_GP, SIGSEGV) != NOTIFY_STOP) |
| 277 | die("general protection fault", regs, error_code); | 290 | die("general protection fault", regs, error_code); |
| 278 | return; | 291 | goto exit; |
| 279 | } | 292 | } |
| 280 | 293 | ||
| 281 | tsk->thread.error_code = error_code; | 294 | tsk->thread.error_code = error_code; |
| @@ -291,7 +304,8 @@ do_general_protection(struct pt_regs *regs, long error_code) | |||
| 291 | } | 304 | } |
| 292 | 305 | ||
| 293 | force_sig(SIGSEGV, tsk); | 306 | force_sig(SIGSEGV, tsk); |
| 294 | return; | 307 | exit: |
| 308 | exception_exit(regs); | ||
| 295 | } | 309 | } |
| 296 | 310 | ||
| 297 | /* May run on IST stack. */ | 311 | /* May run on IST stack. */ |
| @@ -306,15 +320,16 @@ dotraplinkage void __kprobes notrace do_int3(struct pt_regs *regs, long error_co | |||
| 306 | ftrace_int3_handler(regs)) | 320 | ftrace_int3_handler(regs)) |
| 307 | return; | 321 | return; |
| 308 | #endif | 322 | #endif |
| 323 | exception_enter(regs); | ||
| 309 | #ifdef CONFIG_KGDB_LOW_LEVEL_TRAP | 324 | #ifdef CONFIG_KGDB_LOW_LEVEL_TRAP |
| 310 | if (kgdb_ll_trap(DIE_INT3, "int3", regs, error_code, X86_TRAP_BP, | 325 | if (kgdb_ll_trap(DIE_INT3, "int3", regs, error_code, X86_TRAP_BP, |
| 311 | SIGTRAP) == NOTIFY_STOP) | 326 | SIGTRAP) == NOTIFY_STOP) |
| 312 | return; | 327 | goto exit; |
| 313 | #endif /* CONFIG_KGDB_LOW_LEVEL_TRAP */ | 328 | #endif /* CONFIG_KGDB_LOW_LEVEL_TRAP */ |
| 314 | 329 | ||
| 315 | if (notify_die(DIE_INT3, "int3", regs, error_code, X86_TRAP_BP, | 330 | if (notify_die(DIE_INT3, "int3", regs, error_code, X86_TRAP_BP, |
| 316 | SIGTRAP) == NOTIFY_STOP) | 331 | SIGTRAP) == NOTIFY_STOP) |
| 317 | return; | 332 | goto exit; |
| 318 | 333 | ||
| 319 | /* | 334 | /* |
| 320 | * Let others (NMI) know that the debug stack is in use | 335 | * Let others (NMI) know that the debug stack is in use |
| @@ -325,6 +340,8 @@ dotraplinkage void __kprobes notrace do_int3(struct pt_regs *regs, long error_co | |||
| 325 | do_trap(X86_TRAP_BP, SIGTRAP, "int3", regs, error_code, NULL); | 340 | do_trap(X86_TRAP_BP, SIGTRAP, "int3", regs, error_code, NULL); |
| 326 | preempt_conditional_cli(regs); | 341 | preempt_conditional_cli(regs); |
| 327 | debug_stack_usage_dec(); | 342 | debug_stack_usage_dec(); |
| 343 | exit: | ||
| 344 | exception_exit(regs); | ||
| 328 | } | 345 | } |
| 329 | 346 | ||
| 330 | #ifdef CONFIG_X86_64 | 347 | #ifdef CONFIG_X86_64 |
| @@ -385,6 +402,8 @@ dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code) | |||
| 385 | unsigned long dr6; | 402 | unsigned long dr6; |
| 386 | int si_code; | 403 | int si_code; |
| 387 | 404 | ||
| 405 | exception_enter(regs); | ||
| 406 | |||
| 388 | get_debugreg(dr6, 6); | 407 | get_debugreg(dr6, 6); |
| 389 | 408 | ||
| 390 | /* Filter out all the reserved bits which are preset to 1 */ | 409 | /* Filter out all the reserved bits which are preset to 1 */ |
| @@ -400,7 +419,7 @@ dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code) | |||
| 400 | 419 | ||
| 401 | /* Catch kmemcheck conditions first of all! */ | 420 | /* Catch kmemcheck conditions first of all! */ |
| 402 | if ((dr6 & DR_STEP) && kmemcheck_trap(regs)) | 421 | if ((dr6 & DR_STEP) && kmemcheck_trap(regs)) |
| 403 | return; | 422 | goto exit; |
| 404 | 423 | ||
| 405 | /* DR6 may or may not be cleared by the CPU */ | 424 | /* DR6 may or may not be cleared by the CPU */ |
| 406 | set_debugreg(0, 6); | 425 | set_debugreg(0, 6); |
| @@ -415,7 +434,7 @@ dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code) | |||
| 415 | 434 | ||
| 416 | if (notify_die(DIE_DEBUG, "debug", regs, PTR_ERR(&dr6), error_code, | 435 | if (notify_die(DIE_DEBUG, "debug", regs, PTR_ERR(&dr6), error_code, |
| 417 | SIGTRAP) == NOTIFY_STOP) | 436 | SIGTRAP) == NOTIFY_STOP) |
| 418 | return; | 437 | goto exit; |
| 419 | 438 | ||
| 420 | /* | 439 | /* |
| 421 | * Let others (NMI) know that the debug stack is in use | 440 | * Let others (NMI) know that the debug stack is in use |
| @@ -431,7 +450,7 @@ dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code) | |||
| 431 | X86_TRAP_DB); | 450 | X86_TRAP_DB); |
| 432 | preempt_conditional_cli(regs); | 451 | preempt_conditional_cli(regs); |
| 433 | debug_stack_usage_dec(); | 452 | debug_stack_usage_dec(); |
| 434 | return; | 453 | goto exit; |
| 435 | } | 454 | } |
| 436 | 455 | ||
| 437 | /* | 456 | /* |
| @@ -452,7 +471,8 @@ dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code) | |||
| 452 | preempt_conditional_cli(regs); | 471 | preempt_conditional_cli(regs); |
| 453 | debug_stack_usage_dec(); | 472 | debug_stack_usage_dec(); |
| 454 | 473 | ||
| 455 | return; | 474 | exit: |
| 475 | exception_exit(regs); | ||
| 456 | } | 476 | } |
| 457 | 477 | ||
| 458 | /* | 478 | /* |
| @@ -549,14 +569,17 @@ dotraplinkage void do_coprocessor_error(struct pt_regs *regs, long error_code) | |||
| 549 | #ifdef CONFIG_X86_32 | 569 | #ifdef CONFIG_X86_32 |
| 550 | ignore_fpu_irq = 1; | 570 | ignore_fpu_irq = 1; |
| 551 | #endif | 571 | #endif |
| 552 | 572 | exception_enter(regs); | |
| 553 | math_error(regs, error_code, X86_TRAP_MF); | 573 | math_error(regs, error_code, X86_TRAP_MF); |
| 574 | exception_exit(regs); | ||
| 554 | } | 575 | } |
| 555 | 576 | ||
| 556 | dotraplinkage void | 577 | dotraplinkage void |
| 557 | do_simd_coprocessor_error(struct pt_regs *regs, long error_code) | 578 | do_simd_coprocessor_error(struct pt_regs *regs, long error_code) |
| 558 | { | 579 | { |
| 580 | exception_enter(regs); | ||
| 559 | math_error(regs, error_code, X86_TRAP_XF); | 581 | math_error(regs, error_code, X86_TRAP_XF); |
| 582 | exception_exit(regs); | ||
| 560 | } | 583 | } |
| 561 | 584 | ||
| 562 | dotraplinkage void | 585 | dotraplinkage void |
| @@ -623,6 +646,7 @@ EXPORT_SYMBOL_GPL(math_state_restore); | |||
| 623 | dotraplinkage void __kprobes | 646 | dotraplinkage void __kprobes |
| 624 | do_device_not_available(struct pt_regs *regs, long error_code) | 647 | do_device_not_available(struct pt_regs *regs, long error_code) |
| 625 | { | 648 | { |
| 649 | exception_enter(regs); | ||
| 626 | #ifdef CONFIG_MATH_EMULATION | 650 | #ifdef CONFIG_MATH_EMULATION |
| 627 | if (read_cr0() & X86_CR0_EM) { | 651 | if (read_cr0() & X86_CR0_EM) { |
| 628 | struct math_emu_info info = { }; | 652 | struct math_emu_info info = { }; |
| @@ -631,6 +655,7 @@ do_device_not_available(struct pt_regs *regs, long error_code) | |||
| 631 | 655 | ||
| 632 | info.regs = regs; | 656 | info.regs = regs; |
| 633 | math_emulate(&info); | 657 | math_emulate(&info); |
| 658 | exception_exit(regs); | ||
| 634 | return; | 659 | return; |
| 635 | } | 660 | } |
| 636 | #endif | 661 | #endif |
| @@ -638,12 +663,15 @@ do_device_not_available(struct pt_regs *regs, long error_code) | |||
| 638 | #ifdef CONFIG_X86_32 | 663 | #ifdef CONFIG_X86_32 |
| 639 | conditional_sti(regs); | 664 | conditional_sti(regs); |
| 640 | #endif | 665 | #endif |
| 666 | exception_exit(regs); | ||
| 641 | } | 667 | } |
| 642 | 668 | ||
| 643 | #ifdef CONFIG_X86_32 | 669 | #ifdef CONFIG_X86_32 |
| 644 | dotraplinkage void do_iret_error(struct pt_regs *regs, long error_code) | 670 | dotraplinkage void do_iret_error(struct pt_regs *regs, long error_code) |
| 645 | { | 671 | { |
| 646 | siginfo_t info; | 672 | siginfo_t info; |
| 673 | |||
| 674 | exception_enter(regs); | ||
| 647 | local_irq_enable(); | 675 | local_irq_enable(); |
| 648 | 676 | ||
| 649 | info.si_signo = SIGILL; | 677 | info.si_signo = SIGILL; |
| @@ -651,10 +679,11 @@ dotraplinkage void do_iret_error(struct pt_regs *regs, long error_code) | |||
| 651 | info.si_code = ILL_BADSTK; | 679 | info.si_code = ILL_BADSTK; |
| 652 | info.si_addr = NULL; | 680 | info.si_addr = NULL; |
| 653 | if (notify_die(DIE_TRAP, "iret exception", regs, error_code, | 681 | if (notify_die(DIE_TRAP, "iret exception", regs, error_code, |
| 654 | X86_TRAP_IRET, SIGILL) == NOTIFY_STOP) | 682 | X86_TRAP_IRET, SIGILL) != NOTIFY_STOP) { |
| 655 | return; | 683 | do_trap(X86_TRAP_IRET, SIGILL, "iret exception", regs, error_code, |
| 656 | do_trap(X86_TRAP_IRET, SIGILL, "iret exception", regs, error_code, | 684 | &info); |
| 657 | &info); | 685 | } |
| 686 | exception_exit(regs); | ||
| 658 | } | 687 | } |
| 659 | #endif | 688 | #endif |
| 660 | 689 | ||
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 76dcd9d8e0bc..7dde46d68a25 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include <asm/pgalloc.h> /* pgd_*(), ... */ | 18 | #include <asm/pgalloc.h> /* pgd_*(), ... */ |
| 19 | #include <asm/kmemcheck.h> /* kmemcheck_*(), ... */ | 19 | #include <asm/kmemcheck.h> /* kmemcheck_*(), ... */ |
| 20 | #include <asm/fixmap.h> /* VSYSCALL_START */ | 20 | #include <asm/fixmap.h> /* VSYSCALL_START */ |
| 21 | #include <asm/rcu.h> /* exception_enter(), ... */ | ||
| 21 | 22 | ||
| 22 | /* | 23 | /* |
| 23 | * Page fault error code bits: | 24 | * Page fault error code bits: |
| @@ -1000,8 +1001,8 @@ static int fault_in_kernel_space(unsigned long address) | |||
| 1000 | * and the problem, and then passes it off to one of the appropriate | 1001 | * and the problem, and then passes it off to one of the appropriate |
| 1001 | * routines. | 1002 | * routines. |
| 1002 | */ | 1003 | */ |
| 1003 | dotraplinkage void __kprobes | 1004 | static void __kprobes |
| 1004 | do_page_fault(struct pt_regs *regs, unsigned long error_code) | 1005 | __do_page_fault(struct pt_regs *regs, unsigned long error_code) |
| 1005 | { | 1006 | { |
| 1006 | struct vm_area_struct *vma; | 1007 | struct vm_area_struct *vma; |
| 1007 | struct task_struct *tsk; | 1008 | struct task_struct *tsk; |
| @@ -1209,3 +1210,11 @@ good_area: | |||
| 1209 | 1210 | ||
| 1210 | up_read(&mm->mmap_sem); | 1211 | up_read(&mm->mmap_sem); |
| 1211 | } | 1212 | } |
| 1213 | |||
| 1214 | dotraplinkage void __kprobes | ||
| 1215 | do_page_fault(struct pt_regs *regs, unsigned long error_code) | ||
| 1216 | { | ||
| 1217 | exception_enter(regs); | ||
| 1218 | __do_page_fault(regs, error_code); | ||
| 1219 | exception_exit(regs); | ||
| 1220 | } | ||
