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