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.c70
1 files changed, 50 insertions, 20 deletions
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 426cced1e9dc..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);
@@ -373,8 +377,8 @@ void __noreturn die(const char * str, const struct pt_regs * regs)
373 do_exit(SIGSEGV); 377 do_exit(SIGSEGV);
374} 378}
375 379
376extern const struct exception_table_entry __start___dbe_table[]; 380extern struct exception_table_entry __start___dbe_table[];
377extern const struct exception_table_entry __stop___dbe_table[]; 381extern struct exception_table_entry __stop___dbe_table[];
378 382
379__asm__( 383__asm__(
380" .section __dbe_table, \"a\"\n" 384" .section __dbe_table, \"a\"\n"
@@ -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)
@@ -1200,7 +1219,7 @@ void *set_except_vector(int n, void *addr)
1200 if (n == 0 && cpu_has_divec) { 1219 if (n == 0 && cpu_has_divec) {
1201 *(u32 *)(ebase + 0x200) = 0x08000000 | 1220 *(u32 *)(ebase + 0x200) = 0x08000000 |
1202 (0x03ffffff & (handler >> 2)); 1221 (0x03ffffff & (handler >> 2));
1203 flush_icache_range(ebase + 0x200, ebase + 0x204); 1222 local_flush_icache_range(ebase + 0x200, ebase + 0x204);
1204 } 1223 }
1205 return (void *)old_handler; 1224 return (void *)old_handler;
1206} 1225}
@@ -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
@@ -1283,7 +1305,8 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs)
1283 *w = (*w & 0xffff0000) | (((u32)handler >> 16) & 0xffff); 1305 *w = (*w & 0xffff0000) | (((u32)handler >> 16) & 0xffff);
1284 w = (u32 *)(b + ori_offset); 1306 w = (u32 *)(b + ori_offset);
1285 *w = (*w & 0xffff0000) | ((u32)handler & 0xffff); 1307 *w = (*w & 0xffff0000) | ((u32)handler & 0xffff);
1286 flush_icache_range((unsigned long)b, (unsigned long)(b+handler_len)); 1308 local_flush_icache_range((unsigned long)b,
1309 (unsigned long)(b+handler_len));
1287 } 1310 }
1288 else { 1311 else {
1289 /* 1312 /*
@@ -1295,7 +1318,8 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs)
1295 w = (u32 *)b; 1318 w = (u32 *)b;
1296 *w++ = 0x08000000 | (((u32)handler >> 2) & 0x03fffff); /* j handler */ 1319 *w++ = 0x08000000 | (((u32)handler >> 2) & 0x03fffff); /* j handler */
1297 *w = 0; 1320 *w = 0;
1298 flush_icache_range((unsigned long)b, (unsigned long)(b+8)); 1321 local_flush_icache_range((unsigned long)b,
1322 (unsigned long)(b+8));
1299 } 1323 }
1300 1324
1301 return (void *)old_handler; 1325 return (void *)old_handler;
@@ -1515,7 +1539,7 @@ void __cpuinit per_cpu_trap_init(void)
1515void __init set_handler(unsigned long offset, void *addr, unsigned long size) 1539void __init set_handler(unsigned long offset, void *addr, unsigned long size)
1516{ 1540{
1517 memcpy((void *)(ebase + offset), addr, size); 1541 memcpy((void *)(ebase + offset), addr, size);
1518 flush_icache_range(ebase + offset, ebase + offset + size); 1542 local_flush_icache_range(ebase + offset, ebase + offset + size);
1519} 1543}
1520 1544
1521static char panic_null_cerr[] __cpuinitdata = 1545static char panic_null_cerr[] __cpuinitdata =
@@ -1552,6 +1576,10 @@ void __init trap_init(void)
1552 extern char except_vec3_generic, except_vec3_r4000; 1576 extern char except_vec3_generic, except_vec3_r4000;
1553 extern char except_vec4; 1577 extern char except_vec4;
1554 unsigned long i; 1578 unsigned long i;
1579 int rollback;
1580
1581 check_wait();
1582 rollback = (cpu_wait == r4k_wait);
1555 1583
1556#if defined(CONFIG_KGDB) 1584#if defined(CONFIG_KGDB)
1557 if (kgdb_early_setup) 1585 if (kgdb_early_setup)
@@ -1616,7 +1644,7 @@ void __init trap_init(void)
1616 if (board_be_init) 1644 if (board_be_init)
1617 board_be_init(); 1645 board_be_init();
1618 1646
1619 set_except_vector(0, handle_int); 1647 set_except_vector(0, rollback ? rollback_handle_int : handle_int);
1620 set_except_vector(1, handle_tlbm); 1648 set_except_vector(1, handle_tlbm);
1621 set_except_vector(2, handle_tlbl); 1649 set_except_vector(2, handle_tlbl);
1622 set_except_vector(3, handle_tlbs); 1650 set_except_vector(3, handle_tlbs);
@@ -1680,6 +1708,8 @@ void __init trap_init(void)
1680 signal32_init(); 1708 signal32_init();
1681#endif 1709#endif
1682 1710
1683 flush_icache_range(ebase, ebase + 0x400); 1711 local_flush_icache_range(ebase, ebase + 0x400);
1684 flush_tlb_handlers(); 1712 flush_tlb_handlers();
1713
1714 sort_extable(__start___dbe_table, __stop___dbe_table);
1685} 1715}