summaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1997-06-03 09:23:20 +0000
committerRalf Baechle <ralf@linux-mips.org>1997-06-03 09:23:20 +0000
commitac5ff8f4a72f7b4e66f73c3c6cb9fe7758cf6f12 (patch)
tree9fc7f8ce32e0d9a4aa055b2a58a05a5d727b333c /arch/sparc64/kernel
parent52662ff3e66770fd7e4fc508c91056d29c08bff0 (diff)
Sync with Linux 2.1.42.
Diffstat (limited to 'arch/sparc64/kernel')
-rw-r--r--arch/sparc64/kernel/Makefile6
-rw-r--r--arch/sparc64/kernel/entry.S78
-rw-r--r--arch/sparc64/kernel/etrap.S56
-rw-r--r--arch/sparc64/kernel/hack.S24
-rw-r--r--arch/sparc64/kernel/irq.c10
-rw-r--r--arch/sparc64/kernel/process.c3
-rw-r--r--arch/sparc64/kernel/rtrap.S70
-rw-r--r--arch/sparc64/kernel/setup.c32
-rw-r--r--arch/sparc64/kernel/signal.c19
-rw-r--r--arch/sparc64/kernel/signal32.c15
-rw-r--r--arch/sparc64/kernel/sys_sparc32.c261
-rw-r--r--arch/sparc64/kernel/systbls.S10
-rw-r--r--arch/sparc64/kernel/traps.c305
13 files changed, 701 insertions, 188 deletions
diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile
index 4a07295e1..199360a5f 100644
--- a/arch/sparc64/kernel/Makefile
+++ b/arch/sparc64/kernel/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.20 1997/05/18 08:42:11 davem Exp $
+# $Id: Makefile,v 1.22 1997/05/27 19:30:17 jj Exp $
# Makefile for the linux kernel.
#
# Note! Dependencies are done automagically by 'make dep', which also
@@ -18,11 +18,11 @@ all: kernel.o head.o init_task.o
O_TARGET := kernel.o
O_OBJS := etrap.o rtrap.o hack.o process.o setup.o cpu.o idprom.o \
systbls.o traps.o entry.o devices.o auxio.o ioport.o \
- irq.o time.o sys_sparc.o signal.o winfixup.o
+ irq.o ptrace.o time.o sys_sparc.o signal.o winfixup.o
OX_OBJS := sparc64_ksyms.o
ifdef CONFIG_SPARC32_COMPAT
- O_OBJS += sys_sparc32.o signal32.o
+ O_OBJS += sys_sparc32.o signal32.o ioctl32.o
endif
ifdef CONFIG_BINFMT_ELF32
diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S
index 589d1661a..579fbb4c2 100644
--- a/arch/sparc64/kernel/entry.S
+++ b/arch/sparc64/kernel/entry.S
@@ -1,4 +1,4 @@
-/* $Id: entry.S,v 1.21 1997/05/18 10:04:44 davem Exp $
+/* $Id: entry.S,v 1.27 1997/05/27 19:30:11 jj Exp $
* arch/sparc64/kernel/entry.S: Sparc64 trap low-level entry points.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -18,6 +18,8 @@
#include <asm/signal.h>
#include <asm/pgtable.h>
+/* define SYSCALL_TRACING */
+
#define curptr g6
#define NR_SYSCALLS 256 /* Each OS is different... */
@@ -52,6 +54,11 @@ sparc64_dtlb_prot_catch:
b,a,pt %xcc, 1f
sparc64_dtlb_refbit_catch:
+ srlx %g5, 9, %g4
+ and %g4, ((_PAGE_PRESENT | _PAGE_READ) >> 9), %g4
+ cmp %g4, ((_PAGE_PRESENT | _PAGE_READ) >> 9)
+ be,a,pt %xcc, 2f
+ mov 1, %g4
wr %g0, ASI_DMMU, %asi
rdpr %pstate, %g1
wrpr %g1, PSTATE_AG|PSTATE_MG, %pstate
@@ -75,6 +82,11 @@ sparc64_dtlb_refbit_catch:
ba,a,pt %xcc, rtrap
sparc64_itlb_refbit_catch:
+ srlx %g5, 9, %g4
+ and %g4, ((_PAGE_PRESENT | _PAGE_READ) >> 9), %g4
+ cmp %g4, ((_PAGE_PRESENT | _PAGE_READ) >> 9)
+ be,a,pt %xcc, 3f
+ mov 1, %g4
rdpr %pstate, %g1
wrpr %g1, PSTATE_AG|PSTATE_MG, %pstate
ba,pt %xcc, etrap
@@ -89,6 +101,22 @@ sparc64_itlb_refbit_catch:
add %sp, STACK_BIAS + REGWIN_SZ, %o0 ! pt_regs ptr
ba,a,pt %xcc, rtrap
+2:
+ sllx %g4, 63, %g4 ! _PAGE_VALID
+ or %g5, _PAGE_ACCESSED, %g5
+ or %g5, %g4, %g5
+ stxa %g5, [%g3 + %g1] ASI_PHYS_USE_EC ! store new PTE
+ stxa %g5, [%g0] ASI_DTLB_DATA_IN ! TLB load
+ retry
+
+3:
+ sllx %g4, 63, %g4 ! _PAGE_VALID
+ or %g5, _PAGE_ACCESSED, %g5
+ or %g5, %g4, %g5
+ stxa %g5, [%g3 + %g1] ASI_PHYS_USE_EC ! store new PTE
+ stxa %g5, [%g0] ASI_ITLB_DATA_IN ! TLB load
+ retry
+
/* Note check out head.h, this code isn't even used for UP,
* for SMP things will be different. In particular the data
* registers for cross calls will be:
@@ -161,6 +189,7 @@ breakpoint_trap:
.globl sys_pipe, sys_execve, sys_sigpause, sys_nis_syscall
.globl sys_sigsuspend, sys_sigreturn
+ .globl sys32_execve, sys_ptrace
sys_pipe:
sethi %hi(sparc_pipe), %g1
@@ -180,6 +209,12 @@ sys_execve:
jmpl %g1 + %lo(sparc_execve), %g0
add %sp, STACK_BIAS + REGWIN_SZ, %o0
+sys32_execve:
+ sethi %hi(sparc32_execve), %g1
+ add %g1, %g4, %g1
+ jmpl %g1 + %lo(sparc32_execve), %g0
+ add %sp, STACK_BIAS + REGWIN_SZ, %o0
+
sys_sigpause:
/* NOTE: %o0 has a correct value already */
call do_sigpause
@@ -199,7 +234,7 @@ sys_sigsuspend:
ld [%curptr + AOFF_task_flags], %l5
andcc %l5, 0x20, %g0
- be,pt %icc, ret_sys_call
+ be,pt %icc, rtrap
nop
call syscall_trace
nop
@@ -211,13 +246,25 @@ sys_sigreturn:
ld [%curptr + AOFF_task_flags], %l5
andcc %l5, 0x20, %g0
- be,pt %icc, ret_sys_call
+ be,pt %icc, rtrap
nop
call syscall_trace
nop
ba,a,pt %xcc, rtrap
- /* This is how fork() was meant to be done, 11 instruction entry. -DaveM */
+sys_ptrace:
+ call do_ptrace
+ add %sp, STACK_BIAS + REGWIN_SZ, %o0
+
+ ld [%curptr + AOFF_task_flags], %l5
+ andcc %l5, 0x20, %g0
+ be,pt %icc, rtrap
+ nop
+ call syscall_trace
+ nop
+ ba,a,pt %xcc, rtrap
+
+ /* This is how fork() was meant to be done, 10 instruction entry. -DaveM */
.globl sys_fork, sys_vfork, sys_clone
sys_fork:
sys_vfork:
@@ -228,13 +275,12 @@ sys_clone:
flushw
rdpr %cwp, %o4
add %sp, STACK_BIAS + REGWIN_SZ, %o2
- brz,a %o1, 1f
- mov %fp, %o1
-1:
+ movrz %o1, %fp, %o1
+
/* Don't try this at home. */
stx %o4, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G0]
call do_fork
- add %l5, 8, %o7
+ mov %l5, %o7
linux_sparc_ni_syscall:
sethi %hi(sys_ni_syscall), %l7
@@ -281,6 +327,11 @@ linux_sparc_syscall:
.globl syscall_is_too_hard
syscall_is_too_hard:
+#ifdef SYSCALL_TRACING /* Debugging... */
+ mov %g1, %o0 ! o0=scall, o1=ptregs
+ call syscall_trace_entry
+ add %sp, STACK_BIAS + REGWIN_SZ, %o1
+#endif
mov %i0, %o0
mov %i1, %o1
mov %i2, %o2
@@ -295,13 +346,12 @@ syscall_is_too_hard:
call %l7
mov %i5, %o5
- stx %o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0]
-#if 0
- /* Debugging... */
- call syscall_trace_exit
- add %sp, STACK_BIAS + REGWIN_SZ, %o0
- ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0], %o0
+#ifdef SYSCALL_TRACING /* Debugging... */
+ call syscall_trace_exit ! o0=sysret, o1=ptregs
+ add %sp, STACK_BIAS + REGWIN_SZ, %o1
#endif
+ stx %o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0]
+
.globl ret_sys_call
ret_sys_call:
ldx [%curptr + AOFF_task_flags], %l6
diff --git a/arch/sparc64/kernel/etrap.S b/arch/sparc64/kernel/etrap.S
index f936b3071..0c166ec25 100644
--- a/arch/sparc64/kernel/etrap.S
+++ b/arch/sparc64/kernel/etrap.S
@@ -1,4 +1,4 @@
-/* $Id: etrap.S,v 1.17 1997/05/18 22:52:09 davem Exp $
+/* $Id: etrap.S,v 1.18 1997/05/19 05:58:51 davem Exp $
* etrap.S: Preparing for entry into the kernel on Sparc V9.
*
* Copyright (C) 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -29,59 +29,39 @@ etrap_irq:
rdpr %tstate, %g1
sllx %g2, 20, %g2
or %g1, %g2, %g1
-
- /* What happens more often? etrap when already in priv or from userland? */
andcc %g1, TSTATE_PRIV, %g0
bne,a,pn %xcc, 1f
sub %sp, REGWIN_SZ + TRACEREG_SZ - STACK_BIAS, %g2
+ rd %pic, %g3
- /* Just when going from userland to privileged mode,
- * we have to change this stuff.
- *
- * Setup to run in NUCLEUS context, stash user context in
- * secondary for later trap return. Note we must not change
- * trap level until PRIMARY_CONTEXT is set to zero, else
- * we fall out of NUCLEUS too soon and crash hard.
- */
- mov PRIMARY_CONTEXT, %g1
- ldxa [%g1] ASI_DMMU, %g2
- stxa %g0, [%g1] ASI_DMMU
-
- mov SECONDARY_CONTEXT, %g1
- stxa %g2, [%g1] ASI_DMMU
-
- rd %pic, %g1
sethi %hi((PAGE_SIZE<<1)-TRACEREG_SZ-REGWIN_SZ), %g2
or %g2, %lo((PAGE_SIZE<<1)-TRACEREG_SZ-REGWIN_SZ), %g2
- add %g1, %g2, %g2
- rdpr %tstate, %g1
-1:
- stx %g1, [%g2 + REGWIN_SZ + PT_V9_TSTATE]
+ add %g3, %g2, %g2
+1: stx %g1, [%g2 + REGWIN_SZ + PT_V9_TSTATE]
rdpr %tpc, %g1
rdpr %tnpc, %g3
stx %g1, [%g2 + REGWIN_SZ + PT_V9_TPC]
rd %y, %g1
+
stx %g3, [%g2 + REGWIN_SZ + PT_V9_TNPC]
stx %g1, [%g2 + REGWIN_SZ + PT_V9_Y]
-
- wrpr %g0, 0x0, %tl
rdpr %pstate, %g1
save %g2, -STACK_BIAS, %sp
-
- /* Must guarentee that here andcc of TSTATE_PRIV at the top is
- * still valid in %ccr register. Don't show this trick to your
- * mom. -DaveM
- */
bne,pn %xcc, 1f
rdpr %canrestore, %g3
+ rdpr %wstate, %g6
wrpr %g0, 0, %canrestore
- wrpr %g3, 0, %otherwin
- rdpr %wstate, %g6
sll %g6, 3, %g6
+ wrpr %g3, 0, %otherwin
wrpr %g6, %wstate
-
+ sethi %uhi(KERNBASE), %g3
+ sllx %g3, 32, %g3
+ mov PRIMARY_CONTEXT, %g2
+ stxa %g0, [%g2] ASI_DMMU
+ flush %g3
1:
+ wrpr %g0, 0x0, %tl
mov %g1, %l1
mov %g4, %l4
mov %g5, %l5
@@ -89,6 +69,7 @@ etrap_irq:
wrpr %l1, PSTATE_AG, %pstate
stx %g1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G1]
stx %g2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G2]
+
stx %g3, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G3]
stx %g4, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G4]
stx %g5, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G5]
@@ -97,19 +78,24 @@ etrap_irq:
stx %i0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0]
stx %i1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I1]
stx %i2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I2]
+
stx %i3, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I3]
stx %i4, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I4]
stx %i5, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I5]
stx %i6, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I6]
stx %i7, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I7]
wrpr %l1, (PSTATE_IE | PSTATE_AG), %pstate
- srlx %sp, 43, %g4
+ sethi %uhi(KERNBASE), %g4
rd %pic, %g6
+
jmpl %l2 + 0x4, %g0
- sllx %g4, 43, %g4
+ sllx %g4, 32, %g4
.globl etraptl1
etraptl1:
rdpr %tstate, %g1
ba,pt %xcc, 1b
sub %sp, REGWIN_SZ + TRACEREG_SZ - STACK_BIAS, %g2
+ nop
+ nop
+ nop
diff --git a/arch/sparc64/kernel/hack.S b/arch/sparc64/kernel/hack.S
index 034bda2d0..6303bd9e9 100644
--- a/arch/sparc64/kernel/hack.S
+++ b/arch/sparc64/kernel/hack.S
@@ -10,28 +10,16 @@ breakpoint: retl;nop
do_cee: retl;nop
.globl do_cee_tl1
do_cee_tl1: retl;nop
- .globl do_dae
-do_dae: retl;nop
.globl do_dae_tl1
do_dae_tl1: retl;nop
- .globl do_div0
-do_div0: retl;nop
.globl do_div0_tl1
do_div0_tl1: retl;nop
- .globl do_fpdis
-do_fpdis: retl;nop
.globl do_fpdis_tl1
do_fpdis_tl1: retl;nop
- .globl do_fpieee
-do_fpieee: retl;nop
.globl do_fpieee_tl1
do_fpieee_tl1: retl;nop
- .globl do_fpother
-do_fpother: retl;nop
.globl do_fpother_tl1
do_fpother_tl1: retl;nop
- .globl do_iae
-do_iae: retl;nop
.globl do_iae_tl1
do_iae_tl1: retl;nop
.globl do_ill_tl1
@@ -50,16 +38,10 @@ do_mna_tl1: retl;nop
do_paw: retl;nop
.globl do_paw_tl1
do_paw_tl1: retl;nop
- .globl do_privact
-do_privact: retl;nop
- .globl do_privop
-do_privop: retl;nop
.globl do_stdfmna
do_stdfmna: retl;nop
.globl do_stdfmna_tl1
do_stdfmna_tl1: retl;nop
- .globl do_tof
-do_tof: retl;nop
.globl do_tof_tl1
do_tof_tl1: retl;nop
.globl do_vaw
@@ -190,9 +172,3 @@ sunos_wait4: retl;nop
sunos_write: retl;nop
.globl sunos_writev
sunos_writev: retl;nop
- .globl sys_ptrace
-sys_ptrace: retl;nop
- .globl syscall_trace
-syscall_trace: retl;nop
- .globl sys32_ptrace
-sys32_ptrace: retl;nop
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c
index bc9a8053e..3c9b1a89e 100644
--- a/arch/sparc64/kernel/irq.c
+++ b/arch/sparc64/kernel/irq.c
@@ -1,4 +1,4 @@
-/* $Id: irq.c,v 1.12 1997/04/16 05:56:20 davem Exp $
+/* $Id: irq.c,v 1.13 1997/05/27 07:54:28 davem Exp $
* irq.c: UltraSparc IRQ handling/init/registry.
*
* Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -382,15 +382,15 @@ void free_irq(unsigned int irq, void *dev_cookie)
/* Per-processor IRQ locking depth, both SMP and non-SMP code use this. */
unsigned int local_irq_count[NR_CPUS];
-atomic_t __sparc64_bh_counter = ATOMIC_INIT(0);
-#ifdef __SMP__
-#error SMP not supported on sparc64 just yet
-#else
+#ifndef __SMP__
+int __sparc64_bh_counter = 0;
#define irq_enter(cpu, irq) (local_irq_count[cpu]++)
#define irq_exit(cpu, irq) (local_irq_count[cpu]--)
+#else
+#error SMP not supported on sparc64 just yet
#endif /* __SMP__ */
void report_spurious_ivec(struct pt_regs *regs)
diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c
index 4e2bbe016..593c1efc6 100644
--- a/arch/sparc64/kernel/process.c
+++ b/arch/sparc64/kernel/process.c
@@ -1,4 +1,4 @@
-/* $Id: process.c,v 1.11 1997/05/18 22:52:19 davem Exp $
+/* $Id: process.c,v 1.12 1997/05/23 09:35:43 jj Exp $
* arch/sparc64/kernel/process.c
*
* Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -355,6 +355,7 @@ void flush_thread(void)
get_mmu_context(current);
}
current->tss.current_ds = USER_DS;
+ spitfire_set_secondary_context (current->mm->context);
}
static __inline__ void copy_regs(struct pt_regs *dst, struct pt_regs *src)
diff --git a/arch/sparc64/kernel/rtrap.S b/arch/sparc64/kernel/rtrap.S
index 1c4c4df04..0f1dceb33 100644
--- a/arch/sparc64/kernel/rtrap.S
+++ b/arch/sparc64/kernel/rtrap.S
@@ -1,4 +1,4 @@
-/* $Id: rtrap.S,v 1.14 1997/05/18 08:42:14 davem Exp $
+/* $Id: rtrap.S,v 1.18 1997/05/27 06:28:05 davem Exp $
* rtrap.S: Preparing for return from trap on Sparc V9.
*
* Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -9,11 +9,14 @@
#include <asm/pstate.h>
#include <asm/ptrace.h>
#include <asm/spitfire.h>
+#include <asm/head.h>
-/* We assume here this is entered with AG, MG and IG bits in pstate clear */
+ /* We assume here that this is entered with AG, MG and IG bits
+ * in pstate clear.
+ */
.text
- .align 4
+ .align 32
.globl rtrap
rtrap:
sethi %hi(bh_active), %l2
@@ -23,24 +26,26 @@ rtrap:
ldx [%l2 + %g4], %l3
ldx [%l1 + %g4], %l4
andcc %l3, %l4, %g0
+ nop
+
be,pt %xcc, 2f
nop
call do_bottom_half
nop
-2:
- ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TSTATE], %l1
- ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TPC], %l2
+2: ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TSTATE], %l1
sethi %hi(0xf << 20), %l4
andcc %l1, TSTATE_PRIV, %l3
and %l1, %l4, %l4
+
rdpr %pstate, %l7
- andn %l1, %l4, %l1 /* XXX May not be needed -DaveM */
+ andn %l1, %l4, %l1
be,pt %icc, to_user
andn %l7, PSTATE_IE, %l7
-3:
+3: ldx [%g6 + AOFF_task_tss + AOFF_thread_ctx], %l6
ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G1], %g1
ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G2], %g2
ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G3], %g3
+
ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G4], %g4
ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G5], %g5
ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G6], %g6
@@ -49,54 +54,54 @@ rtrap:
ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I1], %i1
ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I2], %i2
ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I3], %i3
+
ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I4], %i4
ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I5], %i5
ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I6], %i6
ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I7], %i7
ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_Y], %o3
+ ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TPC], %l2
ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC], %o2
- rdpr %tl, %o4
wr %o3, %g0, %y
- add %o4, 1, %o4
srl %l4, 20, %l4
wrpr %l7, %g0, %pstate
wrpr %l4, 0x0, %pil
- wrpr %o4, %g0, %tl
+ wrpr %g0, 0x1, %tl
wrpr %l1, %g0, %tstate
wrpr %l2, %g0, %tpc
brnz,pn %l3, 1f
wrpr %o2, %g0, %tnpc
- /* We came here from to_user, ie. we have now AG.
- * Also have to push user context back into primary.
- */
- mov SECONDARY_CONTEXT, %g6
- mov PRIMARY_CONTEXT, %g7
- ldxa [%g6] ASI_DMMU, %g4
- stxa %g4, [%g7] ASI_DMMU
- membar #Sync /* XXX flushi would be better -DaveM */
+ mov PRIMARY_CONTEXT, %l7
+ sethi %uhi(KERNBASE), %l5
+ sllx %l5, 32, %l5
+ stxa %l6, [%l7] ASI_DMMU
+ flush %l5
+ rdpr %wstate, %l1
+ rdpr %otherwin, %l2
+ srl %l1, 3, %l1
- rdpr %wstate, %g1
- rdpr %otherwin, %g2
- srl %g1, 3, %g1
- wrpr %g2, %g0, %canrestore
- wrpr %g1, %g0, %wstate
+ wrpr %l2, %g0, %canrestore
+ wrpr %l1, %g0, %wstate
wrpr %g0, %g0, %otherwin
-1:
- restore
+1: restore
retry
to_user:
sethi %hi(need_resched), %l0
or %l0, %lo(need_resched), %l0
ld [%l0 + %g4], %l0
+
wrpr %l7, PSTATE_IE, %pstate
- brz,pt %l0, 1f
+ brz,pt %l0, check_signal
ldx [%g6 + AOFF_task_signal], %l0
call schedule
nop
-1:
+ ldx [%g6 + AOFF_task_signal], %l0
+ nop
+check_signal:
ldx [%g6 + AOFF_task_blocked], %o0
+
or %l7, PSTATE_AG, %l7 ! Will need this for setting back wstate
andncc %l0, %o0, %g0
be,pt %xcc, check_user_wins
@@ -105,8 +110,17 @@ to_user:
call do_signal
add %sp, STACK_BIAS + REGWIN_SZ, %o1
check_user_wins:
+#if 0
+ call user_rtrap_report
+ add %sp, STACK_BIAS + REGWIN_SZ, %o0
+#endif
ldx [%g6 + AOFF_task_tss + AOFF_thread_w_saved], %o2
+
brz,pt %o2, 3b
add %sp, STACK_BIAS + REGWIN_SZ, %o1
call fault_in_user_windows
add %o7, 3b-.-4, %o7
+ nop
+ nop
+ nop
+ nop
diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c
index 47d900977..832d3b97f 100644
--- a/arch/sparc64/kernel/setup.c
+++ b/arch/sparc64/kernel/setup.c
@@ -1,4 +1,4 @@
-/* $Id: setup.c,v 1.6 1997/05/04 07:21:04 davem Exp $
+/* $Id: setup.c,v 1.7 1997/05/20 07:58:56 jj Exp $
* linux/arch/sparc64/kernel/setup.c
*
* Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu)
@@ -25,6 +25,7 @@
#include <linux/string.h>
#include <linux/blk.h>
#include <linux/init.h>
+#include <linux/inet.h>
#include <asm/segment.h>
#include <asm/system.h>
@@ -247,6 +248,10 @@ extern void register_console(void (*proc)(const char *));
char saved_command_line[256];
char reboot_command[256];
+#ifdef CONFIG_ROOT_NFS
+extern char nfs_root_addrs[];
+#endif
+
unsigned long phys_base;
static struct pt_regs fake_swapper_regs = { { 0, }, 0, 0, 0, 0 };
@@ -346,6 +351,31 @@ __initfunc(void setup_arch(char **cmdline_p,
init_task.mm->context = (unsigned long) NO_CONTEXT;
init_task.tss.kregs = &fake_swapper_regs;
+#ifdef CONFIG_ROOT_NFS
+ if (!*nfs_root_addrs) {
+ int chosen = prom_finddevice ("/chosen");
+ u32 cl, sv, gw;
+ char *p = nfs_root_addrs;
+
+ cl = prom_getintdefault (chosen, "client-ip", 0);
+ sv = prom_getintdefault (chosen, "server-ip", 0);
+ gw = prom_getintdefault (chosen, "gateway-ip", 0);
+ if (cl && sv) {
+ strcpy (p, in_ntoa (cl));
+ p += strlen (p);
+ *p++ = ':';
+ strcpy (p, in_ntoa (sv));
+ p += strlen (p);
+ *p++ = ':';
+ if (gw) {
+ strcpy (p, in_ntoa (gw));
+ p += strlen (p);
+ }
+ strcpy (p, "::::none");
+ }
+ }
+#endif
+
#ifdef CONFIG_SUN_SERIAL
*memory_start_p = sun_serial_setup(*memory_start_p); /* set this up ASAP */
#endif
diff --git a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c
index 1a595491a..f81e30093 100644
--- a/arch/sparc64/kernel/signal.c
+++ b/arch/sparc64/kernel/signal.c
@@ -1,4 +1,4 @@
-/* $Id: signal.c,v 1.2 1997/05/18 08:42:15 davem Exp $
+/* $Id: signal.c,v 1.4 1997/05/27 06:28:05 davem Exp $
* arch/sparc64/kernel/signal.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
@@ -61,7 +61,7 @@ struct new_signal_frame {
*/
asmlinkage void _sigpause_common(unsigned int set, struct pt_regs *regs)
{
- unsigned int mask;
+ unsigned long mask;
#ifdef CONFIG_SPARC32_COMPAT
if (current->tss.flags & SPARC_FLAG_32BIT) {
@@ -134,7 +134,7 @@ void do_sigreturn(struct pt_regs *regs)
struct new_signal_frame *sf;
unsigned long tpc, tnpc, tstate;
__siginfo_fpu_t *fpu_save;
- int mask;
+ unsigned long mask;
#ifdef CONFIG_SPARC32_COMPAT
if (current->tss.flags & SPARC_FLAG_32BIT) {
@@ -270,8 +270,15 @@ new_setup_frame(struct sigaction *sa, struct pt_regs *regs,
regs->tnpc = (regs->tpc + 4);
/* Flush instruction space. */
- __asm__ __volatile__ ("flush %0; flush %0 + 4" : : "r" (&(sf->insns[0])));
-
+ __asm__ __volatile__("
+ membar #StoreStore
+ stxa %%g0, [%0] %2
+ stxa %%g0, [%1] %2
+ flush %%g4
+ " : /* no outputs */
+ : "r" (((unsigned long)&(sf->insns[0])) & ~(PAGE_MASK)),
+ "r" ((((unsigned long)&(sf->insns[0])) & ~(PAGE_MASK)) + PAGE_SIZE),
+ "i" (ASI_IC_TAG));
}
static inline void handle_signal(unsigned long signr, struct sigaction *sa,
@@ -323,7 +330,7 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs,
#endif
while ((signr = current->signal & mask) != 0) {
signr = ffz(~signr);
- clear_bit(signr, &current->signal);
+ clear_bit(signr + 32, &current->signal);
sa = current->sig->action + signr;
signr++;
if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
diff --git a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c
index d8e61511d..33892065f 100644
--- a/arch/sparc64/kernel/signal32.c
+++ b/arch/sparc64/kernel/signal32.c
@@ -1,4 +1,4 @@
-/* $Id: signal32.c,v 1.8 1997/05/18 08:42:15 davem Exp $
+/* $Id: signal32.c,v 1.10 1997/05/27 06:28:07 davem Exp $
* arch/sparc64/kernel/signal32.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
@@ -398,8 +398,15 @@ new_setup_frame32(struct sigaction *sa, struct pt_regs *regs,
regs->tnpc = (regs->tpc + 4);
/* Flush instruction space. */
- __asm__ __volatile__ ("flush %0; flush %0 + 4" : : "r" (&(sf->insns[0])));
-
+ __asm__ __volatile__("
+ membar #StoreStore
+ stxa %%g0, [%0] %2
+ stxa %%g0, [%1] %2
+ flush %%g4
+ " : /* no outputs */
+ : "r" (((unsigned long)&(sf->insns[0])) & ~(PAGE_MASK)),
+ "r" ((((unsigned long)&(sf->insns[0])) & ~(PAGE_MASK)) + PAGE_SIZE),
+ "i" (ASI_IC_TAG));
}
/* Setup a Solaris stack frame */
@@ -677,7 +684,7 @@ asmlinkage int do_signal32(unsigned long oldmask, struct pt_regs * regs,
while ((signr = current->signal & mask) != 0) {
signr = ffz(~signr);
- clear_bit(signr, &current->signal);
+ clear_bit(signr + 32, &current->signal);
sa = current->sig->action + signr;
signr++;
if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
index 147b60c34..c54036de6 100644
--- a/arch/sparc64/kernel/sys_sparc32.c
+++ b/arch/sparc64/kernel/sys_sparc32.c
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc32.c,v 1.13 1997/05/18 04:16:44 davem Exp $
+/* $Id: sys_sparc32.c,v 1.18 1997/05/27 06:28:08 davem Exp $
* sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
*
* Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -48,7 +48,6 @@ extern asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len,
extern asmlinkage int sys_bdflush(int func, long data);
extern asmlinkage int sys_uselib(const char * library);
extern asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg);
-extern asmlinkage int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg);
extern asmlinkage int sys_mknod(const char * filename, int mode, dev_t dev);
extern asmlinkage int sys_mkdir(const char * pathname, int mode);
extern asmlinkage int sys_rmdir(const char * pathname);
@@ -147,6 +146,69 @@ extern asmlinkage int sys_socket(int family, int type, int protocol);
extern asmlinkage int sys_socketpair(int family, int type, int protocol, int usockvec[2]);
extern asmlinkage int sys_shutdown(int fd, int how);
+/*
+ * In order to reduce some races, while at the same time doing additional
+ * checking and hopefully speeding things up, we copy filenames to the
+ * kernel data space before using them..
+ *
+ * POSIX.1 2.4: an empty pathname is invalid (ENOENT).
+ */
+static inline int do_getname32(u32 filename, char *page)
+{
+ int retval;
+
+ /* 32bit pointer will be always far below TASK_SIZE :)) */
+ retval = strncpy_from_user((char *)page, (char *)A(filename), PAGE_SIZE);
+ if (retval > 0) {
+ if (retval < PAGE_SIZE)
+ return 0;
+ return -ENAMETOOLONG;
+ } else if (!retval)
+ retval = -ENOENT;
+ return retval;
+}
+
+/*
+ * This is a single page for faster getname.
+ * If the page is available when entering getname, use it.
+ * If the page is not available, call __get_free_page instead.
+ * This works even though do_getname can block (think about it).
+ * -- Michael Chastain, based on idea of Linus Torvalds, 1 Dec 1996.
+ * We don't use the common getname/putname from namei.c, so that
+ * this still works well, as every routine which calls getname32
+ * will then call getname, then putname and then putname32.
+ */
+static unsigned long name_page_cache32 = 0;
+
+void putname32(char * name)
+{
+ if (name_page_cache32 == 0)
+ name_page_cache32 = (unsigned long) name;
+ else
+ free_page((unsigned long) name);
+}
+
+int getname32(u32 filename, char **result)
+{
+ unsigned long page;
+ int retval;
+
+ page = name_page_cache32;
+ name_page_cache32 = 0;
+ if (!page) {
+ page = __get_free_page(GFP_KERNEL);
+ if (!page)
+ return -ENOMEM;
+ }
+
+ retval = do_getname32(filename, (char *) page);
+ if (retval < 0)
+ putname32( (char *) page );
+ else
+ *result = (char *) page;
+ return retval;
+}
+
asmlinkage int sys32_ioperm(u32 from, u32 num, int on)
{
return sys_ioperm((unsigned long)from, (unsigned long)num, on);
@@ -558,13 +620,6 @@ asmlinkage long sys32_fcntl(unsigned int fd, unsigned int cmd, u32 arg)
}
}
-/* Conversion of args should be probably done in all the locations where it is handled,
- using if (current->tss.flags & SPARC_FLAG_32BIT */
-asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, u32 arg)
-{
- return sys_ioctl(fd, cmd, (unsigned long)arg);
-}
-
asmlinkage int sys32_mknod(u32 filename, int mode, __kernel_dev_t32 dev)
{
return sys_mknod((const char *)A(filename), mode, dev);
@@ -704,14 +759,21 @@ asmlinkage int sys32_utime(u32 filename, u32 times)
struct utimbuf t;
unsigned long old_fs;
int ret;
+ char *filenam;
+ if (!times)
+ return sys_utime((char *)A(filename), NULL);
if (get_user (t.actime, &(((struct utimbuf32 *)A(times))->actime)) ||
__get_user (t.modtime, &(((struct utimbuf32 *)A(times))->modtime)))
return -EFAULT;
- old_fs = get_fs();
- set_fs (KERNEL_DS);
- ret = sys_utime((char *)A(filename), &t);
- set_fs (old_fs);
+ ret = getname32 (filename, &filenam);
+ if (!ret) {
+ old_fs = get_fs();
+ set_fs (KERNEL_DS);
+ ret = sys_utime(filenam, &t);
+ set_fs (old_fs);
+ putname32 (filenam);
+ }
return ret;
}
@@ -992,6 +1054,7 @@ out:
asmlinkage int sys32_select(int n, u32 inp, u32 outp, u32 exp, u32 tvp)
{
+ struct timeval kern_tv, *ktvp;
unsigned long old_fs;
char *p;
u32 *q;
@@ -1015,9 +1078,15 @@ asmlinkage int sys32_select(int n, u32 inp, u32 outp, u32 exp, u32 tvp)
__get_user (q[PAGE_SIZE/2], Exp+1))
goto out;
}
+ ktvp = NULL;
+ if(tvp) {
+ if(copy_from_user(&kern_tv, (struct timeval *)A(tvp), sizeof(*ktvp)))
+ goto out;
+ ktvp = &kern_tv;
+ }
old_fs = get_fs ();
set_fs (KERNEL_DS);
- ret = sys_select(n, (fd_set *)p, (fd_set *)(p + PAGE_SIZE/4), (fd_set *)(p + PAGE_SIZE/2), (struct timeval *)A(tvp));
+ ret = sys_select(n, (fd_set *)p, (fd_set *)(p + PAGE_SIZE/4), (fd_set *)(p + PAGE_SIZE/2), ktvp);
set_fs (old_fs);
q = (u32 *)p;
Inp = (u32 *)A(inp); Outp = (u32 *)A(outp); Exp = (u32 *)A(exp);
@@ -1065,12 +1134,17 @@ asmlinkage int sys32_newstat(u32 filename, u32 statbuf)
{
int ret;
struct stat s;
+ char *filenam;
unsigned long old_fs = get_fs();
- set_fs (KERNEL_DS);
- ret = sys_newstat((char *)A(filename), &s);
- set_fs (old_fs);
- if (putstat (statbuf, &s)) return -EFAULT;
+ ret = getname32 (filename, &filenam);
+ if (!ret) {
+ set_fs (KERNEL_DS);
+ ret = sys_newstat(filenam, &s);
+ set_fs (old_fs);
+ putname32 (filenam);
+ if (putstat (statbuf, &s)) return -EFAULT;
+ }
return ret;
}
@@ -1078,12 +1152,17 @@ asmlinkage int sys32_newlstat(u32 filename, u32 statbuf)
{
int ret;
struct stat s;
+ char *filenam;
unsigned long old_fs = get_fs();
- set_fs (KERNEL_DS);
- ret = sys_newlstat((char *)A(filename), &s);
- set_fs (old_fs);
- if (putstat (statbuf, &s)) return -EFAULT;
+ ret = getname32 (filename, &filenam);
+ if (!ret) {
+ set_fs (KERNEL_DS);
+ ret = sys_newlstat(filenam, &s);
+ set_fs (old_fs);
+ putname32 (filenam);
+ if (putstat (statbuf, &s)) return -EFAULT;
+ }
return ret;
}
@@ -1987,6 +2066,144 @@ asmlinkage int sys32_nfsservctl(int cmd, u32 argp, u32 resp)
return sys_nfsservctl(cmd, (void *)A(argp), (void *)A(resp));
}
+/*
+ * count32() counts the number of arguments/envelopes
+ */
+static int count32(u32 * argv)
+{
+ int i = 0;
+
+ if (argv != NULL) {
+ for (;;) {
+ u32 p; int error;
+
+ error = get_user(p,argv);
+ if (error) return error;
+ if (!p) break;
+ argv++; i++;
+ }
+ }
+ return i;
+}
+
+/*
+ * 'copy_string32()' copies argument/envelope strings from user
+ * memory to free pages in kernel mem. These are in a format ready
+ * to be put directly into the top of new user memory.
+ */
+static unsigned long
+copy_strings32(int argc,u32 * argv,unsigned long *page,
+ unsigned long p)
+{
+ u32 str;
+
+ if (!p) return 0; /* bullet-proofing */
+ while (argc-- > 0) {
+ int len;
+ unsigned long pos;
+
+ get_user(str, argv+argc);
+ if (!str) panic("VFS: argc is wrong");
+ len = strlen_user((char *)A(str)); /* includes the '\0' */
+ if (p < len) /* this shouldn't happen - 128kB */
+ return 0;
+ p -= len; pos = p;
+ while (len) {
+ char *pag;
+ int offset, bytes_to_copy;
+
+ offset = pos % PAGE_SIZE;
+ if (!(pag = (char *) page[pos/PAGE_SIZE]) &&
+ !(pag = (char *) page[pos/PAGE_SIZE] =
+ (unsigned long *) get_free_page(GFP_USER)))
+ return 0;
+ bytes_to_copy = PAGE_SIZE - offset;
+ if (bytes_to_copy > len)
+ bytes_to_copy = len;
+ copy_from_user(pag + offset, (char *)A(str), bytes_to_copy);
+ pos += bytes_to_copy;
+ str += bytes_to_copy;
+ len -= bytes_to_copy;
+ }
+ }
+ return p;
+}
+
+/*
+ * sys32_execve() executes a new program.
+ */
+static inline int
+do_execve32(char * filename, u32 * argv, u32 * envp, struct pt_regs * regs)
+{
+ struct linux_binprm bprm;
+ int retval;
+ int i;
+
+ bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);
+ for (i=0 ; i<MAX_ARG_PAGES ; i++) /* clear page-table */
+ bprm.page[i] = 0;
+ retval = open_namei(filename, 0, 0, &bprm.inode, NULL);
+ if (retval)
+ return retval;
+ bprm.filename = filename;
+ bprm.sh_bang = 0;
+ bprm.java = 0;
+ bprm.loader = 0;
+ bprm.exec = 0;
+ bprm.dont_iput = 0;
+ if ((bprm.argc = count32(argv)) < 0)
+ return bprm.argc;
+ if ((bprm.envc = count32(envp)) < 0)
+ return bprm.envc;
+
+ retval = prepare_binprm(&bprm);
+
+ if(retval>=0) {
+ bprm.p = copy_strings(1, &bprm.filename, bprm.page, bprm.p, 2);
+ bprm.exec = bprm.p;
+ bprm.p = copy_strings32(bprm.envc,envp,bprm.page,bprm.p);
+ bprm.p = copy_strings32(bprm.argc,argv,bprm.page,bprm.p);
+ if (!bprm.p)
+ retval = -E2BIG;
+ }
+
+ if(retval>=0)
+ retval = search_binary_handler(&bprm,regs);
+ if(retval>=0)
+ /* execve success */
+ return retval;
+
+ /* Something went wrong, return the inode and free the argument pages*/
+ if(!bprm.dont_iput)
+ iput(bprm.inode);
+ for (i=0 ; i<MAX_ARG_PAGES ; i++)
+ free_page(bprm.page[i]);
+ return(retval);
+}
+
+/*
+ * sparc32_execve() executes a new program after the asm stub has set
+ * things up for us. This should basically do what I want it to.
+ */
+asmlinkage int sparc32_execve(struct pt_regs *regs)
+{
+ int error, base = 0;
+ char *filename;
+
+ /* Check for indirect call. */
+ if((u32)regs->u_regs[UREG_G1] == 0)
+ base = 1;
+
+ error = getname((char *)(unsigned long)(u32)regs->u_regs[base + UREG_I0], &filename);
+ if(error)
+ return error;
+ error = do_execve32(filename,
+ (u32 *)A((u32)regs->u_regs[base + UREG_I1]),
+ (u32 *)A((u32)regs->u_regs[base + UREG_I2]), regs);
+ putname(filename);
+ return error;
+}
+
struct ncp_mount_data32 {
int version;
unsigned int ncp_fd;
diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S
index 8ff04f02a..02707186a 100644
--- a/arch/sparc64/kernel/systbls.S
+++ b/arch/sparc64/kernel/systbls.S
@@ -1,4 +1,4 @@
-/* $Id: systbls.S,v 1.8 1997/04/21 08:34:23 jj Exp $
+/* $Id: systbls.S,v 1.11 1997/05/27 19:30:20 jj Exp $
* systbls.S: System call entry point tables for OS compatibility.
* The native Linux system call table lives here also.
*
@@ -22,13 +22,13 @@ sys_call_table32:
/*10*/ .xword sys32_unlink, sunos_execv, sys32_chdir, sys_nis_syscall, sys32_mknod
/*15*/ .xword sys32_chmod, sys32_chown, sparc32_brk, sys_nis_syscall, sys32_lseek
/*20*/ .xword sys_getpid, sys_nis_syscall, sys_nis_syscall, sys_setuid, sys_getuid
-/*25*/ .xword sys32_time, sys32_ptrace, sys_alarm, sys_nis_syscall, sys_pause
+/*25*/ .xword sys32_time, sys_ptrace, sys_alarm, sys_nis_syscall, sys_pause
/*30*/ .xword sys32_utime, sys_stty, sys_gtty, sys32_access, sys_nice
.xword sys_ftime, sys_sync, sys_kill, sys32_newstat, sys_nis_syscall
/*40*/ .xword sys32_newlstat, sys_dup, sys_pipe, sys32_times, sys_profil
.xword sys_nis_syscall, sys_setgid, sys_getgid, sys32_signal, sys_geteuid
/*50*/ .xword sys_getegid, sys32_acct, sys_nis_syscall, sys_nis_syscall, sys32_ioctl
- .xword sys32_reboot, sys_nis_syscall, sys32_symlink, sys32_readlink, sys_execve
+ .xword sys32_reboot, sys_nis_syscall, sys32_symlink, sys32_readlink, sys32_execve
/*60*/ .xword sys_umask, sys32_chroot, sys32_newfstat, sys_nis_syscall, sys_getpagesize
.xword sys_nis_syscall, sys_vfork, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
/*70*/ .xword sys_nis_syscall, sys32_mmap, sys_nis_syscall, sys32_munmap, sys32_mprotect
@@ -61,7 +61,7 @@ sys_call_table32:
.xword sys_nis_syscall, sys32_socketcall, sys32_syslog, sys32_olduname, sys_nis_syscall
/*210*/ .xword sys_idle, sys_nis_syscall, sys32_waitpid, sys32_swapoff, sys32_sysinfo
.xword sys32_ipc, sys_sigreturn, sys_clone, sys_nis_syscall, sys32_adjtimex
-/*220*/ .xword sys_sigprocmask, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getpgid
+/*220*/ .xword sys32_sigprocmask, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getpgid
.xword sys32_bdflush, sys32_sysfs, sys_nis_syscall, sys_setfsuid, sys_setfsgid
/*230*/ .xword sys32_llseek, sys32_time, sys_nis_syscall, sys_stime, sys_nis_syscall
.xword sys_nis_syscall, sys32_llseek, sys32_mlock, sys32_munlock, sys_mlockall
@@ -153,7 +153,7 @@ sunos_sys_table:
/*50*/ .xword sunos_nosys, sys_acct, sunos_nosys
.xword sunos_mctl, sunos_ioctl, sys_reboot
.xword sunos_nosys, sys_symlink, sys_readlink
- .xword sys_execve, sys_umask, sys_chroot
+ .xword sys32_execve, sys_umask, sys_chroot
.xword sys_newfstat, sunos_nosys, sys_getpagesize
.xword sys_msync, sys_vfork, sunos_nosys
.xword sunos_nosys, sunos_sbrk, sunos_sstk
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
index c9774df06..6f96408ad 100644
--- a/arch/sparc64/kernel/traps.c
+++ b/arch/sparc64/kernel/traps.c
@@ -1,4 +1,4 @@
-/* $Id: traps.c,v 1.10 1997/05/18 08:42:16 davem Exp $
+/* $Id: traps.c,v 1.13 1997/05/27 19:30:08 jj Exp $
* arch/sparc/kernel/traps.c
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -24,76 +24,271 @@
#include <asm/unistd.h>
#include <asm/uaccess.h>
-/* #define TRAP_DEBUG */
+/* #define SYSCALL_TRACING */
+/* #define VERBOSE_SYSCALL_TRACING */
-struct trap_trace_entry {
- unsigned long pc;
- unsigned long type;
+#ifdef SYSCALL_TRACING
+#ifdef VERBOSE_SYSCALL_TRACING
+struct sdesc {
+ int scall_num;
+ char *name;
+ int num_args;
+ char arg_is_string[6];
+} sdesc_entries[] = {
+ { 0, "setup", 0, },
+ { 1, "exit", 1, { 0, } },
+ { 2, "fork", 0, },
+ { 3, "read", 3, { 0, 0, 0, } },
+ { 4, "write", 3, { 0, 0, 0, } },
+ { 5, "open", 3, { 1, 0, 0, } },
+ { 6, "close", 1, { 0, } },
+ { 7, "wait4", 4, { 0, 0, 0, 0, } },
+ { 8, "creat", 2, { 1, 0, } },
+ { 9, "link", 2, { 1, 1, } },
+ { 10, "unlink", 1, { 1, } },
+ { 11, "execv", 2, { 1, 0, } },
+ { 12, "chdir", 1, { 1, } },
+ { 15, "chmod", 2, { 1, 0, } },
+ { 16, "chown", 3, { 1, 0, 0, } },
+ { 17, "brk", 1, { 0, } },
+ { 19, "lseek", 3, { 0, 0, 0, } },
+ { 27, "alarm", 1, { 0, } },
+ { 29, "pause", 0, },
+ { 33, "access", 2, { 1, 0, } },
+ { 36, "sync", 0, },
+ { 37, "kill", 2, { 0, 0, } },
+ { 38, "stat", 2, { 1, 0, } },
+ { 40, "lstat", 2, { 1, 0, } },
+ { 41, "dup", 1, { 0, } },
+ { 42, "pipd", 0, },
+ { 54, "ioctl", 3, { 0, 0, 0, } },
+ { 57, "symlink", 2, { 1, 1, } },
+ { 58, "readlink", 3, { 1, 0, 0, } },
+ { 59, "execve", 3, { 1, 0, 0, } },
+ { 60, "umask", 1, { 0, } },
+ { 62, "fstat", 2, { 0, 0, } },
+ { 64, "getpagesize", 0, },
+ { 71, "mmap", 6, { 0, 0, 0, 0, 0, 0, } },
+ { 73, "munmap", 2, { 0, 0, } },
+ { 74, "mprotect", 3, { 0, 0, 0, } },
+ { 83, "setitimer", 3, { 0, 0, 0, } },
+ { 90, "dup2", 2, { 0, 0, } },
+ { 92, "fcntl", 3, { 0, 0, 0, } },
+ { 93, "select", 5, { 0, 0, 0, 0, 0, } },
+ { 97, "socket", 3, { 0, 0, 0, } },
+ { 98, "connect", 3, { 0, 0, 0, } },
+ { 99, "accept", 3, { 0, 0, 0, } },
+ { 101, "send", 4, { 0, 0, 0, 0, } },
+ { 102, "recv", 4, { 0, 0, 0, 0, } },
+ { 104, "bind", 3, { 0, 0, 0, } },
+ { 105, "setsockopt", 5, { 0, 0, 0, 0, 0, } },
+ { 106, "listen", 2, { 0, 0, } },
+ { 120, "readv", 3, { 0, 0, 0, } },
+ { 121, "writev", 3, { 0, 0, 0, } },
+ { 123, "fchown", 3, { 0, 0, 0, } },
+ { 124, "fchmod", 2, { 0, 0, } },
+ { 128, "rename", 2, { 1, 1, } },
+ { 129, "truncate", 2, { 1, 0, } },
+ { 130, "ftruncate", 2, { 0, 0, } },
+ { 131, "flock", 2, { 0, 0, } },
+ { 136, "mkdir", 2, { 1, 0, } },
+ { 137, "rmdir", 1, { 1, } },
+ { 146, "killpg", 1, { 0, } },
+ { 157, "statfs", 2, { 1, 0, } },
+ { 158, "fstatfs", 2, { 0, 0, } },
+ { 159, "umount", 1, { 1, } },
+ { 167, "mount", 5, { 1, 1, 1, 0, 0, } },
+ { 174, "getdents", 3, { 0, 0, 0, } },
+ { 176, "fchdir", 2, { 0, 0, } },
+ { 198, "sigaction", 3, { 0, 0, 0, } },
+ { 201, "sigsuspend", 1, { 0, } },
+ { 206, "socketcall", 2, { 0, 0, } },
+ { 216, "sigreturn", 0, },
+ { 230, "newselect", 5, { 0, 0, 0, 0, 0, } },
+ { 236, "llseek", 5, { 0, 0, 0, 0, 0, } },
+ { 251, "sysctl", 1, { 0, } },
};
+#define NUM_SDESC_ENTRIES (sizeof(sdesc_entries) / sizeof(sdesc_entries[0]))
+#endif
-int trap_curbuf = 0;
-struct trap_trace_entry trapbuf[1024];
+#ifdef VERBOSE_SYSCALL_TRACING
+static char scall_strbuf[512];
+#endif
-void syscall_trace_entry(struct pt_regs *regs)
+void syscall_trace_entry(unsigned long g1, struct pt_regs *regs)
{
- printk("%s[%d]: ", current->comm, current->pid);
- printk("scall<%ld> (could be %ld)\n", (long) regs->u_regs[UREG_G1],
- (long) regs->u_regs[UREG_I0]);
-}
+#ifdef VERBOSE_SYSCALL_TRACING
+ struct sdesc *sdp;
+ int i;
+#endif
-void syscall_trace_exit(struct pt_regs *regs)
-{
- printk("Syscall return check, reg dump.\n");
- show_regs(regs);
+ printk("SYS[%s:%d]: <%d> ", current->comm, current->pid, (int)g1);
+#ifdef VERBOSE_SYSCALL_TRACING
+ sdp = NULL;
+ for(i = 0; i < NUM_SDESC_ENTRIES; i++)
+ if(sdesc_entries[i].scall_num == g1) {
+ sdp = &sdesc_entries[i];
+ break;
+ }
+ if(sdp) {
+ printk("%s(", sdp->name);
+ for(i = 0; i < sdp->num_args; i++) {
+ if(i)
+ printk(",");
+ if(!sdp->arg_is_string[i])
+ printk("%08x", (unsigned int)regs->u_regs[UREG_I0 + i]);
+ else {
+ strncpy_from_user(scall_strbuf,
+ (char *)regs->u_regs[UREG_I0 + i],
+ 512);
+ printk("%s", scall_strbuf);
+ }
+ }
+ printk(") ");
+ }
+#endif
}
-void sparc64_dtlb_fault_handler (void)
+unsigned long syscall_trace_exit(unsigned long retval, struct pt_regs *regs)
{
- printk ("sparc64_dtlb_fault_handler\n");
- while (1);
- /* Die for now... */
+ printk("ret[%08x]\n", (unsigned int) retval);
+ return retval;
}
+#endif /* SYSCALL_TRACING */
-void sparc64_dtlb_refbit_handler (struct pt_regs *regs)
+#if 0
+void user_rtrap_report(struct pt_regs *regs)
{
- printk ("sparc64_dtlb_refbit_handler[%016lx]\n", regs->tpc);
- while (1);
- /* Die for now... */
-}
+ static int hits = 0;
-void sparc64_itlb_refbit_handler (void)
-{
- printk ("sparc64_itlb_refbit_handler\n");
- while (1);
- /* Die for now... */
+ /* Bwahhhhrggg... */
+ if(regs->tpc == 0x1f294UL && ++hits == 2) {
+ register unsigned long ctx asm("o4");
+ register unsigned long paddr asm("o5");
+ unsigned long cwp, wstate;
+
+ printk("RT[%016lx:%016lx] ", regs->tpc, regs->u_regs[UREG_I6]);
+ __asm__ __volatile__("rdpr %%cwp, %0" : "=r" (cwp));
+ __asm__ __volatile__("rdpr %%wstate, %0" : "=r" (wstate));
+ printk("CWP[%d] WSTATE[%016lx]\n"
+ "TSS( ksp[%016lx] kpc[%016lx] wstate[%016lx] w_saved[%d] flgs[%x]"
+ " cur_ds[%d] )\n", cwp, wstate,
+ current->tss.ksp, current->tss.kpc, current->tss.wstate,
+ (int) current->tss.w_saved, current->tss.flags,
+ current->tss.current_ds);
+ __asm__ __volatile__("
+ rdpr %%pstate, %%o3
+ wrpr %%o3, %2, %%pstate
+ mov %%g7, %%o5
+ mov 0x10, %%o4
+ ldxa [%%o4] %3, %%o4
+ wrpr %%o3, 0x0, %%pstate
+ " : "=r" (ctx), "=r" (paddr)
+ : "i" (PSTATE_MG|PSTATE_IE), "i" (ASI_DMMU));
+
+ printk("MMU[ppgd(%016lx)sctx(%d)] ", paddr, ctx);
+ printk("mm->context(%016lx) mm->pgd(%p)\n",
+ current->mm->context, current->mm->pgd);
+ printk("TASK: signal[%016lx] blocked[%016lx]\n",
+ current->signal, current->blocked);
+ show_regs(regs);
+ while(1)
+ barrier();
+ }
}
+#endif
void bad_trap (struct pt_regs *regs, long lvl)
{
- printk ("Bad trap %d (tstate %016lx tpc %016lx tnpc %016lx)\n", lvl, regs->tstate, regs->tpc, regs->tnpc);
- while (1);
- /* Die for now... */
+ lock_kernel ();
+ if (lvl < 0x100) {
+ char buffer[24];
+
+ sprintf (buffer, "Bad hw trap %lx at tl0\n", lvl);
+ die_if_kernel (buffer, regs);
+ }
+ if (regs->tstate & TSTATE_PRIV)
+ die_if_kernel ("Kernel bad trap", regs);
+ current->tss.sig_desc = SUBSIG_BADTRAP(lvl - 0x100);
+ current->tss.sig_address = regs->tpc;
+ send_sig(SIGILL, current, 1);
+ unlock_kernel ();
}
void bad_trap_tl1 (struct pt_regs *regs, long lvl)
{
- printk ("Bad trap %d at tl1+ (tstate %016lx tpc %016lx tnpc %016lx)\n", lvl, regs->tstate, regs->tpc, regs->tnpc);
- while (1);
- /* Die for now... */
+ char buffer[24];
+
+ lock_kernel ();
+ sprintf (buffer, "Bad trap %lx at tl>0", lvl);
+ die_if_kernel (buffer, regs);
}
void data_access_exception (struct pt_regs *regs)
{
- printk ("Unhandled data access exception sfsr %016lx sfar %016lx\n", spitfire_get_dsfsr(), spitfire_get_sfar());
+ lock_kernel ();
+ printk ("Unhandled data access exception ");
+ printk("sfsr %016lx sfar %016lx\n", spitfire_get_dsfsr(), spitfire_get_sfar());
die_if_kernel("Data access exception", regs);
}
+void do_dae(struct pt_regs *regs)
+{
+ printk("DAE: at %016lx\n", regs->tpc);
+ while(1)
+ barrier();
+}
+
void instruction_access_exception (struct pt_regs *regs)
{
- printk ("Unhandled instruction access exception sfsr %016lx\n", spitfire_get_isfsr());
+ lock_kernel ();
+ printk ("Unhandled instruction access exception ");
+ printk("sfsr %016lx\n", spitfire_get_isfsr());
die_if_kernel("Instruction access exception", regs);
}
+void do_iae(struct pt_regs *regs)
+{
+ printk("IAE at %016lx\n", regs->tpc);
+ while(1)
+ barrier();
+}
+
+void do_fpdis(struct pt_regs *regs)
+{
+ printk("FPDIS: at %016lx\n", regs->tpc);
+ while(1)
+ barrier();
+}
+
+void do_fpieee(struct pt_regs *regs)
+{
+ printk("FPIEEE: at %016lx\n", regs->tpc);
+ while(1)
+ barrier();
+}
+
+void do_fpother(struct pt_regs *regs)
+{
+ printk("FPOTHER: at %016lx\n", regs->tpc);
+ while(1)
+ barrier();
+}
+
+void do_tof(struct pt_regs *regs)
+{
+ printk("TOF: at %016lx\n", regs->tpc);
+ while(1)
+ barrier();
+}
+
+void do_div0(struct pt_regs *regs)
+{
+ printk("DIV0: at %016lx\n", regs->tpc);
+ while(1)
+ barrier();
+}
+
void instruction_dump (unsigned int *pc)
{
int i;
@@ -116,11 +311,27 @@ void die_if_kernel(char *str, struct pt_regs *regs)
" \\__U_/\n");
printk("%s(%d): %s\n", current->comm, current->pid, str);
+ __asm__ __volatile__("flushw");
show_regs(regs);
+ {
+ struct reg_window *rw = (struct reg_window *)
+ (regs->u_regs[UREG_FP] + STACK_BIAS);
+
+ if(rw) {
+ printk("Caller[%016lx]\n", rw->ins[7]);
+ rw = (struct reg_window *)
+ (rw->ins[6] + STACK_BIAS);
+ if(rw) {
+ printk("Caller[%016lx]\n", rw->ins[7]);
+ rw = (struct reg_window *)
+ (rw->ins[6] + STACK_BIAS);
+ if(rw)
+ printk("Caller[%016lx]\n", rw->ins[7]);
+ }
+ }
+ }
printk("Instruction DUMP:");
instruction_dump ((unsigned int *) regs->tpc);
- while(1)
- barrier();
if(regs->tstate & TSTATE_PRIV)
do_exit(SIGKILL);
do_exit(SIGSEGV);
@@ -160,6 +371,20 @@ void do_mna(struct pt_regs *regs)
barrier();
}
+void do_privop(struct pt_regs *regs)
+{
+ printk("PRIVOP: at %016lx\n", regs->tpc);
+ while(1)
+ barrier();
+}
+
+void do_privact(struct pt_regs *regs)
+{
+ printk("PRIVACT: at %016lx\n", regs->tpc);
+ while(1)
+ barrier();
+}
+
void do_priv_instruction(struct pt_regs *regs, unsigned long pc, unsigned long npc,
unsigned long tstate)
{