diff --git a/sys/arch/powerpc/ibm4xx/trap.c b/sys/arch/powerpc/ibm4xx/trap.c index 43d83db88f51..1d23281f9eca 100644 --- a/sys/arch/powerpc/ibm4xx/trap.c +++ b/sys/arch/powerpc/ibm4xx/trap.c @@ -1,4 +1,4 @@ -/* $NetBSD: trap.c,v 1.7 2002/07/11 01:38:49 simonb Exp $ */ +/* $NetBSD: trap.c,v 1.8 2002/08/02 03:46:42 chs Exp $ */ /* * Copyright 2001 Wasabi Systems, Inc. @@ -249,10 +249,6 @@ frame->srr0, (ftype&VM_PROT_WRITE) ? "write" : "read", frame->srr0, frame)); KERNEL_PROC_UNLOCK(p); break; - case EXC_SC|EXC_USER: - (*p->p_md.md_syscall)(frame); - break; - case EXC_AST|EXC_USER: astpending = 0; /* we are about to do it */ KERNEL_PROC_LOCK(p); diff --git a/sys/arch/powerpc/ibm4xx/trap_subr.S b/sys/arch/powerpc/ibm4xx/trap_subr.S index 268108bab13a..1414be6432ec 100644 --- a/sys/arch/powerpc/ibm4xx/trap_subr.S +++ b/sys/arch/powerpc/ibm4xx/trap_subr.S @@ -1,4 +1,4 @@ -/* $NetBSD: trap_subr.S,v 1.4 2002/07/11 01:38:49 simonb Exp $ */ +/* $NetBSD: trap_subr.S,v 1.5 2002/08/02 03:46:42 chs Exp $ */ /* * Copyright 2001 Wasabi Systems, Inc. @@ -70,7 +70,7 @@ * NOTICE: This is not a standalone file. to use it, #include it in * your port's locore.S, like so: * - * #include + * #include */ /* @@ -358,6 +358,50 @@ _C_LABEL(trapexit): FRAME_LEAVE(exitsave) rfi ba . /* Protect against prefetch */ + + + + .globl _C_LABEL(sctrap),_C_LABEL(scsize) +_C_LABEL(sctrap): + STANDARD_PROLOG(tempsave); + bla s_sctrap +_C_LABEL(scsize) = .-_C_LABEL(sctrap) + +s_sctrap: + FRAME_SETUP(tempsave) +/* Now we can recover interrupts again: */ + wrteei 1 /* Enable interrupts */ +/* Call the appropriate syscall handler: */ + addi 3,1,8 + lis 4,_C_LABEL(curproc)@ha + lwz 4,_C_LABEL(curproc)@l(4) + lwz 4,P_MD_SYSCALL@l(4) + mtctr 4 + bctrl +/* Disable interrupts: */ + wrteei 0 +/* Test AST pending: */ + lwz 5,FRAME_SRR1+8(1) + mtcr 5 + bc 4,17,1f /* branch if PSL_PR is false */ +#if defined(MULTIPROCESSOR) + GET_CPUINFO(3) + lwz 4,CI_ASTPENDING(3) +#else + lis 3,_C_LABEL(astpending)@ha + lwz 4,_C_LABEL(astpending)@l(3) +#endif + andi. 4,4,1 + beq 1f + li 6,EXC_AST + stw 6,FRAME_EXC+8(1) + b trapagain +1: + FRAME_LEAVE(exitsave) + rfi + ba . /* Protect against prefetch */ + + /* * External interrupt second level handler */ diff --git a/sys/arch/powerpc/include/userret.h b/sys/arch/powerpc/include/userret.h new file mode 100644 index 000000000000..fdc8895a509d --- /dev/null +++ b/sys/arch/powerpc/include/userret.h @@ -0,0 +1,81 @@ +/* $NetBSD: userret.h,v 1.1 2002/08/02 03:46:43 chs Exp $ */ + +/* + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Define the code needed before returning to user mode, for + * trap and syscall. + */ +static __inline void +userret(struct proc *p, struct trapframe *frame) +{ + struct cpu_info *ci = curcpu(); + struct pcb *pcb; + int sig; + + /* Take pending signals. */ + while ((sig = CURSIG(p)) != 0) { + KERNEL_PROC_LOCK(p); + postsig(sig); + KERNEL_PROC_UNLOCK(p); + } + + pcb = &p->p_addr->u_pcb; + + /* + * If someone stole the fp or vector unit while we were away, + * disable it + */ +#ifdef PPC_HAS_FPU + if ((pcb->pcb_flags & PCB_FPU) && + (p != ci->ci_fpuproc || pcb->pcb_fpcpu != ci)) { + frame->srr1 &= ~PSL_FP; + } +#endif +#ifdef ALTIVEC + if ((pcb->pcb_flags & PCB_ALTIVEC) && + (p != ci->ci_vecproc || pcb->pcb_veccpu != ci)) { + frame->srr1 &= ~PSL_VEC; + } + + /* + * If the new process isn't the current AltiVec process on this + * cpu, we need to stop any data streams that are active (since + * it will be a different address space). + */ + if (ci->ci_vecproc != NULL && ci->ci_vecproc != p) { + __asm __volatile("dssall;sync"); + } +#endif + + ci->ci_schedstate.spc_curpriority = p->p_priority = p->p_usrpri; +} diff --git a/sys/arch/powerpc/mpc6xx/genassym.cf b/sys/arch/powerpc/mpc6xx/genassym.cf index 4029576b5abb..f08736a609fb 100644 --- a/sys/arch/powerpc/mpc6xx/genassym.cf +++ b/sys/arch/powerpc/mpc6xx/genassym.cf @@ -1,4 +1,4 @@ -# $NetBSD: genassym.cf,v 1.5 2002/07/24 05:44:37 chs Exp $ +# $NetBSD: genassym.cf,v 1.6 2002/08/02 03:46:44 chs Exp $ # # Copyright (C) 1995, 1996 Wolfgang Solfrank. @@ -112,6 +112,8 @@ define P_ADDR offsetof(struct proc, p_addr) define P_STAT offsetof(struct proc, p_stat) define P_CPU offsetof(struct proc, p_cpu) +define P_MD_SYSCALL offsetof(struct proc, p_md.md_syscall) + define SONPROC SONPROC define CI_SIZE sizeof(struct cpu_info) diff --git a/sys/arch/powerpc/mpc6xx/mpc6xx_machdep.c b/sys/arch/powerpc/mpc6xx/mpc6xx_machdep.c index 2ebc9f9a869b..8a6b4a95006e 100644 --- a/sys/arch/powerpc/mpc6xx/mpc6xx_machdep.c +++ b/sys/arch/powerpc/mpc6xx/mpc6xx_machdep.c @@ -1,4 +1,4 @@ -/* $NetBSD: mpc6xx_machdep.c,v 1.4 2002/07/16 16:39:12 matt Exp $ */ +/* $NetBSD: mpc6xx_machdep.c,v 1.5 2002/08/02 03:46:44 chs Exp $ */ /* * Copyright (C) 2002 Matt Thomas @@ -104,6 +104,7 @@ void mpc6xx_init(void (*handler)(void)) { extern int trapcode, trapsize; + extern int sctrap, scsize; extern int alitrap, alisize; extern int dsitrap, dsisize; extern int isitrap, isisize; @@ -162,6 +163,10 @@ mpc6xx_init(void (*handler)(void)) */ break; #endif + case EXC_SC: + size = (size_t)&scsize; + memcpy((void *)EXC_SC, &sctrap, size); + break; case EXC_ALI: size = (size_t)&alisize; memcpy((void *)EXC_ALI, &alitrap, size); diff --git a/sys/arch/powerpc/powerpc/syscall.c b/sys/arch/powerpc/powerpc/syscall.c index 6c31057bb9fb..d2118da1ff03 100644 --- a/sys/arch/powerpc/powerpc/syscall.c +++ b/sys/arch/powerpc/powerpc/syscall.c @@ -1,4 +1,4 @@ -/* $NetBSD: syscall.c,v 1.3 2002/07/28 07:05:53 chs Exp $ */ +/* $NetBSD: syscall.c,v 1.4 2002/08/02 03:46:45 chs Exp $ */ /* * Copyright (C) 2002 Matt Thomas @@ -53,6 +53,7 @@ #include +#include #include #include @@ -86,7 +87,6 @@ syscall_plain(struct trapframe *frame) int n; curcpu()->ci_ev_scalls.ev_count++; - uvmexp.syscalls++; code = frame->fixreg[0]; callp = p->p_emul->e_sysent; @@ -163,6 +163,7 @@ syscall_bad: frame->cr |= 0x10000000; break; } + userret(p, frame); } void @@ -178,9 +179,7 @@ syscall_fancy(struct trapframe *frame) int n; KERNEL_PROC_LOCK(p); - curcpu()->ci_ev_scalls.ev_count++; - uvmexp.syscalls++; code = frame->fixreg[0]; callp = p->p_emul->e_sysent; @@ -251,6 +250,7 @@ syscall_bad: } KERNEL_PROC_UNLOCK(p); trace_exit(p, code, params, rval, error); + userret(p, frame); } void @@ -303,4 +303,3 @@ child_return(void *arg) /* Profiling? XXX */ curcpu()->ci_schedstate.spc_curpriority = p->p_priority; } - diff --git a/sys/arch/powerpc/powerpc/trap.c b/sys/arch/powerpc/powerpc/trap.c index 8bc344dd4f7d..0685bb9d9040 100644 --- a/sys/arch/powerpc/powerpc/trap.c +++ b/sys/arch/powerpc/powerpc/trap.c @@ -1,4 +1,4 @@ -/* $NetBSD: trap.c,v 1.66 2002/07/28 07:07:45 chs Exp $ */ +/* $NetBSD: trap.c,v 1.67 2002/08/02 03:46:45 chs Exp $ */ /* * Copyright (C) 1995, 1996 Wolfgang Solfrank. @@ -55,6 +55,7 @@ #include #include #include +#include #ifndef MULTIPROCESSOR volatile int astpending; @@ -223,9 +224,6 @@ trap(struct trapframe *frame) trapsignal(p, SIGSEGV, EXC_ISI); KERNEL_PROC_UNLOCK(p); break; - case EXC_SC|EXC_USER: - (*p->p_md.md_syscall)(frame); - break; case EXC_FPU|EXC_USER: ci->ci_ev_fpu.ev_count++; @@ -344,39 +342,7 @@ brain_damage2: #endif panic("trap"); } - - /* Take pending signals. */ - { - int sig; - - while ((sig = CURSIG(p)) != 0) - postsig(sig); - } - - /* - * If someone stole the fp or vector unit while we were away, - * disable it - */ - if ((pcb->pcb_flags & PCB_FPU) && - (p != ci->ci_fpuproc || pcb->pcb_fpcpu != ci)) { - frame->srr1 &= ~PSL_FP; - } -#ifdef ALTIVEC - if ((pcb->pcb_flags & PCB_ALTIVEC) && - (p != ci->ci_vecproc || pcb->pcb_veccpu != ci)) { - frame->srr1 &= ~PSL_VEC; - } - /* - * If the new process isn't the current AltiVec process on this - * cpu, we need to stop any data streams that are active (since - * it will be a different address space). - */ - if (ci->ci_vecproc != NULL && ci->ci_vecproc != p) { - __asm __volatile("dssall;sync"); - } -#endif - - ci->ci_schedstate.spc_curpriority = p->p_priority = p->p_usrpri; + userret(p, frame); } static inline void diff --git a/sys/arch/powerpc/powerpc/trap_subr.S b/sys/arch/powerpc/powerpc/trap_subr.S index 912cd52280ba..0c11454d057d 100644 --- a/sys/arch/powerpc/powerpc/trap_subr.S +++ b/sys/arch/powerpc/powerpc/trap_subr.S @@ -1,4 +1,4 @@ -/* $NetBSD: trap_subr.S,v 1.26 2002/07/28 07:06:27 chs Exp $ */ +/* $NetBSD: trap_subr.S,v 1.27 2002/08/02 03:46:45 chs Exp $ */ /* * Copyright (C) 1995, 1996 Wolfgang Solfrank. @@ -764,6 +764,54 @@ trapexit: FRAME_LEAVE(tempsave) rfi +/* + * Trap handler for syscalls (EXC_SC) + */ + + .globl _C_LABEL(sctrap),_C_LABEL(scsize) +_C_LABEL(sctrap): + mtsprg 1,1 /* save SP */ + stmw 28,tempsave(0) /* free r28-r31 */ + mflr 28 /* save LR */ + mfcr 29 /* save CR */ + bla s_sctrap + _C_LABEL(scsize) = .-_C_LABEL(sctrap) + +s_sctrap: + lis 1,_C_LABEL(curpcb)@ha + lwz 1,_C_LABEL(curpcb)@l(1) + addi 1,1,USPACE /* stack is top of user struct */ + RESTORE_KERN_SRS(30,31) /* First enable KERNEL mapping */ + CPU601_KERN_ENTRY(30,31) + FRAME_SETUP(tempsave) +/* Now we can recover interrupts again: */ + mfmsr 7 + ori 7,7,(PSL_EE|PSL_ME|PSL_RI)@l + mtmsr 7 + isync + addi 3,1,8 +/* Call the appropriate syscall handler: */ + lis 4,_C_LABEL(curproc)@ha + lwz 4,_C_LABEL(curproc)@l(4) + lwz 4,P_MD_SYSCALL@l(4) + mtctr 4 + bctrl +/* Disable interrupts: */ + mfmsr 3 + andi. 3,3,~PSL_EE@l + mtmsr 3 +/* Test AST pending: */ + lis 3,_C_LABEL(astpending)@ha + lwz 4,_C_LABEL(astpending)@l(3) + andi. 4,4,1 + beq 1f + li 6,EXC_AST + stw 6,FRAME_EXC+8(1) + b trapagain +1: + FRAME_LEAVE(tempsave) + rfi + /* * DSI second stage fault handler */ diff --git a/sys/arch/powerpc/powerpc/trap_subr_mp.S b/sys/arch/powerpc/powerpc/trap_subr_mp.S index 335cfa15dd02..6f192aa7f665 100644 --- a/sys/arch/powerpc/powerpc/trap_subr_mp.S +++ b/sys/arch/powerpc/powerpc/trap_subr_mp.S @@ -1,4 +1,4 @@ -/* $NetBSD: trap_subr_mp.S,v 1.5 2002/07/28 07:06:27 chs Exp $ */ +/* $NetBSD: trap_subr_mp.S,v 1.6 2002/08/02 03:46:46 chs Exp $ */ /* * Copyright (C) 1995, 1996 Wolfgang Solfrank. @@ -694,6 +694,55 @@ trapexit: FRAME_LEAVE(CI_TEMPSAVE) rfi +/* + * Trap handler for syscalls (EXC_SC) + */ + + .globl _C_LABEL(sctrap),_C_LABEL(scsize) +_C_LABEL(sctrap): + mtsprg 1,1 /* save SP */ + GET_CPUINFO(1) + stmw 28,CI_TEMPSAVE(1) /* free r28-r31 */ + mflr 28 /* save LR */ + mfcr 29 /* save CR */ + bla s_sctrap + _C_LABEL(scsize) = .-_C_LABEL(sctrap) + +s_sctrap: + GET_CPUINFO(1) + lwz 1,CI_CURPCB(1) + addi 1,1,USPACE /* stack is top of user struct */ + RESTORE_KERN_SRS(30,31) /* First enable KERNEL mapping */ + CPU601_KERN_ENTRY(30,31) + FRAME_SETUP(CI_TEMPSAVE) +/* Now we can recover interrupts again: */ + mfmsr 7 + ori 7,7,(PSL_EE|PSL_ME|PSL_RI)@l + mtmsr 7 + isync + addi 3,1,8 +/* Call the appropriate syscall handler: */ + GET_CPUINFO(4) + lwz 4,CI_CURPROC(4) + lwz 4,P_MD_SYSCALL(4) + mtctr 4 + bctrl +/* Disable interrupts: */ + mfmsr 3 + andi. 3,3,~PSL_EE@l + mtmsr 3 +/* Test AST pending: */ + GET_CPUINFO(3) + lwz 4,CI_ASTPENDING(3) + andi. 4,4,1 + beq 1f + li 6,EXC_AST + stw 6,FRAME_EXC+8(1) + b trapagain +1: + FRAME_LEAVE(CI_TEMPSAVE) + rfi + /* * DSI second stage fault handler */ diff --git a/sys/arch/walnut/walnut/genassym.cf b/sys/arch/walnut/walnut/genassym.cf index b67918dfa123..eaf381e06cb2 100644 --- a/sys/arch/walnut/walnut/genassym.cf +++ b/sys/arch/walnut/walnut/genassym.cf @@ -1,4 +1,4 @@ -# $NetBSD: genassym.cf,v 1.3 2002/06/05 06:32:21 augustss Exp $ +# $NetBSD: genassym.cf,v 1.4 2002/08/02 03:46:46 chs Exp $ # # Copyright (C) 1995, 1996 Wolfgang Solfrank. @@ -71,6 +71,8 @@ define P_ADDR offsetof(struct proc, p_addr) define P_STAT offsetof(struct proc, p_stat) define P_CPU offsetof(struct proc, p_cpu) +define P_MD_SYSCALL offsetof(struct proc, p_md.md_syscall) + define SONPROC SONPROC define CPU_CI offsetof(struct cpu_info, ci_ci) diff --git a/sys/arch/walnut/walnut/machdep.c b/sys/arch/walnut/walnut/machdep.c index 79485e653662..1c8e010ab310 100644 --- a/sys/arch/walnut/walnut/machdep.c +++ b/sys/arch/walnut/walnut/machdep.c @@ -1,4 +1,4 @@ -/* $NetBSD: machdep.c,v 1.7 2002/05/13 07:04:25 matt Exp $ */ +/* $NetBSD: machdep.c,v 1.8 2002/08/02 03:46:46 chs Exp $ */ /* * Copyright 2001, 2002 Wasabi Systems, Inc. @@ -153,6 +153,7 @@ void initppc(u_int startkernel, u_int endkernel, char *args, void *info_block) { extern int defaulttrap, defaultsize; + extern int sctrap, scsize; extern int alitrap, alisize; extern int dsitrap, dsisize; extern int isitrap, isisize; @@ -213,6 +214,9 @@ initppc(u_int startkernel, u_int endkernel, char *args, void *info_block) * This one is (potentially) installed during autoconf */ break; + case EXC_SC: + memcpy((void *)EXC_SC, &sctrap, (size_t)&scsize); + break; case EXC_ALI: memcpy((void *)EXC_ALI, &alitrap, (size_t)&alisize); break;