Annotation of researchv9/sys/sun3/machdep.c, revision 1.1.1.1

1.1       root        1: #ifndef lint
                      2: static char sccsid[] = "@(#)machdep.c 1.1 86/02/03 Copyr 1986 Sun Micro";
                      3: #endif lint
                      4: 
                      5: /*
                      6:  * Copyright (c) 1986 by Sun Microsystems, Inc.
                      7:  */
                      8: 
                      9: #include "../h/param.h"
                     10: #include "../h/systm.h"
                     11: #include "../h/dir.h"
                     12: #include "../h/user.h"
                     13: #include "../h/map.h"
                     14: #include "../h/vm.h"
                     15: #include "../h/lnode.h"
                     16: #include "../h/proc.h"
                     17: #include "../h/msgbuf.h"
                     18: #include "../h/buf.h"
                     19: #include "../h/inode.h"
                     20: #include "../h/file.h"
                     21: #include "../h/text.h"
                     22: #include "../h/callout.h"
                     23: #include "../h/cmap.h"
                     24: #include "../h/reboot.h"
                     25: 
                     26: #include "../machine/mbvar.h"
                     27: #include "../machine/psl.h"
                     28: #include "../machine/reg.h"
                     29: #include "../machine/clock.h"
                     30: #include "../machine/pte.h"
                     31: #include "../machine/scb.h"
                     32: #include "../machine/mmu.h"
                     33: #include "../machine/cpu.h"
                     34: #include "../machine/eeprom.h"
                     35: #include "../machine/interreg.h"
                     36: #include "../machine/memerr.h"
                     37: #include "../machine/eccreg.h"
                     38: #include "../machine/frame.h"
                     39: 
                     40: /*
                     41:  * Declare these as initialized data so we can patch them.
                     42:  */
                     43: int nbuf = 0;
                     44: int nswbuf = 0;
                     45: int bufpages = 0;
                     46: int physmem = 0;       /* memory size in pages, patch if you want less */
                     47: int kernprot = 1;      /* write protect kernel text */
                     48: int msgbufinit = 0;    /* message buffer has been initialized, ok to printf */
                     49: dev_t consdev = 0;
                     50: 
                     51: int (*exit_vector)() = (int (*)())0;   /* Where to go when halting UNIX */
                     52: 
                     53: #define TESTVAL        0xA55A  /* memory test value */
                     54: 
                     55: u_char getsegmap(), pmegallocres();
                     56: long   getpgmap();
                     57: 
                     58: #ifdef SUN3_260
                     59: /*
                     60:  * Since there is no implied ordering of the memory cards, we store
                     61:  * a zero terminated list of pointers to eccreg's that are active so
                     62:  * that we only look at existent memory cards during softecc() handling.
                     63:  */
                     64: struct eccreg *ecc_alive[MAX_ECC+1];
                     65: #endif SUN3_260
                     66: 
                     67: /*
                     68:  * We make use of CMAPn (the pte address)
                     69:  * and CADDRn (the virtual address)
                     70:  * which are both temporaries defined in locore.s,
                     71:  * not preserved across context switches,
                     72:  * and not to be used in interrupt routines
                     73:  */
                     74: 
                     75: /*
                     76:  * Machine-dependent startup code
                     77:  */
                     78: startup()
                     79: {
                     80:        register int unixsize, dvmapage;
                     81:        register unsigned i;
                     82:        register int c;
                     83:        register struct pte *pte;
                     84:        register caddr_t v;
                     85:        u_int firstaddr;                /* next free physical page number */
                     86:        extern char start[], etext[], end[], CADDR1[], Syslimit[];
                     87:        u_char oc, u_pmeg;
                     88:        u_int mapaddr;
                     89:        caddr_t zmemall();
                     90:        void v_handler();
                     91:        int mon_mem;
                     92: 
                     93:        initscb();                      /* set trap vectors */
                     94:        *INTERREG |= IR_ENA_INT;        /* make sure interrupts can occur */
                     95:        firstaddr = btoc((int)end - KERNELBASE) + UPAGES;
                     96: 
                     97:        /* 
                     98:         * Initialize map of allocated page map groups.
                     99:         * Must be done before mapin of unallocated segments.
                    100:         */
                    101:        pmeginit();                     /* init list of pmeg data structures */
                    102:        ctxinit();                      /* init context data structures */
                    103: 
                    104:        /*
                    105:         * Reserve necessary pmegs and set segment mapping.
                    106:         * It is assumed here that the pmegs for low
                    107:         * memory have already been duplicated for the
                    108:         * segments up in the kernel virtual address space.
                    109:         */
                    110: 
                    111:        /*
                    112:         * invalidate to start of high mapping
                    113:         */
                    114:        for (i = 0; i < KERNELBASE >> SGSHIFT; i++)
                    115:                setsegmap(i, (u_char)SEGINV);
                    116: 
                    117:        /* reserve kernel pmegs */
                    118:        for (; i < ptos(NPAGSEG - 1 + btoc(end)); i++)
                    119:                pmegreserve(getsegmap(i));
                    120: 
                    121:        for (; i < (MONSTART >> SGSHIFT); i++)  /* invalidate to mon start */
                    122:                setsegmap(i, (u_char)SEGINV);
                    123: 
                    124:        for (; i < (MONEND >> SGSHIFT); i++)    /* reserve monitor pmegs */
                    125:                if ((oc = getsegmap(i)) != (u_char)SEGINV)      
                    126:                        pmegreserve(oc);
                    127: 
                    128:        for (; i < NSEGMAP - 1; i++)            /* invalid until last seg */
                    129:                setsegmap(i, (u_char)SEGINV);
                    130: 
                    131:        /*
                    132:         * Last segment contains the u area itself, 
                    133:         * the pmeg here is reserved for all contexts.
                    134:         * We also reserve the invalid pmeg itself.
                    135:         */
                    136:        u_pmeg = getsegmap(NSEGMAP - 1);
                    137:        pmegreserve(u_pmeg);
                    138:        pmegreserve((u_char)SEGINV);
                    139: 
                    140:        setcputype();                   /* sets cpu and dvmasize variables */
                    141: 
                    142:        /*
                    143:         * Make sure the memory error register is
                    144:         * set up to generate interrupts on error.
                    145:         */
                    146: #if defined(SUN3_160) || defined(SUN3_50)
                    147:        if (cpu == CPU_SUN3_160 || cpu == CPU_SUN3_50)
                    148:                MEMREG->mr_per = PER_INTENA | PER_CHECK;
                    149: #endif defined(SUN3_160) || defined(SUN3_50)
                    150: 
                    151: #ifdef SUN3_260
                    152:        if (cpu == CPU_SUN3_260) {
                    153:                register struct eccreg **ecc_nxt = ecc_alive;
                    154:                register struct eccreg *ecc;
                    155: 
                    156:                /*
                    157:                 * Go probe for all memory cards and perform initialization.
                    158:                 * The address of the cards found is stashed in ecc_alive[].
                    159:                 * We assume that the cards are already enabled and the
                    160:                 * base addresses have been set correctly by the monitor.
                    161:                 */
                    162:                for (ecc = ECCREG; ecc < &ECCREG[MAX_ECC]; ecc++) {
                    163:                        if (peekc((char *)ecc) == -1)
                    164:                                continue;
                    165:                        ecc->eccena.ena_scrub = 1;
                    166:                        ecc->eccena.ena_busena = 1;
                    167:                        *ecc_nxt++ = ecc;
                    168:                }
                    169:                *ecc_nxt = (struct eccreg *)0;          /* terminate list */
                    170: 
                    171:                MEMREG->mr_eer = EER_INTENA | EER_CE_ENA;
                    172:        }
                    173: #endif SUN3_260
                    174: 
                    175:        /*
                    176:         * Allocate pmegs for DVMA space
                    177:         */
                    178:        for (i = ptos(btop(DVMA)); i < ptos(btop(DVMA) + dvmasize); i++) {
                    179:                u_char pm = pmegallocres();
                    180: 
                    181:                setsegmap(i, pm);
                    182:                for (v = (caddr_t)ctob(NPAGSEG * i);
                    183:                        v < (caddr_t)ctob(NPAGSEG * (i+1));
                    184:                    v += NBPG)
                    185:                        setpgmap(v, (long)0);
                    186:        }
                    187: 
                    188:        /*
                    189:         * Now go through all the other contexts and set up the segment
                    190:         * maps so that all segments are mapped the same.
                    191:         * We have to use a PROM routine to do this since we don't want
                    192:         * to switch to a new (unmapped) context to call setsegmap()!
                    193:         */
                    194:        for (c = 0; c < NCONTEXT; c++) {
                    195:                if (c == KCONTEXT)
                    196:                        continue;
                    197: 
                    198:                for (v = (caddr_t)0, i = 0;
                    199:                    v < (caddr_t)ctob(NPAGSEG * NSEGMAP); v += NBSG, i++)
                    200:                        (*romp->v_setcxsegmap)(c, v, getsegmap(i));
                    201:        }
                    202: 
                    203:        /*
                    204:         * Initialize kernel page table entries.
                    205:         */
                    206:        pte = &Sysmap[0];
                    207: 
                    208:        /* invalid until start except scb page which is kernel writable */
                    209:        for (v = (caddr_t)KERNELBASE; v < (caddr_t)start; v += NBPG) {
                    210:                if (v == (caddr_t)&scb)
                    211:                        *(int *)pte = PG_V | PG_KW | getpgmap(v) & PG_PFNUM;
                    212:                else
                    213:                        *(int *)pte = 0;
                    214:                setpgmap(v, *(long *)pte++);
                    215:        }
                    216: 
                    217:        /* set up kernel text pages */
                    218:        for (; v < (caddr_t)etext; v += NBPG) {
                    219:                if (kernprot)           /* is kernel to be protected? */
                    220:                        *(int *)pte = PG_V | PG_KR | getpgmap(v) & PG_PFNUM;
                    221:                else
                    222:                        *(int *)pte = PG_V | PG_KW | getpgmap(v) & PG_PFNUM;
                    223:                setpgmap(v, *(long *)pte++);
                    224:        }
                    225: 
                    226:        /* set up kernel data/bss pages to be writeable */
                    227:        for (; v < (caddr_t)end; v += NBPG) {
                    228:                *(int *)pte = PG_V | PG_KW | getpgmap(v) & PG_PFNUM;
                    229:                setpgmap(v, *(long *)pte++);
                    230:        }
                    231: 
                    232:        /* invalid until end of this segment */
                    233:        i = ((u_int)end + SGOFSET) & ~SGOFSET;
                    234:        for (; v < (caddr_t)i; v += NBPG)
                    235:                setpgmap(v, (long)0);
                    236: 
                    237:        /*
                    238:         * Remove user access to monitor-set-up maps.
                    239:         */
                    240:        for (i = MONSTART>>SGSHIFT; i < MONEND>>SGSHIFT; i++) {
                    241:                if (getsegmap(i) == SEGINV)
                    242:                        continue;
                    243:                for (v = (caddr_t)ctob(NPAGSEG * i); 
                    244:                        v < (caddr_t)ctob(NPAGSEG * (i+1));
                    245:                    v += NBPG)
                    246:                        setpgmap(v, (long)(((getpgmap(v) & ~PG_PROT) | PG_KW)));
                    247:        }
                    248: 
                    249:        /*
                    250:         * Invalidate any other pages in last segment
                    251:         * besides the u area, EEPROM_ADDR, CLKADDR,
                    252:         * MEMREG, INTERREG and MONSHORTPAGE.  This sets
                    253:         * up the kernel redzone below the u area.  We
                    254:         * get interrupt redzone for free when the kernel
                    255:         * is write protected as the interrupt stack is
                    256:         * the first thing in the data area.  Since u
                    257:         * and MONSHORTPAGE are defined as 32 bit virtual
                    258:         * addresses (to get short references to work),
                    259:         * we must mask to get only the 28 bits we really
                    260:         * want to look at.
                    261:         */
                    262:        for (v = (caddr_t)ctob(NPAGSEG * (NSEGMAP - 1));
                    263:             v < (caddr_t)ctob(NPAGSEG * NSEGMAP); v += NBPG) {
                    264:                if (((u_int)v < ((u_int)&u & 0x0FFFFFFF) ||
                    265:                    (u_int)v >= (((u_int)&u & 0x0FFFFFFF) + UPAGES*NBPG)) &&
                    266:                    (u_int)v != ((u_int)MONSHORTPAGE & 0x0FFFFFFF) &&
                    267:                    (u_int)v != (u_int)EEPROM_ADDR &&
                    268:                    (u_int)v != (u_int)CLKADDR &&
                    269:                    (u_int)v != (u_int)MEMREG &&
                    270:                    (u_int)v != (u_int)INTERREG)
                    271:                        setpgmap(v, (long)0);
                    272:        }
                    273: 
                    274:        /*
                    275:         * v_memorysize is the amount of physical memory while
                    276:         * v_memoryavail is the amount of usable memory in versions
                    277:         * equal or greater to 1.  Mon_mem is the difference which
                    278:         * is the number of pages hidden by the monitor.
                    279:         */
                    280:        if (romp->v_romvec_version >= 1)
                    281:                mon_mem = btop(*romp->v_memorysize - *romp->v_memoryavail);
                    282:        else
                    283:                mon_mem = 0;
                    284:        /*
                    285:         * If physmem is patched to be non-zero, use it instead of
                    286:         * the monitor value unless physmem is larger than the total
                    287:         * amount of memory on hand.
                    288:         */
                    289:        if (physmem == 0 || physmem > btop(*romp->v_memorysize))
                    290:                physmem = btop(*romp->v_memorysize);
                    291:        /*
                    292:         * Adjust physmem down for the pages stolen by the monitor.
                    293:         */
                    294:        physmem -= mon_mem;
                    295:        maxmem = physmem;
                    296: 
                    297:        /*
                    298:         * v_vector_cmd is the handler for new monitor vector
                    299:         * command in versions equal or greater to 2.
                    300:         * We install v_handler() there for Unix.
                    301:         */
                    302:        if (romp->v_romvec_version >= 2)
                    303:                *romp->v_vector_cmd = v_handler;
                    304: 
                    305: #include "bwtwo.h"
                    306: #if NBWTWO > 0
                    307:        if (physmem > btop(OBFBADDR + FBSIZE))
                    308:                fbobmemavail = 1;
                    309:        else
                    310:                fbobmemavail = 0;
                    311: #else
                    312:        fbobmemavail = 0;
                    313: #endif
                    314: 
                    315:        /*
                    316:         * Determine if anything lives in DVMA bus space.
                    317:         * We're paranoid and go through both the 16 bit
                    318:         * and 32 bit device types.
                    319:         */
                    320:        disable_dvma();
                    321:        for (dvmapage = 0; dvmapage < btoc(dvmasize); dvmapage++) {
                    322:                mapin(CMAP1, btop(CADDR1), (u_int)(dvmapage | PGT_VME_D16),
                    323:                    1, PG_V | PG_KW);
                    324:                if (poke((short *)CADDR1, TESTVAL) == 0)
                    325:                        break;
                    326:                mapin(CMAP1, btop(CADDR1), (u_int)(dvmapage | PGT_VME_D32),
                    327:                    1, PG_V | PG_KW);
                    328:                if (poke((short *)CADDR1, TESTVAL) == 0)
                    329:                        break;
                    330:        }
                    331:        enable_dvma();
                    332: 
                    333:        /*
                    334:         * Initialize error message buffer (in low real memory before start).
                    335:         * Printf's which occur prior to this will not be captured.
                    336:         */
                    337:        mapin(msgbufmap, (u_int)btop(&msgbuf),
                    338:            (u_int)btop((int)start - sizeof (struct msgbuf) - KERNELBASE),
                    339:            (int)btoc(sizeof (struct msgbuf)), PG_V | PG_KW);
                    340:        msgbufinit = 1;
                    341: 
                    342:        /*
                    343:         * Allocate IOPB memory space just below the message
                    344:         * buffer and map it to the first pages of DVMA space.
                    345:         */
                    346:        maxmem -= IOPBMEM;
                    347:        for (v = (caddr_t)DVMA, i = maxmem; i < maxmem + IOPBMEM;
                    348:            v += NBPG, i++) {
                    349:                struct pte tmp;                 /* scratch pte */
                    350: 
                    351:                mapin(&tmp, btop(v), i, 1, PG_V | PG_KW);
                    352:        }
                    353: 
                    354:        /*
                    355:         * Good {morning,afternoon,evening,night}.
                    356:         * When printing memory, use the total including
                    357:         * those hidden by the monitor (mon_mem).
                    358:         */
                    359:        printf(version);
                    360: 
                    361:        if (dvmapage < btoc(dvmasize)) {
                    362:                printf("CAN'T HAVE PERIPHERALS IN RANGE 0 - %dKB\n",
                    363:                    ctob(dvmasize) / 1024);
                    364:                panic("dvma collision");
                    365:        }
                    366: 
                    367: #ifndef lint
                    368:        if ((int)start - (int)ctob(btoc(sizeof (struct msgbuf))) <= (int)&scb)
                    369:                panic("msgbuf too large");
                    370: 
                    371:        if (sizeof (struct user) > UPAGES * NBPG)
                    372:                panic("user area too large");
                    373: #endif lint
                    374: 
                    375:        if ((int)Syslimit > (CSEG << SGSHIFT))
                    376:                panic("system map tables too large");
                    377: 
                    378:         /*
                    379:         * Determine how many buffers to allocate.
                    380:         * Use 10% of memory (not counting 512K for kernel), with min of 16.
                    381:         * We allocate 1/4 as many swap buffer headers as file i/o buffers.
                    382:         */
                    383:        if (bufpages == 0)
                    384:                bufpages = (physmem * NBPG - 512 * 1024) / 10 / CLBYTES;
                    385:        if (nbuf == 0) {
                    386:                nbuf = bufpages;
                    387:                if (nbuf < 16)
                    388:                        nbuf = 16;
                    389:        }
                    390:        if (bufpages > nbuf * (BUFSIZE / CLBYTES))
                    391:                bufpages = nbuf * (BUFSIZE / CLBYTES);
                    392:        if (nswbuf == 0) {
                    393:                nswbuf = (nbuf / 4) &~ 1;       /* force even */
                    394:                if (nswbuf > 32)
                    395:                        nswbuf = 32;            /* sanity */
                    396:        }
                    397:        printf("real mem = %d nbuf = %d nswbuf = %d\n",
                    398:                ctob(physmem + mon_mem), nbuf, nswbuf);
                    399: 
                    400:        /*
                    401:         * Allocate space for system data structures.
                    402:         * The first available real memory address is in "firstaddr".
                    403:         * The first available kernel virtual address is in "v".
                    404:         * As pages of kernel virtual memory are allocated, "v" is incremented.
                    405:         * "mapaddr" is the real memory address where the tables start.
                    406:         * It is used when remapping the tables later.
                    407:         * In order to support the frame buffer which might appear in 
                    408:         * the middle of contiguous memory we adjust the map address to 
                    409:         * start after the end of the frame buffer.  Later we will adjust
                    410:         * the core map to take this hole into account.  The reason for
                    411:         * this is to keep all the kernel tables contiguous in virtual space.
                    412:         */
                    413:        if (fbobmemavail)
                    414:                mapaddr = btoc(OBFBADDR + FBSIZE);
                    415:        else
                    416:                mapaddr = firstaddr;
                    417:        v = (caddr_t)(ctob(firstaddr) + KERNELBASE);
                    418: #define        valloc(name, type, num) \
                    419:            (name) = (type *)(v); (v) = (caddr_t)((name)+(num))
                    420: #define        valloclim(name, type, num, lim) \
                    421:            (name) = (type *)(v); (v) = (caddr_t)((lim) = ((name)+(num)))
                    422:        valloc(swbuf, struct buf, nswbuf);
                    423:        valloclim(inode, struct inode, ninode, inodeNINODE);
                    424:        valloclim(file, struct file, nfile, fileNFILE);
                    425:        valloclim(proc, struct proc, nproc, procNPROC);
                    426:        valloclim(text, struct text, ntext, textNTEXT);
                    427:        valloclim(lnodes, struct kern_lnode, maxusers, lnodesMAXUSERS);
                    428:        valloc(callout, struct callout, ncallout);
                    429:        valloc(swapmap, struct map, nswapmap = nproc * 2);
                    430:        valloc(argmap, struct map, ARGMAPSIZE);
                    431:        valloc(kernelmap, struct map, nproc);
                    432:        valloc(iopbmap, struct map, IOPBMAPSIZE);
                    433:        valloc(mb_hd.mh_map, struct map, DVMAMAPSIZE);
                    434: 
                    435:        /*
                    436:         * Now allocate space for core map
                    437:         * Allow space for all of physical memory minus the amount 
                    438:         * dedicated to the system. The amount of physical memory
                    439:         * dedicated to the system is the total virtual memory of
                    440:         * the system minus the space in the buffers which is not
                    441:         * allocated real memory.
                    442:         */
                    443:        ncmap = physmem - firstaddr;
                    444:        valloclim(cmap, struct cmap, ncmap, ecmap);
                    445:        unixsize = btoc((int)(ecmap+1) - KERNELBASE);
                    446: 
                    447:        if ((int)unixsize > SYSPTSIZE)
                    448:                panic("sys pt too small");
                    449: 
                    450:        /*
                    451:         * Clear allocated space, and make r/w entries
                    452:         * for the space in the kernel map.
                    453:         */
                    454:        if (unixsize >= physmem - 8*UPAGES)
                    455:                panic("no memory");
                    456: 
                    457:        pte = &Sysmap[firstaddr];
                    458:        for (i = firstaddr + btop(KERNELBASE); i < btoc(v); i++) {
                    459:                mapin(pte++, i, mapaddr,  1, PG_V | PG_KW);
                    460:                clearseg(mapaddr++);
                    461:        }
                    462: 
                    463:        /*
                    464:         * Initialize callouts.
                    465:         */
                    466:        callfree = callout;
                    467:        for (i = 1; i < ncallout; i++)
                    468:                callout[i-1].c_next = &callout[i];
                    469: 
                    470:        /*
                    471:         * Initialize memory allocator and swap
                    472:         * and user page table maps.
                    473:         */
                    474:        if (fbobmemavail) {
                    475:                meminit((int)firstaddr, maxmem);
                    476:                memialloc((int)firstaddr, (int)btop(OBFBADDR));
                    477:                memialloc((int)(1 + mapaddr), maxmem);
                    478:        } else {
                    479:                meminit((int)mapaddr, maxmem);
                    480:                memialloc((int)mapaddr, maxmem);
                    481:        }
                    482:        maxmem = freemem;
                    483:        printf("avail mem = %d\n", ctob(maxmem));
                    484:        rminit(kernelmap, (long)(USRPTSIZE - CLSIZE), (long)CLSIZE,
                    485:            "usrpt", nproc);
                    486:        rminit(iopbmap, (long)ctob(IOPBMEM), (long)DVMA, 
                    487:            "IOPB space", IOPBMAPSIZE);
                    488:        rminit(mb_hd.mh_map, (long)(dvmasize - IOPBMEM), (long)IOPBMEM,
                    489:            "DVMA map space", DVMAMAPSIZE);
                    490: 
                    491:        /*
                    492:         * Configure the system.
                    493:         */
                    494:        bootflags();            /* get the boot options */
                    495:        configure();            /* set up devices */
                    496:        if (fbobmemavail) {
                    497:                /*
                    498:                 * Onboard frame buffer memory still
                    499:                 * available, put back onto the free list.
                    500:                 */
                    501:                memialloc((int)btop(OBFBADDR), (int)btop(OBFBADDR + FBSIZE));
                    502:                fbobmemavail = 0;
                    503:        }
                    504:        bufmemall();
                    505:        uinit();                /* initialize the u area */
                    506:        (void) spl0();          /* drop priority */
                    507: }
                    508: 
                    509: /*
                    510:  * set up a physical address
                    511:  * into users virtual address space.
                    512:  */
                    513: sysphys()
                    514: {
                    515: 
                    516:        if(!suser())
                    517:                return;
                    518:        u.u_error = EINVAL;
                    519: }
                    520: 
                    521: /*
                    522:  * This system call sets the time of year clock without touching
                    523:  * the software clock.  It returns the previous clock value.  If
                    524:  * the argument is zero or the caller is not the super-user, it
                    525:  * does not change the clock.
                    526:  * Since the clocks are the same on the SUN, it just calls stime.
                    527:  */
                    528: settod()
                    529: {
                    530:        register struct a {
                    531:                long unsigned tod;
                    532:        } *uap;
                    533: 
                    534:        u.u_r.r_time = time;
                    535:        if (uap->tod != 0 && suser())
                    536:                stime();
                    537: }
                    538: 
                    539: /*
                    540:  * Allocate physical memory for system buffers
                    541:  * In Ethernet memory if the right board exists &
                    542:  * the root device is ND & there are no block I/O DMA devices
                    543:  */
                    544: bufmemall()
                    545: {
                    546:        struct pte *pte;
                    547:        long a, va;
                    548:        int npages;
                    549:        int i, j, base, residual;
                    550: 
                    551:        a = rmalloc(kernelmap, (long)(nbuf*BUFSIZE/NBPG));
                    552:        if (a == 0)
                    553:                panic("no vmem for buffers");
                    554:        buffers = (caddr_t)kmxtob(a);
                    555:        pte = &Usrptmap[a];
                    556:        base = bufpages / nbuf;
                    557:        residual = bufpages % nbuf;
                    558:        for (i = 0; i < nbuf; i++) {
                    559:                if (i < residual)
                    560:                        npages = base+1;
                    561:                else
                    562:                        npages = base;
                    563:                /* XXX - this loop only works if CLSIZE == 1 */
                    564:                for (j = 0; j < npages; j += CLSIZE) {
                    565:                        if (memall(pte+j, CLSIZE, &proc[0], CSYS) == 0)
                    566:                                panic("no mem for buffers");
                    567:                        *(int *)(pte+j) |= PG_V|PG_KW;
                    568:                        va = (int)kmxtob(a+j);
                    569:                        vmaccess(pte+j, (caddr_t)va, 1);
                    570:                        bzero((caddr_t)va, CLBYTES);
                    571:                }
                    572:                pte += BUFSIZE/CLBYTES;
                    573:                a += BUFSIZE/CLBYTES;
                    574:        }
                    575:        /*
                    576:         * Double map and then unmap the last page of the last
                    577:         * buffer to insure the presence of a pmeg.
                    578:         * AARRRGGGHHH. Kludge away.
                    579:         */
                    580:        if (base < BUFSIZE/CLBYTES) {
                    581:                pte -= BUFSIZE/CLBYTES;
                    582:                va = (int)kmxtob(a-1);
                    583:                pte[BUFSIZE/CLBYTES - 1] = pte[0];
                    584:                vmaccess(&pte[BUFSIZE/CLBYTES - 1], (caddr_t)va, 1);
                    585:                /* now unmap without disturbing the pmeg */
                    586:                *(int *)&pte[BUFSIZE/CLBYTES - 1] = 0;
                    587:                setpgmap((caddr_t)va, (long)0);
                    588:        }
                    589:        buf = (struct buf *)zmemall(memall, nbuf * sizeof(struct buf));
                    590:        if (buf == 0)
                    591:                panic("no mem for buf headers");
                    592: }
                    593: 
                    594: struct bootf {
                    595:        char    let;
                    596:        short   bit;
                    597: } bootf[] = {
                    598:        'a',    RB_ASKNAME,
                    599:        's',    RB_SINGLE,
                    600:        'i',    RB_INITNAME,
                    601:        'h',    RB_HALT,
                    602:        0,      0,
                    603: };
                    604: char *initname = "/etc/init";
                    605: 
                    606: /*
                    607:  * Parse the boot line to determine boot flags .
                    608:  */
                    609: bootflags()
                    610: {
                    611:        register struct bootparam *bp = (*romp->v_bootparam);
                    612:        register char *cp;
                    613:        register int i;
                    614: 
                    615:        cp = bp->bp_argv[1];
                    616:        if (cp && *cp++ == '-')
                    617:                do {
                    618:                        for (i = 0; bootf[i].let; i++) {
                    619:                                if (*cp == bootf[i].let) {
                    620:                                        boothowto |= bootf[i].bit;
                    621:                                        break;
                    622:                                }
                    623:                        }
                    624:                        cp++;
                    625:                } while (bootf[i].let && *cp);
                    626:        if (boothowto & RB_INITNAME)
                    627:                initname = bp->bp_argv[2];
                    628:        if (boothowto & RB_HALT)
                    629:                halt("bootflags");
                    630: }
                    631: 
                    632: /*
                    633:  * Start the initial user process.
                    634:  * The program [initname] is invoked with one argument
                    635:  * containing the boot flags.
                    636:  */
                    637: icode()
                    638: {
                    639:        struct execa {
                    640:                char    *fname;
                    641:                char    **argp;
                    642:                char    **envp;
                    643:        } *ap;
                    644:        char *ucp, **uap, *arg0, *arg1;
                    645:        int i;
                    646: 
                    647:        u.u_error = 0;                          /* paranoid */
                    648:        /* Make a user stack (1 page) */
                    649:        expand(1, 1);
                    650:        (void) swpexpand(0, 1, &u.u_dmap, &u.u_smap);
                    651: 
                    652:        /* Move out the boot flag argument */
                    653:        ucp = (char *)USRSTACK;
                    654:        (void) subyte(--ucp, 0);                /* trailing zero */
                    655:        for (i = 0; bootf[i].let; i++) {
                    656:                if (boothowto & bootf[i].bit)
                    657:                        (void) subyte(--ucp, bootf[i].let);
                    658:        }
                    659:        (void) subyte(--ucp, '-');              /* leading hyphen */
                    660:        arg1 = ucp;
                    661: 
                    662:        /* Move out the file name (also arg 0) */
                    663:        for (i = 0; initname[i]; i++)
                    664:                ;                               /* size the name */
                    665:        for (; i >= 0; i--)
                    666:                (void) subyte(--ucp, initname[i]);
                    667:        arg0 = ucp;
                    668: 
                    669:        /* Move out the arg pointers */
                    670:        uap = (char **) ((int)ucp & ~(NBPW-1));
                    671:        (void) suword((caddr_t)--uap, 0);       /* terminator */
                    672:        (void) suword((caddr_t)--uap, (int)arg1);
                    673:        (void) suword((caddr_t)--uap, (int)arg0);
                    674: 
                    675:        /* Point at the arguments */
                    676:        u.u_ap = u.u_arg;
                    677:        ap = (struct execa *)u.u_ap;
                    678:        ap->fname = arg0;
                    679:        ap->argp = uap;
                    680:        ap->envp = 0;
                    681:        u.u_dirp = (caddr_t)u.u_arg[0];
                    682:        
                    683:        /* Now let exec do the hard work */
                    684:        exece();
                    685:        if (u.u_error) {
                    686:                printf("Can't invoke %s, error %d\n", initname, u.u_error);
                    687:                panic("icode");
                    688:        }
                    689: }
                    690: 
                    691: /*
                    692:  * Set up page tables for process 0 U pages.
                    693:  * This is closely related to way the code
                    694:  * in locore.s sets things up.
                    695:  */
                    696: uinit()
                    697: {
                    698:        register struct pte *pte;
                    699:        u_int page;
                    700:        register int i;
                    701:        extern char end[];
                    702: 
                    703:        /*
                    704:         * main() will initialize proc[0].p_p0br to u.u_pcb.pcb_p0br
                    705:         * and proc[0].p_szpt to 1.  All we have to do is set up
                    706:         * the pcb_p{0,1}{b,l}r registers in the pcb for now.
                    707:         */
                    708: 
                    709:        /* initialize base and length of P0 region */
                    710:        u.u_pcb.pcb_p0br = usrpt;
                    711:        u.u_pcb.pcb_p0lr = 0;           /* no user text/data (P0) for proc 0 */
                    712: 
                    713:        /*
                    714:         * initialize base and length of P1 region,
                    715:         * where the length here is for invalid pages
                    716:         */
                    717:        u.u_pcb.pcb_p1br = initp1br(usrpt + 1 * NPTEPG);
                    718:        u.u_pcb.pcb_p1lr = P1PAGES;     /* no user stack (P1) for proc 0 */
                    719: 
                    720:        /*
                    721:         * Doublely map the page containing the scb to contain the
                    722:         * ptes whose virtual address is usrpt.  Got that?
                    723:         */
                    724:        page = (u_int)(getpgmap((caddr_t)&scb) & PG_PFNUM);
                    725:        mapin(&Usrptmap[0], btop(usrpt), page, 1, PG_V | PG_KW); 
                    726: 
                    727:        /*
                    728:         * Now build the software page maps to map virtual U to physical U.
                    729:         * These pages have already been set up using the real pages beyond
                    730:         * end by locore.s.
                    731:         */
                    732:        pte = usrpt + 1 * NPTEPG - UPAGES;
                    733:        page = btop((int)end + (NBPG - 1) - KERNELBASE);
                    734:        for (i = 0; i < UPAGES; i++)
                    735:                *(int *)pte++ = PG_V | PG_KW | page++;
                    736: }
                    737: 
                    738: struct sigcontext {
                    739:        int     sc_sp;                  /* sp to restore */
                    740:        int     sc_pc;                  /* pc to retore */
                    741:        int     sc_ps;                  /* psl to restore */
                    742: };
                    743: /*
                    744:  * Send an interrupt to process.
                    745:  *
                    746:  * When using new signals user code must do a
                    747:  * sys #139 to return from the signal, which
                    748:  * calls sigcleanup below, which resets the
                    749:  * signal mask and the notion of onsigstack,
                    750:  * and returns from the signal handler.
                    751:  */
                    752: sendsig(p, sig)
                    753:        int (*p)(), sig;
                    754: {
                    755:        register int usp, *regs, scp;
                    756:        struct nframe {
                    757:                int     sig;
                    758:                int     code;
                    759:                int     scp;
                    760:        } frame;
                    761:        struct sigcontext sc;
                    762: 
                    763: #define        mask(s) (1<<((s)-1))
                    764:        regs = u.u_ar0;
                    765: 
                    766:        usp = regs[SP];
                    767:        usp -= sizeof (struct sigcontext);
                    768:        scp = usp;
                    769:        usp -= sizeof (frame);
                    770:        if (usp <= USRSTACK - ctob(u.u_ssize))
                    771:                (void) grow((unsigned)usp);
                    772:        if (useracc((caddr_t)usp, sizeof(frame) + sizeof(sc), B_WRITE) == 0) {
                    773:                /*
                    774:                 * Process has trashed its stack; give it an illegal
                    775:                 * instruction to halt it in its tracks.
                    776:                 */
                    777:                u.u_signal[SIGILL] = SIG_DFL;
                    778:                u.u_procp->p_siga0 &= ~(1<<(SIGILL-1));
                    779:                u.u_procp->p_siga1 &= ~(1<<(SIGILL-1));
                    780:                psignal(u.u_procp, SIGILL);
                    781:        }
                    782:        /*
                    783:         * push sigcontext structure.
                    784:         */
                    785:        sc.sc_sp = regs[SP];
                    786:        sc.sc_pc = regs[PC];
                    787:        sc.sc_ps = regs[PS];
                    788:        /*
                    789:         * If trace mode was on for the user process
                    790:         * when we came in here, it may have been because
                    791:         * of an ast-induced trace on a trap instruction,
                    792:         * in which case we do not want to restore the
                    793:         * trace bit in the status register later on
                    794:         * in sigcleanup().  If we were to restore it
                    795:         * and another ast trap had been posted, we would
                    796:         * end up marking the trace trap as a user-requested
                    797:         * real trace trap and send a bogus "Trace/BPT" signal.
                    798:         */
                    799:        if ((sc.sc_ps & PSL_T) && (u.u_pcb.pcb_p0lr & TRACE_AST))
                    800:                sc.sc_ps &= ~PSL_T;
                    801:        (void) copyout((caddr_t)&sc, (caddr_t)scp, sizeof (sc));
                    802:        /*
                    803:         * push call frame.
                    804:         */
                    805:        frame.sig = sig;
                    806:        if (sig == SIGILL || sig == SIGFPE || sig == SIGEMT) {
                    807:                frame.code = u.u_code;
                    808:                u.u_code = 0;
                    809:        } else
                    810:                frame.code = 0;
                    811:        frame.scp = scp;
                    812:        (void) copyout((caddr_t)&frame, (caddr_t)usp, sizeof (frame));
                    813:        regs[SP] = usp;
                    814:        regs[PC] = (int)p;
                    815: }
                    816: 
                    817: /*
                    818:  * Routine to cleanup state after a signal
                    819:  * has been taken.  Reset signal mask and
                    820:  * notion of on signal stack from context
                    821:  * left there by sendsig (above).  Pop these
                    822:  * values and perform rti.
                    823:  */
                    824: sigcleanup()
                    825: {
                    826:        struct sigcontext *scp, sc;
                    827: 
                    828:        scp = (struct sigcontext *)fuword((caddr_t)u.u_ar0[SP] + sizeof(int));
                    829:        if ((int)scp == -1)
                    830:                return;
                    831:        if (copyin((caddr_t)scp, (caddr_t)&sc, sizeof (sc)))
                    832:                return;
                    833:        u.u_ar0[SP] = sc.sc_sp;
                    834:        u.u_ar0[PC] = sc.sc_pc;
                    835:        u.u_ar0[PS] = sc.sc_ps;
                    836:        u.u_ar0[PS] &= ~PSL_USERCLR;
                    837:        u.u_ar0[PS] |= PSL_USERSET;
                    838:        u.u_eosys = REALLYRETURN;
                    839: }
                    840: #undef mask
                    841: 
                    842: int    waittime = -1;
                    843: 
                    844: boot(arghowto)
                    845:        int arghowto;
                    846: {
                    847:        register int howto;
                    848:        static int prevflag = 0;
                    849:        register struct buf *bp;
                    850:        int iter, nbusy;
                    851:        int s;
                    852: 
                    853:        consdev = 0;
                    854:        startnmi();
                    855:        howto = arghowto;
                    856:        if ((howto&RB_NOSYNC)==0 && waittime < 0 && bfreelist[0].b_forw) {
                    857:                waittime = 0;
                    858:                update();
                    859:                printf("syncing disks... ");
                    860:                while (++waittime <= 5)
                    861:                        sleep((caddr_t)&lbolt, PZERO);
                    862:                printf("done\n");
                    863:        }
                    864:        s = spl7();                             /* extreme priority */
                    865:        if (howto & RB_HALT) {
                    866:                halt((char *)NULL);
                    867:                /* MAYBE REACHED */
                    868:        } else {
                    869:                if ((howto & RB_PANIC) && prevflag == 0) {
                    870:                        prevflag = 1;
                    871:                        dumpsys();
                    872: 
                    873:                }
                    874:                printf("Rebooting Unix...\n");
                    875:                (*romp->v_boot_me)(howto & RB_SINGLE ? "-s" : "");
                    876:                /*NOTREACHED*/
                    877:        }
                    878:        (void) splx(s);
                    879: }
                    880: 
                    881: /*
                    882:  * Initialize UNIX's vector table:
                    883:  * Vectors are copied from protoscb unless
                    884:  * they are zero; zero means preserve whatever the
                    885:  * monitor put there.  If the protoscb is zero,
                    886:  * then the original contents are copied into
                    887:  * the scb we are setting up.
                    888:  */
                    889: initscb()
                    890: {
                    891:        register int *s, *p, *f;
                    892:        register int n;
                    893:        struct scb *orig, *getvbr();
                    894: 
                    895:        orig = getvbr();
                    896:        exit_vector = orig->scb_trap[14];
                    897:        s = (int *)&scb;
                    898:        p = (int *)&protoscb;
                    899:        f = (int *)orig;
                    900:        for (n = sizeof (struct scb)/sizeof (int); n--; s++, p++, f++) {
                    901:                if (*p) 
                    902:                        *s = *p;
                    903:                else
                    904:                        *s = *f;
                    905:        }
                    906:        setvbr(&scb);
                    907: }
                    908: 
                    909: /*
                    910:  * Clear a segment (page (click)).
                    911:  */
                    912: clearseg(pgno)
                    913:        u_int pgno;
                    914: {
                    915:        extern char CADDR1[];
                    916: 
                    917:        mapin(CMAP1, btop(CADDR1), pgno, 1, PG_V | PG_KW); 
                    918:        bzero(CADDR1, NBPG);
                    919: }
                    920: 
                    921: /*
                    922:  * Copy a segment (page) from a user virtual address
                    923:  * to a physical page number.
                    924:  */
                    925: copyseg(vaddr, pgno)
                    926:        caddr_t vaddr;
                    927:        int pgno;
                    928: {
                    929:        register struct pte *pte;
                    930:        register int lock;
                    931:        extern char CADDR1[];
                    932: 
                    933:        /*
                    934:         * Make sure the user's page is valid and locked.
                    935:         */
                    936:        pte = vtopte(u.u_procp, btop(vaddr));
                    937:        if (lock = !pte->pg_v) {
                    938:                pagein((u_int)vaddr, &u, 1);            /* return it locked */
                    939:                pte = vtopte(u.u_procp, btop(vaddr));   /* pte may move */
                    940:        }
                    941:        /*
                    942:         * Map the destination page into kernel address space.
                    943:         */
                    944:        mapin(CMAP1, btop(CADDR1), (u_int)pgno, 1, PG_V | PG_KW);
                    945:        (void) copyin(vaddr, CADDR1, CLBYTES);
                    946:        if (lock)
                    947:                munlock(pte->pg_pfnum);
                    948: }
                    949: 
                    950: /*
                    951:  * Handle "physical" block transfers.
                    952:  */
                    953: physstrat(bp, strat, pri)
                    954:        register struct buf *bp;
                    955:        int (*strat)();
                    956:        int pri;
                    957: {
                    958:        register int npte, n;
                    959:        register long a;
                    960:        unsigned v;
                    961:        register struct pte *pte, *kpte;
                    962:        struct proc *rp;
                    963:        int va, s, o;
                    964: 
                    965:        v = btop(bp->b_un.b_addr);
                    966:        o = (int)bp->b_un.b_addr & PGOFSET;
                    967:        npte = btoc(bp->b_bcount + o) + 1;
                    968:        while ((a = rmalloc(kernelmap, (long)npte)) == NULL) {
                    969:                kmapwnt++;
                    970:                sleep((caddr_t)kernelmap, PSWP+4);
                    971:        }
                    972:        kpte = &Usrptmap[a];
                    973:        rp = bp->b_flags&B_DIRTY ? &proc[2] : bp->b_proc;
                    974:        if ((bp->b_flags & B_PHYS) == 0)
                    975:                pte = &Sysmap[btop((int)bp->b_un.b_addr - KERNELBASE)];
                    976:        else if (bp->b_flags & B_UAREA)
                    977:                pte = &rp->p_addr[v];
                    978:        else if (bp->b_flags & B_PAGET)
                    979:                pte = &Usrptmap[btokmx((struct pte *)bp->b_un.b_addr)];
                    980:        else
                    981:                pte = vtopte(rp, v);
                    982:        for (n = npte; --n != 0; kpte++, pte++)
                    983:                *(int *)kpte = PG_V | PG_KW | (*(int *)pte & PG_PFNUM);
                    984:        *(int *)kpte = 0;
                    985:        va = (int)kmxtob(a);
                    986:        vmaccess(&Usrptmap[a], (caddr_t)va, npte);
                    987:        bp->b_saddr = bp->b_un.b_addr;
                    988:        bp->b_un.b_addr = (caddr_t)(va | o);
                    989:        bp->b_kmx = a;
                    990:        bp->b_npte = npte;
                    991:        (*strat)(bp);
                    992:        if (bp->b_flags & B_DIRTY)
                    993:                return;
                    994:        s = spl6();
                    995:        while ((bp->b_flags & B_DONE) == 0)
                    996:                sleep((caddr_t)bp, pri);
                    997:        (void) splx(s);
                    998:        bp->b_un.b_addr = bp->b_saddr;
                    999:        bp->b_kmx = 0;
                   1000:        bp->b_npte = 0;
                   1001:        mapout(&Usrptmap[a], npte);
                   1002:        rmfree(kernelmap, (long)npte, a);
                   1003: }
                   1004: 
                   1005: /*
                   1006:  * Halt the machine and return to the monitor
                   1007:  */
                   1008: halt(s)
                   1009:        char *s;
                   1010: {
                   1011:        extern struct scb *getvbr();
                   1012: 
                   1013:        if (s)
                   1014:                (*romp->v_printf)("(%s) ", s);
                   1015:        (*romp->v_printf)("Unix Halted\n\n");
                   1016:        startnmi();
                   1017:        if (exit_vector)
                   1018:                getvbr()->scb_trap[14] = exit_vector;
                   1019:        asm("trap #14");
                   1020:        if (exit_vector)
                   1021:                getvbr()->scb_trap[14] = protoscb.scb_trap[14];
                   1022:        stopnmi();
                   1023: }
                   1024: 
                   1025: /*
                   1026:  * Print out a traceback for the caller - can be called anywhere
                   1027:  * within the kernel or from the monitor by typing "g4" (for sun-2
                   1028:  * compatibility) or "w trace".  This causes the monitor to call
                   1029:  * the v_handler() routine which will call tracedump() for these cases.
                   1030:  */
                   1031: /*VARARGS0*/
                   1032: tracedump(x1)
                   1033:        caddr_t x1;
                   1034: {
                   1035:        struct frame *fp = (struct frame *)(&x1 - 2);
                   1036:        u_int tospage = btoc(fp);
                   1037: 
                   1038:        (*romp->v_printf)("Begin traceback...fp = %x\n", fp);
                   1039:        while (btoc(fp) == tospage) {
                   1040:                if (fp == fp->fr_savfp) {
                   1041:                        (*romp->v_printf)("FP loop at %x", fp);
                   1042:                        break;
                   1043:                }
                   1044:                (*romp->v_printf)("Called from %x, fp=%x, args=%x %x %x %x\n",
                   1045:                    fp->fr_savpc, fp->fr_savfp,
                   1046:                    fp->fr_arg[0], fp->fr_arg[1], fp->fr_arg[2], fp->fr_arg[3]);
                   1047:                fp = fp->fr_savfp;
                   1048:        }
                   1049:        (*romp->v_printf)("End traceback...\n");
                   1050: }
                   1051: 
                   1052: /*
                   1053:  * Buscheck is called by mbsetup to check to see it the requested
                   1054:  * setup is a valid busmem type (i.e. VMEbus).  Returns 1 if ok
                   1055:  * busmem type, returns 0 if not busmem type.  This routine
                   1056:  * make checks and panic's if an illegal busmem type request is detected.
                   1057:  */
                   1058: buscheck(pte, npf)
                   1059:        register struct pte *pte;
                   1060:        register int npf;
                   1061: {
                   1062:        register int i, pf;
                   1063:        register int pt = *(int *)pte & PGT_MASK;
                   1064: 
                   1065:        if (pt == PGT_VME_D16 || pt == PGT_VME_D32) {
                   1066:                pf = pte->pg_pfnum;
                   1067:                if (pf < btoc(DVMASIZE))
                   1068:                        panic("buscheck: busmem in DVMA range");
                   1069:                for (i = 0; i < npf; i++, pte++, pf++) {
                   1070:                        if ((*(int *)pte & PGT_MASK) != pt ||
                   1071:                            pte->pg_pfnum != pf)
                   1072:                                panic("buscheck: request not contiguous");
                   1073:                }
                   1074:                return (1);
                   1075:        }
                   1076:        return (0);
                   1077: }
                   1078: 
                   1079: /* 
                   1080:  * Compute the address of an I/O device within standard address
                   1081:  * ranges and return the result.  This is used by DKIOCINFO
                   1082:  * ioctl to get the best guess possible for the actual address
                   1083:  * set on the card.
                   1084:  */
                   1085: getdevaddr(addr)
                   1086:        caddr_t addr;
                   1087: {
                   1088:        int off = (int)addr & PGOFSET;
                   1089:        int pte = getkpgmap(addr);
                   1090:        int physaddr = ((pte & PG_PFNUM) & ~PGT_MASK) * NBPG;
                   1091: 
                   1092:        switch (pte & PGT_MASK) {
                   1093:        case PGT_VME_D16:
                   1094:        case PGT_VME_D32:
                   1095:                if (physaddr > VME16_BASE) {
                   1096:                        /* 16 bit VMEbus address */
                   1097:                        physaddr -= VME16_BASE;
                   1098:                } else if (physaddr > VME24_BASE) {
                   1099:                        /* 24 bit VMEbus address */
                   1100:                        physaddr -= VME24_BASE;
                   1101:                }
                   1102:                /*
                   1103:                 * else 32 bit VMEbus address,
                   1104:                 * physaddr doesn't require adjustments
                   1105:                 */
                   1106:                break;
                   1107: 
                   1108:        case PGT_OBMEM:
                   1109:        case PGT_OBIO:
                   1110:                /* physaddr doesn't require adjustments */
                   1111:                break;
                   1112:        }
                   1113: 
                   1114:        return (physaddr + off);
                   1115: }
                   1116: 
                   1117: static int (*mon_nmi)();               /* monitor's level 7 nmi routine */
                   1118: extern int level7();                   /* Unix's level 7 nmi routine */
                   1119: 
                   1120: stopnmi()
                   1121: {
                   1122:        struct scb *vbr, *getvbr();
                   1123: 
                   1124:        vbr = getvbr();
                   1125:        if (vbr->scb_autovec[7 - 1] != level7) {
                   1126: #ifndef GPROF
                   1127:                set_clk_mode(0, IR_ENA_CLK7);   /* disable level 7 clk intr */
                   1128: #endif !GPROF
                   1129:                mon_nmi = vbr->scb_autovec[7 - 1];      /* save mon vec */
                   1130:                vbr->scb_autovec[7 - 1] = level7;       /* install Unix vec */
                   1131:        }
                   1132: }
                   1133: 
                   1134: startnmi()
                   1135: {
                   1136:        struct scb *getvbr();
                   1137: 
                   1138:        if (mon_nmi) {
                   1139:                getvbr()->scb_autovec[7 - 1] = mon_nmi; /* install mon vec */
                   1140: #ifndef GPROF
                   1141:                set_clk_mode(IR_ENA_CLK7, 0);   /* enable level 7 clk intr */
                   1142: #endif !GPROF
                   1143:        }
                   1144: }
                   1145: 
                   1146: /*
                   1147:  * Handler for monitor vector cmd -
                   1148:  * For now we just implement the old "g0" and "g4"
                   1149:  * commands and a printf hack.
                   1150:  */
                   1151: void
                   1152: v_handler(addr, str)
                   1153:        int addr;
                   1154:        char *str;
                   1155: {
                   1156: 
                   1157:        switch (*str) {
                   1158:        case '\0':
                   1159:                /*
                   1160:                 * No (non-hex) letter was specified on
                   1161:                 * command line, use only the number given
                   1162:                 */
                   1163:                switch (addr) {
                   1164:                case 0:         /* old g0 */
                   1165:                case 0xd:       /* 'd'ump short hand */
                   1166:                        panic("zero");
                   1167:                        /*NOTREACHED*/
                   1168:                
                   1169:                case 4:         /* old g4 */
                   1170:                        tracedump();
                   1171:                        break;
                   1172: 
                   1173:                default:
                   1174:                        goto err;
                   1175:                }
                   1176:                break;
                   1177: 
                   1178:        case 'p':               /* 'p'rint string command */
                   1179:        case 'P':
                   1180:                (*romp->v_printf)("%s\n", (char *)addr);
                   1181:                break;
                   1182: 
                   1183:        case '%':               /* p'%'int anything a la printf */
                   1184:                (*romp->v_printf)(str, addr);
                   1185:                (*romp->v_printf)("\n");
                   1186:                break;
                   1187: 
                   1188:        case 't':               /* 't'race kernel stack */
                   1189:        case 'T':
                   1190:                tracedump();
                   1191:                break;
                   1192: 
                   1193:        case 'u':               /* d'u'mp hack ('d' look like hex) */
                   1194:        case 'U':
                   1195:                if (addr == 0xd) {
                   1196:                        panic("zero");
                   1197:                } else
                   1198:                        goto err;
                   1199:                break;
                   1200: 
                   1201:        default:
                   1202:        err:
                   1203:                (*romp->v_printf)("Don't understand 0x%x '%s'\n", addr, str);
                   1204:        }
                   1205: }
                   1206: 
                   1207: /*
                   1208:  * Handle parity/ECC memory errors.  XXX - use something like
                   1209:  * vax to only look for soft ecc errors periodically?
                   1210:  */
                   1211: memerr()
                   1212: {
                   1213:        u_char per, eer;
                   1214:        char *mess = 0;
                   1215:        int c;
                   1216:        long pme;
                   1217: 
                   1218:        eer = per = MEMREG->mr_er;
                   1219: #ifdef SUN3_260
                   1220:        if (cpu == CPU_SUN3_260 && (eer & EER_ERR) == EER_CE) {
                   1221:                softecc();
                   1222:                MEMREG->mr_dvma = 1;    /* clear latching */
                   1223:                return;
                   1224:        } 
                   1225: #endif SUN3_260
                   1226: 
                   1227:        /*
                   1228:         * Since we are going down in flames, disable further
                   1229:         * memory error interrupts to prevent confusion.
                   1230:         */
                   1231:        MEMREG->mr_er &= ~ER_INTENA;
                   1232: 
                   1233: #if defined(SUN3_160) || defined(SUN3_50)
                   1234:        if ((cpu == CPU_SUN3_160 || cpu == CPU_SUN3_50) &&
                   1235:            (per & PER_ERR) != 0) {
                   1236:                printf("Parity Error Register %b\n", per, PARERR_BITS);
                   1237:                mess = "parity error";
                   1238:        }
                   1239: #endif defined(SUN3_160) || defined(SUN3_50)
                   1240: 
                   1241: #ifdef SUN3_260
                   1242:        if ((cpu == CPU_SUN3_260) && (eer & EER_ERR) != 0) {
                   1243:                printf("ECC Error Register %b\n", eer, ECCERR_BITS);
                   1244:                mess = "uncorrectable ECC error";
                   1245:        }
                   1246: #endif SUN3_260
                   1247: 
                   1248:        if (!mess) {
                   1249:                printf("Memory Error Register %b %b\n",
                   1250:                    per, PARERR_BITS, eer, ECCERR_BITS);
                   1251:                mess = "unknown memory error";
                   1252:        }
                   1253: 
                   1254:        printf("DVMA = %x, context = %x, virtual address = %x\n",
                   1255:                MEMREG->mr_dvma, MEMREG->mr_ctx, MEMREG->mr_vaddr);
                   1256: 
                   1257:        c = getcontext();
                   1258:        setcontext((int)MEMREG->mr_ctx);
                   1259:        pme = getpgmap((caddr_t)MEMREG->mr_vaddr);
                   1260:        printf("pme = %x, physical address = %x\n", pme,
                   1261:            ptob(((struct pte *)&pme)->pg_pfnum) + (MEMREG->mr_vaddr&PGOFSET));
                   1262:        setcontext(c);
                   1263: 
                   1264:        /*
                   1265:         * Clear the latching by writing to the top
                   1266:         * nibble of the memory address register
                   1267:         */
                   1268:        MEMREG->mr_dvma = 1;
                   1269: 
                   1270:        panic(mess);
                   1271:        /*NOTREACHED*/
                   1272: }
                   1273: 
                   1274: #ifdef SUN3_260
                   1275: int prtsoftecc = 1;
                   1276: 
                   1277: /*
                   1278:  * Probe memory cards to find which one(s) had ecc error(s).
                   1279:  * If prtsoftecc is non-zero, log messages regarding the failing
                   1280:  * syndrome.  Then clear the latching on the memory card.
                   1281:  */
                   1282: softecc()
                   1283: {
                   1284:        register struct eccreg **ecc_nxt, *ecc;
                   1285: 
                   1286:        for (ecc_nxt = ecc_alive; *ecc_nxt != (struct eccreg *)0; ecc_nxt++) {
                   1287:                ecc = *ecc_nxt;
                   1288:                if (ecc->syndrome.sy_ce) {
                   1289:                        if (prtsoftecc) {
                   1290:                                printf("mem%d: soft ecc addr %x+%x=%x syn %b\n",
                   1291:                                    ecc - ECCREG,
                   1292:                                    (ecc->eccena.ena_addr << 22),
                   1293:                                    (ecc->syndrome.sy_addr << 3),
                   1294:                                    (ecc->eccena.ena_addr << 22) +
                   1295:                                      (ecc->syndrome.sy_addr << 3),
                   1296:                                    ecc->syndrome.sy_synd, SYNDERR_BITS);
                   1297:                        }
                   1298:                        ecc->syndrome.sy_ce = 1;        /* clear latching */
                   1299:                }
                   1300:        }
                   1301: }
                   1302: #endif SUN3_260

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.