subr_syscall.c revision 12817
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.64 1995/12/09 20:40:43 phk 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/acct.h> 49#include <sys/kernel.h> 50#include <sys/syscall.h> 51#include <sys/sysent.h> 52#include <sys/queue.h> 53#include <sys/vmmeter.h> 54#ifdef KTRACE 55#include <sys/ktrace.h> 56#endif 57 58#include <vm/vm.h> 59#include <vm/vm_param.h> 60#include <vm/vm_prot.h> 61#include <vm/lock.h> 62#include <vm/pmap.h> 63#include <vm/vm_kern.h> 64#include <vm/vm_map.h> 65#include <vm/vm_page.h> 66#include <vm/vm_extern.h> 67 68#include <sys/user.h> 69 70#include <machine/cpu.h> 71#include <machine/md_var.h> 72#include <machine/psl.h> 73#include <machine/reg.h> 74#include <machine/trap.h> 75#include <machine/../isa/isa_device.h> 76 77#ifdef POWERFAIL_NMI 78# include <syslog.h> 79# include <machine/clock.h> 80#endif 81 82#include "isa.h" 83#include "npx.h" 84 85int (*pmath_emulate) __P((struct trapframe *)); 86 87extern void trap __P((struct trapframe frame)); 88extern int trapwrite __P((unsigned addr)); 89extern void syscall __P((struct trapframe frame)); 90extern void linux_syscall __P((struct trapframe frame)); 91 92static int trap_pfault __P((struct trapframe *, int)); 93static void trap_fatal __P((struct trapframe *)); 94 95extern inthand_t IDTVEC(syscall); 96 97#define MAX_TRAP_MSG 27 98static char *trap_msg[] = { 99 "", /* 0 unused */ 100 "privileged instruction fault", /* 1 T_PRIVINFLT */ 101 "", /* 2 unused */ 102 "breakpoint instruction fault", /* 3 T_BPTFLT */ 103 "", /* 4 unused */ 104 "", /* 5 unused */ 105 "arithmetic trap", /* 6 T_ARITHTRAP */ 106 "system forced exception", /* 7 T_ASTFLT */ 107 "", /* 8 unused */ 108 "general protection fault", /* 9 T_PROTFLT */ 109 "trace trap", /* 10 T_TRCTRAP */ 110 "", /* 11 unused */ 111 "page fault", /* 12 T_PAGEFLT */ 112 "", /* 13 unused */ 113 "alignment fault", /* 14 T_ALIGNFLT */ 114 "", /* 15 unused */ 115 "", /* 16 unused */ 116 "", /* 17 unused */ 117 "integer divide fault", /* 18 T_DIVIDE */ 118 "non-maskable interrupt trap", /* 19 T_NMI */ 119 "overflow trap", /* 20 T_OFLOW */ 120 "FPU bounds check fault", /* 21 T_BOUND */ 121 "FPU device not available", /* 22 T_DNA */ 122 "double fault", /* 23 T_DOUBLEFLT */ 123 "FPU operand fetch fault", /* 24 T_FPOPFLT */ 124 "invalid TSS fault", /* 25 T_TSSFLT */ 125 "segment not present fault", /* 26 T_SEGNPFLT */ 126 "stack fault", /* 27 T_STKFLT */ 127}; 128 129static void userret __P((struct proc *p, struct trapframe *frame, 130 u_quad_t oticks)); 131 132static inline void 133userret(p, frame, oticks) 134 struct proc *p; 135 struct trapframe *frame; 136 u_quad_t oticks; 137{ 138 int sig, s; 139 140 while ((sig = CURSIG(p)) != 0) 141 postsig(sig); 142 p->p_priority = p->p_usrpri; 143 if (want_resched) { 144 /* 145 * Since we are curproc, clock will normally just change 146 * our priority without moving us from one queue to another 147 * (since the running process is not on a queue.) 148 * If that happened after we setrunqueue ourselves but before we 149 * mi_switch()'ed, we might not be on the queue indicated by 150 * our priority. 151 */ 152 s = splclock(); 153 setrunqueue(p); 154 p->p_stats->p_ru.ru_nivcsw++; 155 mi_switch(); 156 splx(s); 157 while ((sig = CURSIG(p)) != 0) 158 postsig(sig); 159 } 160 /* 161 * Charge system time if profiling. 162 */ 163 if (p->p_flag & P_PROFIL) { 164 u_quad_t ticks = p->p_sticks - oticks; 165 166 if (ticks) { 167#ifdef PROFTIMER 168 extern int profscale; 169 addupc(frame->tf_eip, &p->p_stats->p_prof, 170 ticks * profscale); 171#else 172 addupc(frame->tf_eip, &p->p_stats->p_prof, ticks); 173#endif 174 } 175 } 176 curpriority = p->p_priority; 177} 178 179/* 180 * Exception, fault, and trap interface to the FreeBSD kernel. 181 * This common code is called from assembly language IDT gate entry 182 * routines that prepare a suitable stack frame, and restore this 183 * frame after the exception has been processed. 184 */ 185 186void 187trap(frame) 188 struct trapframe frame; 189{ 190 struct proc *p = curproc; 191 u_quad_t sticks = 0; 192 int i = 0, ucode = 0, type, code; 193#ifdef DEBUG 194 u_long eva; 195#endif 196 197 type = frame.tf_trapno; 198 code = frame.tf_err; 199 200 if (ISPL(frame.tf_cs) == SEL_UPL) { 201 /* user trap */ 202 203 sticks = p->p_sticks; 204 p->p_md.md_regs = (int *)&frame; 205 206 switch (type) { 207 case T_PRIVINFLT: /* privileged instruction fault */ 208 ucode = type; 209 i = SIGILL; 210 break; 211 212 case T_BPTFLT: /* bpt instruction fault */ 213 case T_TRCTRAP: /* trace trap */ 214 frame.tf_eflags &= ~PSL_T; 215 i = SIGTRAP; 216 break; 217 218 case T_ARITHTRAP: /* arithmetic trap */ 219 ucode = code; 220 i = SIGFPE; 221 break; 222 223 case T_ASTFLT: /* Allow process switch */ 224 astoff(); 225 cnt.v_soft++; 226 if (p->p_flag & P_OWEUPC) { 227 addupc(frame.tf_eip, &p->p_stats->p_prof, 1); 228 p->p_flag &= ~P_OWEUPC; 229 } 230 goto out; 231 232 case T_PROTFLT: /* general protection fault */ 233 case T_SEGNPFLT: /* segment not present fault */ 234 case T_STKFLT: /* stack fault */ 235 case T_TSSFLT: /* invalid TSS fault */ 236 case T_DOUBLEFLT: /* double fault */ 237 default: 238 ucode = code + BUS_SEGM_FAULT ; 239 i = SIGBUS; 240 break; 241 242 case T_PAGEFLT: /* page fault */ 243 i = trap_pfault(&frame, TRUE); 244 if (i == -1) 245 return; 246 if (i == 0) 247 goto out; 248 249 ucode = T_PAGEFLT; 250 break; 251 252 case T_DIVIDE: /* integer divide fault */ 253 ucode = FPE_INTDIV_TRAP; 254 i = SIGFPE; 255 break; 256 257#if NISA > 0 258 case T_NMI: 259#ifdef POWERFAIL_NMI 260 goto handle_powerfail; 261#else /* !POWERFAIL_NMI */ 262#ifdef DDB 263 /* NMI can be hooked up to a pushbutton for debugging */ 264 printf ("NMI ... going to debugger\n"); 265 if (kdb_trap (type, 0, &frame)) 266 return; 267#endif /* DDB */ 268 /* machine/parity/power fail/"kitchen sink" faults */ 269 if (isa_nmi(code) == 0) return; 270 panic("NMI indicates hardware failure"); 271#endif /* POWERFAIL_NMI */ 272#endif /* NISA > 0 */ 273 274 case T_OFLOW: /* integer overflow fault */ 275 ucode = FPE_INTOVF_TRAP; 276 i = SIGFPE; 277 break; 278 279 case T_BOUND: /* bounds check fault */ 280 ucode = FPE_SUBRNG_TRAP; 281 i = SIGFPE; 282 break; 283 284 case T_DNA: 285#if NNPX > 0 286 /* if a transparent fault (due to context switch "late") */ 287 if (npxdna()) 288 return; 289#endif /* NNPX > 0 */ 290 291 if (!pmath_emulate) { 292 i = SIGFPE; 293 ucode = FPE_FPU_NP_TRAP; 294 break; 295 } 296 i = (*pmath_emulate)(&frame); 297 if (i == 0) { 298 if (!(frame.tf_eflags & PSL_T)) 299 return; 300 frame.tf_eflags &= ~PSL_T; 301 i = SIGTRAP; 302 } 303 /* else ucode = emulator_only_knows() XXX */ 304 break; 305 306 case T_FPOPFLT: /* FPU operand fetch fault */ 307 ucode = T_FPOPFLT; 308 i = SIGILL; 309 break; 310 } 311 } else { 312 /* kernel trap */ 313 314 switch (type) { 315 case T_PAGEFLT: /* page fault */ 316 (void) trap_pfault(&frame, FALSE); 317 return; 318 319 case T_PROTFLT: /* general protection fault */ 320 case T_SEGNPFLT: /* segment not present fault */ 321 /* 322 * Invalid segment selectors and out of bounds 323 * %eip's and %esp's can be set up in user mode. 324 * This causes a fault in kernel mode when the 325 * kernel tries to return to user mode. We want 326 * to get this fault so that we can fix the 327 * problem here and not have to check all the 328 * selectors and pointers when the user changes 329 * them. 330 */ 331#define MAYBE_DORETI_FAULT(where, whereto) \ 332 do { \ 333 if (frame.tf_eip == (int)where) { \ 334 frame.tf_eip = (int)whereto; \ 335 return; \ 336 } \ 337 } while (0) 338 339 if (intr_nesting_level == 0) { 340 MAYBE_DORETI_FAULT(doreti_iret, 341 doreti_iret_fault); 342 MAYBE_DORETI_FAULT(doreti_popl_ds, 343 doreti_popl_ds_fault); 344 MAYBE_DORETI_FAULT(doreti_popl_es, 345 doreti_popl_es_fault); 346 } 347 if (curpcb && curpcb->pcb_onfault) { 348 frame.tf_eip = (int)curpcb->pcb_onfault; 349 return; 350 } 351 break; 352 353 case T_TSSFLT: 354 /* 355 * PSL_NT can be set in user mode and isn't cleared 356 * automatically when the kernel is entered. This 357 * causes a TSS fault when the kernel attempts to 358 * `iret' because the TSS link is uninitialized. We 359 * want to get this fault so that we can fix the 360 * problem here and not every time the kernel is 361 * entered. 362 */ 363 if (frame.tf_eflags & PSL_NT) { 364 frame.tf_eflags &= ~PSL_NT; 365 return; 366 } 367 break; 368 369 case T_TRCTRAP: /* trace trap */ 370 if (frame.tf_eip == (int)IDTVEC(syscall)) { 371 /* 372 * We've just entered system mode via the 373 * syscall lcall. Continue single stepping 374 * silently until the syscall handler has 375 * saved the flags. 376 */ 377 return; 378 } 379 if (frame.tf_eip == (int)IDTVEC(syscall) + 1) { 380 /* 381 * The syscall handler has now saved the 382 * flags. Stop single stepping it. 383 */ 384 frame.tf_eflags &= ~PSL_T; 385 return; 386 } 387 /* 388 * Fall through. 389 */ 390 case T_BPTFLT: 391 /* 392 * If DDB is enabled, let it handle the debugger trap. 393 * Otherwise, debugger traps "can't happen". 394 */ 395#ifdef DDB 396 if (kdb_trap (type, 0, &frame)) 397 return; 398#endif 399 break; 400 401#if NISA > 0 402 case T_NMI: 403#ifdef POWERFAIL_NMI 404#ifndef TIMER_FREQ 405# define TIMER_FREQ 1193182 406#endif 407 handle_powerfail: 408 { 409 static unsigned lastalert = 0; 410 411 if(time.tv_sec - lastalert > 10) 412 { 413 log(LOG_WARNING, "NMI: power fail\n"); 414 sysbeep(TIMER_FREQ/880, hz); 415 lastalert = time.tv_sec; 416 } 417 return; 418 } 419#else /* !POWERFAIL_NMI */ 420#ifdef DDB 421 /* NMI can be hooked up to a pushbutton for debugging */ 422 printf ("NMI ... going to debugger\n"); 423 if (kdb_trap (type, 0, &frame)) 424 return; 425#endif /* DDB */ 426 /* machine/parity/power fail/"kitchen sink" faults */ 427 if (isa_nmi(code) == 0) return; 428 /* FALL THROUGH */ 429#endif /* POWERFAIL_NMI */ 430#endif /* NISA > 0 */ 431 } 432 433 trap_fatal(&frame); 434 return; 435 } 436 437 trapsignal(p, i, ucode); 438 439#ifdef DEBUG 440 eva = rcr2(); 441 if (type <= MAX_TRAP_MSG) { 442 uprintf("fatal process exception: %s", 443 trap_msg[type]); 444 if ((type == T_PAGEFLT) || (type == T_PROTFLT)) 445 uprintf(", fault VA = 0x%x", eva); 446 uprintf("\n"); 447 } 448#endif 449 450out: 451 userret(p, &frame, sticks); 452} 453 454#ifdef notyet 455/* 456 * This version doesn't allow a page fault to user space while 457 * in the kernel. The rest of the kernel needs to be made "safe" 458 * before this can be used. I think the only things remaining 459 * to be made safe are the iBCS2 code and the process tracing/ 460 * debugging code. 461 */ 462static int 463trap_pfault(frame, usermode) 464 struct trapframe *frame; 465 int usermode; 466{ 467 vm_offset_t va; 468 struct vmspace *vm = NULL; 469 vm_map_t map = 0; 470 int rv = 0; 471 vm_prot_t ftype; 472 int eva; 473 struct proc *p = curproc; 474 475 if (frame->tf_err & PGEX_W) 476 ftype = VM_PROT_READ | VM_PROT_WRITE; 477 else 478 ftype = VM_PROT_READ; 479 480 eva = rcr2(); 481 va = trunc_page((vm_offset_t)eva); 482 483 if (va < VM_MIN_KERNEL_ADDRESS) { 484 vm_offset_t v; 485 vm_page_t ptepg; 486 487 if (p == NULL || 488 (!usermode && va < VM_MAXUSER_ADDRESS && 489 (curpcb == NULL || curpcb->pcb_onfault == NULL))) { 490 trap_fatal(frame); 491 return (-1); 492 } 493 494 /* 495 * This is a fault on non-kernel virtual memory. 496 * vm is initialized above to NULL. If curproc is NULL 497 * or curproc->p_vmspace is NULL the fault is fatal. 498 */ 499 vm = p->p_vmspace; 500 if (vm == NULL) 501 goto nogo; 502 503 map = &vm->vm_map; 504 505 /* 506 * Keep swapout from messing with us during this 507 * critical time. 508 */ 509 ++p->p_lock; 510 511 /* 512 * Grow the stack if necessary 513 */ 514 if ((caddr_t)va > vm->vm_maxsaddr 515 && (caddr_t)va < (caddr_t)USRSTACK) { 516 if (!grow(p, va)) { 517 rv = KERN_FAILURE; 518 --p->p_lock; 519 goto nogo; 520 } 521 } 522 523 /* 524 * Check if page table is mapped, if not, 525 * fault it first 526 */ 527 v = (vm_offset_t) vtopte(va); 528 529 /* Fault the pte only if needed: */ 530 if (*((int *)vtopte(v)) == 0) 531 (void) vm_fault(map, trunc_page(v), VM_PROT_WRITE, FALSE); 532 533 pmap_use_pt( vm_map_pmap(map), va); 534 535 /* Fault in the user page: */ 536 rv = vm_fault(map, va, ftype, FALSE); 537 538 pmap_unuse_pt( vm_map_pmap(map), va); 539 540 --p->p_lock; 541 } else { 542 /* 543 * Don't allow user-mode faults in kernel address space. 544 */ 545 if (usermode) 546 goto nogo; 547 548 /* 549 * Since we know that kernel virtual address addresses 550 * always have pte pages mapped, we just have to fault 551 * the page. 552 */ 553 rv = vm_fault(kernel_map, va, ftype, FALSE); 554 } 555 556 if (rv == KERN_SUCCESS) 557 return (0); 558nogo: 559 if (!usermode) { 560 if (curpcb && curpcb->pcb_onfault) { 561 frame->tf_eip = (int)curpcb->pcb_onfault; 562 return (0); 563 } 564 trap_fatal(frame); 565 return (-1); 566 } 567 568 /* kludge to pass faulting virtual address to sendsig */ 569 frame->tf_err = eva; 570 571 return((rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV); 572} 573#endif 574 575int 576trap_pfault(frame, usermode) 577 struct trapframe *frame; 578 int usermode; 579{ 580 vm_offset_t va; 581 struct vmspace *vm = NULL; 582 vm_map_t map = 0; 583 int rv = 0; 584 vm_prot_t ftype; 585 int eva; 586 struct proc *p = curproc; 587 588 eva = rcr2(); 589 va = trunc_page((vm_offset_t)eva); 590 591 if (va >= KERNBASE) { 592 /* 593 * Don't allow user-mode faults in kernel address space. 594 */ 595 if (usermode) 596 goto nogo; 597 598 map = kernel_map; 599 } else { 600 /* 601 * This is a fault on non-kernel virtual memory. 602 * vm is initialized above to NULL. If curproc is NULL 603 * or curproc->p_vmspace is NULL the fault is fatal. 604 */ 605 if (p != NULL) 606 vm = p->p_vmspace; 607 608 if (vm == NULL) 609 goto nogo; 610 611 map = &vm->vm_map; 612 } 613 614 if (frame->tf_err & PGEX_W) 615 ftype = VM_PROT_READ | VM_PROT_WRITE; 616 else 617 ftype = VM_PROT_READ; 618 619 if (map != kernel_map) { 620 vm_offset_t v; 621 622 /* 623 * Keep swapout from messing with us during this 624 * critical time. 625 */ 626 ++p->p_lock; 627 628 /* 629 * Grow the stack if necessary 630 */ 631 if ((caddr_t)va > vm->vm_maxsaddr 632 && (caddr_t)va < (caddr_t)USRSTACK) { 633 if (!grow(p, va)) { 634 rv = KERN_FAILURE; 635 --p->p_lock; 636 goto nogo; 637 } 638 } 639 640 /* 641 * Check if page table is mapped, if not, 642 * fault it first 643 */ 644 v = (vm_offset_t) vtopte(va); 645 646 /* Fault the pte only if needed: */ 647 if (*((int *)vtopte(v)) == 0) 648 (void) vm_fault(map, trunc_page(v), VM_PROT_WRITE, FALSE); 649 650 pmap_use_pt( vm_map_pmap(map), va); 651 652 /* Fault in the user page: */ 653 rv = vm_fault(map, va, ftype, FALSE); 654 655 pmap_unuse_pt( vm_map_pmap(map), va); 656 657 --p->p_lock; 658 } else { 659 /* 660 * Since we know that kernel virtual address addresses 661 * always have pte pages mapped, we just have to fault 662 * the page. 663 */ 664 rv = vm_fault(map, va, ftype, FALSE); 665 } 666 667 if (rv == KERN_SUCCESS) 668 return (0); 669nogo: 670 if (!usermode) { 671 if (curpcb && curpcb->pcb_onfault) { 672 frame->tf_eip = (int)curpcb->pcb_onfault; 673 return (0); 674 } 675 trap_fatal(frame); 676 return (-1); 677 } 678 679 /* kludge to pass faulting virtual address to sendsig */ 680 frame->tf_err = eva; 681 682 return((rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV); 683} 684 685static void 686trap_fatal(frame) 687 struct trapframe *frame; 688{ 689 int code, type, eva; 690 struct soft_segment_descriptor softseg; 691 692 code = frame->tf_err; 693 type = frame->tf_trapno; 694 eva = rcr2(); 695 sdtossd(&gdt[IDXSEL(frame->tf_cs & 0xffff)].sd, &softseg); 696 697 if (type <= MAX_TRAP_MSG) 698 printf("\n\nFatal trap %d: %s while in %s mode\n", 699 type, trap_msg[type], 700 ISPL(frame->tf_cs) == SEL_UPL ? "user" : "kernel"); 701 if (type == T_PAGEFLT) { 702 printf("fault virtual address = 0x%x\n", eva); 703 printf("fault code = %s %s, %s\n", 704 code & PGEX_U ? "user" : "supervisor", 705 code & PGEX_W ? "write" : "read", 706 code & PGEX_P ? "protection violation" : "page not present"); 707 } 708 printf("instruction pointer = 0x%x:0x%x\n", frame->tf_cs & 0xffff, frame->tf_eip); 709 printf("code segment = base 0x%x, limit 0x%x, type 0x%x\n", 710 softseg.ssd_base, softseg.ssd_limit, softseg.ssd_type); 711 printf(" = DPL %d, pres %d, def32 %d, gran %d\n", 712 softseg.ssd_dpl, softseg.ssd_p, softseg.ssd_def32, softseg.ssd_gran); 713 printf("processor eflags = "); 714 if (frame->tf_eflags & PSL_T) 715 printf("trace/trap, "); 716 if (frame->tf_eflags & PSL_I) 717 printf("interrupt enabled, "); 718 if (frame->tf_eflags & PSL_NT) 719 printf("nested task, "); 720 if (frame->tf_eflags & PSL_RF) 721 printf("resume, "); 722 if (frame->tf_eflags & PSL_VM) 723 printf("vm86, "); 724 printf("IOPL = %d\n", (frame->tf_eflags & PSL_IOPL) >> 12); 725 printf("current process = "); 726 if (curproc) { 727 printf("%lu (%s)\n", 728 (u_long)curproc->p_pid, curproc->p_comm ? 729 curproc->p_comm : ""); 730 } else { 731 printf("Idle\n"); 732 } 733 printf("interrupt mask = "); 734 if ((cpl & net_imask) == net_imask) 735 printf("net "); 736 if ((cpl & tty_imask) == tty_imask) 737 printf("tty "); 738 if ((cpl & bio_imask) == bio_imask) 739 printf("bio "); 740 if (cpl == 0) 741 printf("none"); 742 printf("\n"); 743 744#ifdef KDB 745 if (kdb_trap(&psl)) 746 return; 747#endif 748#ifdef DDB 749 if (kdb_trap (type, 0, frame)) 750 return; 751#endif 752 if (type <= MAX_TRAP_MSG) 753 panic(trap_msg[type]); 754 else 755 panic("unknown/reserved trap"); 756} 757 758/* 759 * Compensate for 386 brain damage (missing URKR). 760 * This is a little simpler than the pagefault handler in trap() because 761 * it the page tables have already been faulted in and high addresses 762 * are thrown out early for other reasons. 763 */ 764int trapwrite(addr) 765 unsigned addr; 766{ 767 struct proc *p; 768 vm_offset_t va, v; 769 struct vmspace *vm; 770 int rv; 771 772 va = trunc_page((vm_offset_t)addr); 773 /* 774 * XXX - MAX is END. Changed > to >= for temp. fix. 775 */ 776 if (va >= VM_MAXUSER_ADDRESS) 777 return (1); 778 779 p = curproc; 780 vm = p->p_vmspace; 781 782 ++p->p_lock; 783 784 if ((caddr_t)va >= vm->vm_maxsaddr 785 && (caddr_t)va < (caddr_t)USRSTACK) { 786 if (!grow(p, va)) { 787 --p->p_lock; 788 return (1); 789 } 790 } 791 792 v = trunc_page(vtopte(va)); 793 794 /* 795 * wire the pte page 796 */ 797 if (va < USRSTACK) { 798 vm_map_pageable(&vm->vm_map, v, round_page(v+1), FALSE); 799 } 800 801 /* 802 * fault the data page 803 */ 804 rv = vm_fault(&vm->vm_map, va, VM_PROT_READ|VM_PROT_WRITE, FALSE); 805 806 /* 807 * unwire the pte page 808 */ 809 if (va < USRSTACK) { 810 vm_map_pageable(&vm->vm_map, v, round_page(v+1), TRUE); 811 } 812 813 --p->p_lock; 814 815 if (rv != KERN_SUCCESS) 816 return 1; 817 818 return (0); 819} 820 821/* 822 * System call request from POSIX system call gate interface to kernel. 823 * Like trap(), argument is call by reference. 824 */ 825void 826syscall(frame) 827 struct trapframe frame; 828{ 829 caddr_t params; 830 int i; 831 struct sysent *callp; 832 struct proc *p = curproc; 833 u_quad_t sticks; 834 int error; 835 int args[8], rval[2]; 836 u_int code; 837 838 sticks = p->p_sticks; 839 if (ISPL(frame.tf_cs) != SEL_UPL) 840 panic("syscall"); 841 842 p->p_md.md_regs = (int *)&frame; 843 params = (caddr_t)frame.tf_esp + sizeof(int); 844 code = frame.tf_eax; 845 /* 846 * Need to check if this is a 32 bit or 64 bit syscall. 847 */ 848 if (code == SYS_syscall) { 849 /* 850 * Code is first argument, followed by actual args. 851 */ 852 code = fuword(params); 853 params += sizeof(int); 854 } else if (code == SYS___syscall) { 855 /* 856 * Like syscall, but code is a quad, so as to maintain 857 * quad alignment for the rest of the arguments. 858 */ 859 code = fuword(params); 860 params += sizeof(quad_t); 861 } 862 863 if (p->p_sysent->sv_mask) 864 code &= p->p_sysent->sv_mask; 865 866 if (code >= p->p_sysent->sv_size) 867 callp = &p->p_sysent->sv_table[0]; 868 else 869 callp = &p->p_sysent->sv_table[code]; 870 871 if ((i = callp->sy_narg * sizeof(int)) && 872 (error = copyin(params, (caddr_t)args, (u_int)i))) { 873#ifdef KTRACE 874 if (KTRPOINT(p, KTR_SYSCALL)) 875 ktrsyscall(p->p_tracep, code, callp->sy_narg, args); 876#endif 877 goto bad; 878 } 879#ifdef KTRACE 880 if (KTRPOINT(p, KTR_SYSCALL)) 881 ktrsyscall(p->p_tracep, code, callp->sy_narg, args); 882#endif 883 rval[0] = 0; 884 rval[1] = frame.tf_edx; 885 886 error = (*callp->sy_call)(p, args, rval); 887 888 switch (error) { 889 890 case 0: 891 /* 892 * Reinitialize proc pointer `p' as it may be different 893 * if this is a child returning from fork syscall. 894 */ 895 p = curproc; 896 frame.tf_eax = rval[0]; 897 frame.tf_edx = rval[1]; 898 frame.tf_eflags &= ~PSL_C; 899 break; 900 901 case ERESTART: 902 /* 903 * Reconstruct pc, assuming lcall $X,y is 7 bytes. 904 */ 905 frame.tf_eip -= 7; 906 break; 907 908 case EJUSTRETURN: 909 break; 910 911 default: 912bad: 913 if (p->p_sysent->sv_errsize) 914 if (error >= p->p_sysent->sv_errsize) 915 error = -1; /* XXX */ 916 else 917 error = p->p_sysent->sv_errtbl[error]; 918 frame.tf_eax = error; 919 frame.tf_eflags |= PSL_C; 920 break; 921 } 922 923 if (frame.tf_eflags & PSL_T) { 924 /* Traced syscall. */ 925 frame.tf_eflags &= ~PSL_T; 926 trapsignal(p, SIGTRAP, 0); 927 } 928 929 userret(p, &frame, sticks); 930 931#ifdef KTRACE 932 if (KTRPOINT(p, KTR_SYSRET)) 933 ktrsysret(p->p_tracep, code, error, rval[0]); 934#endif 935} 936 937#ifdef COMPAT_LINUX 938void 939linux_syscall(frame) 940 struct trapframe frame; 941{ 942 struct proc *p = curproc; 943 struct sysent *callp; 944 u_quad_t sticks; 945 int error; 946 int rval[2]; 947 u_int code; 948 struct linux_syscall_args { 949 int arg1; 950 int arg2; 951 int arg3; 952 int arg4; 953 int arg5; 954 } args; 955 956 args.arg1 = frame.tf_ebx; 957 args.arg2 = frame.tf_ecx; 958 args.arg3 = frame.tf_edx; 959 args.arg4 = frame.tf_esi; 960 args.arg5 = frame.tf_edi; 961 962 sticks = p->p_sticks; 963 if (ISPL(frame.tf_cs) != SEL_UPL) 964 panic("linux syscall"); 965 966 p->p_md.md_regs = (int *)&frame; 967 code = frame.tf_eax; 968 969 if (p->p_sysent->sv_mask) 970 code &= p->p_sysent->sv_mask; 971 972 if (code >= p->p_sysent->sv_size) 973 callp = &p->p_sysent->sv_table[0]; 974 else 975 callp = &p->p_sysent->sv_table[code]; 976 977#ifdef KTRACE 978 if (KTRPOINT(p, KTR_SYSCALL)) 979 ktrsyscall(p->p_tracep, code, callp->sy_narg, (int *)&args); 980#endif 981 982 rval[0] = 0; 983 984 error = (*callp->sy_call)(p, &args, rval); 985 986 switch (error) { 987 988 case 0: 989 /* 990 * Reinitialize proc pointer `p' as it may be different 991 * if this is a child returning from fork syscall. 992 */ 993 p = curproc; 994 frame.tf_eax = rval[0]; 995 frame.tf_eflags &= ~PSL_C; 996 break; 997 998 case ERESTART: 999 /* Reconstruct pc, subtract size of int 0x80 */ 1000 frame.tf_eip -= 2; 1001 break; 1002 1003 case EJUSTRETURN: 1004 break; 1005 1006 default: 1007 if (p->p_sysent->sv_errsize) 1008 if (error >= p->p_sysent->sv_errsize) 1009 error = -1; /* XXX */ 1010 else 1011 error = p->p_sysent->sv_errtbl[error]; 1012 frame.tf_eax = -error; 1013 frame.tf_eflags |= PSL_C; 1014 break; 1015 } 1016 1017 if (frame.tf_eflags & PSL_T) { 1018 /* Traced syscall. */ 1019 frame.tf_eflags &= ~PSL_T; 1020 trapsignal(p, SIGTRAP, 0); 1021 } 1022 1023 userret(p, &frame, sticks); 1024 1025#ifdef KTRACE 1026 if (KTRPOINT(p, KTR_SYSRET)) 1027 ktrsysret(p->p_tracep, code, error, rval[0]); 1028#endif 1029} 1030#endif /* COMPAT_LINUX */ 1031