aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/traps.c
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /arch/mips/kernel/traps.c
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'arch/mips/kernel/traps.c')
-rw-r--r--arch/mips/kernel/traps.c85
1 files changed, 61 insertions, 24 deletions
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 03ec0019032b..e9b3af27d844 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -28,6 +28,8 @@
28#include <linux/kprobes.h> 28#include <linux/kprobes.h>
29#include <linux/notifier.h> 29#include <linux/notifier.h>
30#include <linux/kdb.h> 30#include <linux/kdb.h>
31#include <linux/irq.h>
32#include <linux/perf_event.h>
31 33
32#include <asm/bootinfo.h> 34#include <asm/bootinfo.h>
33#include <asm/branch.h> 35#include <asm/branch.h>
@@ -51,7 +53,6 @@
51#include <asm/mmu_context.h> 53#include <asm/mmu_context.h>
52#include <asm/types.h> 54#include <asm/types.h>
53#include <asm/stacktrace.h> 55#include <asm/stacktrace.h>
54#include <asm/irq.h>
55#include <asm/uasm.h> 56#include <asm/uasm.h>
56 57
57extern void check_wait(void); 58extern void check_wait(void);
@@ -82,7 +83,8 @@ extern asmlinkage void handle_mcheck(void);
82extern asmlinkage void handle_reserved(void); 83extern asmlinkage void handle_reserved(void);
83 84
84extern int fpu_emulator_cop1Handler(struct pt_regs *xcp, 85extern int fpu_emulator_cop1Handler(struct pt_regs *xcp,
85 struct mips_fpu_struct *ctx, int has_fpu); 86 struct mips_fpu_struct *ctx, int has_fpu,
87 void *__user *fault_addr);
86 88
87void (*board_be_init)(void); 89void (*board_be_init)(void);
88int (*board_be_handler)(struct pt_regs *regs, int is_fixup); 90int (*board_be_handler)(struct pt_regs *regs, int is_fixup);
@@ -372,7 +374,8 @@ void __noreturn die(const char *str, struct pt_regs *regs)
372 unsigned long dvpret = dvpe(); 374 unsigned long dvpret = dvpe();
373#endif /* CONFIG_MIPS_MT_SMTC */ 375#endif /* CONFIG_MIPS_MT_SMTC */
374 376
375 notify_die(DIE_OOPS, str, regs, 0, regs_to_trapnr(regs), SIGSEGV); 377 if (notify_die(DIE_OOPS, str, regs, 0, regs_to_trapnr(regs), SIGSEGV) == NOTIFY_STOP)
378 sig = 0;
376 379
377 console_verbose(); 380 console_verbose();
378 spin_lock_irq(&die_lock); 381 spin_lock_irq(&die_lock);
@@ -381,9 +384,6 @@ void __noreturn die(const char *str, struct pt_regs *regs)
381 mips_mt_regdump(dvpret); 384 mips_mt_regdump(dvpret);
382#endif /* CONFIG_MIPS_MT_SMTC */ 385#endif /* CONFIG_MIPS_MT_SMTC */
383 386
384 if (notify_die(DIE_OOPS, str, regs, 0, regs_to_trapnr(regs), SIGSEGV) == NOTIFY_STOP)
385 sig = 0;
386
387 printk("%s[#%d]:\n", str, ++die_counter); 387 printk("%s[#%d]:\n", str, ++die_counter);
388 show_registers(regs); 388 show_registers(regs);
389 add_taint(TAINT_DIE); 389 add_taint(TAINT_DIE);
@@ -576,10 +576,16 @@ static inline int simulate_sc(struct pt_regs *regs, unsigned int opcode)
576 */ 576 */
577static int simulate_llsc(struct pt_regs *regs, unsigned int opcode) 577static int simulate_llsc(struct pt_regs *regs, unsigned int opcode)
578{ 578{
579 if ((opcode & OPCODE) == LL) 579 if ((opcode & OPCODE) == LL) {
580 perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS,
581 1, 0, regs, 0);
580 return simulate_ll(regs, opcode); 582 return simulate_ll(regs, opcode);
581 if ((opcode & OPCODE) == SC) 583 }
584 if ((opcode & OPCODE) == SC) {
585 perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS,
586 1, 0, regs, 0);
582 return simulate_sc(regs, opcode); 587 return simulate_sc(regs, opcode);
588 }
583 589
584 return -1; /* Must be something else ... */ 590 return -1; /* Must be something else ... */
585} 591}
@@ -595,6 +601,8 @@ static int simulate_rdhwr(struct pt_regs *regs, unsigned int opcode)
595 if ((opcode & OPCODE) == SPEC3 && (opcode & FUNC) == RDHWR) { 601 if ((opcode & OPCODE) == SPEC3 && (opcode & FUNC) == RDHWR) {
596 int rd = (opcode & RD) >> 11; 602 int rd = (opcode & RD) >> 11;
597 int rt = (opcode & RT) >> 16; 603 int rt = (opcode & RT) >> 16;
604 perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS,
605 1, 0, regs, 0);
598 switch (rd) { 606 switch (rd) {
599 case 0: /* CPU number */ 607 case 0: /* CPU number */
600 regs->regs[rt] = smp_processor_id(); 608 regs->regs[rt] = smp_processor_id();
@@ -630,8 +638,11 @@ static int simulate_rdhwr(struct pt_regs *regs, unsigned int opcode)
630 638
631static int simulate_sync(struct pt_regs *regs, unsigned int opcode) 639static int simulate_sync(struct pt_regs *regs, unsigned int opcode)
632{ 640{
633 if ((opcode & OPCODE) == SPEC0 && (opcode & FUNC) == SYNC) 641 if ((opcode & OPCODE) == SPEC0 && (opcode & FUNC) == SYNC) {
642 perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS,
643 1, 0, regs, 0);
634 return 0; 644 return 0;
645 }
635 646
636 return -1; /* Must be something else ... */ 647 return -1; /* Must be something else ... */
637} 648}
@@ -649,12 +660,36 @@ asmlinkage void do_ov(struct pt_regs *regs)
649 force_sig_info(SIGFPE, &info, current); 660 force_sig_info(SIGFPE, &info, current);
650} 661}
651 662
663static int process_fpemu_return(int sig, void __user *fault_addr)
664{
665 if (sig == SIGSEGV || sig == SIGBUS) {
666 struct siginfo si = {0};
667 si.si_addr = fault_addr;
668 si.si_signo = sig;
669 if (sig == SIGSEGV) {
670 if (find_vma(current->mm, (unsigned long)fault_addr))
671 si.si_code = SEGV_ACCERR;
672 else
673 si.si_code = SEGV_MAPERR;
674 } else {
675 si.si_code = BUS_ADRERR;
676 }
677 force_sig_info(sig, &si, current);
678 return 1;
679 } else if (sig) {
680 force_sig(sig, current);
681 return 1;
682 } else {
683 return 0;
684 }
685}
686
652/* 687/*
653 * XXX Delayed fp exceptions when doing a lazy ctx switch XXX 688 * XXX Delayed fp exceptions when doing a lazy ctx switch XXX
654 */ 689 */
655asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) 690asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
656{ 691{
657 siginfo_t info; 692 siginfo_t info = {0};
658 693
659 if (notify_die(DIE_FP, "FP exception", regs, 0, regs_to_trapnr(regs), SIGFPE) 694 if (notify_die(DIE_FP, "FP exception", regs, 0, regs_to_trapnr(regs), SIGFPE)
660 == NOTIFY_STOP) 695 == NOTIFY_STOP)
@@ -663,6 +698,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
663 698
664 if (fcr31 & FPU_CSR_UNI_X) { 699 if (fcr31 & FPU_CSR_UNI_X) {
665 int sig; 700 int sig;
701 void __user *fault_addr = NULL;
666 702
667 /* 703 /*
668 * Unimplemented operation exception. If we've got the full 704 * Unimplemented operation exception. If we've got the full
@@ -678,7 +714,8 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
678 lose_fpu(1); 714 lose_fpu(1);
679 715
680 /* Run the emulator */ 716 /* Run the emulator */
681 sig = fpu_emulator_cop1Handler(regs, &current->thread.fpu, 1); 717 sig = fpu_emulator_cop1Handler(regs, &current->thread.fpu, 1,
718 &fault_addr);
682 719
683 /* 720 /*
684 * We can't allow the emulated instruction to leave any of 721 * We can't allow the emulated instruction to leave any of
@@ -690,8 +727,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
690 own_fpu(1); /* Using the FPU again. */ 727 own_fpu(1); /* Using the FPU again. */
691 728
692 /* If something went wrong, signal */ 729 /* If something went wrong, signal */
693 if (sig) 730 process_fpemu_return(sig, fault_addr);
694 force_sig(sig, current);
695 731
696 return; 732 return;
697 } else if (fcr31 & FPU_CSR_INV_X) 733 } else if (fcr31 & FPU_CSR_INV_X)
@@ -984,11 +1020,11 @@ asmlinkage void do_cpu(struct pt_regs *regs)
984 1020
985 if (!raw_cpu_has_fpu) { 1021 if (!raw_cpu_has_fpu) {
986 int sig; 1022 int sig;
1023 void __user *fault_addr = NULL;
987 sig = fpu_emulator_cop1Handler(regs, 1024 sig = fpu_emulator_cop1Handler(regs,
988 &current->thread.fpu, 0); 1025 &current->thread.fpu,
989 if (sig) 1026 0, &fault_addr);
990 force_sig(sig, current); 1027 if (!process_fpemu_return(sig, fault_addr))
991 else
992 mt_ase_fp_affinity(); 1028 mt_ase_fp_affinity();
993 } 1029 }
994 1030
@@ -1469,6 +1505,7 @@ void __cpuinit per_cpu_trap_init(void)
1469{ 1505{
1470 unsigned int cpu = smp_processor_id(); 1506 unsigned int cpu = smp_processor_id();
1471 unsigned int status_set = ST0_CU0; 1507 unsigned int status_set = ST0_CU0;
1508 unsigned int hwrena = cpu_hwrena_impl_bits;
1472#ifdef CONFIG_MIPS_MT_SMTC 1509#ifdef CONFIG_MIPS_MT_SMTC
1473 int secondaryTC = 0; 1510 int secondaryTC = 0;
1474 int bootTC = (cpu == 0); 1511 int bootTC = (cpu == 0);
@@ -1501,14 +1538,14 @@ void __cpuinit per_cpu_trap_init(void)
1501 change_c0_status(ST0_CU|ST0_MX|ST0_RE|ST0_FR|ST0_BEV|ST0_TS|ST0_KX|ST0_SX|ST0_UX, 1538 change_c0_status(ST0_CU|ST0_MX|ST0_RE|ST0_FR|ST0_BEV|ST0_TS|ST0_KX|ST0_SX|ST0_UX,
1502 status_set); 1539 status_set);
1503 1540
1504 if (cpu_has_mips_r2) { 1541 if (cpu_has_mips_r2)
1505 unsigned int enable = 0x0000000f | cpu_hwrena_impl_bits; 1542 hwrena |= 0x0000000f;
1506 1543
1507 if (!noulri && cpu_has_userlocal) 1544 if (!noulri && cpu_has_userlocal)
1508 enable |= (1 << 29); 1545 hwrena |= (1 << 29);
1509 1546
1510 write_c0_hwrena(enable); 1547 if (hwrena)
1511 } 1548 write_c0_hwrena(hwrena);
1512 1549
1513#ifdef CONFIG_MIPS_MT_SMTC 1550#ifdef CONFIG_MIPS_MT_SMTC
1514 if (!secondaryTC) { 1551 if (!secondaryTC) {
@@ -1553,7 +1590,6 @@ void __cpuinit per_cpu_trap_init(void)
1553#endif /* CONFIG_MIPS_MT_SMTC */ 1590#endif /* CONFIG_MIPS_MT_SMTC */
1554 1591
1555 cpu_data[cpu].asid_cache = ASID_FIRST_VERSION; 1592 cpu_data[cpu].asid_cache = ASID_FIRST_VERSION;
1556 TLBMISS_HANDLER_SETUP();
1557 1593
1558 atomic_inc(&init_mm.mm_count); 1594 atomic_inc(&init_mm.mm_count);
1559 current->active_mm = &init_mm; 1595 current->active_mm = &init_mm;
@@ -1575,6 +1611,7 @@ void __cpuinit per_cpu_trap_init(void)
1575 write_c0_wired(0); 1611 write_c0_wired(0);
1576 } 1612 }
1577#endif /* CONFIG_MIPS_MT_SMTC */ 1613#endif /* CONFIG_MIPS_MT_SMTC */
1614 TLBMISS_HANDLER_SETUP();
1578} 1615}
1579 1616
1580/* Install CPU exception handler */ 1617/* Install CPU exception handler */