summaryrefslogtreecommitdiffstats
path: root/arch/mips
diff options
context:
space:
mode:
authorHarald Koerfgen <hkoerfg@web.de>1999-07-26 19:42:38 +0000
committerHarald Koerfgen <hkoerfg@web.de>1999-07-26 19:42:38 +0000
commit14ab59aa8aba8687dc957c2186e115ac0b8ab542 (patch)
treec2eb55db21b6b46ddd983e2d40196fa61f19b64c /arch/mips
parent552f7f2f262b8ea12edc36f9a260b068bd10f423 (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.S32
-rw-r--r--arch/mips/kernel/head.S29
-rw-r--r--arch/mips/kernel/process.c10
-rw-r--r--arch/mips/kernel/ptrace.c7
-rw-r--r--arch/mips/kernel/scall_o32.S24
-rw-r--r--arch/mips/kernel/traps.c153
-rw-r--r--arch/mips/mm/r2300.c13
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))