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