patch-2.4.19 linux-2.4.19/arch/mips/kernel/traps.c
Next file: linux-2.4.19/arch/mips/kernel/unaligned.c
Previous file: linux-2.4.19/arch/mips/kernel/time.c
Back to the patch index
Back to the overall index
- Lines: 819
- Date:
Fri Aug 2 17:39:43 2002
- Orig file:
linux-2.4.18/arch/mips/kernel/traps.c
- Orig date:
Sun Sep 9 10:43:01 2001
diff -urN linux-2.4.18/arch/mips/kernel/traps.c linux-2.4.19/arch/mips/kernel/traps.c
@@ -10,6 +10,7 @@
*
* Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
* Copyright (C) 2000, 01 MIPS Technologies, Inc.
+ * Copyright (C) 2002 Maciej W. Rozycki
*/
#include <linux/config.h>
#include <linux/init.h>
@@ -32,6 +33,7 @@
#include <asm/siginfo.h>
#include <asm/watch.h>
#include <asm/system.h>
+#include <asm/traps.h>
#include <asm/uaccess.h>
#include <asm/mmu_context.h>
@@ -66,8 +68,7 @@
char watch_available = 0;
-void (*ibe_board_handler)(struct pt_regs *regs);
-void (*dbe_board_handler)(struct pt_regs *regs);
+int (*be_board_handler)(struct pt_regs *regs, int is_fixup);
int kstack_depth_to_print = 24;
@@ -77,12 +78,9 @@
*/
#define MODULE_RANGE (8*1024*1024)
-#ifndef CONFIG_CPU_HAS_LLSC
/*
* This stuff is needed for the userland ll-sc emulation for R2300
*/
-void simulate_ll(struct pt_regs *regs, unsigned int opcode);
-void simulate_sc(struct pt_regs *regs, unsigned int opcode);
#define OPCODE 0xfc000000
#define BASE 0x03e00000
@@ -90,8 +88,97 @@
#define OFFSET 0x0000ffff
#define LL 0xc0000000
#define SC 0xe0000000
+
+/*
+ * The ll_bit is cleared by r*_switch.S
+ */
+
+unsigned long ll_bit;
+#ifdef CONFIG_PROC_FS
+extern unsigned long ll_ops;
+extern unsigned long sc_ops;
+#endif
+
+static struct task_struct *ll_task = NULL;
+
+static inline void simulate_ll(struct pt_regs *regp, unsigned int opcode)
+{
+ unsigned long value, *vaddr;
+ long offset;
+ int signal = 0;
+
+ /*
+ * analyse the ll instruction that just caused a ri exception
+ * and put the referenced address to addr.
+ */
+
+ /* sign extend offset */
+ offset = opcode & OFFSET;
+ offset <<= 16;
+ offset >>= 16;
+
+ vaddr = (unsigned long *)((long)(regp->regs[(opcode & BASE) >> 21]) + offset);
+
+#ifdef CONFIG_PROC_FS
+ ll_ops++;
+#endif
+
+ if ((unsigned long)vaddr & 3)
+ signal = SIGBUS;
+ else if (get_user(value, vaddr))
+ signal = SIGSEGV;
+ else {
+ if (ll_task == NULL || ll_task == current) {
+ ll_bit = 1;
+ } else {
+ ll_bit = 0;
+ }
+ ll_task = current;
+ regp->regs[(opcode & RT) >> 16] = value;
+ }
+ if (compute_return_epc(regp))
+ return;
+ if (signal)
+ send_sig(signal, current, 1);
+}
+
+static inline void simulate_sc(struct pt_regs *regp, unsigned int opcode)
+{
+ unsigned long *vaddr, reg;
+ long offset;
+ int signal = 0;
+
+ /*
+ * analyse the sc instruction that just caused a ri exception
+ * and put the referenced address to addr.
+ */
+
+ /* sign extend offset */
+ offset = opcode & OFFSET;
+ offset <<= 16;
+ offset >>= 16;
+
+ vaddr = (unsigned long *)((long)(regp->regs[(opcode & BASE) >> 21]) + offset);
+ reg = (opcode & RT) >> 16;
+
+#ifdef CONFIG_PROC_FS
+ sc_ops++;
#endif
+ if ((unsigned long)vaddr & 3)
+ signal = SIGBUS;
+ else if (ll_bit == 0 || ll_task != current)
+ regp->regs[reg] = 0;
+ else if (put_user(regp->regs[reg], vaddr))
+ signal = SIGSEGV;
+ else
+ regp->regs[reg] = 1;
+ if (compute_return_epc(regp))
+ return;
+ if (signal)
+ send_sig(signal, current, 1);
+}
+
/*
* This routine abuses get_user()/put_user() to reference pointers
* with at least a bit of error checking ...
@@ -101,7 +188,7 @@
int i;
unsigned int *stack;
- stack = sp;
+ stack = sp ? sp : (unsigned int *)&sp;
i = 0;
printk("Stack:");
@@ -128,12 +215,13 @@
void show_trace(unsigned int *sp)
{
int i;
+ int column = 0;
unsigned int *stack;
unsigned long kernel_start, kernel_end;
unsigned long module_start, module_end;
extern char _stext, _etext;
- stack = sp;
+ stack = sp ? sp : (unsigned int *) &sp;
i = 0;
kernel_start = (unsigned long) &_stext;
@@ -164,12 +252,23 @@
(addr >= module_start && addr < module_end)) {
printk(" [<%08lx>]", addr);
+ if (column++ == 5) {
+ printk("\n");
+ column = 0;
+ }
if (++i > 40) {
printk(" ...");
break;
}
}
}
+ if (column != 0)
+ printk("\n");
+}
+
+void show_trace_task(struct task_struct *tsk)
+{
+ show_trace((unsigned int *)tsk->thread.reg29);
}
void show_code(unsigned int *pc)
@@ -188,17 +287,36 @@
}
}
-spinlock_t die_lock;
+void show_regs(struct pt_regs * regs)
+{
+ /*
+ * Saved main processor registers
+ */
+ printk("$0 : %08x %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+ 0, regs->regs[1], regs->regs[2], regs->regs[3],
+ regs->regs[4], regs->regs[5], regs->regs[6], regs->regs[7]);
+ printk("$8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+ regs->regs[8], regs->regs[9], regs->regs[10], regs->regs[11],
+ regs->regs[12], regs->regs[13], regs->regs[14], regs->regs[15]);
+ printk("$16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+ regs->regs[16], regs->regs[17], regs->regs[18], regs->regs[19],
+ regs->regs[20], regs->regs[21], regs->regs[22], regs->regs[23]);
+ printk("$24: %08lx %08lx %08lx %08lx %08lx %08lx\n",
+ regs->regs[24], regs->regs[25],
+ regs->regs[28], regs->regs[29], regs->regs[30], regs->regs[31]);
+ printk("Hi : %08lx\n", regs->hi);
+ printk("Lo : %08lx\n", regs->lo);
-extern void __die(const char * str, struct pt_regs * regs, const char *where,
- unsigned long line)
+ /*
+ * Saved cp0 registers
+ */
+ printk("epc : %08lx %s\nStatus: %08lx\nCause : %08lx\n",
+ regs->cp0_epc, print_tainted(), regs->cp0_status,
+ regs->cp0_cause);
+}
+
+void show_registers(struct pt_regs *regs)
{
- console_verbose();
- spin_lock_irq(&die_lock);
- printk("%s", str);
- if (where)
- printk(" in %s, line %ld", where, line);
- printk(":\n");
show_regs(regs);
printk("Process %s (pid: %d, stackpage=%08lx)\n",
current->comm, current->pid, (unsigned long) current);
@@ -206,6 +324,20 @@
show_trace((unsigned int *) regs->regs[29]);
show_code((unsigned int *) regs->cp0_epc);
printk("\n");
+}
+
+static spinlock_t die_lock = SPIN_LOCK_UNLOCKED;
+
+void __die(const char * str, struct pt_regs * regs, const char *where,
+ unsigned long line)
+{
+ console_verbose();
+ spin_lock_irq(&die_lock);
+ printk("%s", str);
+ if (where)
+ printk(" in %s, line %ld", where, line);
+ printk(":\n");
+ show_registers(regs);
spin_unlock_irq(&die_lock);
do_exit(SIGSEGV);
}
@@ -286,20 +418,35 @@
#endif
}
-static void default_be_board_handler(struct pt_regs *regs)
+asmlinkage void do_be(struct pt_regs *regs)
{
unsigned long new_epc;
- unsigned long fixup;
+ unsigned long fixup = 0;
int data = regs->cp0_cause & 4;
+ int action = MIPS_BE_FATAL;
- if (data && !user_mode(regs)) {
+ if (data && !user_mode(regs))
fixup = search_dbe_table(regs->cp0_epc);
+
+ if (fixup)
+ action = MIPS_BE_FIXUP;
+
+ if (be_board_handler)
+ action = be_board_handler(regs, fixup != 0);
+
+ switch (action) {
+ case MIPS_BE_DISCARD:
+ return;
+ case MIPS_BE_FIXUP:
if (fixup) {
new_epc = fixup_exception(dpf_reg, fixup,
regs->cp0_epc);
regs->cp0_epc = new_epc;
return;
}
+ break;
+ default:
+ break;
}
/*
@@ -312,16 +459,6 @@
force_sig(SIGBUS, current);
}
-asmlinkage void do_ibe(struct pt_regs *regs)
-{
- ibe_board_handler(regs);
-}
-
-asmlinkage void do_dbe(struct pt_regs *regs)
-{
- dbe_board_handler(regs);
-}
-
asmlinkage void do_ov(struct pt_regs *regs)
{
if (compute_return_epc(regs))
@@ -356,26 +493,31 @@
sig = fpu_emulator_cop1Handler(regs);
/*
- * We can't allow the emulated instruction to leave the
- * Unimplemented Operation bit set in $fcr31.
+ * We can't allow the emulated instruction to leave any of
+ * the cause bit set in $fcr31.
*/
- current->thread.fpu.soft.sr &= ~FPU_CSR_UNI_X;
+ current->thread.fpu.soft.sr &= ~FPU_CSR_ALL_X;
/* Restore the hardware register state */
restore_fp(current);
/* If something went wrong, signal */
if (sig)
+ {
+ /*
+ * Return EPC is not calculated in the FPU emulator,
+ * if a signal is being send. So we calculate it here.
+ */
+ compute_return_epc(regs);
force_sig(sig, current);
+ }
return;
}
if (compute_return_epc(regs))
return;
-
force_sig(SIGFPE, current);
- printk(KERN_DEBUG "Sent send SIGFPE to %s\n", current->comm);
}
static inline int get_insn_opcode(struct pt_regs *regs, unsigned int *opcode)
@@ -424,7 +566,7 @@
info.si_code = FPE_INTOVF;
info.si_signo = SIGFPE;
info.si_errno = 0;
- info.si_addr = (void *)compute_return_epc(regs);
+ info.si_addr = (void *)regs->cp0_epc;
force_sig_info(SIGFPE, &info, current);
break;
default:
@@ -464,7 +606,7 @@
info.si_code = FPE_INTOVF;
info.si_signo = SIGFPE;
info.si_errno = 0;
- info.si_addr = (void *)compute_return_epc(regs);
+ info.si_addr = (void *)regs->cp0_epc;
force_sig_info(SIGFPE, &info, current);
break;
default:
@@ -476,12 +618,6 @@
force_sig(SIGSEGV, current);
}
-#ifndef CONFIG_CPU_HAS_LLSC
-
-#ifdef CONFIG_SMP
-#error "ll/sc emulation is not SMP safe"
-#endif
-
/*
* userland emulation for R2300 CPUs
* needed for the multithreading part of glibc
@@ -491,11 +627,18 @@
*/
asmlinkage void do_ri(struct pt_regs *regs)
{
- unsigned int opcode;
-
if (!user_mode(regs))
BUG();
+#ifndef CONFIG_CPU_HAS_LLSC
+
+#ifdef CONFIG_SMP
+#error "ll/sc emulation is not SMP safe"
+#endif
+
+ {
+ unsigned int opcode;
+
if (!get_insn_opcode(regs, &opcode)) {
if ((opcode & OPCODE) == LL) {
simulate_ll(regs, opcode);
@@ -506,121 +649,19 @@
return;
}
}
-
- if (compute_return_epc(regs))
- return;
- force_sig(SIGILL, current);
-}
-
-/*
- * The ll_bit is cleared by r*_switch.S
- */
-
-unsigned long ll_bit;
-#ifdef CONFIG_PROC_FS
-extern unsigned long ll_ops;
-extern unsigned long sc_ops;
-#endif
-
-static struct task_struct *ll_task = NULL;
-
-void simulate_ll(struct pt_regs *regp, unsigned int opcode)
-{
- unsigned long value, *vaddr;
- long offset;
- int signal = 0;
-
- /*
- * analyse the ll instruction that just caused a ri exception
- * and put the referenced address to addr.
- */
-
- /* sign extend offset */
- offset = opcode & OFFSET;
- offset <<= 16;
- offset >>= 16;
-
- vaddr = (unsigned long *)((long)(regp->regs[(opcode & BASE) >> 21]) + offset);
-
-#ifdef CONFIG_PROC_FS
- ll_ops++;
-#endif
-
- if ((unsigned long)vaddr & 3)
- signal = SIGBUS;
- else if (get_user(value, vaddr))
- signal = SIGSEGV;
- else {
- if (ll_task == NULL || ll_task == current) {
- ll_bit = 1;
- } else {
- ll_bit = 0;
- }
- ll_task = current;
- regp->regs[(opcode & RT) >> 16] = value;
}
- if (compute_return_epc(regp))
- return;
- if (signal)
- send_sig(signal, current, 1);
-}
-
-void simulate_sc(struct pt_regs *regp, unsigned int opcode)
-{
- unsigned long *vaddr, reg;
- long offset;
- int signal = 0;
-
- /*
- * analyse the sc instruction that just caused a ri exception
- * and put the referenced address to addr.
- */
+#endif /* CONFIG_CPU_HAS_LLSC */
- /* sign extend offset */
- offset = opcode & OFFSET;
- offset <<= 16;
- offset >>= 16;
-
- vaddr = (unsigned long *)((long)(regp->regs[(opcode & BASE) >> 21]) + offset);
- reg = (opcode & RT) >> 16;
-
-#ifdef CONFIG_PROC_FS
- sc_ops++;
-#endif
-
- if ((unsigned long)vaddr & 3)
- signal = SIGBUS;
- else if (ll_bit == 0 || ll_task != current)
- regp->regs[reg] = 0;
- else if (put_user(regp->regs[reg], vaddr))
- signal = SIGSEGV;
- else
- regp->regs[reg] = 1;
- if (compute_return_epc(regp))
- return;
- if (signal)
- send_sig(signal, current, 1);
-}
-
-#else /* MIPS 2 or higher */
-
-asmlinkage void do_ri(struct pt_regs *regs)
-{
- unsigned int opcode;
-
- get_insn_opcode(regs, &opcode);
if (compute_return_epc(regs))
return;
-
force_sig(SIGILL, current);
}
-#endif
-
asmlinkage void do_cpu(struct pt_regs *regs)
{
unsigned int cpid;
extern void lazy_fpu_switch(void *);
+ extern void save_fp(struct task_struct *);
extern void init_fpu(void);
void fpu_emulator_init_fpu(void);
int sig;
@@ -639,10 +680,13 @@
if (current->used_math) { /* Using the FPU again. */
lazy_fpu_switch(last_task_used_math);
} else { /* First time FPU user. */
+ if (last_task_used_math != NULL)
+ save_fp(last_task_used_math);
init_fpu();
current->used_math = 1;
}
last_task_used_math = current;
+
return;
fp_emul:
@@ -655,19 +699,38 @@
sig = fpu_emulator_cop1Handler(regs);
last_task_used_math = current;
if (sig)
+ {
+ /*
+ * Return EPC is not calculated in the FPU emulator, if
+ * a signal is being send. So we calculate it here.
+ */
+ compute_return_epc(regs);
force_sig(sig, current);
+ }
return;
bad_cid:
+#ifndef CONFIG_CPU_HAS_LLSC
+ switch (mips_cpu.cputype) {
+ case CPU_TX3927:
+ case CPU_TX39XX:
+ do_ri(regs);
+ return;
+ }
+#endif
+ compute_return_epc(regs);
force_sig(SIGILL, current);
}
asmlinkage void do_watch(struct pt_regs *regs)
{
+ extern void dump_tlb_all(void);
+
/*
* We use the watch exception where available to detect stack
* overflows.
*/
+ dump_tlb_all();
show_regs(regs);
panic("Caught WATCH exception - probably caused by stack overflow.");
}
@@ -753,6 +816,50 @@
panic("Can't handle the cache error!");
}
+/*
+ * SDBBP EJTAG debug exception handler.
+ * We skip the instruction and return to the next instruction.
+ */
+void ejtag_exception_handler(struct pt_regs *regs)
+{
+ unsigned int depc, old_epc, debug;
+
+ printk("SDBBP EJTAG debug exception - not handled yet, just ignored!\n");
+ depc = read_32bit_cp0_register(CP0_DEPC);
+ debug = read_32bit_cp0_register(CP0_DEBUG);
+ printk("DEPC = %08x, DEBUG = %08x\n", depc, debug);
+ if (debug & 0x80000000) {
+ /*
+ * In branch delay slot.
+ * We cheat a little bit here and use EPC to calculate the
+ * debug return address (DEPC). EPC is restored after the
+ * calculation.
+ */
+ old_epc = regs->cp0_epc;
+ regs->cp0_epc = depc;
+ __compute_return_epc(regs);
+ depc = regs->cp0_epc;
+ regs->cp0_epc = old_epc;
+ } else
+ depc += 4;
+ write_32bit_cp0_register(CP0_DEPC, depc);
+
+#if 0
+ printk("\n\n----- Enable EJTAG single stepping ----\n\n");
+ write_32bit_cp0_register(CP0_DEBUG, debug | 0x100);
+#endif
+}
+
+/*
+ * NMI exception handler.
+ */
+void nmi_exception_handler(struct pt_regs *regs)
+{
+ printk("NMI taken!!!!\n");
+ die("NMI", regs);
+ while(1) ; /* We die here. */
+}
+
unsigned long exception_handlers[32];
/*
@@ -782,24 +889,39 @@
extern asmlinkage int fpu_emulator_save_context(struct sigcontext *sc);
extern asmlinkage int fpu_emulator_restore_context(struct sigcontext *sc);
+void __init per_cpu_trap_init(void)
+{
+ unsigned int cpu = smp_processor_id();
+
+ /* Some firmware leaves the BEV flag set, clear it. */
+ clear_cp0_status(ST0_BEV);
+
+ /*
+ * Some MIPS CPUs have a dedicated interrupt vector which reduces the
+ * interrupt processing overhead. Use it where available.
+ */
+ if (mips_cpu.options & MIPS_CPU_DIVEC)
+ set_cp0_cause(CAUSEF_IV);
+
+ cpu_data[cpu].asid_cache = ASID_FIRST_VERSION;
+ set_context(cpu << 23);
+}
+
void __init trap_init(void)
{
- extern char except_vec0_nevada, except_vec0_r4000;
- extern char except_vec0_r4600, except_vec0_r2300;
extern char except_vec1_generic, except_vec2_generic;
extern char except_vec3_generic, except_vec3_r4000;
extern char except_vec4;
extern char except_vec_ejtag_debug;
unsigned long i;
- /* Some firmware leaves the BEV flag set, clear it. */
- clear_cp0_status(ST0_BEV);
+ per_cpu_trap_init();
/* Copy the generic exception handler code to it's final destination. */
memcpy((void *)(KSEG0 + 0x80), &except_vec1_generic, 0x80);
memcpy((void *)(KSEG0 + 0x100), &except_vec2_generic, 0x80);
memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic, 0x80);
- flush_icache_range(KSEG0 + 0x80, KSEG0 + 0x200);
+
/*
* Setup default vectors
*/
@@ -810,7 +932,8 @@
* Copy the EJTAG debug exception vector handler code to it's final
* destination.
*/
- memcpy((void *)(KSEG0 + 0x300), &except_vec_ejtag_debug, 0x80);
+ if (mips_cpu.options & MIPS_CPU_EJTAG)
+ memcpy((void *)(KSEG0 + 0x300), &except_vec_ejtag_debug, 0x80);
/*
* Only some CPUs have the watch exceptions or a dedicated
@@ -833,21 +956,21 @@
*/
parity_protection_init();
+ /*
+ * The Data Bus Errors / Instruction Bus Errors are signaled
+ * by external hardware. Therefore these two exceptions
+ * may have board specific handlers.
+ */
+ bus_error_init();
+
set_except_vector(1, handle_mod);
set_except_vector(2, handle_tlbl);
set_except_vector(3, handle_tlbs);
set_except_vector(4, handle_adel);
set_except_vector(5, handle_ades);
- /*
- * The Data Bus Error/ Instruction Bus Errors are signaled
- * by external hardware. Therefore these two expection have
- * board specific handlers.
- */
set_except_vector(6, handle_ibe);
set_except_vector(7, handle_dbe);
- ibe_board_handler = default_be_board_handler;
- dbe_board_handler = default_be_board_handler;
set_except_vector(8, handle_sys);
set_except_vector(9, handle_bp);
@@ -856,37 +979,22 @@
set_except_vector(12, handle_ov);
set_except_vector(13, handle_tr);
- if (mips_cpu.options & MIPS_CPU_FPU)
+ if ((mips_cpu.options & MIPS_CPU_FPU) &&
+ !(mips_cpu.options & MIPS_CPU_NOFPUEX))
set_except_vector(15, handle_fpe);
+ if (mips_cpu.options & MIPS_CPU_MCHECK)
+ set_except_vector(24, handle_mcheck);
/*
* Handling the following exceptions depends mostly of the cpu type
*/
if ((mips_cpu.options & MIPS_CPU_4KEX)
&& (mips_cpu.options & MIPS_CPU_4KTLB)) {
- if (mips_cpu.cputype == CPU_NEVADA) {
- memcpy((void *)KSEG0, &except_vec0_nevada, 0x80);
- } else if (mips_cpu.cputype == CPU_R4600)
- memcpy((void *)KSEG0, &except_vec0_r4600, 0x80);
- else
- memcpy((void *)KSEG0, &except_vec0_r4000, 0x80);
-
/* Cache error vector already set above. */
if (mips_cpu.options & MIPS_CPU_VCE) {
memcpy((void *)(KSEG0 + 0x180), &except_vec3_r4000,
0x80);
- } else {
- memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic,
- 0x80);
- }
-
- if (mips_cpu.options & MIPS_CPU_FPU) {
- save_fp_context = _save_fp_context;
- restore_fp_context = _restore_fp_context;
- } else {
- save_fp_context = fpu_emulator_save_context;
- restore_fp_context = fpu_emulator_restore_context;
}
} else switch (mips_cpu.cputype) {
case CPU_SB1:
@@ -894,10 +1002,15 @@
* XXX - This should be folded in to the "cleaner" handling,
* above
*/
- memcpy((void *)KSEG0, &except_vec0_r4000, 0x80);
memcpy((void *)(KSEG0 + 0x180), &except_vec3_r4000, 0x80);
- save_fp_context = _save_fp_context;
- restore_fp_context = _restore_fp_context;
+#ifdef CONFIG_SB1_CACHE_ERROR
+ {
+ /* Special cache error handler for SB1 */
+ extern char except_vec2_sb1;
+ memcpy((void *)(KSEG0 + 0x100), &except_vec2_sb1, 0x80);
+ memcpy((void *)(KSEG1 + 0x100), &except_vec2_sb1, 0x80);
+ }
+#endif
/* Enable timer interrupt and scd mapped interrupt */
clear_cp0_status(0xf000);
@@ -905,9 +1018,6 @@
break;
case CPU_R6000:
case CPU_R6000A:
- save_fp_context = _save_fp_context;
- restore_fp_context = _restore_fp_context;
-
/*
* The R6000 is the only R-series CPU that features a machine
* check exception (similar to the R4000 cache error) and
@@ -929,9 +1039,7 @@
case CPU_TX3912:
case CPU_TX3922:
case CPU_TX3927:
- save_fp_context = _save_fp_context;
- restore_fp_context = _restore_fp_context;
- memcpy((void *)KSEG0, &except_vec0_r2300, 0x80);
+ case CPU_TX39XX:
memcpy((void *)(KSEG0 + 0x80), &except_vec3_generic, 0x80);
break;
@@ -939,13 +1047,24 @@
default:
panic("Unknown CPU type");
}
- flush_icache_range(KSEG0, KSEG0 + 0x200);
+
+ flush_icache_range(KSEG0, KSEG0 + 0x400);
+
+ if (mips_cpu.options & MIPS_CPU_FPU) {
+ save_fp_context = _save_fp_context;
+ restore_fp_context = _restore_fp_context;
+ } else {
+ save_fp_context = fpu_emulator_save_context;
+ restore_fp_context = fpu_emulator_restore_context;
+ }
if (mips_cpu.isa_level == MIPS_CPU_ISA_IV)
set_cp0_status(ST0_XX);
atomic_inc(&init_mm.mm_count); /* XXX UP? */
current->active_mm = &init_mm;
- write_32bit_cp0_register(CP0_CONTEXT, smp_processor_id()<<23);
- current_pgd[0] = init_mm.pgd;
+
+ /* XXX Must be done for all CPUs */
+ current_cpu_data.asid_cache = ASID_FIRST_VERSION;
+ TLBMISS_HANDLER_SETUP();
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)