Deleted Added
full compact
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 ---