]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/mips/kernel/traps.c
Fix one more case of computing the return EPC after the registers have
[linux-2.6-omap-h63xx.git] / arch / mips / kernel / traps.c
index a53b1ed7b38625540bddb2af051015f617d6387c..94d9141c04c17ede6bb7382983c37ba5d56de6f9 100644 (file)
@@ -339,9 +339,9 @@ asmlinkage void do_be(struct pt_regs *regs)
 
 static inline int get_insn_opcode(struct pt_regs *regs, unsigned int *opcode)
 {
-       unsigned int *epc;
+       unsigned int __user *epc;
 
-       epc = (unsigned int *) regs->cp0_epc +
+       epc = (unsigned int __user *) regs->cp0_epc +
              ((regs->cp0_cause & CAUSEF_BD) != 0);
        if (!get_user(*opcode, epc))
                return 0;
@@ -371,7 +371,7 @@ static struct task_struct *ll_task = NULL;
 
 static inline void simulate_ll(struct pt_regs *regs, unsigned int opcode)
 {
-       unsigned long value, *vaddr;
+       unsigned long value, __user *vaddr;
        long offset;
        int signal = 0;
 
@@ -385,7 +385,8 @@ static inline void simulate_ll(struct pt_regs *regs, unsigned int opcode)
        offset <<= 16;
        offset >>= 16;
 
-       vaddr = (unsigned long *)((long)(regs->regs[(opcode & BASE) >> 21]) + offset);
+       vaddr = (unsigned long __user *)
+               ((unsigned long)(regs->regs[(opcode & BASE) >> 21]) + offset);
 
        if ((unsigned long)vaddr & 3) {
                signal = SIGBUS;
@@ -407,9 +408,10 @@ static inline void simulate_ll(struct pt_regs *regs, unsigned int opcode)
 
        preempt_enable();
 
+       compute_return_epc(regs);
+
        regs->regs[(opcode & RT) >> 16] = value;
 
-       compute_return_epc(regs);
        return;
 
 sig:
@@ -418,7 +420,8 @@ sig:
 
 static inline void simulate_sc(struct pt_regs *regs, unsigned int opcode)
 {
-       unsigned long *vaddr, reg;
+       unsigned long __user *vaddr;
+       unsigned long reg;
        long offset;
        int signal = 0;
 
@@ -432,7 +435,8 @@ static inline void simulate_sc(struct pt_regs *regs, unsigned int opcode)
        offset <<= 16;
        offset >>= 16;
 
-       vaddr = (unsigned long *)((long)(regs->regs[(opcode & BASE) >> 21]) + offset);
+       vaddr = (unsigned long __user *)
+               ((unsigned long)(regs->regs[(opcode & BASE) >> 21]) + offset);
        reg = (opcode & RT) >> 16;
 
        if ((unsigned long)vaddr & 3) {
@@ -443,9 +447,9 @@ static inline void simulate_sc(struct pt_regs *regs, unsigned int opcode)
        preempt_disable();
 
        if (ll_bit == 0 || ll_task != current) {
+               compute_return_epc(regs);
                regs->regs[reg] = 0;
                preempt_enable();
-               compute_return_epc(regs);
                return;
        }
 
@@ -456,9 +460,9 @@ static inline void simulate_sc(struct pt_regs *regs, unsigned int opcode)
                goto sig;
        }
 
+       compute_return_epc(regs);
        regs->regs[reg] = 1;
 
-       compute_return_epc(regs);
        return;
 
 sig:
@@ -498,7 +502,7 @@ asmlinkage void do_ov(struct pt_regs *regs)
        info.si_code = FPE_INTOVF;
        info.si_signo = SIGFPE;
        info.si_errno = 0;
-       info.si_addr = (void *)regs->cp0_epc;
+       info.si_addr = (void __user *) regs->cp0_epc;
        force_sig_info(SIGFPE, &info, current);
 }
 
@@ -584,7 +588,7 @@ asmlinkage void do_bp(struct pt_regs *regs)
                        info.si_code = FPE_INTOVF;
                info.si_signo = SIGFPE;
                info.si_errno = 0;
-               info.si_addr = (void *)regs->cp0_epc;
+               info.si_addr = (void __user *) regs->cp0_epc;
                force_sig_info(SIGFPE, &info, current);
                break;
        default:
@@ -621,7 +625,7 @@ asmlinkage void do_tr(struct pt_regs *regs)
                        info.si_code = FPE_INTOVF;
                info.si_signo = SIGFPE;
                info.si_errno = 0;
-               info.si_addr = (void *)regs->cp0_epc;
+               info.si_addr = (void __user *) regs->cp0_epc;
                force_sig_info(SIGFPE, &info, current);
                break;
        default:
@@ -736,16 +740,12 @@ static inline void parity_protection_init(void)
 {
        switch (current_cpu_data.cputype) {
        case CPU_24K:
-               /* 24K cache parity not currently implemented in FPGA */
-               printk(KERN_INFO "Disable cache parity protection for "
-                      "MIPS 24K CPU.\n");
-               write_c0_ecc(read_c0_ecc() & ~0x80000000);
-               break;
        case CPU_5KC:
-               /* Set the PE bit (bit 31) in the c0_ecc register. */
-               printk(KERN_INFO "Enable cache parity protection for "
-                      "MIPS 5KC/24K CPUs.\n");
-               write_c0_ecc(read_c0_ecc() | 0x80000000);
+               write_c0_ecc(0x80000000);
+               back_to_back_c0_hazard();
+               /* Set the PE bit (bit 31) in the c0_errctl register. */
+               printk(KERN_INFO "Cache parity protection %sabled\n",
+                      (read_c0_ecc() & 0x80000000) ? "en" : "dis");
                break;
        case CPU_20KC:
        case CPU_25KF: