summaryrefslogtreecommitdiffstats
path: root/sys/powerpc/powerpc
diff options
context:
space:
mode:
authorbenno <benno@FreeBSD.org>2002-05-09 14:22:55 +0000
committerbenno <benno@FreeBSD.org>2002-05-09 14:22:55 +0000
commit4a3201751221d4cec666d9a552eb7275b918c0d7 (patch)
tree5f13751757172e742cc1755cc5cebc76c0ef962b /sys/powerpc/powerpc
parentb25a35b1f3854a215fb2a310ba14c0dbc2922264 (diff)
downloadFreeBSD-src-4a3201751221d4cec666d9a552eb7275b918c0d7.zip
FreeBSD-src-4a3201751221d4cec666d9a552eb7275b918c0d7.tar.gz
Update to newer trap code from NetBSD.
Obtained from: NetBSD
Diffstat (limited to 'sys/powerpc/powerpc')
-rw-r--r--sys/powerpc/powerpc/trap.c868
1 files changed, 433 insertions, 435 deletions
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 <sys/param.h>
-#include <sys/proc.h>
-#include <sys/ktr.h>
#include <sys/lock.h>
#include <sys/mutex.h>
-#include <sys/pioctl.h>
+#include <sys/proc.h>
#include <sys/reboot.h>
#include <sys/syscall.h>
-#include <sys/sysent.h>
#include <sys/systm.h>
-#include <sys/uio.h>
+#include <sys/sysent.h>
#include <sys/user.h>
#ifdef KTRACE
+#include <sys/uio.h>
#include <sys/ktrace.h>
#endif
-#include <sys/vmmeter.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <vm/vm_extern.h>
+#include <vm/vm_param.h>
#include <vm/vm_kern.h>
#include <vm/vm_map.h>
-#include <vm/vm_param.h>
+#include <vm/vm_page.h>
#include <machine/cpu.h>
+#include <machine/db_machdep.h>
+#include <machine/fpu.h>
#include <machine/frame.h>
#include <machine/pcb.h>
+#include <machine/pmap.h>
#include <machine/psl.h>
#include <machine/trap.h>
+#include <machine/spr.h>
+#include <machine/sr.h>
-/* 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, &params);
- 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
OpenPOWER on IntegriCloud