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