diff options
Diffstat (limited to 'arch/mips/kernel/traps.c')
-rw-r--r-- | arch/mips/kernel/traps.c | 104 |
1 files changed, 76 insertions, 28 deletions
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index a75ae40184aa..0903d70b2cfe 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> |
@@ -264,7 +265,7 @@ static void __show_regs(const struct pt_regs *regs) | |||
264 | 265 | ||
265 | printk("Status: %08x ", (uint32_t) regs->cp0_status); | 266 | printk("Status: %08x ", (uint32_t) regs->cp0_status); |
266 | 267 | ||
267 | if (current_cpu_data.isa_level == MIPS_CPU_ISA_I) { | 268 | if (cpu_has_3kex) { |
268 | if (regs->cp0_status & ST0_KUO) | 269 | if (regs->cp0_status & ST0_KUO) |
269 | printk("KUo "); | 270 | printk("KUo "); |
270 | if (regs->cp0_status & ST0_IEO) | 271 | if (regs->cp0_status & ST0_IEO) |
@@ -277,7 +278,7 @@ static void __show_regs(const struct pt_regs *regs) | |||
277 | printk("KUc "); | 278 | printk("KUc "); |
278 | if (regs->cp0_status & ST0_IEC) | 279 | if (regs->cp0_status & ST0_IEC) |
279 | printk("IEc "); | 280 | printk("IEc "); |
280 | } else { | 281 | } else if (cpu_has_4kex) { |
281 | if (regs->cp0_status & ST0_KX) | 282 | if (regs->cp0_status & ST0_KX) |
282 | printk("KX "); | 283 | printk("KX "); |
283 | if (regs->cp0_status & ST0_SX) | 284 | if (regs->cp0_status & ST0_SX) |
@@ -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 | /* |
@@ -1025,21 +1056,16 @@ static int default_cu2_call(struct notifier_block *nfb, unsigned long action, | |||
1025 | { | 1056 | { |
1026 | struct pt_regs *regs = data; | 1057 | struct pt_regs *regs = data; |
1027 | 1058 | ||
1028 | switch (action) { | 1059 | die_if_kernel("COP2: Unhandled kernel unaligned access or invalid " |
1029 | default: | ||
1030 | die_if_kernel("Unhandled kernel unaligned access or invalid " | ||
1031 | "instruction", regs); | 1060 | "instruction", regs); |
1032 | /* Fall through */ | 1061 | force_sig(SIGILL, current); |
1033 | |||
1034 | case CU2_EXCEPTION: | ||
1035 | force_sig(SIGILL, current); | ||
1036 | } | ||
1037 | 1062 | ||
1038 | return NOTIFY_OK; | 1063 | return NOTIFY_OK; |
1039 | } | 1064 | } |
1040 | 1065 | ||
1041 | asmlinkage void do_cpu(struct pt_regs *regs) | 1066 | asmlinkage void do_cpu(struct pt_regs *regs) |
1042 | { | 1067 | { |
1068 | enum ctx_state prev_state; | ||
1043 | unsigned int __user *epc; | 1069 | unsigned int __user *epc; |
1044 | unsigned long old_epc, old31; | 1070 | unsigned long old_epc, old31; |
1045 | unsigned int opcode; | 1071 | unsigned int opcode; |
@@ -1047,10 +1073,12 @@ asmlinkage void do_cpu(struct pt_regs *regs) | |||
1047 | int status; | 1073 | int status; |
1048 | unsigned long __maybe_unused flags; | 1074 | unsigned long __maybe_unused flags; |
1049 | 1075 | ||
1050 | die_if_kernel("do_cpu invoked from kernel context!", regs); | 1076 | prev_state = exception_enter(); |
1051 | |||
1052 | cpid = (regs->cp0_cause >> CAUSEB_CE) & 3; | 1077 | cpid = (regs->cp0_cause >> CAUSEB_CE) & 3; |
1053 | 1078 | ||
1079 | if (cpid != 2) | ||
1080 | die_if_kernel("do_cpu invoked from kernel context!", regs); | ||
1081 | |||
1054 | switch (cpid) { | 1082 | switch (cpid) { |
1055 | case 0: | 1083 | case 0: |
1056 | epc = (unsigned int __user *)exception_epc(regs); | 1084 | epc = (unsigned int __user *)exception_epc(regs); |
@@ -1060,7 +1088,7 @@ asmlinkage void do_cpu(struct pt_regs *regs) | |||
1060 | status = -1; | 1088 | status = -1; |
1061 | 1089 | ||
1062 | if (unlikely(compute_return_epc(regs) < 0)) | 1090 | if (unlikely(compute_return_epc(regs) < 0)) |
1063 | return; | 1091 | goto out; |
1064 | 1092 | ||
1065 | if (get_isa16_mode(regs->cp0_epc)) { | 1093 | if (get_isa16_mode(regs->cp0_epc)) { |
1066 | unsigned short mmop[2] = { 0 }; | 1094 | unsigned short mmop[2] = { 0 }; |
@@ -1093,7 +1121,7 @@ asmlinkage void do_cpu(struct pt_regs *regs) | |||
1093 | force_sig(status, current); | 1121 | force_sig(status, current); |
1094 | } | 1122 | } |
1095 | 1123 | ||
1096 | return; | 1124 | goto out; |
1097 | 1125 | ||
1098 | case 3: | 1126 | case 3: |
1099 | /* | 1127 | /* |
@@ -1131,19 +1159,26 @@ asmlinkage void do_cpu(struct pt_regs *regs) | |||
1131 | mt_ase_fp_affinity(); | 1159 | mt_ase_fp_affinity(); |
1132 | } | 1160 | } |
1133 | 1161 | ||
1134 | return; | 1162 | goto out; |
1135 | 1163 | ||
1136 | case 2: | 1164 | case 2: |
1137 | raw_notifier_call_chain(&cu2_chain, CU2_EXCEPTION, regs); | 1165 | raw_notifier_call_chain(&cu2_chain, CU2_EXCEPTION, regs); |
1138 | return; | 1166 | goto out; |
1139 | } | 1167 | } |
1140 | 1168 | ||
1141 | force_sig(SIGILL, current); | 1169 | force_sig(SIGILL, current); |
1170 | |||
1171 | out: | ||
1172 | exception_exit(prev_state); | ||
1142 | } | 1173 | } |
1143 | 1174 | ||
1144 | asmlinkage void do_mdmx(struct pt_regs *regs) | 1175 | asmlinkage void do_mdmx(struct pt_regs *regs) |
1145 | { | 1176 | { |
1177 | enum ctx_state prev_state; | ||
1178 | |||
1179 | prev_state = exception_enter(); | ||
1146 | force_sig(SIGILL, current); | 1180 | force_sig(SIGILL, current); |
1181 | exception_exit(prev_state); | ||
1147 | } | 1182 | } |
1148 | 1183 | ||
1149 | /* | 1184 | /* |
@@ -1151,8 +1186,10 @@ asmlinkage void do_mdmx(struct pt_regs *regs) | |||
1151 | */ | 1186 | */ |
1152 | asmlinkage void do_watch(struct pt_regs *regs) | 1187 | asmlinkage void do_watch(struct pt_regs *regs) |
1153 | { | 1188 | { |
1189 | enum ctx_state prev_state; | ||
1154 | u32 cause; | 1190 | u32 cause; |
1155 | 1191 | ||
1192 | prev_state = exception_enter(); | ||
1156 | /* | 1193 | /* |
1157 | * Clear WP (bit 22) bit of cause register so we don't loop | 1194 | * Clear WP (bit 22) bit of cause register so we don't loop |
1158 | * forever. | 1195 | * forever. |
@@ -1174,13 +1211,16 @@ asmlinkage void do_watch(struct pt_regs *regs) | |||
1174 | mips_clear_watch_registers(); | 1211 | mips_clear_watch_registers(); |
1175 | local_irq_enable(); | 1212 | local_irq_enable(); |
1176 | } | 1213 | } |
1214 | exception_exit(prev_state); | ||
1177 | } | 1215 | } |
1178 | 1216 | ||
1179 | asmlinkage void do_mcheck(struct pt_regs *regs) | 1217 | asmlinkage void do_mcheck(struct pt_regs *regs) |
1180 | { | 1218 | { |
1181 | const int field = 2 * sizeof(unsigned long); | 1219 | const int field = 2 * sizeof(unsigned long); |
1182 | int multi_match = regs->cp0_status & ST0_TS; | 1220 | int multi_match = regs->cp0_status & ST0_TS; |
1221 | enum ctx_state prev_state; | ||
1183 | 1222 | ||
1223 | prev_state = exception_enter(); | ||
1184 | show_regs(regs); | 1224 | show_regs(regs); |
1185 | 1225 | ||
1186 | if (multi_match) { | 1226 | if (multi_match) { |
@@ -1202,6 +1242,7 @@ asmlinkage void do_mcheck(struct pt_regs *regs) | |||
1202 | panic("Caught Machine Check exception - %scaused by multiple " | 1242 | panic("Caught Machine Check exception - %scaused by multiple " |
1203 | "matching entries in the TLB.", | 1243 | "matching entries in the TLB.", |
1204 | (multi_match) ? "" : "not "); | 1244 | (multi_match) ? "" : "not "); |
1245 | exception_exit(prev_state); | ||
1205 | } | 1246 | } |
1206 | 1247 | ||
1207 | asmlinkage void do_mt(struct pt_regs *regs) | 1248 | asmlinkage void do_mt(struct pt_regs *regs) |
@@ -1627,7 +1668,6 @@ void *set_vi_handler(int n, vi_handler_t addr) | |||
1627 | } | 1668 | } |
1628 | 1669 | ||
1629 | extern void tlb_init(void); | 1670 | extern void tlb_init(void); |
1630 | extern void flush_tlb_handlers(void); | ||
1631 | 1671 | ||
1632 | /* | 1672 | /* |
1633 | * Timer interrupt | 1673 | * Timer interrupt |
@@ -1837,6 +1877,15 @@ void __init trap_init(void) | |||
1837 | ebase += (read_c0_ebase() & 0x3ffff000); | 1877 | ebase += (read_c0_ebase() & 0x3ffff000); |
1838 | } | 1878 | } |
1839 | 1879 | ||
1880 | if (cpu_has_mmips) { | ||
1881 | unsigned int config3 = read_c0_config3(); | ||
1882 | |||
1883 | if (IS_ENABLED(CONFIG_CPU_MICROMIPS)) | ||
1884 | write_c0_config3(config3 | MIPS_CONF3_ISA_OE); | ||
1885 | else | ||
1886 | write_c0_config3(config3 & ~MIPS_CONF3_ISA_OE); | ||
1887 | } | ||
1888 | |||
1840 | if (board_ebase_setup) | 1889 | if (board_ebase_setup) |
1841 | board_ebase_setup(); | 1890 | board_ebase_setup(); |
1842 | per_cpu_trap_init(true); | 1891 | per_cpu_trap_init(true); |
@@ -1956,7 +2005,6 @@ void __init trap_init(void) | |||
1956 | set_handler(0x080, &except_vec3_generic, 0x80); | 2005 | set_handler(0x080, &except_vec3_generic, 0x80); |
1957 | 2006 | ||
1958 | local_flush_icache_range(ebase, ebase + 0x400); | 2007 | local_flush_icache_range(ebase, ebase + 0x400); |
1959 | flush_tlb_handlers(); | ||
1960 | 2008 | ||
1961 | sort_extable(__start___dbe_table, __stop___dbe_table); | 2009 | sort_extable(__start___dbe_table, __stop___dbe_table); |
1962 | 2010 | ||