1 /* $NetBSD: trap.c,v 1.54 2010/02/25 23:31:47 matt 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.54 2010/02/25 23:31:47 matt Exp $"); 71 72 #include "opt_altivec.h" 73 #include "opt_ddb.h" 74 #include "opt_kgdb.h" 75 76 #include <sys/param.h> 77 #include <sys/proc.h> 78 #include <sys/reboot.h> 79 #include <sys/syscall.h> 80 #include <sys/systm.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 #if defined(KGDB) 88 #include <sys/kgdb.h> 89 #endif 90 91 #include <uvm/uvm_extern.h> 92 93 #include <dev/cons.h> 94 95 #include <machine/cpu.h> 96 #include <machine/db_machdep.h> 97 #include <machine/fpu.h> 98 #include <machine/frame.h> 99 #include <machine/pcb.h> 100 #include <machine/psl.h> 101 #include <machine/trap.h> 102 103 #include <powerpc/spr.h> 104 #include <powerpc/ibm4xx/spr.h> 105 #include <powerpc/ibm4xx/pmap.h> 106 #include <powerpc/ibm4xx/tlb.h> 107 #include <powerpc/fpu/fpu_extern.h> 108 109 /* These definitions should probably be somewhere else XXX */ 110 #define FIRSTARG 3 /* first argument is in reg 3 */ 111 #define NARGREG 8 /* 8 args are in registers */ 112 #define MOREARGS(sp) ((void *)((int)(sp) + 8)) /* more args go here */ 113 114 static int fix_unaligned(struct lwp *l, struct trapframe *frame); 115 116 void trap(struct trapframe *); /* Called from locore / trap_subr */ 117 /* Why are these not defined in a header? */ 118 int badaddr(void *, size_t); 119 int badaddr_read(void *, size_t, int *); 120 int ctx_setup(int, int); 121 122 #ifdef DEBUG 123 #define TDB_ALL 0x1 124 int trapdebug = /* TDB_ALL */ 0; 125 #define DBPRINTF(x, y) if (trapdebug & (x)) printf y 126 #else 127 #define DBPRINTF(x, y) 128 #endif 129 130 void 131 trap(struct trapframe *frame) 132 { 133 struct lwp *l = curlwp; 134 struct proc *p = l ? l->l_proc : NULL; 135 struct pcb *pcb; 136 int type = frame->exc; 137 int ftype, rv; 138 ksiginfo_t ksi; 139 140 KASSERT(l == NULL || (l->l_stat == LSONPROC)); 141 142 if (frame->srr1 & PSL_PR) { 143 LWP_CACHE_CREDS(l, p); 144 type |= EXC_USER; 145 } 146 147 ftype = VM_PROT_READ; 148 149 DBPRINTF(TDB_ALL, ("trap(%x) at %lx from frame %p &frame %p\n", 150 type, frame->srr0, frame, &frame)); 151 152 switch (type) { 153 case EXC_DEBUG|EXC_USER: 154 { 155 int srr2, srr3; 156 157 __asm volatile("mfspr %0,0x3f0" : 158 "=r" (rv), "=r" (srr2), "=r" (srr3) :); 159 printf("debug reg is %x srr2 %x srr3 %x\n", rv, srr2, 160 srr3); 161 /* XXX fall through or break here?! */ 162 } 163 /* 164 * DEBUG intr -- probably single-step. 165 */ 166 case EXC_TRC|EXC_USER: 167 frame->srr1 &= ~PSL_SE; 168 KSI_INIT_TRAP(&ksi); 169 ksi.ksi_signo = SIGTRAP; 170 ksi.ksi_trap = EXC_TRC; 171 ksi.ksi_addr = (void *)frame->srr0; 172 trapsignal(l, &ksi); 173 break; 174 175 /* 176 * If we could not find and install appropriate TLB entry, fall through. 177 */ 178 179 case EXC_DSI: 180 /* FALLTHROUGH */ 181 case EXC_DTMISS: 182 { 183 struct vm_map *map; 184 vaddr_t va; 185 struct faultbuf *fb = NULL; 186 187 va = frame->dar; 188 if (frame->tf_xtra[TF_PID] == KERNEL_PID) { 189 map = kernel_map; 190 } else { 191 map = &p->p_vmspace->vm_map; 192 if ((l->l_flag & LW_SA) 193 && (~l->l_pflag & LP_SA_NOBLOCK)) { 194 l->l_savp->savp_faultaddr = va; 195 l->l_pflag |= LP_SA_PAGEFAULT; 196 } 197 } 198 199 if (frame->tf_xtra[TF_ESR] & (ESR_DST|ESR_DIZ)) 200 ftype = VM_PROT_WRITE; 201 202 DBPRINTF(TDB_ALL, 203 ("trap(EXC_DSI) at %lx %s fault on %p esr %x\n", 204 frame->srr0, 205 (ftype & VM_PROT_WRITE) ? "write" : "read", 206 (void *)va, frame->tf_xtra[TF_ESR])); 207 rv = uvm_fault(map, trunc_page(va), ftype); 208 if (map != kernel_map) { 209 l->l_pflag &= ~LP_SA_PAGEFAULT; 210 } 211 if (rv == 0) 212 goto done; 213 pcb = lwp_getpcb(l); 214 if ((fb = pcb->pcb_onfault) != NULL) { 215 frame->tf_xtra[TF_PID] = KERNEL_PID; 216 frame->srr0 = fb->fb_pc; 217 frame->srr1 |= PSL_IR; /* Re-enable IMMU */ 218 frame->fixreg[1] = fb->fb_sp; 219 frame->fixreg[2] = fb->fb_r2; 220 frame->fixreg[3] = 1; /* Return TRUE */ 221 frame->cr = fb->fb_cr; 222 memcpy(&frame->fixreg[13], fb->fb_fixreg, 223 sizeof(fb->fb_fixreg)); 224 goto done; 225 } 226 } 227 goto brain_damage; 228 229 case EXC_DSI|EXC_USER: 230 /* FALLTHROUGH */ 231 case EXC_DTMISS|EXC_USER: 232 if (frame->tf_xtra[TF_ESR] & (ESR_DST|ESR_DIZ)) 233 ftype = VM_PROT_WRITE; 234 235 DBPRINTF(TDB_ALL, 236 ("trap(EXC_DSI|EXC_USER) at %lx %s fault on %lx %x\n", 237 frame->srr0, (ftype & VM_PROT_WRITE) ? "write" : "read", 238 frame->dar, frame->tf_xtra[TF_ESR])); 239 KASSERT(l == curlwp && (l->l_stat == LSONPROC)); 240 if (l->l_flag & LW_SA) { 241 l->l_savp->savp_faultaddr = (vaddr_t)frame->dar; 242 l->l_pflag |= LP_SA_PAGEFAULT; 243 } 244 rv = uvm_fault(&p->p_vmspace->vm_map, trunc_page(frame->dar), 245 ftype); 246 if (rv == 0) { 247 l->l_pflag &= ~LP_SA_PAGEFAULT; 248 break; 249 } 250 KSI_INIT_TRAP(&ksi); 251 ksi.ksi_signo = SIGSEGV; 252 ksi.ksi_trap = EXC_DSI; 253 ksi.ksi_addr = (void *)frame->dar; 254 if (rv == ENOMEM) { 255 printf("UVM: pid %d (%s) lid %d, uid %d killed: " 256 "out of swap\n", 257 p->p_pid, p->p_comm, l->l_lid, 258 l->l_cred ? 259 kauth_cred_geteuid(l->l_cred) : -1); 260 ksi.ksi_signo = SIGKILL; 261 } 262 trapsignal(l, &ksi); 263 l->l_pflag &= ~LP_SA_PAGEFAULT; 264 break; 265 266 case EXC_ITMISS|EXC_USER: 267 case EXC_ISI|EXC_USER: 268 if (l->l_flag & LW_SA) { 269 l->l_savp->savp_faultaddr = (vaddr_t)frame->srr0; 270 l->l_pflag |= LP_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_pflag &= ~LP_SA_PAGEFAULT; 280 break; 281 } 282 KSI_INIT_TRAP(&ksi); 283 ksi.ksi_signo = SIGSEGV; 284 ksi.ksi_trap = EXC_ISI; 285 ksi.ksi_addr = (void *)frame->srr0; 286 ksi.ksi_code = (rv == EACCES ? SEGV_ACCERR : SEGV_MAPERR); 287 trapsignal(l, &ksi); 288 l->l_pflag &= ~LP_SA_PAGEFAULT; 289 break; 290 291 case EXC_AST|EXC_USER: 292 curcpu()->ci_astpending = 0; /* we are about to do it */ 293 uvmexp.softs++; 294 if (l->l_pflag & LP_OWEUPC) { 295 l->l_pflag &= ~LP_OWEUPC; 296 ADDUPROF(l); 297 } 298 /* Check whether we are being preempted. */ 299 if (curcpu()->ci_want_resched) 300 preempt(); 301 break; 302 303 304 case EXC_ALI|EXC_USER: 305 if (fix_unaligned(l, frame) != 0) { 306 KSI_INIT_TRAP(&ksi); 307 ksi.ksi_signo = SIGBUS; 308 ksi.ksi_trap = EXC_ALI; 309 ksi.ksi_addr = (void *)frame->dar; 310 trapsignal(l, &ksi); 311 } else 312 frame->srr0 += 4; 313 break; 314 315 case EXC_PGM|EXC_USER: 316 /* 317 * Illegal insn: 318 * 319 * let's try to see if it's FPU and can be emulated. 320 */ 321 uvmexp.traps++; 322 pcb = lwp_getpcb(l); 323 324 if (!(pcb->pcb_flags & PCB_FPU)) { 325 memset(&pcb->pcb_fpu, 0, sizeof(pcb->pcb_fpu)); 326 pcb->pcb_flags |= PCB_FPU; 327 } 328 329 if ((rv = fpu_emulate(frame, (struct fpreg *)&pcb->pcb_fpu))) { 330 KSI_INIT_TRAP(&ksi); 331 ksi.ksi_signo = rv; 332 ksi.ksi_trap = EXC_PGM; 333 ksi.ksi_addr = (void *)frame->srr0; 334 trapsignal(l, &ksi); 335 } 336 break; 337 338 case EXC_MCHK: 339 { 340 struct faultbuf *fb; 341 342 pcb = lwp_getpcb(l); 343 if ((fb = pcb->pcb_onfault) != NULL) { 344 frame->tf_xtra[TF_PID] = KERNEL_PID; 345 frame->srr0 = fb->fb_pc; 346 frame->srr1 |= PSL_IR; /* Re-enable IMMU */ 347 frame->fixreg[1] = fb->fb_sp; 348 frame->fixreg[2] = fb->fb_r2; 349 frame->fixreg[3] = 1; /* Return TRUE */ 350 frame->cr = fb->fb_cr; 351 memcpy(&frame->fixreg[13], fb->fb_fixreg, 352 sizeof(fb->fb_fixreg)); 353 goto done; 354 } 355 } 356 goto brain_damage; 357 default: 358 brain_damage: 359 printf("trap type 0x%x at 0x%lx\n", type, frame->srr0); 360 #if defined(DDB) || defined(KGDB) 361 if (kdb_trap(type, frame)) 362 goto done; 363 #endif 364 #ifdef TRAP_PANICWAIT 365 printf("Press a key to panic.\n"); 366 cngetc(); 367 #endif 368 panic("trap"); 369 } 370 371 /* Invoke MI userret code */ 372 mi_userret(l); 373 done: 374 return; 375 } 376 377 int 378 ctx_setup(int ctx, int srr1) 379 { 380 volatile struct pmap *pm; 381 382 /* Update PID if we're returning to user mode. */ 383 if (srr1 & PSL_PR) { 384 pm = curproc->p_vmspace->vm_map.pmap; 385 if (!pm->pm_ctx) { 386 ctx_alloc(__UNVOLATILE(pm)); 387 } 388 ctx = pm->pm_ctx; 389 if (srr1 & PSL_SE) { 390 int dbreg, mask = 0x48000000; 391 /* 392 * Set the Internal Debug and 393 * Instruction Completion bits of 394 * the DBCR0 register. 395 * 396 * XXX this is also used by jtag debuggers... 397 */ 398 __asm volatile("mfspr %0,0x3f2;" 399 "or %0,%0,%1;" 400 "mtspr 0x3f2,%0;" : 401 "=&r" (dbreg) : "r" (mask)); 402 } 403 } 404 else if (!ctx) { 405 ctx = KERNEL_PID; 406 } 407 return (ctx); 408 } 409 410 /* 411 * Used by copyin()/copyout() 412 */ 413 extern vaddr_t vmaprange(struct proc *, vaddr_t, vsize_t, int); 414 extern void vunmaprange(vaddr_t, vsize_t); 415 static int bigcopyin(const void *, void *, size_t ); 416 static int bigcopyout(const void *, void *, size_t ); 417 418 int 419 copyin(const void *udaddr, void *kaddr, size_t len) 420 { 421 struct pmap *pm = curproc->p_vmspace->vm_map.pmap; 422 int msr, pid, tmp, ctx, count=0; 423 struct faultbuf env; 424 425 /* For bigger buffers use the faster copy */ 426 if (len > 1024) 427 return (bigcopyin(udaddr, kaddr, len)); 428 429 if (setfault(&env)) { 430 curpcb->pcb_onfault = 0; 431 return EFAULT; 432 } 433 434 if (!(ctx = pm->pm_ctx)) { 435 /* No context -- assign it one */ 436 ctx_alloc(pm); 437 ctx = pm->pm_ctx; 438 } 439 440 __asm volatile( 441 " mfmsr %[msr];" /* Save MSR */ 442 " li %[pid],0x20; " 443 " andc %[pid],%[msr],%[pid]; mtmsr %[pid];" /* Disable IMMU */ 444 " mfpid %[pid];" /* Save old PID */ 445 " sync; isync;" 446 447 " srwi. %[count],%[len],0x2;" /* How many words? */ 448 " beq- 2f;" /* No words. Go do bytes */ 449 " mtctr %[count];" 450 "1: mtpid %[ctx]; sync;" 451 " lswi %[tmp],%[udaddr],4;" /* Load user word */ 452 " addi %[udaddr],%[udaddr],0x4;" /* next udaddr word */ 453 " sync; isync;" 454 " mtpid %[pid];sync;" 455 " stswi %[tmp],%[kaddr],4;" /* Store kernel word */ 456 " dcbf 0,%[kaddr];" /* flush cache */ 457 " addi %[kaddr],%[kaddr],0x4;" /* next udaddr word */ 458 " sync; isync;" 459 " bdnz 1b;" /* repeat */ 460 461 "2: andi. %[count],%[len],0x3;" /* How many remaining bytes? */ 462 " addi %[count],%[count],0x1;" 463 " mtctr %[count];" 464 "3: bdz 10f;" /* while count */ 465 " mtpid %[ctx];sync;" 466 " lbz %[tmp],0(%[udaddr]);" /* Load user byte */ 467 " addi %[udaddr],%[udaddr],0x1;" /* next udaddr byte */ 468 " sync; isync;" 469 " mtpid %[pid]; sync;" 470 " stb %[tmp],0(%[kaddr]);" /* Store kernel byte */ 471 " dcbf 0,%[kaddr];" /* flush cache */ 472 " addi %[kaddr],%[kaddr],0x1;" 473 " sync; isync;" 474 " b 3b;" 475 "10:mtpid %[pid]; mtmsr %[msr]; sync; isync;" /* Restore PID and MSR */ 476 : [msr] "=&r" (msr), [pid] "=&r" (pid), [tmp] "=&r" (tmp) 477 : [udaddr] "b" (udaddr), [ctx] "b" (ctx), [kaddr] "b" (kaddr), [len] "b" (len), [count] "b" (count)); 478 479 curpcb->pcb_onfault = 0; 480 return 0; 481 } 482 483 static int 484 bigcopyin(const void *udaddr, void *kaddr, size_t len) 485 { 486 const char *up; 487 char *kp = kaddr; 488 struct lwp *l = curlwp; 489 struct proc *p; 490 int error; 491 492 if (!l) { 493 return EFAULT; 494 } 495 496 p = l->l_proc; 497 498 /* 499 * Stolen from physio(): 500 */ 501 error = uvm_vslock(p->p_vmspace, __UNCONST(udaddr), len, VM_PROT_READ); 502 if (error) { 503 return EFAULT; 504 } 505 up = (char *)vmaprange(p, (vaddr_t)udaddr, len, VM_PROT_READ); 506 507 memcpy(kp, up, len); 508 vunmaprange((vaddr_t)up, len); 509 uvm_vsunlock(p->p_vmspace, __UNCONST(udaddr), len); 510 511 return 0; 512 } 513 514 int 515 copyout(const void *kaddr, void *udaddr, size_t len) 516 { 517 struct pmap *pm = curproc->p_vmspace->vm_map.pmap; 518 int msr, pid, tmp, ctx, count=0; 519 struct faultbuf env; 520 521 /* For big copies use more efficient routine */ 522 if (len > 1024) 523 return (bigcopyout(kaddr, udaddr, len)); 524 525 if (setfault(&env)) { 526 curpcb->pcb_onfault = 0; 527 return EFAULT; 528 } 529 530 if (!(ctx = pm->pm_ctx)) { 531 /* No context -- assign it one */ 532 ctx_alloc(pm); 533 ctx = pm->pm_ctx; 534 } 535 536 __asm volatile( 537 " mfmsr %[msr];" /* Save MSR */ \ 538 " li %[pid],0x20; " \ 539 " andc %[pid],%[msr],%[pid]; mtmsr %[pid];" /* Disable IMMU */ \ 540 " mfpid %[pid];" /* Save old PID */ \ 541 " sync; isync;" 542 543 " srwi. %[count],%[len],0x2;" /* How many words? */ 544 " beq- 2f;" /* No words. Go do bytes */ 545 " mtctr %[count];" 546 "1: mtpid %[pid];sync;" 547 " lswi %[tmp],%[kaddr],4;" /* Load kernel word */ 548 " addi %[kaddr],%[kaddr],0x4;" /* next kaddr word */ 549 " sync; isync;" 550 " mtpid %[ctx]; sync;" 551 " stswi %[tmp],%[udaddr],4;" /* Store user word */ 552 " dcbf 0,%[udaddr];" /* flush cache */ 553 " addi %[udaddr],%[udaddr],0x4;" /* next udaddr word */ 554 " sync; isync;" 555 " bdnz 1b;" /* repeat */ 556 557 "2: andi. %[count],%[len],0x3;" /* How many remaining bytes? */ 558 " addi %[count],%[count],0x1;" 559 " mtctr %[count];" 560 "3: bdz 10f;" /* while count */ 561 " mtpid %[pid];sync;" 562 " lbz %[tmp],0(%[kaddr]);" /* Load kernel byte */ 563 " addi %[kaddr],%[kaddr],0x1;" /* next kaddr byte */ 564 " sync; isync;" 565 " mtpid %[ctx]; sync;" 566 " stb %[tmp],0(%[udaddr]);" /* Store user byte */ 567 " dcbf 0,%[udaddr];" /* flush cache */ 568 " addi %[udaddr],%[udaddr],0x1;" 569 " sync; isync;" 570 " b 3b;" 571 "10:mtpid %[pid]; mtmsr %[msr]; sync; isync;" /* Restore PID and MSR */ 572 : [msr] "=&r" (msr), [pid] "=&r" (pid), [tmp] "=&r" (tmp) 573 : [udaddr] "b" (udaddr), [ctx] "b" (ctx), [kaddr] "b" (kaddr), [len] "b" (len), [count] "b" (count)); 574 575 curpcb->pcb_onfault = 0; 576 return 0; 577 } 578 579 static int 580 bigcopyout(const void *kaddr, void *udaddr, size_t len) 581 { 582 char *up; 583 const char *kp = (const char *)kaddr; 584 struct lwp *l = curlwp; 585 struct proc *p; 586 int error; 587 588 if (!l) { 589 return EFAULT; 590 } 591 592 p = l->l_proc; 593 594 /* 595 * Stolen from physio(): 596 */ 597 error = uvm_vslock(p->p_vmspace, udaddr, len, VM_PROT_WRITE); 598 if (error) { 599 return EFAULT; 600 } 601 up = (char *)vmaprange(p, (vaddr_t)udaddr, len, 602 VM_PROT_READ | VM_PROT_WRITE); 603 604 memcpy(up, kp, len); 605 vunmaprange((vaddr_t)up, len); 606 uvm_vsunlock(p->p_vmspace, udaddr, len); 607 608 return 0; 609 } 610 611 /* 612 * kcopy(const void *src, void *dst, size_t len); 613 * 614 * Copy len bytes from src to dst, aborting if we encounter a fatal 615 * page fault. 616 * 617 * kcopy() _must_ save and restore the old fault handler since it is 618 * called by uiomove(), which may be in the path of servicing a non-fatal 619 * page fault. 620 */ 621 int 622 kcopy(const void *src, void *dst, size_t len) 623 { 624 struct faultbuf env, *oldfault; 625 626 oldfault = curpcb->pcb_onfault; 627 if (setfault(&env)) { 628 curpcb->pcb_onfault = oldfault; 629 return EFAULT; 630 } 631 632 memcpy(dst, src, len); 633 634 curpcb->pcb_onfault = oldfault; 635 return 0; 636 } 637 638 int 639 badaddr(void *addr, size_t size) 640 { 641 642 return badaddr_read(addr, size, NULL); 643 } 644 645 int 646 badaddr_read(void *addr, size_t size, int *rptr) 647 { 648 struct faultbuf env; 649 int x; 650 651 /* Get rid of any stale machine checks that have been waiting. */ 652 __asm volatile ("sync; isync"); 653 654 if (setfault(&env)) { 655 curpcb->pcb_onfault = 0; 656 __asm volatile ("sync"); 657 return 1; 658 } 659 660 __asm volatile ("sync"); 661 662 switch (size) { 663 case 1: 664 x = *(volatile int8_t *)addr; 665 break; 666 case 2: 667 x = *(volatile int16_t *)addr; 668 break; 669 case 4: 670 x = *(volatile int32_t *)addr; 671 break; 672 default: 673 panic("badaddr: invalid size (%d)", size); 674 } 675 676 /* Make sure we took the machine check, if we caused one. */ 677 __asm volatile ("sync; isync"); 678 679 curpcb->pcb_onfault = 0; 680 __asm volatile ("sync"); /* To be sure. */ 681 682 /* Use the value to avoid reorder. */ 683 if (rptr) 684 *rptr = x; 685 686 return 0; 687 } 688 689 /* 690 * For now, this only deals with the particular unaligned access case 691 * that gcc tends to generate. Eventually it should handle all of the 692 * possibilities that can happen on a 32-bit PowerPC in big-endian mode. 693 */ 694 695 static int 696 fix_unaligned(struct lwp *l, struct trapframe *frame) 697 { 698 699 return -1; 700 } 701 702 /* 703 * Start a new LWP 704 */ 705 void 706 startlwp(void *arg) 707 { 708 int err; 709 ucontext_t *uc = arg; 710 struct lwp *l = curlwp; 711 712 err = cpu_setmcontext(l, &uc->uc_mcontext, uc->uc_flags); 713 #if DIAGNOSTIC 714 if (err) { 715 printf("Error %d from cpu_setmcontext.", err); 716 } 717 #endif 718 pool_put(&lwp_uc_pool, uc); 719 720 upcallret(l); 721 } 722 723 /* 724 * XXX This is a terrible name. 725 */ 726 void 727 upcallret(struct lwp *l) 728 { 729 730 /* Invoke MI userret code */ 731 mi_userret(l); 732 } 733