patch-2.4.10 linux/arch/mips/kernel/traps.c
Next file: linux/arch/mips/kernel/unaligned.c
Previous file: linux/arch/mips/kernel/time.c
Back to the patch index
Back to the overall index
- Lines: 800
- Date:
Sun Sep 9 10:43:01 2001
- Orig file:
v2.4.9/linux/arch/mips/kernel/traps.c
- Orig date:
Tue Jul 3 17:08:18 2001
diff -u --recursive --new-file v2.4.9/linux/arch/mips/kernel/traps.c linux/arch/mips/kernel/traps.c
@@ -3,17 +3,18 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 1994 - 1999 by Ralf Baechle
+ * Copyright (C) 1994 - 1999, 2000, 01 Ralf Baechle
* Modified for R3000 by Paul M. Antoine, 1995, 1996
* Complete output from die() by Ulf Carlsson, 1998
* Copyright (C) 1999 Silicon Graphics, Inc.
*
* Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
+ * Copyright (C) 2000, 01 MIPS Technologies, Inc.
*/
#include <linux/config.h>
#include <linux/init.h>
#include <linux/mm.h>
+#include <linux/module.h>
#include <linux/sched.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
@@ -25,6 +26,7 @@
#include <asm/cachectl.h>
#include <asm/inst.h>
#include <asm/jazz.h>
+#include <asm/module.h>
#include <asm/pgtable.h>
#include <asm/io.h>
#include <asm/siginfo.h>
@@ -32,9 +34,6 @@
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/mmu_context.h>
-#ifndef CONFIG_MIPS_FPU_EMULATOR
-#include <asm/inst.h>
-#endif
/*
* Machine specific interrupt handlers
@@ -63,12 +62,9 @@
extern asmlinkage void handle_mcheck(void);
extern asmlinkage void handle_reserved(void);
-extern int fpu_emulator_cop1Handler(int, struct pt_regs *);
-
-static char *cpu_names[] = CPU_NAMES;
+extern int fpu_emulator_cop1Handler(struct pt_regs *);
char watch_available = 0;
-char dedicated_iv_available = 0;
void (*ibe_board_handler)(struct pt_regs *regs);
void (*dbe_board_handler)(struct pt_regs *regs);
@@ -81,7 +77,7 @@
*/
#define MODULE_RANGE (8*1024*1024)
-#if !defined(CONFIG_CPU_HAS_LLSC)
+#ifndef CONFIG_CPU_HAS_LLSC
/*
* This stuff is needed for the userland ll-sc emulation for R2300
*/
@@ -94,8 +90,6 @@
#define OFFSET 0x0000ffff
#define LL 0xc0000000
#define SC 0xe0000000
-
-#undef DEBUG_LLSC
#endif
/*
@@ -212,7 +206,6 @@
show_trace((unsigned int *) regs->regs[29]);
show_code((unsigned int *) regs->cp0_epc);
printk("\n");
-while(1);
spin_unlock_irq(&die_lock);
do_exit(SIGSEGV);
}
@@ -254,89 +247,101 @@
return (first == last && first->insn == value) ? first->nextinsn : 0;
}
-#define search_dbe_table(addr) \
- search_one_table(__start___dbe_table, __stop___dbe_table - 1, (addr))
+extern spinlock_t modlist_lock;
+
+static inline unsigned long
+search_dbe_table(unsigned long addr)
+{
+ unsigned long ret = 0;
+
+#ifndef CONFIG_MODULES
+ /* There is only the kernel to search. */
+ ret = search_one_table(__start___dbe_table, __stop___dbe_table-1, addr);
+ return ret;
+#else
+ unsigned long flags;
+
+ /* The kernel is the last "module" -- no need to treat it special. */
+ struct module *mp;
+ struct archdata *ap;
+
+ spin_lock_irqsave(&modlist_lock, flags);
+ for (mp = module_list; mp != NULL; mp = mp->next) {
+ if (!mod_member_present(mp, archdata_end) ||
+ !mod_archdata_member_present(mp, struct archdata,
+ dbe_table_end))
+ continue;
+ ap = (struct archdata *)(mp->archdata_start);
+
+ if (ap->dbe_table_start == NULL ||
+ !(mp->flags & (MOD_RUNNING | MOD_INITIALIZING)))
+ continue;
+ ret = search_one_table(ap->dbe_table_start,
+ ap->dbe_table_end - 1, addr);
+ if (ret)
+ break;
+ }
+ spin_unlock_irqrestore(&modlist_lock, flags);
+ return ret;
+#endif
+}
static void default_be_board_handler(struct pt_regs *regs)
{
unsigned long new_epc;
- unsigned long fixup = search_dbe_table(regs->cp0_epc);
+ unsigned long fixup;
+ int data = regs->cp0_cause & 4;
- if (fixup) {
- new_epc = fixup_exception(dpf_reg, fixup, regs->cp0_epc);
- regs->cp0_epc = new_epc;
- return;
+ if (data && !user_mode(regs)) {
+ fixup = search_dbe_table(regs->cp0_epc);
+ if (fixup) {
+ new_epc = fixup_exception(dpf_reg, fixup,
+ regs->cp0_epc);
+ regs->cp0_epc = new_epc;
+ return;
+ }
}
/*
* Assume it would be too dangerous to continue ...
*/
+ printk(KERN_ALERT "%s bus error, epc == %08lx, ra == %08lx\n",
+ data ? "Data" : "Instruction",
+ regs->cp0_epc, regs->regs[31]);
+ die_if_kernel("Oops", regs);
force_sig(SIGBUS, current);
}
-void do_ibe(struct pt_regs *regs)
+asmlinkage void do_ibe(struct pt_regs *regs)
{
ibe_board_handler(regs);
}
-void do_dbe(struct pt_regs *regs)
+asmlinkage void do_dbe(struct pt_regs *regs)
{
dbe_board_handler(regs);
}
-void do_ov(struct pt_regs *regs)
+asmlinkage void do_ov(struct pt_regs *regs)
{
if (compute_return_epc(regs))
return;
- force_sig(SIGFPE, current);
-}
-
-#ifdef CONFIG_MIPS_FPE_MODULE
-static void (*fpe_handler)(struct pt_regs *regs, unsigned int fcr31);
-/*
- * Register_fpe/unregister_fpe are for debugging purposes only. To make
- * this hack work a bit better there is no error checking.
- */
-int register_fpe(void (*handler)(struct pt_regs *regs, unsigned int fcr31))
-{
- fpe_handler = handler;
- return 0;
-}
-
-int unregister_fpe(void (*handler)(struct pt_regs *regs, unsigned int fcr31))
-{
- fpe_handler = NULL;
- return 0;
+ force_sig(SIGFPE, current);
}
-#endif
/*
* XXX Delayed fp exceptions when doing a lazy ctx switch XXX
*/
-void do_fpe(struct pt_regs *regs, unsigned long fcr31)
+asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
{
-
-#ifdef CONFIG_MIPS_FPU_EMULATOR
- if(!(mips_cpu.options & MIPS_CPU_FPU))
- panic("Floating Point Exception with No FPU");
-#endif
-
-#ifdef CONFIG_MIPS_FPE_MODULE
- if (fpe_handler != NULL) {
- fpe_handler(regs, fcr31);
- return;
- }
-#endif
-
if (fcr31 & FPU_CSR_UNI_X) {
-#ifdef CONFIG_MIPS_FPU_EMULATOR
extern void save_fp(struct task_struct *);
extern void restore_fp(struct task_struct *);
int sig;
/*
* Unimplemented operation exception. If we've got the
- * Full software emulator on-board, let's use it...
+ * full software emulator on-board, let's use it...
*
* Force FPU to dump state into task/thread context.
* We're moving a lot of data here for what is probably
@@ -348,11 +353,11 @@
save_fp(current);
/* Run the emulator */
- sig = fpu_emulator_cop1Handler(0, regs);
+ sig = fpu_emulator_cop1Handler(regs);
/*
* We can't allow the emulated instruction to leave the
- * Unimplemented Operation bit set in the FCR31 fp-register.
+ * Unimplemented Operation bit set in $fcr31.
*/
current->thread.fpu.soft.sr &= ~FPU_CSR_UNI_X;
@@ -362,37 +367,6 @@
/* If something went wrong, signal */
if (sig)
force_sig(sig, current);
-#else
- /* Else use mini-emulator */
-
- extern void simfp(int);
- unsigned long pc;
- unsigned int insn;
-
- /* Retry instruction with flush to zero ... */
- if (!(fcr31 & (1<<24))) {
- printk("Setting flush to zero for %s.\n",
- current->comm);
- fcr31 &= ~FPU_CSR_UNI_X;
- fcr31 |= (1<<24);
- __asm__ __volatile__(
- "ctc1\t%0,$31"
- : /* No outputs */
- : "r" (fcr31));
- return;
- }
- pc = regs->cp0_epc + ((regs->cp0_cause & CAUSEF_BD) ? 4 : 0);
- if(pc & 0x80000000) insn = *(unsigned int *)pc;
- else if (get_user(insn, (unsigned int *)pc)) {
- /* XXX Can this happen? */
- force_sig(SIGSEGV, current);
- }
-
- printk(KERN_DEBUG "Unimplemented exception for insn %08x at 0x%08lx in %s.\n",
- insn, regs->cp0_epc, current->comm);
- simfp(MIPSInst(insn));
- compute_return_epc(regs);
-#endif /* CONFIG_MIPS_FPU_EMULATOR */
return;
}
@@ -408,31 +382,31 @@
{
unsigned int *epc;
- epc = (unsigned int *) (unsigned long) regs->cp0_epc;
- if (regs->cp0_cause & CAUSEF_BD)
- epc++;
-
- if (verify_area(VERIFY_READ, epc, 4)) {
- force_sig(SIGSEGV, current);
- return 1;
- }
- *opcode = *epc;
+ epc = (unsigned int *) regs->cp0_epc +
+ ((regs->cp0_cause & CAUSEF_BD) != 0);
+ if (!get_user(*opcode, epc))
+ return 0;
- return 0;
+ force_sig(SIGSEGV, current);
+ return 1;
}
-void do_bp(struct pt_regs *regs)
+asmlinkage void do_bp(struct pt_regs *regs)
{
siginfo_t info;
unsigned int opcode, bcode;
+ unsigned int *epc;
+
+ epc = (unsigned int *) regs->cp0_epc +
+ ((regs->cp0_cause & CAUSEF_BD) != 0);
+ if (get_user(opcode, epc))
+ goto sigsegv;
/*
* There is the ancient bug in the MIPS assemblers that the break
* code starts left to bit 16 instead to bit 6 in the opcode.
* Gas is bug-compatible ...
*/
- if (get_insn_opcode(regs, &opcode))
- return;
bcode = ((opcode >> 16) & ((1 << 20) - 1));
/*
@@ -456,15 +430,23 @@
default:
force_sig(SIGTRAP, current);
}
+ return;
+
+sigsegv:
+ force_sig(SIGSEGV, current);
}
-void do_tr(struct pt_regs *regs)
+asmlinkage void do_tr(struct pt_regs *regs)
{
siginfo_t info;
unsigned int opcode, bcode;
+ unsigned *epc;
+
+ epc = (unsigned int *) regs->cp0_epc +
+ ((regs->cp0_cause & CAUSEF_BD) != 0);
+ if (get_user(opcode, epc))
+ goto sigsegv;
- if (get_insn_opcode(regs, &opcode))
- return;
bcode = ((opcode >> 6) & ((1 << 20) - 1));
/*
@@ -488,9 +470,13 @@
default:
force_sig(SIGTRAP, current);
}
+ return;
+
+sigsegv:
+ force_sig(SIGSEGV, current);
}
-#if !defined(CONFIG_CPU_HAS_LLSC)
+#ifndef CONFIG_CPU_HAS_LLSC
#ifdef CONFIG_SMP
#error "ll/sc emulation is not SMP safe"
@@ -503,7 +489,7 @@
* this implementation can handle only sychronization between 2 or more
* user contexts and is not SMP safe.
*/
-void do_ri(struct pt_regs *regs)
+asmlinkage void do_ri(struct pt_regs *regs)
{
unsigned int opcode;
@@ -520,9 +506,7 @@
return;
}
}
- printk("[%s:%d] Illegal instruction %08lx at %08lx, ra=%08lx, CP0_STATUS=%08lx\n",
- current->comm, current->pid, *((unsigned long*)regs->cp0_epc), regs->cp0_epc,
- regs->regs[31], regs->cp0_status);
+
if (compute_return_epc(regs))
return;
force_sig(SIGILL, current);
@@ -558,10 +542,6 @@
vaddr = (unsigned long *)((long)(regp->regs[(opcode & BASE) >> 21]) + offset);
-#ifdef DEBUG_LLSC
- printk("ll: vaddr = 0x%08x, reg = %d\n", (unsigned int)vaddr, (opcode & RT) >> 16);
-#endif
-
#ifdef CONFIG_PROC_FS
ll_ops++;
#endif
@@ -604,10 +584,6 @@
vaddr = (unsigned long *)((long)(regp->regs[(opcode & BASE) >> 21]) + offset);
reg = (opcode & RT) >> 16;
-#ifdef DEBUG_LLSC
- printk("sc: vaddr = 0x%08x, reg = %d\n", (unsigned int)vaddr, (unsigned int)reg);
-#endif
-
#ifdef CONFIG_PROC_FS
sc_ops++;
#endif
@@ -628,52 +604,33 @@
#else /* MIPS 2 or higher */
-void do_ri(struct pt_regs *regs)
+asmlinkage void do_ri(struct pt_regs *regs)
{
unsigned int opcode;
- get_insn_opcode(regs, &opcode);
- printk("[%s:%ld] Illegal instruction %08x at %08lx ra=%08lx\n",
- current->comm, (unsigned long)current->pid, opcode,
- regs->cp0_epc, regs->regs[31]);
+ get_insn_opcode(regs, &opcode);
if (compute_return_epc(regs))
return;
+
force_sig(SIGILL, current);
}
#endif
-void do_cpu(struct pt_regs *regs)
+asmlinkage void do_cpu(struct pt_regs *regs)
{
unsigned int cpid;
- extern void lazy_fpu_switch(void*);
+ extern void lazy_fpu_switch(void *);
extern void init_fpu(void);
-#ifdef CONFIG_MIPS_FPU_EMULATOR
void fpu_emulator_init_fpu(void);
int sig;
-#endif
+
cpid = (regs->cp0_cause >> CAUSEB_CE) & 3;
if (cpid != 1)
goto bad_cid;
-#ifdef CONFIG_MIPS_FPU_EMULATOR
- if(!(mips_cpu.options & MIPS_CPU_FPU)) {
- if (last_task_used_math != current) {
- if(!current->used_math) {
- fpu_emulator_init_fpu();
- current->used_math = 1;
- }
- }
- sig = fpu_emulator_cop1Handler(0, regs);
- last_task_used_math = current;
- if(sig) {
- force_sig(sig, current);
- }
- return;
- }
-#else
- if(!(mips_cpu.options & MIPS_CPU_FPU)) goto bad_cid;
-#endif
+ if (!(mips_cpu.options & MIPS_CPU_FPU))
+ goto fp_emul;
regs->cp0_status |= ST0_CU1;
if (last_task_used_math == current)
@@ -682,18 +639,30 @@
if (current->used_math) { /* Using the FPU again. */
lazy_fpu_switch(last_task_used_math);
} else { /* First time FPU user. */
-
init_fpu();
current->used_math = 1;
}
last_task_used_math = current;
return;
+fp_emul:
+ if (last_task_used_math != current) {
+ if (!current->used_math) {
+ fpu_emulator_init_fpu();
+ current->used_math = 1;
+ }
+ }
+ sig = fpu_emulator_cop1Handler(regs);
+ last_task_used_math = current;
+ if (sig)
+ force_sig(sig, current);
+ return;
+
bad_cid:
force_sig(SIGILL, current);
}
-void do_watch(struct pt_regs *regs)
+asmlinkage void do_watch(struct pt_regs *regs)
{
/*
* We use the watch exception where available to detect stack
@@ -703,14 +672,14 @@
panic("Caught WATCH exception - probably caused by stack overflow.");
}
-void do_mcheck(struct pt_regs *regs)
+asmlinkage void do_mcheck(struct pt_regs *regs)
{
show_regs(regs);
panic("Caught Machine Check exception - probably caused by multiple "
"matching entries in the TLB.");
}
-void do_reserved(struct pt_regs *regs)
+asmlinkage void do_reserved(struct pt_regs *regs)
{
/*
* Game over - no way to handle this if it ever occurs. Most probably
@@ -723,34 +692,19 @@
static inline void watch_init(void)
{
- if(mips_cpu.options & MIPS_CPU_WATCH ) {
- (void)set_except_vector(23, handle_watch);
+ if (mips_cpu.options & MIPS_CPU_WATCH ) {
+ set_except_vector(23, handle_watch);
watch_available = 1;
}
}
/*
- * Some MIPS CPUs have a dedicated interrupt vector which reduces the
- * interrupt processing overhead. Use it where available.
- */
-static inline void setup_dedicated_int(void)
-{
- extern void except_vec4(void);
-
- if(mips_cpu.options & MIPS_CPU_DIVEC) {
- memcpy((void *)(KSEG0 + 0x200), except_vec4, 8);
- set_cp0_cause(CAUSEF_IV);
- dedicated_iv_available = 1;
- }
-}
-
-/*
- * Some MIPS CPUs can enable/disable for cache parity detection, but does
+ * Some MIPS CPUs can enable/disable for cache parity detection, but do
* it different ways.
*/
static inline void parity_protection_init(void)
{
- switch(mips_cpu.cputype) {
+ switch (mips_cpu.cputype) {
case CPU_5KC:
/* Set the PE bit (bit 31) in the CP0_ECC register. */
printk(KERN_INFO "Enable the cache parity protection for "
@@ -764,38 +718,39 @@
}
}
-void cache_parity_error(void)
+asmlinkage void cache_parity_error(void)
{
- unsigned int reg_val;
+ unsigned int reg_val;
- /* For the moment, report the problem and hang. */
- reg_val = read_32bit_cp0_register(CP0_ERROREPC);
+ /* For the moment, report the problem and hang. */
+ reg_val = read_32bit_cp0_register(CP0_ERROREPC);
printk("Cache error exception:\n");
printk("cp0_errorepc == %08x\n", reg_val);
reg_val = read_32bit_cp0_register(CP0_CACHEERR);
printk("cp0_cacheerr == %08x\n", reg_val);
printk("Decoded CP0_CACHEERR: %s cache fault in %s reference.\n",
- reg_val&(1<<30)?"secondary":"primary",
- reg_val&(1<<31)?"data":"insn");
+ reg_val & (1<<30) ? "secondary" : "primary",
+ reg_val & (1<<31) ? "data" : "insn");
printk("Error bits: %s%s%s%s%s%s%s\n",
- reg_val&(1<<29)?"ED ":"",
- reg_val&(1<<28)?"ET ":"",
- reg_val&(1<<26)?"EE ":"",
- reg_val&(1<<25)?"EB ":"",
- reg_val&(1<<24)?"EI ":"",
- reg_val&(1<<23)?"E1 ":"",
- reg_val&(1<<22)?"E0 ":"");
- printk("IDX: 0x%08x\n", reg_val&((1<<22)-1));
+ reg_val & (1<<29) ? "ED " : "",
+ reg_val & (1<<28) ? "ET " : "",
+ reg_val & (1<<26) ? "EE " : "",
+ reg_val & (1<<25) ? "EB " : "",
+ reg_val & (1<<24) ? "EI " : "",
+ reg_val & (1<<23) ? "E1 " : "",
+ reg_val & (1<<22) ? "E0 " : "");
+ printk("IDX: 0x%08x\n", reg_val & ((1<<22)-1));
if (reg_val&(1<<22))
- printk("DErrAddr0: 0x%08x\n", read_32bit_cp0_set1_register(CP0_S1_DERRADDR0));
+ printk("DErrAddr0: 0x%08x\n",
+ read_32bit_cp0_set1_register(CP0_S1_DERRADDR0));
if (reg_val&(1<<23))
- printk("DErrAddr1: 0x%08x\n", read_32bit_cp0_set1_register(CP0_S1_DERRADDR1));
+ printk("DErrAddr1: 0x%08x\n",
+ read_32bit_cp0_set1_register(CP0_S1_DERRADDR1));
-
- panic("Can't handle the cache error - panic!");
+ panic("Can't handle the cache error!");
}
unsigned long exception_handlers[32];
@@ -810,7 +765,8 @@
unsigned handler = (unsigned long) addr;
unsigned old_handler = exception_handlers[n];
exception_handlers[n] = handler;
- if (n == 0 && dedicated_iv_available) {
+
+ if (n == 0 && mips_cpu.options & MIPS_CPU_DIVEC) {
*(volatile u32 *)(KSEG0+0x200) = 0x08000000 |
(0x03ffffff & (handler >> 2));
flush_icache_range(KSEG0+0x200, KSEG0 + 0x204);
@@ -823,10 +779,8 @@
extern asmlinkage int _save_fp_context(struct sigcontext *sc);
extern asmlinkage int _restore_fp_context(struct sigcontext *sc);
-#ifdef CONFIG_MIPS_FPU_EMULATOR
extern asmlinkage int fpu_emulator_save_context(struct sigcontext *sc);
extern asmlinkage int fpu_emulator_restore_context(struct sigcontext *sc);
-#endif
void __init trap_init(void)
{
@@ -834,13 +788,10 @@
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;
- if(mips_machtype == MACH_MIPS_MAGNUM_4000 ||
- mips_machtype == MACH_SNI_RM200_PCI)
- EISA_bus = 1;
-
/* Some firmware leaves the BEV flag set, clear it. */
clear_cp0_status(ST0_BEV);
@@ -852,8 +803,8 @@
/*
* Setup default vectors
*/
- for(i = 0; i <= 31; i++)
- (void)set_except_vector(i, handle_reserved);
+ for (i = 0; i <= 31; i++)
+ set_except_vector(i, handle_reserved);
/*
* Copy the EJTAG debug exception vector handler code to it's final
@@ -866,7 +817,15 @@
* interrupt vector.
*/
watch_init();
- setup_dedicated_int();
+
+ /*
+ * 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) {
+ memcpy((void *)(KSEG0 + 0x200), &except_vec4, 8);
+ set_cp0_cause(CAUSEF_IV);
+ }
/*
* Some CPUs can enable/disable for cache parity detection, but does
@@ -874,35 +833,38 @@
*/
parity_protection_init();
- (void)set_except_vector(1, handle_mod);
- (void)set_except_vector(2, handle_tlbl);
- (void)set_except_vector(3, handle_tlbs);
- (void)set_except_vector(4, handle_adel);
- (void)set_except_vector(5, handle_ades);
+ 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.
*/
- (void)set_except_vector(6, handle_ibe);
- (void)set_except_vector(7, handle_dbe);
+ 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;
- (void)set_except_vector(8, handle_sys);
- (void)set_except_vector(9, handle_bp);
- (void)set_except_vector(10, handle_ri);
- (void)set_except_vector(11, handle_cpu);
- (void)set_except_vector(12, handle_ov);
- (void)set_except_vector(13, handle_tr);
- (void)set_except_vector(15, handle_fpe);
-
+ set_except_vector(8, handle_sys);
+ set_except_vector(9, handle_bp);
+ set_except_vector(10, handle_ri);
+ set_except_vector(11, handle_cpu);
+ set_except_vector(12, handle_ov);
+ set_except_vector(13, handle_tr);
+
+ if (mips_cpu.options & MIPS_CPU_FPU)
+ set_except_vector(15, handle_fpe);
+
/*
* 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) {
+ 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);
@@ -919,36 +881,25 @@
0x80);
}
- if(mips_cpu.options & MIPS_CPU_FPU) {
+ if (mips_cpu.options & MIPS_CPU_FPU) {
save_fp_context = _save_fp_context;
restore_fp_context = _restore_fp_context;
-#ifdef CONFIG_MIPS_FPU_EMULATOR
} else {
save_fp_context = fpu_emulator_save_context;
restore_fp_context = fpu_emulator_restore_context;
-#endif
}
- } else switch(mips_cpu.cputype) {
- case CPU_R10000:
- /*
- * The R10000 is in most aspects similar to the R4400. It
- * should get some special optimizations.
- */
- write_32bit_cp0_register(CP0_FRAMEMASK, 0);
- set_cp0_status(ST0_XX);
+ } else switch (mips_cpu.cputype) {
+ case CPU_SB1:
/*
- * The R10k might even work for Linux/MIPS - but we're paranoid
- * and refuse to run until this is tested on real silicon
+ * XXX - This should be folded in to the "cleaner" handling,
+ * above
*/
- panic("CPU too expensive - making holiday in the ANDES!");
- break;
- case CPU_SB1:
- /* 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;
- /* Enable timer interrupt and scd mapped interrupt in status register */
+
+ /* Enable timer interrupt and scd mapped interrupt */
clear_cp0_status(0xf000);
set_cp0_status(0xc00);
break;
@@ -983,17 +934,15 @@
memcpy((void *)KSEG0, &except_vec0_r2300, 0x80);
memcpy((void *)(KSEG0 + 0x80), &except_vec3_generic, 0x80);
break;
- case CPU_R8000:
- printk("Detected unsupported CPU type %s.\n",
- cpu_names[mips_cpu.cputype]);
- panic("Can't handle CPU");
- break;
case CPU_UNKNOWN:
default:
panic("Unknown CPU type");
}
flush_icache_range(KSEG0, KSEG0 + 0x200);
+
+ 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;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)