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