Annotation of sys/arch/sparc/sparc/machdep.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: machdep.c,v 1.113 2007/06/06 17:15:12 deraadt Exp $ */
! 2: /* $NetBSD: machdep.c,v 1.85 1997/09/12 08:55:02 pk Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 1992, 1993
! 6: * The Regents of the University of California. All rights reserved.
! 7: *
! 8: * This software was developed by the Computer Systems Engineering group
! 9: * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
! 10: * contributed to Berkeley.
! 11: *
! 12: * All advertising materials mentioning features or use of this software
! 13: * must display the following acknowledgement:
! 14: * This product includes software developed by the University of
! 15: * California, Lawrence Berkeley Laboratory.
! 16: *
! 17: * Redistribution and use in source and binary forms, with or without
! 18: * modification, are permitted provided that the following conditions
! 19: * are met:
! 20: * 1. Redistributions of source code must retain the above copyright
! 21: * notice, this list of conditions and the following disclaimer.
! 22: * 2. Redistributions in binary form must reproduce the above copyright
! 23: * notice, this list of conditions and the following disclaimer in the
! 24: * documentation and/or other materials provided with the distribution.
! 25: * 3. Neither the name of the University nor the names of its contributors
! 26: * may be used to endorse or promote products derived from this software
! 27: * without specific prior written permission.
! 28: *
! 29: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
! 30: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 31: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 32: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 33: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 34: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 35: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 36: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 37: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 38: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 39: * SUCH DAMAGE.
! 40: *
! 41: * @(#)machdep.c 8.6 (Berkeley) 1/14/94
! 42: */
! 43:
! 44: #include <sys/param.h>
! 45: #include <sys/signal.h>
! 46: #include <sys/signalvar.h>
! 47: #include <sys/proc.h>
! 48: #include <sys/user.h>
! 49: #include <sys/buf.h>
! 50: #include <sys/device.h>
! 51: #include <sys/reboot.h>
! 52: #include <sys/systm.h>
! 53: #include <sys/conf.h>
! 54: #include <sys/file.h>
! 55: #include <sys/timeout.h>
! 56: #include <sys/malloc.h>
! 57: #include <sys/mbuf.h>
! 58: #include <sys/mount.h>
! 59: #include <sys/msgbuf.h>
! 60: #include <sys/syscallargs.h>
! 61: #ifdef SYSVMSG
! 62: #include <sys/msg.h>
! 63: #endif
! 64: #include <sys/exec.h>
! 65: #include <sys/sysctl.h>
! 66: #include <sys/extent.h>
! 67:
! 68: #include <uvm/uvm_extern.h>
! 69:
! 70: #include <dev/rndvar.h>
! 71:
! 72: #include <machine/autoconf.h>
! 73: #include <machine/frame.h>
! 74: #include <machine/cpu.h>
! 75: #include <machine/pmap.h>
! 76: #include <machine/vmparam.h>
! 77: #include <machine/oldmon.h>
! 78: #include <machine/bsd_openprom.h>
! 79:
! 80: #include <sparc/sparc/asm.h>
! 81: #include <sparc/sparc/cache.h>
! 82: #include <sparc/sparc/vaddrs.h>
! 83: #include <sparc/sparc/cpuvar.h>
! 84:
! 85: #include <uvm/uvm.h>
! 86:
! 87: #ifdef SUN4M
! 88: #include "power.h"
! 89: #if NPOWER > 0
! 90: #include <sparc/dev/power.h>
! 91: #endif
! 92: #include "scf.h"
! 93: #include "tctrl.h"
! 94: #if NTCTRL > 0
! 95: #include <sparc/dev/tctrlvar.h>
! 96: #endif
! 97: #endif
! 98:
! 99: #include "auxreg.h"
! 100:
! 101: #ifdef SUN4
! 102: #include <sparc/dev/led.h>
! 103: #include "led.h"
! 104: #endif
! 105:
! 106: struct vm_map *exec_map = NULL;
! 107: struct vm_map *phys_map = NULL;
! 108:
! 109: /*
! 110: * Declare these as initialized data so we can patch them.
! 111: */
! 112: #ifndef BUFCACHEPERCENT
! 113: #define BUFCACHEPERCENT 5
! 114: #endif
! 115:
! 116: #ifdef BUFPAGES
! 117: int bufpages = BUFPAGES;
! 118: #else
! 119: int bufpages = 0;
! 120: #endif
! 121: int bufcachepercent = BUFCACHEPERCENT;
! 122:
! 123: int physmem;
! 124:
! 125: /* sysctl settable */
! 126: int sparc_led_blink = 0;
! 127:
! 128: /*
! 129: * safepri is a safe priority for sleep to set for a spin-wait
! 130: * during autoconfiguration or after a panic.
! 131: */
! 132: int safepri = 0;
! 133:
! 134: /*
! 135: * dvmamap is used to manage DVMA memory. Note: this coincides with
! 136: * the memory range in `phys_map' (which is mostly a place-holder).
! 137: */
! 138: vaddr_t dvma_base, dvma_end;
! 139: struct extent *dvmamap_extent;
! 140:
! 141: caddr_t allocsys(caddr_t);
! 142: void dumpsys(void);
! 143: void stackdump(void);
! 144:
! 145: /*
! 146: * Machine-dependent startup code
! 147: */
! 148: void
! 149: cpu_startup()
! 150: {
! 151: caddr_t v;
! 152: int sz;
! 153: #ifdef DEBUG
! 154: extern int pmapdebug;
! 155: int opmapdebug = pmapdebug;
! 156: #endif
! 157: vaddr_t minaddr, maxaddr;
! 158: extern struct user *proc0paddr;
! 159:
! 160: #ifdef DEBUG
! 161: pmapdebug = 0;
! 162: #endif
! 163:
! 164: if (CPU_ISSUN4M) {
! 165: extern int stackgap_random;
! 166:
! 167: stackgap_random = STACKGAP_RANDOM_SUN4M;
! 168: }
! 169:
! 170: /*
! 171: * fix message buffer mapping, note phys addr of msgbuf is 0
! 172: */
! 173: pmap_map(MSGBUF_VA, 0, MSGBUFSIZE, VM_PROT_READ|VM_PROT_WRITE);
! 174: initmsgbuf((caddr_t)(MSGBUF_VA + (CPU_ISSUN4 ? 4096 : 0)), MSGBUFSIZE);
! 175:
! 176: proc0.p_addr = proc0paddr;
! 177:
! 178: /*
! 179: * Good {morning,afternoon,evening,night}.
! 180: */
! 181: printf(version);
! 182: /*identifycpu();*/
! 183: printf("real mem = %u (%uMB)\n", ctob(physmem),
! 184: ctob(physmem)/1024/1024);
! 185:
! 186: /*
! 187: * Find out how much space we need, allocate it,
! 188: * and then give everything true virtual addresses.
! 189: */
! 190: sz = (int)allocsys((caddr_t)0);
! 191:
! 192: if ((v = (caddr_t)uvm_km_alloc(kernel_map, round_page(sz))) == 0)
! 193: panic("startup: no room for tables");
! 194:
! 195: if (allocsys(v) - v != sz)
! 196: panic("startup: table size inconsistency");
! 197:
! 198: /*
! 199: * Determine how many buffers to allocate.
! 200: * We allocate bufcachepercent% of memory for buffer space.
! 201: */
! 202: if (bufpages == 0)
! 203: bufpages = physmem * bufcachepercent / 100;
! 204:
! 205: /* Restrict to at most 25% filled kvm */
! 206: if (bufpages >
! 207: (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) / PAGE_SIZE / 4)
! 208: bufpages = (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) /
! 209: PAGE_SIZE / 4;
! 210:
! 211: /*
! 212: * Allocate a submap for exec arguments. This map effectively
! 213: * limits the number of processes exec'ing at any time.
! 214: */
! 215: minaddr = vm_map_min(kernel_map);
! 216: exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
! 217: 16*NCARGS, VM_MAP_PAGEABLE, FALSE, NULL);
! 218:
! 219: /*
! 220: * Allocate a map for physio. Others use a submap of the kernel
! 221: * map, but we want one completely separate, even though it uses
! 222: * the same pmap.
! 223: */
! 224: dvma_base = CPU_ISSUN4M ? DVMA4M_BASE : DVMA_BASE;
! 225: dvma_end = CPU_ISSUN4M ? DVMA4M_END : DVMA_END;
! 226: #if defined(SUN4M)
! 227: if (CPU_ISSUN4M) {
! 228: /*
! 229: * The DVMA space we want partially overrides kernel_map.
! 230: * Allocate it in kernel_map as well to prevent it from being
! 231: * used for other things.
! 232: */
! 233: if (uvm_map(kernel_map, &dvma_base,
! 234: vm_map_max(kernel_map) - dvma_base,
! 235: NULL, UVM_UNKNOWN_OFFSET, 0,
! 236: UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE,
! 237: UVM_ADV_NORMAL, 0)))
! 238: panic("startup: can not steal dvma map");
! 239: }
! 240: #endif
! 241: phys_map = uvm_map_create(pmap_kernel(), dvma_base, dvma_end,
! 242: VM_MAP_INTRSAFE);
! 243: if (phys_map == NULL)
! 244: panic("unable to create DVMA map");
! 245:
! 246: /*
! 247: * Allocate DVMA space and dump into a privately managed
! 248: * resource map for double mappings which is usable from
! 249: * interrupt contexts.
! 250: */
! 251: if (uvm_km_valloc_wait(phys_map, (dvma_end-dvma_base)) != dvma_base)
! 252: panic("unable to allocate from DVMA map");
! 253: dvmamap_extent = extent_create("dvmamap", dvma_base, dvma_end,
! 254: M_DEVBUF, NULL, 0, EX_NOWAIT);
! 255: if (dvmamap_extent == 0)
! 256: panic("unable to allocate extent for dvma");
! 257:
! 258: #ifdef DEBUG
! 259: pmapdebug = opmapdebug;
! 260: #endif
! 261: printf("avail mem = %lu (%luMB)\n", ptoa(uvmexp.free),
! 262: ptoa(uvmexp.free)/1024/1024);
! 263:
! 264: /*
! 265: * Set up buffers, so they can be used to read disk labels.
! 266: */
! 267: bufinit();
! 268:
! 269: /* Early interrupt handlers initialization */
! 270: intr_init();
! 271: }
! 272:
! 273: /*
! 274: * Allocate space for system data structures. We are given
! 275: * a starting virtual address and we return a final virtual
! 276: * address; along the way we set each data structure pointer.
! 277: *
! 278: * You call allocsys() with 0 to find out how much space we want,
! 279: * allocate that much and fill it with zeroes, and then call
! 280: * allocsys() again with the correct base virtual address.
! 281: */
! 282: caddr_t
! 283: allocsys(v)
! 284: caddr_t v;
! 285: {
! 286:
! 287: #define valloc(name, type, num) \
! 288: v = (caddr_t)(((name) = (type *)v) + (num))
! 289: #ifdef SYSVMSG
! 290: valloc(msgpool, char, msginfo.msgmax);
! 291: valloc(msgmaps, struct msgmap, msginfo.msgseg);
! 292: valloc(msghdrs, struct msg, msginfo.msgtql);
! 293: valloc(msqids, struct msqid_ds, msginfo.msgmni);
! 294: #endif
! 295:
! 296: return (v);
! 297: }
! 298:
! 299: /*
! 300: * Set up registers on exec.
! 301: *
! 302: * XXX this entire mess must be fixed
! 303: */
! 304: /* ARGSUSED */
! 305: void
! 306: setregs(p, pack, stack, retval)
! 307: struct proc *p;
! 308: struct exec_package *pack;
! 309: u_long stack;
! 310: register_t *retval;
! 311: {
! 312: struct trapframe *tf = p->p_md.md_tf;
! 313: struct fpstate *fs;
! 314: int psr;
! 315:
! 316: /*
! 317: * Setup the process StackGhost cookie which will be XORed into
! 318: * the return pointer as register windows are over/underflowed
! 319: */
! 320: p->p_addr->u_pcb.pcb_wcookie = arc4random();
! 321:
! 322: /* The cookie needs to guarantee invalid alignment after the XOR */
! 323: switch (p->p_addr->u_pcb.pcb_wcookie % 3) {
! 324: case 0: /* Two lsb's already both set except if the cookie is 0 */
! 325: p->p_addr->u_pcb.pcb_wcookie |= 0x3;
! 326: break;
! 327: case 1: /* Set the lsb */
! 328: p->p_addr->u_pcb.pcb_wcookie = 1 |
! 329: (p->p_addr->u_pcb.pcb_wcookie & ~0x3);
! 330: break;
! 331: case 2: /* Set the second most lsb */
! 332: p->p_addr->u_pcb.pcb_wcookie = 2 |
! 333: (p->p_addr->u_pcb.pcb_wcookie & ~0x3);
! 334: break;
! 335: }
! 336:
! 337: /* Don't allow misaligned code by default */
! 338: p->p_md.md_flags &= ~MDP_FIXALIGN;
! 339:
! 340: /*
! 341: * The syscall will ``return'' to npc or %g7 or %g2; set them all.
! 342: * Set the rest of the registers to 0 except for %o6 (stack pointer,
! 343: * built in exec()) and psr (retain CWP and PSR_S bits).
! 344: */
! 345: psr = tf->tf_psr & (PSR_S | PSR_CWP);
! 346: if ((fs = p->p_md.md_fpstate) != NULL) {
! 347: /*
! 348: * We hold an FPU state. If we own *the* FPU chip state
! 349: * we must get rid of it, and the only way to do that is
! 350: * to save it. In any case, get rid of our FPU state.
! 351: */
! 352: if (p == cpuinfo.fpproc) {
! 353: savefpstate(fs);
! 354: cpuinfo.fpproc = NULL;
! 355: }
! 356: free((void *)fs, M_SUBPROC);
! 357: p->p_md.md_fpstate = NULL;
! 358: }
! 359: bzero((caddr_t)tf, sizeof *tf);
! 360: tf->tf_psr = psr;
! 361: tf->tf_npc = pack->ep_entry & ~3;
! 362: tf->tf_global[1] = (int)PS_STRINGS;
! 363: tf->tf_global[2] = tf->tf_global[7] = tf->tf_npc;
! 364: /* XXX exec of init(8) returns via proc_trampoline() */
! 365: if (p->p_pid == 1) {
! 366: tf->tf_pc = tf->tf_npc;
! 367: tf->tf_npc += 4;
! 368: }
! 369: stack -= sizeof(struct rwindow);
! 370: tf->tf_out[6] = stack;
! 371: retval[1] = 0;
! 372: }
! 373:
! 374: #ifdef DEBUG
! 375: int sigdebug = 0;
! 376: int sigpid = 0;
! 377: #define SDB_FOLLOW 0x01
! 378: #define SDB_KSTACK 0x02
! 379: #define SDB_FPSTATE 0x04
! 380: #endif
! 381:
! 382: struct sigframe {
! 383: int sf_signo; /* signal number */
! 384: siginfo_t *sf_sip; /* points to siginfo_t */
! 385: #ifdef COMPAT_SUNOS
! 386: struct sigcontext *sf_scp; /* points to user addr of sigcontext */
! 387: #else
! 388: int sf_xxx; /* placeholder */
! 389: #endif
! 390: caddr_t sf_addr; /* SunOS compat */
! 391: struct sigcontext sf_sc; /* actual sigcontext */
! 392: siginfo_t sf_si;
! 393: };
! 394:
! 395: /*
! 396: * machine dependent system variables.
! 397: */
! 398: int
! 399: cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
! 400: int *name;
! 401: u_int namelen;
! 402: void *oldp;
! 403: size_t *oldlenp;
! 404: void *newp;
! 405: size_t newlen;
! 406: struct proc *p;
! 407: {
! 408: #if (NLED > 0) || (NAUXREG > 0) || (NSCF > 0)
! 409: int oldval;
! 410: #endif
! 411: int ret;
! 412: extern int v8mul;
! 413:
! 414: /* all sysctl names are this level are terminal */
! 415: if (namelen != 1)
! 416: return (ENOTDIR); /* overloaded */
! 417:
! 418: switch (name[0]) {
! 419: case CPU_LED_BLINK:
! 420: #if (NLED > 0) || (NAUXREG > 0) || (NSCF > 0)
! 421: oldval = sparc_led_blink;
! 422: ret = sysctl_int(oldp, oldlenp, newp, newlen,
! 423: &sparc_led_blink);
! 424:
! 425: /*
! 426: * If we were false and are now true, call led_blink().
! 427: * led_blink() itself will catch the other case.
! 428: */
! 429: if (!oldval && sparc_led_blink > oldval) {
! 430: #if NAUXREG > 0
! 431: led_blink((caddr_t *)0);
! 432: #endif
! 433: #if NLED > 0
! 434: led_cycle((caddr_t *)led_sc);
! 435: #endif
! 436: #if NSCF > 0
! 437: scfblink((caddr_t *)0);
! 438: #endif
! 439: }
! 440:
! 441: return (ret);
! 442: #else
! 443: return (EOPNOTSUPP);
! 444: #endif
! 445: case CPU_CPUTYPE:
! 446: return (sysctl_rdint(oldp, oldlenp, newp, cputyp));
! 447: case CPU_V8MUL:
! 448: return (sysctl_rdint(oldp, oldlenp, newp, v8mul));
! 449: default:
! 450: return (EOPNOTSUPP);
! 451: }
! 452: /* NOTREACHED */
! 453: }
! 454:
! 455: /*
! 456: * Send an interrupt to process.
! 457: */
! 458: void
! 459: sendsig(catcher, sig, mask, code, type, val)
! 460: sig_t catcher;
! 461: int sig, mask;
! 462: u_long code;
! 463: int type;
! 464: union sigval val;
! 465: {
! 466: struct proc *p = curproc;
! 467: struct sigacts *psp = p->p_sigacts;
! 468: struct sigframe *fp;
! 469: struct trapframe *tf;
! 470: int caddr, oonstack, oldsp, newsp;
! 471: struct sigframe sf;
! 472: #ifdef COMPAT_SUNOS
! 473: extern struct emul emul_sunos;
! 474: #endif
! 475:
! 476: tf = p->p_md.md_tf;
! 477: oldsp = tf->tf_out[6];
! 478: oonstack = psp->ps_sigstk.ss_flags & SS_ONSTACK;
! 479: /*
! 480: * Compute new user stack addresses, subtract off
! 481: * one signal frame, and align.
! 482: */
! 483: if ((psp->ps_flags & SAS_ALTSTACK) && !oonstack &&
! 484: (psp->ps_sigonstack & sigmask(sig))) {
! 485: fp = (struct sigframe *)(psp->ps_sigstk.ss_sp +
! 486: psp->ps_sigstk.ss_size);
! 487: psp->ps_sigstk.ss_flags |= SS_ONSTACK;
! 488: } else
! 489: fp = (struct sigframe *)oldsp;
! 490: fp = (struct sigframe *)((int)(fp - 1) & ~7);
! 491:
! 492: #ifdef DEBUG
! 493: if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
! 494: printf("sendsig: %s[%d] sig %d newusp %p scp %p\n",
! 495: p->p_comm, p->p_pid, sig, fp, &fp->sf_sc);
! 496: #endif
! 497: /*
! 498: * Now set up the signal frame. We build it in kernel space
! 499: * and then copy it out. We probably ought to just build it
! 500: * directly in user space....
! 501: */
! 502: sf.sf_signo = sig;
! 503: sf.sf_sip = NULL;
! 504: #ifdef COMPAT_SUNOS
! 505: if (p->p_emul == &emul_sunos) {
! 506: sf.sf_sip = (void *)code; /* SunOS has "int code" */
! 507: sf.sf_scp = &fp->sf_sc;
! 508: sf.sf_addr = val.sival_ptr;
! 509: }
! 510: #endif
! 511:
! 512: /*
! 513: * Build the signal context to be used by sigreturn.
! 514: */
! 515: sf.sf_sc.sc_onstack = oonstack;
! 516: sf.sf_sc.sc_mask = mask;
! 517: sf.sf_sc.sc_sp = oldsp;
! 518: sf.sf_sc.sc_pc = tf->tf_pc;
! 519: sf.sf_sc.sc_npc = tf->tf_npc;
! 520: sf.sf_sc.sc_psr = tf->tf_psr;
! 521: sf.sf_sc.sc_g1 = tf->tf_global[1];
! 522: sf.sf_sc.sc_o0 = tf->tf_out[0];
! 523:
! 524: if (psp->ps_siginfo & sigmask(sig)) {
! 525: sf.sf_sip = &fp->sf_si;
! 526: initsiginfo(&sf.sf_si, sig, code, type, val);
! 527: }
! 528:
! 529: /*
! 530: * Put the stack in a consistent state before we whack away
! 531: * at it. Note that write_user_windows may just dump the
! 532: * registers into the pcb; we need them in the process's memory.
! 533: * We also need to make sure that when we start the signal handler,
! 534: * its %i6 (%fp), which is loaded from the newly allocated stack area,
! 535: * joins seamlessly with the frame it was in when the signal occurred,
! 536: * so that the debugger and _longjmp code can back up through it.
! 537: */
! 538: newsp = (int)fp - sizeof(struct rwindow);
! 539: write_user_windows();
! 540: /* XXX do not copyout siginfo if not needed */
! 541: if (rwindow_save(p) || copyout((caddr_t)&sf, (caddr_t)fp, sizeof sf) ||
! 542: copyout(&oldsp, &((struct rwindow *)newsp)->rw_in[6],
! 543: sizeof(register_t)) != 0) {
! 544: /*
! 545: * Process has trashed its stack; give it an illegal
! 546: * instruction to halt it in its tracks.
! 547: */
! 548: #ifdef DEBUG
! 549: if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
! 550: printf("sendsig: window save or copyout error\n");
! 551: #endif
! 552: sigexit(p, SIGILL);
! 553: /* NOTREACHED */
! 554: }
! 555: #ifdef DEBUG
! 556: if (sigdebug & SDB_FOLLOW)
! 557: printf("sendsig: %s[%d] sig %d scp %p\n",
! 558: p->p_comm, p->p_pid, sig, &fp->sf_sc);
! 559: #endif
! 560: /*
! 561: * Arrange to continue execution at the code copied out in exec().
! 562: * It needs the function to call in %g1, and a new stack pointer.
! 563: */
! 564: #ifdef COMPAT_SUNOS
! 565: if (psp->ps_usertramp & sigmask(sig)) {
! 566: caddr = (int)catcher; /* user does his own trampolining */
! 567: } else
! 568: #endif
! 569: {
! 570: caddr = p->p_sigcode;
! 571: tf->tf_global[1] = (int)catcher;
! 572: }
! 573: tf->tf_pc = caddr;
! 574: tf->tf_npc = caddr + 4;
! 575: tf->tf_out[6] = newsp;
! 576: #ifdef DEBUG
! 577: if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
! 578: printf("sendsig: about to return to catcher\n");
! 579: #endif
! 580: }
! 581:
! 582: /*
! 583: * System call to cleanup state after a signal
! 584: * has been taken. Reset signal mask and
! 585: * stack state from context left by sendsig (above),
! 586: * and return to the given trap frame (if there is one).
! 587: * Check carefully to make sure that the user has not
! 588: * modified the state to gain improper privileges or to cause
! 589: * a machine fault.
! 590: */
! 591: /* ARGSUSED */
! 592: int
! 593: sys_sigreturn(p, v, retval)
! 594: struct proc *p;
! 595: void *v;
! 596: register_t *retval;
! 597: {
! 598: struct sys_sigreturn_args /* {
! 599: syscallarg(struct sigcontext *) sigcntxp;
! 600: } */ *uap = v;
! 601: struct sigcontext ksc;
! 602: struct trapframe *tf;
! 603: int error;
! 604:
! 605: /* First ensure consistent stack state (see sendsig). */
! 606: write_user_windows();
! 607: if (rwindow_save(p))
! 608: sigexit(p, SIGILL);
! 609: #ifdef DEBUG
! 610: if (sigdebug & SDB_FOLLOW)
! 611: printf("sigreturn: %s[%d], sigcntxp %p\n",
! 612: p->p_comm, p->p_pid, SCARG(uap, sigcntxp));
! 613: #endif
! 614: if ((error = copyin(SCARG(uap, sigcntxp), &ksc, sizeof(ksc))) != 0)
! 615: return (error);
! 616: tf = p->p_md.md_tf;
! 617: /*
! 618: * Only the icc bits in the psr are used, so it need not be
! 619: * verified. pc and npc must be multiples of 4. This is all
! 620: * that is required; if it holds, just do it.
! 621: */
! 622: if (((ksc.sc_pc | ksc.sc_npc) & 3) != 0)
! 623: return (EINVAL);
! 624: /* take only psr ICC field */
! 625: tf->tf_psr = (tf->tf_psr & ~PSR_ICC) | (ksc.sc_psr & PSR_ICC);
! 626: tf->tf_pc = ksc.sc_pc;
! 627: tf->tf_npc = ksc.sc_npc;
! 628: tf->tf_global[1] = ksc.sc_g1;
! 629: tf->tf_out[0] = ksc.sc_o0;
! 630: tf->tf_out[6] = ksc.sc_sp;
! 631: if (ksc.sc_onstack & 1)
! 632: p->p_sigacts->ps_sigstk.ss_flags |= SS_ONSTACK;
! 633: else
! 634: p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK;
! 635: p->p_sigmask = ksc.sc_mask & ~sigcantmask;
! 636: return (EJUSTRETURN);
! 637: }
! 638:
! 639: int waittime = -1;
! 640:
! 641: void
! 642: boot(howto)
! 643: int howto;
! 644: {
! 645: int i;
! 646: static char str[4]; /* room for "-sd\0" */
! 647:
! 648: /* If system is cold, just halt. */
! 649: if (cold) {
! 650: /* (Unless the user explicitly asked for reboot.) */
! 651: if ((howto & RB_USERREQ) == 0)
! 652: howto |= RB_HALT;
! 653: goto haltsys;
! 654: }
! 655:
! 656: fb_unblank();
! 657: boothowto = howto;
! 658: if ((howto & RB_NOSYNC) == 0 && waittime < 0) {
! 659: extern struct proc proc0;
! 660:
! 661: /* XXX protect against curproc->p_stats.foo refs in sync() */
! 662: if (curproc == NULL)
! 663: curproc = &proc0;
! 664: waittime = 0;
! 665: vfs_shutdown();
! 666:
! 667: /*
! 668: * If we've been adjusting the clock, the todr
! 669: * will be out of synch; adjust it now unless
! 670: * the system was sitting in ddb.
! 671: */
! 672: if ((howto & RB_TIMEBAD) == 0) {
! 673: resettodr();
! 674: } else {
! 675: printf("WARNING: not updating battery clock\n");
! 676: }
! 677: }
! 678: (void) splhigh(); /* ??? */
! 679:
! 680: if (howto & RB_DUMP)
! 681: dumpsys();
! 682:
! 683: haltsys:
! 684: /* Run any shutdown hooks */
! 685: doshutdownhooks();
! 686:
! 687: if ((howto & RB_HALT) || (howto & RB_POWERDOWN)) {
! 688: #if defined(SUN4M)
! 689: if (howto & RB_POWERDOWN) {
! 690: printf("attempting to power down...\n");
! 691: #if NTCTRL > 0
! 692: tadpole_powerdown();
! 693: #endif
! 694: #if NPOWER > 0
! 695: auxio_powerdown();
! 696: #endif
! 697: rominterpret("power-off");
! 698: printf("WARNING: powerdown failed!\n");
! 699: }
! 700: #endif /* SUN4M */
! 701: printf("halted\n\n");
! 702: romhalt();
! 703: }
! 704:
! 705: printf("rebooting\n\n");
! 706: i = 1;
! 707: if (howto & RB_SINGLE)
! 708: str[i++] = 's';
! 709: if (howto & RB_KDB)
! 710: str[i++] = 'd';
! 711: if (i > 1) {
! 712: str[0] = '-';
! 713: str[i] = 0;
! 714: } else
! 715: str[0] = 0;
! 716: romboot(str);
! 717: /*NOTREACHED*/
! 718: }
! 719:
! 720: /* XXX - dumpmag not eplicitly used, savecore may search for it to get here */
! 721: u_long dumpmag = 0x8fca0101; /* magic number for savecore */
! 722: int dumpsize = 0; /* also for savecore */
! 723: long dumplo = 0;
! 724:
! 725: void
! 726: dumpconf(void)
! 727: {
! 728: int nblks, dumpblks;
! 729:
! 730: if (dumpdev == NODEV ||
! 731: (nblks = (bdevsw[major(dumpdev)].d_psize)(dumpdev)) == 0)
! 732: return;
! 733: if (nblks <= ctod(1))
! 734: return;
! 735:
! 736: dumpblks = ctod(physmem) + ctod(pmap_dumpsize());
! 737: if (dumpblks > (nblks - ctod(1)))
! 738: /*
! 739: * dump size is too big for the partition.
! 740: * Note, we safeguard a click at the front for a
! 741: * possible disk label.
! 742: */
! 743: return;
! 744:
! 745: /* Put the dump at the end of the partition */
! 746: dumplo = nblks - dumpblks;
! 747:
! 748: /*
! 749: * savecore(8) expects dumpsize to be the number of pages
! 750: * of actual core dumped (i.e. excluding the MMU stuff).
! 751: */
! 752: dumpsize = physmem;
! 753: }
! 754:
! 755: #define BYTES_PER_DUMP (32 * 1024) /* must be a multiple of pagesize */
! 756: static vaddr_t dumpspace;
! 757:
! 758: /*
! 759: * Allocate the dump i/o buffer area during kernel memory allocation
! 760: */
! 761: caddr_t
! 762: reserve_dumppages(p)
! 763: caddr_t p;
! 764: {
! 765:
! 766: dumpspace = (vaddr_t)p;
! 767: return (p + BYTES_PER_DUMP);
! 768: }
! 769:
! 770: /*
! 771: * Write a crash dump.
! 772: */
! 773: void
! 774: dumpsys()
! 775: {
! 776: int psize;
! 777: daddr64_t blkno;
! 778: int (*dump)(dev_t, daddr64_t, caddr_t, size_t);
! 779: int error = 0;
! 780: struct memarr *mp;
! 781: int nmem;
! 782: extern struct memarr pmemarr[];
! 783: extern int npmemarr;
! 784:
! 785: /* copy registers to memory */
! 786: snapshot(cpcb);
! 787: stackdump();
! 788:
! 789: if (dumpdev == NODEV)
! 790: return;
! 791:
! 792: /*
! 793: * For dumps during autoconfiguration,
! 794: * if dump device has already configured...
! 795: */
! 796: if (dumpsize == 0)
! 797: dumpconf();
! 798: if (dumplo <= 0)
! 799: return;
! 800: printf("\ndumping to dev(%d,%d), at offset %ld blocks\n",
! 801: major(dumpdev), minor(dumpdev), dumplo);
! 802:
! 803: psize = (*bdevsw[major(dumpdev)].d_psize)(dumpdev);
! 804: printf("dump ");
! 805: if (psize == -1) {
! 806: printf("area unavailable\n");
! 807: return;
! 808: }
! 809: blkno = dumplo;
! 810: dump = bdevsw[major(dumpdev)].d_dump;
! 811:
! 812: printf("mmu ");
! 813: error = pmap_dumpmmu(dump, blkno);
! 814: blkno += ctod(pmap_dumpsize());
! 815:
! 816: printf("memory ");
! 817: for (mp = pmemarr, nmem = npmemarr; --nmem >= 0 && error == 0; mp++) {
! 818: unsigned i = 0, n;
! 819: unsigned maddr = mp->addr;
! 820:
! 821: /* XXX - what's so special about PA 0 that we can't dump it? */
! 822: if (maddr == 0) {
! 823: /* Skip first page at physical address 0 */
! 824: maddr += NBPG;
! 825: i += NBPG;
! 826: blkno += btodb(NBPG);
! 827: }
! 828:
! 829: printf("@0x%x:", maddr);
! 830:
! 831: for (; i < mp->len; i += n) {
! 832: n = mp->len - i;
! 833: if (n > BYTES_PER_DUMP)
! 834: n = BYTES_PER_DUMP;
! 835:
! 836: /* print out which MBs we are dumping */
! 837: if (i % (1024*1024) <= NBPG)
! 838: printf("%d ", i / (1024*1024));
! 839:
! 840: (void) pmap_map(dumpspace, maddr, maddr + n,
! 841: VM_PROT_READ);
! 842: error = (*dump)(dumpdev, blkno,
! 843: (caddr_t)dumpspace, (int)n);
! 844: pmap_remove(pmap_kernel(), dumpspace, dumpspace + n);
! 845: if (error)
! 846: break;
! 847: maddr += n;
! 848: blkno += btodb(n);
! 849: }
! 850: }
! 851:
! 852: switch (error) {
! 853:
! 854: case ENXIO:
! 855: printf("device bad\n");
! 856: break;
! 857:
! 858: case EFAULT:
! 859: printf("device not ready\n");
! 860: break;
! 861:
! 862: case EINVAL:
! 863: printf("area improper\n");
! 864: break;
! 865:
! 866: case EIO:
! 867: printf("i/o error\n");
! 868: break;
! 869:
! 870: case 0:
! 871: printf("succeeded\n");
! 872: break;
! 873:
! 874: default:
! 875: printf("error %d\n", error);
! 876: break;
! 877: }
! 878: }
! 879:
! 880: /*
! 881: * get the fp and dump the stack as best we can. don't leave the
! 882: * current stack page
! 883: */
! 884: void
! 885: stackdump()
! 886: {
! 887: struct frame *fp = getfp(), *sfp;
! 888:
! 889: sfp = fp;
! 890: printf("Frame pointer is at %p\n", fp);
! 891: printf("Call traceback:\n");
! 892: while (fp && ((u_long)fp >> PGSHIFT) == ((u_long)sfp >> PGSHIFT)) {
! 893: printf(" pc = 0x%x args = (0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x) fp = %p\n",
! 894: fp->fr_pc, fp->fr_arg[0], fp->fr_arg[1], fp->fr_arg[2],
! 895: fp->fr_arg[3], fp->fr_arg[4], fp->fr_arg[5], fp->fr_arg[6],
! 896: fp->fr_fp);
! 897: fp = fp->fr_fp;
! 898: }
! 899: }
! 900:
! 901: /*
! 902: * Map an I/O device given physical address and size in bytes, e.g.,
! 903: *
! 904: * mydev = (struct mydev *)mapdev(myioaddr, 0,
! 905: * 0, sizeof(struct mydev));
! 906: *
! 907: * See also machine/autoconf.h.
! 908: *
! 909: * XXXART - verify types (too tired now).
! 910: */
! 911: void *
! 912: mapdev(phys, virt, offset, size)
! 913: struct rom_reg *phys;
! 914: int offset, virt, size;
! 915: {
! 916: vaddr_t va;
! 917: paddr_t pa, base;
! 918: void *ret;
! 919: static vaddr_t iobase;
! 920: unsigned int pmtype;
! 921:
! 922: if (iobase == NULL)
! 923: iobase = IODEV_BASE;
! 924:
! 925: base = (paddr_t)phys->rr_paddr + offset;
! 926: if (virt != 0) {
! 927: va = trunc_page(virt);
! 928: size = round_page(virt + size) - va;
! 929: } else {
! 930: size = round_page(base + size) - trunc_page(base);
! 931: va = iobase;
! 932: iobase += size;
! 933: if (iobase > IODEV_END) /* unlikely */
! 934: panic("mapiodev");
! 935: }
! 936: if (size == 0)
! 937: panic("mapdev: zero size");
! 938:
! 939: ret = (void *)(va | (base & PGOFSET));
! 940: /* note: preserve page offset */
! 941:
! 942: pa = trunc_page(base);
! 943: pmtype = PMAP_IOENC(phys->rr_iospace);
! 944:
! 945: do {
! 946: pmap_kenter_pa(va, pa | pmtype | PMAP_NC,
! 947: VM_PROT_READ | VM_PROT_WRITE);
! 948: va += PAGE_SIZE;
! 949: pa += PAGE_SIZE;
! 950: } while ((size -= PAGE_SIZE) > 0);
! 951: pmap_update(pmap_kernel());
! 952: return (ret);
! 953: }
! 954:
! 955: #ifdef COMPAT_SUNOS
! 956: int
! 957: cpu_exec_aout_makecmds(p, epp)
! 958: struct proc *p;
! 959: struct exec_package *epp;
! 960: {
! 961: int error = ENOEXEC;
! 962:
! 963: extern int sunos_exec_aout_makecmds(struct proc *, struct exec_package *);
! 964: if ((error = sunos_exec_aout_makecmds(p, epp)) == 0)
! 965: return 0;
! 966: return error;
! 967: }
! 968: #endif
! 969:
! 970: #ifdef SUN4
! 971: void
! 972: oldmon_w_trace(va)
! 973: u_long va;
! 974: {
! 975: u_long stop;
! 976: struct frame *fp;
! 977:
! 978: if (curproc)
! 979: printf("curproc = %p, pid %d\n", curproc, curproc->p_pid);
! 980: else
! 981: printf("no curproc\n");
! 982: printf("uvm: swtch %d, trap %d, sys %d, intr %d, soft %d, faults %d\n",
! 983: uvmexp.swtch, uvmexp.traps, uvmexp.syscalls, uvmexp.intrs,
! 984: uvmexp.softs, uvmexp.faults);
! 985: write_user_windows();
! 986:
! 987: printf("\nstack trace with sp = 0x%lx\n", va);
! 988: stop = round_page(va);
! 989: printf("stop at 0x%lx\n", stop);
! 990: fp = (struct frame *) va;
! 991: while (round_page((u_long) fp) == stop) {
! 992: printf(" 0x%x(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x) fp %p\n", fp->fr_pc,
! 993: fp->fr_arg[0], fp->fr_arg[1], fp->fr_arg[2], fp->fr_arg[3],
! 994: fp->fr_arg[4], fp->fr_arg[5], fp->fr_arg[6], fp->fr_fp);
! 995: fp = fp->fr_fp;
! 996: if (fp == NULL)
! 997: break;
! 998: }
! 999: printf("end of stack trace\n");
! 1000: }
! 1001:
! 1002: void
! 1003: oldmon_w_cmd(va, ar)
! 1004: u_long va;
! 1005: char *ar;
! 1006: {
! 1007: switch (*ar) {
! 1008: case '\0':
! 1009: switch (va) {
! 1010: case 0:
! 1011: panic("g0 panic");
! 1012: case 4:
! 1013: printf("w: case 4\n");
! 1014: break;
! 1015: default:
! 1016: printf("w: unknown case %ld\n", va);
! 1017: break;
! 1018: }
! 1019: break;
! 1020: case 't':
! 1021: oldmon_w_trace(va);
! 1022: break;
! 1023: default:
! 1024: printf("w: arg not allowed\n");
! 1025: }
! 1026: }
! 1027:
! 1028: int
! 1029: ldcontrolb(addr)
! 1030: caddr_t addr;
! 1031: {
! 1032: struct pcb *xpcb;
! 1033: extern struct user *proc0paddr;
! 1034: u_long saveonfault;
! 1035: int res;
! 1036: int s;
! 1037:
! 1038: s = splhigh();
! 1039: if (curproc == NULL)
! 1040: xpcb = (struct pcb *)proc0paddr;
! 1041: else
! 1042: xpcb = &curproc->p_addr->u_pcb;
! 1043:
! 1044: saveonfault = (u_long)xpcb->pcb_onfault;
! 1045: res = xldcontrolb(addr, xpcb);
! 1046: xpcb->pcb_onfault = (caddr_t)saveonfault;
! 1047:
! 1048: splx(s);
! 1049: return (res);
! 1050: }
! 1051: #endif /* SUN4 */
CVSweb