diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-12-10 07:56:02 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-12-10 07:56:02 +0000 |
commit | 57826f276a6fc8de0665dd956f78533fe0c25c7e (patch) | |
tree | 467de18afa9e4a3b3c02073a945a317a850991d7 | |
parent | 5c03a0eb664aa8802f9e3ede6fb6531581302762 (diff) |
Final round of FPU emulator bits.
-rw-r--r-- | arch/mips/kernel/ptrace.c | 38 | ||||
-rw-r--r-- | arch/mips/kernel/r2300_fpu.S | 13 | ||||
-rw-r--r-- | arch/mips/kernel/r4k_fpu.S | 13 | ||||
-rw-r--r-- | arch/mips/kernel/r6000_fpu.S | 10 | ||||
-rw-r--r-- | arch/mips/kernel/signal.c | 5 | ||||
-rw-r--r-- | arch/mips/kernel/traps.c | 233 | ||||
-rw-r--r-- | arch/mips/kernel/unaligned.c | 15 | ||||
-rw-r--r-- | arch/mips/math-emu/cp1emu.c | 16 | ||||
-rw-r--r-- | arch/mips/tools/offset.c | 11 | ||||
-rw-r--r-- | include/asm-mips/asmmacro.h | 200 | ||||
-rw-r--r-- | include/asm-mips/system.h | 8 |
11 files changed, 345 insertions, 217 deletions
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 618f418f8..02ef1a754 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -7,7 +7,10 @@ * Copyright (C) Linus Torvalds * Copyright (C) 1994, 95, 96, 97, 98, 2000 Ralf Baechle * Copyright (C) 1996 David S. Miller + * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com + * Copyright (C) 1999 MIPS Technologies, Inc. */ +#include <linux/config.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/mm.h> @@ -24,6 +27,7 @@ #include <asm/system.h> #include <asm/uaccess.h> #include <asm/bootinfo.h> +#include <asm/cpu.h> asmlinkage int sys_ptrace(long request, long pid, long addr, long data) { @@ -131,13 +135,22 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) break; case FPR_BASE ... FPR_BASE + 31: if (child->used_math) { + unsigned long long *fregs + = (unsigned long long *) + &child->thread.fpu.hard.fp_regs[0]; +#ifdef CONFIG_MIPS_FPU_EMULATOR + if(!(mips_cpu.options & MIPS_CPU_FPU)) { + fregs = (unsigned long long *) + &child->thread.fpu.soft.regs[0]; + } else +#endif if (last_task_used_math == child) { enable_cp1(); save_fp(child); disable_cp1(); last_task_used_math = NULL; } - tmp = child->thread.fpu.hard.fp_regs[addr - 32]; + tmp = (unsigned long) fregs[(addr - 32)]; } else { tmp = -1; /* FP not yet used */ } @@ -158,6 +171,11 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) tmp = regs->lo; break; case FPC_CSR: +#ifdef CONFIG_MIPS_FPU_EMULATOR + if(!(mips_cpu.options & MIPS_CPU_FPU)) + tmp = child->thread.fpu.soft.sr; + else +#endif tmp = child->thread.fpu.hard.control; break; case FPC_EIR: { /* implementation / version register */ @@ -198,9 +216,17 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) regs->regs[addr] = data; break; case FPR_BASE ... FPR_BASE + 31: { - unsigned int *fregs; + unsigned long long *fregs; + fregs = (unsigned long long *)&child->thread.fpu.hard.fp_regs[0]; if (child->used_math) { - if (last_task_used_math == child) { + if (last_task_used_math == child) +#ifdef CONFIG_MIPS_FPU_EMULATOR + if(!(mips_cpu.options & MIPS_CPU_FPU)) { + fregs = (unsigned long long *) + &child->thread.fpu.soft.regs[0]; + } else +#endif + { enable_cp1(); save_fp(child); disable_cp1(); @@ -213,7 +239,6 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) sizeof(child->thread.fpu.hard)); child->thread.fpu.hard.control = 0; } - fregs = child->thread.fpu.hard.fp_regs; fregs[addr - FPR_BASE] = data; break; } @@ -227,6 +252,11 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) regs->lo = data; break; case FPC_CSR: +#ifdef CONFIG_MIPS_FPU_EMULATOR + if(!(mips_cpu.options & MIPS_CPU_FPU)) + child->thread.fpu.soft.sr = data; + else +#endif child->thread.fpu.hard.control = data; break; default: diff --git a/arch/mips/kernel/r2300_fpu.S b/arch/mips/kernel/r2300_fpu.S index efb00dce1..34881ef94 100644 --- a/arch/mips/kernel/r2300_fpu.S +++ b/arch/mips/kernel/r2300_fpu.S @@ -1,7 +1,4 @@ -/* $Id: r2300_fpu.S,v 1.6 1999/08/09 19:43:14 harald Exp $ - * - * r2300_fpu.S: Save/restore floating point context for signal handlers. - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. @@ -30,7 +27,7 @@ .set noreorder .set mips1 /* Save floating point context */ -LEAF(save_fp_context) +LEAF(_save_fp_context) li v0, 0 # assume success cfc1 t1,fcr31 EX(swc1 $f0,(SC_FPREGS+0)(a0)) @@ -71,7 +68,7 @@ LEAF(save_fp_context) .set nomacro EX(sw t0,SC_FPC_EIR(a0)) .set macro - END(save_fp_context) + END(_save_fp_context) /* * Restore FPU state: @@ -82,7 +79,7 @@ LEAF(save_fp_context) * frame on the current content of c0_status, not on the content of the * stack frame which might have been changed by the user. */ -LEAF(restore_fp_context) +LEAF(_restore_fp_context) li v0, 0 # assume success EX(lw t0,SC_FPC_CSR(a0)) EX(lwc1 $f0,(SC_FPREGS+0)(a0)) @@ -119,7 +116,7 @@ LEAF(restore_fp_context) EX(lwc1 $f31,(SC_FPREGS+248)(a0)) jr ra ctc1 t0,fcr31 - END(restore_fp_context) + END(_restore_fp_context) .type fault@function .ent fault diff --git a/arch/mips/kernel/r4k_fpu.S b/arch/mips/kernel/r4k_fpu.S index d55ac303a..6ad810d04 100644 --- a/arch/mips/kernel/r4k_fpu.S +++ b/arch/mips/kernel/r4k_fpu.S @@ -1,6 +1,4 @@ /* - * r4k_fpu.S: Save/restore floating point context for signal handlers. - * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. @@ -9,6 +7,9 @@ * * Multi-arch abstraction and asm macros for easier reading: * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. */ #include <asm/asm.h> #include <asm/errno.h> @@ -26,7 +27,7 @@ .set noreorder .set mips3 /* Save floating point context */ -LEAF(save_fp_context) +LEAF(_save_fp_context) li v0, 0 # assume success cfc1 t1,fcr31 @@ -54,7 +55,7 @@ LEAF(save_fp_context) .set nomacro EX(sw t0,SC_FPC_EIR(a0)) .set macro - END(save_fp_context) + END(_save_fp_context) /* * Restore FPU state: @@ -65,7 +66,7 @@ LEAF(save_fp_context) * frame on the current content of c0_status, not on the content of the * stack frame which might have been changed by the user. */ -LEAF(restore_fp_context) +LEAF(_restore_fp_context) li v0, 0 # assume success EX(lw t0,SC_FPC_CSR(a0)) @@ -91,7 +92,7 @@ LEAF(restore_fp_context) EX(ldc1 $f30,(SC_FPREGS+240)(a0)) jr ra ctc1 t0,fcr31 - END(restore_fp_context) + END(_restore_fp_context) .type fault@function .ent fault diff --git a/arch/mips/kernel/r6000_fpu.S b/arch/mips/kernel/r6000_fpu.S index 851b4dc48..d8d3b13fe 100644 --- a/arch/mips/kernel/r6000_fpu.S +++ b/arch/mips/kernel/r6000_fpu.S @@ -9,8 +9,6 @@ * * Multi-arch abstraction and asm macros for easier reading: * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * - * $Id: r6000_fpu.S,v 1.5 1999/05/01 22:40:37 ralf Exp $ */ #include <asm/asm.h> #include <asm/fpregdef.h> @@ -21,7 +19,7 @@ .set noreorder .set mips2 /* Save floating point context */ - LEAF(save_fp_context) + LEAF(_save_fp_context) mfc0 t0,CP0_STATUS sll t0,t0,2 bgez t0,1f @@ -49,7 +47,7 @@ sw t0,SC_FPC_CSR(a0) 1: jr ra nop - END(save_fp_context) + END(_save_fp_context) /* Restore FPU state: * - fp gp registers @@ -59,7 +57,7 @@ * frame on the current content of c0_status, not on the content of the * stack frame which might have been changed by the user. */ - LEAF(restore_fp_context) + LEAF(_restore_fp_context) mfc0 t0,CP0_STATUS sll t0,t0,2 @@ -86,4 +84,4 @@ ctc1 t0,fcr31 1: jr ra nop - END(restore_fp_context) + END(_restore_fp_context) diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index ed821d7df..a1e26db87 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c @@ -33,8 +33,9 @@ extern asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr, int options, unsigned long *ru); extern asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs); -extern asmlinkage int save_fp_context(struct sigcontext *sc); -extern asmlinkage int restore_fp_context(struct sigcontext *sc); + +extern asmlinkage int (*save_fp_context)(struct sigcontext *sc); +extern asmlinkage int (*restore_fp_context)(struct sigcontext *sc); extern asmlinkage void syscall_trace(void); diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 0abd55e78..779b72805 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -7,6 +7,9 @@ * 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. */ #include <linux/config.h> #include <linux/init.h> @@ -28,6 +31,9 @@ #include <asm/system.h> #include <asm/uaccess.h> #include <asm/mmu_context.h> +#ifndef CONFIG_MIPS_FPU_EMULATOR +#include <asm/inst.h> +#endif extern int console_loglevel; @@ -66,6 +72,7 @@ extern asmlinkage void handle_ov(void); extern asmlinkage void handle_tr(void); extern asmlinkage void handle_fpe(void); extern asmlinkage void handle_watch(void); +extern asmlinkage void handle_mcheck(void); extern asmlinkage void handle_reserved(void); extern int fpu_emulator_cop1Handler(int, struct pt_regs *); @@ -377,6 +384,8 @@ void do_fpe(struct pt_regs *regs, unsigned long fcr31) /* 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__( @@ -386,13 +395,26 @@ void do_fpe(struct pt_regs *regs, unsigned long fcr31) return; } pc = regs->cp0_epc + ((regs->cp0_cause & CAUSEF_BD) ? 4 : 0); - if (get_user(insn, (unsigned int *)pc)) + if(pc & 0x80000000) insn = *(unsigned int *)pc; + else if (get_user(insn, (unsigned int *)pc)) { + /* XXX Can this happen? */ force_sig(SIGSEGV, current); -#endif /* !CONFIG_MIPS_FPU_EMULATOR */ + } + + 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; } - if (!compute_return_epc(regs)) - force_sig(SIGFPE, current); + 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) @@ -465,8 +487,9 @@ void do_ri(struct pt_regs *regs) if ((opcode & OPCODE) == SC) simulate_sc(regs, opcode); } else { - printk("[%s:%d] Illegal instruction at %08lx ra=%08lx\n", - current->comm, current->pid, regs->cp0_epc, regs->regs[31]); + printk("[%s:%ld] Illegal instruction %08x at %08lx ra=%08lx\n", + current->comm, (unsigned long)current->pid, opcode, + regs->cp0_epc, regs->regs[31]); } if (compute_return_epc(regs)) return; @@ -553,8 +576,12 @@ void simulate_sc(struct pt_regs *regp, unsigned int opcode) void do_ri(struct pt_regs *regs) { - printk("[%s:%d] Illegal instruction at %08lx ra=%08lx\n", - current->comm, current->pid, regs->cp0_epc, regs->regs[31]); + 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]); if (compute_return_epc(regs)) return; force_sig(SIGILL, current); @@ -622,6 +649,12 @@ void do_watch(struct pt_regs *regs) panic("Caught WATCH exception - probably caused by stack overflow."); } +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) { /* @@ -632,40 +665,61 @@ void do_reserved(struct pt_regs *regs) panic("Caught reserved exception - should not happen."); } -static inline void watch_init(unsigned long cputype) +static inline void watch_init(void) { - switch(cputype) { - case CPU_R10000: - case CPU_R4000MC: - case CPU_R4400MC: - case CPU_R4000SC: - case CPU_R4400SC: - case CPU_R4000PC: - case CPU_R4400PC: - case CPU_R4200: - case CPU_R4300: - set_except_vector(23, handle_watch); - watch_available = 1; - break; - } + if(mips_cpu.options & MIPS_CPU_WATCH ) { + (void)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. - * FIXME: more CPUs than just the Nevada have this feature. */ static inline void setup_dedicated_int(void) { extern void except_vec4(void); - switch(mips_cpu.cputype) { - case CPU_NEVADA: + + if(mips_cpu.options & MIPS_CPU_DIVEC) { memcpy((void *)(KSEG0 + 0x200), except_vec4, 8); set_cp0_cause(CAUSEF_IV, CAUSEF_IV); dedicated_iv_available = 1; } } +/* + * Some MIPS CPUs can enable/disable for cache parity detection, but does + * it different ways. + */ +static inline void parity_protection_init(void) +{ + switch(mips_cpu.cputype) + { + case CPU_5KC: + /* Set the PE bit (bit 31) in the CP0_ECC register. */ + printk("Enable the cache parity protection for MIPS 5KC CPUs.\n"); + write_32bit_cp0_register(CP0_ECC, read_32bit_cp0_register(CP0_ECC) + | 0x80000000); + break; + default: + } +} + +void cache_parity_error(void) +{ + unsigned int reg_val; + + /* 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("c0_cacheerr == %08x\n", reg_val); + + panic("Can't handle the cache error - panic!"); +} + unsigned long exception_handlers[32]; /* @@ -673,23 +727,36 @@ unsigned long exception_handlers[32]; * to interrupt handlers in the address range from * KSEG0 <= x < KSEG0 + 256mb on the Nevada. Oh well ... */ -void set_except_vector(int n, void *addr) +void *set_except_vector(int n, void *addr) { unsigned handler = (unsigned long) addr; + unsigned old_handler = exception_handlers[n]; exception_handlers[n] = handler; if (n == 0 && dedicated_iv_available) { *(volatile u32 *)(KSEG0+0x200) = 0x08000000 | (0x03ffffff & (handler >> 2)); flush_icache_range(KSEG0+0x200, KSEG0 + 0x204); } + return (void *)old_handler; } +asmlinkage int (*save_fp_context)(struct sigcontext *sc); +asmlinkage int (*restore_fp_context)(struct sigcontext *sc); +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) { 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_vec_ejtag_debug; unsigned long i; if(mips_machtype == MACH_MIPS_MAGNUM_4000 || @@ -708,71 +775,55 @@ void __init trap_init(void) * Setup default vectors */ for(i = 0; i <= 31; i++) - set_except_vector(i, handle_reserved); + (void)set_except_vector(i, handle_reserved); + + /* + * Copy the EJTAG debug exception vector handler code to it's final + * destination. + */ + memcpy((void *)(KSEG0 + 0x300), &except_vec_ejtag_debug, 0x80); /* * Only some CPUs have the watch exceptions or a dedicated * interrupt vector. */ - watch_init(mips_cpu.cputype); + watch_init(); setup_dedicated_int(); - 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); + /* + * Some CPUs can enable/disable for cache parity detection, but does + * it different ways. + */ + 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); /* * 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); + (void)set_except_vector(6, handle_ibe); + (void)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); - set_except_vector(10, handle_ri); - set_except_vector(11, handle_cpu); - set_except_vector(12, handle_ov); - set_except_vector(13, handle_tr); - set_except_vector(15, handle_fpe); - + (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); + /* * Handling the following exceptions depends mostly of the cpu type */ - 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, ST0_XX); - /* - * The R10k might even work for Linux/MIPS - but we're paranoid - * and refuse to run until this is tested on real silicon - */ - panic("CPU too expensive - making holiday in the ANDES!"); - break; - case CPU_R4000MC: - case CPU_R4400MC: - case CPU_R4000SC: - case CPU_R4400SC: - vce_available = 1; - /* Fall through ... */ - case CPU_R4000PC: - case CPU_R4400PC: - case CPU_R4200: - case CPU_R4300: - /* case CPU_R4640: */ - case CPU_R4600: - case CPU_R5000: - case CPU_R5432: - case CPU_NEVADA: - case CPU_RM7000: + 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) @@ -782,17 +833,41 @@ void __init trap_init(void) /* Cache error vector already set above. */ - if (vce_available) { + if (mips_cpu.options & MIPS_CPU_VCE) { memcpy((void *)(KSEG0 + 0x180), &except_vec3_r4000, 0x80); } else { memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic, 0x80); } - break; + 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, ST0_XX); + /* + * The R10k might even work for Linux/MIPS - but we're paranoid + * and refuse to run until this is tested on real silicon + */ + panic("CPU too expensive - making holiday in the ANDES!"); + break; case CPU_R6000: case CPU_R6000A: + save_fp_context = _save_fp_context; + restore_fp_context = _restore_fp_context; #if 0 /* * The R6000 is the only R-series CPU that features a machine @@ -802,8 +877,8 @@ void __init trap_init(void) * current list of targets for Linux/MIPS. * (Duh, crap, there is someone with a tripple R6k machine) */ - set_except_vector(14, handle_mc); - set_except_vector(15, handle_ndc); + (void)set_except_vector(14, handle_mc); + (void)set_except_vector(15, handle_ndc); #endif case CPU_R2000: case CPU_R3000: @@ -813,6 +888,8 @@ void __init trap_init(void) case CPU_R3052: case CPU_R3081: case CPU_R3081E: + save_fp_context = _save_fp_context; + restore_fp_context = _restore_fp_context; memcpy((void *)KSEG0, &except_vec0_r2300, 0x80); memcpy((void *)(KSEG0 + 0x80), &except_vec3_generic, 0x80); break; diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c index a5b8791c1..672388d52 100644 --- a/arch/mips/kernel/unaligned.c +++ b/arch/mips/kernel/unaligned.c @@ -379,6 +379,21 @@ unsigned long unaligned_instructions; asmlinkage void do_ade(struct pt_regs *regs) { unsigned long pc; +#ifdef CONFIG_MIPS_FPU_EMULATOR + extern int do_dsemulret(struct pt_regs *); + + /* + * Address errors may be deliberately induced + * by the FPU emulator to take retake control + * of the CPU after executing the instruction + * in the delay slot of an emulated branch. + */ + + if((unsigned long)regs->cp0_epc == current->thread.dsemul_aerpc) { + (void)do_dsemulret(regs); + return; + } +#endif /* CONFIG_MIPS_FPU_EMULATOR */ /* * Did we catch a fault trying to load an instruction? diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index a95e4e600..e26bacd24 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -872,14 +872,14 @@ mips_dsemul(struct pt_regs *xcp, mips_instruction ir, vaddr_t cpc) * cond = ieee754dp_cmp(x,y,IEEE754_UN); */ static const unsigned char cmptab[8] = { - 0, /* cmp_0 (sig) cmp_sf */ - IEEE754_CUN, /* cmp_un (sig) cmp_ngle */ - IEEE754_CEQ, /* cmp_eq (sig) cmp_seq */ - IEEE754_CEQ | IEEE754_CUN, /* cmp_ueq (sig) cmp_ngl */ - IEEE754_CLT, /* cmp_olt (sig) cmp_lt */ - IEEE754_CLT | IEEE754_CUN, /* cmp_ult (sig) cmp_nge */ - IEEE754_CLT | IEEE754_CEQ, /* cmp_ole (sig) cmp_le */ - IEEE754_CLT | IEEE754_CEQ | IEEE754_CUN, /* cmp_ule (sig) cmp_ngt */ + 0, /* cmp_0 (sig) cmp_sf */ + IEEE754_CUN, /* cmp_un (sig) cmp_ngle */ + IEEE754_CEQ, /* cmp_eq (sig) cmp_seq */ + IEEE754_CEQ | IEEE754_CUN, /* cmp_ueq (sig) cmp_ngl */ + IEEE754_CLT, /* cmp_olt (sig) cmp_lt */ + IEEE754_CLT | IEEE754_CUN, /* cmp_ult (sig) cmp_nge */ + IEEE754_CLT | IEEE754_CEQ, /* cmp_ole (sig) cmp_le */ + IEEE754_CLT | IEEE754_CEQ | IEEE754_CUN, /* cmp_ule (sig) cmp_ngt */ }; #define SIFROMREG(si,x) ((si) = ctx->regs[x]) diff --git a/arch/mips/tools/offset.c b/arch/mips/tools/offset.c index 977a791d8..7df4a6c1d 100644 --- a/arch/mips/tools/offset.c +++ b/arch/mips/tools/offset.c @@ -1,12 +1,13 @@ -/* $Id: offset.c,v 1.11 1999/09/28 22:25:50 ralf Exp $ - * +/* * offset.c: Calculate pt_regs and task_struct offsets. * * Copyright (C) 1996 David S. Miller * Copyright (C) 1997, 1998, 1999 Ralf Baechle * Copyright (C) 1999 Silicon Graphics, Inc. + * + * Kevin Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. */ - #include <linux/types.h> #include <linux/sched.h> @@ -120,6 +121,10 @@ void output_thread_defines(void) thread.irix_trampoline); offset("#define THREAD_OLDCTX ", struct task_struct, \ thread.irix_oldctx); + offset("#define THREAD_DSEEPC ", struct task_struct, \ + thread.dsemul_epc); + offset("#define THREAD_DSEAERPC ", struct task_struct, \ + thread.dsemul_aerpc); linefeed; } diff --git a/include/asm-mips/asmmacro.h b/include/asm-mips/asmmacro.h index fb3692dd7..7becc9bd1 100644 --- a/include/asm-mips/asmmacro.h +++ b/include/asm-mips/asmmacro.h @@ -3,124 +3,122 @@ * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * Copyright (C) 1998 Ralf Baechle - * - * $Id: asmmacro.h,v 1.3 1998/03/27 04:47:58 ralf Exp $ */ -#ifndef __MIPS_ASMMACRO_H -#define __MIPS_ASMMACRO_H +#ifndef _ASM_ASMMACRO_H +#define _ASM_ASMMACRO_H #include <asm/offset.h> #define FPU_SAVE_DOUBLE(thread, tmp) \ cfc1 tmp, fcr31; \ sdc1 $f0, (THREAD_FPU + 0x000)(thread); \ - sdc1 $f2, (THREAD_FPU + 0x008)(thread); \ - sdc1 $f4, (THREAD_FPU + 0x010)(thread); \ - sdc1 $f6, (THREAD_FPU + 0x018)(thread); \ - sdc1 $f8, (THREAD_FPU + 0x020)(thread); \ - sdc1 $f10, (THREAD_FPU + 0x028)(thread); \ - sdc1 $f12, (THREAD_FPU + 0x030)(thread); \ - sdc1 $f14, (THREAD_FPU + 0x038)(thread); \ - sdc1 $f16, (THREAD_FPU + 0x040)(thread); \ - sdc1 $f18, (THREAD_FPU + 0x048)(thread); \ - sdc1 $f20, (THREAD_FPU + 0x050)(thread); \ - sdc1 $f22, (THREAD_FPU + 0x058)(thread); \ - sdc1 $f24, (THREAD_FPU + 0x060)(thread); \ - sdc1 $f26, (THREAD_FPU + 0x068)(thread); \ - sdc1 $f28, (THREAD_FPU + 0x070)(thread); \ - sdc1 $f30, (THREAD_FPU + 0x078)(thread); \ - sw tmp, (THREAD_FPU + 0x080)(thread) + sdc1 $f2, (THREAD_FPU + 0x010)(thread); \ + sdc1 $f4, (THREAD_FPU + 0x020)(thread); \ + sdc1 $f6, (THREAD_FPU + 0x030)(thread); \ + sdc1 $f8, (THREAD_FPU + 0x040)(thread); \ + sdc1 $f10, (THREAD_FPU + 0x050)(thread); \ + sdc1 $f12, (THREAD_FPU + 0x060)(thread); \ + sdc1 $f14, (THREAD_FPU + 0x070)(thread); \ + sdc1 $f16, (THREAD_FPU + 0x080)(thread); \ + sdc1 $f18, (THREAD_FPU + 0x090)(thread); \ + sdc1 $f20, (THREAD_FPU + 0x0a0)(thread); \ + sdc1 $f22, (THREAD_FPU + 0x0b0)(thread); \ + sdc1 $f24, (THREAD_FPU + 0x0c0)(thread); \ + sdc1 $f26, (THREAD_FPU + 0x0d0)(thread); \ + sdc1 $f28, (THREAD_FPU + 0x0e0)(thread); \ + sdc1 $f30, (THREAD_FPU + 0x0f0)(thread); \ + sw tmp, (THREAD_FPU + 0x100)(thread) #define FPU_SAVE_SINGLE(thread,tmp) \ cfc1 tmp, fcr31; \ swc1 $f0, (THREAD_FPU + 0x000)(thread); \ - swc1 $f1, (THREAD_FPU + 0x004)(thread); \ - swc1 $f2, (THREAD_FPU + 0x008)(thread); \ - swc1 $f3, (THREAD_FPU + 0x00c)(thread); \ - swc1 $f4, (THREAD_FPU + 0x010)(thread); \ - swc1 $f5, (THREAD_FPU + 0x014)(thread); \ - swc1 $f6, (THREAD_FPU + 0x018)(thread); \ - swc1 $f7, (THREAD_FPU + 0x01c)(thread); \ - swc1 $f8, (THREAD_FPU + 0x020)(thread); \ - swc1 $f9, (THREAD_FPU + 0x024)(thread); \ - swc1 $f10, (THREAD_FPU + 0x028)(thread); \ - swc1 $f11, (THREAD_FPU + 0x02c)(thread); \ - swc1 $f12, (THREAD_FPU + 0x030)(thread); \ - swc1 $f13, (THREAD_FPU + 0x034)(thread); \ - swc1 $f14, (THREAD_FPU + 0x038)(thread); \ - swc1 $f15, (THREAD_FPU + 0x03c)(thread); \ - swc1 $f16, (THREAD_FPU + 0x040)(thread); \ - swc1 $f17, (THREAD_FPU + 0x044)(thread); \ - swc1 $f18, (THREAD_FPU + 0x048)(thread); \ - swc1 $f19, (THREAD_FPU + 0x04c)(thread); \ - swc1 $f20, (THREAD_FPU + 0x050)(thread); \ - swc1 $f21, (THREAD_FPU + 0x054)(thread); \ - swc1 $f22, (THREAD_FPU + 0x058)(thread); \ - swc1 $f23, (THREAD_FPU + 0x05c)(thread); \ - swc1 $f24, (THREAD_FPU + 0x060)(thread); \ - swc1 $f25, (THREAD_FPU + 0x064)(thread); \ - swc1 $f26, (THREAD_FPU + 0x068)(thread); \ - swc1 $f27, (THREAD_FPU + 0x06c)(thread); \ - swc1 $f28, (THREAD_FPU + 0x070)(thread); \ - swc1 $f29, (THREAD_FPU + 0x074)(thread); \ - swc1 $f30, (THREAD_FPU + 0x078)(thread); \ - swc1 $f31, (THREAD_FPU + 0x07c)(thread); \ - sw tmp, (THREAD_FPU + 0x080)(thread) + swc1 $f1, (THREAD_FPU + 0x008)(thread); \ + swc1 $f2, (THREAD_FPU + 0x010)(thread); \ + swc1 $f3, (THREAD_FPU + 0x018)(thread); \ + swc1 $f4, (THREAD_FPU + 0x020)(thread); \ + swc1 $f5, (THREAD_FPU + 0x028)(thread); \ + swc1 $f6, (THREAD_FPU + 0x030)(thread); \ + swc1 $f7, (THREAD_FPU + 0x038)(thread); \ + swc1 $f8, (THREAD_FPU + 0x040)(thread); \ + swc1 $f9, (THREAD_FPU + 0x048)(thread); \ + swc1 $f10, (THREAD_FPU + 0x050)(thread); \ + swc1 $f11, (THREAD_FPU + 0x058)(thread); \ + swc1 $f12, (THREAD_FPU + 0x060)(thread); \ + swc1 $f13, (THREAD_FPU + 0x068)(thread); \ + swc1 $f14, (THREAD_FPU + 0x070)(thread); \ + swc1 $f15, (THREAD_FPU + 0x078)(thread); \ + swc1 $f16, (THREAD_FPU + 0x080)(thread); \ + swc1 $f17, (THREAD_FPU + 0x088)(thread); \ + swc1 $f18, (THREAD_FPU + 0x090)(thread); \ + swc1 $f19, (THREAD_FPU + 0x098)(thread); \ + swc1 $f20, (THREAD_FPU + 0x0a0)(thread); \ + swc1 $f21, (THREAD_FPU + 0x0a8)(thread); \ + swc1 $f22, (THREAD_FPU + 0x0b0)(thread); \ + swc1 $f23, (THREAD_FPU + 0x0b8)(thread); \ + swc1 $f24, (THREAD_FPU + 0x0c0)(thread); \ + swc1 $f25, (THREAD_FPU + 0x0c8)(thread); \ + swc1 $f26, (THREAD_FPU + 0x0d0)(thread); \ + swc1 $f27, (THREAD_FPU + 0x0d8)(thread); \ + swc1 $f28, (THREAD_FPU + 0x0e0)(thread); \ + swc1 $f29, (THREAD_FPU + 0x0e8)(thread); \ + swc1 $f30, (THREAD_FPU + 0x0f0)(thread); \ + swc1 $f31, (THREAD_FPU + 0x0f8)(thread); \ + sw tmp, (THREAD_FPU + 0x100)(thread) #define FPU_RESTORE_DOUBLE(thread, tmp) \ - lw tmp, (THREAD_FPU + 0x080)(thread); \ + lw tmp, (THREAD_FPU + 0x100)(thread); \ ldc1 $f0, (THREAD_FPU + 0x000)(thread); \ - ldc1 $f2, (THREAD_FPU + 0x008)(thread); \ - ldc1 $f4, (THREAD_FPU + 0x010)(thread); \ - ldc1 $f6, (THREAD_FPU + 0x018)(thread); \ - ldc1 $f8, (THREAD_FPU + 0x020)(thread); \ - ldc1 $f10, (THREAD_FPU + 0x028)(thread); \ - ldc1 $f12, (THREAD_FPU + 0x030)(thread); \ - ldc1 $f14, (THREAD_FPU + 0x038)(thread); \ - ldc1 $f16, (THREAD_FPU + 0x040)(thread); \ - ldc1 $f18, (THREAD_FPU + 0x048)(thread); \ - ldc1 $f20, (THREAD_FPU + 0x050)(thread); \ - ldc1 $f22, (THREAD_FPU + 0x058)(thread); \ - ldc1 $f24, (THREAD_FPU + 0x060)(thread); \ - ldc1 $f26, (THREAD_FPU + 0x068)(thread); \ - ldc1 $f28, (THREAD_FPU + 0x070)(thread); \ - ldc1 $f30, (THREAD_FPU + 0x078)(thread); \ + ldc1 $f2, (THREAD_FPU + 0x010)(thread); \ + ldc1 $f4, (THREAD_FPU + 0x020)(thread); \ + ldc1 $f6, (THREAD_FPU + 0x030)(thread); \ + ldc1 $f8, (THREAD_FPU + 0x040)(thread); \ + ldc1 $f10, (THREAD_FPU + 0x050)(thread); \ + ldc1 $f12, (THREAD_FPU + 0x060)(thread); \ + ldc1 $f14, (THREAD_FPU + 0x070)(thread); \ + ldc1 $f16, (THREAD_FPU + 0x080)(thread); \ + ldc1 $f18, (THREAD_FPU + 0x090)(thread); \ + ldc1 $f20, (THREAD_FPU + 0x0a0)(thread); \ + ldc1 $f22, (THREAD_FPU + 0x0b0)(thread); \ + ldc1 $f24, (THREAD_FPU + 0x0c0)(thread); \ + ldc1 $f26, (THREAD_FPU + 0x0d0)(thread); \ + ldc1 $f28, (THREAD_FPU + 0x0e0)(thread); \ + ldc1 $f30, (THREAD_FPU + 0x0f0)(thread); \ ctc1 tmp, fcr31 #define FPU_RESTORE_SINGLE(thread,tmp) \ - lw tmp, (THREAD_FPU + 0x080)(thread); \ + lw tmp, (THREAD_FPU + 0x100)(thread); \ lwc1 $f0, (THREAD_FPU + 0x000)(thread); \ - lwc1 $f1, (THREAD_FPU + 0x004)(thread); \ - lwc1 $f2, (THREAD_FPU + 0x008)(thread); \ - lwc1 $f3, (THREAD_FPU + 0x00c)(thread); \ - lwc1 $f4, (THREAD_FPU + 0x010)(thread); \ - lwc1 $f5, (THREAD_FPU + 0x014)(thread); \ - lwc1 $f6, (THREAD_FPU + 0x018)(thread); \ - lwc1 $f7, (THREAD_FPU + 0x01c)(thread); \ - lwc1 $f8, (THREAD_FPU + 0x020)(thread); \ - lwc1 $f9, (THREAD_FPU + 0x024)(thread); \ - lwc1 $f10, (THREAD_FPU + 0x028)(thread); \ - lwc1 $f11, (THREAD_FPU + 0x02c)(thread); \ - lwc1 $f12, (THREAD_FPU + 0x030)(thread); \ - lwc1 $f13, (THREAD_FPU + 0x034)(thread); \ - lwc1 $f14, (THREAD_FPU + 0x038)(thread); \ - lwc1 $f15, (THREAD_FPU + 0x03c)(thread); \ - lwc1 $f16, (THREAD_FPU + 0x040)(thread); \ - lwc1 $f17, (THREAD_FPU + 0x044)(thread); \ - lwc1 $f18, (THREAD_FPU + 0x048)(thread); \ - lwc1 $f19, (THREAD_FPU + 0x04c)(thread); \ - lwc1 $f20, (THREAD_FPU + 0x050)(thread); \ - lwc1 $f21, (THREAD_FPU + 0x054)(thread); \ - lwc1 $f22, (THREAD_FPU + 0x058)(thread); \ - lwc1 $f23, (THREAD_FPU + 0x05c)(thread); \ - lwc1 $f24, (THREAD_FPU + 0x060)(thread); \ - lwc1 $f25, (THREAD_FPU + 0x064)(thread); \ - lwc1 $f26, (THREAD_FPU + 0x068)(thread); \ - lwc1 $f27, (THREAD_FPU + 0x06c)(thread); \ - lwc1 $f28, (THREAD_FPU + 0x070)(thread); \ - lwc1 $f29, (THREAD_FPU + 0x074)(thread); \ - lwc1 $f30, (THREAD_FPU + 0x078)(thread); \ - lwc1 $f31, (THREAD_FPU + 0x07c)(thread); \ + lwc1 $f1, (THREAD_FPU + 0x008)(thread); \ + lwc1 $f2, (THREAD_FPU + 0x010)(thread); \ + lwc1 $f3, (THREAD_FPU + 0x018)(thread); \ + lwc1 $f4, (THREAD_FPU + 0x020)(thread); \ + lwc1 $f5, (THREAD_FPU + 0x028)(thread); \ + lwc1 $f6, (THREAD_FPU + 0x030)(thread); \ + lwc1 $f7, (THREAD_FPU + 0x038)(thread); \ + lwc1 $f8, (THREAD_FPU + 0x040)(thread); \ + lwc1 $f9, (THREAD_FPU + 0x048)(thread); \ + lwc1 $f10, (THREAD_FPU + 0x050)(thread); \ + lwc1 $f11, (THREAD_FPU + 0x058)(thread); \ + lwc1 $f12, (THREAD_FPU + 0x060)(thread); \ + lwc1 $f13, (THREAD_FPU + 0x068)(thread); \ + lwc1 $f14, (THREAD_FPU + 0x070)(thread); \ + lwc1 $f15, (THREAD_FPU + 0x078)(thread); \ + lwc1 $f16, (THREAD_FPU + 0x080)(thread); \ + lwc1 $f17, (THREAD_FPU + 0x088)(thread); \ + lwc1 $f18, (THREAD_FPU + 0x090)(thread); \ + lwc1 $f19, (THREAD_FPU + 0x098)(thread); \ + lwc1 $f20, (THREAD_FPU + 0x0a0)(thread); \ + lwc1 $f21, (THREAD_FPU + 0x0a8)(thread); \ + lwc1 $f22, (THREAD_FPU + 0x0b0)(thread); \ + lwc1 $f23, (THREAD_FPU + 0x0b8)(thread); \ + lwc1 $f24, (THREAD_FPU + 0x0c0)(thread); \ + lwc1 $f25, (THREAD_FPU + 0x0c8)(thread); \ + lwc1 $f26, (THREAD_FPU + 0x0d0)(thread); \ + lwc1 $f27, (THREAD_FPU + 0x0d8)(thread); \ + lwc1 $f28, (THREAD_FPU + 0x0e0)(thread); \ + lwc1 $f29, (THREAD_FPU + 0x0e8)(thread); \ + lwc1 $f30, (THREAD_FPU + 0x0f0)(thread); \ + lwc1 $f31, (THREAD_FPU + 0x0f8)(thread); \ ctc1 tmp, fcr31 #define CPU_SAVE_NONSCRATCH(thread) \ @@ -148,4 +146,4 @@ lw fp, THREAD_REG30(thread); \ lw ra, THREAD_REG31(thread) -#endif /* !(__MIPS_ASMMACRO_H) */ +#endif /* _ASM_ASMMACRO_H */ diff --git a/include/asm-mips/system.h b/include/asm-mips/system.h index deca93a7b..68117be89 100644 --- a/include/asm-mips/system.h +++ b/include/asm-mips/system.h @@ -6,6 +6,12 @@ * Copyright (C) 1994 - 1999 by Ralf Baechle * Copyright (C) 1996 by Paul M. Antoine * Copyright (C) 1994 - 1999 by Ralf Baechle + * + * Changed set_except_vector declaration to allow return of previous + * vector address value - necessary for "borrowing" vectors. + * + * Kevin D. Kissell, kevink@mips.org and Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. */ #ifndef _ASM_SYSTEM_H #define _ASM_SYSTEM_H @@ -231,7 +237,7 @@ __xchg(unsigned long x, volatile void * ptr, int size) return x; } -extern void set_except_vector(int n, void *addr); +extern void *set_except_vector(int n, void *addr); extern void __die(const char *, struct pt_regs *, const char *where, unsigned long line) __attribute__((noreturn)); |