trap.c (228869) | trap.c (230123) |
---|---|
1/*- 2 * Copyright (C) 1995, 1996 Wolfgang Solfrank. 3 * Copyright (C) 1995, 1996 TooLs GmbH. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: --- 18 unchanged lines hidden (view full) --- 27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 * 31 * $NetBSD: trap.c,v 1.58 2002/03/04 04:07:35 dbj Exp $ 32 */ 33 34#include <sys/cdefs.h> | 1/*- 2 * Copyright (C) 1995, 1996 Wolfgang Solfrank. 3 * Copyright (C) 1995, 1996 TooLs GmbH. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: --- 18 unchanged lines hidden (view full) --- 27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 * 31 * $NetBSD: trap.c,v 1.58 2002/03/04 04:07:35 dbj Exp $ 32 */ 33 34#include <sys/cdefs.h> |
35__FBSDID("$FreeBSD: head/sys/powerpc/aim/trap.c 228869 2011-12-24 19:34:52Z jhibbits $"); | 35__FBSDID("$FreeBSD: head/sys/powerpc/aim/trap.c 230123 2012-01-15 00:08:14Z nwhitehorn $"); |
36 37#include "opt_hwpmc_hooks.h" 38 39#include <sys/param.h> 40#include <sys/kdb.h> 41#include <sys/proc.h> 42#include <sys/ktr.h> 43#include <sys/lock.h> --- 39 unchanged lines hidden (view full) --- 83 int user); 84static int trap_pfault(struct trapframe *frame, int user); 85static int fix_unaligned(struct thread *td, struct trapframe *frame); 86static int ppc_instr_emulate(struct trapframe *frame); 87static int handle_onfault(struct trapframe *frame); 88static void syscall(struct trapframe *frame); 89 90#ifdef __powerpc64__ | 36 37#include "opt_hwpmc_hooks.h" 38 39#include <sys/param.h> 40#include <sys/kdb.h> 41#include <sys/proc.h> 42#include <sys/ktr.h> 43#include <sys/lock.h> --- 39 unchanged lines hidden (view full) --- 83 int user); 84static int trap_pfault(struct trapframe *frame, int user); 85static int fix_unaligned(struct thread *td, struct trapframe *frame); 86static int ppc_instr_emulate(struct trapframe *frame); 87static int handle_onfault(struct trapframe *frame); 88static void syscall(struct trapframe *frame); 89 90#ifdef __powerpc64__ |
91static int handle_slb_spill(pmap_t pm, vm_offset_t addr); | 91 void handle_kernel_slb_spill(int, register_t, register_t); 92static int handle_user_slb_spill(pmap_t pm, vm_offset_t addr); 93extern int n_slbs; |
92#endif 93 94int setfault(faultbuf); /* defined in locore.S */ 95 96/* Why are these not defined in a header? */ 97int badaddr(void *, size_t); 98int badaddr_read(void *, size_t, int *); 99 --- 86 unchanged lines hidden (view full) --- 186 case EXC_TRC: 187 frame->srr1 &= ~PSL_SE; 188 sig = SIGTRAP; 189 break; 190 191#ifdef __powerpc64__ 192 case EXC_ISE: 193 case EXC_DSE: | 94#endif 95 96int setfault(faultbuf); /* defined in locore.S */ 97 98/* Why are these not defined in a header? */ 99int badaddr(void *, size_t); 100int badaddr_read(void *, size_t, int *); 101 --- 86 unchanged lines hidden (view full) --- 188 case EXC_TRC: 189 frame->srr1 &= ~PSL_SE; 190 sig = SIGTRAP; 191 break; 192 193#ifdef __powerpc64__ 194 case EXC_ISE: 195 case EXC_DSE: |
194 if (handle_slb_spill(&p->p_vmspace->vm_pmap, | 196 if (handle_user_slb_spill(&p->p_vmspace->vm_pmap, |
195 (type == EXC_ISE) ? frame->srr0 : 196 frame->cpu.aim.dar) != 0) 197 sig = SIGSEGV; 198 break; 199#endif 200 case EXC_DSI: 201 case EXC_ISI: 202 sig = trap_pfault(frame, 1); --- 51 unchanged lines hidden (view full) --- 254 trap_fatal(frame); 255 } 256 } else { 257 /* Kernel Mode Traps */ 258 259 KASSERT(cold || td->td_ucred != NULL, 260 ("kernel trap doesn't have ucred")); 261 switch (type) { | 197 (type == EXC_ISE) ? frame->srr0 : 198 frame->cpu.aim.dar) != 0) 199 sig = SIGSEGV; 200 break; 201#endif 202 case EXC_DSI: 203 case EXC_ISI: 204 sig = trap_pfault(frame, 1); --- 51 unchanged lines hidden (view full) --- 256 trap_fatal(frame); 257 } 258 } else { 259 /* Kernel Mode Traps */ 260 261 KASSERT(cold || td->td_ucred != NULL, 262 ("kernel trap doesn't have ucred")); 263 switch (type) { |
262 case EXC_DSI: 263 if (trap_pfault(frame, 0) == 0) 264 return; 265 break; | |
266#ifdef __powerpc64__ 267 case EXC_DSE: 268 if ((frame->cpu.aim.dar & SEGMENT_MASK) == USER_ADDR) { 269 __asm __volatile ("slbmte %0, %1" :: | 264#ifdef __powerpc64__ 265 case EXC_DSE: 266 if ((frame->cpu.aim.dar & SEGMENT_MASK) == USER_ADDR) { 267 __asm __volatile ("slbmte %0, %1" :: |
270 "r"(td->td_pcb->pcb_cpu.aim.usr_vsid), 271 "r"(USER_SLB_SLBE)); | 268 "r"(td->td_pcb->pcb_cpu.aim.usr_vsid), 269 "r"(USER_SLB_SLBE)); |
272 return; 273 } | 270 return; 271 } |
274 275 /* FALLTHROUGH */ 276 case EXC_ISE: 277 if (handle_slb_spill(kernel_pmap, 278 (type == EXC_ISE) ? frame->srr0 : 279 frame->cpu.aim.dar) != 0) 280 panic("Fault handling kernel SLB miss"); 281 return; | 272 break; |
282#endif | 273#endif |
274 case EXC_DSI: 275 if (trap_pfault(frame, 0) == 0) 276 return; 277 break; |
|
283 case EXC_MCHK: 284 if (handle_onfault(frame)) 285 return; 286 break; 287 default: 288 break; 289 } 290 trap_fatal(frame); --- 30 unchanged lines hidden (view full) --- 321static void 322printtrap(u_int vector, struct trapframe *frame, int isfatal, int user) 323{ 324 325 printf("\n"); 326 printf("%s %s trap:\n", isfatal ? "fatal" : "handled", 327 user ? "user" : "kernel"); 328 printf("\n"); | 278 case EXC_MCHK: 279 if (handle_onfault(frame)) 280 return; 281 break; 282 default: 283 break; 284 } 285 trap_fatal(frame); --- 30 unchanged lines hidden (view full) --- 316static void 317printtrap(u_int vector, struct trapframe *frame, int isfatal, int user) 318{ 319 320 printf("\n"); 321 printf("%s %s trap:\n", isfatal ? "fatal" : "handled", 322 user ? "user" : "kernel"); 323 printf("\n"); |
329 printf(" exception = 0x%x (%s)\n", vector >> 8, 330 trapname(vector)); | 324 printf(" exception = 0x%x (%s)\n", vector, trapname(vector)); |
331 switch (vector) { 332 case EXC_DSE: 333 case EXC_DSI: 334 printf(" virtual address = 0x%" PRIxPTR "\n", 335 frame->cpu.aim.dar); 336 break; 337 case EXC_ISE: 338 case EXC_ISI: --- 142 unchanged lines hidden (view full) --- 481 "r"(td->td_pcb->pcb_cpu.aim.usr_vsid), "r"(USER_SLB_SLBE)); 482#endif 483 484 error = syscallenter(td, &sa); 485 syscallret(td, error, &sa); 486} 487 488#ifdef __powerpc64__ | 325 switch (vector) { 326 case EXC_DSE: 327 case EXC_DSI: 328 printf(" virtual address = 0x%" PRIxPTR "\n", 329 frame->cpu.aim.dar); 330 break; 331 case EXC_ISE: 332 case EXC_ISI: --- 142 unchanged lines hidden (view full) --- 475 "r"(td->td_pcb->pcb_cpu.aim.usr_vsid), "r"(USER_SLB_SLBE)); 476#endif 477 478 error = syscallenter(td, &sa); 479 syscallret(td, error, &sa); 480} 481 482#ifdef __powerpc64__ |
483/* Handle kernel SLB faults -- runs in real mode, all seat belts off */ 484void 485handle_kernel_slb_spill(int type, register_t dar, register_t srr0) 486{ 487 struct slb *slbcache; 488 uint64_t slbe, slbv; 489 uint64_t esid, addr; 490 int i; 491 492 addr = (type == EXC_ISE) ? srr0 : dar; 493 slbcache = PCPU_GET(slb); 494 esid = (uintptr_t)addr >> ADDR_SR_SHFT; 495 slbe = (esid << SLBE_ESID_SHIFT) | SLBE_VALID; 496 497 /* See if the hardware flushed this somehow (can happen in LPARs) */ 498 for (i = 0; i < n_slbs; i++) 499 if (slbcache[i].slbe == (slbe | (uint64_t)i)) 500 return; 501 502 /* Not in the map, needs to actually be added */ 503 slbv = kernel_va_to_slbv(addr); 504 if (slbcache[USER_SLB_SLOT].slbe == 0) { 505 for (i = 0; i < n_slbs; i++) { 506 if (i == USER_SLB_SLOT) 507 continue; 508 if (!(slbcache[i].slbe & SLBE_VALID)) 509 goto fillkernslb; 510 } 511 512 if (i == n_slbs) 513 slbcache[USER_SLB_SLOT].slbe = 1; 514 } 515 516 /* Sacrifice a random SLB entry that is not the user entry */ 517 i = mftb() % n_slbs; 518 if (i == USER_SLB_SLOT) 519 i = (i+1) % n_slbs; 520 521fillkernslb: 522 /* Write new entry */ 523 slbcache[i].slbv = slbv; 524 slbcache[i].slbe = slbe | (uint64_t)i; 525 526 /* Trap handler will restore from cache on exit */ 527} 528 |
|
489static int | 529static int |
490handle_slb_spill(pmap_t pm, vm_offset_t addr) | 530handle_user_slb_spill(pmap_t pm, vm_offset_t addr) |
491{ 492 struct slb *user_entry; 493 uint64_t esid; 494 int i; 495 496 esid = (uintptr_t)addr >> ADDR_SR_SHFT; 497 | 531{ 532 struct slb *user_entry; 533 uint64_t esid; 534 int i; 535 536 esid = (uintptr_t)addr >> ADDR_SR_SHFT; 537 |
498 if (pm == kernel_pmap) { 499 slb_insert_kernel((esid << SLBE_ESID_SHIFT) | SLBE_VALID, 500 kernel_va_to_slbv(addr)); 501 return (0); 502 } 503 | |
504 PMAP_LOCK(pm); 505 user_entry = user_va_to_slb_entry(pm, addr); 506 507 if (user_entry == NULL) { 508 /* allocate_vsid auto-spills it */ 509 (void)allocate_user_vsid(pm, esid, 0); 510 } else { 511 /* --- 212 unchanged lines hidden --- | 538 PMAP_LOCK(pm); 539 user_entry = user_va_to_slb_entry(pm, addr); 540 541 if (user_entry == NULL) { 542 /* allocate_vsid auto-spills it */ 543 (void)allocate_user_vsid(pm, esid, 0); 544 } else { 545 /* --- 212 unchanged lines hidden --- |