subr_syscall.c revision 7090
1/*- 2 * Copyright (C) 1994, David Greenman 3 * Copyright (c) 1990, 1993 4 * The Regents of the University of California. All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * the University of Utah, and William Jolitz. 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 by the University of 20 * California, Berkeley and its contributors. 21 * 4. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 * 37 * from: @(#)trap.c 7.4 (Berkeley) 5/13/91 38 * $Id: trap.c,v 1.48 1995/02/14 19:20:31 sos Exp $ 39 */ 40 41/* 42 * 386 Trap and System call handling 43 */ 44 45#include <sys/param.h> 46#include <sys/systm.h> 47#include <sys/proc.h> 48#include <sys/user.h> 49#include <sys/acct.h> 50#include <sys/kernel.h> 51#include <sys/syscall.h> 52#include <sys/sysent.h> 53#ifdef KTRACE 54#include <sys/ktrace.h> 55#endif 56 57#include <vm/vm_param.h> 58#include <vm/pmap.h> 59#include <vm/vm_kern.h> 60#include <vm/vm_map.h> 61#include <vm/vm_page.h> 62 63#include <machine/cpu.h> 64#include <machine/md_var.h> 65#include <machine/psl.h> 66#include <machine/reg.h> 67#include <machine/trap.h> 68#include <machine/../isa/isa_device.h> 69 70#include "isa.h" 71#include "npx.h" 72 73int trap_pfault __P((struct trapframe *, int)); 74void trap_fatal __P((struct trapframe *)); 75 76#define MAX_TRAP_MSG 27 77char *trap_msg[] = { 78 "", /* 0 unused */ 79 "privileged instruction fault", /* 1 T_PRIVINFLT */ 80 "", /* 2 unused */ 81 "breakpoint instruction fault", /* 3 T_BPTFLT */ 82 "", /* 4 unused */ 83 "", /* 5 unused */ 84 "arithmetic trap", /* 6 T_ARITHTRAP */ 85 "system forced exception", /* 7 T_ASTFLT */ 86 "", /* 8 unused */ 87 "general protection fault", /* 9 T_PROTFLT */ 88 "trace trap", /* 10 T_TRCTRAP */ 89 "", /* 11 unused */ 90 "page fault", /* 12 T_PAGEFLT */ 91 "", /* 13 unused */ 92 "alignment fault", /* 14 T_ALIGNFLT */ 93 "", /* 15 unused */ 94 "", /* 16 unused */ 95 "", /* 17 unused */ 96 "integer divide fault", /* 18 T_DIVIDE */ 97 "non-maskable interrupt trap", /* 19 T_NMI */ 98 "overflow trap", /* 20 T_OFLOW */ 99 "FPU bounds check fault", /* 21 T_BOUND */ 100 "FPU device not available", /* 22 T_DNA */ 101 "double fault", /* 23 T_DOUBLEFLT */ 102 "FPU operand fetch fault", /* 24 T_FPOPFLT */ 103 "invalid TSS fault", /* 25 T_TSSFLT */ 104 "segment not present fault", /* 26 T_SEGNPFLT */ 105 "stack fault", /* 27 T_STKFLT */ 106}; 107 108static inline void 109userret(p, frame, oticks) 110 struct proc *p; 111 struct trapframe *frame; 112 u_quad_t oticks; 113{ 114 int sig, s; 115 116 while ((sig = CURSIG(p)) != 0) 117 postsig(sig); 118 p->p_priority = p->p_usrpri; 119 if (want_resched) { 120 /* 121 * Since we are curproc, clock will normally just change 122 * our priority without moving us from one queue to another 123 * (since the running process is not on a queue.) 124 * If that happened after we setrunqueue ourselves but before we 125 * mi_switch()'ed, we might not be on the queue indicated by 126 * our priority. 127 */ 128 s = splclock(); 129 setrunqueue(p); 130 p->p_stats->p_ru.ru_nivcsw++; 131 mi_switch(); 132 splx(s); 133 while ((sig = CURSIG(p)) != 0) 134 postsig(sig); 135 } 136 /* 137 * Charge system time if profiling. 138 */ 139 if (p->p_flag & P_PROFIL) { 140 u_quad_t ticks = p->p_sticks - oticks; 141 142 if (ticks) { 143#ifdef PROFTIMER 144 extern int profscale; 145 addupc(frame->tf_eip, &p->p_stats->p_prof, 146 ticks * profscale); 147#else 148 addupc(frame->tf_eip, &p->p_stats->p_prof, ticks); 149#endif 150 } 151 } 152 curpriority = p->p_priority; 153} 154 155/* 156 * trap(frame): 157 * Exception, fault, and trap interface to the FreeBSD kernel. 158 * This common code is called from assembly language IDT gate entry 159 * routines that prepare a suitable stack frame, and restore this 160 * frame after the exception has been processed. 161 */ 162 163/*ARGSUSED*/ 164void 165trap(frame) 166 struct trapframe frame; 167{ 168 struct proc *p = curproc; 169 u_quad_t sticks = 0; 170 int i = 0, ucode = 0, type, code; 171#ifdef DIAGNOSTIC 172 u_long eva; 173#endif 174 175 type = frame.tf_trapno; 176 code = frame.tf_err; 177 178 if (ISPL(frame.tf_cs) == SEL_UPL) { 179 /* user trap */ 180 181 sticks = p->p_sticks; 182 p->p_md.md_regs = (int *)&frame; 183 184 switch (type) { 185 case T_PRIVINFLT: /* privileged instruction fault */ 186 ucode = type; 187 i = SIGILL; 188 break; 189 190 case T_BPTFLT: /* bpt instruction fault */ 191 case T_TRCTRAP: /* trace trap */ 192 frame.tf_eflags &= ~PSL_T; 193 i = SIGTRAP; 194 break; 195 196 case T_ARITHTRAP: /* arithmetic trap */ 197 ucode = code; 198 i = SIGFPE; 199 break; 200 201 case T_ASTFLT: /* Allow process switch */ 202 astoff(); 203 cnt.v_soft++; 204 if (p->p_flag & P_OWEUPC) { 205 addupc(frame.tf_eip, &p->p_stats->p_prof, 1); 206 p->p_flag &= ~P_OWEUPC; 207 } 208 goto out; 209 210 case T_PROTFLT: /* general protection fault */ 211 case T_SEGNPFLT: /* segment not present fault */ 212 case T_STKFLT: /* stack fault */ 213 case T_TSSFLT: /* invalid TSS fault */ 214 case T_DOUBLEFLT: /* double fault */ 215 default: 216 ucode = code + BUS_SEGM_FAULT ; 217 i = SIGBUS; 218 break; 219 220 case T_PAGEFLT: /* page fault */ 221 i = trap_pfault(&frame, TRUE); 222 if (i == -1) 223 return; 224 if (i == 0) 225 goto out; 226 227 ucode = T_PAGEFLT; 228 break; 229 230 case T_DIVIDE: /* integer divide fault */ 231 ucode = FPE_INTDIV_TRAP; 232 i = SIGFPE; 233 break; 234 235#if NISA > 0 236 case T_NMI: 237#ifdef DDB 238 /* NMI can be hooked up to a pushbutton for debugging */ 239 printf ("NMI ... going to debugger\n"); 240 if (kdb_trap (type, 0, &frame)) 241 return; 242#endif 243 /* machine/parity/power fail/"kitchen sink" faults */ 244 if (isa_nmi(code) == 0) return; 245 panic("NMI indicates hardware failure"); 246#endif 247 248 case T_OFLOW: /* integer overflow fault */ 249 ucode = FPE_INTOVF_TRAP; 250 i = SIGFPE; 251 break; 252 253 case T_BOUND: /* bounds check fault */ 254 ucode = FPE_SUBRNG_TRAP; 255 i = SIGFPE; 256 break; 257 258 case T_DNA: 259#if NNPX > 0 260 /* if a transparent fault (due to context switch "late") */ 261 if (npxdna()) 262 return; 263#endif /* NNPX > 0 */ 264 265#if defined(MATH_EMULATE) || defined(GPL_MATH_EMULATE) 266 i = math_emulate(&frame); 267 if (i == 0) { 268 if (!(frame.tf_eflags & PSL_T)) 269 return; 270 frame.tf_eflags &= ~PSL_T; 271 i = SIGTRAP; 272 } 273 /* else ucode = emulator_only_knows() XXX */ 274#else /* MATH_EMULATE || GPL_MATH_EMULATE */ 275 i = SIGFPE; 276 ucode = FPE_FPU_NP_TRAP; 277#endif /* MATH_EMULATE || GPL_MATH_EMULATE */ 278 break; 279 280 case T_FPOPFLT: /* FPU operand fetch fault */ 281 ucode = T_FPOPFLT; 282 i = SIGILL; 283 break; 284 } 285 } else { 286 /* kernel trap */ 287 288 switch (type) { 289 case T_PAGEFLT: /* page fault */ 290 (void) trap_pfault(&frame, FALSE); 291 return; 292 293 case T_PROTFLT: /* general protection fault */ 294 case T_SEGNPFLT: /* segment not present fault */ 295 /* 296 * Invalid segment selectors and out of bounds 297 * %eip's and %esp's can be set up in user mode. 298 * This causes a fault in kernel mode when the 299 * kernel tries to return to user mode. We want 300 * to get this fault so that we can fix the 301 * problem here and not have to check all the 302 * selectors and pointers when the user changes 303 * them. 304 */ 305#define MAYBE_DORETI_FAULT(where, whereto) \ 306 do { \ 307 if (frame.tf_eip == (int)where) { \ 308 frame.tf_eip = (int)whereto; \ 309 return; \ 310 } \ 311 } while (0) 312 313 if (intr_nesting_level == 0) { 314 MAYBE_DORETI_FAULT(doreti_iret, 315 doreti_iret_fault); 316 MAYBE_DORETI_FAULT(doreti_popl_ds, 317 doreti_popl_ds_fault); 318 MAYBE_DORETI_FAULT(doreti_popl_es, 319 doreti_popl_es_fault); 320 } 321 if (curpcb && curpcb->pcb_onfault) { 322 frame.tf_eip = (int)curpcb->pcb_onfault; 323 return; 324 } 325 break; 326 327 case T_TSSFLT: 328 /* 329 * PSL_NT can be set in user mode and isn't cleared 330 * automatically when the kernel is entered. This 331 * causes a TSS fault when the kernel attempts to 332 * `iret' because the TSS link is uninitialized. We 333 * want to get this fault so that we can fix the 334 * problem here and not every time the kernel is 335 * entered. 336 */ 337 if (frame.tf_eflags & PSL_NT) { 338 frame.tf_eflags &= ~PSL_NT; 339 return; 340 } 341 break; 342 343#ifdef DDB 344 case T_BPTFLT: 345 case T_TRCTRAP: 346 if (kdb_trap (type, 0, &frame)) 347 return; 348 break; 349#else 350 case T_TRCTRAP: /* trace trap -- someone single stepping lcall's */ 351 /* Q: how do we turn it on again? */ 352 frame.tf_eflags &= ~PSL_T; 353 return; 354#endif 355 356#if NISA > 0 357 case T_NMI: 358#ifdef DDB 359 /* NMI can be hooked up to a pushbutton for debugging */ 360 printf ("NMI ... going to debugger\n"); 361 if (kdb_trap (type, 0, &frame)) 362 return; 363#endif 364 /* machine/parity/power fail/"kitchen sink" faults */ 365 if (isa_nmi(code) == 0) return; 366 /* FALL THROUGH */ 367#endif 368 } 369 370 trap_fatal(&frame); 371 return; 372 } 373 374 trapsignal(p, i, ucode); 375 376#ifdef DIAGNOSTIC 377 eva = rcr2(); 378 if (type <= MAX_TRAP_MSG) { 379 uprintf("fatal process exception: %s", 380 trap_msg[type]); 381 if ((type == T_PAGEFLT) || (type == T_PROTFLT)) 382 uprintf(", fault VA = 0x%x", eva); 383 uprintf("\n"); 384 } 385#endif 386 387out: 388 userret(p, &frame, sticks); 389} 390 391int 392trap_pfault(frame, usermode) 393 struct trapframe *frame; 394 int usermode; 395{ 396 vm_offset_t va; 397 struct vmspace *vm = NULL; 398 vm_map_t map = 0; 399 int rv = 0; 400 vm_prot_t ftype; 401 int eva; 402 struct proc *p = curproc; 403 404 eva = rcr2(); 405 va = trunc_page((vm_offset_t)eva); 406 407 if (va >= KERNBASE) { 408 /* 409 * Don't allow user-mode faults in kernel address space. 410 */ 411 if (usermode) 412 goto nogo; 413 414 map = kernel_map; 415 } else { 416 /* 417 * This is a fault on non-kernel virtual memory. 418 * vm is initialized above to NULL. If curproc is NULL 419 * or curproc->p_vmspace is NULL the fault is fatal. 420 */ 421 if (p != NULL) 422 vm = p->p_vmspace; 423 424 if (vm == NULL) 425 goto nogo; 426 427 map = &vm->vm_map; 428 } 429 430 if (frame->tf_err & PGEX_W) 431 ftype = VM_PROT_READ | VM_PROT_WRITE; 432 else 433 ftype = VM_PROT_READ; 434 435 if (map != kernel_map) { 436 vm_offset_t v = (vm_offset_t) vtopte(va); 437 vm_page_t ptepg; 438 439 /* 440 * Keep swapout from messing with us during this 441 * critical time. 442 */ 443 ++p->p_lock; 444 445 /* 446 * Grow the stack if necessary 447 */ 448 if ((caddr_t)va > vm->vm_maxsaddr 449 && (caddr_t)va < (caddr_t)USRSTACK) { 450 if (!grow(p, va)) { 451 rv = KERN_FAILURE; 452 --p->p_lock; 453 goto nogo; 454 } 455 } 456 457 /* 458 * Check if page table is mapped, if not, 459 * fault it first 460 */ 461 462 /* Fault the pte only if needed: */ 463 *(volatile char *)v += 0; 464 465 pmap_use_pt( vm_map_pmap(map), va); 466 467 /* Fault in the user page: */ 468 rv = vm_fault(map, va, ftype, FALSE); 469 470 pmap_unuse_pt( vm_map_pmap(map), va); 471 472 --p->p_lock; 473 } else { 474 /* 475 * Since we know that kernel virtual address addresses 476 * always have pte pages mapped, we just have to fault 477 * the page. 478 */ 479 rv = vm_fault(map, va, ftype, FALSE); 480 } 481 482 if (rv == KERN_SUCCESS) 483 return (0); 484nogo: 485 if (!usermode) { 486 if (curpcb && curpcb->pcb_onfault) { 487 frame->tf_eip = (int)curpcb->pcb_onfault; 488 return (0); 489 } 490 trap_fatal(frame); 491 return (-1); 492 } 493 494 /* kludge to pass faulting virtual address to sendsig */ 495 frame->tf_err = eva; 496 497 return((rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV); 498} 499 500void 501trap_fatal(frame) 502 struct trapframe *frame; 503{ 504 int code, type, eva; 505 struct soft_segment_descriptor softseg; 506 507 code = frame->tf_err; 508 type = frame->tf_trapno; 509 eva = rcr2(); 510 sdtossd(&gdt[IDXSEL(frame->tf_cs & 0xffff)].sd, &softseg); 511 512 if (type <= MAX_TRAP_MSG) 513 printf("\n\nFatal trap %d: %s while in %s mode\n", 514 type, trap_msg[type], 515 ISPL(frame->tf_cs) == SEL_UPL ? "user" : "kernel"); 516 if (type == T_PAGEFLT) { 517 printf("fault virtual address = 0x%x\n", eva); 518 printf("fault code = %s %s, %s\n", 519 code & PGEX_U ? "user" : "supervisor", 520 code & PGEX_W ? "write" : "read", 521 code & PGEX_P ? "protection violation" : "page not present"); 522 } 523 printf("instruction pointer = 0x%x:0x%x\n", frame->tf_cs & 0xffff, frame->tf_eip); 524 printf("code segment = base 0x%x, limit 0x%x, type 0x%x\n", 525 softseg.ssd_base, softseg.ssd_limit, softseg.ssd_type); 526 printf(" = DPL %d, pres %d, def32 %d, gran %d\n", 527 softseg.ssd_dpl, softseg.ssd_p, softseg.ssd_def32, softseg.ssd_gran); 528 printf("processor eflags = "); 529 if (frame->tf_eflags & PSL_T) 530 printf("trace/trap, "); 531 if (frame->tf_eflags & PSL_I) 532 printf("interrupt enabled, "); 533 if (frame->tf_eflags & PSL_NT) 534 printf("nested task, "); 535 if (frame->tf_eflags & PSL_RF) 536 printf("resume, "); 537 if (frame->tf_eflags & PSL_VM) 538 printf("vm86, "); 539 printf("IOPL = %d\n", (frame->tf_eflags & PSL_IOPL) >> 12); 540 printf("current process = "); 541 if (curproc) { 542 printf("%lu (%s)\n", 543 (u_long)curproc->p_pid, curproc->p_comm ? 544 curproc->p_comm : ""); 545 } else { 546 printf("Idle\n"); 547 } 548 printf("interrupt mask = "); 549 if ((cpl & net_imask) == net_imask) 550 printf("net "); 551 if ((cpl & tty_imask) == tty_imask) 552 printf("tty "); 553 if ((cpl & bio_imask) == bio_imask) 554 printf("bio "); 555 if (cpl == 0) 556 printf("none"); 557 printf("\n"); 558 559#ifdef KDB 560 if (kdb_trap(&psl)) 561 return; 562#endif 563#ifdef DDB 564 if (kdb_trap (type, 0, frame)) 565 return; 566#endif 567 if (type <= MAX_TRAP_MSG) 568 panic(trap_msg[type]); 569 else 570 panic("unknown/reserved trap"); 571} 572 573/* 574 * Compensate for 386 brain damage (missing URKR). 575 * This is a little simpler than the pagefault handler in trap() because 576 * it the page tables have already been faulted in and high addresses 577 * are thrown out early for other reasons. 578 */ 579int trapwrite(addr) 580 unsigned addr; 581{ 582 struct proc *p; 583 vm_offset_t va, v; 584 struct vmspace *vm; 585 int rv; 586 587 va = trunc_page((vm_offset_t)addr); 588 /* 589 * XXX - MAX is END. Changed > to >= for temp. fix. 590 */ 591 if (va >= VM_MAXUSER_ADDRESS) 592 return (1); 593 594 p = curproc; 595 vm = p->p_vmspace; 596 597 ++p->p_lock; 598 599 if ((caddr_t)va >= vm->vm_maxsaddr 600 && (caddr_t)va < (caddr_t)USRSTACK) { 601 if (!grow(p, va)) { 602 --p->p_lock; 603 return (1); 604 } 605 } 606 607 v = trunc_page(vtopte(va)); 608 609 /* 610 * wire the pte page 611 */ 612 if (va < USRSTACK) { 613 vm_map_pageable(&vm->vm_map, v, round_page(v+1), FALSE); 614 } 615 616 /* 617 * fault the data page 618 */ 619 rv = vm_fault(&vm->vm_map, va, VM_PROT_READ|VM_PROT_WRITE, FALSE); 620 621 /* 622 * unwire the pte page 623 */ 624 if (va < USRSTACK) { 625 vm_map_pageable(&vm->vm_map, v, round_page(v+1), TRUE); 626 } 627 628 --p->p_lock; 629 630 if (rv != KERN_SUCCESS) 631 return 1; 632 633 return (0); 634} 635 636/* 637 * syscall(frame): 638 * System call request from POSIX system call gate interface to kernel. 639 * Like trap(), argument is call by reference. 640 */ 641/*ARGSUSED*/ 642void 643syscall(frame) 644 struct trapframe frame; 645{ 646 caddr_t params; 647 int i; 648 struct sysent *callp; 649 struct proc *p = curproc; 650 u_quad_t sticks; 651 int error, opc; 652 int args[8], rval[2]; 653 u_int code; 654 655 sticks = p->p_sticks; 656 if (ISPL(frame.tf_cs) != SEL_UPL) 657 panic("syscall"); 658 659 code = frame.tf_eax; 660 p->p_md.md_regs = (int *)&frame; 661 params = (caddr_t)frame.tf_esp + sizeof (int) ; 662 663 /* 664 * Reconstruct pc, assuming lcall $X,y is 7 bytes, as it is always. 665 */ 666 opc = frame.tf_eip - 7; 667 /* 668 * Need to check if this is a 32 bit or 64 bit syscall. 669 */ 670 if (code == SYS_syscall) { 671 /* 672 * Code is first argument, followed by actual args. 673 */ 674 code = fuword(params); 675 params += sizeof (int); 676 } else if (code == SYS___syscall) { 677 /* 678 * Like syscall, but code is a quad, so as to maintain 679 * quad alignment for the rest of the arguments. 680 */ 681 code = fuword(params + _QUAD_LOWWORD * sizeof(int)); 682 params += sizeof(quad_t); 683 } 684 685 if (p->p_sysent->sv_mask) 686 code = code & p->p_sysent->sv_mask; 687 688 if (code >= p->p_sysent->sv_size) 689 callp = &p->p_sysent->sv_table[0]; 690 else 691 callp = &p->p_sysent->sv_table[code]; 692 693 if ((i = callp->sy_narg * sizeof (int)) && 694 (error = copyin(params, (caddr_t)args, (u_int)i))) { 695#ifdef KTRACE 696 if (KTRPOINT(p, KTR_SYSCALL)) 697 ktrsyscall(p->p_tracep, code, callp->sy_narg, args); 698#endif 699 goto bad; 700 } 701#ifdef KTRACE 702 if (KTRPOINT(p, KTR_SYSCALL)) 703 ktrsyscall(p->p_tracep, code, callp->sy_narg, args); 704#endif 705 rval[0] = 0; 706 rval[1] = frame.tf_edx; 707 708 error = (*callp->sy_call)(p, args, rval); 709 710 switch (error) { 711 712 case 0: 713 /* 714 * Reinitialize proc pointer `p' as it may be different 715 * if this is a child returning from fork syscall. 716 */ 717 p = curproc; 718 frame.tf_eax = rval[0]; 719 frame.tf_edx = rval[1]; 720 frame.tf_eflags &= ~PSL_C; /* carry bit */ 721 break; 722 723 case ERESTART: 724 frame.tf_eip = opc; 725 break; 726 727 case EJUSTRETURN: 728 break; 729 730 default: 731 bad: 732 if (p->p_sysent->sv_errsize) 733 if (error >= p->p_sysent->sv_errsize) 734 error = -1; /* XXX */ 735 else 736 error = p->p_sysent->sv_errtbl[error]; 737 frame.tf_eax = error; 738 frame.tf_eflags |= PSL_C; /* carry bit */ 739 break; 740 } 741 742 userret(p, &frame, sticks); 743 744#ifdef KTRACE 745 if (KTRPOINT(p, KTR_SYSRET)) 746 ktrsysret(p->p_tracep, code, error, rval[0]); 747#endif 748} 749 750#ifdef COMPAT_LINUX 751/* 752 * linux_syscall(frame): 753 */ 754/*ARGSUSED*/ 755void 756linux_syscall(frame) 757 struct trapframe frame; 758{ 759 caddr_t params; 760 int i; 761 struct proc *p = curproc; 762 struct sysent *callp; 763 u_quad_t sticks; 764 int error, opc; 765 int rval[2]; 766 int code; 767 struct linux_syscall_args { 768 int ebx; 769 int ecx; 770 int edx; 771 int esi; 772 int edi; 773 int ebp; 774 int eax; 775 } args; 776 777 args.ebx = frame.tf_ebx; 778 args.ecx = frame.tf_ecx; 779 args.edx = frame.tf_edx; 780 args.esi = frame.tf_esi; 781 args.edi = frame.tf_edi; 782 args.ebp = frame.tf_ebp; 783 args.eax = frame.tf_eax; 784 785 sticks = p->p_sticks; 786 if (ISPL(frame.tf_cs) != SEL_UPL) 787 panic("linux syscall"); 788 789 code = frame.tf_eax; 790 p->p_md.md_regs = (int *)&frame; 791 params = (caddr_t)frame.tf_esp + sizeof (int) ; 792 793 /* 794 * Reconstruct pc, assuming lcall $X,y is 7 bytes, as it is always. 795 * THIS IS WRONG FOR LINUX XXX SOS 796 * SIZE OF INT 0x80 (2??) NEEDED HERE !!! 797 */ 798 opc = frame.tf_eip - 2; /* was 7 */ 799 if (code == 0) { 800 code = fuword(params); 801 params += sizeof (int); 802 } 803 if (p->p_sysent->sv_mask) 804 code = code & p->p_sysent->sv_mask; 805 806 if (code < 0 || code >= p->p_sysent->sv_size) 807 callp = &p->p_sysent->sv_table[0]; 808 else 809 callp = &p->p_sysent->sv_table[code]; 810 811#ifdef KTRACE 812 if (KTRPOINT(p, KTR_SYSCALL)) 813 ktrsyscall(p->p_tracep, code, callp->sy_narg, &args); 814#endif 815 816#ifdef KTRACE 817 if (KTRPOINT(p, KTR_SYSCALL)) 818 ktrsyscall(p->p_tracep, code, callp->sy_narg, &args); 819#endif 820 rval[0] = 0; 821 rval[1] = frame.tf_edx; 822 823 error = (*callp->sy_call)(p, &args, rval); 824 825 switch (error) { 826 827 case 0: 828 /* 829 * Reinitialize proc pointer `p' as it may be different 830 * if this is a child returning from fork syscall. 831 */ 832 p = curproc; 833 frame.tf_eax = rval[0]; 834 frame.tf_eflags &= ~PSL_C; /* carry bit */ 835 break; 836 837 case ERESTART: 838 frame.tf_eip = opc; 839 break; 840 841 case EJUSTRETURN: 842 break; 843 844 default: 845 bad: 846 if (p->p_sysent->sv_errsize) 847 if (error >= p->p_sysent->sv_errsize) 848 error = -1; /* XXX */ 849 else 850 error = p->p_sysent->sv_errtbl[error]; 851 frame.tf_eax = -error; 852 frame.tf_eflags |= PSL_C; /* carry bit */ 853 break; 854 } 855 856 userret(p, &frame, sticks); 857 858#ifdef KTRACE 859 if (KTRPOINT(p, KTR_SYSRET)) 860 ktrsysret(p->p_tracep, code, error, rval[0]); 861#endif 862} 863#endif /* COMPAT_LINUX */ 864