1 /* 2 * Copyright (c) 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This software was developed by the Computer Systems Engineering group 6 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 7 * contributed to Berkeley. 8 * 9 * All advertising materials mentioning features or use of this software 10 * must display the following acknowledgement: 11 * This product includes software developed by the University of 12 * California, Lawrence Berkeley Laboratory. 13 * 14 * %sccs.include.redist.c% 15 * 16 * @(#)trap.c 8.5 (Berkeley) 11/21/94 17 * 18 * from: $Header: trap.c,v 1.34 93/05/28 04:34:50 torek Exp $ 19 */ 20 21 #include <sys/param.h> 22 #include <sys/systm.h> 23 #include <sys/proc.h> 24 #include <sys/user.h> 25 #include <sys/kernel.h> 26 #include <sys/malloc.h> 27 #include <sys/resource.h> 28 #include <sys/signal.h> 29 #include <sys/wait.h> 30 #include <sys/syscall.h> 31 #include <sys/syslog.h> 32 #ifdef KTRACE 33 #include <sys/ktrace.h> 34 #endif 35 36 #include <vm/vm_kern.h> 37 38 #include <machine/cpu.h> 39 #include <machine/ctlreg.h> 40 #include <machine/frame.h> 41 #include <machine/trap.h> 42 43 #define offsetof(s, f) ((int)&((s *)0)->f) 44 45 extern int cold; 46 47 int rwindow_debug = 0; 48 49 /* 50 * Initial FPU state is all registers == all 1s, everything else == all 0s. 51 * This makes every floating point register a signalling NaN, with sign bit 52 * set, no matter how it is interpreted. Appendix N of the Sparc V8 document 53 * seems to imply that we should do this, and it does make sense. 54 */ 55 struct fpstate initfpstate = { 56 { ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, 57 ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0 } 58 }; 59 60 /* 61 * There are more than 100 trap types, but most are unused. 62 * 63 * Trap type 0 is taken over as an `Asynchronous System Trap'. 64 * This is left-over Vax emulation crap that should be fixed. 65 */ 66 static const char T[] = "trap"; 67 const char *trap_type[] = { 68 /* non-user vectors */ 69 "ast", /* 0 */ 70 "text fault", /* 1 */ 71 "illegal instruction", /* 2 */ 72 "privileged instruction",/*3 */ 73 "fp disabled", /* 4 */ 74 "window overflow", /* 5 */ 75 "window underflow", /* 6 */ 76 "alignment fault", /* 7 */ 77 "fp exception", /* 8 */ 78 "data fault", /* 9 */ 79 "tag overflow", /* 0a */ 80 T, T, T, T, T, T, /* 0b..10 */ 81 "level 1 int", /* 11 */ 82 "level 2 int", /* 12 */ 83 "level 3 int", /* 13 */ 84 "level 4 int", /* 14 */ 85 "level 5 int", /* 15 */ 86 "level 6 int", /* 16 */ 87 "level 7 int", /* 17 */ 88 "level 8 int", /* 18 */ 89 "level 9 int", /* 19 */ 90 "level 10 int", /* 1a */ 91 "level 11 int", /* 1b */ 92 "level 12 int", /* 1c */ 93 "level 13 int", /* 1d */ 94 "level 14 int", /* 1e */ 95 "level 15 int", /* 1f */ 96 T, T, T, T, T, T, T, T, /* 20..27 */ 97 T, T, T, T, T, T, T, T, /* 28..2f */ 98 T, T, T, T, T, T, /* 30..35 */ 99 "cp disabled", /* 36 */ 100 T, /* 37 */ 101 T, T, T, T, T, T, T, T, /* 38..3f */ 102 "cp exception", /* 40 */ 103 T, T, T, T, T, T, T, /* 41..47 */ 104 T, T, T, T, T, T, T, T, /* 48..4f */ 105 T, T, T, T, T, T, T, T, /* 50..57 */ 106 T, T, T, T, T, T, T, T, /* 58..5f */ 107 T, T, T, T, T, T, T, T, /* 60..67 */ 108 T, T, T, T, T, T, T, T, /* 68..6f */ 109 T, T, T, T, T, T, T, T, /* 70..77 */ 110 T, T, T, T, T, T, T, T, /* 78..7f */ 111 112 /* user (software trap) vectors */ 113 "sun syscall", /* 80 */ 114 "breakpoint", /* 81 */ 115 "zero divide", /* 82 */ 116 "flush windows", /* 83 */ 117 "clean windows", /* 84 */ 118 "range check", /* 85 */ 119 "fix align", /* 86 */ 120 "integer overflow", /* 87 */ 121 "kgdb exec", /* 88 */ 122 "syscall" /* 89 */ 123 }; 124 125 #define N_TRAP_TYPES (sizeof trap_type / sizeof *trap_type) 126 127 /* 128 * Define the code needed before returning to user mode, for 129 * trap, mem_access_fault, and syscall. 130 */ 131 static inline void 132 userret(struct proc *p, int pc, u_quad_t oticks) 133 { 134 int sig; 135 136 /* take pending signals */ 137 while ((sig = CURSIG(p)) != 0) 138 postsig(sig); 139 p->p_priority = p->p_usrpri; 140 if (want_ast) { 141 want_ast = 0; 142 if (p->p_flag & P_OWEUPC) { 143 p->p_flag &= ~P_OWEUPC; 144 ADDUPROF(p); 145 } 146 } 147 if (want_resched) { 148 /* 149 * Since we are curproc, clock will normally just change 150 * our priority without moving us from one queue to another 151 * (since the running process is not on a queue.) 152 * If that happened after we put ourselves on the run queue 153 * but before we switched, we might not be on the queue 154 * indicated by our priority. 155 */ 156 (void) splstatclock(); 157 setrunqueue(p); 158 p->p_stats->p_ru.ru_nivcsw++; 159 mi_switch(); 160 (void) spl0(); 161 while ((sig = CURSIG(p)) != 0) 162 postsig(sig); 163 } 164 165 /* 166 * If profiling, charge recent system time to the trapped pc. 167 */ 168 if (p->p_flag & P_PROFIL) 169 addupc_task(p, pc, (int)(p->p_sticks - oticks)); 170 171 curpriority = p->p_priority; 172 } 173 174 /* 175 * If someone stole the FPU while we were away, do not enable it 176 * on return. This is not done in userret() above as it must follow 177 * the ktrsysret() in syscall(). Actually, it is likely that the 178 * ktrsysret should occur before the call to userret. 179 */ 180 static inline void share_fpu(struct proc *p, struct trapframe *tf) { 181 if ((tf->tf_psr & PSR_EF) != 0 && fpproc != p) 182 tf->tf_psr &= ~PSR_EF; 183 } 184 185 /* 186 * Called from locore.s trap handling, for non-MMU-related traps. 187 * (MMU-related traps go through mem_access_fault, below.) 188 */ 189 trap(type, psr, pc, tf) 190 register unsigned type; 191 register int psr, pc; 192 register struct trapframe *tf; 193 { 194 register struct proc *p; 195 register struct pcb *pcb; 196 register int n; 197 u_quad_t sticks; 198 199 /* This steps the PC over the trap. */ 200 #define ADVANCE (n = tf->tf_npc, tf->tf_pc = n, tf->tf_npc = n + 4) 201 202 cnt.v_trap++; 203 /* 204 * Generally, kernel traps cause a panic. Any exceptions are 205 * handled early here. 206 */ 207 if (psr & PSR_PS) { 208 /* 209 * Storing %fsr in cpu_attach will cause this trap 210 * even though the fpu has been enabled, if and only 211 * if there is no FPU. 212 */ 213 if (type == T_FPDISABLED && cold) { 214 ADVANCE; 215 return; 216 } 217 goto dopanic; 218 } 219 if ((p = curproc) == NULL) 220 p = &proc0; 221 sticks = p->p_sticks; 222 pcb = &p->p_addr->u_pcb; 223 p->p_md.md_tf = tf; /* for ptrace/signals */ 224 225 switch (type) { 226 227 default: 228 if (type < 0x80) { 229 dopanic: 230 printf("trap type 0x%x: pc=%x npc=%x psr=%b\n", 231 type, pc, tf->tf_npc, psr, PSR_BITS); 232 panic(type < N_TRAP_TYPES ? trap_type[type] : T); 233 /* NOTREACHED */ 234 } 235 /* the following message is gratuitous */ 236 /* ... but leave it in until we find anything */ 237 printf("%s[%d]: unimplemented software trap 0x%x\n", 238 p->p_comm, p->p_pid, type); 239 trapsignal(p, SIGILL, type); 240 break; 241 242 case T_AST: 243 break; /* the work is all in userret() */ 244 245 case T_ILLINST: 246 trapsignal(p, SIGILL, 0); /* XXX code?? */ 247 break; 248 249 case T_PRIVINST: 250 trapsignal(p, SIGILL, 0); /* XXX code?? */ 251 break; 252 253 case T_FPDISABLED: { 254 register struct fpstate *fs = p->p_md.md_fpstate; 255 256 if (fs == NULL) { 257 fs = malloc(sizeof *fs, M_SUBPROC, M_WAITOK); 258 *fs = initfpstate; 259 p->p_md.md_fpstate = fs; 260 } 261 /* 262 * If we have not found an FPU, we have to emulate it. 263 */ 264 if (!foundfpu) { 265 #ifdef notyet 266 fpu_emulate(p, tf, fs); 267 break; 268 #else 269 trapsignal(p, SIGFPE, 0); /* XXX code?? */ 270 break; 271 #endif 272 } 273 /* 274 * We may have more FPEs stored up and/or ops queued. 275 * If they exist, handle them and get out. Otherwise, 276 * resolve the FPU state, turn it on, and try again. 277 */ 278 if (fs->fs_qsize) { 279 fpu_cleanup(p, fs); 280 break; 281 } 282 if (fpproc != p) { /* we do not have it */ 283 if (fpproc != NULL) /* someone else had it */ 284 savefpstate(fpproc->p_md.md_fpstate); 285 loadfpstate(fs); 286 fpproc = p; /* now we do have it */ 287 } 288 tf->tf_psr |= PSR_EF; 289 break; 290 } 291 292 case T_WINOF: 293 if (rwindow_save(p)) 294 sigexit(p, SIGILL); 295 break; 296 297 #define read_rw(src, dst) \ 298 copyin((caddr_t)(src), (caddr_t)(dst), sizeof(struct rwindow)) 299 300 case T_RWRET: 301 /* 302 * T_RWRET is a window load needed in order to rett. 303 * It simply needs the window to which tf->tf_out[6] 304 * (%sp) points. There are no user or saved windows now. 305 * Copy the one from %sp into pcb->pcb_rw[0] and set 306 * nsaved to -1. If we decide to deliver a signal on 307 * our way out, we will clear nsaved. 308 */ 309 if (pcb->pcb_uw || pcb->pcb_nsaved) panic("trap T_RWRET 1"); 310 if (rwindow_debug) 311 printf("%s[%d]: rwindow: pcb<-stack: %x\n", p->p_comm, p->p_pid, tf->tf_out[6]); 312 if (read_rw(tf->tf_out[6], &pcb->pcb_rw[0])) 313 sigexit(p, SIGILL); 314 if (pcb->pcb_nsaved) panic("trap T_RWRET 2"); 315 pcb->pcb_nsaved = -1; /* mark success */ 316 break; 317 318 case T_WINUF: 319 /* 320 * T_WINUF is a real window underflow, from a restore 321 * instruction. It needs to have the contents of two 322 * windows---the one belonging to the restore instruction 323 * itself, which is at its %sp, and the one belonging to 324 * the window above, which is at its %fp or %i6---both 325 * in the pcb. The restore's window may still be in 326 * the cpu; we need to force it out to the stack. 327 */ 328 if (rwindow_debug) 329 printf("%s[%d]: rwindow: T_WINUF 0: pcb<-stack: %x\n", 330 p->p_comm, p->p_pid, tf->tf_out[6]); 331 write_user_windows(); 332 if (rwindow_save(p) || read_rw(tf->tf_out[6], &pcb->pcb_rw[0])) 333 sigexit(p, SIGILL); 334 if (rwindow_debug) 335 printf("%s[%d]: rwindow: T_WINUF 1: pcb<-stack: %x\n", 336 p->p_comm, p->p_pid, pcb->pcb_rw[0].rw_in[6]); 337 if (read_rw(pcb->pcb_rw[0].rw_in[6], &pcb->pcb_rw[1])) 338 sigexit(p, SIGILL); 339 if (pcb->pcb_nsaved) panic("trap T_WINUF"); 340 pcb->pcb_nsaved = -1; /* mark success */ 341 break; 342 343 case T_ALIGN: 344 trapsignal(p, SIGBUS, 0); /* XXX code?? */ 345 break; 346 347 case T_FPE: 348 /* 349 * Clean up after a floating point exception. 350 * fpu_cleanup can (and usually does) modify the 351 * state we save here, so we must `give up' the FPU 352 * chip context. (The software and hardware states 353 * will not match once fpu_cleanup does its job, so 354 * we must not save again later.) 355 */ 356 if (p != fpproc) 357 panic("fpe without being the FP user"); 358 savefpstate(p->p_md.md_fpstate); 359 fpproc = NULL; 360 /* tf->tf_psr &= ~PSR_EF; */ /* share_fpu will do this */ 361 fpu_cleanup(p, p->p_md.md_fpstate); 362 /* fpu_cleanup posts signals if needed */ 363 #if 0 /* ??? really never??? */ 364 ADVANCE; 365 #endif 366 break; 367 368 case T_TAGOF: 369 trapsignal(p, SIGEMT, 0); /* XXX code?? */ 370 break; 371 372 case T_CPDISABLED: 373 uprintf("coprocessor instruction\n"); /* XXX */ 374 trapsignal(p, SIGILL, 0); /* XXX code?? */ 375 break; 376 377 case T_BREAKPOINT: 378 trapsignal(p, SIGTRAP, 0); 379 break; 380 381 case T_DIV0: 382 ADVANCE; 383 trapsignal(p, SIGFPE, FPE_INTDIV_TRAP); 384 break; 385 386 case T_FLUSHWIN: 387 write_user_windows(); 388 #ifdef probably_slower_since_this_is_usually_false 389 if (pcb->pcb_nsaved && rwindow_save(p)) 390 sigexit(p, SIGILL); 391 #endif 392 ADVANCE; 393 break; 394 395 case T_CLEANWIN: 396 uprintf("T_CLEANWIN\n"); /* XXX */ 397 ADVANCE; 398 break; 399 400 case T_RANGECHECK: 401 uprintf("T_RANGECHECK\n"); /* XXX */ 402 ADVANCE; 403 trapsignal(p, SIGILL, 0); /* XXX code?? */ 404 break; 405 406 case T_FIXALIGN: 407 uprintf("T_FIXALIGN\n"); /* XXX */ 408 ADVANCE; 409 break; 410 411 case T_INTOF: 412 uprintf("T_INTOF\n"); /* XXX */ 413 ADVANCE; 414 trapsignal(p, SIGFPE, FPE_INTOVF_TRAP); 415 break; 416 } 417 userret(p, pc, sticks); 418 share_fpu(p, tf); 419 #undef ADVANCE 420 } 421 422 /* 423 * Save windows from PCB into user stack, and return 0. This is used on 424 * window overflow pseudo-traps (from locore.s, just before returning to 425 * user mode) and when ptrace or sendsig needs a consistent state. 426 * As a side effect, rwindow_save() always sets pcb_nsaved to 0, 427 * clobbering the `underflow restore' indicator if it was -1. 428 * 429 * If the windows cannot be saved, pcb_nsaved is restored and we return -1. 430 */ 431 int 432 rwindow_save(p) 433 register struct proc *p; 434 { 435 register struct pcb *pcb = &p->p_addr->u_pcb; 436 register struct rwindow *rw = &pcb->pcb_rw[0]; 437 register int i; 438 439 i = pcb->pcb_nsaved; 440 if (i < 0) { 441 pcb->pcb_nsaved = 0; 442 return (0); 443 } 444 if (i == 0) 445 return (0); 446 if(rwindow_debug) 447 printf("%s[%d]: rwindow: pcb->stack:", p->p_comm, p->p_pid); 448 do { 449 if(rwindow_debug) 450 printf(" %x", rw[1].rw_in[6]); 451 if (copyout((caddr_t)rw, (caddr_t)rw[1].rw_in[6], 452 sizeof *rw)) 453 return (-1); 454 rw++; 455 } while (--i > 0); 456 if(rwindow_debug) 457 printf("\n"); 458 pcb->pcb_nsaved = 0; 459 return (0); 460 } 461 462 /* 463 * Kill user windows (before exec) by writing back to stack or pcb 464 * and then erasing any pcb tracks. Otherwise we might try to write 465 * the registers into the new process after the exec. 466 */ 467 kill_user_windows(p) 468 struct proc *p; 469 { 470 471 write_user_windows(); 472 p->p_addr->u_pcb.pcb_nsaved = 0; 473 } 474 475 /* 476 * Called from locore.s trap handling, for synchronous memory faults. 477 * 478 * This duplicates a lot of logic in trap() and perhaps should be 479 * moved there; but the bus-error-register parameters are unique to 480 * this routine. 481 * 482 * Since synchronous errors accumulate during prefetch, we can have 483 * more than one `cause'. But we do not care what the cause, here; 484 * we just want to page in the page and try again. 485 */ 486 mem_access_fault(type, ser, v, pc, psr, tf) 487 register unsigned type; 488 register int ser; 489 register u_int v; 490 register int pc, psr; 491 register struct trapframe *tf; 492 { 493 register struct proc *p; 494 register struct vmspace *vm; 495 register vm_offset_t va; 496 register int i, rv, sig = SIGBUS; 497 vm_prot_t ftype; 498 int onfault, mmucode; 499 u_quad_t sticks; 500 501 cnt.v_trap++; 502 if ((p = curproc) == NULL) /* safety check */ 503 p = &proc0; 504 sticks = p->p_sticks; 505 506 /* 507 * Figure out what to pass the VM code, and ignore the sva register 508 * value in v on text faults (text faults are always at pc). 509 * Kernel faults are somewhat different: text faults are always 510 * illegal, and data faults are extra complex. User faults must 511 * set p->p_md.md_tf, in case we decide to deliver a signal. Check 512 * for illegal virtual addresses early since those can induce more 513 * faults. 514 */ 515 if (type == T_TEXTFAULT) 516 v = pc; 517 i = (int)v >> PG_VSHIFT; 518 if (i != 0 && i != -1) 519 goto fault; 520 ftype = ser & SER_WRITE ? VM_PROT_READ|VM_PROT_WRITE : VM_PROT_READ; 521 va = trunc_page(v); 522 if (psr & PSR_PS) { 523 extern char Lfsbail[]; 524 if (type == T_TEXTFAULT) { 525 (void) splhigh(); 526 printf("text fault: pc=%x ser=%b\n", pc, ser, SER_BITS); 527 panic("kernel fault"); 528 /* NOTREACHED */ 529 } 530 /* 531 * If this was an access that we shouldn't try to page in, 532 * resume at the fault handler without any action. 533 */ 534 if (p->p_addr && p->p_addr->u_pcb.pcb_onfault == Lfsbail) 535 goto kfault; 536 537 /* 538 * During autoconfiguration, faults are never OK unless 539 * pcb_onfault is set. Once running normally we must allow 540 * exec() to cause copy-on-write faults to kernel addresses. 541 */ 542 if (cold) 543 goto kfault; 544 if (va >= KERNBASE) { 545 if (vm_fault(kernel_map, va, ftype, 0) == KERN_SUCCESS) 546 return; 547 goto kfault; 548 } 549 } else 550 p->p_md.md_tf = tf; 551 552 /* 553 * mmu_pagein returns -1 if the page is already valid, in which 554 * case we have a hard fault; it returns 1 if it loads a segment 555 * that got bumped out via LRU replacement. 556 */ 557 vm = p->p_vmspace; 558 rv = mmu_pagein(&vm->vm_pmap, va, ser & SER_WRITE ? PG_V|PG_W : PG_V); 559 if (rv < 0) 560 goto fault; 561 if (rv > 0) 562 goto out; 563 564 /* alas! must call the horrible vm code */ 565 rv = vm_fault(&vm->vm_map, (vm_offset_t)va, ftype, FALSE); 566 567 /* 568 * If this was a stack access we keep track of the maximum 569 * accessed stack size. Also, if vm_fault gets a protection 570 * failure it is due to accessing the stack region outside 571 * the current limit and we need to reflect that as an access 572 * error. 573 */ 574 if ((caddr_t)va >= vm->vm_maxsaddr) { 575 if (rv == KERN_SUCCESS) { 576 unsigned nss = clrnd(btoc(USRSTACK - va)); 577 if (nss > vm->vm_ssize) 578 vm->vm_ssize = nss; 579 } else if (rv == KERN_PROTECTION_FAILURE) 580 rv = KERN_INVALID_ADDRESS; 581 } 582 if (rv == KERN_SUCCESS) { 583 /* 584 * pmap_enter() does not enter all requests made from 585 * vm_fault into the MMU (as that causes unnecessary 586 * entries for `wired' pages). Instead, we call 587 * mmu_pagein here to make sure the new PTE gets installed. 588 */ 589 (void) mmu_pagein(&vm->vm_pmap, va, 0); 590 } else { 591 /* 592 * Pagein failed. If doing copyin/out, return to onfault 593 * address. Any other page fault in kernel, die; if user 594 * fault, deliver SIGBUS or SIGSEGV. 595 */ 596 if (rv != KERN_PROTECTION_FAILURE) 597 sig = SIGSEGV; 598 fault: 599 if (psr & PSR_PS) { 600 kfault: 601 onfault = p->p_addr ? 602 (int)p->p_addr->u_pcb.pcb_onfault : 0; 603 if (!onfault) { 604 (void) splhigh(); 605 printf("data fault: pc=%x addr=%x ser=%b\n", 606 pc, v, ser, SER_BITS); 607 panic("kernel fault"); 608 /* NOTREACHED */ 609 } 610 tf->tf_pc = onfault; 611 tf->tf_npc = onfault + 4; 612 return; 613 } 614 trapsignal(p, sig, (u_int)v); 615 } 616 out: 617 if ((psr & PSR_PS) == 0) { 618 userret(p, pc, sticks); 619 share_fpu(p, tf); 620 } 621 } 622 623 /* 624 * System calls. `pc' is just a copy of tf->tf_pc. 625 * 626 * Note that the things labelled `out' registers in the trapframe were the 627 * `in' registers within the syscall trap code (because of the automatic 628 * `save' effect of each trap). They are, however, the %o registers of the 629 * thing that made the system call, and are named that way here. 630 * 631 * The `suncompat' parameter actually only exists if COMPAT_SUNOS is defined. 632 */ 633 syscall(code, tf, pc, suncompat) 634 register u_int code; 635 register struct trapframe *tf; 636 int pc, suncompat; 637 { 638 register int i, nsys, *ap, nap; 639 register struct sysent *callp; 640 register struct proc *p; 641 int error, new; 642 struct args { 643 int i[8]; 644 } args; 645 int rval[2]; 646 u_quad_t sticks; 647 extern int nsysent; 648 extern struct pcb *cpcb; 649 650 cnt.v_syscall++; 651 p = curproc; 652 #ifdef DIAGNOSTIC 653 if (tf->tf_psr & PSR_PS) 654 panic("syscall"); 655 if (cpcb != &p->p_addr->u_pcb) 656 panic("syscall cpcb/ppcb"); 657 if (tf != (struct trapframe *)((caddr_t)cpcb + UPAGES * NBPG) - 1) 658 panic("syscall trapframe"); 659 #endif 660 sticks = p->p_sticks; 661 p->p_md.md_tf = tf; 662 new = code & (SYSCALL_G7RFLAG | SYSCALL_G2RFLAG); 663 code &= ~(SYSCALL_G7RFLAG | SYSCALL_G2RFLAG); 664 #ifdef COMPAT_SUNOS 665 if (suncompat) { 666 extern int nsunsys; 667 extern struct sysent sunsys[]; 668 669 callp = sunsys, nsys = nsunsys; 670 } else 671 #endif 672 callp = sysent, nsys = nsysent; 673 674 /* 675 * The first six system call arguments are in the six %o registers. 676 * Any arguments beyond that are in the `argument extension' area 677 * of the user's stack frame (see <machine/frame.h>). 678 * 679 * Check for ``special'' codes that alter this, namely syscall and 680 * __syscall. The latter takes a quad syscall number, so that other 681 * arguments are at their natural alignments. Adjust the number 682 * of ``easy'' arguments as appropriate; we will copy the hard 683 * ones later as needed. 684 */ 685 ap = &tf->tf_out[0]; 686 nap = 6; 687 switch (code) { 688 689 case SYS_syscall: 690 code = *ap++; 691 nap--; 692 break; 693 694 case SYS___syscall: 695 #ifdef COMPAT_SUNOS 696 if (suncompat) 697 break; 698 #endif 699 code = ap[_QUAD_LOWWORD]; 700 ap += 2; 701 nap -= 2; 702 break; 703 704 } 705 /* Callp currently points to syscall, which returns ENOSYS. */ 706 if (code < nsys) { 707 callp += code; 708 i = callp->sy_narg; 709 if (i > nap) { /* usually false */ 710 if (i > 8) 711 panic("syscall nargs"); 712 error = copyin((caddr_t)tf->tf_out[6] + 713 offsetof(struct frame, fr_argx), 714 (caddr_t)&args.i[nap], (i - nap) * sizeof(int)); 715 if (error) { 716 #ifdef KTRACE 717 if (KTRPOINT(p, KTR_SYSCALL)) 718 ktrsyscall(p->p_tracep, code, 719 callp->sy_narg, args.i); 720 #endif 721 goto bad; 722 } 723 i = nap; 724 } 725 copywords(ap, args.i, i * 4); 726 } 727 #ifdef KTRACE 728 if (KTRPOINT(p, KTR_SYSCALL)) 729 ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i); 730 #endif 731 rval[0] = 0; 732 rval[1] = tf->tf_out[1]; 733 error = (*callp->sy_call)(p, &args, rval); 734 if (error == 0) { 735 /* 736 * If fork succeeded and we are the child, our stack 737 * has moved and the pointer tf is no longer valid, 738 * and p is wrong. Compute the new trapframe pointer. 739 * (The trap frame invariably resides at the 740 * tippity-top of the u. area.) 741 */ 742 p = curproc; 743 tf = (struct trapframe *) 744 ((caddr_t)p->p_addr + UPAGES * NBPG - sizeof(*tf)); 745 /* this is done earlier: */ 746 /* p->p_md.md_tf = tf; */ 747 tf->tf_out[0] = rval[0]; 748 tf->tf_out[1] = rval[1]; 749 if (new) { 750 /* jmp %g2 (or %g7, deprecated) on success */ 751 i = tf->tf_global[new & SYSCALL_G2RFLAG ? 2 : 7]; 752 if (i & 3) { 753 error = EINVAL; 754 goto bad; 755 } 756 } else { 757 /* old system call convention: clear C on success */ 758 tf->tf_psr &= ~PSR_C; /* success */ 759 i = tf->tf_npc; 760 } 761 tf->tf_pc = i; 762 tf->tf_npc = i + 4; 763 } else if (error > 0 /*error != ERESTART && error != EJUSTRETURN*/) { 764 bad: 765 tf->tf_out[0] = error; 766 tf->tf_psr |= PSR_C; /* fail */ 767 i = tf->tf_npc; 768 tf->tf_pc = i; 769 tf->tf_npc = i + 4; 770 } 771 /* else if (error == ERESTART || error == EJUSTRETURN) */ 772 /* nothing to do */ 773 userret(p, pc, sticks); 774 #ifdef KTRACE 775 if (KTRPOINT(p, KTR_SYSRET)) 776 ktrsysret(p->p_tracep, code, error, rval[0]); 777 #endif 778 share_fpu(p, tf); 779 } 780