diff options
Diffstat (limited to 'arch/mips/kernel/traps.c')
-rw-r--r-- | arch/mips/kernel/traps.c | 71 |
1 files changed, 58 insertions, 13 deletions
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index f9c8746be8d6..e0b499694d18 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c | |||
@@ -78,6 +78,7 @@ extern asmlinkage void handle_cpu(void); | |||
78 | extern asmlinkage void handle_ov(void); | 78 | extern asmlinkage void handle_ov(void); |
79 | extern asmlinkage void handle_tr(void); | 79 | extern asmlinkage void handle_tr(void); |
80 | extern asmlinkage void handle_fpe(void); | 80 | extern asmlinkage void handle_fpe(void); |
81 | extern asmlinkage void handle_ftlb(void); | ||
81 | extern asmlinkage void handle_mdmx(void); | 82 | extern asmlinkage void handle_mdmx(void); |
82 | extern asmlinkage void handle_watch(void); | 83 | extern asmlinkage void handle_watch(void); |
83 | extern asmlinkage void handle_mt(void); | 84 | extern asmlinkage void handle_mt(void); |
@@ -1080,7 +1081,7 @@ asmlinkage void do_cpu(struct pt_regs *regs) | |||
1080 | unsigned long old_epc, old31; | 1081 | unsigned long old_epc, old31; |
1081 | unsigned int opcode; | 1082 | unsigned int opcode; |
1082 | unsigned int cpid; | 1083 | unsigned int cpid; |
1083 | int status; | 1084 | int status, err; |
1084 | unsigned long __maybe_unused flags; | 1085 | unsigned long __maybe_unused flags; |
1085 | 1086 | ||
1086 | prev_state = exception_enter(); | 1087 | prev_state = exception_enter(); |
@@ -1153,19 +1154,19 @@ asmlinkage void do_cpu(struct pt_regs *regs) | |||
1153 | 1154 | ||
1154 | case 1: | 1155 | case 1: |
1155 | if (used_math()) /* Using the FPU again. */ | 1156 | if (used_math()) /* Using the FPU again. */ |
1156 | own_fpu(1); | 1157 | err = own_fpu(1); |
1157 | else { /* First time FPU user. */ | 1158 | else { /* First time FPU user. */ |
1158 | init_fpu(); | 1159 | err = init_fpu(); |
1159 | set_used_math(); | 1160 | set_used_math(); |
1160 | } | 1161 | } |
1161 | 1162 | ||
1162 | if (!raw_cpu_has_fpu) { | 1163 | if (!raw_cpu_has_fpu || err) { |
1163 | int sig; | 1164 | int sig; |
1164 | void __user *fault_addr = NULL; | 1165 | void __user *fault_addr = NULL; |
1165 | sig = fpu_emulator_cop1Handler(regs, | 1166 | sig = fpu_emulator_cop1Handler(regs, |
1166 | ¤t->thread.fpu, | 1167 | ¤t->thread.fpu, |
1167 | 0, &fault_addr); | 1168 | 0, &fault_addr); |
1168 | if (!process_fpemu_return(sig, fault_addr)) | 1169 | if (!process_fpemu_return(sig, fault_addr) && !err) |
1169 | mt_ase_fp_affinity(); | 1170 | mt_ase_fp_affinity(); |
1170 | } | 1171 | } |
1171 | 1172 | ||
@@ -1336,6 +1337,8 @@ static inline void parity_protection_init(void) | |||
1336 | case CPU_34K: | 1337 | case CPU_34K: |
1337 | case CPU_74K: | 1338 | case CPU_74K: |
1338 | case CPU_1004K: | 1339 | case CPU_1004K: |
1340 | case CPU_INTERAPTIV: | ||
1341 | case CPU_PROAPTIV: | ||
1339 | { | 1342 | { |
1340 | #define ERRCTL_PE 0x80000000 | 1343 | #define ERRCTL_PE 0x80000000 |
1341 | #define ERRCTL_L2P 0x00800000 | 1344 | #define ERRCTL_L2P 0x00800000 |
@@ -1425,14 +1428,27 @@ asmlinkage void cache_parity_error(void) | |||
1425 | printk("Decoded c0_cacheerr: %s cache fault in %s reference.\n", | 1428 | printk("Decoded c0_cacheerr: %s cache fault in %s reference.\n", |
1426 | reg_val & (1<<30) ? "secondary" : "primary", | 1429 | reg_val & (1<<30) ? "secondary" : "primary", |
1427 | reg_val & (1<<31) ? "data" : "insn"); | 1430 | reg_val & (1<<31) ? "data" : "insn"); |
1428 | printk("Error bits: %s%s%s%s%s%s%s\n", | 1431 | if (cpu_has_mips_r2 && |
1429 | reg_val & (1<<29) ? "ED " : "", | 1432 | ((current_cpu_data.processor_id && 0xff0000) == PRID_COMP_MIPS)) { |
1430 | reg_val & (1<<28) ? "ET " : "", | 1433 | pr_err("Error bits: %s%s%s%s%s%s%s%s\n", |
1431 | reg_val & (1<<26) ? "EE " : "", | 1434 | reg_val & (1<<29) ? "ED " : "", |
1432 | reg_val & (1<<25) ? "EB " : "", | 1435 | reg_val & (1<<28) ? "ET " : "", |
1433 | reg_val & (1<<24) ? "EI " : "", | 1436 | reg_val & (1<<27) ? "ES " : "", |
1434 | reg_val & (1<<23) ? "E1 " : "", | 1437 | reg_val & (1<<26) ? "EE " : "", |
1435 | reg_val & (1<<22) ? "E0 " : ""); | 1438 | reg_val & (1<<25) ? "EB " : "", |
1439 | reg_val & (1<<24) ? "EI " : "", | ||
1440 | reg_val & (1<<23) ? "E1 " : "", | ||
1441 | reg_val & (1<<22) ? "E0 " : ""); | ||
1442 | } else { | ||
1443 | pr_err("Error bits: %s%s%s%s%s%s%s\n", | ||
1444 | reg_val & (1<<29) ? "ED " : "", | ||
1445 | reg_val & (1<<28) ? "ET " : "", | ||
1446 | reg_val & (1<<26) ? "EE " : "", | ||
1447 | reg_val & (1<<25) ? "EB " : "", | ||
1448 | reg_val & (1<<24) ? "EI " : "", | ||
1449 | reg_val & (1<<23) ? "E1 " : "", | ||
1450 | reg_val & (1<<22) ? "E0 " : ""); | ||
1451 | } | ||
1436 | printk("IDX: 0x%08x\n", reg_val & ((1<<22)-1)); | 1452 | printk("IDX: 0x%08x\n", reg_val & ((1<<22)-1)); |
1437 | 1453 | ||
1438 | #if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64) | 1454 | #if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64) |
@@ -1446,6 +1462,34 @@ asmlinkage void cache_parity_error(void) | |||
1446 | panic("Can't handle the cache error!"); | 1462 | panic("Can't handle the cache error!"); |
1447 | } | 1463 | } |
1448 | 1464 | ||
1465 | asmlinkage void do_ftlb(void) | ||
1466 | { | ||
1467 | const int field = 2 * sizeof(unsigned long); | ||
1468 | unsigned int reg_val; | ||
1469 | |||
1470 | /* For the moment, report the problem and hang. */ | ||
1471 | if (cpu_has_mips_r2 && | ||
1472 | ((current_cpu_data.processor_id && 0xff0000) == PRID_COMP_MIPS)) { | ||
1473 | pr_err("FTLB error exception, cp0_ecc=0x%08x:\n", | ||
1474 | read_c0_ecc()); | ||
1475 | pr_err("cp0_errorepc == %0*lx\n", field, read_c0_errorepc()); | ||
1476 | reg_val = read_c0_cacheerr(); | ||
1477 | pr_err("c0_cacheerr == %08x\n", reg_val); | ||
1478 | |||
1479 | if ((reg_val & 0xc0000000) == 0xc0000000) { | ||
1480 | pr_err("Decoded c0_cacheerr: FTLB parity error\n"); | ||
1481 | } else { | ||
1482 | pr_err("Decoded c0_cacheerr: %s cache fault in %s reference.\n", | ||
1483 | reg_val & (1<<30) ? "secondary" : "primary", | ||
1484 | reg_val & (1<<31) ? "data" : "insn"); | ||
1485 | } | ||
1486 | } else { | ||
1487 | pr_err("FTLB error exception\n"); | ||
1488 | } | ||
1489 | /* Just print the cacheerr bits for now */ | ||
1490 | cache_parity_error(); | ||
1491 | } | ||
1492 | |||
1449 | /* | 1493 | /* |
1450 | * SDBBP EJTAG debug exception handler. | 1494 | * SDBBP EJTAG debug exception handler. |
1451 | * We skip the instruction and return to the next instruction. | 1495 | * We skip the instruction and return to the next instruction. |
@@ -1995,6 +2039,7 @@ void __init trap_init(void) | |||
1995 | if (cpu_has_fpu && !cpu_has_nofpuex) | 2039 | if (cpu_has_fpu && !cpu_has_nofpuex) |
1996 | set_except_vector(15, handle_fpe); | 2040 | set_except_vector(15, handle_fpe); |
1997 | 2041 | ||
2042 | set_except_vector(16, handle_ftlb); | ||
1998 | set_except_vector(22, handle_mdmx); | 2043 | set_except_vector(22, handle_mdmx); |
1999 | 2044 | ||
2000 | if (cpu_has_mcheck) | 2045 | if (cpu_has_mcheck) |