Annotation of sys/arch/powerpc/powerpc/trap.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: trap.c,v 1.78 2007/04/26 21:36:32 kettenis Exp $ */
! 2: /* $NetBSD: trap.c,v 1.3 1996/10/13 03:31:37 christos Exp $ */
! 3:
! 4: /*
! 5: * Copyright (C) 1995, 1996 Wolfgang Solfrank.
! 6: * Copyright (C) 1995, 1996 TooLs GmbH.
! 7: * All rights reserved.
! 8: *
! 9: * Redistribution and use in source and binary forms, with or without
! 10: * modification, are permitted provided that the following conditions
! 11: * are met:
! 12: * 1. Redistributions of source code must retain the above copyright
! 13: * notice, this list of conditions and the following disclaimer.
! 14: * 2. Redistributions in binary form must reproduce the above copyright
! 15: * notice, this list of conditions and the following disclaimer in the
! 16: * documentation and/or other materials provided with the distribution.
! 17: * 3. All advertising materials mentioning features or use of this software
! 18: * must display the following acknowledgement:
! 19: * This product includes software developed by TooLs GmbH.
! 20: * 4. The name of TooLs GmbH may not be used to endorse or promote products
! 21: * derived from this software without specific prior written permission.
! 22: *
! 23: * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
! 24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 25: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 26: * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
! 27: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
! 28: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
! 29: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
! 30: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
! 31: * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
! 32: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 33: */
! 34: #include <sys/param.h>
! 35: #include <sys/proc.h>
! 36: #include <sys/signalvar.h>
! 37: #include <sys/reboot.h>
! 38: #include <sys/syscall.h>
! 39: #include <sys/systm.h>
! 40: #include <sys/user.h>
! 41: #include <sys/ktrace.h>
! 42: #include <sys/pool.h>
! 43:
! 44: #include <dev/cons.h>
! 45:
! 46: #include <machine/cpu.h>
! 47: #include <machine/fpu.h>
! 48: #include <machine/frame.h>
! 49: #include <machine/pcb.h>
! 50: #include <machine/pmap.h>
! 51: #include <machine/psl.h>
! 52: #include <machine/trap.h>
! 53: #include <machine/db_machdep.h>
! 54:
! 55: #include "systrace.h"
! 56: #include <dev/systrace.h>
! 57:
! 58: #include <uvm/uvm_extern.h>
! 59:
! 60: #include <ddb/db_extern.h>
! 61: #include <ddb/db_sym.h>
! 62: #include <ddb/db_output.h>
! 63:
! 64: static int fix_unaligned(struct proc *p, struct trapframe *frame);
! 65: int badaddr(char *addr, u_int32_t len);
! 66: static __inline void userret(struct proc *);
! 67: void trap(struct trapframe *frame);
! 68:
! 69: /* These definitions should probably be somewhere else XXX */
! 70: #define FIRSTARG 3 /* first argument is in reg 3 */
! 71: #define NARGREG 8 /* 8 args are in registers */
! 72: #define MOREARGS(sp) ((caddr_t)((int)(sp) + 8)) /* more args go here */
! 73:
! 74: #ifdef DDB
! 75: void ppc_dumpbt(struct trapframe *frame);
! 76:
! 77: void
! 78: ppc_dumpbt(struct trapframe *frame)
! 79: {
! 80: u_int32_t addr;
! 81: /* dumpframe is defined in db_trace.c */
! 82: addr=frame->fixreg[1];
! 83: while (addr != 0)
! 84: addr = db_dumpframe(addr, db_printf);
! 85: return;
! 86: }
! 87: #endif
! 88:
! 89: #ifdef ALTIVEC
! 90: /*
! 91: * Save state of the vector processor, This is done lazily in the hope
! 92: * that few processes in the system will be using the vector unit
! 93: * and that the exception time taken to switch them will be less than
! 94: * the necessary time to save the vector on every context switch.
! 95: *
! 96: * Also note that in this version, the VRSAVE register is saved with
! 97: * the state of the current process holding the vector processor,
! 98: * and the contents of that register are not used to optimize the save.
! 99: *
! 100: * This can lead to VRSAVE corruption, data passing between processes,
! 101: * because this register is accessable without the MSR[VEC] bit set.
! 102: * To store/restore this cleanly a processor identifier bit would need
! 103: * to be saved and this register saved on every context switch.
! 104: * Since we do not use the information, we may be able to get by
! 105: * with not saving it rigorously.
! 106: */
! 107: void
! 108: save_vec(struct proc *p)
! 109: {
! 110: struct pcb *pcb = &p->p_addr->u_pcb;
! 111: struct vreg *pcb_vr = pcb->pcb_vr;
! 112: u_int32_t oldmsr, msr;
! 113:
! 114: if (p == NULL)
! 115: return;
! 116:
! 117: /* first we enable vector so that we dont throw an exception
! 118: * in kernel mode
! 119: */
! 120: oldmsr = ppc_mfmsr();
! 121: msr = oldmsr | PSL_VEC;
! 122: ppc_mtmsr(msr);
! 123: __asm__ volatile ("sync;isync");
! 124:
! 125: pcb->pcb_vr->vrsave = ppc_mfvrsave();
! 126:
! 127: #define STR(x) #x
! 128: #define SAVE_VEC_REG(reg, addr) \
! 129: __asm__ volatile ("stvxl %0, 0, %1" :: "n"(reg),"r" (addr));
! 130:
! 131: SAVE_VEC_REG(0,&pcb_vr->vreg[0]);
! 132: SAVE_VEC_REG(1,&pcb_vr->vreg[1]);
! 133: SAVE_VEC_REG(2,&pcb_vr->vreg[2]);
! 134: SAVE_VEC_REG(3,&pcb_vr->vreg[3]);
! 135: SAVE_VEC_REG(4,&pcb_vr->vreg[4]);
! 136: SAVE_VEC_REG(5,&pcb_vr->vreg[5]);
! 137: SAVE_VEC_REG(6,&pcb_vr->vreg[6]);
! 138: SAVE_VEC_REG(7,&pcb_vr->vreg[7]);
! 139: SAVE_VEC_REG(8,&pcb_vr->vreg[8]);
! 140: SAVE_VEC_REG(9,&pcb_vr->vreg[9]);
! 141: SAVE_VEC_REG(10,&pcb_vr->vreg[10]);
! 142: SAVE_VEC_REG(11,&pcb_vr->vreg[11]);
! 143: SAVE_VEC_REG(12,&pcb_vr->vreg[12]);
! 144: SAVE_VEC_REG(13,&pcb_vr->vreg[13]);
! 145: SAVE_VEC_REG(14,&pcb_vr->vreg[14]);
! 146: SAVE_VEC_REG(15,&pcb_vr->vreg[15]);
! 147: SAVE_VEC_REG(16,&pcb_vr->vreg[16]);
! 148: SAVE_VEC_REG(17,&pcb_vr->vreg[17]);
! 149: SAVE_VEC_REG(18,&pcb_vr->vreg[18]);
! 150: SAVE_VEC_REG(19,&pcb_vr->vreg[19]);
! 151: SAVE_VEC_REG(20,&pcb_vr->vreg[20]);
! 152: SAVE_VEC_REG(21,&pcb_vr->vreg[21]);
! 153: SAVE_VEC_REG(22,&pcb_vr->vreg[22]);
! 154: SAVE_VEC_REG(23,&pcb_vr->vreg[23]);
! 155: SAVE_VEC_REG(24,&pcb_vr->vreg[24]);
! 156: SAVE_VEC_REG(25,&pcb_vr->vreg[25]);
! 157: SAVE_VEC_REG(26,&pcb_vr->vreg[26]);
! 158: SAVE_VEC_REG(27,&pcb_vr->vreg[27]);
! 159: SAVE_VEC_REG(28,&pcb_vr->vreg[28]);
! 160: SAVE_VEC_REG(29,&pcb_vr->vreg[29]);
! 161: SAVE_VEC_REG(30,&pcb_vr->vreg[30]);
! 162: SAVE_VEC_REG(31,&pcb_vr->vreg[31]);
! 163: __asm__ volatile ("mfvscr 0");
! 164: SAVE_VEC_REG(0,&pcb_vr->vscr);
! 165:
! 166: /* fix kernel msr back */
! 167: ppc_mtmsr(oldmsr);
! 168: }
! 169:
! 170: /*
! 171: * Copy the context of a given process into the vector registers.
! 172: */
! 173: void
! 174: enable_vec(struct proc *p)
! 175: {
! 176: struct pcb *pcb = &p->p_addr->u_pcb;
! 177: struct vreg *pcb_vr = pcb->pcb_vr;
! 178: u_int32_t oldmsr, msr;
! 179:
! 180: /* If this is the very first altivec instruction executed
! 181: * by this process, create a context.
! 182: */
! 183: if (pcb->pcb_vr == NULL) {
! 184: pcb->pcb_vr = pool_get(&ppc_vecpl, PR_WAITOK);
! 185: bzero(pcb->pcb_vr, sizeof *(pcb->pcb_vr));
! 186: }
! 187:
! 188: /* first we enable vector so that we dont throw an exception
! 189: * in kernel mode
! 190: */
! 191: oldmsr = ppc_mfmsr();
! 192: msr = oldmsr | PSL_VEC;
! 193: ppc_mtmsr(msr);
! 194: __asm__ volatile ("sync;isync");
! 195:
! 196: #define LOAD_VEC_REG(reg, addr) \
! 197: __asm__ volatile ("lvxl %0, 0, %1" :: "n"(reg), "r" (addr));
! 198:
! 199: LOAD_VEC_REG(0, &pcb_vr->vscr);
! 200: __asm__ volatile ("mtvscr 0");
! 201: ppc_mtvrsave(pcb_vr->vrsave);
! 202:
! 203: LOAD_VEC_REG(0, &pcb_vr->vreg[0]);
! 204: LOAD_VEC_REG(1, &pcb_vr->vreg[1]);
! 205: LOAD_VEC_REG(2, &pcb_vr->vreg[2]);
! 206: LOAD_VEC_REG(3, &pcb_vr->vreg[3]);
! 207: LOAD_VEC_REG(4, &pcb_vr->vreg[4]);
! 208: LOAD_VEC_REG(5, &pcb_vr->vreg[5]);
! 209: LOAD_VEC_REG(6, &pcb_vr->vreg[6]);
! 210: LOAD_VEC_REG(7, &pcb_vr->vreg[7]);
! 211: LOAD_VEC_REG(8, &pcb_vr->vreg[8]);
! 212: LOAD_VEC_REG(9, &pcb_vr->vreg[9]);
! 213: LOAD_VEC_REG(10, &pcb_vr->vreg[10]);
! 214: LOAD_VEC_REG(11, &pcb_vr->vreg[11]);
! 215: LOAD_VEC_REG(12, &pcb_vr->vreg[12]);
! 216: LOAD_VEC_REG(13, &pcb_vr->vreg[13]);
! 217: LOAD_VEC_REG(14, &pcb_vr->vreg[14]);
! 218: LOAD_VEC_REG(15, &pcb_vr->vreg[15]);
! 219: LOAD_VEC_REG(16, &pcb_vr->vreg[16]);
! 220: LOAD_VEC_REG(17, &pcb_vr->vreg[17]);
! 221: LOAD_VEC_REG(18, &pcb_vr->vreg[18]);
! 222: LOAD_VEC_REG(19, &pcb_vr->vreg[19]);
! 223: LOAD_VEC_REG(20, &pcb_vr->vreg[20]);
! 224: LOAD_VEC_REG(21, &pcb_vr->vreg[21]);
! 225: LOAD_VEC_REG(22, &pcb_vr->vreg[22]);
! 226: LOAD_VEC_REG(23, &pcb_vr->vreg[23]);
! 227: LOAD_VEC_REG(24, &pcb_vr->vreg[24]);
! 228: LOAD_VEC_REG(25, &pcb_vr->vreg[25]);
! 229: LOAD_VEC_REG(26, &pcb_vr->vreg[26]);
! 230: LOAD_VEC_REG(27, &pcb_vr->vreg[27]);
! 231: LOAD_VEC_REG(28, &pcb_vr->vreg[28]);
! 232: LOAD_VEC_REG(29, &pcb_vr->vreg[29]);
! 233: LOAD_VEC_REG(30, &pcb_vr->vreg[30]);
! 234: LOAD_VEC_REG(31, &pcb_vr->vreg[31]);
! 235:
! 236: /* fix kernel msr back */
! 237: ppc_mtmsr(oldmsr);
! 238: }
! 239: #endif /* ALTIVEC */
! 240:
! 241: static __inline void
! 242: userret(struct proc *p)
! 243: {
! 244: int sig;
! 245:
! 246: /* take pending signals */
! 247: while ((sig = CURSIG(p)) != 0)
! 248: postsig(sig);
! 249: curcpu()->ci_schedstate.spc_curpriority = p->p_priority;
! 250: }
! 251:
! 252: void
! 253: trap(struct trapframe *frame)
! 254: {
! 255: struct cpu_info *ci = curcpu();
! 256: struct proc *p = curproc;
! 257: int type = frame->exc;
! 258: union sigval sv;
! 259: char *name;
! 260: db_expr_t offset;
! 261:
! 262: if (frame->srr1 & PSL_PR) {
! 263: type |= EXC_USER;
! 264: }
! 265:
! 266: switch (type) {
! 267: case EXC_TRC|EXC_USER:
! 268: {
! 269: sv.sival_int = frame->srr0;
! 270: KERNEL_PROC_LOCK(p);
! 271: trapsignal(p, SIGTRAP, type, TRAP_TRACE, sv);
! 272: KERNEL_PROC_UNLOCK(p);
! 273: }
! 274: break;
! 275:
! 276: case EXC_MCHK:
! 277: {
! 278: faultbuf *fb;
! 279:
! 280: if ((fb = p->p_addr->u_pcb.pcb_onfault)) {
! 281: p->p_addr->u_pcb.pcb_onfault = 0;
! 282: frame->srr0 = fb->pc; /* PC */
! 283: frame->srr1 = fb->sr; /* SR */
! 284: frame->fixreg[1] = fb->sp; /* SP */
! 285: frame->fixreg[3] = 1; /* != 0 */
! 286: frame->cr = fb->cr;
! 287: bcopy(&fb->regs[0], &frame->fixreg[13], 19*4);
! 288: return;
! 289: }
! 290: }
! 291: goto brain_damage;
! 292:
! 293: case EXC_DSI:
! 294: {
! 295: struct vm_map *map;
! 296: vaddr_t va;
! 297: int ftype;
! 298: faultbuf *fb;
! 299:
! 300: map = kernel_map;
! 301: va = frame->dar;
! 302: if ((va >> ADDR_SR_SHIFT) == PPC_USER_SR) {
! 303: sr_t user_sr;
! 304:
! 305: asm ("mfsr %0, %1"
! 306: : "=r"(user_sr) : "K"(PPC_USER_SR));
! 307: va &= ADDR_PIDX | ADDR_POFF;
! 308: va |= user_sr << ADDR_SR_SHIFT;
! 309: map = &p->p_vmspace->vm_map;
! 310: if (pte_spill_v(map->pmap, va, frame->dsisr, 0))
! 311: return;
! 312: }
! 313: if (frame->dsisr & DSISR_STORE)
! 314: ftype = VM_PROT_READ | VM_PROT_WRITE;
! 315: else
! 316: ftype = VM_PROT_READ;
! 317: if (uvm_fault(map, trunc_page(va), 0, ftype) == 0)
! 318: return;
! 319:
! 320: if ((fb = p->p_addr->u_pcb.pcb_onfault)) {
! 321: p->p_addr->u_pcb.pcb_onfault = 0;
! 322: frame->srr0 = fb->pc; /* PC */
! 323: frame->fixreg[1] = fb->sp; /* SP */
! 324: frame->fixreg[3] = 1; /* != 0 */
! 325: frame->cr = fb->cr;
! 326: bcopy(&fb->regs[0], &frame->fixreg[13], 19*4);
! 327: return;
! 328: }
! 329: map = kernel_map;
! 330: }
! 331: printf("kern dsi on addr %x iar %x\n", frame->dar, frame->srr0);
! 332: goto brain_damage;
! 333: case EXC_DSI|EXC_USER:
! 334: {
! 335: int ftype, vftype;
! 336:
! 337: /* Try spill handler first */
! 338: if (pte_spill_v(p->p_vmspace->vm_map.pmap,
! 339: frame->dar, frame->dsisr, 0))
! 340: break;
! 341:
! 342: KERNEL_PROC_LOCK(p);
! 343: if (frame->dsisr & DSISR_STORE) {
! 344: ftype = VM_PROT_READ | VM_PROT_WRITE;
! 345: vftype = VM_PROT_WRITE;
! 346: } else
! 347: vftype = ftype = VM_PROT_READ;
! 348: if (uvm_fault(&p->p_vmspace->vm_map,
! 349: trunc_page(frame->dar), 0, ftype) == 0) {
! 350: uvm_grow(p, trunc_page(frame->dar));
! 351: KERNEL_PROC_UNLOCK(p);
! 352: break;
! 353: }
! 354:
! 355: #if 0
! 356: printf("dsi on addr %x iar %x lr %x\n", frame->dar, frame->srr0,frame->lr);
! 357: #endif
! 358: /*
! 359: * keep this for later in case we want it later.
! 360: */
! 361: sv.sival_int = frame->dar;
! 362: trapsignal(p, SIGSEGV, vftype, SEGV_MAPERR, sv);
! 363: KERNEL_PROC_UNLOCK(p);
! 364: }
! 365: break;
! 366: case EXC_ISI|EXC_USER:
! 367: {
! 368: int ftype;
! 369:
! 370: /* Try spill handler */
! 371: if (pte_spill_v(p->p_vmspace->vm_map.pmap,
! 372: frame->srr0, 0, 1))
! 373: break;
! 374:
! 375: KERNEL_PROC_LOCK(p);
! 376: ftype = VM_PROT_READ | VM_PROT_EXECUTE;
! 377: if (uvm_fault(&p->p_vmspace->vm_map,
! 378: trunc_page(frame->srr0), 0, ftype) == 0) {
! 379: uvm_grow(p, trunc_page(frame->srr0));
! 380: KERNEL_PROC_UNLOCK(p);
! 381: break;
! 382: }
! 383: KERNEL_PROC_UNLOCK(p);
! 384: }
! 385: #if 0
! 386: printf("isi iar %x lr %x\n", frame->srr0, frame->lr);
! 387: #endif
! 388: /* FALLTHROUGH */
! 389: case EXC_MCHK|EXC_USER:
! 390: /* XXX Likely that returning from this trap is bogus... */
! 391: /* XXX Have to make sure that sigreturn does the right thing. */
! 392: sv.sival_int = frame->srr0;
! 393: KERNEL_PROC_LOCK(p);
! 394: trapsignal(p, SIGSEGV, VM_PROT_EXECUTE, SEGV_MAPERR, sv);
! 395: KERNEL_PROC_UNLOCK(p);
! 396: break;
! 397: case EXC_SC|EXC_USER:
! 398: {
! 399: struct sysent *callp;
! 400: size_t argsize;
! 401: register_t code, error;
! 402: register_t *params, rval[2];
! 403: int nsys, n;
! 404: register_t args[10];
! 405:
! 406: uvmexp.syscalls++;
! 407:
! 408: nsys = p->p_emul->e_nsysent;
! 409: callp = p->p_emul->e_sysent;
! 410:
! 411: code = frame->fixreg[0];
! 412: params = frame->fixreg + FIRSTARG;
! 413:
! 414: switch (code) {
! 415: case SYS_syscall:
! 416: /*
! 417: * code is first argument,
! 418: * followed by actual args.
! 419: */
! 420: code = *params++;
! 421: break;
! 422: case SYS___syscall:
! 423: /*
! 424: * Like syscall, but code is a quad,
! 425: * so as to maintain quad alignment
! 426: * for the rest of the args.
! 427: */
! 428: if (callp != sysent)
! 429: break;
! 430: params++;
! 431: code = *params++;
! 432: break;
! 433: default:
! 434: break;
! 435: }
! 436: if (code < 0 || code >= nsys)
! 437: callp += p->p_emul->e_nosys;
! 438: else
! 439: callp += code;
! 440: argsize = callp->sy_argsize;
! 441: n = NARGREG - (params - (frame->fixreg + FIRSTARG));
! 442: if (argsize > n * sizeof(register_t)) {
! 443: bcopy(params, args, n * sizeof(register_t));
! 444:
! 445: error = copyin(MOREARGS(frame->fixreg[1]),
! 446: args + n, argsize - n * sizeof(register_t));
! 447: if (error) {
! 448: #ifdef KTRACE
! 449: /* Can't get all the arguments! */
! 450: if (KTRPOINT(p, KTR_SYSCALL))
! 451: ktrsyscall(p, code,
! 452: argsize, args);
! 453: #endif
! 454: goto syscall_bad;
! 455: }
! 456: params = args;
! 457: }
! 458:
! 459: KERNEL_PROC_LOCK(p);
! 460: #ifdef KTRACE
! 461: if (KTRPOINT(p, KTR_SYSCALL))
! 462: ktrsyscall(p, code, argsize, params);
! 463: #endif
! 464: rval[0] = 0;
! 465: rval[1] = frame->fixreg[FIRSTARG + 1];
! 466:
! 467: #ifdef SYSCALL_DEBUG
! 468: scdebug_call(p, code, params);
! 469: #endif
! 470:
! 471:
! 472: #if NSYSTRACE > 0
! 473: if (ISSET(p->p_flag, P_SYSTRACE))
! 474: error = systrace_redirect(code, p, params,
! 475: rval);
! 476: else
! 477: #endif
! 478: error = (*callp->sy_call)(p, params, rval);
! 479: KERNEL_PROC_UNLOCK(p);
! 480: switch (error) {
! 481: case 0:
! 482: frame->fixreg[0] = error;
! 483: frame->fixreg[FIRSTARG] = rval[0];
! 484: frame->fixreg[FIRSTARG + 1] = rval[1];
! 485: frame->cr &= ~0x10000000;
! 486: break;
! 487: case ERESTART:
! 488: /*
! 489: * Set user's pc back to redo the system call.
! 490: */
! 491: frame->srr0 -= 4;
! 492: break;
! 493: case EJUSTRETURN:
! 494: /* nothing to do */
! 495: break;
! 496: default:
! 497: syscall_bad:
! 498: if (p->p_emul->e_errno)
! 499: error = p->p_emul->e_errno[error];
! 500: frame->fixreg[0] = error;
! 501: frame->fixreg[FIRSTARG] = error;
! 502: frame->fixreg[FIRSTARG + 1] = rval[1];
! 503: frame->cr |= 0x10000000;
! 504: break;
! 505: }
! 506: #ifdef SYSCALL_DEBUG
! 507: KERNEL_PROC_LOCK(p);
! 508: scdebug_ret(p, code, error, rval);
! 509: KERNEL_PROC_UNLOCK(p);
! 510: #endif
! 511: #ifdef KTRACE
! 512: if (KTRPOINT(p, KTR_SYSRET)) {
! 513: KERNEL_PROC_LOCK(p);
! 514: ktrsysret(p, code, error, rval[0]);
! 515: KERNEL_PROC_UNLOCK(p);
! 516: }
! 517: #endif
! 518: }
! 519: break;
! 520:
! 521: case EXC_FPU|EXC_USER:
! 522: if (ci->ci_fpuproc)
! 523: save_fpu();
! 524: uvmexp.fpswtch++;
! 525: enable_fpu(p);
! 526: break;
! 527:
! 528: case EXC_ALI|EXC_USER:
! 529: /* alignment exception
! 530: * we check to see if this can be fixed up
! 531: * by the code that fixes the typical gcc misaligned code
! 532: * then kill the process if not.
! 533: */
! 534: if (fix_unaligned(p, frame) == 0)
! 535: frame->srr0 += 4;
! 536: else {
! 537: sv.sival_int = frame->srr0;
! 538: KERNEL_PROC_LOCK(p);
! 539: trapsignal(p, SIGSEGV, VM_PROT_EXECUTE, SEGV_MAPERR,
! 540: sv);
! 541: KERNEL_PROC_UNLOCK(p);
! 542: }
! 543: break;
! 544:
! 545: default:
! 546:
! 547: brain_damage:
! 548: /*
! 549: mpc_print_pci_stat();
! 550: */
! 551:
! 552: #ifdef DDB
! 553: /* set up registers */
! 554: db_save_regs(frame);
! 555: db_find_sym_and_offset(frame->srr0, &name, &offset);
! 556: #else
! 557: name = NULL;
! 558: #endif
! 559: if (!name) {
! 560: name = "0";
! 561: offset = frame->srr0;
! 562: }
! 563: panic ("trap type %x at %x (%s+0x%lx) lr %x",
! 564: type, frame->srr0, name, offset, frame->lr);
! 565:
! 566:
! 567: case EXC_PGM|EXC_USER:
! 568: {
! 569: #if 0
! 570: char *errstr[8];
! 571: int errnum = 0;
! 572:
! 573: if (frame->srr1 & (1<<(31-11))) {
! 574: /* floating point enabled program exception */
! 575: errstr[errnum] = "floating point";
! 576: errnum++;
! 577: }
! 578: if (frame->srr1 & (1<<(31-12))) {
! 579: /* illegal instruction program exception */
! 580: errstr[errnum] = "illegal instruction";
! 581: errnum++;
! 582: }
! 583: if (frame->srr1 & (1<<(31-13))) {
! 584: /* privileged instruction exception */
! 585: errstr[errnum] = "privileged instr";
! 586: errnum++;
! 587: }
! 588: #endif
! 589: if (frame->srr1 & (1<<(31-14))) {
! 590: #if 0
! 591: errstr[errnum] = "trap instr";
! 592: errnum++;
! 593: #endif
! 594: sv.sival_int = frame->srr0;
! 595: KERNEL_PROC_LOCK(p);
! 596: trapsignal(p, SIGTRAP, type, TRAP_BRKPT, sv);
! 597: KERNEL_PROC_UNLOCK(p);
! 598: break;
! 599: }
! 600: #if 0
! 601: if (frame->srr1 & (1<<(31-15))) {
! 602: errstr[errnum] = "previous address";
! 603: errnum++;
! 604: }
! 605: #endif
! 606: #if 0
! 607: printf("pgm iar %x srr1 %x\n", frame->srr0, frame->srr1);
! 608: {
! 609: int i;
! 610: for (i = 0; i < errnum; i++) {
! 611: printf("\t[%s]\n", errstr[i]);
! 612: }
! 613: }
! 614: #endif
! 615: sv.sival_int = frame->srr0;
! 616: KERNEL_PROC_LOCK(p);
! 617: trapsignal(p, SIGILL, 0, ILL_ILLOPC, sv);
! 618: KERNEL_PROC_UNLOCK(p);
! 619: break;
! 620: }
! 621: case EXC_PGM:
! 622: /* should check for correct byte here or panic */
! 623: #ifdef DDB
! 624: db_save_regs(frame);
! 625: cnpollc(TRUE);
! 626: db_trap(T_BREAKPOINT, 0);
! 627: cnpollc(FALSE);
! 628: #else
! 629: panic("trap EXC_PGM");
! 630: #endif
! 631: break;
! 632:
! 633: /* This is not really a perf exception, but is an ALTIVEC unavail
! 634: * if we do not handle it, kill the process with illegal instruction.
! 635: */
! 636: case EXC_PERF|EXC_USER:
! 637: #ifdef ALTIVEC
! 638: case EXC_VEC|EXC_USER:
! 639: if (ci->ci_vecproc)
! 640: save_vec(ci->ci_vecproc);
! 641:
! 642: ci->ci_vecproc = p;
! 643: enable_vec(p);
! 644: break;
! 645: #else /* ALTIVEC */
! 646: sv.sival_int = frame->srr0;
! 647: KERNEL_PROC_LOCK(p);
! 648: trapsignal(p, SIGILL, 0, ILL_ILLOPC, sv);
! 649: KERNEL_PROC_UNLOCK(p);
! 650: break;
! 651: #endif
! 652:
! 653: case EXC_VECAST|EXC_USER:
! 654: KERNEL_PROC_LOCK(p);
! 655: trapsignal(p, SIGFPE, 0, FPE_FLTRES, sv);
! 656: KERNEL_PROC_UNLOCK(p);
! 657: break;
! 658:
! 659: case EXC_AST|EXC_USER:
! 660: uvmexp.softs++;
! 661: ci->ci_astpending = 0; /* we are about to do it */
! 662: if (p->p_flag & P_OWEUPC) {
! 663: KERNEL_PROC_LOCK(p);
! 664: ADDUPROF(p);
! 665: KERNEL_PROC_UNLOCK(p);
! 666: }
! 667: if (ci->ci_want_resched)
! 668: preempt(NULL);
! 669: break;
! 670: }
! 671:
! 672: userret(p);
! 673:
! 674: /*
! 675: * If someone stole the fpu while we were away, disable it
! 676: */
! 677: if (p != ci->ci_fpuproc)
! 678: frame->srr1 &= ~PSL_FP;
! 679: else if (p->p_addr->u_pcb.pcb_flags & PCB_FPU)
! 680: frame->srr1 |= PSL_FP;
! 681:
! 682: #ifdef ALTIVEC
! 683: /*
! 684: * If someone stole the vector unit while we were away, disable it
! 685: */
! 686: if (p == ci->ci_vecproc)
! 687: frame->srr1 |= PSL_VEC;
! 688: else
! 689: frame->srr1 &= ~PSL_VEC;
! 690: #endif /* ALTIVEC */
! 691: }
! 692:
! 693: void
! 694: child_return(void *arg)
! 695: {
! 696: struct proc *p = (struct proc *)arg;
! 697: struct trapframe *tf = trapframe(p);
! 698:
! 699: tf->fixreg[0] = 0;
! 700: tf->fixreg[FIRSTARG] = 0;
! 701: tf->fixreg[FIRSTARG + 1] = 1;
! 702: tf->cr &= ~0x10000000;
! 703: /* Disable FPU, VECT, as we can't be fpuproc */
! 704: tf->srr1 &= ~(PSL_FP|PSL_VEC);
! 705:
! 706: KERNEL_PROC_UNLOCK(p);
! 707:
! 708: userret(p);
! 709:
! 710: #ifdef KTRACE
! 711: if (KTRPOINT(p, KTR_SYSRET)) {
! 712: KERNEL_PROC_LOCK(p);
! 713: ktrsysret(p,
! 714: (p->p_flag & P_PPWAIT) ? SYS_vfork : SYS_fork, 0, 0);
! 715: KERNEL_PROC_UNLOCK(p);
! 716: }
! 717: #endif
! 718: }
! 719:
! 720: int
! 721: badaddr(char *addr, u_int32_t len)
! 722: {
! 723: faultbuf env;
! 724: u_int32_t v;
! 725: void *oldh = curpcb->pcb_onfault;
! 726:
! 727: if (setfault(&env)) {
! 728: curpcb->pcb_onfault = oldh;
! 729: return EFAULT;
! 730: }
! 731: switch(len) {
! 732: case 4:
! 733: v = *((volatile u_int32_t *)addr);
! 734: break;
! 735: case 2:
! 736: v = *((volatile u_int16_t *)addr);
! 737: break;
! 738: default:
! 739: v = *((volatile u_int8_t *)addr);
! 740: break;
! 741: }
! 742: /* Make sure all loads retire before turning off fault handling!! */
! 743: __asm__ volatile ("sync");
! 744: curpcb->pcb_onfault = oldh;
! 745: return(0);
! 746: }
! 747:
! 748:
! 749: /*
! 750: * For now, this only deals with the particular unaligned access case
! 751: * that gcc tends to generate. Eventually it should handle all of the
! 752: * possibilities that can happen on a 32-bit PowerPC in big-endian mode.
! 753: */
! 754:
! 755: static int
! 756: fix_unaligned(struct proc *p, struct trapframe *frame)
! 757: {
! 758: int indicator = EXC_ALI_OPCODE_INDICATOR(frame->dsisr);
! 759: struct cpu_info *ci = curcpu();
! 760:
! 761: switch (indicator) {
! 762: case EXC_ALI_LFD:
! 763: case EXC_ALI_STFD:
! 764: {
! 765: int reg = EXC_ALI_RST(frame->dsisr);
! 766: double *fpr = &p->p_addr->u_pcb.pcb_fpu.fpr[reg];
! 767:
! 768: /* Juggle the FPU to ensure that we've initialized
! 769: * the FPRs, and that their current state is in
! 770: * the PCB.
! 771: */
! 772: if (ci->ci_fpuproc != p) {
! 773: if (ci->ci_fpuproc)
! 774: save_fpu();
! 775: enable_fpu(p);
! 776: }
! 777: save_fpu();
! 778:
! 779: if (indicator == EXC_ALI_LFD) {
! 780: if (copyin((void *)frame->dar, fpr,
! 781: sizeof(double)) != 0)
! 782: return -1;
! 783: } else {
! 784: if (copyout(fpr, (void *)frame->dar,
! 785: sizeof(double)) != 0)
! 786: return -1;
! 787: }
! 788: enable_fpu(p);
! 789: return 0;
! 790: }
! 791: break;
! 792: }
! 793: return -1;
! 794: }
CVSweb