[BACK]Return to machdep.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / arch / i386 / i386

Annotation of src/sys/arch/i386/i386/machdep.c, Revision 1.83

1.1       cgd         1: /*-
1.60      mycroft     2:  * Copyright (c) 1993 Charles Hannum.
1.35      cgd         3:  * Copyright (c) 1992 Terrence R. Lambert.
1.1       cgd         4:  * Copyright (c) 1982, 1987, 1990 The Regents of the University of California.
                      5:  * All rights reserved.
                      6:  *
                      7:  * This code is derived from software contributed to Berkeley by
                      8:  * William Jolitz.
                      9:  *
                     10:  * Redistribution and use in source and binary forms, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
                     18:  * 3. All advertising materials mentioning features or use of this software
                     19:  *    must display the following acknowledgement:
                     20:  *     This product includes software developed by the University of
                     21:  *     California, Berkeley and its contributors.
                     22:  * 4. Neither the name of the University nor the names of its contributors
                     23:  *    may be used to endorse or promote products derived from this software
                     24:  *    without specific prior written permission.
                     25:  *
                     26:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     27:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     28:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     29:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     30:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     31:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     32:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     33:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     34:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     35:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     36:  * SUCH DAMAGE.
                     37:  *
1.13      cgd        38:  *     from: @(#)machdep.c     7.4 (Berkeley) 6/3/91
1.83    ! mycroft    39:  *     $Id: machdep.c,v 1.82 1994/01/20 21:22:06 ws Exp $
1.1       cgd        40:  */
                     41:
1.27      cgd        42: #include <stddef.h>
1.59      mycroft    43: #include <sys/param.h>
                     44: #include <sys/systm.h>
                     45: #include <sys/signalvar.h>
                     46: #include <sys/kernel.h>
                     47: #include <sys/map.h>
                     48: #include <sys/proc.h>
                     49: #include <sys/user.h>
                     50: #include <sys/exec.h>
1.69      cgd        51: #include <sys/exec_aout.h>
1.59      mycroft    52: #include <sys/buf.h>
                     53: #include <sys/reboot.h>
                     54: #include <sys/conf.h>
                     55: #include <sys/file.h>
                     56: #include <sys/callout.h>
                     57: #include <sys/malloc.h>
                     58: #include <sys/mbuf.h>
                     59: #include <sys/msgbuf.h>
                     60: #include <sys/mount.h>
                     61: #include <sys/vnode.h>
1.57      cgd        62: #ifdef SYSVMSG
1.59      mycroft    63: #include <sys/msg.h>
1.57      cgd        64: #endif
                     65: #ifdef SYSVSEM
1.59      mycroft    66: #include <sys/sem.h>
                     67: #endif
                     68: #ifdef SYSVSHM
                     69: #include <sys/shm.h>
1.57      cgd        70: #endif
                     71:
1.59      mycroft    72: #include <vm/vm.h>
                     73: #include <vm/vm_kern.h>
                     74: #include <vm/vm_page.h>
1.31      cgd        75:
1.59      mycroft    76: #include <machine/cpu.h>
                     77: #include <machine/cpufunc.h>
                     78: #include <machine/psl.h>
                     79: #include <machine/reg.h>
                     80: #include <machine/specialreg.h>
1.43      brezak     81:
1.59      mycroft    82: #include <i386/isa/isa.h>
                     83: #include <i386/isa/rtc.h>
1.43      brezak     84:
1.59      mycroft    85: #include "isa.h"
                     86: #include "npx.h"
1.2       cgd        87:
1.1       cgd        88: /*
                     89:  * Declare these as initialized data so we can patch them.
                     90:  */
                     91: int    nswbuf = 0;
                     92: #ifdef NBUF
                     93: int    nbuf = NBUF;
                     94: #else
                     95: int    nbuf = 0;
                     96: #endif
                     97: #ifdef BUFPAGES
                     98: int    bufpages = BUFPAGES;
                     99: #else
                    100: int    bufpages = 0;
                    101: #endif
                    102:
1.59      mycroft   103: int    physmem;
                    104: int    boothowto;
                    105: int    cpu_class;
                    106:
                    107: struct msgbuf *msgbufp;
                    108: int    msgbufmapped;
                    109:
                    110: vm_map_t buffer_map;
1.48      brezak    111:
1.59      mycroft   112: extern vm_offset_t avail_start, avail_end;
                    113: static vm_offset_t hole_start, hole_end;
                    114: static vm_offset_t avail_next;
                    115: static vm_size_t avail_remaining;
1.1       cgd       116:
1.59      mycroft   117: int    _udatasel, _ucodesel, _gsel_tss;
1.14      cgd       118:
1.59      mycroft   119: long dumplo;
1.24      cgd       120:
1.32      andrew    121: void dumpsys __P((void));
                    122:
1.59      mycroft   123: caddr_t allocsys();
                    124:
                    125: /*
                    126:  * Machine-dependent startup code
                    127:  */
1.32      andrew    128: void
1.1       cgd       129: cpu_startup()
                    130: {
1.59      mycroft   131:        unsigned i;
                    132:        caddr_t v;
                    133:        int sz;
                    134:        int base, residual;
1.1       cgd       135:        vm_offset_t minaddr, maxaddr;
                    136:        vm_size_t size;
                    137:
                    138:        /*
                    139:         * Initialize error message buffer (at end of core).
                    140:         */
                    141:        /* avail_end was pre-decremented in pmap_bootstrap to compensate */
1.59      mycroft   142:        for (i = 0; i < btoc(sizeof(struct msgbuf)); i++)
1.43      brezak    143:                pmap_enter(pmap_kernel(), (caddr_t)msgbufp + i * NBPG,
                    144:                           avail_end + i * NBPG, VM_PROT_ALL, TRUE);
1.1       cgd       145:        msgbufmapped = 1;
                    146:
1.6       cgd       147:        printf(version);
1.16      cgd       148:        identifycpu();
1.6       cgd       149:        printf("real mem  = %d\n", ctob(physmem));
1.1       cgd       150:
                    151:        /*
1.59      mycroft   152:         * Find out how much space we need, allocate it,
                    153:         * and then give everything true virtual addresses.
1.1       cgd       154:         */
1.59      mycroft   155:        sz = (int)allocsys((caddr_t)0);
                    156:        if ((v = (caddr_t)kmem_alloc(kernel_map, round_page(sz))) == 0)
                    157:                panic("startup: no room for tables");
                    158:        if (allocsys(v) - v != sz)
1.1       cgd       159:                panic("startup: table size inconsistency");
1.50      cgd       160:
1.36      cgd       161:        /*
                    162:         * Now allocate buffers proper.  They are different than the above
                    163:         * in that they usually occupy more virtual memory than physical.
                    164:         */
                    165:        size = MAXBSIZE * nbuf;
1.68      mycroft   166:        buffer_map = kmem_suballoc(kernel_map, (vm_offset_t *)&buffers,
1.36      cgd       167:                                   &maxaddr, size, FALSE);
                    168:        minaddr = (vm_offset_t)buffers;
                    169:        if (vm_map_find(buffer_map, vm_object_allocate(size), (vm_offset_t)0,
                    170:                        &minaddr, size, FALSE) != KERN_SUCCESS)
                    171:                panic("startup: cannot allocate buffers");
1.54      cgd       172:        if ((bufpages / nbuf) >= btoc(MAXBSIZE)) {
                    173:                /* don't want to alloc more physical mem than needed */
                    174:                bufpages = btoc(MAXBSIZE) * nbuf;
                    175:        }
1.36      cgd       176:        base = bufpages / nbuf;
                    177:        residual = bufpages % nbuf;
                    178:        for (i = 0; i < nbuf; i++) {
                    179:                vm_size_t curbufsize;
                    180:                vm_offset_t curbuf;
                    181:
                    182:                /*
                    183:                 * First <residual> buffers get (base+1) physical pages
                    184:                 * allocated for them.  The rest get (base) physical pages.
                    185:                 *
                    186:                 * The rest of each buffer occupies virtual space,
                    187:                 * but has no physical memory allocated for it.
                    188:                 */
                    189:                curbuf = (vm_offset_t)buffers + i * MAXBSIZE;
                    190:                curbufsize = CLBYTES * (i < residual ? base+1 : base);
                    191:                vm_map_pageable(buffer_map, curbuf, curbuf+curbufsize, FALSE);
                    192:                vm_map_simplify(buffer_map, curbuf);
                    193:        }
1.41      cgd       194:
1.1       cgd       195:        /*
1.36      cgd       196:         * Allocate a submap for exec arguments.  This map effectively
                    197:         * limits the number of processes exec'ing at any time.
1.1       cgd       198:         */
1.59      mycroft   199:        exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
1.79      mycroft   200:                                 16*NCARGS, TRUE);
1.59      mycroft   201:
1.1       cgd       202:        /*
                    203:         * Allocate a submap for physio
                    204:         */
                    205:        phys_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
                    206:                                 VM_PHYS_SIZE, TRUE);
                    207:
                    208:        /*
                    209:         * Finally, allocate mbuf pool.  Since mclrefcnt is an off-size
                    210:         * we use the more space efficient malloc in place of kmem_alloc.
                    211:         */
                    212:        mclrefcnt = (char *)malloc(NMBCLUSTERS+CLBYTES/MCLBYTES,
                    213:                                   M_MBUF, M_NOWAIT);
                    214:        bzero(mclrefcnt, NMBCLUSTERS+CLBYTES/MCLBYTES);
1.68      mycroft   215:        mb_map = kmem_suballoc(kernel_map, (vm_offset_t *)&mbutl, &maxaddr,
1.73      mycroft   216:            VM_MBUF_SIZE, FALSE);
1.59      mycroft   217:
1.1       cgd       218:        /*
                    219:         * Initialize callouts
                    220:         */
                    221:        callfree = callout;
                    222:        for (i = 1; i < ncallout; i++)
                    223:                callout[i-1].c_next = &callout[i];
                    224:
1.6       cgd       225:        printf("avail mem = %d\n", ptoa(vm_page_free_count));
1.36      cgd       226:        printf("using %d buffers containing %d bytes of memory\n",
                    227:                nbuf, bufpages * CLBYTES);
1.1       cgd       228:
                    229:        /*
                    230:         * Set up buffers, so they can be used to read disk labels.
                    231:         */
                    232:        bufinit();
                    233:
                    234:        /*
                    235:         * Configure the system.
                    236:         */
                    237:        configure();
1.16      cgd       238: }
                    239:
1.59      mycroft   240: /*
                    241:  * Allocate space for system data structures.  We are given
                    242:  * a starting virtual address and we return a final virtual
                    243:  * address; along the way we set each data structure pointer.
                    244:  *
                    245:  * We call allocsys() with 0 to find out how much space we want,
                    246:  * allocate that much and fill it with zeroes, and then call
                    247:  * allocsys() again with the correct base virtual address.
                    248:  */
                    249: caddr_t
                    250: allocsys(v)
                    251:        register caddr_t v;
                    252: {
                    253:
                    254: #define        valloc(name, type, num) \
                    255:            v = (caddr_t)(((name) = (type *)v) + (num))
                    256: #ifdef REAL_CLISTS
                    257:        valloc(cfree, struct cblock, nclist);
                    258: #endif
                    259:        valloc(callout, struct callout, ncallout);
                    260:        valloc(swapmap, struct map, nswapmap = maxproc * 2);
                    261: #ifdef SYSVSHM
                    262:        valloc(shmsegs, struct shmid_ds, shminfo.shmmni);
                    263: #endif
                    264: #ifdef SYSVSEM
                    265:        valloc(sema, struct semid_ds, seminfo.semmni);
                    266:        valloc(sem, struct sem, seminfo.semmns);
                    267:        /* This is pretty disgusting! */
                    268:        valloc(semu, int, (seminfo.semmnu * seminfo.semusz) / sizeof(int));
                    269: #endif
                    270: #ifdef SYSVMSG
                    271:        valloc(msgpool, char, msginfo.msgmax);
                    272:        valloc(msgmaps, struct msgmap, msginfo.msgseg);
                    273:        valloc(msghdrs, struct msg, msginfo.msgtql);
                    274:        valloc(msqids, struct msqid_ds, msginfo.msgmni);
                    275: #endif
                    276:
                    277:        /*
1.77      mycroft   278:         * Determine how many buffers to allocate.  We use 10% of the
                    279:         * first 2MB of memory, and 5% of the rest, with a minimum of 16
                    280:         * buffers.  We allocate 1/2 as many swap buffer headers as file
                    281:         * i/o buffers.
1.59      mycroft   282:         */
                    283:        if (bufpages == 0)
1.77      mycroft   284:                if (physmem < btoc(2 * 1024 * 1024))
                    285:                        bufpages = physmem / (10 * CLSIZE);
                    286:                else
                    287:                        bufpages = (btoc(2 * 1024 * 1024) + physmem) /
                    288:                            (20 * CLSIZE);
1.59      mycroft   289:        if (nbuf == 0) {
                    290:                nbuf = bufpages;
                    291:                if (nbuf < 16)
                    292:                        nbuf = 16;
                    293:        }
                    294:        if (nswbuf == 0) {
                    295:                nswbuf = (nbuf / 2) &~ 1;       /* force even */
                    296:                if (nswbuf > 256)
                    297:                        nswbuf = 256;           /* sanity */
                    298:        }
                    299:        valloc(swbuf, struct buf, nswbuf);
                    300:        valloc(buf, struct buf, nbuf);
                    301:        return v;
                    302: }
1.18      cgd       303:
                    304: struct cpu_nameclass i386_cpus[] = {
1.59      mycroft   305:        { "i386SX",     CPUCLASS_386 }, /* CPU_386SX */
                    306:        { "i386DX",     CPUCLASS_386 }, /* CPU_386   */
                    307:        { "i486SX",     CPUCLASS_486 }, /* CPU_486SX */
                    308:        { "i486DX",     CPUCLASS_486 }, /* CPU_486   */
                    309:        { "Pentium",    CPUCLASS_586 }, /* CPU_586   */
1.18      cgd       310: };
                    311:
1.59      mycroft   312: identifycpu()
1.16      cgd       313: {
1.17      cgd       314:        printf("CPU: ");
1.59      mycroft   315: #ifdef DIAGNOSTIC
                    316:        if (cpu < 0 || cpu >= (sizeof i386_cpus/sizeof(struct cpu_nameclass)))
1.63      cgd       317: #ifdef notyet /* XXX */
1.59      mycroft   318:                panic("unknown cpu type %d\n", cpu);
1.63      cgd       319: #else
                    320:                panic("unknown cpu type\n");
                    321: #endif
1.59      mycroft   322: #endif
                    323:        printf("%s", i386_cpus[cpu].cpu_name);
                    324:        cpu_class = i386_cpus[cpu].cpu_class;
1.18      cgd       325:        printf(" (");
1.24      cgd       326:        switch(cpu_class) {
1.18      cgd       327:        case CPUCLASS_386:
                    328:                printf("386");
1.17      cgd       329:                break;
1.18      cgd       330:        case CPUCLASS_486:
                    331:                printf("486");
1.17      cgd       332:                break;
1.18      cgd       333:        case CPUCLASS_586:
                    334:                printf("586");
1.17      cgd       335:                break;
                    336:        default:
1.18      cgd       337:                printf("unknown");      /* will panic below... */
1.16      cgd       338:        }
1.18      cgd       339:        printf("-class CPU)");
1.17      cgd       340:        printf("\n");   /* cpu speed would be nice, but how? */
1.18      cgd       341:
1.16      cgd       342:        /*
                    343:         * Now that we have told the user what they have,
                    344:         * let them know if that machine type isn't configured.
                    345:         */
1.24      cgd       346:        switch (cpu_class) {
1.16      cgd       347: #if !defined(I386_CPU)
1.18      cgd       348:        case CPUCLASS_386:
1.16      cgd       349: #endif
                    350: #if !defined(I486_CPU)
1.18      cgd       351:        case CPUCLASS_486:
1.16      cgd       352: #endif
                    353: #if !defined(I586_CPU)
1.18      cgd       354:        case CPUCLASS_586:
1.16      cgd       355: #endif
1.59      mycroft   356: #if !defined(I386_CPU) && !defined(I486_CPU) && !defined(I586_CPU)
                    357: #error No CPU classes configured.
                    358: #endif
1.18      cgd       359:                panic("CPU class not configured");
1.16      cgd       360:        default:
                    361:                break;
                    362:        }
1.1       cgd       363: }
                    364:
                    365: #ifdef PGINPROF
                    366: /*
1.59      mycroft   367:  * Return the difference (in microseconds) between the current time and a
                    368:  * previous time as represented by the arguments.  If there is a pending
                    369:  * clock interrupt which has not been serviced due to high ipl, return error
                    370:  * code.
1.1       cgd       371:  */
                    372: /*ARGSUSED*/
                    373: vmtime(otime, olbolt, oicr)
                    374:        register int otime, olbolt, oicr;
                    375: {
                    376:
1.59      mycroft   377:        return (((time.tv_sec-otime)*HZ + lbolt-olbolt)*(1000000/HZ));
1.1       cgd       378: }
                    379: #endif
                    380:
                    381: /*
                    382:  * Send an interrupt to process.
                    383:  *
                    384:  * Stack is set up to allow sigcode stored
                    385:  * in u. to call routine, followed by kcall
                    386:  * to sigreturn routine below.  After sigreturn
                    387:  * resets the signal mask, the stack, and the
                    388:  * frame pointer, it returns to the user
                    389:  * specified pc, psl.
                    390:  */
                    391: void
                    392: sendsig(catcher, sig, mask, code)
                    393:        sig_t catcher;
                    394:        int sig, mask;
                    395:        unsigned code;
                    396: {
                    397:        register struct proc *p = curproc;
1.59      mycroft   398:        register struct trapframe *tf;
1.82      ws        399:        struct sigframe *fp, frame;
1.1       cgd       400:        struct sigacts *ps = p->p_sigacts;
1.48      brezak    401:        int oonstack;
1.22      cgd       402:        extern char sigcode[], esigcode[];
1.1       cgd       403:
1.59      mycroft   404:        tf = (struct trapframe *)p->p_regs;
                    405:        oonstack = ps->ps_onstack;
1.1       cgd       406:        /*
1.82      ws        407:         * Allocate space for the signal handler context.
1.1       cgd       408:         */
1.59      mycroft   409:        if (!ps->ps_onstack && (ps->ps_sigonstack & sigmask(sig))) {
1.1       cgd       410:                fp = (struct sigframe *)(ps->ps_sigsp
                    411:                                - sizeof(struct sigframe));
1.59      mycroft   412:                ps->ps_onstack = 1;
1.1       cgd       413:        } else {
1.59      mycroft   414:                fp = (struct sigframe *)(tf->tf_esp - sizeof(struct sigframe));
1.1       cgd       415:        }
                    416:
1.82      ws        417:        /*
                    418:         * Build the argument list for the signal handler.
                    419:         */
                    420:        frame.sf_signum = sig;
                    421:        frame.sf_code = code;
                    422:        frame.sf_scp = &fp->sf_sc;
                    423:        frame.sf_handler = catcher;
                    424:
                    425:        /*
                    426:         * Build the signal context to be used by sigreturn.
                    427:         */
                    428:        frame.sf_sc.sc_onstack = oonstack;
                    429:        frame.sf_sc.sc_mask = mask;
                    430:        frame.sf_sc.sc_ebp = tf->tf_ebp;
                    431:        frame.sf_sc.sc_esp = tf->tf_esp;
                    432:        frame.sf_sc.sc_eip = tf->tf_eip;
                    433:        frame.sf_sc.sc_efl = tf->tf_eflags;
                    434:        frame.sf_sc.sc_eax = tf->tf_eax;
                    435:        frame.sf_sc.sc_ebx = tf->tf_ebx;
                    436:        frame.sf_sc.sc_ecx = tf->tf_ecx;
                    437:        frame.sf_sc.sc_edx = tf->tf_edx;
                    438:        frame.sf_sc.sc_esi = tf->tf_esi;
                    439:        frame.sf_sc.sc_edi = tf->tf_edi;
                    440:        frame.sf_sc.sc_cs = tf->tf_cs;
                    441:        frame.sf_sc.sc_ds = tf->tf_ds;
                    442:        frame.sf_sc.sc_es = tf->tf_es;
                    443:        frame.sf_sc.sc_ss = tf->tf_ss;
1.1       cgd       444:
1.83    ! mycroft   445:        if (copyout(&frame, fp, sizeof(frame)) < 0) {
1.1       cgd       446:                /*
                    447:                 * Process has trashed its stack; give it an illegal
                    448:                 * instruction to halt it in its tracks.
                    449:                 */
                    450:                SIGACTION(p, SIGILL) = SIG_DFL;
                    451:                sig = sigmask(SIGILL);
                    452:                p->p_sigignore &= ~sig;
                    453:                p->p_sigcatch &= ~sig;
                    454:                p->p_sigmask &= ~sig;
                    455:                psignal(p, SIGILL);
                    456:                return;
                    457:        }
                    458:
1.73      mycroft   459:        /*
1.59      mycroft   460:         * Build context to run handler in.
                    461:         */
                    462:        tf->tf_esp = (int)fp;
                    463:        tf->tf_eip = (int)(((char *)PS_STRINGS) - (esigcode - sigcode));
                    464:        tf->tf_eflags &= ~PSL_VM;
                    465:        tf->tf_cs = _ucodesel;
                    466:        tf->tf_ds = _udatasel;
                    467:        tf->tf_es = _udatasel;
                    468:        tf->tf_ss = _udatasel;
1.1       cgd       469: }
                    470:
                    471: /*
                    472:  * System call to cleanup state after a signal
                    473:  * has been taken.  Reset signal mask and
                    474:  * stack state from context left by sendsig (above).
                    475:  * Return to previous pc and psl as specified by
                    476:  * context left by sendsig. Check carefully to
                    477:  * make sure that the user has not modified the
                    478:  * psl to gain improper priviledges or to cause
                    479:  * a machine fault.
                    480:  */
1.39      mycroft   481: struct sigreturn_args {
                    482:        struct sigcontext *sigcntxp;
                    483: };
                    484:
1.1       cgd       485: sigreturn(p, uap, retval)
                    486:        struct proc *p;
1.39      mycroft   487:        struct sigreturn_args *uap;
1.1       cgd       488:        int *retval;
                    489: {
1.82      ws        490:        struct sigcontext *scp, context;
1.1       cgd       491:        register struct sigframe *fp;
1.59      mycroft   492:        register struct trapframe *tf;
1.72      mycroft   493:        int eflags;
1.59      mycroft   494:
                    495:        tf = (struct trapframe *)p->p_regs;
1.1       cgd       496:
1.27      cgd       497:        /*
1.59      mycroft   498:         * The trampoline code hands us the context.
                    499:         * It is unsafe to keep track of it ourselves, in the event that a
                    500:         * program jumps out of a signal handler.
1.27      cgd       501:         */
                    502:        scp = uap->sigcntxp;
                    503:        fp = (struct sigframe *)
1.73      mycroft   504:            ((caddr_t)scp - offsetof(struct sigframe, sf_sc));
1.1       cgd       505:
1.59      mycroft   506:        if (useracc((caddr_t)fp, sizeof(*fp), 0) == 0)
1.72      mycroft   507:                return(EFAULT);
1.59      mycroft   508:
1.82      ws        509:        if (copyin((caddr_t)scp, &context, sizeof(*scp)) < 0)
1.72      mycroft   510:                return(EFAULT);
1.1       cgd       511:
1.82      ws        512:        eflags = context.sc_efl;
1.72      mycroft   513:        if ((eflags & PSL_USERCLR) != 0 ||
                    514:            (eflags & PSL_USERSET) != PSL_USERSET ||
                    515:            (eflags & PSL_IOPL) > (tf->tf_eflags & PSL_IOPL))
1.1       cgd       516:                return(EINVAL);
1.59      mycroft   517:
1.74      brezak    518:        /*
                    519:         * Sanity check the user's selectors and error if they
                    520:         * are suspect.
                    521:         */
                    522: #define max_ldt_sel(pcb) \
1.75      mycroft   523:        ((pcb)->pcb_ldt ? (pcb)->pcb_ldt_len : (sizeof(ldt) / sizeof(ldt[0])))
                    524:
                    525: #define valid_ldt_sel(sel) \
                    526:        (ISLDT(sel) && ISPL(sel) == SEL_UPL && \
                    527:         IDXSEL(sel) < max_ldt_sel(&p->p_addr->u_pcb))
                    528:
                    529: #define null_sel(sel) \
                    530:        (!ISLDT(sel) && IDXSEL(sel) == 0)
                    531:
1.82      ws        532:        if ((context.sc_cs&0xffff != _ucodesel && !valid_ldt_sel(context.sc_cs)) ||
                    533:            (context.sc_ss&0xffff != _udatasel && !valid_ldt_sel(context.sc_ss)) ||
                    534:            (context.sc_ds&0xffff != _udatasel && !valid_ldt_sel(context.sc_ds) &&
                    535:             !null_sel(context.sc_ds)) ||
                    536:            (context.sc_es&0xffff != _udatasel && !valid_ldt_sel(context.sc_es) &&
                    537:             !null_sel(context.sc_es))) {
1.75      mycroft   538:                trapsignal(p, SIGBUS, T_PROTFLT);
                    539:                return(EINVAL);
1.74      brezak    540:        }
1.75      mycroft   541:
                    542: #undef max_ldt_sel
                    543: #undef valid_ldt_sel
                    544: #undef null_sel
1.59      mycroft   545:
1.82      ws        546:        p->p_sigacts->ps_onstack = context.sc_onstack & 01;
                    547:        p->p_sigmask = context.sc_mask &~
1.1       cgd       548:            (sigmask(SIGKILL)|sigmask(SIGCONT)|sigmask(SIGSTOP));
1.49      brezak    549:
1.59      mycroft   550:        /*
                    551:         * Restore signal context.
                    552:         */
1.82      ws        553:        tf->tf_ebp = context.sc_ebp;
                    554:        tf->tf_esp = context.sc_esp;
                    555:        tf->tf_eip = context.sc_eip;
1.72      mycroft   556:        tf->tf_eflags = eflags;
1.82      ws        557:        tf->tf_eax = context.sc_eax;
                    558:        tf->tf_ebx = context.sc_ebx;
                    559:        tf->tf_ecx = context.sc_ecx;
                    560:        tf->tf_edx = context.sc_edx;
                    561:        tf->tf_esi = context.sc_esi;
                    562:        tf->tf_edi = context.sc_edi;
                    563:        tf->tf_cs = context.sc_cs;
                    564:        tf->tf_ds = context.sc_ds;
                    565:        tf->tf_es = context.sc_es;
                    566:        tf->tf_ss = context.sc_ss;
1.72      mycroft   567:
1.1       cgd       568:        return(EJUSTRETURN);
1.37      cgd       569: }
                    570:
1.1       cgd       571: int    waittime = -1;
                    572: struct pcb dumppcb;
                    573:
1.32      andrew    574: void
1.1       cgd       575: boot(arghowto)
                    576:        int arghowto;
                    577: {
                    578:        register long dummy;            /* r12 is reserved */
                    579:        register int howto;             /* r11 == how to boot */
                    580:        register int devtype;           /* r10 == major of root dev */
                    581:        extern int cold;
                    582:
                    583:        if(cold) {
                    584:                printf("hit reset please");
                    585:                for(;;);
                    586:        }
                    587:        howto = arghowto;
                    588:        if ((howto&RB_NOSYNC) == 0 && waittime < 0 && bfreelist[0].b_forw) {
                    589:                register struct buf *bp;
                    590:                int iter, nbusy;
                    591:
                    592:                waittime = 0;
                    593:                (void) splnet();
1.25      cgd       594:                printf("syncing disks... ");
1.1       cgd       595:                /*
                    596:                 * Release inodes held by texts before update.
                    597:                 */
                    598:                if (panicstr == 0)
                    599:                        vnode_pager_umount(NULL);
1.83    ! mycroft   600:                sync((struct proc *)0, (void *)0, (int *)0);
1.43      brezak    601:                /*
                    602:                 * Unmount filesystems
                    603:                 */
                    604: #if 0
                    605:                if (panicstr == 0)
                    606:                        vfs_unmountall();
                    607: #endif
1.1       cgd       608:                for (iter = 0; iter < 20; iter++) {
                    609:                        nbusy = 0;
                    610:                        for (bp = &buf[nbuf]; --bp >= buf; )
                    611:                                if ((bp->b_flags & (B_BUSY|B_INVAL)) == B_BUSY)
                    612:                                        nbusy++;
                    613:                        if (nbusy == 0)
                    614:                                break;
1.25      cgd       615:                        printf("%d ", nbusy);
1.1       cgd       616:                        DELAY(40000 * iter);
                    617:                }
                    618:                if (nbusy)
1.25      cgd       619:                        printf("giving up\n");
1.26      cgd       620:                else
1.25      cgd       621:                        printf("done\n");
1.59      mycroft   622:                /*
                    623:                 * If we've been adjusting the clock, the todr
                    624:                 * will be out of synch; adjust it now.
                    625:                 */
                    626:                resettodr();
1.55      brezak    627:
1.1       cgd       628:                DELAY(10000);                   /* wait for printf to finish */
                    629:        }
                    630:        splhigh();
                    631:        devtype = major(rootdev);
                    632:        if (howto&RB_HALT) {
1.25      cgd       633:                printf("\n");
                    634:                printf("The operating system has halted.\n");
                    635:                printf("Please press any key to reboot.\n\n");
1.12      cgd       636:                cngetc();
1.1       cgd       637:        } else {
                    638:                if (howto & RB_DUMP) {
                    639:                        savectx(&dumppcb, 0);
                    640:                        dumppcb.pcb_ptd = rcr3();
1.73      mycroft   641:                        dumpsys();
1.1       cgd       642:                        /*NOTREACHED*/
                    643:                }
                    644:        }
                    645: #ifdef lint
                    646:        dummy = 0; dummy = dummy;
                    647:        printf("howto %d, devtype %d\n", arghowto, devtype);
                    648: #endif
                    649:        cpu_reset();
                    650:        for(;;) ;
                    651:        /*NOTREACHED*/
                    652: }
                    653:
1.32      andrew    654: unsigned       dumpmag = 0x8fca0101;   /* magic number for savecore */
                    655: int            dumpsize = 0;           /* also for savecore */
1.1       cgd       656: /*
                    657:  * Doadump comes here after turning off memory management and
                    658:  * getting on the dump stack, either when called above, or by
                    659:  * the auto-restart code.
                    660:  */
1.32      andrew    661: void
1.1       cgd       662: dumpsys()
                    663: {
                    664:
                    665:        if (dumpdev == NODEV)
                    666:                return;
                    667:        if ((minor(dumpdev)&07) != 1)
                    668:                return;
                    669:        dumpsize = physmem;
1.35      cgd       670:        printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo);
                    671:        printf("dump ");
1.1       cgd       672:        switch ((*bdevsw[major(dumpdev)].d_dump)(dumpdev)) {
                    673:
                    674:        case ENXIO:
1.35      cgd       675:                printf("device bad\n");
1.1       cgd       676:                break;
                    677:
                    678:        case EFAULT:
1.35      cgd       679:                printf("device not ready\n");
1.1       cgd       680:                break;
                    681:
                    682:        case EINVAL:
1.35      cgd       683:                printf("area improper\n");
1.1       cgd       684:                break;
                    685:
                    686:        case EIO:
1.35      cgd       687:                printf("i/o error\n");
1.1       cgd       688:                break;
                    689:
                    690:        case EINTR:
1.35      cgd       691:                printf("aborted from console\n");
1.1       cgd       692:                break;
                    693:
                    694:        default:
1.35      cgd       695:                printf("succeeded\n");
1.1       cgd       696:                break;
                    697:        }
1.35      cgd       698:        printf("\n\n");
                    699:        DELAY(1000);
1.1       cgd       700: }
                    701:
1.3       cgd       702: #ifdef HZ
1.7       cgd       703: /*
                    704:  * If HZ is defined we use this code, otherwise the code in
1.59      mycroft   705:  * /sys/i386/i386/microtime.s is used.  The other code only works
1.7       cgd       706:  * for HZ=100.
                    707:  */
1.1       cgd       708: microtime(tvp)
                    709:        register struct timeval *tvp;
                    710: {
                    711:        int s = splhigh();
                    712:
                    713:        *tvp = time;
                    714:        tvp->tv_usec += tick;
1.59      mycroft   715:        splx(s);
1.1       cgd       716:        while (tvp->tv_usec > 1000000) {
                    717:                tvp->tv_sec++;
                    718:                tvp->tv_usec -= 1000000;
                    719:        }
                    720: }
1.7       cgd       721: #endif /* HZ */
1.1       cgd       722:
                    723: /*
                    724:  * Clear registers on exec
                    725:  */
1.33      cgd       726: void
                    727: setregs(p, entry, stack, retval)
1.1       cgd       728:        struct proc *p;
                    729:        u_long entry;
1.21      cgd       730:        u_long stack;
1.33      cgd       731:        int retval[2];
1.1       cgd       732: {
1.59      mycroft   733:        register struct trapframe *tf;
                    734:
                    735:        tf = (struct trapframe *)p->p_regs;
                    736:        tf->tf_ebp = 0; /* bottom of the fp chain */
                    737:        tf->tf_eip = entry;
                    738:        tf->tf_esp = stack;
                    739:        tf->tf_ss = _udatasel;
                    740:        tf->tf_ds = _udatasel;
                    741:        tf->tf_es = _udatasel;
                    742:        tf->tf_cs = _ucodesel;
1.1       cgd       743:
1.21      cgd       744:        p->p_addr->u_pcb.pcb_flags &= 0 /* FM_SYSCTRC */; /* no fp at all */
1.65      mycroft   745:        lcr0(rcr0() | CR0_TS);  /* start emulating */
1.30      brezak    746: #if    NNPX > 0
1.1       cgd       747:        npxinit(__INITIAL_NPXCW__);
                    748: #endif
1.59      mycroft   749:
                    750:        retval[1] = 0;
1.1       cgd       751: }
                    752:
                    753: /*
                    754:  * Initialize 386 and configure to run kernel
                    755:  */
                    756:
                    757: /*
1.55      brezak    758:  * Initialize segments and descriptor tables
1.1       cgd       759:  */
                    760:
1.59      mycroft   761: union descriptor gdt[NGDT];
                    762: union descriptor ldt[NLDT];
                    763: struct gate_descriptor idt[NIDT];
1.49      brezak    764:
                    765: int _default_ldt, currentldt;
                    766:
1.1       cgd       767: struct i386tss tss, panic_tss;
                    768:
                    769: extern  struct user *proc0paddr;
                    770:
1.40      andrew    771: /* software prototypes -- in more palatable form */
1.1       cgd       772: struct soft_segment_descriptor gdt_segs[] = {
                    773:        /* Null Descriptor */
                    774: {      0x0,                    /* segment base address  */
1.40      andrew    775:        0x0,                    /* length */
1.1       cgd       776:        0,                      /* segment type */
                    777:        0,                      /* segment descriptor priority level */
                    778:        0,                      /* segment descriptor present */
1.40      andrew    779:        0, 0,
1.1       cgd       780:        0,                      /* default 32 vs 16 bit size */
                    781:        0                       /* limit granularity (byte/page units)*/ },
                    782:        /* Code Descriptor for kernel */
                    783: {      0x0,                    /* segment base address  */
                    784:        0xfffff,                /* length - all address space */
                    785:        SDT_MEMERA,             /* segment type */
                    786:        0,                      /* segment descriptor priority level */
                    787:        1,                      /* segment descriptor present */
1.40      andrew    788:        0, 0,
1.1       cgd       789:        1,                      /* default 32 vs 16 bit size */
                    790:        1                       /* limit granularity (byte/page units)*/ },
                    791:        /* Data Descriptor for kernel */
                    792: {      0x0,                    /* segment base address  */
                    793:        0xfffff,                /* length - all address space */
                    794:        SDT_MEMRWA,             /* segment type */
                    795:        0,                      /* segment descriptor priority level */
                    796:        1,                      /* segment descriptor present */
1.40      andrew    797:        0, 0,
1.1       cgd       798:        1,                      /* default 32 vs 16 bit size */
                    799:        1                       /* limit granularity (byte/page units)*/ },
                    800:        /* LDT Descriptor */
                    801: {      (int) ldt,                      /* segment base address  */
                    802:        sizeof(ldt)-1,          /* length - all address space */
                    803:        SDT_SYSLDT,             /* segment type */
                    804:        0,                      /* segment descriptor priority level */
                    805:        1,                      /* segment descriptor present */
1.40      andrew    806:        0, 0,
1.1       cgd       807:        0,                      /* unused - default 32 vs 16 bit size */
                    808:        0                       /* limit granularity (byte/page units)*/ },
                    809:        /* Null Descriptor - Placeholder */
                    810: {      0x0,                    /* segment base address  */
1.40      andrew    811:        0x0,                    /* length */
1.1       cgd       812:        0,                      /* segment type */
                    813:        0,                      /* segment descriptor priority level */
                    814:        0,                      /* segment descriptor present */
1.40      andrew    815:        0, 0,
1.1       cgd       816:        0,                      /* default 32 vs 16 bit size */
                    817:        0                       /* limit granularity (byte/page units)*/ },
                    818:        /* Panic Tss Descriptor */
                    819: {      (int) &panic_tss,               /* segment base address  */
                    820:        sizeof(tss)-1,          /* length - all address space */
                    821:        SDT_SYS386TSS,          /* segment type */
                    822:        0,                      /* segment descriptor priority level */
                    823:        1,                      /* segment descriptor present */
1.40      andrew    824:        0, 0,
1.1       cgd       825:        0,                      /* unused - default 32 vs 16 bit size */
                    826:        0                       /* limit granularity (byte/page units)*/ },
                    827:        /* Proc 0 Tss Descriptor */
1.59      mycroft   828: {      (int) USRSTACK,         /* segment base address  */
1.1       cgd       829:        sizeof(tss)-1,          /* length - all address space */
                    830:        SDT_SYS386TSS,          /* segment type */
                    831:        0,                      /* segment descriptor priority level */
                    832:        1,                      /* segment descriptor present */
1.40      andrew    833:        0, 0,
1.1       cgd       834:        0,                      /* unused - default 32 vs 16 bit size */
1.49      brezak    835:        0                       /* limit granularity (byte/page units)*/ },
                    836:        /* User LDT Descriptor per process */
                    837: {      (int) ldt,                      /* segment base address  */
                    838:        (512 * sizeof(union descriptor)-1),             /* length */
                    839:        SDT_SYSLDT,             /* segment type */
                    840:        0,                      /* segment descriptor priority level */
                    841:        1,                      /* segment descriptor present */
                    842:        0, 0,
                    843:        0,                      /* unused - default 32 vs 16 bit size */
                    844:        0                       /* limit granularity (byte/page units)*/ },
                    845: };
1.1       cgd       846:
                    847: struct soft_segment_descriptor ldt_segs[] = {
                    848:        /* Null Descriptor - overwritten by call gate */
                    849: {      0x0,                    /* segment base address  */
1.40      andrew    850:        0x0,                    /* length */
1.1       cgd       851:        0,                      /* segment type */
                    852:        0,                      /* segment descriptor priority level */
                    853:        0,                      /* segment descriptor present */
1.40      andrew    854:        0, 0,
1.1       cgd       855:        0,                      /* default 32 vs 16 bit size */
                    856:        0                       /* limit granularity (byte/page units)*/ },
                    857:        /* Null Descriptor - overwritten by call gate */
                    858: {      0x0,                    /* segment base address  */
1.40      andrew    859:        0x0,                    /* length */
1.1       cgd       860:        0,                      /* segment type */
                    861:        0,                      /* segment descriptor priority level */
                    862:        0,                      /* segment descriptor present */
1.40      andrew    863:        0, 0,
1.1       cgd       864:        0,                      /* default 32 vs 16 bit size */
                    865:        0                       /* limit granularity (byte/page units)*/ },
                    866:        /* Null Descriptor - overwritten by call gate */
                    867: {      0x0,                    /* segment base address  */
1.40      andrew    868:        0x0,                    /* length */
1.1       cgd       869:        0,                      /* segment type */
                    870:        0,                      /* segment descriptor priority level */
                    871:        0,                      /* segment descriptor present */
1.40      andrew    872:        0, 0,
1.1       cgd       873:        0,                      /* default 32 vs 16 bit size */
                    874:        0                       /* limit granularity (byte/page units)*/ },
                    875:        /* Code Descriptor for user */
                    876: {      0x0,                    /* segment base address  */
                    877:        0xfffff,                /* length - all address space */
                    878:        SDT_MEMERA,             /* segment type */
                    879:        SEL_UPL,                /* segment descriptor priority level */
                    880:        1,                      /* segment descriptor present */
1.40      andrew    881:        0, 0,
1.1       cgd       882:        1,                      /* default 32 vs 16 bit size */
                    883:        1                       /* limit granularity (byte/page units)*/ },
                    884:        /* Data Descriptor for user */
                    885: {      0x0,                    /* segment base address  */
                    886:        0xfffff,                /* length - all address space */
                    887:        SDT_MEMRWA,             /* segment type */
                    888:        SEL_UPL,                /* segment descriptor priority level */
                    889:        1,                      /* segment descriptor present */
1.40      andrew    890:        0, 0,
1.1       cgd       891:        1,                      /* default 32 vs 16 bit size */
                    892:        1                       /* limit granularity (byte/page units)*/ } };
                    893:
1.59      mycroft   894: void
                    895: setidt(idx, func, typ, dpl)
                    896:        int idx;
                    897:        char *func;
                    898:        int typ, dpl;
                    899: {
1.1       cgd       900:        struct gate_descriptor *ip = idt + idx;
                    901:
                    902:        ip->gd_looffset = (int)func;
                    903:        ip->gd_selector = 8;
                    904:        ip->gd_stkcpy = 0;
                    905:        ip->gd_xx = 0;
                    906:        ip->gd_type = typ;
                    907:        ip->gd_dpl = dpl;
                    908:        ip->gd_p = 1;
1.59      mycroft   909:        ip->gd_hioffset = ((int)func)>>16;
1.1       cgd       910: }
                    911:
                    912: #define        IDTVEC(name)    __CONCAT(X, name)
                    913: extern IDTVEC(div), IDTVEC(dbg), IDTVEC(nmi), IDTVEC(bpt), IDTVEC(ofl),
                    914:        IDTVEC(bnd), IDTVEC(ill), IDTVEC(dna), IDTVEC(dble), IDTVEC(fpusegm),
                    915:        IDTVEC(tss), IDTVEC(missing), IDTVEC(stk), IDTVEC(prot),
1.62      mycroft   916:        IDTVEC(page), IDTVEC(rsvd), IDTVEC(fpu), IDTVEC(align),
1.1       cgd       917:        IDTVEC(rsvd1), IDTVEC(rsvd2), IDTVEC(rsvd3), IDTVEC(rsvd4),
                    918:        IDTVEC(rsvd5), IDTVEC(rsvd6), IDTVEC(rsvd7), IDTVEC(rsvd8),
                    919:        IDTVEC(rsvd9), IDTVEC(rsvd10), IDTVEC(rsvd11), IDTVEC(rsvd12),
                    920:        IDTVEC(rsvd13), IDTVEC(rsvd14), IDTVEC(rsvd14), IDTVEC(syscall);
                    921:
1.59      mycroft   922: void
1.43      brezak    923: init386(first_avail)
                    924:        vm_offset_t first_avail;
1.2       cgd       925: {
1.73      mycroft   926:        extern ssdtosd(), lgdt(), etext;
1.1       cgd       927:        int x, *pi;
                    928:        unsigned biosbasemem, biosextmem;
                    929:        struct gate_descriptor *gdp;
1.22      cgd       930:        extern char sigcode[], esigcode[];
1.1       cgd       931:        /* table descriptors - used to load tables by microp */
                    932:        struct region_descriptor r_gdt, r_idt;
                    933:
                    934:        proc0.p_addr = proc0paddr;
                    935:
1.59      mycroft   936:        cninit();       /* XXXX should be consinit() */
1.1       cgd       937:
1.28      cgd       938: #ifndef LKM            /* don't do this if we're using LKM's */
1.59      mycroft   939:        /* set code segment limit to end of kernel text */
                    940:        gdt_segs[GCODE_SEL].ssd_limit = i386_btop(i386_round_page(&etext)) - 1;
1.28      cgd       941: #endif
                    942:
1.59      mycroft   943:        for (x = 0; x < NGDT; x++)
                    944:                ssdtosd(gdt_segs + x, gdt + x);
                    945:
1.1       cgd       946:        /* make ldt memory segments */
1.59      mycroft   947:        ldt_segs[LUCODE_SEL].ssd_limit = i386_btop(VM_MAXUSER_ADDRESS) - 1;
                    948:        ldt_segs[LUDATA_SEL].ssd_limit = i386_btop(VM_MAXUSER_ADDRESS) - 1;
                    949:        for (x = 0; x < NLDT; x++)
                    950:                ssdtosd(ldt_segs + x, ldt + x);
1.1       cgd       951:
                    952:        /* exceptions */
1.59      mycroft   953:        setidt(0, &IDTVEC(div), SDT_SYS386TGT, SEL_KPL);
                    954:        setidt(1, &IDTVEC(dbg), SDT_SYS386TGT, SEL_KPL);
                    955:        setidt(2, &IDTVEC(nmi), SDT_SYS386TGT, SEL_KPL);
1.73      mycroft   956:        setidt(3, &IDTVEC(bpt), SDT_SYS386TGT, SEL_UPL);        /* XXXX */
1.59      mycroft   957:        setidt(4, &IDTVEC(ofl), SDT_SYS386TGT, SEL_KPL);
                    958:        setidt(5, &IDTVEC(bnd), SDT_SYS386TGT, SEL_KPL);
                    959:        setidt(6, &IDTVEC(ill), SDT_SYS386TGT, SEL_KPL);
                    960:        setidt(7, &IDTVEC(dna), SDT_SYS386TGT, SEL_KPL);
                    961:        setidt(8, &IDTVEC(dble), SDT_SYS386TGT, SEL_KPL);
                    962:        setidt(9, &IDTVEC(fpusegm), SDT_SYS386TGT, SEL_KPL);
                    963:        setidt(10, &IDTVEC(tss), SDT_SYS386TGT, SEL_KPL);
                    964:        setidt(11, &IDTVEC(missing), SDT_SYS386TGT, SEL_KPL);
                    965:        setidt(12, &IDTVEC(stk), SDT_SYS386TGT, SEL_KPL);
                    966:        setidt(13, &IDTVEC(prot), SDT_SYS386TGT, SEL_KPL);
                    967:        setidt(14, &IDTVEC(page), SDT_SYS386TGT, SEL_KPL);
                    968:        setidt(15, &IDTVEC(rsvd), SDT_SYS386TGT, SEL_KPL);
                    969:        setidt(16, &IDTVEC(fpu), SDT_SYS386TGT, SEL_KPL);
1.62      mycroft   970:        setidt(17, &IDTVEC(align), SDT_SYS386TGT, SEL_KPL);
1.59      mycroft   971:        setidt(18, &IDTVEC(rsvd1), SDT_SYS386TGT, SEL_KPL);
                    972:        setidt(19, &IDTVEC(rsvd2), SDT_SYS386TGT, SEL_KPL);
                    973:        setidt(20, &IDTVEC(rsvd3), SDT_SYS386TGT, SEL_KPL);
                    974:        setidt(21, &IDTVEC(rsvd4), SDT_SYS386TGT, SEL_KPL);
                    975:        setidt(22, &IDTVEC(rsvd5), SDT_SYS386TGT, SEL_KPL);
                    976:        setidt(23, &IDTVEC(rsvd6), SDT_SYS386TGT, SEL_KPL);
                    977:        setidt(24, &IDTVEC(rsvd7), SDT_SYS386TGT, SEL_KPL);
                    978:        setidt(25, &IDTVEC(rsvd8), SDT_SYS386TGT, SEL_KPL);
                    979:        setidt(26, &IDTVEC(rsvd9), SDT_SYS386TGT, SEL_KPL);
                    980:        setidt(27, &IDTVEC(rsvd10), SDT_SYS386TGT, SEL_KPL);
                    981:        setidt(28, &IDTVEC(rsvd11), SDT_SYS386TGT, SEL_KPL);
                    982:        setidt(29, &IDTVEC(rsvd12), SDT_SYS386TGT, SEL_KPL);
                    983:        setidt(30, &IDTVEC(rsvd13), SDT_SYS386TGT, SEL_KPL);
                    984:        setidt(31, &IDTVEC(rsvd14), SDT_SYS386TGT, SEL_KPL);
1.1       cgd       985:
                    986: #if    NISA >0
                    987:        isa_defaultirq();
                    988: #endif
                    989:        r_gdt.rd_limit = sizeof(gdt)-1;
                    990:        r_gdt.rd_base = (int) gdt;
                    991:        lgdt(&r_gdt);
                    992:        r_idt.rd_limit = sizeof(idt)-1;
                    993:        r_idt.rd_base = (int) idt;
                    994:        lidt(&r_idt);
1.59      mycroft   995:        _default_ldt = GSEL(GLDT_SEL, SEL_KPL);
1.49      brezak    996:        lldt(_default_ldt);
1.59      mycroft   997:        currentldt = _default_ldt;
1.1       cgd       998:
1.5       glass     999: #ifdef DDB
1.42      brezak   1000:        ddb_init();
1.1       cgd      1001:        if (boothowto & RB_KDB)
                   1002:                Debugger();
                   1003: #endif
1.43      brezak   1004: #ifdef KGDB
                   1005:        if (boothowto & RB_KDB)
1.59      mycroft  1006:                kgdb_connect(0);
1.43      brezak   1007: #endif
1.1       cgd      1008:
1.59      mycroft  1009:        /*
                   1010:         * Use BIOS values stored in RTC CMOS RAM, since probing
1.1       cgd      1011:         * breaks certain 386 AT relics.
                   1012:         */
1.73      mycroft  1013:        biosbasemem = (rtcin(RTC_BASEHI)<<8) | (rtcin(RTC_BASELO));
                   1014:        biosextmem = (rtcin(RTC_EXTHI)<<8) | (rtcin(RTC_EXTLO));
1.59      mycroft  1015:
                   1016: #ifndef BIOS_BASEMEM
                   1017: #define        BIOS_BASEMEM 640
                   1018: #endif
1.2       cgd      1019:
1.59      mycroft  1020:        if (biosbasemem == 0 || biosbasemem > 640) {
                   1021:                printf("warning: nvram reports %dk base memory; assuming %dk\n",
1.73      mycroft  1022:                    biosbasemem, BIOS_BASEMEM);
1.59      mycroft  1023:                biosbasemem = BIOS_BASEMEM;
1.2       cgd      1024:        }
                   1025:
1.59      mycroft  1026:        avail_start = NBPG;     /* BIOS leaves data in low memory */
1.43      brezak   1027:                                /* and VM system doesn't work with phys 0 */
1.59      mycroft  1028:        avail_end = biosextmem ? IOM_END + biosextmem * 1024
1.73      mycroft  1029:            : biosbasemem * 1024;
                   1030:
1.59      mycroft  1031:        /* number of pages of physmem addr space */
                   1032:        physmem = btoc((biosbasemem + biosextmem) * 1024);
1.2       cgd      1033:
1.43      brezak   1034:        /*
1.59      mycroft  1035:         * Initialize for pmap_free_pages and pmap_next_page.
                   1036:         * These guys should be page-aligned.
1.43      brezak   1037:         */
                   1038:        hole_start = biosbasemem * 1024;
1.59      mycroft  1039:        /* we load right after the I/O hole; adjust hole_end to compensate */
1.43      brezak   1040:        hole_end = round_page((vm_offset_t)first_avail);
                   1041:        avail_next = avail_start;
1.59      mycroft  1042:        avail_remaining = i386_btop((avail_end - avail_start) -
                   1043:                                    (hole_end - hole_start));
1.73      mycroft  1044:
1.59      mycroft  1045:        if (avail_remaining < i386_btop(2 * 1024 * 1024)) {
                   1046:                printf("warning: too little memory available; running in degraded mode\n"
1.73      mycroft  1047:                    "press a key to confirm\n\n");
1.2       cgd      1048:                /*
1.59      mycroft  1049:                 * People with less than 2 Meg have to press a key; this way
1.2       cgd      1050:                 * we see the messages and can tell them why they blow up later.
1.59      mycroft  1051:                 * If they get working well enough to recompile, they can remove
                   1052:                 * this; otherwise, it's a toy and they have to lump it.
1.2       cgd      1053:                 */
1.20      deraadt  1054:                cngetc();
1.2       cgd      1055:        }
1.59      mycroft  1056:
1.1       cgd      1057:        /* call pmap initialization to make new kernel address space */
1.59      mycroft  1058:        pmap_bootstrap((vm_offset_t)atdevbase + IOM_SIZE);
1.73      mycroft  1059:
1.1       cgd      1060:        /* now running on new page tables, configured,and u/iom is accessible */
                   1061:
                   1062:        /* make a initial tss so microp can get interrupt stack on syscall! */
1.59      mycroft  1063:        proc0.p_addr->u_pcb.pcb_tss.tss_esp0 = (int) USRSTACK + UPAGES*NBPG;
                   1064:        proc0.p_addr->u_pcb.pcb_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL);
1.1       cgd      1065:        _gsel_tss = GSEL(GPROC0_SEL, SEL_KPL);
1.11      cgd      1066:
1.73      mycroft  1067:        ((struct i386tss *)gdt_segs[GPROC0_SEL].ssd_base)->tss_ioopt =
1.11      cgd      1068:                (sizeof(tss))<<16;
                   1069:
1.1       cgd      1070:        ltr(_gsel_tss);
                   1071:
                   1072:        /* make a call gate to reenter kernel with */
                   1073:        gdp = &ldt[LSYS5CALLS_SEL].gd;
1.73      mycroft  1074:
1.1       cgd      1075:        x = (int) &IDTVEC(syscall);
                   1076:        gdp->gd_looffset = x++;
1.83    ! mycroft  1077:        gdp->gd_selector = GSEL(GCODE_SEL, SEL_KPL);
1.59      mycroft  1078:        gdp->gd_stkcpy = 1;     /* leaves room for eflags like a trap */
1.1       cgd      1079:        gdp->gd_type = SDT_SYS386CGT;
                   1080:        gdp->gd_dpl = SEL_UPL;
                   1081:        gdp->gd_p = 1;
                   1082:        gdp->gd_hioffset = ((int) &IDTVEC(syscall)) >>16;
                   1083:
                   1084:        /* transfer to user mode */
                   1085:        _ucodesel = LSEL(LUCODE_SEL, SEL_UPL);
                   1086:        _udatasel = LSEL(LUDATA_SEL, SEL_UPL);
                   1087:
                   1088:        /* setup proc 0's pcb */
                   1089:        proc0.p_addr->u_pcb.pcb_flags = 0;
                   1090:        proc0.p_addr->u_pcb.pcb_ptd = IdlePTD;
                   1091: }
                   1092:
                   1093: /*
1.73      mycroft  1094:  * insert an element into a queue
1.1       cgd      1095:  */
                   1096: #undef insque
                   1097: _insque(element, head)
                   1098:        register struct prochd *element, *head;
                   1099: {
                   1100:        element->ph_link = head->ph_link;
                   1101:        head->ph_link = (struct proc *)element;
                   1102:        element->ph_rlink = (struct proc *)head;
                   1103:        ((struct prochd *)(element->ph_link))->ph_rlink=(struct proc *)element;
                   1104: }
                   1105:
                   1106: /*
                   1107:  * remove an element from a queue
                   1108:  */
                   1109: #undef remque
                   1110: _remque(element)
                   1111:        register struct prochd *element;
                   1112: {
                   1113:        ((struct prochd *)(element->ph_link))->ph_rlink = element->ph_rlink;
                   1114:        ((struct prochd *)(element->ph_rlink))->ph_link = element->ph_link;
                   1115:        element->ph_rlink = (struct proc *)0;
                   1116: }
                   1117:
1.46      cgd      1118: /*
                   1119:  * cpu_exec_aout_makecmds():
                   1120:  *     cpu-dependent a.out format hook for execve().
1.73      mycroft  1121:  *
1.46      cgd      1122:  * Determine of the given exec package refers to something which we
                   1123:  * understand and, if so, set up the vmcmds for it.
                   1124:  *
                   1125:  * On the i386, old (386bsd) ZMAGIC binaries and BSDI QMAGIC binaries
                   1126:  * if COMPAT_NOMID is given as a kernel option.
                   1127:  */
1.67      mycroft  1128: int
1.46      cgd      1129: cpu_exec_aout_makecmds(p, epp)
1.59      mycroft  1130:        struct proc *p;
                   1131:        struct exec_package *epp;
1.31      cgd      1132: {
                   1133: #ifdef COMPAT_NOMID
1.59      mycroft  1134:        int error;
                   1135:        u_long midmag, magic;
                   1136:        u_short mid;
1.80      cgd      1137:        struct exec *execp = epp->ep_hdr;
1.31      cgd      1138:
1.80      cgd      1139:        /* check on validity of epp->ep_hdr performed by exec_out_makecmds */
                   1140:
                   1141:        midmag = ntohl(execp->a_midmag);
1.59      mycroft  1142:        mid = (midmag >> 16) & 0xffff;
                   1143:        magic = midmag & 0xffff;
                   1144:
                   1145:        if (magic == 0) {
1.80      cgd      1146:                magic = (execp->a_midmag & 0xffff);
1.59      mycroft  1147:                mid = MID_ZERO;
                   1148:        }
                   1149:
                   1150:        midmag = mid << 16 | magic;
                   1151:
                   1152:        switch (midmag) {
                   1153:        case (MID_ZERO << 16) | ZMAGIC:
                   1154:                /*
                   1155:                 * 386BSD's ZMAGIC format:
                   1156:                 */
                   1157:                error = cpu_exec_aout_prep_oldzmagic(p, epp);
                   1158:                break;
                   1159:
                   1160:        case (MID_ZERO << 16) | QMAGIC:
                   1161:                /*
                   1162:                 * BSDI's QMAGIC format:
                   1163:                 * same as new ZMAGIC format, but with different magic number
                   1164:                 */
                   1165:                error = exec_aout_prep_zmagic(p, epp);
                   1166:                break;
                   1167:
                   1168:        default:
                   1169:                error = ENOEXEC;
                   1170:        }
                   1171:
                   1172:        return error;
1.31      cgd      1173: #else /* ! COMPAT_NOMID */
1.59      mycroft  1174:        return ENOEXEC;
1.31      cgd      1175: #endif
                   1176: }
1.24      cgd      1177:
1.31      cgd      1178: #ifdef COMPAT_NOMID
1.46      cgd      1179: /*
                   1180:  * cpu_exec_aout_prep_oldzmagic():
                   1181:  *     Prepare the vmcmds to build a vmspace for an old (386BSD) ZMAGIC
                   1182:  *     binary.
                   1183:  *
                   1184:  * Cloned from exec_aout_prep_zmagic() in kern/exec_aout.c; a more verbose
                   1185:  * description of operation is there.
                   1186:  */
1.24      cgd      1187: int
1.46      cgd      1188: cpu_exec_aout_prep_oldzmagic(p, epp)
1.59      mycroft  1189:        struct proc *p;
                   1190:        struct exec_package *epp;
1.24      cgd      1191: {
1.80      cgd      1192:        struct exec *execp = epp->ep_hdr;
1.59      mycroft  1193:        struct exec_vmcmd *ccmdp;
1.24      cgd      1194:
1.59      mycroft  1195:        epp->ep_taddr = 0;
                   1196:        epp->ep_tsize = execp->a_text;
                   1197:        epp->ep_daddr = epp->ep_taddr + execp->a_text;
                   1198:        epp->ep_dsize = execp->a_data + execp->a_bss;
                   1199:        epp->ep_entry = execp->a_entry;
                   1200:
                   1201:        /*
                   1202:         * check if vnode is in open for writing, because we want to
                   1203:         * demand-page out of it.  if it is, don't do it, for various
                   1204:         * reasons
                   1205:         */
                   1206:        if ((execp->a_text != 0 || execp->a_data != 0) &&
                   1207:            epp->ep_vp->v_writecount != 0) {
1.31      cgd      1208: #ifdef DIAGNOSTIC
1.59      mycroft  1209:                if (epp->ep_vp->v_flag & VTEXT)
                   1210:                        panic("exec: a VTEXT vnode has writecount != 0\n");
1.31      cgd      1211: #endif
1.59      mycroft  1212:                return ETXTBSY;
                   1213:        }
                   1214:        epp->ep_vp->v_flag |= VTEXT;
                   1215:
                   1216:        /* set up command for text segment */
1.69      cgd      1217:        NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_pagedvn, execp->a_text,
                   1218:            epp->ep_taddr, epp->ep_vp, NBPG, /* XXX should NBPG be CLBYTES? */
                   1219:            VM_PROT_READ|VM_PROT_EXECUTE);
1.59      mycroft  1220:
                   1221:        /* set up command for data segment */
1.69      cgd      1222:        NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_pagedvn, execp->a_data,
                   1223:            epp->ep_daddr, epp->ep_vp,
                   1224:            execp->a_text + NBPG, /* XXX should NBPG be CLBYTES? */
                   1225:            VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
1.59      mycroft  1226:
                   1227:        /* set up command for bss segment */
1.69      cgd      1228:        NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero, execp->a_bss,
1.71      mycroft  1229:            epp->ep_daddr + execp->a_data, NULLVP, 0,
1.69      cgd      1230:            VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
1.24      cgd      1231:
1.69      cgd      1232:        return exec_aout_setup_stack(p, epp);
1.1       cgd      1233: }
1.31      cgd      1234: #endif /* COMPAT_NOMID */
1.43      brezak   1235:
1.59      mycroft  1236: unsigned int
                   1237: pmap_free_pages()
                   1238: {
                   1239:
                   1240:        return avail_remaining;
                   1241: }
                   1242:
                   1243: int
                   1244: pmap_next_page(addrp)
                   1245:        vm_offset_t *addrp;
                   1246: {
                   1247:
                   1248:        if (avail_next == avail_end)
                   1249:                return FALSE;
1.73      mycroft  1250:
1.59      mycroft  1251:        /* skip the hole */
                   1252:        if (avail_next == hole_start)
                   1253:                avail_next = hole_end;
1.73      mycroft  1254:
1.59      mycroft  1255:        *addrp = avail_next;
                   1256:        avail_next += NBPG;
                   1257:        avail_remaining--;
                   1258:        return TRUE;
                   1259: }
                   1260:
                   1261: unsigned int
                   1262: pmap_page_index(pa)
                   1263:        vm_offset_t pa;
                   1264: {
                   1265:
                   1266:        if (pa >= avail_start && pa < hole_start)
                   1267:                return i386_btop(pa - avail_start);
                   1268:        if (pa >= hole_end && pa < avail_end)
                   1269:                return i386_btop(pa - hole_end + hole_start - avail_start);
                   1270:        return -1;
1.45      cgd      1271: }

CVSweb <webmaster@jp.NetBSD.org>