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