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