trap.c revision 1.35
1/* $NetBSD: trap.c,v 1.35 2006/07/19 21:11:45 ad Exp $ */ 2 3/* 4 * Copyright 2001 Wasabi Systems, Inc. 5 * All rights reserved. 6 * 7 * Written by Eduardo Horvath and Simon Burge for Wasabi Systems, Inc. 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 for the NetBSD Project by 20 * Wasabi Systems, Inc. 21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 22 * or promote products derived from this software without specific prior 23 * written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 * POSSIBILITY OF SUCH DAMAGE. 36 */ 37 38/* 39 * Copyright (C) 1995, 1996 Wolfgang Solfrank. 40 * Copyright (C) 1995, 1996 TooLs GmbH. 41 * All rights reserved. 42 * 43 * Redistribution and use in source and binary forms, with or without 44 * modification, are permitted provided that the following conditions 45 * are met: 46 * 1. Redistributions of source code must retain the above copyright 47 * notice, this list of conditions and the following disclaimer. 48 * 2. Redistributions in binary form must reproduce the above copyright 49 * notice, this list of conditions and the following disclaimer in the 50 * documentation and/or other materials provided with the distribution. 51 * 3. All advertising materials mentioning features or use of this software 52 * must display the following acknowledgement: 53 * This product includes software developed by TooLs GmbH. 54 * 4. The name of TooLs GmbH may not be used to endorse or promote products 55 * derived from this software without specific prior written permission. 56 * 57 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 58 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 59 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 60 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 61 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 62 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 63 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 64 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 65 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 66 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 67 */ 68 69#include <sys/cdefs.h> 70__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.35 2006/07/19 21:11:45 ad Exp $"); 71 72#include "opt_altivec.h" 73#include "opt_ddb.h" 74 75#include <sys/param.h> 76#include <sys/proc.h> 77#include <sys/reboot.h> 78#include <sys/syscall.h> 79#include <sys/systm.h> 80#include <sys/user.h> 81#include <sys/pool.h> 82#include <sys/sa.h> 83#include <sys/savar.h> 84#include <sys/userret.h> 85#include <sys/kauth.h> 86 87#include <uvm/uvm_extern.h> 88 89#include <dev/cons.h> 90 91#include <machine/cpu.h> 92#include <machine/db_machdep.h> 93#include <machine/fpu.h> 94#include <machine/frame.h> 95#include <machine/pcb.h> 96#include <machine/psl.h> 97#include <machine/trap.h> 98 99#include <powerpc/spr.h> 100#include <powerpc/ibm4xx/pmap.h> 101#include <powerpc/ibm4xx/tlb.h> 102#include <powerpc/fpu/fpu_extern.h> 103 104/* These definitions should probably be somewhere else XXX */ 105#define FIRSTARG 3 /* first argument is in reg 3 */ 106#define NARGREG 8 /* 8 args are in registers */ 107#define MOREARGS(sp) ((caddr_t)((int)(sp) + 8)) /* more args go here */ 108 109static int fix_unaligned __P((struct lwp *l, struct trapframe *frame)); 110 111void trap __P((struct trapframe *)); /* Called from locore / trap_subr */ 112/* Why are these not defined in a header? */ 113int badaddr __P((void *, size_t)); 114int badaddr_read __P((void *, size_t, int *)); 115int ctx_setup __P((int, int)); 116 117#ifdef DEBUG 118#define TDB_ALL 0x1 119int trapdebug = /* TDB_ALL */ 0; 120#define DBPRINTF(x, y) if (trapdebug & (x)) printf y 121#else 122#define DBPRINTF(x, y) 123#endif 124 125void 126trap(struct trapframe *frame) 127{ 128 struct lwp *l = curlwp; 129 struct proc *p = l ? l->l_proc : NULL; 130 int type = frame->exc; 131 int ftype, rv; 132 ksiginfo_t ksi; 133 134 KASSERT(l == 0 || (l->l_stat == LSONPROC)); 135 136 if (frame->srr1 & PSL_PR) { 137 LWP_CACHE_CREDS(l, p); 138 type |= EXC_USER; 139 } 140 141 ftype = VM_PROT_READ; 142 143 DBPRINTF(TDB_ALL, ("trap(%x) at %lx from frame %p &frame %p\n", 144 type, frame->srr0, frame, &frame)); 145 146 switch (type) { 147 case EXC_DEBUG|EXC_USER: 148 { 149 int srr2, srr3; 150 151 __asm volatile("mfspr %0,0x3f0" : 152 "=r" (rv), "=r" (srr2), "=r" (srr3) :); 153 printf("debug reg is %x srr2 %x srr3 %x\n", rv, srr2, 154 srr3); 155 /* XXX fall through or break here?! */ 156 } 157 /* 158 * DEBUG intr -- probably single-step. 159 */ 160 case EXC_TRC|EXC_USER: 161 frame->srr1 &= ~PSL_SE; 162 KSI_INIT_TRAP(&ksi); 163 ksi.ksi_signo = SIGTRAP; 164 ksi.ksi_trap = EXC_TRC; 165 ksi.ksi_addr = (void *)frame->srr0; 166 KERNEL_PROC_LOCK(l); 167 trapsignal(l, &ksi); 168 KERNEL_PROC_UNLOCK(l); 169 break; 170 171 /* 172 * If we could not find and install appropriate TLB entry, fall through. 173 */ 174 175 case EXC_DSI: 176 /* FALLTHROUGH */ 177 case EXC_DTMISS: 178 { 179 struct vm_map *map; 180 vaddr_t va; 181 struct faultbuf *fb = NULL; 182 183 KERNEL_LOCK(LK_CANRECURSE|LK_EXCLUSIVE); 184 va = frame->dar; 185 if (frame->tf_xtra[TF_PID] == KERNEL_PID) { 186 map = kernel_map; 187 } else { 188 map = &p->p_vmspace->vm_map; 189 if (l->l_flag & L_SA) { 190 l->l_savp->savp_faultaddr = va; 191 l->l_flag |= L_SA_PAGEFAULT; 192 } 193 } 194 195 if (frame->tf_xtra[TF_ESR] & (ESR_DST|ESR_DIZ)) 196 ftype = VM_PROT_WRITE; 197 198 DBPRINTF(TDB_ALL, 199 ("trap(EXC_DSI) at %lx %s fault on %p esr %x\n", 200 frame->srr0, 201 (ftype & VM_PROT_WRITE) ? "write" : "read", 202 (void *)va, frame->tf_xtra[TF_ESR])); 203 rv = uvm_fault(map, trunc_page(va), ftype); 204 KERNEL_UNLOCK(); 205 if (map != kernel_map) 206 l->l_flag &= ~L_SA_PAGEFAULT; 207 if (rv == 0) 208 goto done; 209 if ((fb = l->l_addr->u_pcb.pcb_onfault) != NULL) { 210 frame->tf_xtra[TF_PID] = KERNEL_PID; 211 frame->srr0 = fb->fb_pc; 212 frame->srr1 |= PSL_IR; /* Re-enable IMMU */ 213 frame->fixreg[1] = fb->fb_sp; 214 frame->fixreg[2] = fb->fb_r2; 215 frame->fixreg[3] = 1; /* Return TRUE */ 216 frame->cr = fb->fb_cr; 217 memcpy(&frame->fixreg[13], fb->fb_fixreg, 218 sizeof(fb->fb_fixreg)); 219 goto done; 220 } 221 } 222 goto brain_damage; 223 224 case EXC_DSI|EXC_USER: 225 /* FALLTHROUGH */ 226 case EXC_DTMISS|EXC_USER: 227 KERNEL_PROC_LOCK(l); 228 229 if (frame->tf_xtra[TF_ESR] & (ESR_DST|ESR_DIZ)) 230 ftype = VM_PROT_WRITE; 231 232 DBPRINTF(TDB_ALL, 233 ("trap(EXC_DSI|EXC_USER) at %lx %s fault on %lx %x\n", 234 frame->srr0, (ftype & VM_PROT_WRITE) ? "write" : "read", 235 frame->dar, frame->tf_xtra[TF_ESR])); 236 KASSERT(l == curlwp && (l->l_stat == LSONPROC)); 237 if (l->l_flag & L_SA) { 238 l->l_savp->savp_faultaddr = (vaddr_t)frame->dar; 239 l->l_flag |= L_SA_PAGEFAULT; 240 } 241 rv = uvm_fault(&p->p_vmspace->vm_map, trunc_page(frame->dar), 242 ftype); 243 if (rv == 0) { 244 l->l_flag &= ~L_SA_PAGEFAULT; 245 KERNEL_PROC_UNLOCK(l); 246 break; 247 } 248 KSI_INIT_TRAP(&ksi); 249 ksi.ksi_signo = SIGSEGV; 250 ksi.ksi_trap = EXC_DSI; 251 ksi.ksi_addr = (void *)frame->dar; 252 if (rv == ENOMEM) { 253 printf("UVM: pid %d (%s) lid %d, uid %d killed: " 254 "out of swap\n", 255 p->p_pid, p->p_comm, l->l_lid, 256 p->p_cred ? 257 kauth_cred_geteuid(p->p_cred) : -1); 258 ksi.ksi_signo = SIGKILL; 259 } 260 trapsignal(l, &ksi); 261 l->l_flag &= ~L_SA_PAGEFAULT; 262 KERNEL_PROC_UNLOCK(l); 263 break; 264 265 case EXC_ITMISS|EXC_USER: 266 case EXC_ISI|EXC_USER: 267 KERNEL_PROC_LOCK(l); 268 if (l->l_flag & L_SA) { 269 l->l_savp->savp_faultaddr = (vaddr_t)frame->srr0; 270 l->l_flag |= L_SA_PAGEFAULT; 271 } 272 ftype = VM_PROT_EXECUTE; 273 DBPRINTF(TDB_ALL, 274 ("trap(EXC_ISI|EXC_USER) at %lx execute fault tf %p\n", 275 frame->srr0, frame)); 276 rv = uvm_fault(&p->p_vmspace->vm_map, trunc_page(frame->srr0), 277 ftype); 278 if (rv == 0) { 279 l->l_flag &= ~L_SA_PAGEFAULT; 280 KERNEL_PROC_UNLOCK(l); 281 break; 282 } 283 KSI_INIT_TRAP(&ksi); 284 ksi.ksi_signo = SIGSEGV; 285 ksi.ksi_trap = EXC_ISI; 286 ksi.ksi_addr = (void *)frame->srr0; 287 ksi.ksi_code = (rv == EACCES ? SEGV_ACCERR : SEGV_MAPERR); 288 trapsignal(l, &ksi); 289 l->l_flag &= ~L_SA_PAGEFAULT; 290 KERNEL_PROC_UNLOCK(l); 291 break; 292 293 case EXC_AST|EXC_USER: 294 curcpu()->ci_astpending = 0; /* we are about to do it */ 295 KERNEL_PROC_LOCK(l); 296 uvmexp.softs++; 297 if (p->p_flag & P_OWEUPC) { 298 p->p_flag &= ~P_OWEUPC; 299 ADDUPROF(p); 300 } 301 /* Check whether we are being preempted. */ 302 if (curcpu()->ci_want_resched) 303 preempt(0); 304 KERNEL_PROC_UNLOCK(l); 305 break; 306 307 308 case EXC_ALI|EXC_USER: 309 KERNEL_PROC_LOCK(l); 310 if (fix_unaligned(l, frame) != 0) { 311 KSI_INIT_TRAP(&ksi); 312 ksi.ksi_signo = SIGBUS; 313 ksi.ksi_trap = EXC_ALI; 314 ksi.ksi_addr = (void *)frame->dar; 315 trapsignal(l, &ksi); 316 } else 317 frame->srr0 += 4; 318 KERNEL_PROC_UNLOCK(l); 319 break; 320 321 case EXC_PGM|EXC_USER: 322 /* 323 * Illegal insn: 324 * 325 * let's try to see if it's FPU and can be emulated. 326 */ 327 uvmexp.traps++; 328 if (!(l->l_addr->u_pcb.pcb_flags & PCB_FPU)) { 329 memset(&l->l_addr->u_pcb.pcb_fpu, 0, 330 sizeof l->l_addr->u_pcb.pcb_fpu); 331 l->l_addr->u_pcb.pcb_flags |= PCB_FPU; 332 } 333 334 if ((rv = fpu_emulate(frame, 335 (struct fpreg *)&l->l_addr->u_pcb.pcb_fpu))) { 336 KSI_INIT_TRAP(&ksi); 337 ksi.ksi_signo = rv; 338 ksi.ksi_trap = EXC_PGM; 339 ksi.ksi_addr = (void *)frame->srr0; 340 KERNEL_PROC_LOCK(l); 341 trapsignal(l, &ksi); 342 KERNEL_PROC_UNLOCK(l); 343 } 344 break; 345 346 case EXC_MCHK: 347 { 348 struct faultbuf *fb; 349 350 if ((fb = l->l_addr->u_pcb.pcb_onfault) != NULL) { 351 frame->tf_xtra[TF_PID] = KERNEL_PID; 352 frame->srr0 = fb->fb_pc; 353 frame->srr1 |= PSL_IR; /* Re-enable IMMU */ 354 frame->fixreg[1] = fb->fb_sp; 355 frame->fixreg[2] = fb->fb_r2; 356 frame->fixreg[3] = 1; /* Return TRUE */ 357 frame->cr = fb->fb_cr; 358 memcpy(&frame->fixreg[13], fb->fb_fixreg, 359 sizeof(fb->fb_fixreg)); 360 goto done; 361 } 362 } 363 goto brain_damage; 364 default: 365 brain_damage: 366 printf("trap type 0x%x at 0x%lx\n", type, frame->srr0); 367#ifdef DDB 368 if (kdb_trap(type, frame)) 369 goto done; 370#endif 371#ifdef TRAP_PANICWAIT 372 printf("Press a key to panic.\n"); 373 cngetc(); 374#endif 375 panic("trap"); 376 } 377 378 /* Invoke MI userret code */ 379 mi_userret(l); 380 381 curcpu()->ci_schedstate.spc_curpriority = l->l_priority = l->l_usrpri; 382 done: 383 return; 384} 385 386int 387ctx_setup(int ctx, int srr1) 388{ 389 volatile struct pmap *pm; 390 391 /* Update PID if we're returning to user mode. */ 392 if (srr1 & PSL_PR) { 393 pm = curproc->p_vmspace->vm_map.pmap; 394 if (!pm->pm_ctx) { 395 ctx_alloc(__UNVOLATILE(pm)); 396 } 397 ctx = pm->pm_ctx; 398 if (srr1 & PSL_SE) { 399 int dbreg, mask = 0x48000000; 400 /* 401 * Set the Internal Debug and 402 * Instruction Completion bits of 403 * the DBCR0 register. 404 * 405 * XXX this is also used by jtag debuggers... 406 */ 407 __asm volatile("mfspr %0,0x3f2;" 408 "or %0,%0,%1;" 409 "mtspr 0x3f2,%0;" : 410 "=&r" (dbreg) : "r" (mask)); 411 } 412 } 413 else if (!ctx) { 414 ctx = KERNEL_PID; 415 } 416 return (ctx); 417} 418 419/* 420 * Used by copyin()/copyout() 421 */ 422extern vaddr_t vmaprange __P((struct proc *, vaddr_t, vsize_t, int)); 423extern void vunmaprange __P((vaddr_t, vsize_t)); 424static int bigcopyin __P((const void *, void *, size_t )); 425static int bigcopyout __P((const void *, void *, size_t )); 426 427int 428copyin(const void *udaddr, void *kaddr, size_t len) 429{ 430 struct pmap *pm = curproc->p_vmspace->vm_map.pmap; 431 int msr, pid, tmp, ctx; 432 struct faultbuf env; 433 434 /* For bigger buffers use the faster copy */ 435 if (len > 256) 436 return (bigcopyin(udaddr, kaddr, len)); 437 438 if (setfault(&env)) { 439 curpcb->pcb_onfault = 0; 440 return EFAULT; 441 } 442 443 if (!(ctx = pm->pm_ctx)) { 444 /* No context -- assign it one */ 445 ctx_alloc(pm); 446 ctx = pm->pm_ctx; 447 } 448 449 __asm volatile("addi %6,%6,1; mtctr %6;" /* Set up counter */ 450 "mfmsr %0;" /* Save MSR */ 451 "li %1,0x20; " 452 "andc %1,%0,%1; mtmsr %1;" /* Disable IMMU */ 453 "mfpid %1;" /* Save old PID */ 454 "sync; isync;" 455 456 "1: bdz 2f;" /* while len */ 457 "mtpid %3; sync;" /* Load user ctx */ 458 "lbz %2,0(%4); addi %4,%4,1;" /* Load byte */ 459 "sync; isync;" 460 "mtpid %1;sync;" 461 "stb %2,0(%5); dcbf 0,%5; addi %5,%5,1;" /* Store kernel byte */ 462 "sync; isync;" 463 "b 1b;" /* repeat */ 464 465 "2: mtpid %1; mtmsr %0;" /* Restore PID and MSR */ 466 "sync; isync;" 467 : "=&r" (msr), "=&r" (pid), "=&r" (tmp) 468 : "r" (ctx), "b" (udaddr), "b" (kaddr), "b" (len)); 469 470 curpcb->pcb_onfault = 0; 471 return 0; 472} 473 474static int 475bigcopyin(const void *udaddr, void *kaddr, size_t len) 476{ 477 const char *up; 478 char *kp = kaddr; 479 struct lwp *l = curlwp; 480 struct proc *p; 481 int error; 482 483 if (!l) { 484 return EFAULT; 485 } 486 487 p = l->l_proc; 488 489 /* 490 * Stolen from physio(): 491 */ 492 PHOLD(l); 493 error = uvm_vslock(p, __UNCONST(udaddr), len, VM_PROT_READ); 494 if (error) { 495 PRELE(l); 496 return EFAULT; 497 } 498 up = (char *)vmaprange(p, (vaddr_t)udaddr, len, VM_PROT_READ); 499 500 memcpy(kp, up, len); 501 vunmaprange((vaddr_t)up, len); 502 uvm_vsunlock(p, __UNCONST(udaddr), len); 503 PRELE(l); 504 505 return 0; 506} 507 508int 509copyout(const void *kaddr, void *udaddr, size_t len) 510{ 511 struct pmap *pm = curproc->p_vmspace->vm_map.pmap; 512 int msr, pid, tmp, ctx; 513 struct faultbuf env; 514 515 /* For big copies use more efficient routine */ 516 if (len > 256) 517 return (bigcopyout(kaddr, udaddr, len)); 518 519 if (setfault(&env)) { 520 curpcb->pcb_onfault = 0; 521 return EFAULT; 522 } 523 524 if (!(ctx = pm->pm_ctx)) { 525 /* No context -- assign it one */ 526 ctx_alloc(pm); 527 ctx = pm->pm_ctx; 528 } 529 530 __asm volatile("addi %6,%6,1; mtctr %6;" /* Set up counter */ 531 "mfmsr %0;" /* Save MSR */ 532 "li %1,0x20; " 533 "andc %1,%0,%1; mtmsr %1;" /* Disable IMMU */ 534 "mfpid %1;" /* Save old PID */ 535 "sync; isync;" 536 537 "1: bdz 2f;" /* while len */ 538 "mtpid %1;sync;" 539 "lbz %2,0(%5); addi %5,%5,1;" /* Load kernel byte */ 540 "sync; isync;" 541 "mtpid %3; sync;" /* Load user ctx */ 542 "stb %2,0(%4); dcbf 0,%4; addi %4,%4,1;" /* Store user byte */ 543 "sync; isync;" 544 "b 1b;" /* repeat */ 545 546 "2: mtpid %1; mtmsr %0;" /* Restore PID and MSR */ 547 "sync; isync;" 548 : "=&r" (msr), "=&r" (pid), "=&r" (tmp) 549 : "r" (ctx), "b" (udaddr), "b" (kaddr), "b" (len)); 550 551 curpcb->pcb_onfault = 0; 552 return 0; 553} 554 555static int 556bigcopyout(const void *kaddr, void *udaddr, size_t len) 557{ 558 char *up; 559 const char *kp = (const char *)kaddr; 560 struct lwp *l = curlwp; 561 struct proc *p; 562 int error; 563 564 if (!l) { 565 return EFAULT; 566 } 567 568 p = l->l_proc; 569 570 /* 571 * Stolen from physio(): 572 */ 573 PHOLD(l); 574 error = uvm_vslock(p, udaddr, len, VM_PROT_WRITE); 575 if (error) { 576 PRELE(l); 577 return EFAULT; 578 } 579 up = (char *)vmaprange(p, (vaddr_t)udaddr, len, 580 VM_PROT_READ | VM_PROT_WRITE); 581 582 memcpy(up, kp, len); 583 vunmaprange((vaddr_t)up, len); 584 uvm_vsunlock(p, udaddr, len); 585 PRELE(l); 586 587 return 0; 588} 589 590/* 591 * kcopy(const void *src, void *dst, size_t len); 592 * 593 * Copy len bytes from src to dst, aborting if we encounter a fatal 594 * page fault. 595 * 596 * kcopy() _must_ save and restore the old fault handler since it is 597 * called by uiomove(), which may be in the path of servicing a non-fatal 598 * page fault. 599 */ 600int 601kcopy(const void *src, void *dst, size_t len) 602{ 603 struct faultbuf env, *oldfault; 604 605 oldfault = curpcb->pcb_onfault; 606 if (setfault(&env)) { 607 curpcb->pcb_onfault = oldfault; 608 return EFAULT; 609 } 610 611 memcpy(dst, src, len); 612 613 curpcb->pcb_onfault = oldfault; 614 return 0; 615} 616 617int 618badaddr(void *addr, size_t size) 619{ 620 621 return badaddr_read(addr, size, NULL); 622} 623 624int 625badaddr_read(void *addr, size_t size, int *rptr) 626{ 627 struct faultbuf env; 628 int x; 629 630 /* Get rid of any stale machine checks that have been waiting. */ 631 __asm volatile ("sync; isync"); 632 633 if (setfault(&env)) { 634 curpcb->pcb_onfault = 0; 635 __asm volatile ("sync"); 636 return 1; 637 } 638 639 __asm volatile ("sync"); 640 641 switch (size) { 642 case 1: 643 x = *(volatile int8_t *)addr; 644 break; 645 case 2: 646 x = *(volatile int16_t *)addr; 647 break; 648 case 4: 649 x = *(volatile int32_t *)addr; 650 break; 651 default: 652 panic("badaddr: invalid size (%d)", size); 653 } 654 655 /* Make sure we took the machine check, if we caused one. */ 656 __asm volatile ("sync; isync"); 657 658 curpcb->pcb_onfault = 0; 659 __asm volatile ("sync"); /* To be sure. */ 660 661 /* Use the value to avoid reorder. */ 662 if (rptr) 663 *rptr = x; 664 665 return 0; 666} 667 668/* 669 * For now, this only deals with the particular unaligned access case 670 * that gcc tends to generate. Eventually it should handle all of the 671 * possibilities that can happen on a 32-bit PowerPC in big-endian mode. 672 */ 673 674static int 675fix_unaligned(struct lwp *l, struct trapframe *frame) 676{ 677 678 return -1; 679} 680 681/* 682 * Start a new LWP 683 */ 684void 685startlwp(arg) 686 void *arg; 687{ 688 int err; 689 ucontext_t *uc = arg; 690 struct lwp *l = curlwp; 691 692 err = cpu_setmcontext(l, &uc->uc_mcontext, uc->uc_flags); 693#if DIAGNOSTIC 694 if (err) { 695 printf("Error %d from cpu_setmcontext.", err); 696 } 697#endif 698 pool_put(&lwp_uc_pool, uc); 699 700 upcallret(l); 701} 702 703/* 704 * XXX This is a terrible name. 705 */ 706void 707upcallret(l) 708 struct lwp *l; 709{ 710 711 /* Invoke MI userret code */ 712 mi_userret(l); 713 714 curcpu()->ci_schedstate.spc_curpriority = l->l_priority = l->l_usrpri; 715} 716