trap.c revision 1.6
1/* $NetBSD: trap.c,v 1.6 1998/10/01 02:53:55 thorpej Exp $ */ 2 3/* 4 * Copyright (c) 1988 University of Utah. 5 * Copyright (c) 1982, 1986, 1990, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * the Systems Programming Group of the University of Utah Computer 10 * Science Department. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by the University of 23 * California, Berkeley and its contributors. 24 * 4. Neither the name of the University nor the names of its contributors 25 * may be used to endorse or promote products derived from this software 26 * without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 * 40 * from: Utah $Hdr: trap.c 1.37 92/12/20$ 41 * 42 * @(#)trap.c 8.5 (Berkeley) 1/4/94 43 */ 44 45#include "opt_ddb.h" 46#include "opt_ktrace.h" 47#include "opt_compat_netbsd.h" 48#include "opt_compat_sunos.h" 49#include "opt_compat_hpux.h" 50 51#if 0 52#include <machine/hp300spu.h> /* XXX param.h includes cpu.h */ 53#endif 54 55#include <sys/param.h> 56#include <sys/systm.h> 57#include <sys/proc.h> 58#include <sys/acct.h> 59#include <sys/kernel.h> 60#include <sys/signalvar.h> 61#include <sys/resourcevar.h> 62#include <sys/syscall.h> 63#include <sys/syslog.h> 64#include <sys/user.h> 65#ifdef KTRACE 66#include <sys/ktrace.h> 67#endif 68 69#include <m68k/frame.h> 70 71#include <machine/db_machdep.h> 72#include <machine/psl.h> 73#include <machine/trap.h> 74#include <machine/cpu.h> 75#include <machine/reg.h> 76#include <machine/intr.h> 77 78#include <vm/vm.h> 79#include <vm/pmap.h> 80 81#include <dev/cons.h> 82 83#ifdef COMPAT_HPUX 84#include <compat/hpux/hpux.h> 85extern struct emul emul_hpux; 86#endif 87 88#ifdef COMPAT_SUNOS 89#include <compat/sunos/sunos_syscall.h> 90extern struct emul emul_sunos; 91#endif 92 93int writeback __P((struct frame *fp, int docachepush)); 94void trap __P((int type, u_int code, u_int v, struct frame frame)); 95void syscall __P((register_t code, struct frame frame)); 96void child_return __P((struct proc *, struct frame)); 97 98#ifdef DEBUG 99void dumpssw __P((u_short)); 100void dumpwb __P((int, u_short, u_int, u_int)); 101#endif 102 103static inline void userret __P((struct proc *p, struct frame *fp, 104 u_quad_t oticks, u_int faultaddr, int fromtrap)); 105 106char *trap_type[] = { 107 "Bus error", 108 "Address error", 109 "Illegal instruction", 110 "Zero divide", 111 "CHK instruction", 112 "TRAPV instruction", 113 "Privilege violation", 114 "Trace trap", 115 "MMU fault", 116 "SSIR trap", 117 "Format error", 118 "68881 exception", 119 "Coprocessor violation", 120 "Async system trap" 121}; 122int trap_types = sizeof trap_type / sizeof trap_type[0]; 123 124/* 125 * Size of various exception stack frames (minus the standard 8 bytes) 126 */ 127short exframesize[] = { 128 FMT0SIZE, /* type 0 - normal (68020/030/040/060) */ 129 FMT1SIZE, /* type 1 - throwaway (68020/030/040) */ 130 FMT2SIZE, /* type 2 - normal 6-word (68020/030/040/060) */ 131 FMT3SIZE, /* type 3 - FP post-instruction (68040/060) */ 132 FMT4SIZE, /* type 4 - access error/fp disabled (68060) */ 133 -1, -1, /* type 5-6 - undefined */ 134 FMT7SIZE, /* type 7 - access error (68040) */ 135 58, /* type 8 - bus fault (68010) */ 136 FMT9SIZE, /* type 9 - coprocessor mid-instruction (68020/030) */ 137 FMTASIZE, /* type A - short bus fault (68020/030) */ 138 FMTBSIZE, /* type B - long bus fault (68020/030) */ 139 -1, -1, -1, -1 /* type C-F - undefined */ 140}; 141 142#ifdef M68060 143#define KDFAULT_060(c) (cputype == CPU_68060 && ((c) & FSLW_TM_SV)) 144#define WRFAULT_060(c) (cputype == CPU_68060 && ((c) & FSLW_RW_W)) 145#else 146#define KDFAULT_060(c) 0 147#define WRFAULT_060(c) 0 148#endif 149 150#ifdef M68040 151#define KDFAULT_040(c) (cputype == CPU_68040 && \ 152 ((c) & SSW4_TMMASK) == SSW4_TMKD) 153#define WRFAULT_040(c) (cputype == CPU_68040 && \ 154 ((c) & SSW4_RW) == 0) 155#else 156#define KDFAULT_040(c) 0 157#define WRFAULT_040(c) 0 158#endif 159 160#if defined(M68030) || defined(M68020) 161#define KDFAULT_OTH(c) (cputype <= CPU_68030 && \ 162 ((c) & (SSW_DF|SSW_FCMASK)) == (SSW_DF|FC_SUPERD)) 163#define WRFAULT_OTH(c) (cputype <= CPU_68030 && \ 164 ((c) & (SSW_DF|SSW_RW)) == SSW_DF) 165#else 166#define KDFAULT_OTH(c) 0 167#define WRFAULT_OTH(c) 0 168#endif 169 170#define KDFAULT(c) (KDFAULT_060(c) || KDFAULT_040(c) || KDFAULT_OTH(c)) 171#define WRFAULT(c) (WRFAULT_060(c) || WRFAULT_040(c) || WRFAULT_OTH(c)) 172 173#ifdef DEBUG 174int mmudebug = 0; 175int mmupid = -1; 176#define MDB_FOLLOW 1 177#define MDB_WBFOLLOW 2 178#define MDB_WBFAILED 4 179#define MDB_ISPID(p) ((p) == mmupid) 180#endif 181 182#define NSIR 32 183void (*sir_routines[NSIR])(); 184void *sir_args[NSIR]; 185int next_sir; 186 187/* 188 * trap and syscall both need the following work done before returning 189 * to user mode. 190 */ 191static inline void 192userret(p, fp, oticks, faultaddr, fromtrap) 193 struct proc *p; 194 struct frame *fp; 195 u_quad_t oticks; 196 u_int faultaddr; 197 int fromtrap; 198{ 199 int sig, s; 200#ifdef M68040 201 int beenhere = 0; 202 203again: 204#endif 205 /* take pending signals */ 206 while ((sig = CURSIG(p)) != 0) 207 postsig(sig); 208 p->p_priority = p->p_usrpri; 209 if (want_resched) { 210 /* 211 * Since we are curproc, clock will normally just change 212 * our priority without moving us from one queue to another 213 * (since the running process is not on a queue.) 214 * If that happened after we put ourselves on the run queue 215 * but before we mi_switch()'ed, we might not be on the queue 216 * indicated by our priority. 217 */ 218 s = splstatclock(); 219 setrunqueue(p); 220 p->p_stats->p_ru.ru_nivcsw++; 221 mi_switch(); 222 splx(s); 223 while ((sig = CURSIG(p)) != 0) 224 postsig(sig); 225 } 226 227 /* 228 * If profiling, charge system time to the trapped pc. 229 */ 230 if (p->p_flag & P_PROFIL) { 231 extern int psratio; 232 233 addupc_task(p, fp->f_pc, 234 (int)(p->p_sticks - oticks) * psratio); 235 } 236#ifdef M68040 237 /* 238 * Deal with user mode writebacks (from trap, or from sigreturn). 239 * If any writeback fails, go back and attempt signal delivery. 240 * unless we have already been here and attempted the writeback 241 * (e.g. bad address with user ignoring SIGSEGV). In that case 242 * we just return to the user without sucessfully completing 243 * the writebacks. Maybe we should just drop the sucker? 244 */ 245 if (cputype == CPU_68040 && fp->f_format == FMT7) { 246 if (beenhere) { 247#ifdef DEBUG 248 if (mmudebug & MDB_WBFAILED) 249 printf(fromtrap ? 250 "pid %d(%s): writeback aborted, pc=%x, fa=%x\n" : 251 "pid %d(%s): writeback aborted in sigreturn, pc=%x\n", 252 p->p_pid, p->p_comm, fp->f_pc, faultaddr); 253#endif 254 } else if ((sig = writeback(fp, fromtrap))) { 255 beenhere = 1; 256 oticks = p->p_sticks; 257 trapsignal(p, sig, faultaddr); 258 goto again; 259 } 260 } 261#endif 262 curpriority = p->p_priority; 263} 264 265/* 266 * Trap is called from locore to handle most types of processor traps, 267 * including events such as simulated software interrupts/AST's. 268 * System calls are broken out for efficiency. 269 */ 270/*ARGSUSED*/ 271void 272trap(type, code, v, frame) 273 int type; 274 unsigned code; 275 unsigned v; 276 struct frame frame; 277{ 278 extern char fubail[], subail[]; 279 struct proc *p; 280 int i, s; 281 int bit; 282 u_int ucode; 283 u_quad_t sticks = 0 /* XXX initializer works around compiler bug */; 284 285 cnt.v_trap++; 286 p = curproc; 287 ucode = 0; 288 289 /* I have verified that this DOES happen! -gwr */ 290 if (p == NULL) 291 p = &proc0; 292#ifdef DIAGNOSTIC 293 if (p->p_addr == NULL) 294 panic("trap: no pcb"); 295#endif 296 297 if (USERMODE(frame.f_sr)) { 298 type |= T_USER; 299 sticks = p->p_sticks; 300 p->p_md.md_regs = frame.f_regs; 301 } 302 switch (type) { 303 304 default: 305 dopanic: 306 printf("trap type %d, code = 0x%x, v = 0x%x\n", type, code, v); 307 printf("%s program counter = 0x%x\n", 308 (type & T_USER) ? "user" : "kernel", frame.f_pc); 309 /* 310 * Let the kernel debugger see the trap frame that 311 * caused us to panic. This is a convenience so 312 * one can see registers at the point of failure. 313 */ 314 s = splhigh(); 315#ifdef KGDB 316 /* If connected, step or cont returns 1 */ 317 if (kgdb_trap(type, &frame)) 318 goto kgdb_cont; 319#endif 320#ifdef DDB 321 (void)kdb_trap(type, (db_regs_t *)&frame); 322#endif 323#ifdef KGDB 324 kgdb_cont: 325#endif 326 splx(s); 327 if (panicstr) { 328 printf("trap during panic!\n"); 329#ifdef DEBUG 330 /* XXX should be a machine-dependent hook */ 331 printf("(press a key)\n"); (void)cngetc(); 332#endif 333 } 334 regdump((struct trapframe *)&frame, 128); 335 type &= ~T_USER; 336 if ((u_int)type < trap_types) 337 panic(trap_type[type]); 338 panic("trap"); 339 340 case T_BUSERR: /* kernel bus error */ 341 if (p->p_addr->u_pcb.pcb_onfault == 0) 342 goto dopanic; 343 /* FALLTHROUGH */ 344 345 copyfault: 346 /* 347 * If we have arranged to catch this fault in any of the 348 * copy to/from user space routines, set PC to return to 349 * indicated location and set flag informing buserror code 350 * that it may need to clean up stack frame. 351 */ 352 frame.f_stackadj = exframesize[frame.f_format]; 353 frame.f_format = frame.f_vector = 0; 354 frame.f_pc = (int) p->p_addr->u_pcb.pcb_onfault; 355 return; 356 357 case T_BUSERR|T_USER: /* bus error */ 358 case T_ADDRERR|T_USER: /* address error */ 359 ucode = v; 360 i = SIGBUS; 361 break; 362 363 case T_COPERR: /* kernel coprocessor violation */ 364 case T_FMTERR|T_USER: /* do all RTE errors come in as T_USER? */ 365 case T_FMTERR: /* ...just in case... */ 366 /* 367 * The user has most likely trashed the RTE or FP state info 368 * in the stack frame of a signal handler. 369 */ 370 printf("pid %d: kernel %s exception\n", p->p_pid, 371 type==T_COPERR ? "coprocessor" : "format"); 372 type |= T_USER; 373 p->p_sigacts->ps_sigact[SIGILL].sa_handler = SIG_DFL; 374 sigdelset(&p->p_sigignore, SIGILL); 375 sigdelset(&p->p_sigcatch, SIGILL); 376 sigdelset(&p->p_sigmask, SIGILL); 377 i = SIGILL; 378 ucode = frame.f_format; /* XXX was ILL_RESAD_FAULT */ 379 break; 380 381 case T_COPERR|T_USER: /* user coprocessor violation */ 382 /* What is a proper response here? */ 383 ucode = 0; 384 i = SIGFPE; 385 break; 386 387 case T_FPERR|T_USER: /* 68881 exceptions */ 388 /* 389 * We pass along the 68881 status which locore stashed 390 * in code for us. Note that there is a possibility that the 391 * bit pattern of this will conflict with one of the 392 * FPE_* codes defined in signal.h. Fortunately for us, the 393 * only such codes we use are all in the range 1-7 and the low 394 * 3 bits of the status are defined as 0 so there is 395 * no clash. 396 */ 397 ucode = code; 398 i = SIGFPE; 399 break; 400 401#ifdef M68040 402 case T_FPEMULI|T_USER: /* unimplemented FP instuction */ 403 case T_FPEMULD|T_USER: /* unimplemented FP data type */ 404 /* XXX need to FSAVE */ 405 printf("pid %d(%s): unimplemented FP %s at %x (EA %x)\n", 406 p->p_pid, p->p_comm, 407 frame.f_format == 2 ? "instruction" : "data type", 408 frame.f_pc, frame.f_fmt2.f_iaddr); 409 /* XXX need to FRESTORE */ 410 i = SIGFPE; 411 break; 412#endif 413 414 case T_ILLINST|T_USER: /* illegal instruction fault */ 415#ifdef COMPAT_HPUX 416 if (p->p_emul == &emul_hpux) { 417 ucode = HPUX_ILL_ILLINST_TRAP; 418 i = SIGILL; 419 break; 420 } 421 /* fall through */ 422#endif 423 case T_PRIVINST|T_USER: /* privileged instruction fault */ 424#ifdef COMPAT_HPUX 425 if (p->p_emul == &emul_hpux) 426 ucode = HPUX_ILL_PRIV_TRAP; 427 else 428#endif 429 ucode = frame.f_format; /* XXX was ILL_PRIVIN_FAULT */ 430 i = SIGILL; 431 break; 432 433 case T_ZERODIV|T_USER: /* Divide by zero */ 434#ifdef COMPAT_HPUX 435 if (p->p_emul == &emul_hpux) 436 ucode = HPUX_FPE_INTDIV_TRAP; 437 else 438#endif 439 ucode = frame.f_format; /* XXX was FPE_INTDIV_TRAP */ 440 i = SIGFPE; 441 break; 442 443 case T_CHKINST|T_USER: /* CHK instruction trap */ 444#ifdef COMPAT_HPUX 445 if (p->p_emul == &emul_hpux) { 446 /* handled differently under hp-ux */ 447 i = SIGILL; 448 ucode = HPUX_ILL_CHK_TRAP; 449 break; 450 } 451#endif 452 ucode = frame.f_format; /* XXX was FPE_SUBRNG_TRAP */ 453 i = SIGFPE; 454 break; 455 456 case T_TRAPVINST|T_USER: /* TRAPV instruction trap */ 457#ifdef COMPAT_HPUX 458 if (p->p_emul == &emul_hpux) { 459 /* handled differently under hp-ux */ 460 i = SIGILL; 461 ucode = HPUX_ILL_TRAPV_TRAP; 462 break; 463 } 464#endif 465 ucode = frame.f_format; /* XXX was FPE_INTOVF_TRAP */ 466 i = SIGFPE; 467 break; 468 469 /* 470 * XXX: Trace traps are a nightmare. 471 * 472 * HP-UX uses trap #1 for breakpoints, 473 * NetBSD/m68k uses trap #2, 474 * SUN 3.x uses trap #15, 475 * DDB and KGDB uses trap #15 (for kernel breakpoints; 476 * handled elsewhere). 477 * 478 * NetBSD and HP-UX traps both get mapped by locore.s into T_TRACE. 479 * SUN 3.x traps get passed through as T_TRAP15 and are not really 480 * supported yet. 481 * 482 * XXX: We should never get kernel-mode T_TRACE or T_TRAP15 483 * XXX: because locore.s now gives them special treatment. 484 */ 485 case T_TRACE: /* kernel trace trap */ 486 case T_TRAP15: /* kernel breakpoint */ 487#ifdef DEBUG 488 printf("unexpected kernel trace trap, type = %d\n", type); 489 printf("program counter = 0x%x\n", frame.f_pc); 490#endif 491 frame.f_sr &= ~PSL_T; 492 return; 493 494 case T_TRACE|T_USER: /* user trace trap */ 495 case T_TRAP15|T_USER: /* SUN user trace trap */ 496#ifdef COMPAT_SUNOS 497 /* 498 * SunOS uses Trap #2 for a "CPU cache flush". 499 * Just flush the on-chip caches and return. 500 */ 501 if (p->p_emul == &emul_sunos) { 502 ICIA(); 503 DCIU(); 504 return; 505 } 506#endif 507 frame.f_sr &= ~PSL_T; 508 i = SIGTRAP; 509 break; 510 511 case T_ASTFLT: /* system async trap, cannot happen */ 512 goto dopanic; 513 514 case T_ASTFLT|T_USER: /* user async trap */ 515 astpending = 0; 516 /* 517 * We check for software interrupts first. This is because 518 * they are at a higher level than ASTs, and on a VAX would 519 * interrupt the AST. We assume that if we are processing 520 * an AST that we must be at IPL0 so we don't bother to 521 * check. Note that we ensure that we are at least at SIR 522 * IPL while processing the SIR. 523 */ 524 spl1(); 525 /* fall into... */ 526 527 case T_SSIR: /* software interrupt */ 528 case T_SSIR|T_USER: 529 while (bit = ffs(ssir)) { 530 --bit; 531 ssir &= ~(1 << bit); 532 cnt.v_soft++; 533 if (sir_routines[bit]) 534 sir_routines[bit](sir_args[bit]); 535 } 536 537 /* 538 * If this was not an AST trap, we are all done. 539 */ 540 if (type != (T_ASTFLT|T_USER)) { 541 cnt.v_trap--; 542 return; 543 } 544 spl0(); 545 if (p->p_flag & P_OWEUPC) { 546 p->p_flag &= ~P_OWEUPC; 547 ADDUPROF(p); 548 } 549 goto out; 550 551 case T_MMUFLT: /* kernel mode page fault */ 552 /* 553 * If we were doing profiling ticks or other user mode 554 * stuff from interrupt code, Just Say No. 555 */ 556 if (p->p_addr->u_pcb.pcb_onfault == fubail || 557 p->p_addr->u_pcb.pcb_onfault == subail) 558 goto copyfault; 559 /* fall into ... */ 560 561 case T_MMUFLT|T_USER: /* page fault */ 562 { 563 vm_offset_t va; 564 struct vmspace *vm = p->p_vmspace; 565 vm_map_t map; 566 int rv; 567 vm_prot_t ftype; 568 extern vm_map_t kernel_map; 569 570#ifdef DEBUG 571 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 572 printf("trap: T_MMUFLT pid=%d, code=%x, v=%x, pc=%x, sr=%x\n", 573 p->p_pid, code, v, frame.f_pc, frame.f_sr); 574#endif 575 /* 576 * It is only a kernel address space fault iff: 577 * 1. (type & T_USER) == 0 and 578 * 2. pcb_onfault not set or 579 * 3. pcb_onfault set but supervisor space data fault 580 * The last can occur during an exec() copyin where the 581 * argument space is lazy-allocated. 582 */ 583 if ((type & T_USER) == 0 && 584 ((p->p_addr->u_pcb.pcb_onfault == 0) || KDFAULT(code))) 585 map = kernel_map; 586 else 587 map = vm ? &vm->vm_map : kernel_map; 588 589 if (WRFAULT(code)) 590 ftype = VM_PROT_READ | VM_PROT_WRITE; 591 else 592 ftype = VM_PROT_READ; 593 594 va = trunc_page((vm_offset_t)v); 595 596 if (map == kernel_map && va == 0) { 597 printf("trap: bad kernel %s access at 0x%x\n", 598 (ftype & VM_PROT_WRITE) ? "read/write" : 599 "read", v); 600 goto dopanic; 601 } 602 603#ifdef COMPAT_HPUX 604 if (ISHPMMADDR(va)) { 605 int pmap_mapmulti __P((pmap_t, vm_offset_t)); 606 vm_offset_t bva; 607 608 rv = pmap_mapmulti(map->pmap, va); 609 if (rv != KERN_SUCCESS) { 610 bva = HPMMBASEADDR(va); 611 rv = vm_fault(map, bva, ftype, FALSE); 612 if (rv == KERN_SUCCESS) 613 (void) pmap_mapmulti(map->pmap, va); 614 } 615 } else 616#endif 617 rv = vm_fault(map, va, ftype, FALSE); 618#ifdef DEBUG 619 if (rv && MDB_ISPID(p->p_pid)) 620 printf("vm_fault(%p, %lx, %x, 0) -> %x\n", 621 map, va, ftype, rv); 622#endif 623 /* 624 * If this was a stack access we keep track of the maximum 625 * accessed stack size. Also, if vm_fault gets a protection 626 * failure it is due to accessing the stack region outside 627 * the current limit and we need to reflect that as an access 628 * error. 629 */ 630 if ((vm != NULL && (caddr_t)va >= vm->vm_maxsaddr) 631 && map != kernel_map) { 632 if (rv == KERN_SUCCESS) { 633 unsigned nss; 634 635 nss = clrnd(btoc(USRSTACK-(unsigned)va)); 636 if (nss > vm->vm_ssize) 637 vm->vm_ssize = nss; 638 } else if (rv == KERN_PROTECTION_FAILURE) 639 rv = KERN_INVALID_ADDRESS; 640 } 641 if (rv == KERN_SUCCESS) { 642 if (type == T_MMUFLT) { 643#ifdef M68040 644 if (cputype == CPU_68040) 645 (void) writeback(&frame, 1); 646#endif 647 return; 648 } 649 goto out; 650 } 651 if (type == T_MMUFLT) { 652 if (p->p_addr->u_pcb.pcb_onfault) 653 goto copyfault; 654 printf("vm_fault(%p, %lx, %x, 0) -> %x\n", 655 map, va, ftype, rv); 656 printf(" type %x, code [mmu,,ssw]: %x\n", 657 type, code); 658 goto dopanic; 659 } 660 ucode = v; 661 i = SIGSEGV; 662 break; 663 } 664 } 665 trapsignal(p, i, ucode); 666 if ((type & T_USER) == 0) 667 return; 668out: 669 userret(p, &frame, sticks, v, 1); 670} 671 672#ifdef M68040 673#ifdef DEBUG 674struct writebackstats { 675 int calls; 676 int cpushes; 677 int move16s; 678 int wb1s, wb2s, wb3s; 679 int wbsize[4]; 680} wbstats; 681 682char *f7sz[] = { "longword", "byte", "word", "line" }; 683char *f7tt[] = { "normal", "MOVE16", "AFC", "ACK" }; 684char *f7tm[] = { "d-push", "u-data", "u-code", "M-data", 685 "M-code", "k-data", "k-code", "RES" }; 686char wberrstr[] = 687 "WARNING: pid %d(%s) writeback [%s] failed, pc=%x fa=%x wba=%x wbd=%x\n"; 688#endif 689 690int 691writeback(fp, docachepush) 692 struct frame *fp; 693 int docachepush; 694{ 695 struct fmt7 *f = &fp->f_fmt7; 696 struct proc *p = curproc; 697 int err = 0; 698 u_int fa; 699 caddr_t oonfault = p->p_addr->u_pcb.pcb_onfault; 700 701#ifdef DEBUG 702 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) { 703 printf(" pid=%d, fa=%x,", p->p_pid, f->f_fa); 704 dumpssw(f->f_ssw); 705 } 706 wbstats.calls++; 707#endif 708 /* 709 * Deal with special cases first. 710 */ 711 if ((f->f_ssw & SSW4_TMMASK) == SSW4_TMDCP) { 712 /* 713 * Dcache push fault. 714 * Line-align the address and write out the push data to 715 * the indicated physical address. 716 */ 717#ifdef DEBUG 718 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) { 719 printf(" pushing %s to PA %x, data %x", 720 f7sz[(f->f_ssw & SSW4_SZMASK) >> 5], 721 f->f_fa, f->f_pd0); 722 if ((f->f_ssw & SSW4_SZMASK) == SSW4_SZLN) 723 printf("/%x/%x/%x", 724 f->f_pd1, f->f_pd2, f->f_pd3); 725 printf("\n"); 726 } 727 if (f->f_wb1s & SSW4_WBSV) 728 panic("writeback: cache push with WB1S valid"); 729 wbstats.cpushes++; 730#endif 731 /* 732 * XXX there are security problems if we attempt to do a 733 * cache push after a signal handler has been called. 734 */ 735 if (docachepush) { 736 pmap_enter(pmap_kernel(), (vm_offset_t)vmmap, 737 trunc_page(f->f_fa), VM_PROT_WRITE, TRUE); 738 fa = (u_int)&vmmap[(f->f_fa & PGOFSET) & ~0xF]; 739 bcopy((caddr_t)&f->f_pd0, (caddr_t)fa, 16); 740 DCFL(pmap_extract(pmap_kernel(), (vm_offset_t)fa)); 741 pmap_remove(pmap_kernel(), (vm_offset_t)vmmap, 742 (vm_offset_t)&vmmap[NBPG]); 743 } else 744 printf("WARNING: pid %d(%s) uid %d: CPUSH not done\n", 745 p->p_pid, p->p_comm, p->p_ucred->cr_uid); 746 } else if ((f->f_ssw & (SSW4_RW|SSW4_TTMASK)) == SSW4_TTM16) { 747 /* 748 * MOVE16 fault. 749 * Line-align the address and write out the push data to 750 * the indicated virtual address. 751 */ 752#ifdef DEBUG 753 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 754 printf(" MOVE16 to VA %x(%x), data %x/%x/%x/%x\n", 755 f->f_fa, f->f_fa & ~0xF, f->f_pd0, f->f_pd1, 756 f->f_pd2, f->f_pd3); 757 if (f->f_wb1s & SSW4_WBSV) 758 panic("writeback: MOVE16 with WB1S valid"); 759 wbstats.move16s++; 760#endif 761 if (KDFAULT(f->f_wb1s)) 762 bcopy((caddr_t)&f->f_pd0, (caddr_t)(f->f_fa & ~0xF), 16); 763 else 764 err = suline((caddr_t)(f->f_fa & ~0xF), (caddr_t)&f->f_pd0); 765 if (err) { 766 fa = f->f_fa & ~0xF; 767#ifdef DEBUG 768 if (mmudebug & MDB_WBFAILED) 769 printf(wberrstr, p->p_pid, p->p_comm, 770 "MOVE16", fp->f_pc, f->f_fa, 771 f->f_fa & ~0xF, f->f_pd0); 772#endif 773 } 774 } else if (f->f_wb1s & SSW4_WBSV) { 775 /* 776 * Writeback #1. 777 * Position the "memory-aligned" data and write it out. 778 */ 779 u_int wb1d = f->f_wb1d; 780 int off; 781 782#ifdef DEBUG 783 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 784 dumpwb(1, f->f_wb1s, f->f_wb1a, f->f_wb1d); 785 wbstats.wb1s++; 786 wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++; 787#endif 788 off = (f->f_wb1a & 3) * 8; 789 switch (f->f_wb1s & SSW4_SZMASK) { 790 case SSW4_SZLW: 791 if (off) 792 wb1d = (wb1d >> (32 - off)) | (wb1d << off); 793 if (KDFAULT(f->f_wb1s)) 794 *(long *)f->f_wb1a = wb1d; 795 else 796 err = suword((caddr_t)f->f_wb1a, wb1d); 797 break; 798 case SSW4_SZB: 799 off = 24 - off; 800 if (off) 801 wb1d >>= off; 802 if (KDFAULT(f->f_wb1s)) 803 *(char *)f->f_wb1a = wb1d; 804 else 805 err = subyte((caddr_t)f->f_wb1a, wb1d); 806 break; 807 case SSW4_SZW: 808 off = (off + 16) % 32; 809 if (off) 810 wb1d = (wb1d >> (32 - off)) | (wb1d << off); 811 if (KDFAULT(f->f_wb1s)) 812 *(short *)f->f_wb1a = wb1d; 813 else 814 err = susword((caddr_t)f->f_wb1a, wb1d); 815 break; 816 } 817 if (err) { 818 fa = f->f_wb1a; 819#ifdef DEBUG 820 if (mmudebug & MDB_WBFAILED) 821 printf(wberrstr, p->p_pid, p->p_comm, 822 "#1", fp->f_pc, f->f_fa, 823 f->f_wb1a, f->f_wb1d); 824#endif 825 } 826 } 827 /* 828 * Deal with the "normal" writebacks. 829 * 830 * XXX writeback2 is known to reflect a LINE size writeback after 831 * a MOVE16 was already dealt with above. Ignore it. 832 */ 833 if (err == 0 && (f->f_wb2s & SSW4_WBSV) && 834 (f->f_wb2s & SSW4_SZMASK) != SSW4_SZLN) { 835#ifdef DEBUG 836 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 837 dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d); 838 wbstats.wb2s++; 839 wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++; 840#endif 841 switch (f->f_wb2s & SSW4_SZMASK) { 842 case SSW4_SZLW: 843 if (KDFAULT(f->f_wb2s)) 844 *(long *)f->f_wb2a = f->f_wb2d; 845 else 846 err = suword((caddr_t)f->f_wb2a, f->f_wb2d); 847 break; 848 case SSW4_SZB: 849 if (KDFAULT(f->f_wb2s)) 850 *(char *)f->f_wb2a = f->f_wb2d; 851 else 852 err = subyte((caddr_t)f->f_wb2a, f->f_wb2d); 853 break; 854 case SSW4_SZW: 855 if (KDFAULT(f->f_wb2s)) 856 *(short *)f->f_wb2a = f->f_wb2d; 857 else 858 err = susword((caddr_t)f->f_wb2a, f->f_wb2d); 859 break; 860 } 861 if (err) { 862 fa = f->f_wb2a; 863#ifdef DEBUG 864 if (mmudebug & MDB_WBFAILED) { 865 printf(wberrstr, p->p_pid, p->p_comm, 866 "#2", fp->f_pc, f->f_fa, 867 f->f_wb2a, f->f_wb2d); 868 dumpssw(f->f_ssw); 869 dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d); 870 } 871#endif 872 } 873 } 874 if (err == 0 && (f->f_wb3s & SSW4_WBSV)) { 875#ifdef DEBUG 876 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 877 dumpwb(3, f->f_wb3s, f->f_wb3a, f->f_wb3d); 878 wbstats.wb3s++; 879 wbstats.wbsize[(f->f_wb3s&SSW4_SZMASK)>>5]++; 880#endif 881 switch (f->f_wb3s & SSW4_SZMASK) { 882 case SSW4_SZLW: 883 if (KDFAULT(f->f_wb3s)) 884 *(long *)f->f_wb3a = f->f_wb3d; 885 else 886 err = suword((caddr_t)f->f_wb3a, f->f_wb3d); 887 break; 888 case SSW4_SZB: 889 if (KDFAULT(f->f_wb3s)) 890 *(char *)f->f_wb3a = f->f_wb3d; 891 else 892 err = subyte((caddr_t)f->f_wb3a, f->f_wb3d); 893 break; 894 case SSW4_SZW: 895 if (KDFAULT(f->f_wb3s)) 896 *(short *)f->f_wb3a = f->f_wb3d; 897 else 898 err = susword((caddr_t)f->f_wb3a, f->f_wb3d); 899 break; 900#ifdef DEBUG 901 case SSW4_SZLN: 902 panic("writeback: wb3s indicates LINE write"); 903#endif 904 } 905 if (err) { 906 fa = f->f_wb3a; 907#ifdef DEBUG 908 if (mmudebug & MDB_WBFAILED) 909 printf(wberrstr, p->p_pid, p->p_comm, 910 "#3", fp->f_pc, f->f_fa, 911 f->f_wb3a, f->f_wb3d); 912#endif 913 } 914 } 915 p->p_addr->u_pcb.pcb_onfault = oonfault; 916 if (err) 917 err = SIGSEGV; 918 return (err); 919} 920 921#ifdef DEBUG 922void 923dumpssw(ssw) 924 u_short ssw; 925{ 926 printf(" SSW: %x: ", ssw); 927 if (ssw & SSW4_CP) 928 printf("CP,"); 929 if (ssw & SSW4_CU) 930 printf("CU,"); 931 if (ssw & SSW4_CT) 932 printf("CT,"); 933 if (ssw & SSW4_CM) 934 printf("CM,"); 935 if (ssw & SSW4_MA) 936 printf("MA,"); 937 if (ssw & SSW4_ATC) 938 printf("ATC,"); 939 if (ssw & SSW4_LK) 940 printf("LK,"); 941 if (ssw & SSW4_RW) 942 printf("RW,"); 943 printf(" SZ=%s, TT=%s, TM=%s\n", 944 f7sz[(ssw & SSW4_SZMASK) >> 5], 945 f7tt[(ssw & SSW4_TTMASK) >> 3], 946 f7tm[ssw & SSW4_TMMASK]); 947} 948 949void 950dumpwb(num, s, a, d) 951 int num; 952 u_short s; 953 u_int a, d; 954{ 955 struct proc *p = curproc; 956 vm_offset_t pa; 957 958 printf(" writeback #%d: VA %x, data %x, SZ=%s, TT=%s, TM=%s\n", 959 num, a, d, f7sz[(s & SSW4_SZMASK) >> 5], 960 f7tt[(s & SSW4_TTMASK) >> 3], f7tm[s & SSW4_TMMASK]); 961 printf(" PA "); 962 pa = pmap_extract(p->p_vmspace->vm_map.pmap, (vm_offset_t)a); 963 if (pa == 0) 964 printf("<invalid address>"); 965 else 966 printf("%lx, current value %lx", pa, fuword((caddr_t)a)); 967 printf("\n"); 968} 969#endif 970#endif 971 972/* 973 * Process a system call. 974 */ 975void 976syscall(code, frame) 977 register_t code; 978 struct frame frame; 979{ 980 caddr_t params; 981 struct sysent *callp; 982 struct proc *p; 983 int error, opc, nsys; 984 size_t argsize; 985 register_t args[8], rval[2]; 986 u_quad_t sticks; 987 988 cnt.v_syscall++; 989 if (!USERMODE(frame.f_sr)) 990 panic("syscall"); 991 p = curproc; 992 sticks = p->p_sticks; 993 p->p_md.md_regs = frame.f_regs; 994 opc = frame.f_pc; 995 996 nsys = p->p_emul->e_nsysent; 997 callp = p->p_emul->e_sysent; 998 999#ifdef COMPAT_SUNOS 1000 if (p->p_emul == &emul_sunos) { 1001 /* 1002 * SunOS passes the syscall-number on the stack, whereas 1003 * BSD passes it in D0. So, we have to get the real "code" 1004 * from the stack, and clean up the stack, as SunOS glue 1005 * code assumes the kernel pops the syscall argument the 1006 * glue pushed on the stack. Sigh... 1007 */ 1008 code = fuword((caddr_t)frame.f_regs[SP]); 1009 1010 /* 1011 * XXX 1012 * Don't do this for sunos_sigreturn, as there's no stored pc 1013 * on the stack to skip, the argument follows the syscall 1014 * number without a gap. 1015 */ 1016 if (code != SUNOS_SYS_sigreturn) { 1017 frame.f_regs[SP] += sizeof (int); 1018 /* 1019 * remember that we adjusted the SP, 1020 * might have to undo this if the system call 1021 * returns ERESTART. 1022 */ 1023 p->p_md.md_flags |= MDP_STACKADJ; 1024 } else 1025 p->p_md.md_flags &= ~MDP_STACKADJ; 1026 } 1027#endif 1028 1029 params = (caddr_t)frame.f_regs[SP] + sizeof(int); 1030 1031 switch (code) { 1032 case SYS_syscall: 1033 /* 1034 * Code is first argument, followed by actual args. 1035 */ 1036 code = fuword(params); 1037 params += sizeof(int); 1038 /* 1039 * XXX sigreturn requires special stack manipulation 1040 * that is only done if entered via the sigreturn 1041 * trap. Cannot allow it here so make sure we fail. 1042 */ 1043 switch (code) { 1044#ifdef COMPAT_13 1045 case SYS_compat_13_sigreturn13: 1046#endif 1047 case SYS___sigreturn14: 1048 code = nsys; 1049 break; 1050 } 1051 break; 1052 case SYS___syscall: 1053 /* 1054 * Like syscall, but code is a quad, so as to maintain 1055 * quad alignment for the rest of the arguments. 1056 */ 1057 if (callp != sysent) 1058 break; 1059 code = fuword(params + _QUAD_LOWWORD * sizeof(int)); 1060 params += sizeof(quad_t); 1061 break; 1062 default: 1063 break; 1064 } 1065 if (code < 0 || code >= nsys) 1066 callp += p->p_emul->e_nosys; /* illegal */ 1067 else 1068 callp += code; 1069 argsize = callp->sy_argsize; 1070 if (argsize) 1071 error = copyin(params, (caddr_t)args, argsize); 1072 else 1073 error = 0; 1074#ifdef SYSCALL_DEBUG 1075 scdebug_call(p, code, args); 1076#endif 1077#ifdef KTRACE 1078 if (KTRPOINT(p, KTR_SYSCALL)) 1079 ktrsyscall(p->p_tracep, code, argsize, args); 1080#endif 1081 if (error) 1082 goto bad; 1083 rval[0] = 0; 1084 rval[1] = frame.f_regs[D1]; 1085 error = (*callp->sy_call)(p, args, rval); 1086 switch (error) { 1087 case 0: 1088 frame.f_regs[D0] = rval[0]; 1089 frame.f_regs[D1] = rval[1]; 1090 frame.f_sr &= ~PSL_C; /* carry bit */ 1091 break; 1092 case ERESTART: 1093 /* 1094 * We always enter through a `trap' instruction, which is 2 1095 * bytes, so adjust the pc by that amount. 1096 */ 1097 frame.f_pc = opc - 2; 1098 break; 1099 case EJUSTRETURN: 1100 /* nothing to do */ 1101 break; 1102 default: 1103 bad: 1104 if (p->p_emul->e_errno) 1105 error = p->p_emul->e_errno[error]; 1106 frame.f_regs[D0] = error; 1107 frame.f_sr |= PSL_C; /* carry bit */ 1108 break; 1109 } 1110 1111#ifdef SYSCALL_DEBUG 1112 scdebug_ret(p, code, error, rval); 1113#endif 1114#ifdef COMPAT_SUNOS 1115 /* need new p-value for this */ 1116 if (error == ERESTART && (p->p_md.md_flags & MDP_STACKADJ)) 1117 frame.f_regs[SP] -= sizeof (int); 1118#endif 1119 userret(p, &frame, sticks, (u_int)0, 0); 1120#ifdef KTRACE 1121 if (KTRPOINT(p, KTR_SYSRET)) 1122 ktrsysret(p->p_tracep, code, error, rval[0]); 1123#endif 1124} 1125 1126void 1127child_return(p, frame) 1128 struct proc *p; 1129 struct frame frame; 1130{ 1131 1132 frame.f_regs[D0] = 0; 1133 frame.f_sr &= ~PSL_C; 1134 frame.f_format = FMT0; 1135 1136 userret(p, &frame, 0, (u_int)0, 0); 1137#ifdef KTRACE 1138 if (KTRPOINT(p, KTR_SYSRET)) 1139 ktrsysret(p->p_tracep, SYS_fork, 0, 0); 1140#endif 1141} 1142 1143/* 1144 * Allocation routines for software interrupts. 1145 */ 1146u_long 1147allocate_sir(proc, arg) 1148 void (*proc)(); 1149 void *arg; 1150{ 1151 int bit; 1152 1153 if( next_sir >= NSIR ) 1154 panic("allocate_sir: none left"); 1155 bit = next_sir++; 1156 sir_routines[bit] = proc; 1157 sir_args[bit] = arg; 1158 return (1 << bit); 1159} 1160 1161void 1162init_sir() 1163{ 1164 extern void netintr(); 1165 1166 sir_routines[0] = netintr; 1167 sir_routines[1] = softclock; 1168 next_sir = 2; 1169} 1170