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