diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2013-05-28 19:07:19 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2013-06-10 12:02:30 -0400 |
commit | c3fc5cd5c5a5f4738776a965a020a32c1a37c8fd (patch) | |
tree | 59c7114e5c9e682b0b6ec647cabfa4d942ee1377 /arch/mips/kernel | |
parent | e7f3b48af7be9f8007a224663a5b91340626fed5 (diff) |
MIPS: Implement HAVE_CONTEXT_TRACKING.
This enables support for CONFIG_NO_HZ_FULL.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/kernel')
-rw-r--r-- | arch/mips/kernel/cpu-bugs64.c | 5 | ||||
-rw-r--r-- | arch/mips/kernel/ptrace.c | 12 | ||||
-rw-r--r-- | arch/mips/kernel/signal.c | 5 | ||||
-rw-r--r-- | arch/mips/kernel/traps.c | 74 | ||||
-rw-r--r-- | arch/mips/kernel/unaligned.c | 4 |
5 files changed, 86 insertions, 14 deletions
diff --git a/arch/mips/kernel/cpu-bugs64.c b/arch/mips/kernel/cpu-bugs64.c index de3c25ffd9f9..0c61df281ce6 100644 --- a/arch/mips/kernel/cpu-bugs64.c +++ b/arch/mips/kernel/cpu-bugs64.c | |||
@@ -6,6 +6,7 @@ | |||
6 | * as published by the Free Software Foundation; either version | 6 | * as published by the Free Software Foundation; either version |
7 | * 2 of the License, or (at your option) any later version. | 7 | * 2 of the License, or (at your option) any later version. |
8 | */ | 8 | */ |
9 | #include <linux/context_tracking.h> | ||
9 | #include <linux/init.h> | 10 | #include <linux/init.h> |
10 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
11 | #include <linux/ptrace.h> | 12 | #include <linux/ptrace.h> |
@@ -171,8 +172,12 @@ static volatile int daddi_ov __cpuinitdata; | |||
171 | 172 | ||
172 | asmlinkage void __init do_daddi_ov(struct pt_regs *regs) | 173 | asmlinkage void __init do_daddi_ov(struct pt_regs *regs) |
173 | { | 174 | { |
175 | enum ctx_state prev_state; | ||
176 | |||
177 | prev_state = exception_enter(); | ||
174 | daddi_ov = 1; | 178 | daddi_ov = 1; |
175 | regs->cp0_epc += 4; | 179 | regs->cp0_epc += 4; |
180 | exception_exit(prev_state); | ||
176 | } | 181 | } |
177 | 182 | ||
178 | static inline void check_daddi(void) | 183 | static inline void check_daddi(void) |
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 9c6299c733a3..8ae1ebef8b71 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c | |||
@@ -15,6 +15,7 @@ | |||
15 | * binaries. | 15 | * binaries. |
16 | */ | 16 | */ |
17 | #include <linux/compiler.h> | 17 | #include <linux/compiler.h> |
18 | #include <linux/context_tracking.h> | ||
18 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
19 | #include <linux/sched.h> | 20 | #include <linux/sched.h> |
20 | #include <linux/mm.h> | 21 | #include <linux/mm.h> |
@@ -534,6 +535,8 @@ static inline int audit_arch(void) | |||
534 | */ | 535 | */ |
535 | asmlinkage void syscall_trace_enter(struct pt_regs *regs) | 536 | asmlinkage void syscall_trace_enter(struct pt_regs *regs) |
536 | { | 537 | { |
538 | user_exit(); | ||
539 | |||
537 | /* do the secure computing check first */ | 540 | /* do the secure computing check first */ |
538 | secure_computing_strict(regs->regs[2]); | 541 | secure_computing_strict(regs->regs[2]); |
539 | 542 | ||
@@ -570,6 +573,13 @@ out: | |||
570 | */ | 573 | */ |
571 | asmlinkage void syscall_trace_leave(struct pt_regs *regs) | 574 | asmlinkage void syscall_trace_leave(struct pt_regs *regs) |
572 | { | 575 | { |
576 | /* | ||
577 | * We may come here right after calling schedule_user() | ||
578 | * or do_notify_resume(), in which case we can be in RCU | ||
579 | * user mode. | ||
580 | */ | ||
581 | user_exit(); | ||
582 | |||
573 | audit_syscall_exit(regs); | 583 | audit_syscall_exit(regs); |
574 | 584 | ||
575 | if (!(current->ptrace & PT_PTRACED)) | 585 | if (!(current->ptrace & PT_PTRACED)) |
@@ -592,4 +602,6 @@ asmlinkage void syscall_trace_leave(struct pt_regs *regs) | |||
592 | send_sig(current->exit_code, current, 1); | 602 | send_sig(current->exit_code, current, 1); |
593 | current->exit_code = 0; | 603 | current->exit_code = 0; |
594 | } | 604 | } |
605 | |||
606 | user_enter(); | ||
595 | } | 607 | } |
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index fd3ef2c2afbc..2f285abc76d5 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c | |||
@@ -8,6 +8,7 @@ | |||
8 | * Copyright (C) 1999, 2000 Silicon Graphics, Inc. | 8 | * Copyright (C) 1999, 2000 Silicon Graphics, Inc. |
9 | */ | 9 | */ |
10 | #include <linux/cache.h> | 10 | #include <linux/cache.h> |
11 | #include <linux/context_tracking.h> | ||
11 | #include <linux/irqflags.h> | 12 | #include <linux/irqflags.h> |
12 | #include <linux/sched.h> | 13 | #include <linux/sched.h> |
13 | #include <linux/mm.h> | 14 | #include <linux/mm.h> |
@@ -573,6 +574,8 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused, | |||
573 | { | 574 | { |
574 | local_irq_enable(); | 575 | local_irq_enable(); |
575 | 576 | ||
577 | user_exit(); | ||
578 | |||
576 | /* deal with pending signal delivery */ | 579 | /* deal with pending signal delivery */ |
577 | if (thread_info_flags & _TIF_SIGPENDING) | 580 | if (thread_info_flags & _TIF_SIGPENDING) |
578 | do_signal(regs); | 581 | do_signal(regs); |
@@ -581,6 +584,8 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused, | |||
581 | clear_thread_flag(TIF_NOTIFY_RESUME); | 584 | clear_thread_flag(TIF_NOTIFY_RESUME); |
582 | tracehook_notify_resume(regs); | 585 | tracehook_notify_resume(regs); |
583 | } | 586 | } |
587 | |||
588 | user_enter(); | ||
584 | } | 589 | } |
585 | 590 | ||
586 | #ifdef CONFIG_SMP | 591 | #ifdef CONFIG_SMP |
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index a75ae40184aa..beba1e616b6e 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c | |||
@@ -13,6 +13,7 @@ | |||
13 | */ | 13 | */ |
14 | #include <linux/bug.h> | 14 | #include <linux/bug.h> |
15 | #include <linux/compiler.h> | 15 | #include <linux/compiler.h> |
16 | #include <linux/context_tracking.h> | ||
16 | #include <linux/kexec.h> | 17 | #include <linux/kexec.h> |
17 | #include <linux/init.h> | 18 | #include <linux/init.h> |
18 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
@@ -423,7 +424,9 @@ asmlinkage void do_be(struct pt_regs *regs) | |||
423 | const struct exception_table_entry *fixup = NULL; | 424 | const struct exception_table_entry *fixup = NULL; |
424 | int data = regs->cp0_cause & 4; | 425 | int data = regs->cp0_cause & 4; |
425 | int action = MIPS_BE_FATAL; | 426 | int action = MIPS_BE_FATAL; |
427 | enum ctx_state prev_state; | ||
426 | 428 | ||
429 | prev_state = exception_enter(); | ||
427 | /* XXX For now. Fixme, this searches the wrong table ... */ | 430 | /* XXX For now. Fixme, this searches the wrong table ... */ |
428 | if (data && !user_mode(regs)) | 431 | if (data && !user_mode(regs)) |
429 | fixup = search_dbe_tables(exception_epc(regs)); | 432 | fixup = search_dbe_tables(exception_epc(regs)); |
@@ -436,11 +439,11 @@ asmlinkage void do_be(struct pt_regs *regs) | |||
436 | 439 | ||
437 | switch (action) { | 440 | switch (action) { |
438 | case MIPS_BE_DISCARD: | 441 | case MIPS_BE_DISCARD: |
439 | return; | 442 | goto out; |
440 | case MIPS_BE_FIXUP: | 443 | case MIPS_BE_FIXUP: |
441 | if (fixup) { | 444 | if (fixup) { |
442 | regs->cp0_epc = fixup->nextinsn; | 445 | regs->cp0_epc = fixup->nextinsn; |
443 | return; | 446 | goto out; |
444 | } | 447 | } |
445 | break; | 448 | break; |
446 | default: | 449 | default: |
@@ -455,10 +458,13 @@ asmlinkage void do_be(struct pt_regs *regs) | |||
455 | field, regs->cp0_epc, field, regs->regs[31]); | 458 | field, regs->cp0_epc, field, regs->regs[31]); |
456 | if (notify_die(DIE_OOPS, "bus error", regs, 0, regs_to_trapnr(regs), SIGBUS) | 459 | if (notify_die(DIE_OOPS, "bus error", regs, 0, regs_to_trapnr(regs), SIGBUS) |
457 | == NOTIFY_STOP) | 460 | == NOTIFY_STOP) |
458 | return; | 461 | goto out; |
459 | 462 | ||
460 | die_if_kernel("Oops", regs); | 463 | die_if_kernel("Oops", regs); |
461 | force_sig(SIGBUS, current); | 464 | force_sig(SIGBUS, current); |
465 | |||
466 | out: | ||
467 | exception_exit(prev_state); | ||
462 | } | 468 | } |
463 | 469 | ||
464 | /* | 470 | /* |
@@ -673,8 +679,10 @@ static int simulate_sync(struct pt_regs *regs, unsigned int opcode) | |||
673 | 679 | ||
674 | asmlinkage void do_ov(struct pt_regs *regs) | 680 | asmlinkage void do_ov(struct pt_regs *regs) |
675 | { | 681 | { |
682 | enum ctx_state prev_state; | ||
676 | siginfo_t info; | 683 | siginfo_t info; |
677 | 684 | ||
685 | prev_state = exception_enter(); | ||
678 | die_if_kernel("Integer overflow", regs); | 686 | die_if_kernel("Integer overflow", regs); |
679 | 687 | ||
680 | info.si_code = FPE_INTOVF; | 688 | info.si_code = FPE_INTOVF; |
@@ -682,6 +690,7 @@ asmlinkage void do_ov(struct pt_regs *regs) | |||
682 | info.si_errno = 0; | 690 | info.si_errno = 0; |
683 | info.si_addr = (void __user *) regs->cp0_epc; | 691 | info.si_addr = (void __user *) regs->cp0_epc; |
684 | force_sig_info(SIGFPE, &info, current); | 692 | force_sig_info(SIGFPE, &info, current); |
693 | exception_exit(prev_state); | ||
685 | } | 694 | } |
686 | 695 | ||
687 | int process_fpemu_return(int sig, void __user *fault_addr) | 696 | int process_fpemu_return(int sig, void __user *fault_addr) |
@@ -713,11 +722,13 @@ int process_fpemu_return(int sig, void __user *fault_addr) | |||
713 | */ | 722 | */ |
714 | asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) | 723 | asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) |
715 | { | 724 | { |
725 | enum ctx_state prev_state; | ||
716 | siginfo_t info = {0}; | 726 | siginfo_t info = {0}; |
717 | 727 | ||
728 | prev_state = exception_enter(); | ||
718 | if (notify_die(DIE_FP, "FP exception", regs, 0, regs_to_trapnr(regs), SIGFPE) | 729 | if (notify_die(DIE_FP, "FP exception", regs, 0, regs_to_trapnr(regs), SIGFPE) |
719 | == NOTIFY_STOP) | 730 | == NOTIFY_STOP) |
720 | return; | 731 | goto out; |
721 | die_if_kernel("FP exception in kernel code", regs); | 732 | die_if_kernel("FP exception in kernel code", regs); |
722 | 733 | ||
723 | if (fcr31 & FPU_CSR_UNI_X) { | 734 | if (fcr31 & FPU_CSR_UNI_X) { |
@@ -753,7 +764,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) | |||
753 | /* If something went wrong, signal */ | 764 | /* If something went wrong, signal */ |
754 | process_fpemu_return(sig, fault_addr); | 765 | process_fpemu_return(sig, fault_addr); |
755 | 766 | ||
756 | return; | 767 | goto out; |
757 | } else if (fcr31 & FPU_CSR_INV_X) | 768 | } else if (fcr31 & FPU_CSR_INV_X) |
758 | info.si_code = FPE_FLTINV; | 769 | info.si_code = FPE_FLTINV; |
759 | else if (fcr31 & FPU_CSR_DIV_X) | 770 | else if (fcr31 & FPU_CSR_DIV_X) |
@@ -770,6 +781,9 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) | |||
770 | info.si_errno = 0; | 781 | info.si_errno = 0; |
771 | info.si_addr = (void __user *) regs->cp0_epc; | 782 | info.si_addr = (void __user *) regs->cp0_epc; |
772 | force_sig_info(SIGFPE, &info, current); | 783 | force_sig_info(SIGFPE, &info, current); |
784 | |||
785 | out: | ||
786 | exception_exit(prev_state); | ||
773 | } | 787 | } |
774 | 788 | ||
775 | static void do_trap_or_bp(struct pt_regs *regs, unsigned int code, | 789 | static void do_trap_or_bp(struct pt_regs *regs, unsigned int code, |
@@ -835,9 +849,11 @@ static void do_trap_or_bp(struct pt_regs *regs, unsigned int code, | |||
835 | asmlinkage void do_bp(struct pt_regs *regs) | 849 | asmlinkage void do_bp(struct pt_regs *regs) |
836 | { | 850 | { |
837 | unsigned int opcode, bcode; | 851 | unsigned int opcode, bcode; |
852 | enum ctx_state prev_state; | ||
838 | unsigned long epc; | 853 | unsigned long epc; |
839 | u16 instr[2]; | 854 | u16 instr[2]; |
840 | 855 | ||
856 | prev_state = exception_enter(); | ||
841 | if (get_isa16_mode(regs->cp0_epc)) { | 857 | if (get_isa16_mode(regs->cp0_epc)) { |
842 | /* Calculate EPC. */ | 858 | /* Calculate EPC. */ |
843 | epc = exception_epc(regs); | 859 | epc = exception_epc(regs); |
@@ -852,7 +868,7 @@ asmlinkage void do_bp(struct pt_regs *regs) | |||
852 | goto out_sigsegv; | 868 | goto out_sigsegv; |
853 | bcode = (instr[0] >> 6) & 0x3f; | 869 | bcode = (instr[0] >> 6) & 0x3f; |
854 | do_trap_or_bp(regs, bcode, "Break"); | 870 | do_trap_or_bp(regs, bcode, "Break"); |
855 | return; | 871 | goto out; |
856 | } | 872 | } |
857 | } else { | 873 | } else { |
858 | if (__get_user(opcode, (unsigned int __user *) exception_epc(regs))) | 874 | if (__get_user(opcode, (unsigned int __user *) exception_epc(regs))) |
@@ -876,12 +892,12 @@ asmlinkage void do_bp(struct pt_regs *regs) | |||
876 | switch (bcode) { | 892 | switch (bcode) { |
877 | case BRK_KPROBE_BP: | 893 | case BRK_KPROBE_BP: |
878 | if (notify_die(DIE_BREAK, "debug", regs, bcode, regs_to_trapnr(regs), SIGTRAP) == NOTIFY_STOP) | 894 | if (notify_die(DIE_BREAK, "debug", regs, bcode, regs_to_trapnr(regs), SIGTRAP) == NOTIFY_STOP) |
879 | return; | 895 | goto out; |
880 | else | 896 | else |
881 | break; | 897 | break; |
882 | case BRK_KPROBE_SSTEPBP: | 898 | case BRK_KPROBE_SSTEPBP: |
883 | if (notify_die(DIE_SSTEPBP, "single_step", regs, bcode, regs_to_trapnr(regs), SIGTRAP) == NOTIFY_STOP) | 899 | if (notify_die(DIE_SSTEPBP, "single_step", regs, bcode, regs_to_trapnr(regs), SIGTRAP) == NOTIFY_STOP) |
884 | return; | 900 | goto out; |
885 | else | 901 | else |
886 | break; | 902 | break; |
887 | default: | 903 | default: |
@@ -889,18 +905,24 @@ asmlinkage void do_bp(struct pt_regs *regs) | |||
889 | } | 905 | } |
890 | 906 | ||
891 | do_trap_or_bp(regs, bcode, "Break"); | 907 | do_trap_or_bp(regs, bcode, "Break"); |
908 | |||
909 | out: | ||
910 | exception_exit(prev_state); | ||
892 | return; | 911 | return; |
893 | 912 | ||
894 | out_sigsegv: | 913 | out_sigsegv: |
895 | force_sig(SIGSEGV, current); | 914 | force_sig(SIGSEGV, current); |
915 | goto out; | ||
896 | } | 916 | } |
897 | 917 | ||
898 | asmlinkage void do_tr(struct pt_regs *regs) | 918 | asmlinkage void do_tr(struct pt_regs *regs) |
899 | { | 919 | { |
900 | u32 opcode, tcode = 0; | 920 | u32 opcode, tcode = 0; |
921 | enum ctx_state prev_state; | ||
901 | u16 instr[2]; | 922 | u16 instr[2]; |
902 | unsigned long epc = msk_isa16_mode(exception_epc(regs)); | 923 | unsigned long epc = msk_isa16_mode(exception_epc(regs)); |
903 | 924 | ||
925 | prev_state = exception_enter(); | ||
904 | if (get_isa16_mode(regs->cp0_epc)) { | 926 | if (get_isa16_mode(regs->cp0_epc)) { |
905 | if (__get_user(instr[0], (u16 __user *)(epc + 0)) || | 927 | if (__get_user(instr[0], (u16 __user *)(epc + 0)) || |
906 | __get_user(instr[1], (u16 __user *)(epc + 2))) | 928 | __get_user(instr[1], (u16 __user *)(epc + 2))) |
@@ -918,10 +940,14 @@ asmlinkage void do_tr(struct pt_regs *regs) | |||
918 | } | 940 | } |
919 | 941 | ||
920 | do_trap_or_bp(regs, tcode, "Trap"); | 942 | do_trap_or_bp(regs, tcode, "Trap"); |
943 | |||
944 | out: | ||
945 | exception_exit(prev_state); | ||
921 | return; | 946 | return; |
922 | 947 | ||
923 | out_sigsegv: | 948 | out_sigsegv: |
924 | force_sig(SIGSEGV, current); | 949 | force_sig(SIGSEGV, current); |
950 | goto out; | ||
925 | } | 951 | } |
926 | 952 | ||
927 | asmlinkage void do_ri(struct pt_regs *regs) | 953 | asmlinkage void do_ri(struct pt_regs *regs) |
@@ -929,17 +955,19 @@ asmlinkage void do_ri(struct pt_regs *regs) | |||
929 | unsigned int __user *epc = (unsigned int __user *)exception_epc(regs); | 955 | unsigned int __user *epc = (unsigned int __user *)exception_epc(regs); |
930 | unsigned long old_epc = regs->cp0_epc; | 956 | unsigned long old_epc = regs->cp0_epc; |
931 | unsigned long old31 = regs->regs[31]; | 957 | unsigned long old31 = regs->regs[31]; |
958 | enum ctx_state prev_state; | ||
932 | unsigned int opcode = 0; | 959 | unsigned int opcode = 0; |
933 | int status = -1; | 960 | int status = -1; |
934 | 961 | ||
962 | prev_state = exception_enter(); | ||
935 | if (notify_die(DIE_RI, "RI Fault", regs, 0, regs_to_trapnr(regs), SIGILL) | 963 | if (notify_die(DIE_RI, "RI Fault", regs, 0, regs_to_trapnr(regs), SIGILL) |
936 | == NOTIFY_STOP) | 964 | == NOTIFY_STOP) |
937 | return; | 965 | goto out; |
938 | 966 | ||
939 | die_if_kernel("Reserved instruction in kernel code", regs); | 967 | die_if_kernel("Reserved instruction in kernel code", regs); |
940 | 968 | ||
941 | if (unlikely(compute_return_epc(regs) < 0)) | 969 | if (unlikely(compute_return_epc(regs) < 0)) |
942 | return; | 970 | goto out; |
943 | 971 | ||
944 | if (get_isa16_mode(regs->cp0_epc)) { | 972 | if (get_isa16_mode(regs->cp0_epc)) { |
945 | unsigned short mmop[2] = { 0 }; | 973 | unsigned short mmop[2] = { 0 }; |
@@ -974,6 +1002,9 @@ asmlinkage void do_ri(struct pt_regs *regs) | |||
974 | regs->regs[31] = old31; | 1002 | regs->regs[31] = old31; |
975 | force_sig(status, current); | 1003 | force_sig(status, current); |
976 | } | 1004 | } |
1005 | |||
1006 | out: | ||
1007 | exception_exit(prev_state); | ||
977 | } | 1008 | } |
978 | 1009 | ||
979 | /* | 1010 | /* |
@@ -1040,6 +1071,7 @@ static int default_cu2_call(struct notifier_block *nfb, unsigned long action, | |||
1040 | 1071 | ||
1041 | asmlinkage void do_cpu(struct pt_regs *regs) | 1072 | asmlinkage void do_cpu(struct pt_regs *regs) |
1042 | { | 1073 | { |
1074 | enum ctx_state prev_state; | ||
1043 | unsigned int __user *epc; | 1075 | unsigned int __user *epc; |
1044 | unsigned long old_epc, old31; | 1076 | unsigned long old_epc, old31; |
1045 | unsigned int opcode; | 1077 | unsigned int opcode; |
@@ -1047,6 +1079,7 @@ asmlinkage void do_cpu(struct pt_regs *regs) | |||
1047 | int status; | 1079 | int status; |
1048 | unsigned long __maybe_unused flags; | 1080 | unsigned long __maybe_unused flags; |
1049 | 1081 | ||
1082 | prev_state = exception_enter(); | ||
1050 | die_if_kernel("do_cpu invoked from kernel context!", regs); | 1083 | die_if_kernel("do_cpu invoked from kernel context!", regs); |
1051 | 1084 | ||
1052 | cpid = (regs->cp0_cause >> CAUSEB_CE) & 3; | 1085 | cpid = (regs->cp0_cause >> CAUSEB_CE) & 3; |
@@ -1060,7 +1093,7 @@ asmlinkage void do_cpu(struct pt_regs *regs) | |||
1060 | status = -1; | 1093 | status = -1; |
1061 | 1094 | ||
1062 | if (unlikely(compute_return_epc(regs) < 0)) | 1095 | if (unlikely(compute_return_epc(regs) < 0)) |
1063 | return; | 1096 | goto out; |
1064 | 1097 | ||
1065 | if (get_isa16_mode(regs->cp0_epc)) { | 1098 | if (get_isa16_mode(regs->cp0_epc)) { |
1066 | unsigned short mmop[2] = { 0 }; | 1099 | unsigned short mmop[2] = { 0 }; |
@@ -1093,7 +1126,7 @@ asmlinkage void do_cpu(struct pt_regs *regs) | |||
1093 | force_sig(status, current); | 1126 | force_sig(status, current); |
1094 | } | 1127 | } |
1095 | 1128 | ||
1096 | return; | 1129 | goto out; |
1097 | 1130 | ||
1098 | case 3: | 1131 | case 3: |
1099 | /* | 1132 | /* |
@@ -1131,19 +1164,26 @@ asmlinkage void do_cpu(struct pt_regs *regs) | |||
1131 | mt_ase_fp_affinity(); | 1164 | mt_ase_fp_affinity(); |
1132 | } | 1165 | } |
1133 | 1166 | ||
1134 | return; | 1167 | goto out; |
1135 | 1168 | ||
1136 | case 2: | 1169 | case 2: |
1137 | raw_notifier_call_chain(&cu2_chain, CU2_EXCEPTION, regs); | 1170 | raw_notifier_call_chain(&cu2_chain, CU2_EXCEPTION, regs); |
1138 | return; | 1171 | goto out; |
1139 | } | 1172 | } |
1140 | 1173 | ||
1141 | force_sig(SIGILL, current); | 1174 | force_sig(SIGILL, current); |
1175 | |||
1176 | out: | ||
1177 | exception_exit(prev_state); | ||
1142 | } | 1178 | } |
1143 | 1179 | ||
1144 | asmlinkage void do_mdmx(struct pt_regs *regs) | 1180 | asmlinkage void do_mdmx(struct pt_regs *regs) |
1145 | { | 1181 | { |
1182 | enum ctx_state prev_state; | ||
1183 | |||
1184 | prev_state = exception_enter(); | ||
1146 | force_sig(SIGILL, current); | 1185 | force_sig(SIGILL, current); |
1186 | exception_exit(prev_state); | ||
1147 | } | 1187 | } |
1148 | 1188 | ||
1149 | /* | 1189 | /* |
@@ -1151,8 +1191,10 @@ asmlinkage void do_mdmx(struct pt_regs *regs) | |||
1151 | */ | 1191 | */ |
1152 | asmlinkage void do_watch(struct pt_regs *regs) | 1192 | asmlinkage void do_watch(struct pt_regs *regs) |
1153 | { | 1193 | { |
1194 | enum ctx_state prev_state; | ||
1154 | u32 cause; | 1195 | u32 cause; |
1155 | 1196 | ||
1197 | prev_state = exception_enter(); | ||
1156 | /* | 1198 | /* |
1157 | * Clear WP (bit 22) bit of cause register so we don't loop | 1199 | * Clear WP (bit 22) bit of cause register so we don't loop |
1158 | * forever. | 1200 | * forever. |
@@ -1174,13 +1216,16 @@ asmlinkage void do_watch(struct pt_regs *regs) | |||
1174 | mips_clear_watch_registers(); | 1216 | mips_clear_watch_registers(); |
1175 | local_irq_enable(); | 1217 | local_irq_enable(); |
1176 | } | 1218 | } |
1219 | exception_exit(prev_state); | ||
1177 | } | 1220 | } |
1178 | 1221 | ||
1179 | asmlinkage void do_mcheck(struct pt_regs *regs) | 1222 | asmlinkage void do_mcheck(struct pt_regs *regs) |
1180 | { | 1223 | { |
1181 | const int field = 2 * sizeof(unsigned long); | 1224 | const int field = 2 * sizeof(unsigned long); |
1182 | int multi_match = regs->cp0_status & ST0_TS; | 1225 | int multi_match = regs->cp0_status & ST0_TS; |
1226 | enum ctx_state prev_state; | ||
1183 | 1227 | ||
1228 | prev_state = exception_enter(); | ||
1184 | show_regs(regs); | 1229 | show_regs(regs); |
1185 | 1230 | ||
1186 | if (multi_match) { | 1231 | if (multi_match) { |
@@ -1202,6 +1247,7 @@ asmlinkage void do_mcheck(struct pt_regs *regs) | |||
1202 | panic("Caught Machine Check exception - %scaused by multiple " | 1247 | panic("Caught Machine Check exception - %scaused by multiple " |
1203 | "matching entries in the TLB.", | 1248 | "matching entries in the TLB.", |
1204 | (multi_match) ? "" : "not "); | 1249 | (multi_match) ? "" : "not "); |
1250 | exception_exit(prev_state); | ||
1205 | } | 1251 | } |
1206 | 1252 | ||
1207 | asmlinkage void do_mt(struct pt_regs *regs) | 1253 | asmlinkage void do_mt(struct pt_regs *regs) |
diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c index 203d8857070d..3eaa02aa8ae0 100644 --- a/arch/mips/kernel/unaligned.c +++ b/arch/mips/kernel/unaligned.c | |||
@@ -72,6 +72,7 @@ | |||
72 | * A store crossing a page boundary might be executed only partially. | 72 | * A store crossing a page boundary might be executed only partially. |
73 | * Undo the partial store in this case. | 73 | * Undo the partial store in this case. |
74 | */ | 74 | */ |
75 | #include <linux/context_tracking.h> | ||
75 | #include <linux/mm.h> | 76 | #include <linux/mm.h> |
76 | #include <linux/signal.h> | 77 | #include <linux/signal.h> |
77 | #include <linux/smp.h> | 78 | #include <linux/smp.h> |
@@ -1550,9 +1551,11 @@ sigill: | |||
1550 | } | 1551 | } |
1551 | asmlinkage void do_ade(struct pt_regs *regs) | 1552 | asmlinkage void do_ade(struct pt_regs *regs) |
1552 | { | 1553 | { |
1554 | enum ctx_state prev_state; | ||
1553 | unsigned int __user *pc; | 1555 | unsigned int __user *pc; |
1554 | mm_segment_t seg; | 1556 | mm_segment_t seg; |
1555 | 1557 | ||
1558 | prev_state = exception_enter(); | ||
1556 | perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, | 1559 | perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, |
1557 | 1, regs, regs->cp0_badvaddr); | 1560 | 1, regs, regs->cp0_badvaddr); |
1558 | /* | 1561 | /* |
@@ -1628,6 +1631,7 @@ sigbus: | |||
1628 | /* | 1631 | /* |
1629 | * XXX On return from the signal handler we should advance the epc | 1632 | * XXX On return from the signal handler we should advance the epc |
1630 | */ | 1633 | */ |
1634 | exception_exit(prev_state); | ||
1631 | } | 1635 | } |
1632 | 1636 | ||
1633 | #ifdef CONFIG_DEBUG_FS | 1637 | #ifdef CONFIG_DEBUG_FS |