[BACK]Return to machdep.c CVS log [TXT][DIR] Up to [local] / sys / arch / sparc / sparc

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