From 4a3201751221d4cec666d9a552eb7275b918c0d7 Mon Sep 17 00:00:00 2001 From: benno Date: Thu, 9 May 2002 14:22:55 +0000 Subject: Update to newer trap code from NetBSD. Obtained from: NetBSD --- sys/powerpc/aim/trap.c | 868 ++++++++++++++++++++++----------------------- sys/powerpc/include/trap.h | 48 ++- sys/powerpc/powerpc/trap.c | 868 ++++++++++++++++++++++----------------------- 3 files changed, 897 insertions(+), 887 deletions(-) (limited to 'sys/powerpc') diff --git a/sys/powerpc/aim/trap.c b/sys/powerpc/aim/trap.c index 097c59d..d5ba1fe 100644 --- a/sys/powerpc/aim/trap.c +++ b/sys/powerpc/aim/trap.c @@ -28,7 +28,7 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $NetBSD: trap.c,v 1.26 2000/05/27 00:40:40 sommerfeld Exp $ + * $NetBSD: trap.c,v 1.58 2002/03/04 04:07:35 dbj Exp $ */ #ifndef lint @@ -40,506 +40,499 @@ static const char rcsid[] = #include "opt_ktrace.h" #include -#include -#include #include #include -#include +#include #include #include -#include #include -#include +#include #include #ifdef KTRACE +#include #include #endif -#include #include #include #include +#include #include #include -#include +#include #include +#include +#include #include #include +#include #include #include +#include +#include -/* These definitions should probably be somewhere else XXX */ +/* These definitions should probably be somewhere else XXX */ #define FIRSTARG 3 /* first argument is in reg 3 */ #define NARGREG 8 /* 8 args are in registers */ #define MOREARGS(sp) ((caddr_t)((int)(sp) + 8)) /* more args go here */ -#ifdef WITNESS -extern char *syscallnames[]; +#ifndef MULTIPROCESSOR +volatile int astpending; +volatile int want_resched; +extern int intr_depth; #endif -#if 0 /* XXX: not used yet */ +void *syscall = NULL; /* XXX dummy symbol for emul_netbsd */ + static int fix_unaligned(struct proc *p, struct trapframe *frame); -#endif -static void trap_fatal(struct trapframe *frame); -static void printtrap(int vector, struct trapframe *frame, int isfatal, - int user); -static int trap_pfault(struct trapframe *frame, int user); -static int handle_onfault (struct trapframe *frame); - -static const char *ppc_exception_names[] = { - "reserved 0", /* 0 */ - "reset", /* 1 */ - "machine check", /* 2 */ - "data storage interrupt", /* 3 */ - "instruction storage interrupt", /* 4 */ - "external interrupt", /* 5 */ - "alignment interrupt", /* 6 */ - "program interrupt", /* 7 */ - "floating point unavailable", /* 8 */ - "decrementer interrupt", /* 9 */ - "reserved", /* 10 */ - "reserved", /* 11 */ - "system call", /* 12 */ - "trace", /* 13 */ - "floating point assist", /* 14 */ - "performance monitoring", /* 15 */ - "instruction tlb miss", /* 16 */ - "data load tlb miss", /* 17 */ - "data store tlb miss", /* 18 */ - "instruction breakpoint", /* 19 */ - "system management interrupt", /* 20 */ - "reserved 21", /* 21 */ - "reserved 22", /* 22 */ - "reserved 23", /* 23 */ - "reserved 24", /* 24 */ - "reserved 25", /* 25 */ - "reserved 26", /* 26 */ - "reserved 27", /* 27 */ - "reserved 28", /* 28 */ - "reserved 29", /* 29 */ - "reserved 30", /* 30 */ - "reserved 31", /* 31 */ - "reserved 32", /* 32 */ - "reserved 33", /* 33 */ - "reserved 34", /* 34 */ - "reserved 35", /* 35 */ - "reserved 36", /* 36 */ - "reserved 37", /* 37 */ - "reserved 38", /* 38 */ - "reserved 39", /* 39 */ - "reserved 40", /* 40 */ - "reserved 41", /* 41 */ - "reserved 42", /* 42 */ - "reserved 43", /* 43 */ - "reserved 44", /* 44 */ - "reserved 45", /* 45 */ - "reserved 46", /* 46 */ - "reserved 47", /* 47 */ -}; - -static void -printtrap(int vector, struct trapframe *frame, int isfatal, int user) -{ +static __inline void setusr(int); - printf("\n"); - printf("%s %s trap:\n", isfatal ? "fatal" : "handled", - user ? "user" : "kernel"); - printf("\n"); - printf(" exception = 0x%x (%s)\n", vector >> 8, - ppc_exception_names[vector >> 8]); - switch (vector) { - case EXC_DSI: - printf(" virtual address = 0x%x\n", frame->dar); - break; - case EXC_ISI: - printf(" virtual address = 0x%x\n", frame->srr0); - break; - } - printf(" srr0 = 0x%x", frame->srr0); - printf(" curthread = %p\n", curthread); - if (curthread != NULL) - printf(" pid = %d, comm = %s\n", - curthread->td_proc->p_pid, curthread->td_proc->p_comm); - printf("\n"); -} +void trap(struct trapframe *); /* Called from locore / trap_subr */ +int setfault(faultbuf); /* defined in locore.S */ +/* Why are these not defined in a header? */ +int badaddr(void *, size_t); +int badaddr_read(void *, size_t, int *); -static void -trap_fatal(struct trapframe *frame) +void +trap(frame) + struct trapframe *frame; { + struct thread *td = PCPU_GET(curthread); + struct proc *p = td->td_proc; + int type = frame->exc; + int ftype, rv; - printtrap(frame->exc, frame, 1, (frame->srr1 & PSL_PR)); -#ifdef DDB - if ((debugger_on_panic || db_active) && kdb_trap(frame->exc, 0, frame)) - return; +#if 0 + curcpu()->ci_ev_traps.ev_count++; #endif - panic("%s Trap", ppc_exception_names[frame->exc >> 8]); -} -/* - * Handles a fatal fault when we have onfault state to recover. Returns - * non-zero if there was onfault recovery state available. - */ -static int -handle_onfault (struct trapframe *frame) -{ - struct thread *td; - faultbuf *fb; - - td = curthread; - fb = td->td_pcb->pcb_onfault; - if (fb != NULL) { - frame->srr0 = (*fb)[0]; - frame->fixreg[1] = (*fb)[1]; - frame->fixreg[2] = (*fb)[2]; - frame->cr = (*fb)[3]; - bcopy(&(*fb)[4], &frame->fixreg[13], - 19 * sizeof(register_t)); - return (1); - } - return (0); -} + if (frame->srr1 & PSL_PR) + type |= EXC_USER; -void -trap(struct trapframe *frame) -{ - struct thread *td; - struct proc *p; - int sig, type, user; - u_int sticks, ucode; - - atomic_add_int(&cnt.v_trap, 1); - - td = curthread; - p = td->td_proc; - - type = frame->exc; - ucode = type; - sig = 0; - user = (frame->srr1 & PSL_PR); - sticks = 0; - - CTR3(KTR_TRAP, "trap: %s type=%s (%s)", p->p_comm, - ppc_exception_names[type >> 8], - user ? "user" : "kernel"); - - if (user) { - sticks = td->td_kse->ke_sticks; - td->td_frame = frame; - if (td->td_ucred != p->p_ucred) - cred_update_thread(td); - - /* User Mode Traps */ - switch (type) { - case EXC_TRC: - frame->srr1 &= ~PSL_SE; - sig = SIGTRAP; - break; - case EXC_DSI: - case EXC_ISI: - sig = trap_pfault(frame, 1); - break; - case EXC_SC: - syscall(frame); - break; - case EXC_FPU: - enable_fpu(PCPU_GET(curpcb)); - frame->srr1 |= PSL_FP; - break; +#ifdef DIAGNOSTIC + if (curpcb->pcb_pmreal != curpm) + panic("trap: curpm (%p) != curpcb->pcb_pmreal (%p)", + curpm, curpcb->pcb_pmreal); +#endif - case EXC_ALI: -#if 0 - if (fix_unaligned(p, frame) != 0) -#endif - sig = SIGBUS; -#if 0 - else - frame->srr0 += 4; -#endif +#if 0 + uvmexp.traps++; +#endif + + switch (type) { + case EXC_RUNMODETRC|EXC_USER: + /* FALLTHROUGH */ + case EXC_TRC|EXC_USER: + PROC_LOCK(p); + frame->srr1 &= ~PSL_SE; + trapsignal(p, SIGTRAP, EXC_TRC); + PROC_UNLOCK(p); break; + case EXC_DSI: { + faultbuf *fb; + /* + * Only query UVM if no interrupts are active (this applies + * "on-fault" as well. + */ +#if 0 + curcpu()->ci_ev_kdsi.ev_count++; +#endif + if (intr_depth < 0) { + struct vm_map *map; + vm_offset_t va; - case EXC_PGM: - /* XXX temporarily */ - /* XXX: Magic Number? */ - if (frame->srr1 & 0x0002000) - sig = SIGTRAP; +#if 0 + KERNEL_LOCK(LK_CANRECURSE|LK_EXCLUSIVE); +#endif + map = kernel_map; + va = frame->dar; + if ((va >> ADDR_SR_SHFT) == USER_SR) { + register_t user_sr; + + __asm ("mfsr %0, %1" + : "=r"(user_sr) : "K"(USER_SR)); + va &= ADDR_PIDX | ADDR_POFF; + va |= user_sr << ADDR_SR_SHFT; + /* KERNEL_PROC_LOCK(p); XXX */ + map = &p->p_vmspace->vm_map; + } + if (frame->dsisr & DSISR_STORE) + ftype = VM_PROT_WRITE; else - sig = SIGILL; - break; - - default: - trap_fatal(frame); - } - } else { - /* Kernel Mode Traps */ - - KASSERT(cold || td->td_ucred != NULL, - ("kernel trap doesn't have ucred")); - switch (type) { - case EXC_DSI: - if (trap_pfault(frame, 0) == 0) - return; - break; - case EXC_MCHK: - if (handle_onfault(frame)) + ftype = VM_PROT_READ; + rv = vm_fault(map, trunc_page(va), ftype, + VM_FAULT_NORMAL); +#if 0 + KERNEL_UNLOCK(); +#endif + if (rv == 0) return; - break; - default: - trap_fatal(frame); + if (rv == EACCES) + rv = EFAULT; + } else { + rv = EFAULT; } - /* NOTREACHED */ - } - if (sig != 0) { - if (p->p_sysent->sv_transtrap != NULL) - sig = (p->p_sysent->sv_transtrap)(sig, type); - trapsignal(p, sig, ucode); + if ((fb = td->td_pcb->pcb_onfault) != NULL) { + frame->srr0 = (*fb)[0]; + frame->fixreg[1] = (*fb)[1]; + frame->fixreg[2] = (*fb)[2]; + frame->fixreg[3] = rv; + frame->cr = (*fb)[3]; + memcpy(&frame->fixreg[13], &(*fb)[4], + 19 * sizeof(register_t)); + return; + } + printf("trap: kernel %s DSI @ %#x by %#x (DSISR %#x, err=%d)\n", + (frame->dsisr & DSISR_STORE) ? "write" : "read", + frame->dar, frame->srr0, frame->dsisr, rv); + goto brain_damage2; } - userret(td, frame, sticks); - mtx_assert(&Giant, MA_NOTOWNED); -#ifdef DIAGNOSTIC - cred_free_thread(td); + case EXC_DSI|EXC_USER: + PROC_LOCK(p); +#if 0 + curcpu()->ci_ev_udsi.ev_count++; #endif -} + if (frame->dsisr & DSISR_STORE) + ftype = VM_PROT_WRITE; + else + ftype = VM_PROT_READ; + rv = vm_fault(&p->p_vmspace->vm_map, trunc_page(frame->dar), + ftype, VM_FAULT_NORMAL); +#if 0 + curcpu()->ci_ev_udsi_fatal.ev_count++; +#endif + printf("trap: pid %d (%s): user %s DSI @ %#x " + "by %#x (DSISR %#x, err=%d)\n", + p->p_pid, p->p_comm, + (frame->dsisr & DSISR_STORE) ? "write" : "read", + frame->dar, frame->srr0, frame->dsisr, rv); + if (rv == ENOMEM) { + printf("UVM: pid %d (%s), uid %d killed: " + "out of swap\n", + p->p_pid, p->p_comm, + td->td_ucred ? td->td_ucred->cr_uid : -1); + trapsignal(p, SIGKILL, EXC_DSI); + } else { + trapsignal(p, SIGSEGV, EXC_DSI); + } + PROC_UNLOCK(p); + break; + case EXC_ISI: + printf("trap: kernel ISI by %#x (SRR1 %#x)\n", + frame->srr0, frame->srr1); + goto brain_damage2; + case EXC_ISI|EXC_USER: + PROC_LOCK(p); +#if 0 + curcpu()->ci_ev_isi.ev_count++; +#endif + ftype = VM_PROT_READ | VM_PROT_EXECUTE; + rv = vm_fault(&p->p_vmspace->vm_map, trunc_page(frame->srr0), + ftype, VM_FAULT_NORMAL); + printf("vm_fault said %d\n", rv); + if (rv == 0) { + PROC_UNLOCK(p); + break; + } +#if 0 + curcpu()->ci_ev_isi_fatal.ev_count++; +#endif + printf("trap: pid %d (%s): user ISI trap @ %#x " + "(SSR1=%#x)\n", + p->p_pid, p->p_comm, frame->srr0, frame->srr1); + trapsignal(p, SIGSEGV, EXC_ISI); + PROC_UNLOCK(p); + break; + case EXC_SC|EXC_USER: +#if 0 + curcpu()->ci_ev_scalls.ev_count++; +#endif + { + const struct sysent *callp; + size_t argsize; + register_t code, error; + register_t *params, rval[2]; + int n; + register_t args[10]; -void -syscall(struct trapframe *frame) -{ - caddr_t params; - struct sysent *callp; - struct thread *td; - struct proc *p; - int error, n; - size_t narg; - register_t args[10]; - u_int code; - - td = curthread; - p = td->td_proc; - - atomic_add_int(&cnt.v_syscall, 1); - - code = frame->fixreg[0]; - params = (caddr_t) (frame->fixreg + FIRSTARG); - - if (p->p_sysent->sv_prepsyscall) - /* - * The prep code is MP aware. - */ - (*p->p_sysent->sv_prepsyscall)(frame, args, &code, ¶ms); - else if (code == SYS_syscall) - /* - * code is first argument, - * followed by actual args. - */ - code = *params++; - else if (code == SYS___syscall) { - /* - * Like syscall, but code is a quad, - * so as to maintain quad alignment - * for the rest of the args. - */ - params++; - code = *params++; - } + PROC_LOCK(p); - if (p->p_sysent->sv_mask) - code &= p->p_sysent->sv_mask; +#if 0 + uvmexp.syscalls++; +#endif - if (code >= p->p_sysent->sv_size) - callp = &p->p_sysent->sv_table[0]; - else - callp = &p->p_sysent->sv_table[code]; + code = frame->fixreg[0]; + callp = &p->p_sysent->sv_table[0]; + params = frame->fixreg + FIRSTARG; + n = NARGREG; + + switch (code) { + case SYS_syscall: + /* + * code is first argument, + * followed by actual args. + */ + code = *params++; + n -= 1; + break; + case SYS___syscall: + params++; + code = *params++; + n -= 2; + break; + default: + break; + } - narg = callp->sy_narg & SYF_ARGMASK; + if (p->p_sysent->sv_mask) + code &= p->p_sysent->sv_mask; + callp += code; + argsize = callp->sy_narg & SYF_ARGMASK; + + if (argsize > n * sizeof(register_t)) { + memcpy(args, params, n * sizeof(register_t)); + error = copyin(MOREARGS(frame->fixreg[1]), + args + n, + argsize - n * sizeof(register_t)); + if (error) + goto syscall_bad; + params = args; + } - n = NARGREG - (params - (caddr_t)(frame->fixreg + FIRSTARG)); - if (narg > n * sizeof(register_t)) { - bcopy(params, args, n * sizeof(register_t)); - if (error = copyin(MOREARGS(frame->fixreg[1]), args + n, - narg - n * sizeof(register_t))) { #ifdef KTRACE - /* Can't get all the arguments! */ if (KTRPOINT(p, KTR_SYSCALL)) - ktrsyscall(p->p_tracep, code, narg, args); + ktrsyscall(p, code, argsize, params); #endif - goto bad; - } - params = (caddr_t) args; - } - /* - * Try to run the syscall without Giant if the syscall is MP safe. - */ - if ((callp->sy_narg & SYF_MPSAFE) == 0) - mtx_lock(&Giant); + rval[0] = 0; + rval[1] = 0; + + error = (*callp->sy_call)(td, params); + switch (error) { + case 0: + frame->fixreg[FIRSTARG] = rval[0]; + frame->fixreg[FIRSTARG + 1] = rval[1]; + frame->cr &= ~0x10000000; + break; + case ERESTART: + /* + * Set user's pc back to redo the system call. + */ + frame->srr0 -= 4; + break; + case EJUSTRETURN: + /* nothing to do */ + break; + default: +syscall_bad: +#if 0 + if (p->p_emul->e_errno) + error = p->p_emul->e_errno[error]; +#endif + frame->fixreg[FIRSTARG] = error; + frame->cr |= 0x10000000; + break; + } #ifdef KTRACE - if (KTRPOINT(p, KTR_SYSCALL)) - ktrsyscall(p->p_tracep, code, narg, params); + if (KTRPOINT(p, KTR_SYSRET)) + ktrsysret(p, code, error, rval[0]); #endif - td->td_retval[0] = 0; - td->td_retval[1] = frame->fixreg[FIRSTARG + 1]; - - STOPEVENT(p, S_SCE, narg); - - error = (*callp->sy_call)(td, args); - switch (error) { - case 0: - frame->fixreg[FIRSTARG] = td->td_retval[0]; - frame->fixreg[FIRSTARG + 1] = td->td_retval[1]; - /* XXX: Magic number */ - frame->cr &= ~0x10000000; - break; - case ERESTART: - /* - * Set user's pc back to redo the system call. - */ - frame->srr0 -= 4; - break; - case EJUSTRETURN: - /* nothing to do */ - break; - default: -bad: - if (p->p_sysent->sv_errsize) { - if (error >= p->p_sysent->sv_errsize) - error = -1; /* XXX */ - else - error = p->p_sysent->sv_errtbl[error]; } - frame->fixreg[FIRSTARG] = error; - /* XXX: Magic number: Carry Flag Equivalent? */ - frame->cr |= 0x10000000; + PROC_UNLOCK(p); break; - } - -#ifdef KTRACE - if (KTRPOINT(p, KTR_SYSRET)) - ktrsysret(p->p_tracep, code, error, td->td_retval[0]); + case EXC_FPU|EXC_USER: +#if 0 + curcpu()->ci_ev_fpu.ev_count++; #endif +#if 0 + if (fpuproc) { + curcpu()->ci_ev_fpusw.ev_count++; + save_fpu(fpuproc); + } +#endif +#if defined(MULTIPROCESSOR) + if (p->p_addr->u_pcb.pcb_fpcpu) + save_fpu_proc(p); +#endif +#if 0 + fpuproc = p; + p->p_addr->u_pcb.pcb_fpcpu = curcpu(); + enable_fpu(p); +#endif + break; - if ((callp->sy_narg & SYF_MPSAFE) == 0) - mtx_unlock(&Giant); - - /* - * Does the comment in the i386 code about errno apply here? - */ - STOPEVENT(p, S_SCX, code); +#ifdef ALTIVEC + case EXC_VEC|EXC_USER: +#if 0 + curcpu()->ci_ev_vec.ev_count++; +#endif + if (vecproc) { +#if 0 + curcpu()->ci_ev_vecsw.ev_count++; +#endif + save_vec(vecproc); + } + vecproc = p; + enable_vec(p); + break; +#endif -#ifdef WITNESS - if (witness_list(td)) { - panic("system call %s returning with mutex(s) held\n", - syscallnames[code]); - } + case EXC_AST|EXC_USER: + astpending = 0; /* we are about to do it */ + PROC_LOCK(p); +#if 0 + uvmexp.softs++; + if (p->p_flag & P_OWEUPC) { + p->p_flag &= ~P_OWEUPC; + ADDUPROF(p); + } #endif - mtx_assert(&sched_lock, MA_NOTOWNED); - mtx_assert(&Giant, MA_NOTOWNED); -} + /* Check whether we are being preempted. */ + if (want_resched) + mi_switch(); + PROC_UNLOCK(p); + break; -static int -trap_pfault(struct trapframe *frame, int user) -{ - vm_offset_t eva, va; - struct thread *td; - struct proc *p; - vm_map_t map; - vm_prot_t ftype; - int rv; + case EXC_ALI|EXC_USER: + PROC_LOCK(p); +#if 0 + curcpu()->ci_ev_ali.ev_count++; +#endif + if (fix_unaligned(p, frame) != 0) { +#if 0 + curcpu()->ci_ev_ali_fatal.ev_count++; +#endif + printf("trap: pid %d (%s): user ALI trap @ %#x " + "(SSR1=%#x)\n", + p->p_pid, p->p_comm, frame->srr0, + frame->srr1); + trapsignal(p, SIGBUS, EXC_ALI); + } else + frame->srr0 += 4; + PROC_UNLOCK(p); + break; - td = curthread; - p = td->td_proc; - if (frame->exc == EXC_ISI) { - eva = frame->srr0; - ftype = VM_PROT_READ | VM_PROT_EXECUTE; - } else { - eva = frame->dar; - if (frame->dsisr & DSISR_STORE) - ftype = VM_PROT_READ | VM_PROT_WRITE; + case EXC_PGM|EXC_USER: +/* XXX temporarily */ + PROC_LOCK(p); +#if 0 + curcpu()->ci_ev_pgm.ev_count++; +#endif + printf("trap: pid %d (%s): user PGM trap @ %#x " + "(SSR1=%#x)\n", + p->p_pid, p->p_comm, frame->srr0, frame->srr1); + if (frame->srr1 & 0x00020000) /* Bit 14 is set if trap */ + trapsignal(p, SIGTRAP, EXC_PGM); else - ftype = VM_PROT_READ; - } + trapsignal(p, SIGILL, EXC_PGM); + PROC_UNLOCK(p); + break; - if ((eva >> ADDR_SR_SHFT) != USER_SR) { - if (user) - return (SIGSEGV); - map = kernel_map; - } else { - u_int user_sr; - - if (p->p_vmspace == NULL) - return (SIGSEGV); - - __asm ("mfsr %0, %1" - : "=r"(user_sr) - : "K"(USER_SR)); - eva &= ADDR_PIDX | ADDR_POFF; - eva |= user_sr << ADDR_SR_SHFT; - map = &p->p_vmspace->vm_map; + case EXC_MCHK: { + faultbuf *fb; + + if ((fb = td->td_pcb->pcb_onfault) != NULL) { + frame->srr0 = (*fb)[0]; + frame->fixreg[1] = (*fb)[1]; + frame->fixreg[2] = (*fb)[2]; + frame->fixreg[3] = EFAULT; + frame->cr = (*fb)[3]; + memcpy(&frame->fixreg[13], &(*fb)[4], + 19 * sizeof(register_t)); + return; + } + goto brain_damage; } - va = trunc_page(eva); - if (map != kernel_map) { - /* - * Keep swapout from messing with us during this - * critical time. - */ - PROC_LOCK(p); - ++p->p_lock; - PROC_UNLOCK(p); + default: +brain_damage: + printf("trap type %x at %x\n", type, frame->srr0); +brain_damage2: +#ifdef DDBX + if (kdb_trap(type, frame)) + return; +#endif +#ifdef TRAP_PANICWAIT + printf("Press a key to panic.\n"); + cnpollc(1); + cngetc(); + cnpollc(0); +#endif + panic("trap"); + } - /* Fault in the user page: */ - rv = vm_fault(map, va, ftype, - (ftype & VM_PROT_WRITE) ? VM_FAULT_DIRTY - : VM_FAULT_NORMAL); + /* Take pending signals. */ + { + int sig; - PROC_LOCK(p); - --p->p_lock; - PROC_UNLOCK(p); - } else { - /* - * Don't have to worry about process locking or stacks in the - * kernel. - */ - rv = vm_fault(map, va, ftype, VM_FAULT_NORMAL); + while ((sig = CURSIG(p)) != 0) + postsig(sig); } - if (rv == KERN_SUCCESS) - return (0); - if (!user && handle_onfault(frame)) - return (0); + /* + * If someone stole the fp or vector unit while we were away, + * disable it + */ +#if 0 + if (p != fpuproc || p->p_addr->u_pcb.pcb_fpcpu != curcpu()) + frame->srr1 &= ~PSL_FP; +#endif +#ifdef ALTIVEC + if (p != vecproc) + frame->srr1 &= ~PSL_VEC; +#endif - return (SIGSEGV); +#if 0 + curcpu()->ci_schedstate.spc_curpriority = p->p_priority = p->p_usrpri; + p->p_priority = p->p_usrpri; +#endif } -#if 0 /* XXX: child_return not used */ -/* - * XXX: the trapframe return values should be setup in vm_machdep.c in - * cpu_fork(). - */ +void child_return(void *); + void child_return(void *arg) { - struct proc *p; - struct trapframe *tf; + struct thread *td = arg; + struct proc *p = td->td_proc; + struct trapframe *tf = trapframe(td); - p = arg; - tf = trapframe(p); + PROC_UNLOCK(p); tf->fixreg[FIRSTARG] = 0; tf->fixreg[FIRSTARG + 1] = 1; tf->cr &= ~0x10000000; - tf->srr1 &= ~PSL_FP; /* Disable FPU, as we can't be fpuproc */ +#if 0 + tf->srr1 &= ~(PSL_FP|PSL_VEC); /* Disable FP & AltiVec, as we can't + be them. */ + td->td_pcb->pcb_fpcpu = NULL; +#endif #ifdef KTRACE - if (KTRPOINT(p, KTR_SYSRET)) + if (KTRPOINT(p, KTR_SYSRET)) { + PROC_LOCK(p); ktrsysret(p, SYS_fork, 0, 0); + PROC_UNLOCK(p); + } #endif /* Profiling? XXX */ +#if 0 curcpu()->ci_schedstate.spc_curpriority = p->p_priority; -} #endif +} + +static __inline void +setusr(content) + int content; +{ + __asm __volatile ("isync; mtsr %0,%1; isync" + :: "n"(USER_SR), "r"(content)); +} + +int kcopy(const void *, void *, size_t); -#if 0 /* XXX: not used yet */ /* * kcopy(const void *src, void *dst, size_t len); * @@ -553,38 +546,48 @@ child_return(void *arg) int kcopy(const void *src, void *dst, size_t len) { + struct thread *td; faultbuf env, *oldfault; + int rv; - oldfault = PCPU_GET(curpcb)->pcb_onfault; - if (setfault(env)) { - PCPU_GET(curpcb)->pcb_onfault = oldfault; - return EFAULT; + td = PCPU_GET(curthread); + oldfault = td->td_pcb->pcb_onfault; + if ((rv = setfault(env)) != 0) { + td->td_pcb->pcb_onfault = oldfault; + return rv; } - bcopy(src, dst, len); + memcpy(dst, src, len); - PCPU_GET(curpcb)->pcb_onfault = oldfault; + td->td_pcb->pcb_onfault = oldfault; return 0; } int -badaddr(void *addr, size_t size) +badaddr(addr, size) + void *addr; + size_t size; { - return badaddr_read(addr, size, NULL); } int -badaddr_read(void *addr, size_t size, int *rptr) +badaddr_read(addr, size, rptr) + void *addr; + size_t size; + int *rptr; { + struct thread *td; faultbuf env; int x; /* Get rid of any stale machine checks that have been waiting. */ __asm __volatile ("sync; isync"); + td = PCPU_GET(curthread); + if (setfault(env)) { - PCPU_GET(curpcb)->pcb_onfault = 0; + td->td_pcb->pcb_onfault = 0; __asm __volatile ("sync"); return 1; } @@ -608,7 +611,7 @@ badaddr_read(void *addr, size_t size, int *rptr) /* Make sure we took the machine check, if we caused one. */ __asm __volatile ("sync; isync"); - PCPU_GET(curpcb)->pcb_onfault = 0; + td->td_pcb->pcb_onfault = 0; __asm __volatile ("sync"); /* To be sure. */ /* Use the value to avoid reorder. */ @@ -617,7 +620,6 @@ badaddr_read(void *addr, size_t size, int *rptr) return 0; } -#endif /* * For now, this only deals with the particular unaligned access case @@ -625,19 +627,17 @@ badaddr_read(void *addr, size_t size, int *rptr) * possibilities that can happen on a 32-bit PowerPC in big-endian mode. */ -#if 0 /* XXX: Not used yet */ static int fix_unaligned(p, frame) struct proc *p; struct trapframe *frame; { - int indicator; - - indicator = EXC_ALI_OPCODE_INDICATOR(frame->dsisr); + int indicator = EXC_ALI_OPCODE_INDICATOR(frame->dsisr); switch (indicator) { case EXC_ALI_LFD: case EXC_ALI_STFD: +#if 0 { int reg = EXC_ALI_RST(frame->dsisr); double *fpr = &p->p_addr->u_pcb.pcb_fpu.fpr[reg]; @@ -646,20 +646,18 @@ fix_unaligned(p, frame) * the FPRs, and that their current state is in * the PCB. */ - if (!(pcb->pcb_flags & PCB_FPU)) - enable_fpu(PCPU_GET(curpcb)); - frame->srr1 |= PSL_FP; + if (fpuproc != p) { + if (fpuproc) + save_fpu(fpuproc); + enable_fpu(p); } - save_fpu(PCPU_GET(curpcb)); + save_fpu(p); if (indicator == EXC_ALI_LFD) { if (copyin((void *)frame->dar, fpr, sizeof(double)) != 0) return -1; - if (!(pcb->pcb_flags & PCB_FPU)) - enable_fpu(PCPU_GET(curpcb)); - frame->srr1 |= PSL_FP; - } + enable_fpu(p); } else { if (copyout(fpr, (void *)frame->dar, sizeof(double)) != 0) @@ -667,9 +665,9 @@ fix_unaligned(p, frame) } return 0; } +#endif break; } return -1; } -#endif diff --git a/sys/powerpc/include/trap.h b/sys/powerpc/include/trap.h index 2438f08..2883e1e 100644 --- a/sys/powerpc/include/trap.h +++ b/sys/powerpc/include/trap.h @@ -28,15 +28,15 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $NetBSD: trap.h,v 1.3 2000/05/25 21:10:14 is Exp $ - * $FreeBSD$ + * $NetBSD: trap.h,v 1.7 2002/02/22 13:51:40 kleink Exp $ + * $FreeBSD$ */ #ifndef _POWERPC_TRAP_H_ #define _POWERPC_TRAP_H_ #define EXC_RSVD 0x0000 /* Reserved */ -#define EXC_RST 0x0100 /* Reset */ +#define EXC_RST 0x0100 /* Reset; all but IBM4xx */ #define EXC_MCHK 0x0200 /* Machine Check */ #define EXC_DSI 0x0300 /* Data Storage Interrupt */ #define EXC_ISI 0x0400 /* Instruction Storage Interrupt */ @@ -49,18 +49,39 @@ #define EXC_TRC 0x0d00 /* Trace */ #define EXC_FPA 0x0e00 /* Floating-point Assist */ -/* The following are only available on 604: */ +/* The following is only available on the 601: */ +#define EXC_RUNMODETRC 0x2000 /* Run Mode/Trace Exception */ + +/* The following are only available on 7400(G4): */ +#define EXC_VEC 0x0f20 /* AltiVec Unavailable */ +#define EXC_VECAST 0x1600 /* AltiVec Assist */ + +/* The following are only available on 604/750/7400: */ #define EXC_PERF 0x0f00 /* Performance Monitoring */ #define EXC_BPT 0x1300 /* Instruction Breakpoint */ -#define EXC_SMI 0x1400 /* System Management Interrupt */ +#define EXC_SMI 0x1400 /* System Managment Interrupt */ + +/* The following are only available on 750/7400: */ +#define EXC_THRM 0x1700 /* Thermal Management Interrupt */ /* And these are only on the 603: */ #define EXC_IMISS 0x1000 /* Instruction translation miss */ #define EXC_DLMISS 0x1100 /* Data load translation miss */ #define EXC_DSMISS 0x1200 /* Data store translation miss */ +/* The following are only available on 405 (and 403?) */ +#define EXC_CII 0x0100 /* Critical Input Interrupt */ +#define EXC_PIT 0x1000 /* Programmable Interval Timer */ +#define EXC_FIT 0x1010 /* Fixed Interval Timer */ +#define EXC_WDOG 0x1020 /* Watchdog Timer */ +#define EXC_DTMISS 0x1100 /* Data TLB Miss */ +#define EXC_ITMISS 0x1200 /* Instruction TLB Miss */ +#define EXC_DEBUG 0x2000 /* Debug trap */ + #define EXC_LAST 0x2f00 /* Last possible exception vector */ +#define EXC_AST 0x3000 /* Fake AST vector */ + /* Trap was in user mode */ #define EXC_USER 0x10000 @@ -74,19 +95,12 @@ * PowerPC Architecture". */ -#define EXC_ALI_OPCODE_INDICATOR(dsisr) ((dsisr >> 10) & 0x7f) -#define EXC_ALI_LFD 0x09 -#define EXC_ALI_STFD 0x0b +#define EXC_ALI_OPCODE_INDICATOR(dsisr) ((dsisr >> 10) & 0x7f) +#define EXC_ALI_LFD 0x09 +#define EXC_ALI_STFD 0x0b /* Macros to extract register information */ -#define EXC_ALI_RST(dsisr) ((dsisr >> 5) & 0x1f) /* source or target */ -#define EXC_ALI_RA(dsisr) (dsisr & 0x1f) - -#ifndef LOCORE - -void trap(struct trapframe *); -void syscall(struct trapframe *); - -#endif /* !LOCORE */ +#define EXC_ALI_RST(dsisr) ((dsisr >> 5) & 0x1f) /* source or target */ +#define EXC_ALI_RA(dsisr) (dsisr & 0x1f) #endif /* _POWERPC_TRAP_H_ */ diff --git a/sys/powerpc/powerpc/trap.c b/sys/powerpc/powerpc/trap.c index 097c59d..d5ba1fe 100644 --- a/sys/powerpc/powerpc/trap.c +++ b/sys/powerpc/powerpc/trap.c @@ -28,7 +28,7 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $NetBSD: trap.c,v 1.26 2000/05/27 00:40:40 sommerfeld Exp $ + * $NetBSD: trap.c,v 1.58 2002/03/04 04:07:35 dbj Exp $ */ #ifndef lint @@ -40,506 +40,499 @@ static const char rcsid[] = #include "opt_ktrace.h" #include -#include -#include #include #include -#include +#include #include #include -#include #include -#include +#include #include #ifdef KTRACE +#include #include #endif -#include #include #include #include +#include #include #include -#include +#include #include +#include +#include #include #include +#include #include #include +#include +#include -/* These definitions should probably be somewhere else XXX */ +/* These definitions should probably be somewhere else XXX */ #define FIRSTARG 3 /* first argument is in reg 3 */ #define NARGREG 8 /* 8 args are in registers */ #define MOREARGS(sp) ((caddr_t)((int)(sp) + 8)) /* more args go here */ -#ifdef WITNESS -extern char *syscallnames[]; +#ifndef MULTIPROCESSOR +volatile int astpending; +volatile int want_resched; +extern int intr_depth; #endif -#if 0 /* XXX: not used yet */ +void *syscall = NULL; /* XXX dummy symbol for emul_netbsd */ + static int fix_unaligned(struct proc *p, struct trapframe *frame); -#endif -static void trap_fatal(struct trapframe *frame); -static void printtrap(int vector, struct trapframe *frame, int isfatal, - int user); -static int trap_pfault(struct trapframe *frame, int user); -static int handle_onfault (struct trapframe *frame); - -static const char *ppc_exception_names[] = { - "reserved 0", /* 0 */ - "reset", /* 1 */ - "machine check", /* 2 */ - "data storage interrupt", /* 3 */ - "instruction storage interrupt", /* 4 */ - "external interrupt", /* 5 */ - "alignment interrupt", /* 6 */ - "program interrupt", /* 7 */ - "floating point unavailable", /* 8 */ - "decrementer interrupt", /* 9 */ - "reserved", /* 10 */ - "reserved", /* 11 */ - "system call", /* 12 */ - "trace", /* 13 */ - "floating point assist", /* 14 */ - "performance monitoring", /* 15 */ - "instruction tlb miss", /* 16 */ - "data load tlb miss", /* 17 */ - "data store tlb miss", /* 18 */ - "instruction breakpoint", /* 19 */ - "system management interrupt", /* 20 */ - "reserved 21", /* 21 */ - "reserved 22", /* 22 */ - "reserved 23", /* 23 */ - "reserved 24", /* 24 */ - "reserved 25", /* 25 */ - "reserved 26", /* 26 */ - "reserved 27", /* 27 */ - "reserved 28", /* 28 */ - "reserved 29", /* 29 */ - "reserved 30", /* 30 */ - "reserved 31", /* 31 */ - "reserved 32", /* 32 */ - "reserved 33", /* 33 */ - "reserved 34", /* 34 */ - "reserved 35", /* 35 */ - "reserved 36", /* 36 */ - "reserved 37", /* 37 */ - "reserved 38", /* 38 */ - "reserved 39", /* 39 */ - "reserved 40", /* 40 */ - "reserved 41", /* 41 */ - "reserved 42", /* 42 */ - "reserved 43", /* 43 */ - "reserved 44", /* 44 */ - "reserved 45", /* 45 */ - "reserved 46", /* 46 */ - "reserved 47", /* 47 */ -}; - -static void -printtrap(int vector, struct trapframe *frame, int isfatal, int user) -{ +static __inline void setusr(int); - printf("\n"); - printf("%s %s trap:\n", isfatal ? "fatal" : "handled", - user ? "user" : "kernel"); - printf("\n"); - printf(" exception = 0x%x (%s)\n", vector >> 8, - ppc_exception_names[vector >> 8]); - switch (vector) { - case EXC_DSI: - printf(" virtual address = 0x%x\n", frame->dar); - break; - case EXC_ISI: - printf(" virtual address = 0x%x\n", frame->srr0); - break; - } - printf(" srr0 = 0x%x", frame->srr0); - printf(" curthread = %p\n", curthread); - if (curthread != NULL) - printf(" pid = %d, comm = %s\n", - curthread->td_proc->p_pid, curthread->td_proc->p_comm); - printf("\n"); -} +void trap(struct trapframe *); /* Called from locore / trap_subr */ +int setfault(faultbuf); /* defined in locore.S */ +/* Why are these not defined in a header? */ +int badaddr(void *, size_t); +int badaddr_read(void *, size_t, int *); -static void -trap_fatal(struct trapframe *frame) +void +trap(frame) + struct trapframe *frame; { + struct thread *td = PCPU_GET(curthread); + struct proc *p = td->td_proc; + int type = frame->exc; + int ftype, rv; - printtrap(frame->exc, frame, 1, (frame->srr1 & PSL_PR)); -#ifdef DDB - if ((debugger_on_panic || db_active) && kdb_trap(frame->exc, 0, frame)) - return; +#if 0 + curcpu()->ci_ev_traps.ev_count++; #endif - panic("%s Trap", ppc_exception_names[frame->exc >> 8]); -} -/* - * Handles a fatal fault when we have onfault state to recover. Returns - * non-zero if there was onfault recovery state available. - */ -static int -handle_onfault (struct trapframe *frame) -{ - struct thread *td; - faultbuf *fb; - - td = curthread; - fb = td->td_pcb->pcb_onfault; - if (fb != NULL) { - frame->srr0 = (*fb)[0]; - frame->fixreg[1] = (*fb)[1]; - frame->fixreg[2] = (*fb)[2]; - frame->cr = (*fb)[3]; - bcopy(&(*fb)[4], &frame->fixreg[13], - 19 * sizeof(register_t)); - return (1); - } - return (0); -} + if (frame->srr1 & PSL_PR) + type |= EXC_USER; -void -trap(struct trapframe *frame) -{ - struct thread *td; - struct proc *p; - int sig, type, user; - u_int sticks, ucode; - - atomic_add_int(&cnt.v_trap, 1); - - td = curthread; - p = td->td_proc; - - type = frame->exc; - ucode = type; - sig = 0; - user = (frame->srr1 & PSL_PR); - sticks = 0; - - CTR3(KTR_TRAP, "trap: %s type=%s (%s)", p->p_comm, - ppc_exception_names[type >> 8], - user ? "user" : "kernel"); - - if (user) { - sticks = td->td_kse->ke_sticks; - td->td_frame = frame; - if (td->td_ucred != p->p_ucred) - cred_update_thread(td); - - /* User Mode Traps */ - switch (type) { - case EXC_TRC: - frame->srr1 &= ~PSL_SE; - sig = SIGTRAP; - break; - case EXC_DSI: - case EXC_ISI: - sig = trap_pfault(frame, 1); - break; - case EXC_SC: - syscall(frame); - break; - case EXC_FPU: - enable_fpu(PCPU_GET(curpcb)); - frame->srr1 |= PSL_FP; - break; +#ifdef DIAGNOSTIC + if (curpcb->pcb_pmreal != curpm) + panic("trap: curpm (%p) != curpcb->pcb_pmreal (%p)", + curpm, curpcb->pcb_pmreal); +#endif - case EXC_ALI: -#if 0 - if (fix_unaligned(p, frame) != 0) -#endif - sig = SIGBUS; -#if 0 - else - frame->srr0 += 4; -#endif +#if 0 + uvmexp.traps++; +#endif + + switch (type) { + case EXC_RUNMODETRC|EXC_USER: + /* FALLTHROUGH */ + case EXC_TRC|EXC_USER: + PROC_LOCK(p); + frame->srr1 &= ~PSL_SE; + trapsignal(p, SIGTRAP, EXC_TRC); + PROC_UNLOCK(p); break; + case EXC_DSI: { + faultbuf *fb; + /* + * Only query UVM if no interrupts are active (this applies + * "on-fault" as well. + */ +#if 0 + curcpu()->ci_ev_kdsi.ev_count++; +#endif + if (intr_depth < 0) { + struct vm_map *map; + vm_offset_t va; - case EXC_PGM: - /* XXX temporarily */ - /* XXX: Magic Number? */ - if (frame->srr1 & 0x0002000) - sig = SIGTRAP; +#if 0 + KERNEL_LOCK(LK_CANRECURSE|LK_EXCLUSIVE); +#endif + map = kernel_map; + va = frame->dar; + if ((va >> ADDR_SR_SHFT) == USER_SR) { + register_t user_sr; + + __asm ("mfsr %0, %1" + : "=r"(user_sr) : "K"(USER_SR)); + va &= ADDR_PIDX | ADDR_POFF; + va |= user_sr << ADDR_SR_SHFT; + /* KERNEL_PROC_LOCK(p); XXX */ + map = &p->p_vmspace->vm_map; + } + if (frame->dsisr & DSISR_STORE) + ftype = VM_PROT_WRITE; else - sig = SIGILL; - break; - - default: - trap_fatal(frame); - } - } else { - /* Kernel Mode Traps */ - - KASSERT(cold || td->td_ucred != NULL, - ("kernel trap doesn't have ucred")); - switch (type) { - case EXC_DSI: - if (trap_pfault(frame, 0) == 0) - return; - break; - case EXC_MCHK: - if (handle_onfault(frame)) + ftype = VM_PROT_READ; + rv = vm_fault(map, trunc_page(va), ftype, + VM_FAULT_NORMAL); +#if 0 + KERNEL_UNLOCK(); +#endif + if (rv == 0) return; - break; - default: - trap_fatal(frame); + if (rv == EACCES) + rv = EFAULT; + } else { + rv = EFAULT; } - /* NOTREACHED */ - } - if (sig != 0) { - if (p->p_sysent->sv_transtrap != NULL) - sig = (p->p_sysent->sv_transtrap)(sig, type); - trapsignal(p, sig, ucode); + if ((fb = td->td_pcb->pcb_onfault) != NULL) { + frame->srr0 = (*fb)[0]; + frame->fixreg[1] = (*fb)[1]; + frame->fixreg[2] = (*fb)[2]; + frame->fixreg[3] = rv; + frame->cr = (*fb)[3]; + memcpy(&frame->fixreg[13], &(*fb)[4], + 19 * sizeof(register_t)); + return; + } + printf("trap: kernel %s DSI @ %#x by %#x (DSISR %#x, err=%d)\n", + (frame->dsisr & DSISR_STORE) ? "write" : "read", + frame->dar, frame->srr0, frame->dsisr, rv); + goto brain_damage2; } - userret(td, frame, sticks); - mtx_assert(&Giant, MA_NOTOWNED); -#ifdef DIAGNOSTIC - cred_free_thread(td); + case EXC_DSI|EXC_USER: + PROC_LOCK(p); +#if 0 + curcpu()->ci_ev_udsi.ev_count++; #endif -} + if (frame->dsisr & DSISR_STORE) + ftype = VM_PROT_WRITE; + else + ftype = VM_PROT_READ; + rv = vm_fault(&p->p_vmspace->vm_map, trunc_page(frame->dar), + ftype, VM_FAULT_NORMAL); +#if 0 + curcpu()->ci_ev_udsi_fatal.ev_count++; +#endif + printf("trap: pid %d (%s): user %s DSI @ %#x " + "by %#x (DSISR %#x, err=%d)\n", + p->p_pid, p->p_comm, + (frame->dsisr & DSISR_STORE) ? "write" : "read", + frame->dar, frame->srr0, frame->dsisr, rv); + if (rv == ENOMEM) { + printf("UVM: pid %d (%s), uid %d killed: " + "out of swap\n", + p->p_pid, p->p_comm, + td->td_ucred ? td->td_ucred->cr_uid : -1); + trapsignal(p, SIGKILL, EXC_DSI); + } else { + trapsignal(p, SIGSEGV, EXC_DSI); + } + PROC_UNLOCK(p); + break; + case EXC_ISI: + printf("trap: kernel ISI by %#x (SRR1 %#x)\n", + frame->srr0, frame->srr1); + goto brain_damage2; + case EXC_ISI|EXC_USER: + PROC_LOCK(p); +#if 0 + curcpu()->ci_ev_isi.ev_count++; +#endif + ftype = VM_PROT_READ | VM_PROT_EXECUTE; + rv = vm_fault(&p->p_vmspace->vm_map, trunc_page(frame->srr0), + ftype, VM_FAULT_NORMAL); + printf("vm_fault said %d\n", rv); + if (rv == 0) { + PROC_UNLOCK(p); + break; + } +#if 0 + curcpu()->ci_ev_isi_fatal.ev_count++; +#endif + printf("trap: pid %d (%s): user ISI trap @ %#x " + "(SSR1=%#x)\n", + p->p_pid, p->p_comm, frame->srr0, frame->srr1); + trapsignal(p, SIGSEGV, EXC_ISI); + PROC_UNLOCK(p); + break; + case EXC_SC|EXC_USER: +#if 0 + curcpu()->ci_ev_scalls.ev_count++; +#endif + { + const struct sysent *callp; + size_t argsize; + register_t code, error; + register_t *params, rval[2]; + int n; + register_t args[10]; -void -syscall(struct trapframe *frame) -{ - caddr_t params; - struct sysent *callp; - struct thread *td; - struct proc *p; - int error, n; - size_t narg; - register_t args[10]; - u_int code; - - td = curthread; - p = td->td_proc; - - atomic_add_int(&cnt.v_syscall, 1); - - code = frame->fixreg[0]; - params = (caddr_t) (frame->fixreg + FIRSTARG); - - if (p->p_sysent->sv_prepsyscall) - /* - * The prep code is MP aware. - */ - (*p->p_sysent->sv_prepsyscall)(frame, args, &code, ¶ms); - else if (code == SYS_syscall) - /* - * code is first argument, - * followed by actual args. - */ - code = *params++; - else if (code == SYS___syscall) { - /* - * Like syscall, but code is a quad, - * so as to maintain quad alignment - * for the rest of the args. - */ - params++; - code = *params++; - } + PROC_LOCK(p); - if (p->p_sysent->sv_mask) - code &= p->p_sysent->sv_mask; +#if 0 + uvmexp.syscalls++; +#endif - if (code >= p->p_sysent->sv_size) - callp = &p->p_sysent->sv_table[0]; - else - callp = &p->p_sysent->sv_table[code]; + code = frame->fixreg[0]; + callp = &p->p_sysent->sv_table[0]; + params = frame->fixreg + FIRSTARG; + n = NARGREG; + + switch (code) { + case SYS_syscall: + /* + * code is first argument, + * followed by actual args. + */ + code = *params++; + n -= 1; + break; + case SYS___syscall: + params++; + code = *params++; + n -= 2; + break; + default: + break; + } - narg = callp->sy_narg & SYF_ARGMASK; + if (p->p_sysent->sv_mask) + code &= p->p_sysent->sv_mask; + callp += code; + argsize = callp->sy_narg & SYF_ARGMASK; + + if (argsize > n * sizeof(register_t)) { + memcpy(args, params, n * sizeof(register_t)); + error = copyin(MOREARGS(frame->fixreg[1]), + args + n, + argsize - n * sizeof(register_t)); + if (error) + goto syscall_bad; + params = args; + } - n = NARGREG - (params - (caddr_t)(frame->fixreg + FIRSTARG)); - if (narg > n * sizeof(register_t)) { - bcopy(params, args, n * sizeof(register_t)); - if (error = copyin(MOREARGS(frame->fixreg[1]), args + n, - narg - n * sizeof(register_t))) { #ifdef KTRACE - /* Can't get all the arguments! */ if (KTRPOINT(p, KTR_SYSCALL)) - ktrsyscall(p->p_tracep, code, narg, args); + ktrsyscall(p, code, argsize, params); #endif - goto bad; - } - params = (caddr_t) args; - } - /* - * Try to run the syscall without Giant if the syscall is MP safe. - */ - if ((callp->sy_narg & SYF_MPSAFE) == 0) - mtx_lock(&Giant); + rval[0] = 0; + rval[1] = 0; + + error = (*callp->sy_call)(td, params); + switch (error) { + case 0: + frame->fixreg[FIRSTARG] = rval[0]; + frame->fixreg[FIRSTARG + 1] = rval[1]; + frame->cr &= ~0x10000000; + break; + case ERESTART: + /* + * Set user's pc back to redo the system call. + */ + frame->srr0 -= 4; + break; + case EJUSTRETURN: + /* nothing to do */ + break; + default: +syscall_bad: +#if 0 + if (p->p_emul->e_errno) + error = p->p_emul->e_errno[error]; +#endif + frame->fixreg[FIRSTARG] = error; + frame->cr |= 0x10000000; + break; + } #ifdef KTRACE - if (KTRPOINT(p, KTR_SYSCALL)) - ktrsyscall(p->p_tracep, code, narg, params); + if (KTRPOINT(p, KTR_SYSRET)) + ktrsysret(p, code, error, rval[0]); #endif - td->td_retval[0] = 0; - td->td_retval[1] = frame->fixreg[FIRSTARG + 1]; - - STOPEVENT(p, S_SCE, narg); - - error = (*callp->sy_call)(td, args); - switch (error) { - case 0: - frame->fixreg[FIRSTARG] = td->td_retval[0]; - frame->fixreg[FIRSTARG + 1] = td->td_retval[1]; - /* XXX: Magic number */ - frame->cr &= ~0x10000000; - break; - case ERESTART: - /* - * Set user's pc back to redo the system call. - */ - frame->srr0 -= 4; - break; - case EJUSTRETURN: - /* nothing to do */ - break; - default: -bad: - if (p->p_sysent->sv_errsize) { - if (error >= p->p_sysent->sv_errsize) - error = -1; /* XXX */ - else - error = p->p_sysent->sv_errtbl[error]; } - frame->fixreg[FIRSTARG] = error; - /* XXX: Magic number: Carry Flag Equivalent? */ - frame->cr |= 0x10000000; + PROC_UNLOCK(p); break; - } - -#ifdef KTRACE - if (KTRPOINT(p, KTR_SYSRET)) - ktrsysret(p->p_tracep, code, error, td->td_retval[0]); + case EXC_FPU|EXC_USER: +#if 0 + curcpu()->ci_ev_fpu.ev_count++; #endif +#if 0 + if (fpuproc) { + curcpu()->ci_ev_fpusw.ev_count++; + save_fpu(fpuproc); + } +#endif +#if defined(MULTIPROCESSOR) + if (p->p_addr->u_pcb.pcb_fpcpu) + save_fpu_proc(p); +#endif +#if 0 + fpuproc = p; + p->p_addr->u_pcb.pcb_fpcpu = curcpu(); + enable_fpu(p); +#endif + break; - if ((callp->sy_narg & SYF_MPSAFE) == 0) - mtx_unlock(&Giant); - - /* - * Does the comment in the i386 code about errno apply here? - */ - STOPEVENT(p, S_SCX, code); +#ifdef ALTIVEC + case EXC_VEC|EXC_USER: +#if 0 + curcpu()->ci_ev_vec.ev_count++; +#endif + if (vecproc) { +#if 0 + curcpu()->ci_ev_vecsw.ev_count++; +#endif + save_vec(vecproc); + } + vecproc = p; + enable_vec(p); + break; +#endif -#ifdef WITNESS - if (witness_list(td)) { - panic("system call %s returning with mutex(s) held\n", - syscallnames[code]); - } + case EXC_AST|EXC_USER: + astpending = 0; /* we are about to do it */ + PROC_LOCK(p); +#if 0 + uvmexp.softs++; + if (p->p_flag & P_OWEUPC) { + p->p_flag &= ~P_OWEUPC; + ADDUPROF(p); + } #endif - mtx_assert(&sched_lock, MA_NOTOWNED); - mtx_assert(&Giant, MA_NOTOWNED); -} + /* Check whether we are being preempted. */ + if (want_resched) + mi_switch(); + PROC_UNLOCK(p); + break; -static int -trap_pfault(struct trapframe *frame, int user) -{ - vm_offset_t eva, va; - struct thread *td; - struct proc *p; - vm_map_t map; - vm_prot_t ftype; - int rv; + case EXC_ALI|EXC_USER: + PROC_LOCK(p); +#if 0 + curcpu()->ci_ev_ali.ev_count++; +#endif + if (fix_unaligned(p, frame) != 0) { +#if 0 + curcpu()->ci_ev_ali_fatal.ev_count++; +#endif + printf("trap: pid %d (%s): user ALI trap @ %#x " + "(SSR1=%#x)\n", + p->p_pid, p->p_comm, frame->srr0, + frame->srr1); + trapsignal(p, SIGBUS, EXC_ALI); + } else + frame->srr0 += 4; + PROC_UNLOCK(p); + break; - td = curthread; - p = td->td_proc; - if (frame->exc == EXC_ISI) { - eva = frame->srr0; - ftype = VM_PROT_READ | VM_PROT_EXECUTE; - } else { - eva = frame->dar; - if (frame->dsisr & DSISR_STORE) - ftype = VM_PROT_READ | VM_PROT_WRITE; + case EXC_PGM|EXC_USER: +/* XXX temporarily */ + PROC_LOCK(p); +#if 0 + curcpu()->ci_ev_pgm.ev_count++; +#endif + printf("trap: pid %d (%s): user PGM trap @ %#x " + "(SSR1=%#x)\n", + p->p_pid, p->p_comm, frame->srr0, frame->srr1); + if (frame->srr1 & 0x00020000) /* Bit 14 is set if trap */ + trapsignal(p, SIGTRAP, EXC_PGM); else - ftype = VM_PROT_READ; - } + trapsignal(p, SIGILL, EXC_PGM); + PROC_UNLOCK(p); + break; - if ((eva >> ADDR_SR_SHFT) != USER_SR) { - if (user) - return (SIGSEGV); - map = kernel_map; - } else { - u_int user_sr; - - if (p->p_vmspace == NULL) - return (SIGSEGV); - - __asm ("mfsr %0, %1" - : "=r"(user_sr) - : "K"(USER_SR)); - eva &= ADDR_PIDX | ADDR_POFF; - eva |= user_sr << ADDR_SR_SHFT; - map = &p->p_vmspace->vm_map; + case EXC_MCHK: { + faultbuf *fb; + + if ((fb = td->td_pcb->pcb_onfault) != NULL) { + frame->srr0 = (*fb)[0]; + frame->fixreg[1] = (*fb)[1]; + frame->fixreg[2] = (*fb)[2]; + frame->fixreg[3] = EFAULT; + frame->cr = (*fb)[3]; + memcpy(&frame->fixreg[13], &(*fb)[4], + 19 * sizeof(register_t)); + return; + } + goto brain_damage; } - va = trunc_page(eva); - if (map != kernel_map) { - /* - * Keep swapout from messing with us during this - * critical time. - */ - PROC_LOCK(p); - ++p->p_lock; - PROC_UNLOCK(p); + default: +brain_damage: + printf("trap type %x at %x\n", type, frame->srr0); +brain_damage2: +#ifdef DDBX + if (kdb_trap(type, frame)) + return; +#endif +#ifdef TRAP_PANICWAIT + printf("Press a key to panic.\n"); + cnpollc(1); + cngetc(); + cnpollc(0); +#endif + panic("trap"); + } - /* Fault in the user page: */ - rv = vm_fault(map, va, ftype, - (ftype & VM_PROT_WRITE) ? VM_FAULT_DIRTY - : VM_FAULT_NORMAL); + /* Take pending signals. */ + { + int sig; - PROC_LOCK(p); - --p->p_lock; - PROC_UNLOCK(p); - } else { - /* - * Don't have to worry about process locking or stacks in the - * kernel. - */ - rv = vm_fault(map, va, ftype, VM_FAULT_NORMAL); + while ((sig = CURSIG(p)) != 0) + postsig(sig); } - if (rv == KERN_SUCCESS) - return (0); - if (!user && handle_onfault(frame)) - return (0); + /* + * If someone stole the fp or vector unit while we were away, + * disable it + */ +#if 0 + if (p != fpuproc || p->p_addr->u_pcb.pcb_fpcpu != curcpu()) + frame->srr1 &= ~PSL_FP; +#endif +#ifdef ALTIVEC + if (p != vecproc) + frame->srr1 &= ~PSL_VEC; +#endif - return (SIGSEGV); +#if 0 + curcpu()->ci_schedstate.spc_curpriority = p->p_priority = p->p_usrpri; + p->p_priority = p->p_usrpri; +#endif } -#if 0 /* XXX: child_return not used */ -/* - * XXX: the trapframe return values should be setup in vm_machdep.c in - * cpu_fork(). - */ +void child_return(void *); + void child_return(void *arg) { - struct proc *p; - struct trapframe *tf; + struct thread *td = arg; + struct proc *p = td->td_proc; + struct trapframe *tf = trapframe(td); - p = arg; - tf = trapframe(p); + PROC_UNLOCK(p); tf->fixreg[FIRSTARG] = 0; tf->fixreg[FIRSTARG + 1] = 1; tf->cr &= ~0x10000000; - tf->srr1 &= ~PSL_FP; /* Disable FPU, as we can't be fpuproc */ +#if 0 + tf->srr1 &= ~(PSL_FP|PSL_VEC); /* Disable FP & AltiVec, as we can't + be them. */ + td->td_pcb->pcb_fpcpu = NULL; +#endif #ifdef KTRACE - if (KTRPOINT(p, KTR_SYSRET)) + if (KTRPOINT(p, KTR_SYSRET)) { + PROC_LOCK(p); ktrsysret(p, SYS_fork, 0, 0); + PROC_UNLOCK(p); + } #endif /* Profiling? XXX */ +#if 0 curcpu()->ci_schedstate.spc_curpriority = p->p_priority; -} #endif +} + +static __inline void +setusr(content) + int content; +{ + __asm __volatile ("isync; mtsr %0,%1; isync" + :: "n"(USER_SR), "r"(content)); +} + +int kcopy(const void *, void *, size_t); -#if 0 /* XXX: not used yet */ /* * kcopy(const void *src, void *dst, size_t len); * @@ -553,38 +546,48 @@ child_return(void *arg) int kcopy(const void *src, void *dst, size_t len) { + struct thread *td; faultbuf env, *oldfault; + int rv; - oldfault = PCPU_GET(curpcb)->pcb_onfault; - if (setfault(env)) { - PCPU_GET(curpcb)->pcb_onfault = oldfault; - return EFAULT; + td = PCPU_GET(curthread); + oldfault = td->td_pcb->pcb_onfault; + if ((rv = setfault(env)) != 0) { + td->td_pcb->pcb_onfault = oldfault; + return rv; } - bcopy(src, dst, len); + memcpy(dst, src, len); - PCPU_GET(curpcb)->pcb_onfault = oldfault; + td->td_pcb->pcb_onfault = oldfault; return 0; } int -badaddr(void *addr, size_t size) +badaddr(addr, size) + void *addr; + size_t size; { - return badaddr_read(addr, size, NULL); } int -badaddr_read(void *addr, size_t size, int *rptr) +badaddr_read(addr, size, rptr) + void *addr; + size_t size; + int *rptr; { + struct thread *td; faultbuf env; int x; /* Get rid of any stale machine checks that have been waiting. */ __asm __volatile ("sync; isync"); + td = PCPU_GET(curthread); + if (setfault(env)) { - PCPU_GET(curpcb)->pcb_onfault = 0; + td->td_pcb->pcb_onfault = 0; __asm __volatile ("sync"); return 1; } @@ -608,7 +611,7 @@ badaddr_read(void *addr, size_t size, int *rptr) /* Make sure we took the machine check, if we caused one. */ __asm __volatile ("sync; isync"); - PCPU_GET(curpcb)->pcb_onfault = 0; + td->td_pcb->pcb_onfault = 0; __asm __volatile ("sync"); /* To be sure. */ /* Use the value to avoid reorder. */ @@ -617,7 +620,6 @@ badaddr_read(void *addr, size_t size, int *rptr) return 0; } -#endif /* * For now, this only deals with the particular unaligned access case @@ -625,19 +627,17 @@ badaddr_read(void *addr, size_t size, int *rptr) * possibilities that can happen on a 32-bit PowerPC in big-endian mode. */ -#if 0 /* XXX: Not used yet */ static int fix_unaligned(p, frame) struct proc *p; struct trapframe *frame; { - int indicator; - - indicator = EXC_ALI_OPCODE_INDICATOR(frame->dsisr); + int indicator = EXC_ALI_OPCODE_INDICATOR(frame->dsisr); switch (indicator) { case EXC_ALI_LFD: case EXC_ALI_STFD: +#if 0 { int reg = EXC_ALI_RST(frame->dsisr); double *fpr = &p->p_addr->u_pcb.pcb_fpu.fpr[reg]; @@ -646,20 +646,18 @@ fix_unaligned(p, frame) * the FPRs, and that their current state is in * the PCB. */ - if (!(pcb->pcb_flags & PCB_FPU)) - enable_fpu(PCPU_GET(curpcb)); - frame->srr1 |= PSL_FP; + if (fpuproc != p) { + if (fpuproc) + save_fpu(fpuproc); + enable_fpu(p); } - save_fpu(PCPU_GET(curpcb)); + save_fpu(p); if (indicator == EXC_ALI_LFD) { if (copyin((void *)frame->dar, fpr, sizeof(double)) != 0) return -1; - if (!(pcb->pcb_flags & PCB_FPU)) - enable_fpu(PCPU_GET(curpcb)); - frame->srr1 |= PSL_FP; - } + enable_fpu(p); } else { if (copyout(fpr, (void *)frame->dar, sizeof(double)) != 0) @@ -667,9 +665,9 @@ fix_unaligned(p, frame) } return 0; } +#endif break; } return -1; } -#endif -- cgit v1.1