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