1 /* $NetBSD: trap.c,v 1.168 2026/01/09 22:54:34 jmcneill Exp $ */ 2 3 /* 4 * Copyright (C) 1995, 1996 Wolfgang Solfrank. 5 * Copyright (C) 1995, 1996 TooLs GmbH. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by TooLs GmbH. 19 * 4. The name of TooLs GmbH may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 28 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #define __UFETCHSTORE_PRIVATE 35 #define __UCAS_PRIVATE 36 37 #include <sys/cdefs.h> 38 __KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.168 2026/01/09 22:54:34 jmcneill Exp $"); 39 40 #ifdef _KERNEL_OPT 41 #include "opt_altivec.h" 42 #include "opt_ddb.h" 43 #include "opt_ppcarch.h" 44 #endif 45 46 #include <sys/param.h> 47 48 #include <sys/proc.h> 49 #include <sys/ras.h> 50 #include <sys/reboot.h> 51 #include <sys/systm.h> 52 #include <sys/kauth.h> 53 #include <sys/cpu.h> 54 55 #include <uvm/uvm_extern.h> 56 57 #include <dev/cons.h> 58 59 #include <powerpc/altivec.h> 60 #include <powerpc/db_machdep.h> 61 #include <powerpc/fpu.h> 62 #include <powerpc/frame.h> 63 #include <powerpc/instr.h> 64 #include <powerpc/pcb.h> 65 #include <powerpc/pmap.h> 66 #include <powerpc/trap.h> 67 #include <powerpc/userret.h> 68 69 #include <powerpc/spr.h> 70 #include <powerpc/oea/spr.h> 71 72 static int emulate_privileged(struct lwp *, struct trapframe *); 73 static int fix_unaligned(struct lwp *, struct trapframe *); 74 #ifdef PPC_IBMESPRESSO 75 static int fix_stwcx(struct lwp *, struct trapframe *); 76 #endif 77 static inline vaddr_t setusr(vaddr_t, size_t *); 78 static inline void unsetusr(void); 79 80 void trap(struct trapframe *); /* Called from locore / trap_subr */ 81 /* Why are these not defined in a header? */ 82 int badaddr(void *, size_t); 83 int badaddr_read(void *, size_t, int *); 84 85 struct dsi_info { 86 uint16_t indicator; 87 uint16_t flags; 88 }; 89 90 static const struct dsi_info* get_dsi_info(register_t); 91 92 void 93 trap(struct trapframe *tf) 94 { 95 struct cpu_info * const ci = curcpu(); 96 struct lwp * const l = curlwp; 97 struct proc * const p = l->l_proc; 98 struct pcb * const pcb = curpcb; 99 struct vm_map *map; 100 ksiginfo_t ksi; 101 const bool usertrap = (tf->tf_srr1 & PSL_PR); 102 int type = tf->tf_exc; 103 int ftype, rv; 104 105 ci->ci_ev_traps.ev_count++; 106 107 KASSERTMSG(!usertrap || tf == l->l_md.md_utf, 108 "trap: tf=%p is invalid: trapframe(%p)=%p", tf, l, l->l_md.md_utf); 109 110 if (usertrap) { 111 type |= EXC_USER; 112 #ifdef DIAGNOSTIC 113 if (l == NULL || p == NULL) 114 panic("trap: user trap %d with lwp = %p, proc = %p", 115 type, l, p); 116 #endif 117 } 118 119 ci->ci_data.cpu_ntrap++; 120 121 switch (type) { 122 case EXC_RUNMODETRC|EXC_USER: 123 /* FALLTHROUGH */ 124 case EXC_TRC|EXC_USER: 125 tf->tf_srr1 &= ~PSL_SE; 126 if (p->p_raslist == NULL || 127 ras_lookup(p, (void *)tf->tf_srr0) == (void *) -1) { 128 KSI_INIT_TRAP(&ksi); 129 ksi.ksi_signo = SIGTRAP; 130 ksi.ksi_trap = EXC_TRC; 131 ksi.ksi_addr = (void *)tf->tf_srr0; 132 ksi.ksi_code = TRAP_TRACE; 133 (*p->p_emul->e_trapsignal)(l, &ksi); 134 } 135 break; 136 case EXC_DSI: { 137 struct faultbuf * const fb = pcb->pcb_onfault; 138 vaddr_t va = tf->tf_dar; 139 140 ci->ci_ev_kdsi.ev_count++; 141 142 if ((va >> ADDR_SR_SHFT) == pcb->pcb_kmapsr) { 143 va &= ADDR_PIDX | ADDR_POFF; 144 va |= pcb->pcb_umapsr << ADDR_SR_SHFT; 145 map = &p->p_vmspace->vm_map; 146 } 147 #if defined(DIAGNOSTIC) && !defined(PPC_OEA64) 148 else if (__predict_false((va >> ADDR_SR_SHFT) == USER_SR)) { 149 printf("trap: kernel %s DSI trap @ %#lx by %#lx" 150 " (DSISR %#x): USER_SR unset\n", 151 (tf->tf_dsisr & DSISR_STORE) 152 ? "write" : "read", 153 va, tf->tf_srr0, tf->tf_dsisr); 154 goto brain_damage2; 155 } 156 #endif 157 else { 158 map = kernel_map; 159 } 160 161 #ifdef PPC_OEA64 162 if ((tf->tf_dsisr & DSISR_NOTFOUND) && 163 vm_map_pmap(map)->pm_ste_evictions > 0 && 164 pmap_ste_spill(vm_map_pmap(map), trunc_page(va), false)) 165 return; 166 #endif 167 if ((tf->tf_dsisr & DSISR_NOTFOUND) && 168 vm_map_pmap(map)->pm_evictions > 0 && 169 pmap_pte_spill(vm_map_pmap(map), trunc_page(va), false)) 170 return; 171 172 /* 173 * Only query UVM if no interrupts are active. 174 */ 175 if (ci->ci_idepth < 0) { 176 if (tf->tf_dsisr & DSISR_STORE) 177 ftype = VM_PROT_WRITE; 178 else 179 ftype = VM_PROT_READ; 180 181 pcb->pcb_onfault = NULL; 182 rv = uvm_fault(map, trunc_page(va), ftype); 183 pcb->pcb_onfault = fb; 184 185 if (map != kernel_map) { 186 /* 187 * Record any stack growth... 188 */ 189 if (rv == 0) 190 uvm_grow(p, trunc_page(va)); 191 } 192 if (rv == 0) 193 return; 194 if (rv == EACCES) 195 rv = EFAULT; 196 } else { 197 /* 198 * Note that this implies that access to the USER 199 * segment is not allowed in interrupt context. 200 */ 201 rv = EFAULT; 202 } 203 if (fb != NULL) { 204 tf->tf_srr0 = fb->fb_pc; 205 tf->tf_cr = fb->fb_cr; 206 tf->tf_fixreg[1] = fb->fb_sp; 207 tf->tf_fixreg[2] = fb->fb_r2; 208 tf->tf_fixreg[3] = rv; 209 memcpy(&tf->tf_fixreg[13], fb->fb_fixreg, 210 sizeof(fb->fb_fixreg)); 211 return; 212 } 213 printf("trap: kernel %s DSI trap @ %#lx by %#lx (DSISR %#x, err" 214 "=%d), lr %#lx\n", (tf->tf_dsisr & DSISR_STORE) ? "write" : "read", 215 va, tf->tf_srr0, tf->tf_dsisr, rv, tf->tf_lr); 216 goto brain_damage2; 217 } 218 case EXC_DSI|EXC_USER: 219 ci->ci_ev_udsi.ev_count++; 220 if (tf->tf_dsisr & DSISR_STORE) 221 ftype = VM_PROT_WRITE; 222 else 223 ftype = VM_PROT_READ; 224 225 /* 226 * Try to spill an evicted pte into the page table 227 * if this wasn't a protection fault and the pmap 228 * has some evicted pte's. 229 */ 230 map = &p->p_vmspace->vm_map; 231 #ifdef PPC_OEA64 232 if ((tf->tf_dsisr & DSISR_NOTFOUND) && 233 vm_map_pmap(map)->pm_ste_evictions > 0 && 234 pmap_ste_spill(vm_map_pmap(map), trunc_page(tf->tf_dar), 235 false)) { 236 break; 237 } 238 #endif 239 240 if ((tf->tf_dsisr & DSISR_NOTFOUND) && 241 vm_map_pmap(map)->pm_evictions > 0 && 242 pmap_pte_spill(vm_map_pmap(map), trunc_page(tf->tf_dar), 243 false)) { 244 break; 245 } 246 247 KASSERT(pcb->pcb_onfault == NULL); 248 rv = uvm_fault(map, trunc_page(tf->tf_dar), ftype); 249 if (rv == 0) { 250 /* 251 * Record any stack growth... 252 */ 253 uvm_grow(p, trunc_page(tf->tf_dar)); 254 break; 255 } 256 ci->ci_ev_udsi_fatal.ev_count++; 257 if (cpu_printfataltraps 258 && (p->p_slflag & PSL_TRACED) == 0 259 && !sigismember(&p->p_sigctx.ps_sigcatch, SIGSEGV)) { 260 printf("trap: pid %d.%d (%s): user %s DSI trap @ %#lx " 261 "by %#lx (DSISR %#x, err=%d)\n", 262 p->p_pid, l->l_lid, p->p_comm, 263 (tf->tf_dsisr & DSISR_STORE) ? "write" : "read", 264 tf->tf_dar, tf->tf_srr0, tf->tf_dsisr, rv); 265 } 266 KSI_INIT_TRAP(&ksi); 267 ksi.ksi_trap = EXC_DSI; 268 ksi.ksi_addr = (void *)tf->tf_dar; 269 vm_signal: 270 switch (rv) { 271 case EINVAL: 272 ksi.ksi_signo = SIGBUS; 273 ksi.ksi_code = BUS_ADRERR; 274 break; 275 case EACCES: 276 ksi.ksi_signo = SIGSEGV; 277 ksi.ksi_code = SEGV_ACCERR; 278 break; 279 case ENOMEM: 280 ksi.ksi_signo = SIGKILL; 281 printf("UVM: pid %d.%d (%s), uid %d killed: " 282 "out of swap\n", p->p_pid, l->l_lid, p->p_comm, 283 l->l_cred ? kauth_cred_geteuid(l->l_cred) : -1); 284 break; 285 default: 286 ksi.ksi_signo = SIGSEGV; 287 ksi.ksi_code = SEGV_MAPERR; 288 break; 289 } 290 (*p->p_emul->e_trapsignal)(l, &ksi); 291 break; 292 293 case EXC_ISI: 294 ci->ci_ev_kisi.ev_count++; 295 296 printf("trap: kernel ISI by %#lx (SRR1 %#lx), lr: %#lx\n", 297 tf->tf_srr0, tf->tf_srr1, tf->tf_lr); 298 goto brain_damage2; 299 300 case EXC_ISI|EXC_USER: 301 ci->ci_ev_isi.ev_count++; 302 303 /* 304 * Try to spill an evicted pte into the page table 305 * if this wasn't a protection fault and the pmap 306 * has some evicted pte's. 307 */ 308 map = &p->p_vmspace->vm_map; 309 #ifdef PPC_OEA64 310 if (vm_map_pmap(map)->pm_ste_evictions > 0 && 311 pmap_ste_spill(vm_map_pmap(map), trunc_page(tf->tf_srr0), 312 true)) { 313 break; 314 } 315 #endif 316 317 if (vm_map_pmap(map)->pm_evictions > 0 && 318 pmap_pte_spill(vm_map_pmap(map), trunc_page(tf->tf_srr0), 319 true)) { 320 break; 321 } 322 323 ftype = VM_PROT_EXECUTE; 324 KASSERT(pcb->pcb_onfault == NULL); 325 rv = uvm_fault(map, trunc_page(tf->tf_srr0), ftype); 326 if (rv == 0) { 327 break; 328 } 329 ci->ci_ev_isi_fatal.ev_count++; 330 if (cpu_printfataltraps 331 && (p->p_slflag & PSL_TRACED) == 0 332 && !sigismember(&p->p_sigctx.ps_sigcatch, SIGSEGV)) { 333 printf("trap: pid %d.%d (%s): user ISI trap @ %#lx " 334 "(SRR1=%#lx)\n", p->p_pid, l->l_lid, p->p_comm, 335 tf->tf_srr0, tf->tf_srr1); 336 } 337 KSI_INIT_TRAP(&ksi); 338 ksi.ksi_trap = EXC_ISI; 339 ksi.ksi_addr = (void *)tf->tf_srr0; 340 goto vm_signal; 341 342 case EXC_FPU|EXC_USER: 343 ci->ci_ev_fpu.ev_count++; 344 fpu_load(); 345 break; 346 347 case EXC_AST|EXC_USER: 348 cpu_ast(l, ci); 349 break; 350 351 case EXC_ALI|EXC_USER: 352 ci->ci_ev_ali.ev_count++; 353 if (fix_unaligned(l, tf) != 0) { 354 ci->ci_ev_ali_fatal.ev_count++; 355 if (cpu_printfataltraps 356 && (p->p_slflag & PSL_TRACED) == 0 357 && !sigismember(&p->p_sigctx.ps_sigcatch, SIGBUS)) { 358 printf("trap: pid %d.%d (%s): user ALI trap @ " 359 "%#lx by %#lx (DSISR %#x)\n", 360 p->p_pid, l->l_lid, p->p_comm, 361 tf->tf_dar, tf->tf_srr0, tf->tf_dsisr); 362 } 363 KSI_INIT_TRAP(&ksi); 364 ksi.ksi_signo = SIGBUS; 365 ksi.ksi_trap = EXC_ALI; 366 ksi.ksi_addr = (void *)tf->tf_dar; 367 ksi.ksi_code = BUS_ADRALN; 368 (*p->p_emul->e_trapsignal)(l, &ksi); 369 } else 370 tf->tf_srr0 += 4; 371 break; 372 373 case EXC_PERF|EXC_USER: 374 /* Not really, but needed due to how trap_subr.S works */ 375 case EXC_VEC|EXC_USER: 376 ci->ci_ev_vec.ev_count++; 377 #ifdef ALTIVEC 378 vec_load(); 379 break; 380 #else 381 if (cpu_printfataltraps 382 && (p->p_slflag & PSL_TRACED) == 0 383 && !sigismember(&p->p_sigctx.ps_sigcatch, SIGILL)) { 384 printf("trap: pid %d.%d (%s): user VEC trap @ %#lx " 385 "(SRR1=%#lx)\n", 386 p->p_pid, l->l_lid, p->p_comm, 387 tf->tf_srr0, tf->tf_srr1); 388 } 389 KSI_INIT_TRAP(&ksi); 390 ksi.ksi_signo = SIGILL; 391 ksi.ksi_trap = EXC_PGM; 392 ksi.ksi_addr = (void *)tf->tf_srr0; 393 ksi.ksi_code = ILL_ILLOPC; 394 (*p->p_emul->e_trapsignal)(l, &ksi); 395 break; 396 #endif 397 case EXC_MCHK|EXC_USER: 398 ci->ci_ev_umchk.ev_count++; 399 if (cpu_printfataltraps 400 && (p->p_slflag & PSL_TRACED) == 0 401 && !sigismember(&p->p_sigctx.ps_sigcatch, SIGBUS)) { 402 printf("trap: pid %d (%s): user MCHK trap @ %#lx " 403 "(SRR1=%#lx)\n", 404 p->p_pid, p->p_comm, tf->tf_srr0, tf->tf_srr1); 405 } 406 KSI_INIT_TRAP(&ksi); 407 ksi.ksi_signo = SIGBUS; 408 ksi.ksi_trap = EXC_MCHK; 409 ksi.ksi_addr = (void *)tf->tf_srr0; 410 ksi.ksi_code = BUS_OBJERR; 411 (*p->p_emul->e_trapsignal)(l, &ksi); 412 break; 413 414 case EXC_PGM|EXC_USER: 415 ci->ci_ev_pgm.ev_count++; 416 if (tf->tf_srr1 & 0x00020000) { /* Bit 14 is set if trap */ 417 if (p->p_raslist == NULL || 418 ras_lookup(p, (void *)tf->tf_srr0) == (void *) -1) { 419 KSI_INIT_TRAP(&ksi); 420 ksi.ksi_signo = SIGTRAP; 421 ksi.ksi_trap = EXC_PGM; 422 ksi.ksi_addr = (void *)tf->tf_srr0; 423 ksi.ksi_code = TRAP_BRKPT; 424 (*p->p_emul->e_trapsignal)(l, &ksi); 425 } else { 426 /* skip the trap instruction */ 427 tf->tf_srr0 += 4; 428 } 429 } else { 430 KSI_INIT_TRAP(&ksi); 431 ksi.ksi_signo = SIGILL; 432 ksi.ksi_trap = EXC_PGM; 433 ksi.ksi_addr = (void *)tf->tf_srr0; 434 if (tf->tf_srr1 & 0x100000) { 435 ksi.ksi_signo = SIGFPE; 436 ksi.ksi_code = fpu_get_fault_code(); 437 } else if (tf->tf_srr1 & 0x40000) { 438 if (emulate_privileged(l, tf)) { 439 tf->tf_srr0 += 4; 440 break; 441 } 442 ksi.ksi_code = ILL_PRVOPC; 443 } else { 444 #ifdef PPC_IBMESPRESSO 445 if (fix_stwcx(l, tf)) { 446 tf->tf_srr0 += 4; 447 break; 448 } 449 #endif 450 ksi.ksi_code = ILL_ILLOPC; 451 } 452 if (cpu_printfataltraps 453 && (p->p_slflag & PSL_TRACED) == 0 454 && !sigismember(&p->p_sigctx.ps_sigcatch, 455 ksi.ksi_signo)) { 456 printf("trap: pid %d.%d (%s): user PGM trap @" 457 " %#lx (SRR1=%#lx)\n", p->p_pid, l->l_lid, 458 p->p_comm, tf->tf_srr0, tf->tf_srr1); 459 } 460 (*p->p_emul->e_trapsignal)(l, &ksi); 461 } 462 break; 463 464 case EXC_MCHK: { 465 struct faultbuf *fb; 466 467 if ((fb = pcb->pcb_onfault) != NULL) { 468 tf->tf_srr0 = fb->fb_pc; 469 tf->tf_fixreg[1] = fb->fb_sp; 470 tf->tf_fixreg[2] = fb->fb_r2; 471 tf->tf_fixreg[3] = EFAULT; 472 tf->tf_cr = fb->fb_cr; 473 memcpy(&tf->tf_fixreg[13], fb->fb_fixreg, 474 sizeof(fb->fb_fixreg)); 475 return; 476 } 477 printf("trap: pid %d.%d (%s): kernel MCHK trap @" 478 " %#lx (SRR1=%#lx)\n", p->p_pid, l->l_lid, 479 p->p_comm, tf->tf_srr0, tf->tf_srr1); 480 goto brain_damage2; 481 } 482 case EXC_ALI: 483 printf("trap: pid %d.%d (%s): kernel ALI trap @ %#lx by %#lx " 484 "(DSISR %#x)\n", p->p_pid, l->l_lid, p->p_comm, 485 tf->tf_dar, tf->tf_srr0, tf->tf_dsisr); 486 goto brain_damage2; 487 case EXC_PGM: 488 printf("trap: pid %d.%d (%s): kernel PGM trap @" 489 " %#lx (SRR1=%#lx)\n", p->p_pid, l->l_lid, 490 p->p_comm, tf->tf_srr0, tf->tf_srr1); 491 goto brain_damage2; 492 493 default: 494 printf("trap type %x at %lx\n", type, tf->tf_srr0); 495 brain_damage2: 496 #if defined(DDB) && 0 /* XXX */ 497 if (kdb_trap(type, tf)) 498 return; 499 #endif 500 #ifdef TRAP_PANICWAIT 501 printf("Press a key to panic.\n"); 502 cnpollc(true); 503 cngetc(); 504 cnpollc(false); 505 #endif 506 panic("trap"); 507 } 508 userret(l, tf); 509 } 510 511 #ifdef _LP64 512 static inline vaddr_t 513 setusr(vaddr_t uva, size_t *len_p) 514 { 515 *len_p = SEGMENT_LENGTH - (uva & ~SEGMENT_MASK); 516 return pmap_setusr(uva) + (uva & ~SEGMENT_MASK); 517 } 518 static void 519 unsetusr(void) 520 { 521 pmap_unsetusr(); 522 } 523 #else 524 static inline vaddr_t 525 setusr(vaddr_t uva, size_t *len_p) 526 { 527 struct pcb *pcb = curpcb; 528 vaddr_t p; 529 KASSERT(pcb != NULL); 530 KASSERT(pcb->pcb_kmapsr == 0); 531 pcb->pcb_kmapsr = USER_SR; 532 pcb->pcb_umapsr = uva >> ADDR_SR_SHFT; 533 *len_p = SEGMENT_LENGTH - (uva & ~SEGMENT_MASK); 534 p = (USER_SR << ADDR_SR_SHFT) + (uva & ~SEGMENT_MASK); 535 __asm volatile ("isync; mtsr %0,%1; isync" 536 :: "n"(USER_SR), "r"(pcb->pcb_pm->pm_sr[pcb->pcb_umapsr])); 537 return p; 538 } 539 540 static void 541 unsetusr(void) 542 { 543 curpcb->pcb_kmapsr = 0; 544 __asm volatile ("isync; mtsr %0,%1; isync" 545 :: "n"(USER_SR), "r"(EMPTY_SEGMENT)); 546 } 547 #endif 548 549 #define UFETCH(sz) \ 550 int \ 551 _ufetch_ ## sz(const uint ## sz ## _t *uaddr, uint ## sz ## _t *valp) \ 552 { \ 553 struct faultbuf env; \ 554 vaddr_t p; \ 555 size_t seglen; \ 556 int rv; \ 557 \ 558 if ((rv = setfault(&env)) != 0) { \ 559 goto out; \ 560 } \ 561 p = setusr((vaddr_t)uaddr, &seglen); \ 562 *valp = *(const volatile uint ## sz ## _t *)p; \ 563 out: \ 564 unsetusr(); \ 565 curpcb->pcb_onfault = 0; \ 566 return rv; \ 567 } 568 569 UFETCH(8) 570 UFETCH(16) 571 UFETCH(32) 572 #ifdef _LP64 573 UFETCH(64) 574 #endif 575 576 #undef UFETCH 577 578 #define USTORE(sz) \ 579 int \ 580 _ustore_ ## sz(uint ## sz ## _t *uaddr, uint ## sz ## _t val) \ 581 { \ 582 struct faultbuf env; \ 583 vaddr_t p; \ 584 size_t seglen; \ 585 int rv; \ 586 \ 587 if ((rv = setfault(&env)) != 0) { \ 588 goto out; \ 589 } \ 590 p = setusr((vaddr_t)uaddr, &seglen); \ 591 *(volatile uint ## sz ## _t *)p = val; \ 592 out: \ 593 unsetusr(); \ 594 curpcb->pcb_onfault = 0; \ 595 return rv; \ 596 } 597 598 USTORE(8) 599 USTORE(16) 600 USTORE(32) 601 #ifdef _LP64 602 USTORE(64) 603 #endif 604 605 #undef USTORE 606 607 int 608 copyin(const void *udaddr, void *kaddr, size_t len) 609 { 610 vaddr_t uva = (vaddr_t) udaddr; 611 char *kp = kaddr; 612 struct faultbuf env; 613 int rv; 614 615 if ((rv = setfault(&env)) != 0) { 616 unsetusr(); 617 goto out; 618 } 619 620 while (len > 0) { 621 size_t seglen; 622 vaddr_t p = setusr(uva, &seglen); 623 if (seglen > len) 624 seglen = len; 625 memcpy(kp, (const char *) p, seglen); 626 uva += seglen; 627 kp += seglen; 628 len -= seglen; 629 unsetusr(); 630 } 631 632 out: 633 curpcb->pcb_onfault = 0; 634 return rv; 635 } 636 637 int 638 copyout(const void *kaddr, void *udaddr, size_t len) 639 { 640 const char *kp = kaddr; 641 vaddr_t uva = (vaddr_t) udaddr; 642 struct faultbuf env; 643 int rv; 644 645 if ((rv = setfault(&env)) != 0) { 646 unsetusr(); 647 goto out; 648 } 649 650 while (len > 0) { 651 size_t seglen; 652 vaddr_t p = setusr(uva, &seglen); 653 if (seglen > len) 654 seglen = len; 655 memcpy((char *)p, kp, seglen); 656 uva += seglen; 657 kp += seglen; 658 len -= seglen; 659 unsetusr(); 660 } 661 662 out: 663 curpcb->pcb_onfault = 0; 664 return rv; 665 } 666 667 /* 668 * kcopy(const void *src, void *dst, size_t len); 669 * 670 * Copy len bytes from src to dst, aborting if we encounter a fatal 671 * page fault. 672 * 673 * kcopy() _must_ save and restore the old fault handler since it is 674 * called by uiomove(), which may be in the path of servicing a non-fatal 675 * page fault. 676 */ 677 int 678 kcopy(const void *src, void *dst, size_t len) 679 { 680 struct faultbuf env, *oldfault; 681 int rv; 682 683 oldfault = curpcb->pcb_onfault; 684 685 if ((rv = setfault(&env)) == 0) 686 memcpy(dst, src, len); 687 688 curpcb->pcb_onfault = oldfault; 689 return rv; 690 } 691 692 #if 0 /* XXX CPU configuration spaghetti */ 693 int 694 _ucas_32(volatile uint32_t *uptr, uint32_t old, uint32_t new, uint32_t *ret) 695 { 696 extern int do_ucas_32(volatile int32_t *, int32_t, int32_t, int32_t *); 697 vaddr_t uva = (vaddr_t)uptr; 698 vaddr_t p; 699 struct faultbuf env; 700 size_t seglen; 701 int rv; 702 703 if ((rv = setfault(&env)) != 0) { 704 unsetusr(); 705 goto out; 706 } 707 p = setusr(uva, &seglen); 708 KASSERT(seglen >= sizeof(*uptr)); 709 do_ucas_32((void *)p, old, new, ret); 710 unsetusr(); 711 712 out: 713 curpcb->pcb_onfault = 0; 714 return rv; 715 } 716 #endif 717 718 int 719 badaddr(void *addr, size_t size) 720 { 721 return badaddr_read(addr, size, NULL); 722 } 723 724 int 725 badaddr_read(void *addr, size_t size, int *rptr) 726 { 727 struct faultbuf env; 728 int x; 729 730 /* Get rid of any stale machine checks that have been waiting. */ 731 __asm volatile ("sync; isync"); 732 733 if (setfault(&env)) { 734 curpcb->pcb_onfault = 0; 735 __asm volatile ("sync"); 736 return 1; 737 } 738 739 __asm volatile ("sync"); 740 741 switch (size) { 742 case 1: 743 x = *(volatile int8_t *)addr; 744 break; 745 case 2: 746 x = *(volatile int16_t *)addr; 747 break; 748 case 4: 749 x = *(volatile int32_t *)addr; 750 break; 751 default: 752 panic("badaddr: invalid size (%lu)", (u_long) size); 753 } 754 755 /* Make sure we took the machine check, if we caused one. */ 756 __asm volatile ("sync; isync"); 757 758 curpcb->pcb_onfault = 0; 759 __asm volatile ("sync"); /* To be sure. */ 760 761 /* Use the value to avoid reorder. */ 762 if (rptr) 763 *rptr = x; 764 765 return 0; 766 } 767 768 /* 769 * For now, this only deals with the particular unaligned access case 770 * that gcc tends to generate. Eventually it should handle all of the 771 * possibilities that can happen on a 32-bit PowerPC in big-endian mode. 772 */ 773 774 static int 775 fix_unaligned(struct lwp *l, struct trapframe *tf) 776 { 777 const struct dsi_info* dsi = get_dsi_info(tf->tf_dsisr); 778 779 if ( !dsi ) 780 return -1; 781 782 switch (dsi->indicator) { 783 case EXC_ALI_DCBZ: 784 { 785 /* 786 * The DCBZ (Data Cache Block Zero) instruction 787 * gives an alignment fault if used on non-cacheable 788 * memory. We handle the fault mainly for the 789 * case when we are running with the cache disabled 790 * for debugging. 791 */ 792 static char zeroes[MAXCACHELINESIZE]; 793 int error; 794 error = copyout(zeroes, 795 (void *)(tf->tf_dar & -curcpu()->ci_ci.dcache_line_size), 796 curcpu()->ci_ci.dcache_line_size); 797 if (error) 798 return -1; 799 return 0; 800 } 801 break; 802 803 case EXC_ALI_LFD: 804 case EXC_ALI_LFDU: 805 case EXC_ALI_LDFX: 806 case EXC_ALI_LFDUX: 807 { 808 struct pcb * const pcb = lwp_getpcb(l); 809 const int reg = EXC_ALI_RST(tf->tf_dsisr); 810 const int a_reg = EXC_ALI_RA(tf->tf_dsisr); 811 uint64_t * const fpreg = &pcb->pcb_fpu.fpreg[reg]; 812 register_t* a_reg_addr = &tf->tf_fixreg[a_reg]; 813 814 /* 815 * Juggle the FPU to ensure that we've initialized 816 * the FPRs, and that their current state is in 817 * the PCB. 818 */ 819 820 KASSERT(l == curlwp); 821 if (!fpu_used_p(l)) { 822 memset(&pcb->pcb_fpu, 0, sizeof(pcb->pcb_fpu)); 823 fpu_mark_used(l); 824 } else { 825 fpu_save(l); 826 } 827 828 if (copyin((void *)tf->tf_dar, fpreg, 829 sizeof(double)) != 0) 830 return -1; 831 832 if (dsi->flags & DSI_OP_INDEXED) { 833 /* do nothing */ 834 } 835 836 if (dsi->flags & DSI_OP_UPDATE) { 837 /* this is valid for 601, but to simplify logic don't pass for any */ 838 if (a_reg == 0) 839 return -1; 840 else 841 *a_reg_addr = tf->tf_dar; 842 } 843 844 fpu_load(); 845 return 0; 846 } 847 break; 848 849 case EXC_ALI_STFD: 850 case EXC_ALI_STFDU: 851 case EXC_ALI_STFDX: 852 case EXC_ALI_STFDUX: 853 { 854 struct pcb * const pcb = lwp_getpcb(l); 855 const int reg = EXC_ALI_RST(tf->tf_dsisr); 856 const int a_reg = EXC_ALI_RA(tf->tf_dsisr); 857 uint64_t * const fpreg = &pcb->pcb_fpu.fpreg[reg]; 858 register_t* a_reg_addr = &tf->tf_fixreg[a_reg]; 859 860 /* 861 * Juggle the FPU to ensure that we've initialized 862 * the FPRs, and that their current state is in 863 * the PCB. 864 */ 865 866 KASSERT(l == curlwp); 867 if (!fpu_used_p(l)) { 868 memset(&pcb->pcb_fpu, 0, sizeof(pcb->pcb_fpu)); 869 fpu_mark_used(l); 870 } else { 871 fpu_save(l); 872 } 873 874 if (copyout(fpreg, (void *)tf->tf_dar, 875 sizeof(double)) != 0) 876 return -1; 877 878 if (dsi->flags & DSI_OP_INDEXED) { 879 /* do nothing */ 880 } 881 882 if (dsi->flags & DSI_OP_UPDATE) { 883 /* this is valid for 601, but to simplify logic don't pass for any */ 884 if (a_reg == 0) 885 return -1; 886 else 887 *a_reg_addr = tf->tf_dar; 888 } 889 890 fpu_load(); 891 return 0; 892 } 893 break; 894 895 case EXC_ALI_LHZ: 896 case EXC_ALI_LHZU: 897 case EXC_ALI_LHZX: 898 case EXC_ALI_LHZUX: 899 case EXC_ALI_LHA: 900 case EXC_ALI_LHAU: 901 case EXC_ALI_LHAX: 902 case EXC_ALI_LHAUX: 903 case EXC_ALI_LHBRX: 904 { 905 const register_t ea_addr = tf->tf_dar; 906 const unsigned int t_reg = EXC_ALI_RST(tf->tf_dsisr); 907 const unsigned int a_reg = EXC_ALI_RA(tf->tf_dsisr); 908 register_t* t_reg_addr = &tf->tf_fixreg[t_reg]; 909 register_t* a_reg_addr = &tf->tf_fixreg[a_reg]; 910 911 /* load into lower 2 bytes of reg */ 912 if (copyin((void *)ea_addr, 913 t_reg_addr+2, 914 sizeof(uint16_t)) != 0) 915 return -1; 916 917 if (dsi->flags & DSI_OP_UPDATE) { 918 /* this is valid for 601, but to simplify logic don't pass for any */ 919 if (a_reg == 0) 920 return -1; 921 else 922 *a_reg_addr = ea_addr; 923 } 924 925 if (dsi->flags & DSI_OP_INDEXED) { 926 /* do nothing , indexed address already in ea */ 927 } 928 929 if (dsi->flags & DSI_OP_ZERO) { 930 /* clear upper 2 bytes */ 931 *t_reg_addr &= 0x0000ffff; 932 } else if (dsi->flags & DSI_OP_ALGEBRAIC) { 933 /* sign extend upper 2 bytes */ 934 if (*t_reg_addr & 0x00008000) 935 *t_reg_addr |= 0xffff0000; 936 else 937 *t_reg_addr &= 0x0000ffff; 938 } 939 940 if (dsi->flags & DSI_OP_REVERSED) { 941 /* reverse lower 2 bytes */ 942 uint32_t temp = *t_reg_addr; 943 944 *t_reg_addr = ((temp & 0x000000ff) << 8 ) | 945 ((temp & 0x0000ff00) >> 8 ); 946 } 947 return 0; 948 } 949 break; 950 951 case EXC_ALI_STH: 952 case EXC_ALI_STHU: 953 case EXC_ALI_STHX: 954 case EXC_ALI_STHUX: 955 case EXC_ALI_STHBRX: 956 { 957 const register_t ea_addr = tf->tf_dar; 958 const unsigned int s_reg = EXC_ALI_RST(tf->tf_dsisr); 959 const unsigned int a_reg = EXC_ALI_RA(tf->tf_dsisr); 960 register_t* s_reg_addr = &tf->tf_fixreg[s_reg]; 961 register_t* a_reg_addr = &tf->tf_fixreg[a_reg]; 962 963 /* byte-reversed write out of lower 2 bytes */ 964 if (dsi->flags & DSI_OP_REVERSED) { 965 uint16_t tmp = *s_reg_addr & 0xffff; 966 tmp = bswap16(tmp); 967 968 if (copyout(&tmp, 969 (void *)ea_addr, 970 sizeof(uint16_t)) != 0) 971 return -1; 972 } 973 /* write out lower 2 bytes */ 974 else if (copyout(s_reg_addr+2, 975 (void *)ea_addr, 976 sizeof(uint16_t)) != 0) { 977 return -1; 978 } 979 980 if (dsi->flags & DSI_OP_INDEXED) { 981 /* do nothing, indexed address already in ea */ 982 } 983 984 if (dsi->flags & DSI_OP_UPDATE) { 985 /* this is valid for 601, but to simplify logic don't pass for any */ 986 if (a_reg == 0) 987 return -1; 988 else 989 *a_reg_addr = ea_addr; 990 } 991 992 return 0; 993 } 994 break; 995 996 case EXC_ALI_LWARX_LWZ: 997 case EXC_ALI_LWZU: 998 case EXC_ALI_LWZX: 999 case EXC_ALI_LWZUX: 1000 case EXC_ALI_LWBRX: 1001 { 1002 const register_t ea_addr = tf->tf_dar; 1003 const unsigned int t_reg = EXC_ALI_RST(tf->tf_dsisr); 1004 const unsigned int a_reg = EXC_ALI_RA(tf->tf_dsisr); 1005 register_t* t_reg_addr = &tf->tf_fixreg[t_reg]; 1006 register_t* a_reg_addr = &tf->tf_fixreg[a_reg]; 1007 1008 if (copyin((void *)ea_addr, 1009 t_reg_addr, 1010 sizeof(uint32_t)) != 0) 1011 return -1; 1012 1013 if (dsi->flags & DSI_OP_UPDATE) { 1014 /* this is valid for 601, but to simplify logic don't pass for any */ 1015 if (a_reg == 0) 1016 return -1; 1017 else 1018 *a_reg_addr = ea_addr; 1019 } 1020 1021 if (dsi->flags & DSI_OP_INDEXED) { 1022 /* do nothing , indexed address already in ea */ 1023 } 1024 1025 if (dsi->flags & DSI_OP_ZERO) { 1026 /* XXX - 64bit clear upper word */ 1027 } 1028 1029 if (dsi->flags & DSI_OP_REVERSED) { 1030 /* reverse bytes */ 1031 register_t temp = bswap32(*t_reg_addr); 1032 *t_reg_addr = temp; 1033 } 1034 1035 return 0; 1036 } 1037 break; 1038 1039 case EXC_ALI_STW: 1040 case EXC_ALI_STWU: 1041 case EXC_ALI_STWX: 1042 case EXC_ALI_STWUX: 1043 case EXC_ALI_STWBRX: 1044 { 1045 const register_t ea_addr = tf->tf_dar; 1046 const unsigned int s_reg = EXC_ALI_RST(tf->tf_dsisr); 1047 const unsigned int a_reg = EXC_ALI_RA(tf->tf_dsisr); 1048 register_t* s_reg_addr = &tf->tf_fixreg[s_reg]; 1049 register_t* a_reg_addr = &tf->tf_fixreg[a_reg]; 1050 1051 if (dsi->flags & DSI_OP_REVERSED) { 1052 /* byte-reversed write out */ 1053 register_t temp = bswap32(*s_reg_addr); 1054 1055 if (copyout(&temp, 1056 (void *)ea_addr, 1057 sizeof(uint32_t)) != 0) 1058 return -1; 1059 } 1060 /* write out word */ 1061 else if (copyout(s_reg_addr, 1062 (void *)ea_addr, 1063 sizeof(uint32_t)) != 0) 1064 return -1; 1065 1066 if (dsi->flags & DSI_OP_INDEXED) { 1067 /* do nothing, indexed address already in ea */ 1068 } 1069 1070 if (dsi->flags & DSI_OP_UPDATE) { 1071 /* this is valid for 601, but to simplify logic don't pass for any */ 1072 if (a_reg == 0) 1073 return -1; 1074 else 1075 *a_reg_addr = ea_addr; 1076 } 1077 1078 return 0; 1079 } 1080 break; 1081 } 1082 1083 return -1; 1084 } 1085 1086 static int 1087 emulate_privileged(struct lwp *l, struct trapframe *tf) 1088 { 1089 uint32_t opcode; 1090 1091 if (copyin((void *)tf->tf_srr0, &opcode, sizeof(opcode)) != 0) 1092 return 0; 1093 1094 if (OPC_MFSPR_P(opcode, SPR_PVR)) { 1095 __asm ("mfpvr %0" : "=r"(tf->tf_fixreg[OPC_MFSPR_REG(opcode)])); 1096 return 1; 1097 } 1098 1099 return emulate_mxmsr(l, tf, opcode); 1100 } 1101 1102 int 1103 copyinstr(const void *udaddr, void *kaddr, size_t len, size_t *done) 1104 { 1105 vaddr_t uva = (vaddr_t) udaddr; 1106 char *kp = kaddr; 1107 struct faultbuf env; 1108 int rv; 1109 1110 if ((rv = setfault(&env)) != 0) { 1111 unsetusr(); 1112 goto out2; 1113 } 1114 1115 while (len > 0) { 1116 size_t seglen; 1117 vaddr_t p = setusr(uva, &seglen); 1118 if (seglen > len) 1119 seglen = len; 1120 len -= seglen; 1121 uva += seglen; 1122 for (; seglen-- > 0; p++) { 1123 if ((*kp++ = *(char *)p) == 0) { 1124 unsetusr(); 1125 goto out; 1126 } 1127 } 1128 unsetusr(); 1129 } 1130 rv = ENAMETOOLONG; 1131 1132 out: 1133 if (done != NULL) 1134 *done = kp - (char *) kaddr; 1135 out2: 1136 curpcb->pcb_onfault = 0; 1137 return rv; 1138 } 1139 1140 1141 int 1142 copyoutstr(const void *kaddr, void *udaddr, size_t len, size_t *done) 1143 { 1144 const char *kp = kaddr; 1145 vaddr_t uva = (vaddr_t) udaddr; 1146 struct faultbuf env; 1147 int rv; 1148 1149 if ((rv = setfault(&env)) != 0) { 1150 unsetusr(); 1151 goto out2; 1152 } 1153 1154 while (len > 0) { 1155 size_t seglen; 1156 vaddr_t p = setusr(uva, &seglen); 1157 if (seglen > len) 1158 seglen = len; 1159 len -= seglen; 1160 uva += seglen; 1161 for (; seglen-- > 0; p++) { 1162 if ((*(char *)p = *kp++) == 0) { 1163 unsetusr(); 1164 goto out; 1165 } 1166 } 1167 unsetusr(); 1168 } 1169 rv = ENAMETOOLONG; 1170 1171 out: 1172 if (done != NULL) 1173 *done = kp - (const char*)kaddr; 1174 out2: 1175 curpcb->pcb_onfault = 0; 1176 return rv; 1177 } 1178 1179 const struct dsi_info* 1180 get_dsi_info(register_t dsisr) 1181 { 1182 static const struct dsi_info dsi[] = 1183 { 1184 /* data cache block zero */ 1185 {EXC_ALI_DCBZ, 0}, 1186 1187 /* load halfwords */ 1188 {EXC_ALI_LHZ, DSI_OP_ZERO}, 1189 {EXC_ALI_LHZU, DSI_OP_ZERO|DSI_OP_UPDATE}, 1190 {EXC_ALI_LHZX, DSI_OP_ZERO|DSI_OP_INDEXED}, 1191 {EXC_ALI_LHZUX, DSI_OP_ZERO|DSI_OP_UPDATE|DSI_OP_INDEXED}, 1192 {EXC_ALI_LHA, DSI_OP_ALGEBRAIC}, 1193 {EXC_ALI_LHAU, DSI_OP_ALGEBRAIC|DSI_OP_UPDATE}, 1194 {EXC_ALI_LHAX, DSI_OP_ALGEBRAIC|DSI_OP_INDEXED}, 1195 {EXC_ALI_LHAUX, DSI_OP_ALGEBRAIC|DSI_OP_UPDATE|DSI_OP_INDEXED}, 1196 1197 /* store halfwords */ 1198 {EXC_ALI_STH, 0}, 1199 {EXC_ALI_STHU, DSI_OP_UPDATE}, 1200 {EXC_ALI_STHX, DSI_OP_INDEXED}, 1201 {EXC_ALI_STHUX, DSI_OP_UPDATE|DSI_OP_INDEXED}, 1202 1203 /* load words */ 1204 {EXC_ALI_LWARX_LWZ, DSI_OP_ZERO}, 1205 {EXC_ALI_LWZU, DSI_OP_ZERO|DSI_OP_UPDATE}, 1206 {EXC_ALI_LWZX, DSI_OP_ZERO|DSI_OP_INDEXED}, 1207 {EXC_ALI_LWZUX, DSI_OP_ZERO|DSI_OP_UPDATE|DSI_OP_INDEXED}, 1208 1209 /* store words */ 1210 {EXC_ALI_STW, 0}, 1211 {EXC_ALI_STWU, DSI_OP_UPDATE}, 1212 {EXC_ALI_STWX, DSI_OP_INDEXED}, 1213 {EXC_ALI_STWUX, DSI_OP_UPDATE|DSI_OP_INDEXED}, 1214 1215 /* load byte-reversed */ 1216 {EXC_ALI_LHBRX, DSI_OP_REVERSED|DSI_OP_INDEXED|DSI_OP_ZERO}, 1217 {EXC_ALI_LWBRX, DSI_OP_REVERSED|DSI_OP_INDEXED}, 1218 1219 /* store byte-reversed */ 1220 {EXC_ALI_STHBRX, DSI_OP_REVERSED|DSI_OP_INDEXED}, 1221 {EXC_ALI_STWBRX, DSI_OP_REVERSED|DSI_OP_INDEXED}, 1222 1223 /* load float double-precision */ 1224 {EXC_ALI_LFD, 0}, 1225 {EXC_ALI_LFDU, DSI_OP_UPDATE}, 1226 {EXC_ALI_LDFX, DSI_OP_INDEXED}, 1227 {EXC_ALI_LFDUX, DSI_OP_UPDATE|DSI_OP_INDEXED}, 1228 1229 /* store float double precision */ 1230 {EXC_ALI_STFD, 0}, 1231 {EXC_ALI_STFDU, DSI_OP_UPDATE}, 1232 {EXC_ALI_STFDX, DSI_OP_INDEXED}, 1233 {EXC_ALI_STFDUX, DSI_OP_UPDATE|DSI_OP_INDEXED}, 1234 1235 /* XXX - ones below here not yet implemented in fix_unaligned() */ 1236 /* load float single precision */ 1237 {EXC_ALI_LFS, 0}, 1238 {EXC_ALI_LFSU, DSI_OP_UPDATE}, 1239 {EXC_ALI_LSFX, DSI_OP_INDEXED}, 1240 {EXC_ALI_LFSUX, DSI_OP_UPDATE|DSI_OP_INDEXED}, 1241 1242 /* store float single precision */ 1243 {EXC_ALI_STFS, 0}, 1244 {EXC_ALI_STFSU, DSI_OP_UPDATE}, 1245 {EXC_ALI_STFSX, DSI_OP_INDEXED}, 1246 {EXC_ALI_STFSUX, DSI_OP_UPDATE|DSI_OP_INDEXED}, 1247 1248 /* multiple */ 1249 {EXC_ALI_LMW, 0}, 1250 {EXC_ALI_STMW, 0}, 1251 1252 /* load & store string */ 1253 {EXC_ALI_LSWI, 0}, 1254 {EXC_ALI_LSWX, DSI_OP_INDEXED}, 1255 {EXC_ALI_STSWI, 0}, 1256 {EXC_ALI_STSWX, DSI_OP_INDEXED}, 1257 1258 /* get/send word from external */ 1259 {EXC_ALI_ECIWX, DSI_OP_INDEXED}, 1260 {EXC_ALI_ECOWX, DSI_OP_INDEXED}, 1261 1262 /* store float as integer word */ 1263 {EXC_ALI_STFIWX, 0}, 1264 1265 /* store conditional */ 1266 {EXC_ALI_LDARX, DSI_OP_INDEXED}, /* stdcx */ 1267 {EXC_ALI_STDCX, DSI_OP_INDEXED}, 1268 {EXC_ALI_STWCX, DSI_OP_INDEXED}, /* lwarx */ 1269 1270 #ifdef PPC_OEA64 1271 /* 64 bit, load word algebriac */ 1272 {EXC_ALI_LWAX, DSI_OP_ALGEBRAIC|DSI_OP_INDEXED}, 1273 {EXC_ALI_LWAUX, DSI_OP_ALGEBRAIC|DSI_OP_UPDATE|DSI_OP_INDEXED}, 1274 1275 /* 64 bit load doubleword */ 1276 {EXC_ALI_LD_LDU_LWA, 0}, 1277 {EXC_ALI_LDX, DSI_OP_INDEXED}, 1278 {EXC_ALI_LDUX, DSI_OP_UPDATE|DSI_OP_INDEXED}, 1279 1280 /* 64 bit store double word */ 1281 {EXC_ALI_STD_STDU, 0}, 1282 {EXC_ALI_STDX, DSI_OP_INDEXED}, 1283 {EXC_ALI_STDUX, DSI_OP_UPDATE|DSI_OP_INDEXED}, 1284 #endif 1285 }; 1286 1287 int num_elems = sizeof(dsi)/sizeof(dsi[0]); 1288 int indicator = EXC_ALI_OPCODE_INDICATOR(dsisr); 1289 int i; 1290 1291 for (i = 0 ; i < num_elems; i++) { 1292 if (indicator == dsi[i].indicator){ 1293 return &dsi[i]; 1294 } 1295 } 1296 return 0; 1297 } 1298 1299 #ifdef PPC_IBMESPRESSO 1300 static int 1301 fix_stwcx(struct lwp *l, struct trapframe *tf) 1302 { 1303 struct faultbuf env; 1304 union instr instr; 1305 vaddr_t uva, p; 1306 size_t len; 1307 uint32_t cr; 1308 1309 if (copyin((void *)tf->tf_srr0, &instr.i_int, sizeof(instr)) != 0) { 1310 printf("trap: copyin of 0x%08lx failed\n", tf->tf_srr0); 1311 return 0; 1312 } 1313 1314 if (instr.i_any.i_opcd != OPC_integer_31 || 1315 instr.i_x.i_xo != OPC31_STWCX) { 1316 return 0; 1317 } 1318 KASSERT(instr.i_x.i_rc == 0); 1319 1320 if (setfault(&env) != 0) { 1321 unsetusr(); 1322 curpcb->pcb_onfault = 0; 1323 printf("trap: stwcx. emulate failed\n"); 1324 return 0; 1325 } 1326 1327 uva = (instr.i_x.i_ra ? tf->tf_ureg.r_fixreg[instr.i_x.i_ra] : 0) + 1328 tf->tf_ureg.r_fixreg[instr.i_x.i_rb]; 1329 p = setusr(uva, &len); 1330 1331 asm volatile( 1332 "dcbst 0, %1 \n" 1333 "stwcx. %2, 0, %1 \n" 1334 "mfcr %0 \n" 1335 : "=r" (cr) 1336 : "r" (p), 1337 "r" (tf->tf_ureg.r_fixreg[instr.i_x.i_rs]) 1338 : "cr0", "memory" 1339 ); 1340 1341 tf->tf_ureg.r_cr &= ~0xf0000000; 1342 tf->tf_ureg.r_cr |= (cr & 0xf0000000); 1343 1344 unsetusr(); 1345 curpcb->pcb_onfault = 0; 1346 return 1; 1347 } 1348 #endif 1349