aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/traps.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kernel/traps.c')
-rw-r--r--arch/mips/kernel/traps.c52
1 files changed, 39 insertions, 13 deletions
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 6bee29097a56..80b9e070c207 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -42,10 +42,14 @@
42#include <asm/tlbdebug.h> 42#include <asm/tlbdebug.h>
43#include <asm/traps.h> 43#include <asm/traps.h>
44#include <asm/uaccess.h> 44#include <asm/uaccess.h>
45#include <asm/watch.h>
45#include <asm/mmu_context.h> 46#include <asm/mmu_context.h>
46#include <asm/types.h> 47#include <asm/types.h>
47#include <asm/stacktrace.h> 48#include <asm/stacktrace.h>
48 49
50extern void check_wait(void);
51extern asmlinkage void r4k_wait(void);
52extern asmlinkage void rollback_handle_int(void);
49extern asmlinkage void handle_int(void); 53extern asmlinkage void handle_int(void);
50extern asmlinkage void handle_tlbm(void); 54extern asmlinkage void handle_tlbm(void);
51extern asmlinkage void handle_tlbl(void); 55extern asmlinkage void handle_tlbl(void);
@@ -822,8 +826,10 @@ static void mt_ase_fp_affinity(void)
822 if (cpus_intersects(current->cpus_allowed, mt_fpu_cpumask)) { 826 if (cpus_intersects(current->cpus_allowed, mt_fpu_cpumask)) {
823 cpumask_t tmask; 827 cpumask_t tmask;
824 828
825 cpus_and(tmask, current->thread.user_cpus_allowed, 829 current->thread.user_cpus_allowed
826 mt_fpu_cpumask); 830 = current->cpus_allowed;
831 cpus_and(tmask, current->cpus_allowed,
832 mt_fpu_cpumask);
827 set_cpus_allowed(current, tmask); 833 set_cpus_allowed(current, tmask);
828 set_thread_flag(TIF_FPUBOUND); 834 set_thread_flag(TIF_FPUBOUND);
829 } 835 }
@@ -907,13 +913,26 @@ asmlinkage void do_mdmx(struct pt_regs *regs)
907 913
908asmlinkage void do_watch(struct pt_regs *regs) 914asmlinkage void do_watch(struct pt_regs *regs)
909{ 915{
916 u32 cause;
917
910 /* 918 /*
911 * We use the watch exception where available to detect stack 919 * Clear WP (bit 22) bit of cause register so we don't loop
912 * overflows. 920 * forever.
913 */ 921 */
914 dump_tlb_all(); 922 cause = read_c0_cause();
915 show_regs(regs); 923 cause &= ~(1 << 22);
916 panic("Caught WATCH exception - probably caused by stack overflow."); 924 write_c0_cause(cause);
925
926 /*
927 * If the current thread has the watch registers loaded, save
928 * their values and send SIGTRAP. Otherwise another thread
929 * left the registers set, clear them and continue.
930 */
931 if (test_tsk_thread_flag(current, TIF_LOAD_WATCH)) {
932 mips_read_watch_registers();
933 force_sig(SIGTRAP, current);
934 } else
935 mips_clear_watch_registers();
917} 936}
918 937
919asmlinkage void do_mcheck(struct pt_regs *regs) 938asmlinkage void do_mcheck(struct pt_regs *regs)
@@ -1251,6 +1270,9 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs)
1251 1270
1252 extern char except_vec_vi, except_vec_vi_lui; 1271 extern char except_vec_vi, except_vec_vi_lui;
1253 extern char except_vec_vi_ori, except_vec_vi_end; 1272 extern char except_vec_vi_ori, except_vec_vi_end;
1273 extern char rollback_except_vec_vi;
1274 char *vec_start = (cpu_wait == r4k_wait) ?
1275 &rollback_except_vec_vi : &except_vec_vi;
1254#ifdef CONFIG_MIPS_MT_SMTC 1276#ifdef CONFIG_MIPS_MT_SMTC
1255 /* 1277 /*
1256 * We need to provide the SMTC vectored interrupt handler 1278 * We need to provide the SMTC vectored interrupt handler
@@ -1258,11 +1280,11 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs)
1258 * Status.IM bit to be masked before going there. 1280 * Status.IM bit to be masked before going there.
1259 */ 1281 */
1260 extern char except_vec_vi_mori; 1282 extern char except_vec_vi_mori;
1261 const int mori_offset = &except_vec_vi_mori - &except_vec_vi; 1283 const int mori_offset = &except_vec_vi_mori - vec_start;
1262#endif /* CONFIG_MIPS_MT_SMTC */ 1284#endif /* CONFIG_MIPS_MT_SMTC */
1263 const int handler_len = &except_vec_vi_end - &except_vec_vi; 1285 const int handler_len = &except_vec_vi_end - vec_start;
1264 const int lui_offset = &except_vec_vi_lui - &except_vec_vi; 1286 const int lui_offset = &except_vec_vi_lui - vec_start;
1265 const int ori_offset = &except_vec_vi_ori - &except_vec_vi; 1287 const int ori_offset = &except_vec_vi_ori - vec_start;
1266 1288
1267 if (handler_len > VECTORSPACING) { 1289 if (handler_len > VECTORSPACING) {
1268 /* 1290 /*
@@ -1272,7 +1294,7 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs)
1272 panic("VECTORSPACING too small"); 1294 panic("VECTORSPACING too small");
1273 } 1295 }
1274 1296
1275 memcpy(b, &except_vec_vi, handler_len); 1297 memcpy(b, vec_start, handler_len);
1276#ifdef CONFIG_MIPS_MT_SMTC 1298#ifdef CONFIG_MIPS_MT_SMTC
1277 BUG_ON(n > 7); /* Vector index %d exceeds SMTC maximum. */ 1299 BUG_ON(n > 7); /* Vector index %d exceeds SMTC maximum. */
1278 1300
@@ -1554,6 +1576,10 @@ void __init trap_init(void)
1554 extern char except_vec3_generic, except_vec3_r4000; 1576 extern char except_vec3_generic, except_vec3_r4000;
1555 extern char except_vec4; 1577 extern char except_vec4;
1556 unsigned long i; 1578 unsigned long i;
1579 int rollback;
1580
1581 check_wait();
1582 rollback = (cpu_wait == r4k_wait);
1557 1583
1558#if defined(CONFIG_KGDB) 1584#if defined(CONFIG_KGDB)
1559 if (kgdb_early_setup) 1585 if (kgdb_early_setup)
@@ -1618,7 +1644,7 @@ void __init trap_init(void)
1618 if (board_be_init) 1644 if (board_be_init)
1619 board_be_init(); 1645 board_be_init();
1620 1646
1621 set_except_vector(0, handle_int); 1647 set_except_vector(0, rollback ? rollback_handle_int : handle_int);
1622 set_except_vector(1, handle_tlbm); 1648 set_except_vector(1, handle_tlbm);
1623 set_except_vector(2, handle_tlbl); 1649 set_except_vector(2, handle_tlbl);
1624 set_except_vector(3, handle_tlbs); 1650 set_except_vector(3, handle_tlbs);