aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/traps.c
diff options
context:
space:
mode:
authorJames Morris <jmorris@namei.org>2008-09-21 20:41:56 -0400
committerJames Morris <jmorris@namei.org>2008-09-21 20:41:56 -0400
commitab2b49518e743962f71b94246855c44ee9cf52cc (patch)
tree26b260a350f0a0a0d19b558bf147b812e3a1564c /arch/mips/kernel/traps.c
parentf058925b201357fba48d56cc9c1719ae274b2022 (diff)
parent72d31053f62c4bc464c2783974926969614a8649 (diff)
Merge branch 'master' into next
Conflicts: MAINTAINERS Thanks for breaking my tree :-) Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'arch/mips/kernel/traps.c')
-rw-r--r--arch/mips/kernel/traps.c40
1 files changed, 27 insertions, 13 deletions
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 426cced1e9dc..5fd0cd020af5 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -46,6 +46,9 @@
46#include <asm/types.h> 46#include <asm/types.h>
47#include <asm/stacktrace.h> 47#include <asm/stacktrace.h>
48 48
49extern void check_wait(void);
50extern asmlinkage void r4k_wait(void);
51extern asmlinkage void rollback_handle_int(void);
49extern asmlinkage void handle_int(void); 52extern asmlinkage void handle_int(void);
50extern asmlinkage void handle_tlbm(void); 53extern asmlinkage void handle_tlbm(void);
51extern asmlinkage void handle_tlbl(void); 54extern asmlinkage void handle_tlbl(void);
@@ -373,8 +376,8 @@ void __noreturn die(const char * str, const struct pt_regs * regs)
373 do_exit(SIGSEGV); 376 do_exit(SIGSEGV);
374} 377}
375 378
376extern const struct exception_table_entry __start___dbe_table[]; 379extern struct exception_table_entry __start___dbe_table[];
377extern const struct exception_table_entry __stop___dbe_table[]; 380extern struct exception_table_entry __stop___dbe_table[];
378 381
379__asm__( 382__asm__(
380" .section __dbe_table, \"a\"\n" 383" .section __dbe_table, \"a\"\n"
@@ -1200,7 +1203,7 @@ void *set_except_vector(int n, void *addr)
1200 if (n == 0 && cpu_has_divec) { 1203 if (n == 0 && cpu_has_divec) {
1201 *(u32 *)(ebase + 0x200) = 0x08000000 | 1204 *(u32 *)(ebase + 0x200) = 0x08000000 |
1202 (0x03ffffff & (handler >> 2)); 1205 (0x03ffffff & (handler >> 2));
1203 flush_icache_range(ebase + 0x200, ebase + 0x204); 1206 local_flush_icache_range(ebase + 0x200, ebase + 0x204);
1204 } 1207 }
1205 return (void *)old_handler; 1208 return (void *)old_handler;
1206} 1209}
@@ -1251,6 +1254,9 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs)
1251 1254
1252 extern char except_vec_vi, except_vec_vi_lui; 1255 extern char except_vec_vi, except_vec_vi_lui;
1253 extern char except_vec_vi_ori, except_vec_vi_end; 1256 extern char except_vec_vi_ori, except_vec_vi_end;
1257 extern char rollback_except_vec_vi;
1258 char *vec_start = (cpu_wait == r4k_wait) ?
1259 &rollback_except_vec_vi : &except_vec_vi;
1254#ifdef CONFIG_MIPS_MT_SMTC 1260#ifdef CONFIG_MIPS_MT_SMTC
1255 /* 1261 /*
1256 * We need to provide the SMTC vectored interrupt handler 1262 * We need to provide the SMTC vectored interrupt handler
@@ -1258,11 +1264,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. 1264 * Status.IM bit to be masked before going there.
1259 */ 1265 */
1260 extern char except_vec_vi_mori; 1266 extern char except_vec_vi_mori;
1261 const int mori_offset = &except_vec_vi_mori - &except_vec_vi; 1267 const int mori_offset = &except_vec_vi_mori - vec_start;
1262#endif /* CONFIG_MIPS_MT_SMTC */ 1268#endif /* CONFIG_MIPS_MT_SMTC */
1263 const int handler_len = &except_vec_vi_end - &except_vec_vi; 1269 const int handler_len = &except_vec_vi_end - vec_start;
1264 const int lui_offset = &except_vec_vi_lui - &except_vec_vi; 1270 const int lui_offset = &except_vec_vi_lui - vec_start;
1265 const int ori_offset = &except_vec_vi_ori - &except_vec_vi; 1271 const int ori_offset = &except_vec_vi_ori - vec_start;
1266 1272
1267 if (handler_len > VECTORSPACING) { 1273 if (handler_len > VECTORSPACING) {
1268 /* 1274 /*
@@ -1272,7 +1278,7 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs)
1272 panic("VECTORSPACING too small"); 1278 panic("VECTORSPACING too small");
1273 } 1279 }
1274 1280
1275 memcpy(b, &except_vec_vi, handler_len); 1281 memcpy(b, vec_start, handler_len);
1276#ifdef CONFIG_MIPS_MT_SMTC 1282#ifdef CONFIG_MIPS_MT_SMTC
1277 BUG_ON(n > 7); /* Vector index %d exceeds SMTC maximum. */ 1283 BUG_ON(n > 7); /* Vector index %d exceeds SMTC maximum. */
1278 1284
@@ -1283,7 +1289,8 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs)
1283 *w = (*w & 0xffff0000) | (((u32)handler >> 16) & 0xffff); 1289 *w = (*w & 0xffff0000) | (((u32)handler >> 16) & 0xffff);
1284 w = (u32 *)(b + ori_offset); 1290 w = (u32 *)(b + ori_offset);
1285 *w = (*w & 0xffff0000) | ((u32)handler & 0xffff); 1291 *w = (*w & 0xffff0000) | ((u32)handler & 0xffff);
1286 flush_icache_range((unsigned long)b, (unsigned long)(b+handler_len)); 1292 local_flush_icache_range((unsigned long)b,
1293 (unsigned long)(b+handler_len));
1287 } 1294 }
1288 else { 1295 else {
1289 /* 1296 /*
@@ -1295,7 +1302,8 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs)
1295 w = (u32 *)b; 1302 w = (u32 *)b;
1296 *w++ = 0x08000000 | (((u32)handler >> 2) & 0x03fffff); /* j handler */ 1303 *w++ = 0x08000000 | (((u32)handler >> 2) & 0x03fffff); /* j handler */
1297 *w = 0; 1304 *w = 0;
1298 flush_icache_range((unsigned long)b, (unsigned long)(b+8)); 1305 local_flush_icache_range((unsigned long)b,
1306 (unsigned long)(b+8));
1299 } 1307 }
1300 1308
1301 return (void *)old_handler; 1309 return (void *)old_handler;
@@ -1515,7 +1523,7 @@ void __cpuinit per_cpu_trap_init(void)
1515void __init set_handler(unsigned long offset, void *addr, unsigned long size) 1523void __init set_handler(unsigned long offset, void *addr, unsigned long size)
1516{ 1524{
1517 memcpy((void *)(ebase + offset), addr, size); 1525 memcpy((void *)(ebase + offset), addr, size);
1518 flush_icache_range(ebase + offset, ebase + offset + size); 1526 local_flush_icache_range(ebase + offset, ebase + offset + size);
1519} 1527}
1520 1528
1521static char panic_null_cerr[] __cpuinitdata = 1529static char panic_null_cerr[] __cpuinitdata =
@@ -1552,6 +1560,10 @@ void __init trap_init(void)
1552 extern char except_vec3_generic, except_vec3_r4000; 1560 extern char except_vec3_generic, except_vec3_r4000;
1553 extern char except_vec4; 1561 extern char except_vec4;
1554 unsigned long i; 1562 unsigned long i;
1563 int rollback;
1564
1565 check_wait();
1566 rollback = (cpu_wait == r4k_wait);
1555 1567
1556#if defined(CONFIG_KGDB) 1568#if defined(CONFIG_KGDB)
1557 if (kgdb_early_setup) 1569 if (kgdb_early_setup)
@@ -1616,7 +1628,7 @@ void __init trap_init(void)
1616 if (board_be_init) 1628 if (board_be_init)
1617 board_be_init(); 1629 board_be_init();
1618 1630
1619 set_except_vector(0, handle_int); 1631 set_except_vector(0, rollback ? rollback_handle_int : handle_int);
1620 set_except_vector(1, handle_tlbm); 1632 set_except_vector(1, handle_tlbm);
1621 set_except_vector(2, handle_tlbl); 1633 set_except_vector(2, handle_tlbl);
1622 set_except_vector(3, handle_tlbs); 1634 set_except_vector(3, handle_tlbs);
@@ -1680,6 +1692,8 @@ void __init trap_init(void)
1680 signal32_init(); 1692 signal32_init();
1681#endif 1693#endif
1682 1694
1683 flush_icache_range(ebase, ebase + 0x400); 1695 local_flush_icache_range(ebase, ebase + 0x400);
1684 flush_tlb_handlers(); 1696 flush_tlb_handlers();
1697
1698 sort_extable(__start___dbe_table, __stop___dbe_table);
1685} 1699}