#include <asm/watch.h>
#include <asm/types.h>
-extern asmlinkage void handle_mod(void);
+extern asmlinkage void handle_tlbm(void);
extern asmlinkage void handle_tlbl(void);
extern asmlinkage void handle_tlbs(void);
-extern asmlinkage void __xtlb_mod(void);
-extern asmlinkage void __xtlb_tlbl(void);
-extern asmlinkage void __xtlb_tlbs(void);
extern asmlinkage void handle_adel(void);
extern asmlinkage void handle_ades(void);
extern asmlinkage void handle_ibe(void);
long stackdata;
int i;
- sp = sp ? sp : (unsigned long *) &sp;
+ if (!sp) {
+ if (task && task != current)
+ sp = (unsigned long *) task->thread.reg29;
+ else
+ sp = (unsigned long *) &sp;
+ }
printk("Stack :");
i = 0;
const int field = 2 * sizeof(unsigned long);
unsigned long addr;
- if (!stack)
- stack = (unsigned long*)&stack;
+ if (!stack) {
+ if (task && task != current)
+ stack = (unsigned long *) task->thread.reg29;
+ else
+ stack = (unsigned long *) &stack;
+ }
printk("Call Trace:");
#ifdef CONFIG_KALLSYMS
printk("\n");
}
-static spinlock_t die_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(die_lock);
NORET_TYPE void __die(const char * str, struct pt_regs * regs,
const char * file, const char * func, unsigned long line)
goto sig;
}
+ preempt_disable();
+
if (ll_task == NULL || ll_task == current) {
ll_bit = 1;
} else {
}
ll_task = current;
+ preempt_enable();
+
regs->regs[(opcode & RT) >> 16] = value;
compute_return_epc(regs);
signal = SIGBUS;
goto sig;
}
+
+ preempt_disable();
+
if (ll_bit == 0 || ll_task != current) {
regs->regs[reg] = 0;
+ preempt_enable();
compute_return_epc(regs);
return;
}
+ preempt_enable();
+
if (put_user(regs->regs[reg], vaddr)) {
signal = SIGSEGV;
goto sig;
if (fcr31 & FPU_CSR_UNI_X) {
int sig;
+ preempt_disable();
+
/*
* Unimplemented operation exception. If we've got the full
* software emulator on-board, let's use it...
/* Restore the hardware register state */
restore_fp(current);
+ preempt_enable();
+
/* If something went wrong, signal */
if (sig)
force_sig(sig, current);
break;
case 1:
+ preempt_disable();
+
own_fpu();
- if (current->used_math) { /* Using the FPU again. */
+ if (used_math()) { /* Using the FPU again. */
restore_fp(current);
} else { /* First time FPU user. */
init_fpu();
- current->used_math = 1;
+ set_used_math();
}
if (!cpu_has_fpu) {
force_sig(sig, current);
}
+ preempt_enable();
+
return;
case 2:
void __init per_cpu_trap_init(void)
{
unsigned int cpu = smp_processor_id();
+ unsigned int status_set = ST0_CU0;
- /* Some firmware leaves the BEV flag set, clear it. */
- clear_c0_status(ST0_CU1|ST0_CU2|ST0_CU3|ST0_BEV);
+ /*
+ * Disable coprocessors and select 32-bit or 64-bit addressing
+ * and the 16/32 or 32/32 FPR register model. Reset the BEV
+ * flag that some firmware may have left set and the TS bit (for
+ * IP27). Set XX for ISA IV code to work.
+ */
#ifdef CONFIG_MIPS64
- set_c0_status(ST0_CU0|ST0_FR|ST0_KX|ST0_SX|ST0_UX);
+ status_set |= ST0_FR|ST0_KX|ST0_SX|ST0_UX;
#endif
-
if (current_cpu_data.isa_level == MIPS_CPU_ISA_IV)
- set_c0_status(ST0_XX);
+ status_set |= ST0_XX;
+ change_c0_status(ST0_CU|ST0_FR|ST0_BEV|ST0_TS|ST0_KX|ST0_SX|ST0_UX,
+ status_set);
/*
* Some MIPS CPUs have a dedicated interrupt vector which reduces the
if (board_be_init)
board_be_init();
-#ifdef CONFIG_MIPS32
- set_except_vector(1, handle_mod);
+ set_except_vector(1, handle_tlbm);
set_except_vector(2, handle_tlbl);
set_except_vector(3, handle_tlbs);
-#endif
-#ifdef CONFIG_MIPS64
- set_except_vector(1, __xtlb_mod);
- set_except_vector(2, __xtlb_tlbl);
- set_except_vector(3, __xtlb_tlbs);
-#endif
+
set_except_vector(4, handle_adel);
set_except_vector(5, handle_ades);
set_except_vector(24, handle_mcheck);
if (cpu_has_vce)
- memcpy((void *)(CAC_BASE + 0x180), &except_vec3_r4000, 0x80);
+ /* Special exception: R4[04]00 uses also the divec space. */
+ memcpy((void *)(CAC_BASE + 0x180), &except_vec3_r4000, 0x100);
else if (cpu_has_4kex)
memcpy((void *)(CAC_BASE + 0x180), &except_vec3_generic, 0x80);
else
* unaligned ldc1/sdc1 exception. The handlers have not been
* written yet. Well, anyway there is no R6000 machine on the
* current list of targets for Linux/MIPS.
- * (Duh, crap, there is someone with a tripple R6k machine)
+ * (Duh, crap, there is someone with a triple R6k machine)
*/
//set_except_vector(14, handle_mc);
//set_except_vector(15, handle_ndc);