diff options
author | Harald Koerfgen <hkoerfg@web.de> | 1999-07-26 19:42:38 +0000 |
---|---|---|
committer | Harald Koerfgen <hkoerfg@web.de> | 1999-07-26 19:42:38 +0000 |
commit | 14ab59aa8aba8687dc957c2186e115ac0b8ab542 (patch) | |
tree | c2eb55db21b6b46ddd983e2d40196fa61f19b64c /arch/mips | |
parent | 552f7f2f262b8ea12edc36f9a260b068bd10f423 (diff) |
The remaining R3000 changes. From now on the CVS will be R3000 aware. R3000 Indigo anyone? :-)
Diffstat (limited to 'arch/mips')
-rw-r--r-- | arch/mips/kernel/entry.S | 32 | ||||
-rw-r--r-- | arch/mips/kernel/head.S | 29 | ||||
-rw-r--r-- | arch/mips/kernel/process.c | 10 | ||||
-rw-r--r-- | arch/mips/kernel/ptrace.c | 7 | ||||
-rw-r--r-- | arch/mips/kernel/scall_o32.S | 24 | ||||
-rw-r--r-- | arch/mips/kernel/traps.c | 153 | ||||
-rw-r--r-- | arch/mips/mm/r2300.c | 13 |
7 files changed, 210 insertions, 58 deletions
diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S index 534cba7cf..a740bac27 100644 --- a/arch/mips/kernel/entry.S +++ b/arch/mips/kernel/entry.S @@ -7,7 +7,7 @@ * * Copyright (C) 1994, 1995 by Ralf Baechle * - * $Id: entry.S,v 1.13 1998/10/14 23:40:43 ralf Exp $ + * $Id: entry.S,v 1.14 1999/04/12 19:13:21 harald Exp $ */ /* @@ -31,23 +31,21 @@ #include <asm/regdef.h> #include <asm/fpregdef.h> #include <asm/unistd.h> +#include <asm/isadep.h> /* * Heia ... The %lo, %hi and %HI stuff is too strong for the ELF assembler * and the ABI to cope with ... */ .text - .set noreorder - .set mips3 .align 4 + .set push + .set reorder EXPORT(handle_bottom_half) jal do_bottom_half - nop b 9f - nop reschedule: jal schedule - nop EXPORT(ret_from_sys_call) EXPORT(ret_from_irq) @@ -55,22 +53,20 @@ EXPORT(ret_from_irq) lw t1,bh_active # unused delay slot and t0,t1 bnez t0,handle_bottom_half -9: lw t0,PT_STATUS(sp) # returning to kernel mode? - andi t1, t0, 0x10 +9: lw t0,PT_STATUS(sp) # returning to kernel mode? + lw t2, TASK_NEED_RESCHED($28) + andi t1, t0, KU_USER beqz t1, return # -> yes - lw t1, TASK_NEED_RESCHED($28) - bnez t1, reschedule + bnez t2, reschedule lw v0, TASK_SIGPENDING($28) move a0, zero beqz v0, return - nop - jal do_signal move a1, sp + jal do_signal EXPORT(return) .set noat - RESTORE_ALL - eret + RESTORE_ALL_AND_RET .set at /* @@ -84,7 +80,9 @@ LEAF(spurious_interrupt) * couldn't find a cause for it. */ lui t1,%hi(spurious_count) + .set reorder lw t0,%lo(spurious_count)(t1) + .set noreorder addiu t0,1 j ret_from_irq sw t0,%lo(spurious_count)(t1) @@ -107,7 +105,9 @@ LEAF(spurious_interrupt) ctc1 a2,fcr31; \ STI #define __BUILD_clear_ade(exception) \ + .set reorder; \ MFC0 t0,CP0_BADVADDR; \ + .set noreorder; \ REG_S t0,PT_BVADDR(sp); \ KMODE #define __BUILD_silent(exception) @@ -122,9 +122,9 @@ LEAF(spurious_interrupt) #define __BUILD_count(exception) \ .set reorder; \ lw t0,exception_count_##exception; \ + .set noreorder; \ addiu t0, 1; \ sw t0,exception_count_##exception; \ - .set noreorder; \ .data; \ EXPORT(exception_count_##exception); \ .word 0; \ @@ -156,6 +156,8 @@ EXPORT(exception_count_##exception); \ BUILD_HANDLER(watch,watch,sti,verbose) /* #23 */ BUILD_HANDLER(reserved,reserved,sti,verbose) /* others */ + .set pop + /* * Table of syscalls */ diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S index 1eb0ca5dc..72d42a2da 100644 --- a/arch/mips/kernel/head.S +++ b/arch/mips/kernel/head.S @@ -1,4 +1,4 @@ -/* $Id: head.S,v 1.10 1998/10/14 23:40:44 ralf Exp $ +/* $Id: head.S,v 1.11 1998/10/18 13:27:12 tsbogend Exp $ * * arch/mips/kernel/head.S * @@ -11,7 +11,7 @@ * Copyright (C) 1995, 1996, 1997, 1998 Ralf Baechle * Copyright (C) 1996 Paul M. Antoine * Modified for DECStation and hence R3000 support by Paul M. Antoine - * Further modifications by David S. Miller + * Further modifications by David S. Miller and Harald Koerfgen * * Head.S contains the MIPS exception handler and startup code. */ @@ -258,6 +258,7 @@ /* TLB refill, EXL == 0, R[23]00 version */ LEAF(except_vec0_r2300) + .set noat .set mips1 mfc0 k0, CP0_BADVADDR _GET_CURRENT(k1) # get current task ptr @@ -267,18 +268,13 @@ addu k1, k1, k0 mfc0 k0, CP0_CONTEXT lw k1, (k1) - srl k0, k0, 1 and k0, k0, 0xffc addu k1, k1, k0 lw k0, (k1) - srl k0, k0, 12 + nop mtc0 k0, CP0_ENTRYLO0 mfc0 k1, CP0_EPC tlbwr - nop - nop - nop - nop jr k1 rfe END(except_vec0_r2300) @@ -371,6 +367,7 @@ handle_vcei: /* General exception vector. */ NESTED(except_vec3_generic, 0, sp) .set noat + .set mips0 mfc0 k1, CP0_CAUSE la k0, exception_handlers andi k1, k1, 0x7c @@ -408,6 +405,14 @@ NESTED(kernel_entry, 16, sp) probe_done: + /* + * Stack for kernel and init, current variable + */ + la $28, init_task_union + addiu t0, $28, KERNEL_STACK_SIZE-32 + sw t0, kernelsp + subu sp, t0, 4*SZREG + /* The firmware/bootloader passes argc/argp/envp * to us as arguments. But clear bss first because * the romvec and other important info is stored there @@ -441,14 +446,6 @@ probe_done: jal loadmmu nop - /* - * Stack for kernel and init, current variable - */ - la $28, init_task_union - addiu t0, $28, KERNEL_STACK_SIZE-32 - sw t0, kernelsp - subu sp, t0, 4*SZREG - /* Disable coprocessors */ mfc0 t0, CP0_STATUS li t1, ~(ST0_CU1|ST0_CU2|ST0_CU3|ST0_KX|ST0_SX) diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index a4f64b5fb..04e6dc191 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.11 1999/01/03 17:50:51 ralf Exp $ +/* $Id: process.c,v 1.12 1999/06/17 13:25:46 ralf Exp $ * * 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 @@ -28,6 +28,7 @@ #include <asm/uaccess.h> #include <asm/io.h> #include <asm/elf.h> +#include <asm/isadep.h> struct task_struct *last_task_used_math = NULL; @@ -39,7 +40,7 @@ asmlinkage void ret_from_sys_call(void); void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp) { /* New thread looses kernel privileges. */ - regs->cp0_status = (regs->cp0_status & ~(ST0_CU0|ST0_KSU)) | KSU_USER; + regs->cp0_status = (regs->cp0_status & ~(ST0_CU0|KU_MASK)) | KU_USER; regs->cp0_epc = pc; regs->regs[29] = sp; current->tss.current_ds = USER_DS; @@ -74,12 +75,13 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, { struct pt_regs * childregs; long childksp; + extern void (*save_fp)(struct sigcontext *); childksp = (unsigned long)p + KERNEL_STACK_SIZE - 32; if (last_task_used_math == current) { set_cp0_status(ST0_CU1, ST0_CU1); - r4xx0_save_fp(p); + save_fp(p); } /* set up new TSS. */ childregs = (struct pt_regs *) childksp - 1; @@ -111,7 +113,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, * switching for most programs since they don't use the fpu. */ p->tss.cp0_status = read_32bit_cp0_register(CP0_STATUS) & - ~(ST0_CU3|ST0_CU2|ST0_CU1|ST0_KSU); + ~(ST0_CU3|ST0_CU2|ST0_CU1|KU_MASK); childregs->cp0_status &= ~(ST0_CU3|ST0_CU2|ST0_CU1); p->mm->context = 0; diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 476f331ef..77ea1a58c 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -1,4 +1,4 @@ -/* $Id: ptrace.c,v 1.12 1999/06/13 16:30:32 ralf Exp $ +/* $Id: ptrace.c,v 1.13 1999/06/17 13:25:46 ralf Exp $ * * 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 @@ -242,6 +242,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) struct task_struct *child; unsigned int flags; int res; + extern void (*save_fp)(struct sigcontext *); lock_kernel(); #if 0 @@ -351,7 +352,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) if (last_task_used_math == child) { enable_cp1(); - r4xx0_save_fp(child); + save_fp(child); disable_cp1(); last_task_used_math = NULL; } @@ -413,7 +414,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) if (child->used_math) { if (last_task_used_math == child) { enable_cp1(); - r4xx0_save_fp(child); + save_fp(child); disable_cp1(); last_task_used_math = NULL; } diff --git a/arch/mips/kernel/scall_o32.S b/arch/mips/kernel/scall_o32.S index b31a8b18e..aa949f7ee 100644 --- a/arch/mips/kernel/scall_o32.S +++ b/arch/mips/kernel/scall_o32.S @@ -12,6 +12,7 @@ #include <asm/mipsregs.h> #include <asm/regdef.h> #include <asm/stackframe.h> +#include <asm/isadep.h> #include <asm/unistd.h> /* This duplicates the definition from <linux/sched.h> */ @@ -48,6 +49,7 @@ NESTED(handle_sys, PT_SIZE, sp) bgez t0, stackargs stack_done: + sw a3, PT_R26(sp) # save for syscall restart lw t0, TASK_FLAGS($28) # syscall tracing enabled? andi t0, PF_TRACESYS bnez t0, trace_a_syscall @@ -70,7 +72,7 @@ EXPORT(o32_ret_from_sys_call) bnez t0,o32_handle_bottom_half 9: lw t0,PT_STATUS(sp) # returning to kernel mode? - andi t1, t0, 0x10 + andi t1, t0, KU_USER lw t2, TASK_NEED_RESCHED($28) beqz t1, o32_return # -> yes bnez t2, o32_reschedule @@ -83,10 +85,7 @@ EXPORT(o32_ret_from_sys_call) o32_return: RESTORE_SOME - RESTORE_SP - .set mips3 - eret - .set mips0 + RESTORE_SP_AND_RET o32_handle_bottom_half: jal do_bottom_half @@ -140,15 +139,28 @@ stackargs: lw t0, PT_R29(sp) # get old user stack pointer la t1, 3f # copy 1 to 2 arguments - sll t3, t3, 3 + sll t3, t3, 4 subu t1, t3 jr t1 /* Ok, copy the args from the luser stack to the kernel stack */ + /* + * I know Ralf doesn't like nops but this avoids code + * duplication for R3000 targets (and this is the + * only place where ".set reorder" doesn't help). + * Harald. + */ + .set push + .set noreorder 1: lw t1, 20(t0) # argument #6 from usp + nop sw t1, 20(sp) + nop 2: lw t1, 16(t0) # argument #5 from usp + nop sw t1, 16(sp) + nop + .set pop 3: j stack_done # go back diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 757fbafc2..3cca8acb1 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -1,4 +1,4 @@ -/* $Id: traps.c,v 1.20 1999/06/13 16:30:34 ralf Exp $ +/* $Id: traps.c,v 1.21 1999/06/23 22:15:57 ralf Exp $ * * 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 @@ -60,6 +60,15 @@ extern asmlinkage void handle_fpe(void); extern asmlinkage void handle_watch(void); extern asmlinkage void handle_reserved(void); +extern asmlinkage void r4xx0_lazy_fpu_switch(struct task_struct *); +extern asmlinkage void r4xx0_init_fpu(void); +extern asmlinkage void r4xx0_save_fp(struct sigcontext *); +extern asmlinkage void r2300_lazy_fpu_switch(struct task_struct *); +extern asmlinkage void r2300_init_fpu(void); +extern asmlinkage void r2300_save_fp(struct sigcontext *); + +extern asmlinkage void simfp(unsigned int); + static char *cpu_names[] = CPU_NAMES; char watch_available = 0; @@ -69,6 +78,10 @@ char vce_available = 0; void (*ibe_board_handler)(struct pt_regs *regs); void (*dbe_board_handler)(struct pt_regs *regs); +static void (*lazy_fpu_switch)(struct task_struct *); +static void (*init_fpu)(void); +void (*save_fp)(struct sigcontext *); + int kstack_depth_to_print = 24; /* @@ -77,6 +90,23 @@ int kstack_depth_to_print = 24; */ #define MODULE_RANGE (8*1024*1024) +#if (_MIPS_ISA == _MIPS_ISA_MIPS1) +/* + * 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 +#define RT 0x001f0000 +#define OFFSET 0x0000ffff +#define LL 0xc0000000 +#define SC 0xd0000000 + +#define DEBUG_LLSC +#endif + /* * This routine abuses get_user()/put_user() to reference pointers * with at least a bit of error checking ... @@ -201,8 +231,10 @@ static void default_be_board_handler(struct pt_regs *regs) /* * Assume it would be too dangerous to continue ... */ - force_sig(SIGBUS, current); +/* XXX */ +printk("Got Bus Error at %08x\n", (unsigned int)regs->cp0_epc); show_regs(regs); while(1); + force_sig(SIGBUS, current); } void do_ibe(struct pt_regs *regs) @@ -345,6 +377,110 @@ void do_tr(struct pt_regs *regs) force_sig(SIGTRAP, current); } +#if (_MIPS_ISA == _MIPS_ISA_MIPS1) + +/* + * userland emulation for R2300 CPUs + * needed for the multithreading part of glibc + */ +void do_ri(struct pt_regs *regs) +{ + unsigned int opcode; + + lock_kernel(); + if (!get_insn_opcode(regs, &opcode)) { + if ((opcode & OPCODE) == LL) + simulate_ll(regs, opcode); + if ((opcode & OPCODE) == SC) + simulate_sc(regs, opcode); + } else { + printk("[%s:%ld] Illegal instruction at %08lx ra=%08lx\n", + current->comm, current->pid, regs->cp0_epc, regs->regs[31]); + } + unlock_kernel(); + if (compute_return_epc(regs)) + return; + force_sig(SIGILL, current); +} + +/* + * the ll_bit will be cleared by r2300_switch.S + */ +unsigned long ll_bit, *lladdr; + +void simulate_ll(struct pt_regs *regp, unsigned int opcode) +{ + unsigned long *addr, *vaddr; + long offset; + + /* + * analyse the ll instruction that just caused a ri exception + * and put the referenced address to addr. + */ + /* sign extend offset */ + offset = opcode & OFFSET; + if (offset & 0x00008000) + offset = -(offset & 0x00007fff); + else + offset = (offset & 0x00007fff); + + 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 + + /* + * TODO: compute physical address from vaddr + */ + panic("ll: emulation not yet finished!"); + + lladdr = addr; + ll_bit = 1; + regp->regs[(opcode & RT) >> 16] = *addr; +} + +void simulate_sc(struct pt_regs *regp, unsigned int opcode) +{ + unsigned long *addr, *vaddr, reg; + long offset; + + /* + * analyse the sc instruction that just caused a ri exception + * and put the referenced address to addr. + */ + /* sign extend offset */ + offset = opcode & OFFSET; + if (offset & 0x00008000) + offset = -(offset & 0x00007fff); + else + offset = (offset & 0x00007fff); + + 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 + + /* + * TODO: compute physical address from vaddr + */ + panic("sc: emulation not yet finished!"); + + lladdr = addr; + + if (ll_bit == 0) { + regp->regs[reg] = 0; + return; + } + + *addr = regp->regs[reg]; + regp->regs[reg] = 1; +} + +#else /* MIPS 2 or higher */ + void do_ri(struct pt_regs *regs) { lock_kernel(); @@ -356,6 +492,8 @@ void do_ri(struct pt_regs *regs) force_sig(SIGILL, current); } +#endif + void do_cpu(struct pt_regs *regs) { unsigned int cpid; @@ -369,10 +507,10 @@ void do_cpu(struct pt_regs *regs) return; if (current->used_math) { /* Using the FPU again. */ - r4xx0_lazy_fpu_switch(last_task_used_math); + lazy_fpu_switch(last_task_used_math); } else { /* First time FPU user. */ - r4xx0_init_fpu(); + init_fpu(); current->used_math = 1; } last_task_used_math = current; @@ -548,6 +686,9 @@ __initfunc(void trap_init(void)) save_fp_context = r4k_save_fp_context; restore_fp_context = r4k_restore_fp_context; + lazy_fpu_switch = r4xx0_lazy_fpu_switch; + init_fpu = r4xx0_init_fpu; + save_fp = r4xx0_save_fp; resume = r4xx0_resume; set_except_vector(1, r4k_handle_mod); set_except_vector(2, r4k_handle_tlbl); @@ -592,8 +733,12 @@ __initfunc(void trap_init(void)) case CPU_R3000: case CPU_R3000A: memcpy((void *)KSEG0, &except_vec0_r2300, 0x80); + memcpy((void *)(KSEG0 + 0x80), &except_vec3_generic, 0x80); save_fp_context = r2300_save_fp_context; restore_fp_context = r2300_restore_fp_context; + lazy_fpu_switch = r2300_lazy_fpu_switch; + init_fpu = r2300_init_fpu; + save_fp = r2300_save_fp; resume = r2300_resume; set_except_vector(1, r2300_handle_mod); set_except_vector(2, r2300_handle_tlbl); diff --git a/arch/mips/mm/r2300.c b/arch/mips/mm/r2300.c index 3c2cec663..6e4127e7e 100644 --- a/arch/mips/mm/r2300.c +++ b/arch/mips/mm/r2300.c @@ -7,7 +7,7 @@ * Copyright (C) 1998 Harald Koerfgen * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov * - * $Id: r2300.c,v 1.5 1998/04/05 11:23:55 ralf Exp $ + * $Id: r2300.c,v 1.8 1999/04/11 17:13:56 harald Exp $ */ #include <linux/init.h> #include <linux/kernel.h> @@ -19,13 +19,9 @@ #include <asm/mmu_context.h> #include <asm/system.h> #include <asm/sgialib.h> -#include <asm/mipsregs.h> +#include <asm/isadep.h> #include <asm/io.h> -/* - * Temporarily disabled - * #include <asm/wbflush.h> - */ /* * According to the paper written by D. Miller about Linux cache & TLB @@ -374,10 +370,7 @@ static void r3k_dma_cache_wback_inv(unsigned long start, unsigned long size) register unsigned long i, flags; register volatile unsigned char *p = (volatile unsigned char*) start; -/* - * Temporarily disabled wbflush(); - */ /* * Invalidate dcache @@ -680,7 +673,7 @@ printk("r2300_add_wired_entry"); static int r2300_user_mode(struct pt_regs *regs) { - return !(regs->cp0_status & ST0_KUP); + return !(regs->cp0_status & KU_USER); } __initfunc(void ld_mmu_r2300(void)) |