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