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.c66
1 files changed, 60 insertions, 6 deletions
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 22b19c275044..ad3d2031c327 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -724,6 +724,50 @@ int process_fpemu_return(int sig, void __user *fault_addr)
724 } 724 }
725} 725}
726 726
727static int simulate_fp(struct pt_regs *regs, unsigned int opcode,
728 unsigned long old_epc, unsigned long old_ra)
729{
730 union mips_instruction inst = { .word = opcode };
731 void __user *fault_addr = NULL;
732 int sig;
733
734 /* If it's obviously not an FP instruction, skip it */
735 switch (inst.i_format.opcode) {
736 case cop1_op:
737 case cop1x_op:
738 case lwc1_op:
739 case ldc1_op:
740 case swc1_op:
741 case sdc1_op:
742 break;
743
744 default:
745 return -1;
746 }
747
748 /*
749 * do_ri skipped over the instruction via compute_return_epc, undo
750 * that for the FPU emulator.
751 */
752 regs->cp0_epc = old_epc;
753 regs->regs[31] = old_ra;
754
755 /* Save the FP context to struct thread_struct */
756 lose_fpu(1);
757
758 /* Run the emulator */
759 sig = fpu_emulator_cop1Handler(regs, &current->thread.fpu, 1,
760 &fault_addr);
761
762 /* If something went wrong, signal */
763 process_fpemu_return(sig, fault_addr);
764
765 /* Restore the hardware register state */
766 own_fpu(1);
767
768 return 0;
769}
770
727/* 771/*
728 * XXX Delayed fp exceptions when doing a lazy ctx switch XXX 772 * XXX Delayed fp exceptions when doing a lazy ctx switch XXX
729 */ 773 */
@@ -1016,6 +1060,9 @@ asmlinkage void do_ri(struct pt_regs *regs)
1016 1060
1017 if (status < 0) 1061 if (status < 0)
1018 status = simulate_sync(regs, opcode); 1062 status = simulate_sync(regs, opcode);
1063
1064 if (status < 0)
1065 status = simulate_fp(regs, opcode, old_epc, old31);
1019 } 1066 }
1020 1067
1021 if (status < 0) 1068 if (status < 0)
@@ -1380,12 +1427,19 @@ asmlinkage void do_mcheck(struct pt_regs *regs)
1380 show_regs(regs); 1427 show_regs(regs);
1381 1428
1382 if (multi_match) { 1429 if (multi_match) {
1383 printk("Index : %0x\n", read_c0_index()); 1430 pr_err("Index : %0x\n", read_c0_index());
1384 printk("Pagemask: %0x\n", read_c0_pagemask()); 1431 pr_err("Pagemask: %0x\n", read_c0_pagemask());
1385 printk("EntryHi : %0*lx\n", field, read_c0_entryhi()); 1432 pr_err("EntryHi : %0*lx\n", field, read_c0_entryhi());
1386 printk("EntryLo0: %0*lx\n", field, read_c0_entrylo0()); 1433 pr_err("EntryLo0: %0*lx\n", field, read_c0_entrylo0());
1387 printk("EntryLo1: %0*lx\n", field, read_c0_entrylo1()); 1434 pr_err("EntryLo1: %0*lx\n", field, read_c0_entrylo1());
1388 printk("\n"); 1435 pr_err("Wired : %0x\n", read_c0_wired());
1436 pr_err("Pagegrain: %0x\n", read_c0_pagegrain());
1437 if (cpu_has_htw) {
1438 pr_err("PWField : %0*lx\n", field, read_c0_pwfield());
1439 pr_err("PWSize : %0*lx\n", field, read_c0_pwsize());
1440 pr_err("PWCtl : %0x\n", read_c0_pwctl());
1441 }
1442 pr_err("\n");
1389 dump_tlb_all(); 1443 dump_tlb_all();
1390 } 1444 }
1391 1445