[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.162

1.162   ! mycroft     1: /*     $NetBSD: machdep.c,v 1.161 1995/05/18 18:59:16 mycroft Exp $    */
1.125     cgd         2:
1.1       cgd         3: /*-
1.148     mycroft     4:  * Copyright (c) 1993, 1994, 1995 Charles M. Hannum.  All rights reserved.
1.35      cgd         5:  * Copyright (c) 1992 Terrence R. Lambert.
1.1       cgd         6:  * Copyright (c) 1982, 1987, 1990 The Regents of the University of California.
                      7:  * All rights reserved.
                      8:  *
                      9:  * This code is derived from software contributed to Berkeley by
                     10:  * William Jolitz.
                     11:  *
                     12:  * Redistribution and use in source and binary forms, with or without
                     13:  * modification, are permitted provided that the following conditions
                     14:  * are met:
                     15:  * 1. Redistributions of source code must retain the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer.
                     17:  * 2. Redistributions in binary form must reproduce the above copyright
                     18:  *    notice, this list of conditions and the following disclaimer in the
                     19:  *    documentation and/or other materials provided with the distribution.
                     20:  * 3. All advertising materials mentioning features or use of this software
                     21:  *    must display the following acknowledgement:
                     22:  *     This product includes software developed by the University of
                     23:  *     California, Berkeley and its contributors.
                     24:  * 4. Neither the name of the University nor the names of its contributors
                     25:  *    may be used to endorse or promote products derived from this software
                     26:  *    without specific prior written permission.
                     27:  *
                     28:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     29:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     30:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     31:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     32:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     33:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     34:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     35:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     36:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     37:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     38:  * SUCH DAMAGE.
                     39:  *
1.125     cgd        40:  *     @(#)machdep.c   7.4 (Berkeley) 6/3/91
1.1       cgd        41:  */
                     42:
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>
                     51: #include <sys/buf.h>
                     52: #include <sys/reboot.h>
                     53: #include <sys/conf.h>
                     54: #include <sys/file.h>
                     55: #include <sys/callout.h>
                     56: #include <sys/malloc.h>
                     57: #include <sys/mbuf.h>
                     58: #include <sys/msgbuf.h>
                     59: #include <sys/mount.h>
                     60: #include <sys/vnode.h>
1.92      mycroft    61: #include <sys/device.h>
1.104     cgd        62: #include <sys/sysctl.h>
1.123     cgd        63: #include <sys/syscallargs.h>
1.57      cgd        64: #ifdef SYSVMSG
1.59      mycroft    65: #include <sys/msg.h>
1.57      cgd        66: #endif
                     67: #ifdef SYSVSEM
1.59      mycroft    68: #include <sys/sem.h>
                     69: #endif
                     70: #ifdef SYSVSHM
                     71: #include <sys/shm.h>
1.57      cgd        72: #endif
                     73:
1.104     cgd        74: #include <dev/cons.h>
                     75:
1.59      mycroft    76: #include <vm/vm.h>
                     77: #include <vm/vm_kern.h>
                     78: #include <vm/vm_page.h>
1.31      cgd        79:
1.59      mycroft    80: #include <machine/cpu.h>
                     81: #include <machine/cpufunc.h>
1.149     mycroft    82: #include <machine/pio.h>
1.59      mycroft    83: #include <machine/psl.h>
                     84: #include <machine/reg.h>
                     85: #include <machine/specialreg.h>
1.43      brezak     86:
1.146     cgd        87: #include <dev/isa/isareg.h>
                     88: #include <dev/isa/isavar.h>
1.149     mycroft    89: #include <dev/ic/i8042.h>
1.158     cgd        90: #include <dev/ic/mc146818.h>
1.146     cgd        91: #include <i386/isa/isa_machdep.h>
1.158     cgd        92: #include <i386/isa/nvram.h>
1.43      brezak     93:
1.59      mycroft    94: #include "isa.h"
                     95: #include "npx.h"
1.161     mycroft    96: #if NNPX > 0
                     97: extern struct proc *npxproc;
                     98: #endif
1.2       cgd        99:
1.104     cgd       100: /* the following is used externally (sysctl_hw) */
                    101: char machine[] = "i386";               /* cpu "architecture" */
                    102:
1.1       cgd       103: /*
                    104:  * Declare these as initialized data so we can patch them.
                    105:  */
                    106: int    nswbuf = 0;
                    107: #ifdef NBUF
                    108: int    nbuf = NBUF;
                    109: #else
                    110: int    nbuf = 0;
                    111: #endif
                    112: #ifdef BUFPAGES
                    113: int    bufpages = BUFPAGES;
                    114: #else
                    115: int    bufpages = 0;
                    116: #endif
                    117:
1.59      mycroft   118: int    physmem;
                    119: int    boothowto;
                    120: int    cpu_class;
                    121:
                    122: struct msgbuf *msgbufp;
                    123: int    msgbufmapped;
                    124:
                    125: vm_map_t buffer_map;
1.48      brezak    126:
1.59      mycroft   127: extern vm_offset_t avail_start, avail_end;
                    128: static vm_offset_t hole_start, hole_end;
                    129: static vm_offset_t avail_next;
1.1       cgd       130:
1.149     mycroft   131: caddr_t allocsys __P((caddr_t));
1.32      andrew    132: void dumpsys __P((void));
1.149     mycroft   133: void cpu_reset __P((void));
1.59      mycroft   134:
                    135: /*
                    136:  * Machine-dependent startup code
                    137:  */
1.32      andrew    138: void
1.1       cgd       139: cpu_startup()
                    140: {
1.59      mycroft   141:        unsigned i;
                    142:        caddr_t v;
                    143:        int sz;
                    144:        int base, residual;
1.1       cgd       145:        vm_offset_t minaddr, maxaddr;
                    146:        vm_size_t size;
                    147:
                    148:        /*
                    149:         * Initialize error message buffer (at end of core).
                    150:         */
                    151:        /* avail_end was pre-decremented in pmap_bootstrap to compensate */
1.59      mycroft   152:        for (i = 0; i < btoc(sizeof(struct msgbuf)); i++)
1.143     mycroft   153:                pmap_enter(pmap_kernel(),
1.108     cgd       154:                    (vm_offset_t)((caddr_t)msgbufp + i * NBPG),
                    155:                    avail_end + i * NBPG, VM_PROT_ALL, TRUE);
1.1       cgd       156:        msgbufmapped = 1;
                    157:
1.6       cgd       158:        printf(version);
1.16      cgd       159:        identifycpu();
1.6       cgd       160:        printf("real mem  = %d\n", ctob(physmem));
1.1       cgd       161:
                    162:        /*
1.59      mycroft   163:         * Find out how much space we need, allocate it,
                    164:         * and then give everything true virtual addresses.
1.1       cgd       165:         */
1.59      mycroft   166:        sz = (int)allocsys((caddr_t)0);
                    167:        if ((v = (caddr_t)kmem_alloc(kernel_map, round_page(sz))) == 0)
                    168:                panic("startup: no room for tables");
                    169:        if (allocsys(v) - v != sz)
1.1       cgd       170:                panic("startup: table size inconsistency");
1.50      cgd       171:
1.36      cgd       172:        /*
                    173:         * Now allocate buffers proper.  They are different than the above
                    174:         * in that they usually occupy more virtual memory than physical.
                    175:         */
                    176:        size = MAXBSIZE * nbuf;
1.68      mycroft   177:        buffer_map = kmem_suballoc(kernel_map, (vm_offset_t *)&buffers,
1.108     cgd       178:                                   &maxaddr, size, TRUE);
1.36      cgd       179:        minaddr = (vm_offset_t)buffers;
                    180:        if (vm_map_find(buffer_map, vm_object_allocate(size), (vm_offset_t)0,
                    181:                        &minaddr, size, FALSE) != KERN_SUCCESS)
                    182:                panic("startup: cannot allocate buffers");
1.54      cgd       183:        if ((bufpages / nbuf) >= btoc(MAXBSIZE)) {
                    184:                /* don't want to alloc more physical mem than needed */
                    185:                bufpages = btoc(MAXBSIZE) * nbuf;
                    186:        }
1.36      cgd       187:        base = bufpages / nbuf;
                    188:        residual = bufpages % nbuf;
                    189:        for (i = 0; i < nbuf; i++) {
                    190:                vm_size_t curbufsize;
                    191:                vm_offset_t curbuf;
                    192:
                    193:                /*
                    194:                 * First <residual> buffers get (base+1) physical pages
                    195:                 * allocated for them.  The rest get (base) physical pages.
                    196:                 *
                    197:                 * The rest of each buffer occupies virtual space,
                    198:                 * but has no physical memory allocated for it.
                    199:                 */
                    200:                curbuf = (vm_offset_t)buffers + i * MAXBSIZE;
                    201:                curbufsize = CLBYTES * (i < residual ? base+1 : base);
                    202:                vm_map_pageable(buffer_map, curbuf, curbuf+curbufsize, FALSE);
                    203:                vm_map_simplify(buffer_map, curbuf);
                    204:        }
1.41      cgd       205:
1.1       cgd       206:        /*
1.36      cgd       207:         * Allocate a submap for exec arguments.  This map effectively
                    208:         * limits the number of processes exec'ing at any time.
1.1       cgd       209:         */
1.59      mycroft   210:        exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
1.79      mycroft   211:                                 16*NCARGS, TRUE);
1.59      mycroft   212:
1.1       cgd       213:        /*
                    214:         * Allocate a submap for physio
                    215:         */
                    216:        phys_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
                    217:                                 VM_PHYS_SIZE, TRUE);
                    218:
                    219:        /*
                    220:         * Finally, allocate mbuf pool.  Since mclrefcnt is an off-size
                    221:         * we use the more space efficient malloc in place of kmem_alloc.
                    222:         */
                    223:        mclrefcnt = (char *)malloc(NMBCLUSTERS+CLBYTES/MCLBYTES,
                    224:                                   M_MBUF, M_NOWAIT);
                    225:        bzero(mclrefcnt, NMBCLUSTERS+CLBYTES/MCLBYTES);
1.68      mycroft   226:        mb_map = kmem_suballoc(kernel_map, (vm_offset_t *)&mbutl, &maxaddr,
1.73      mycroft   227:            VM_MBUF_SIZE, FALSE);
1.59      mycroft   228:
1.1       cgd       229:        /*
                    230:         * Initialize callouts
                    231:         */
                    232:        callfree = callout;
                    233:        for (i = 1; i < ncallout; i++)
                    234:                callout[i-1].c_next = &callout[i];
                    235:
1.98      cgd       236:        printf("avail mem = %d\n", ptoa(cnt.v_free_count));
1.36      cgd       237:        printf("using %d buffers containing %d bytes of memory\n",
                    238:                nbuf, bufpages * CLBYTES);
1.1       cgd       239:
                    240:        /*
                    241:         * Set up buffers, so they can be used to read disk labels.
                    242:         */
                    243:        bufinit();
                    244:
                    245:        /*
                    246:         * Configure the system.
                    247:         */
                    248:        configure();
1.153     mycroft   249:
                    250:        /*
                    251:         * After configuring npx, etc., save the value of cr0 so it can
                    252:         * be reloaded quickly.
                    253:         */
                    254:        proc0.p_addr->u_pcb.pcb_cr0 = rcr0();
1.16      cgd       255: }
                    256:
1.59      mycroft   257: /*
                    258:  * Allocate space for system data structures.  We are given
                    259:  * a starting virtual address and we return a final virtual
                    260:  * address; along the way we set each data structure pointer.
                    261:  *
                    262:  * We call allocsys() with 0 to find out how much space we want,
                    263:  * allocate that much and fill it with zeroes, and then call
                    264:  * allocsys() again with the correct base virtual address.
                    265:  */
                    266: caddr_t
                    267: allocsys(v)
                    268:        register caddr_t v;
                    269: {
                    270:
                    271: #define        valloc(name, type, num) \
                    272:            v = (caddr_t)(((name) = (type *)v) + (num))
                    273: #ifdef REAL_CLISTS
                    274:        valloc(cfree, struct cblock, nclist);
                    275: #endif
                    276:        valloc(callout, struct callout, ncallout);
                    277:        valloc(swapmap, struct map, nswapmap = maxproc * 2);
                    278: #ifdef SYSVSHM
                    279:        valloc(shmsegs, struct shmid_ds, shminfo.shmmni);
                    280: #endif
                    281: #ifdef SYSVSEM
                    282:        valloc(sema, struct semid_ds, seminfo.semmni);
                    283:        valloc(sem, struct sem, seminfo.semmns);
                    284:        /* This is pretty disgusting! */
                    285:        valloc(semu, int, (seminfo.semmnu * seminfo.semusz) / sizeof(int));
                    286: #endif
                    287: #ifdef SYSVMSG
                    288:        valloc(msgpool, char, msginfo.msgmax);
                    289:        valloc(msgmaps, struct msgmap, msginfo.msgseg);
                    290:        valloc(msghdrs, struct msg, msginfo.msgtql);
                    291:        valloc(msqids, struct msqid_ds, msginfo.msgmni);
                    292: #endif
                    293:
                    294:        /*
1.77      mycroft   295:         * Determine how many buffers to allocate.  We use 10% of the
                    296:         * first 2MB of memory, and 5% of the rest, with a minimum of 16
                    297:         * buffers.  We allocate 1/2 as many swap buffer headers as file
                    298:         * i/o buffers.
1.59      mycroft   299:         */
                    300:        if (bufpages == 0)
1.77      mycroft   301:                if (physmem < btoc(2 * 1024 * 1024))
                    302:                        bufpages = physmem / (10 * CLSIZE);
                    303:                else
                    304:                        bufpages = (btoc(2 * 1024 * 1024) + physmem) /
                    305:                            (20 * CLSIZE);
1.59      mycroft   306:        if (nbuf == 0) {
                    307:                nbuf = bufpages;
                    308:                if (nbuf < 16)
                    309:                        nbuf = 16;
                    310:        }
                    311:        if (nswbuf == 0) {
                    312:                nswbuf = (nbuf / 2) &~ 1;       /* force even */
                    313:                if (nswbuf > 256)
                    314:                        nswbuf = 256;           /* sanity */
                    315:        }
                    316:        valloc(swbuf, struct buf, nswbuf);
                    317:        valloc(buf, struct buf, nbuf);
                    318:        return v;
                    319: }
1.18      cgd       320:
1.104     cgd       321: /*
                    322:  * Info for CTL_HW
                    323:  */
                    324: char   cpu_model[120];
                    325: extern char version[];
                    326:
1.18      cgd       327: struct cpu_nameclass i386_cpus[] = {
1.59      mycroft   328:        { "i386SX",     CPUCLASS_386 }, /* CPU_386SX */
                    329:        { "i386DX",     CPUCLASS_386 }, /* CPU_386   */
                    330:        { "i486SX",     CPUCLASS_486 }, /* CPU_486SX */
                    331:        { "i486DX",     CPUCLASS_486 }, /* CPU_486   */
                    332:        { "Pentium",    CPUCLASS_586 }, /* CPU_586   */
1.109     deraadt   333:        { "Cx486DLC",   CPUCLASS_486 }, /* CPU_486DLC (Cyrix) */
1.18      cgd       334: };
                    335:
1.59      mycroft   336: identifycpu()
1.16      cgd       337: {
1.104     cgd       338:        int len;
1.86      mycroft   339:        extern char cpu_vendor[];
                    340:
1.17      cgd       341:        printf("CPU: ");
1.59      mycroft   342: #ifdef DIAGNOSTIC
                    343:        if (cpu < 0 || cpu >= (sizeof i386_cpus/sizeof(struct cpu_nameclass)))
                    344:                panic("unknown cpu type %d\n", cpu);
                    345: #endif
1.104     cgd       346:        sprintf(cpu_model, "%s (", i386_cpus[cpu].cpu_name);
                    347:        if (cpu_vendor[0] != '\0') {
                    348:                strcat(cpu_model, cpu_vendor);
                    349:                strcat(cpu_model, " ");
                    350:        }
                    351:
1.59      mycroft   352:        cpu_class = i386_cpus[cpu].cpu_class;
1.24      cgd       353:        switch(cpu_class) {
1.18      cgd       354:        case CPUCLASS_386:
1.104     cgd       355:                strcat(cpu_model, "386");
1.17      cgd       356:                break;
1.18      cgd       357:        case CPUCLASS_486:
1.104     cgd       358:                strcat(cpu_model, "486");
1.17      cgd       359:                break;
1.18      cgd       360:        case CPUCLASS_586:
1.104     cgd       361:                strcat(cpu_model, "586");
1.17      cgd       362:                break;
                    363:        default:
1.104     cgd       364:                strcat(cpu_model, "unknown");   /* will panic below... */
1.148     mycroft   365:                break;
1.16      cgd       366:        }
1.104     cgd       367:        strcat(cpu_model, "-class CPU)");
                    368:        printf("%s\n", cpu_model);      /* cpu speed would be nice, but how? */
1.18      cgd       369:
1.16      cgd       370:        /*
                    371:         * Now that we have told the user what they have,
                    372:         * let them know if that machine type isn't configured.
                    373:         */
1.24      cgd       374:        switch (cpu_class) {
1.100     mycroft   375: #if !defined(I386_CPU) && !defined(I486_CPU) && !defined(I586_CPU)
                    376: #error No CPU classes configured.
                    377: #endif
1.118     mycroft   378: #if !defined(I586_CPU)
                    379:        case CPUCLASS_586:
                    380: #endif
                    381: #if defined(I486_CPU) && (!defined(I586_CPU))
                    382:                printf("NOTICE: lowering CPU class to i486\n");
                    383:                cpu_class = CPUCLASS_486;
                    384:                break;
1.16      cgd       385: #endif
                    386: #if !defined(I486_CPU)
1.18      cgd       387:        case CPUCLASS_486:
1.16      cgd       388: #endif
1.118     mycroft   389: #if defined(I386_CPU) && (!defined(I586_CPU) || !defined(I486_CPU))
                    390:                printf("NOTICE: lowering CPU class to i386\n");
                    391:                cpu_class = CPUCLASS_386;
                    392:                break;
                    393: #endif
                    394: #if !defined(I386_CPU)
                    395:        case CPUCLASS_386:
1.16      cgd       396: #endif
1.118     mycroft   397: #if !defined(I586_CPU) || !defined(I486_CPU) || !defined(I386_CPU)
1.100     mycroft   398:                panic("CPU class not configured");
1.59      mycroft   399: #endif
1.16      cgd       400:        default:
                    401:                break;
1.121     mycroft   402:        }
                    403:
                    404:        if (cpu == CPU_486DLC) {
                    405: #ifndef CYRIX_CACHE_WORKS
                    406:                printf("WARNING: CYRIX 486DLC CACHE UNCHANGED.\n");
                    407: #else
                    408: #ifndef CYRIX_CACHE_REALLY_WORKS
                    409:                printf("WARNING: CYRIX 486DLC CACHE ENABLED IN HOLD-FLUSH MODE.\n");
                    410: #else
                    411:                printf("WARNING: CYRIX 486DLC CACHE ENABLED.\n");
                    412: #endif
                    413: #endif
1.16      cgd       414:        }
1.147     mycroft   415:
                    416: #if defined(I486_CPU) || defined(I586_CPU)
                    417:        /*
                    418:         * On a 486 or above, enable ring 0 write protection and outer ring
                    419:         * alignment checking.
                    420:         */
                    421:        if (cpu_class >= CPUCLASS_486)
                    422:                lcr0(rcr0() | CR0_WP | CR0_AM);
                    423: #endif
1.1       cgd       424: }
                    425:
1.104     cgd       426: /*
                    427:  * machine dependent system variables.
                    428:  */
                    429: cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
                    430:        int *name;
                    431:        u_int namelen;
                    432:        void *oldp;
                    433:        size_t *oldlenp;
                    434:        void *newp;
                    435:        size_t newlen;
                    436:        struct proc *p;
                    437: {
                    438:        dev_t consdev;
                    439:
                    440:        /* all sysctl names at this level are terminal */
                    441:        if (namelen != 1)
                    442:                return (ENOTDIR);               /* overloaded */
                    443:
                    444:        switch (name[0]) {
                    445:        case CPU_CONSDEV:
                    446:                if (cn_tab != NULL)
                    447:                        consdev = cn_tab->cn_dev;
                    448:                else
                    449:                        consdev = NODEV;
                    450:                return (sysctl_rdstruct(oldp, oldlenp, newp, &consdev,
                    451:                    sizeof consdev));
                    452:        default:
                    453:                return (EOPNOTSUPP);
                    454:        }
                    455:        /* NOTREACHED */
                    456: }
                    457:
1.1       cgd       458: #ifdef PGINPROF
                    459: /*
1.59      mycroft   460:  * Return the difference (in microseconds) between the current time and a
                    461:  * previous time as represented by the arguments.  If there is a pending
                    462:  * clock interrupt which has not been serviced due to high ipl, return error
                    463:  * code.
1.1       cgd       464:  */
                    465: /*ARGSUSED*/
                    466: vmtime(otime, olbolt, oicr)
                    467:        register int otime, olbolt, oicr;
                    468: {
                    469:
1.59      mycroft   470:        return (((time.tv_sec-otime)*HZ + lbolt-olbolt)*(1000000/HZ));
1.1       cgd       471: }
                    472: #endif
                    473:
1.151     christos  474: #ifdef COMPAT_IBCS2
                    475: void
                    476: ibcs2_sendsig(catcher, sig, mask, code)
                    477:        sig_t catcher;
                    478:        int sig, mask;
                    479:        u_long code;
                    480: {
                    481:        sendsig(catcher, bsd2ibcs_sig(sig), mask, code);
                    482: }
                    483: #endif
                    484:
1.1       cgd       485: /*
                    486:  * Send an interrupt to process.
                    487:  *
                    488:  * Stack is set up to allow sigcode stored
                    489:  * in u. to call routine, followed by kcall
                    490:  * to sigreturn routine below.  After sigreturn
                    491:  * resets the signal mask, the stack, and the
                    492:  * frame pointer, it returns to the user
                    493:  * specified pc, psl.
                    494:  */
                    495: void
                    496: sendsig(catcher, sig, mask, code)
                    497:        sig_t catcher;
                    498:        int sig, mask;
1.126     cgd       499:        u_long code;
1.1       cgd       500: {
                    501:        register struct proc *p = curproc;
1.59      mycroft   502:        register struct trapframe *tf;
1.82      ws        503:        struct sigframe *fp, frame;
1.104     cgd       504:        struct sigacts *psp = p->p_sigacts;
1.48      brezak    505:        int oonstack;
1.22      cgd       506:        extern char sigcode[], esigcode[];
1.1       cgd       507:
1.135     christos  508:        /*
                    509:         * Build the argument list for the signal handler.
                    510:         */
1.151     christos  511:        frame.sf_signum = sig;
1.135     christos  512:
1.154     mycroft   513:        tf = p->p_md.md_regs;
1.104     cgd       514:        oonstack = psp->ps_sigstk.ss_flags & SA_ONSTACK;
1.135     christos  515:
1.1       cgd       516:        /*
1.82      ws        517:         * Allocate space for the signal handler context.
1.1       cgd       518:         */
1.105     mycroft   519:        if ((psp->ps_flags & SAS_ALTSTACK) && !oonstack &&
1.104     cgd       520:            (psp->ps_sigonstack & sigmask(sig))) {
                    521:                fp = (struct sigframe *)(psp->ps_sigstk.ss_base +
                    522:                    psp->ps_sigstk.ss_size - sizeof(struct sigframe));
                    523:                psp->ps_sigstk.ss_flags |= SA_ONSTACK;
1.1       cgd       524:        } else {
1.91      mycroft   525:                fp = (struct sigframe *)tf->tf_esp - 1;
1.1       cgd       526:        }
                    527:
1.82      ws        528:        frame.sf_code = code;
                    529:        frame.sf_scp = &fp->sf_sc;
                    530:        frame.sf_handler = catcher;
                    531:
                    532:        /*
                    533:         * Build the signal context to be used by sigreturn.
                    534:         */
                    535:        frame.sf_sc.sc_onstack = oonstack;
                    536:        frame.sf_sc.sc_mask = mask;
1.157     mycroft   537: #ifdef VM86
                    538:        if (tf->tf_eflags & PSL_VM) {
                    539:                frame.sf_sc.sc_gs = tf->tf_vm86_gs;
                    540:                frame.sf_sc.sc_fs = tf->tf_vm86_fs;
                    541:                frame.sf_sc.sc_es = tf->tf_vm86_es;
                    542:                frame.sf_sc.sc_ds = tf->tf_vm86_ds;
                    543:        } else
                    544: #endif
                    545:        {
                    546:                __asm("movl %%gs,%w0" : "=r" (frame.sf_sc.sc_gs));
                    547:                __asm("movl %%fs,%w0" : "=r" (frame.sf_sc.sc_fs));
                    548:                frame.sf_sc.sc_es = tf->tf_es;
                    549:                frame.sf_sc.sc_ds = tf->tf_ds;
                    550:        }
1.122     mycroft   551:        frame.sf_sc.sc_edi    = tf->tf_edi;
                    552:        frame.sf_sc.sc_esi    = tf->tf_esi;
                    553:        frame.sf_sc.sc_ebp    = tf->tf_ebp;
                    554:        frame.sf_sc.sc_ebx    = tf->tf_ebx;
                    555:        frame.sf_sc.sc_edx    = tf->tf_edx;
                    556:        frame.sf_sc.sc_ecx    = tf->tf_ecx;
                    557:        frame.sf_sc.sc_eax    = tf->tf_eax;
                    558:        frame.sf_sc.sc_eip    = tf->tf_eip;
                    559:        frame.sf_sc.sc_cs     = tf->tf_cs;
                    560:        frame.sf_sc.sc_eflags = tf->tf_eflags;
                    561:        frame.sf_sc.sc_esp    = tf->tf_esp;
                    562:        frame.sf_sc.sc_ss     = tf->tf_ss;
1.1       cgd       563:
1.87      mycroft   564:        if (copyout(&frame, fp, sizeof(frame)) != 0) {
1.1       cgd       565:                /*
                    566:                 * Process has trashed its stack; give it an illegal
                    567:                 * instruction to halt it in its tracks.
                    568:                 */
1.93      mycroft   569:                sigexit(p, SIGILL);
                    570:                /* NOTREACHED */
1.1       cgd       571:        }
                    572:
1.73      mycroft   573:        /*
1.59      mycroft   574:         * Build context to run handler in.
                    575:         */
                    576:        tf->tf_esp = (int)fp;
                    577:        tf->tf_eip = (int)(((char *)PS_STRINGS) - (esigcode - sigcode));
1.154     mycroft   578: #ifdef VM86
1.59      mycroft   579:        tf->tf_eflags &= ~PSL_VM;
1.154     mycroft   580: #endif
                    581:        tf->tf_cs = LSEL(LUCODE_SEL, SEL_UPL);
                    582:        tf->tf_ds = LSEL(LUDATA_SEL, SEL_UPL);
                    583:        tf->tf_es = LSEL(LUDATA_SEL, SEL_UPL);
                    584:        tf->tf_ss = LSEL(LUDATA_SEL, SEL_UPL);
1.1       cgd       585: }
                    586:
                    587: /*
                    588:  * System call to cleanup state after a signal
                    589:  * has been taken.  Reset signal mask and
                    590:  * stack state from context left by sendsig (above).
                    591:  * Return to previous pc and psl as specified by
                    592:  * context left by sendsig. Check carefully to
                    593:  * make sure that the user has not modified the
1.110     mycroft   594:  * psl to gain improper privileges or to cause
1.1       cgd       595:  * a machine fault.
                    596:  */
                    597: sigreturn(p, uap, retval)
                    598:        struct proc *p;
1.123     cgd       599:        struct sigreturn_args /* {
                    600:                syscallarg(struct sigcontext *) sigcntxp;
                    601:        } */ *uap;
                    602:        register_t *retval;
1.1       cgd       603: {
1.82      ws        604:        struct sigcontext *scp, context;
1.59      mycroft   605:        register struct trapframe *tf;
                    606:
1.154     mycroft   607:        tf = p->p_md.md_regs;
1.1       cgd       608:
1.27      cgd       609:        /*
1.59      mycroft   610:         * The trampoline code hands us the context.
                    611:         * It is unsafe to keep track of it ourselves, in the event that a
                    612:         * program jumps out of a signal handler.
1.27      cgd       613:         */
1.123     cgd       614:        scp = SCARG(uap, sigcntxp);
1.87      mycroft   615:        if (copyin((caddr_t)scp, &context, sizeof(*scp)) != 0)
1.122     mycroft   616:                return (EFAULT);
1.1       cgd       617:
1.74      brezak    618:        /*
1.154     mycroft   619:         * Check for security violations.  If we're returning to protected
                    620:         * mode, the CPU will validate the segment registers automatically
                    621:         * and generate a trap on violations.  We handle the trap, rather
                    622:         * than doing all of the checking here.
1.136     mycroft   623:         */
                    624:        if (((context.sc_eflags ^ tf->tf_eflags) & PSL_USERSTATIC) != 0 ||
                    625:            ISPL(context.sc_cs) != SEL_UPL)
1.122     mycroft   626:                return (EINVAL);
1.59      mycroft   627:
1.104     cgd       628:        if (context.sc_onstack & 01)
                    629:                p->p_sigacts->ps_sigstk.ss_flags |= SA_ONSTACK;
                    630:        else
                    631:                p->p_sigacts->ps_sigstk.ss_flags &= ~SA_ONSTACK;
1.131     mycroft   632:        p->p_sigmask = context.sc_mask & ~sigcantmask;
1.49      brezak    633:
1.59      mycroft   634:        /*
                    635:         * Restore signal context.
                    636:         */
1.157     mycroft   637: #ifdef VM86
                    638:        if (context.sc_eflags & PSL_VM) {
                    639:                tf->tf_vm86_gs = context.sc_gs;
                    640:                tf->tf_vm86_fs = context.sc_fs;
                    641:                tf->tf_vm86_es = context.sc_es;
                    642:                tf->tf_vm86_ds = context.sc_ds;
                    643:        } else
                    644: #endif
                    645:        {
                    646:                /* %fs and %gs were restored by the trampoline. */
                    647:                tf->tf_es = context.sc_es;
                    648:                tf->tf_ds = context.sc_ds;
                    649:        }
1.122     mycroft   650:        tf->tf_edi    = context.sc_edi;
                    651:        tf->tf_esi    = context.sc_esi;
                    652:        tf->tf_ebp    = context.sc_ebp;
                    653:        tf->tf_ebx    = context.sc_ebx;
                    654:        tf->tf_edx    = context.sc_edx;
                    655:        tf->tf_ecx    = context.sc_ecx;
                    656:        tf->tf_eax    = context.sc_eax;
                    657:        tf->tf_eip    = context.sc_eip;
                    658:        tf->tf_cs     = context.sc_cs;
1.136     mycroft   659:        tf->tf_eflags = context.sc_eflags;
1.122     mycroft   660:        tf->tf_esp    = context.sc_esp;
                    661:        tf->tf_ss     = context.sc_ss;
1.72      mycroft   662:
1.122     mycroft   663:        return (EJUSTRETURN);
1.37      cgd       664: }
                    665:
1.1       cgd       666: int    waittime = -1;
                    667: struct pcb dumppcb;
                    668:
1.32      andrew    669: void
1.106     mycroft   670: boot(howto)
                    671:        register int howto;
1.1       cgd       672: {
                    673:        extern int cold;
                    674:
1.106     mycroft   675:        if (cold) {
1.1       cgd       676:                printf("hit reset please");
                    677:                for(;;);
                    678:        }
1.106     mycroft   679:        boothowto = howto;
1.101     cgd       680:        if ((howto&RB_NOSYNC) == 0 && waittime < 0) {
1.1       cgd       681:                waittime = 0;
1.150     mycroft   682:                vfs_shutdown();
1.59      mycroft   683:                /*
                    684:                 * If we've been adjusting the clock, the todr
                    685:                 * will be out of synch; adjust it now.
                    686:                 */
                    687:                resettodr();
1.1       cgd       688:        }
                    689:        splhigh();
1.152     cgd       690:        if (howto & RB_HALT) {
1.25      cgd       691:                printf("\n");
                    692:                printf("The operating system has halted.\n");
                    693:                printf("Please press any key to reboot.\n\n");
1.12      cgd       694:                cngetc();
1.1       cgd       695:        } else {
                    696:                if (howto & RB_DUMP) {
                    697:                        savectx(&dumppcb, 0);
1.154     mycroft   698:                        dumppcb.pcb_cr3 = rcr3();
1.73      mycroft   699:                        dumpsys();
1.1       cgd       700:                }
                    701:        }
1.110     mycroft   702:        printf("rebooting...\n");
1.1       cgd       703:        cpu_reset();
                    704:        for(;;) ;
                    705:        /*NOTREACHED*/
                    706: }
                    707:
1.116     gwr       708: /*
                    709:  * These variables are needed by /sbin/savecore
                    710:  */
                    711: u_long dumpmag = 0x8fca0101;   /* magic number */
                    712: int    dumpsize = 0;           /* pages */
                    713: long   dumplo = 0;             /* blocks */
                    714:
                    715: /*
1.134     mycroft   716:  * This is called by configure to set dumplo and dumpsize.
1.116     gwr       717:  * Dumps always skip the first CLBYTES of disk space
                    718:  * in case there might be a disk label stored there.
                    719:  * If there is extra space, put dump at the end to
                    720:  * reduce the chance that swapping trashes it.
                    721:  */
                    722: void
                    723: dumpconf()
                    724: {
                    725:        int nblks;      /* size of dump area */
                    726:        int maj;
                    727:
                    728:        if (dumpdev == NODEV)
                    729:                return;
                    730:        maj = major(dumpdev);
                    731:        if (maj < 0 || maj >= nblkdev)
                    732:                panic("dumpconf: bad dumpdev=0x%x", dumpdev);
1.134     mycroft   733:        if (bdevsw[maj].d_psize == NULL)
1.116     gwr       734:                return;
1.134     mycroft   735:        nblks = (*bdevsw[maj].d_psize)(dumpdev);
1.116     gwr       736:        if (nblks <= ctod(1))
                    737:                return;
                    738:
1.134     mycroft   739:        dumpsize = physmem;
1.116     gwr       740:
1.134     mycroft   741:        /* Always skip the first CLBYTES, in case there is a label there. */
                    742:        if (dumplo < ctod(1))
1.116     gwr       743:                dumplo = ctod(1);
1.134     mycroft   744:
                    745:        /* Put dump at end of partition, and make it fit. */
                    746:        if (dumpsize > dtoc(nblks - dumplo))
1.116     gwr       747:                dumpsize = dtoc(nblks - dumplo);
1.134     mycroft   748:        if (dumplo < nblks - ctod(dumpsize))
                    749:                dumplo = nblks - ctod(dumpsize);
1.116     gwr       750: }
                    751:
1.1       cgd       752: /*
                    753:  * Doadump comes here after turning off memory management and
                    754:  * getting on the dump stack, either when called above, or by
                    755:  * the auto-restart code.
                    756:  */
1.32      andrew    757: void
1.1       cgd       758: dumpsys()
                    759: {
                    760:
1.141     mycroft   761:        msgbufmapped = 0;
1.1       cgd       762:        if (dumpdev == NODEV)
                    763:                return;
1.134     mycroft   764:        if (dumpsize == 0) {
                    765:                dumpconf();
                    766:                if (dumpsize == 0)
                    767:                        return;
                    768:        }
1.35      cgd       769:        printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo);
1.134     mycroft   770:
1.35      cgd       771:        printf("dump ");
1.1       cgd       772:        switch ((*bdevsw[major(dumpdev)].d_dump)(dumpdev)) {
                    773:
                    774:        case ENXIO:
1.35      cgd       775:                printf("device bad\n");
1.1       cgd       776:                break;
                    777:
                    778:        case EFAULT:
1.35      cgd       779:                printf("device not ready\n");
1.1       cgd       780:                break;
                    781:
                    782:        case EINVAL:
1.35      cgd       783:                printf("area improper\n");
1.1       cgd       784:                break;
                    785:
                    786:        case EIO:
1.35      cgd       787:                printf("i/o error\n");
1.1       cgd       788:                break;
                    789:
                    790:        case EINTR:
1.35      cgd       791:                printf("aborted from console\n");
1.1       cgd       792:                break;
                    793:
                    794:        default:
1.35      cgd       795:                printf("succeeded\n");
1.1       cgd       796:                break;
                    797:        }
1.35      cgd       798:        printf("\n\n");
1.90      mycroft   799:        delay(1000);
1.1       cgd       800: }
                    801:
1.3       cgd       802: #ifdef HZ
1.7       cgd       803: /*
                    804:  * If HZ is defined we use this code, otherwise the code in
1.59      mycroft   805:  * /sys/i386/i386/microtime.s is used.  The other code only works
1.7       cgd       806:  * for HZ=100.
                    807:  */
1.1       cgd       808: microtime(tvp)
                    809:        register struct timeval *tvp;
                    810: {
                    811:        int s = splhigh();
                    812:
                    813:        *tvp = time;
                    814:        tvp->tv_usec += tick;
1.59      mycroft   815:        splx(s);
1.1       cgd       816:        while (tvp->tv_usec > 1000000) {
                    817:                tvp->tv_sec++;
                    818:                tvp->tv_usec -= 1000000;
                    819:        }
                    820: }
1.7       cgd       821: #endif /* HZ */
1.1       cgd       822:
                    823: /*
                    824:  * Clear registers on exec
                    825:  */
1.33      cgd       826: void
1.151     christos  827: setregs(p, pack, stack, retval)
1.1       cgd       828:        struct proc *p;
1.151     christos  829:        struct exec_package *pack;
1.21      cgd       830:        u_long stack;
1.123     cgd       831:        register_t *retval;
1.1       cgd       832: {
1.154     mycroft   833:        register struct pcb *pcb;
1.59      mycroft   834:        register struct trapframe *tf;
1.1       cgd       835:
1.153     mycroft   836:        pcb = &p->p_addr->u_pcb;
1.161     mycroft   837:        lcr0(pcb->pcb_cr0 |= CR0_EM|CR0_TS);
1.153     mycroft   838:        pcb->pcb_flags = 0;
1.161     mycroft   839:
                    840: #if NNPX > 0
                    841:        /* If we were using the FPU, forget about it. */
                    842:        if (npxproc == p)
                    843:                npxproc = 0;
                    844: #endif
1.59      mycroft   845:
1.154     mycroft   846:        tf = p->p_md.md_regs;
                    847:        tf->tf_es = LSEL(LUDATA_SEL, SEL_UPL);
                    848:        tf->tf_ds = LSEL(LUDATA_SEL, SEL_UPL);
                    849:        tf->tf_ebp = 0;
1.160     mycroft   850:        tf->tf_ebx = (int)PS_STRINGS;
1.154     mycroft   851:        tf->tf_eip = pack->ep_entry;
                    852:        tf->tf_cs = LSEL(LUCODE_SEL, SEL_UPL);
                    853:        tf->tf_eflags = PSL_USERSET;
                    854:        tf->tf_esp = stack;
                    855:        tf->tf_ss = LSEL(LUDATA_SEL, SEL_UPL);
                    856:
1.59      mycroft   857:        retval[1] = 0;
1.1       cgd       858: }
                    859:
                    860: /*
                    861:  * Initialize 386 and configure to run kernel
                    862:  */
                    863:
                    864: /*
1.55      brezak    865:  * Initialize segments and descriptor tables
1.1       cgd       866:  */
                    867:
1.59      mycroft   868: union descriptor gdt[NGDT];
                    869: union descriptor ldt[NLDT];
                    870: struct gate_descriptor idt[NIDT];
1.49      brezak    871:
1.156     mycroft   872: int currentldt;
1.49      brezak    873:
1.154     mycroft   874: struct i386tss tss;
1.1       cgd       875:
                    876: extern  struct user *proc0paddr;
                    877:
1.40      andrew    878: /* software prototypes -- in more palatable form */
1.1       cgd       879: struct soft_segment_descriptor gdt_segs[] = {
1.154     mycroft   880:        /* Null descriptor */
1.155     mycroft   881: {      0x0,                    /* segment base address */
1.40      andrew    882:        0x0,                    /* length */
1.1       cgd       883:        0,                      /* segment type */
1.155     mycroft   884:        0,                      /* segment descriptor privilege level */
1.1       cgd       885:        0,                      /* segment descriptor present */
1.40      andrew    886:        0, 0,
1.1       cgd       887:        0,                      /* default 32 vs 16 bit size */
1.155     mycroft   888:        0                       /* limit granularity (byte/page units) */ },
1.154     mycroft   889:        /* Kernel code descriptor */
1.155     mycroft   890: {      0x0,                    /* segment base address */
1.1       cgd       891:        0xfffff,                /* length - all address space */
                    892:        SDT_MEMERA,             /* segment type */
1.155     mycroft   893:        SEL_KPL,                /* segment descriptor privilege level */
1.1       cgd       894:        1,                      /* segment descriptor present */
1.40      andrew    895:        0, 0,
1.1       cgd       896:        1,                      /* default 32 vs 16 bit size */
1.155     mycroft   897:        1                       /* limit granularity (byte/page units) */ },
1.154     mycroft   898:        /* Kernel data descriptor */
1.155     mycroft   899: {      0x0,                    /* segment base address */
1.1       cgd       900:        0xfffff,                /* length - all address space */
                    901:        SDT_MEMRWA,             /* segment type */
1.155     mycroft   902:        SEL_KPL,                /* segment descriptor privilege level */
1.1       cgd       903:        1,                      /* segment descriptor present */
1.40      andrew    904:        0, 0,
1.1       cgd       905:        1,                      /* default 32 vs 16 bit size */
1.155     mycroft   906:        1                       /* limit granularity (byte/page units) */ },
1.159     mycroft   907:        /* LDT descriptor */
1.155     mycroft   908: {      (int) ldt,              /* segment base address */
1.1       cgd       909:        sizeof(ldt)-1,          /* length - all address space */
                    910:        SDT_SYSLDT,             /* segment type */
1.155     mycroft   911:        0,                      /* segment descriptor privilege level */
1.1       cgd       912:        1,                      /* segment descriptor present */
1.40      andrew    913:        0, 0,
1.1       cgd       914:        0,                      /* unused - default 32 vs 16 bit size */
1.155     mycroft   915:        0                       /* limit granularity (byte/page units) */ },
1.159     mycroft   916:        /* User code descriptor */
                    917: {      0x0,                    /* segment base address */
                    918:        0xfffff,                /* length - all address space */
                    919:        SDT_MEMERA,             /* segment type */
                    920:        SEL_UPL,                /* segment descriptor privilege level */
                    921:        1,                      /* segment descriptor present */
                    922:        0, 0,
                    923:        1,                      /* default 32 vs 16 bit size */
                    924:        1                       /* limit granularity (byte/page units) */ },
                    925:        /* User data descriptor */
                    926: {      0x0,                    /* segment base address */
                    927:        0xfffff,                /* length - all address space */
                    928:        SDT_MEMRWA,             /* segment type */
                    929:        SEL_UPL,                /* segment descriptor privilege level */
                    930:        1,                      /* segment descriptor present */
                    931:        0, 0,
                    932:        1,                      /* default 32 vs 16 bit size */
                    933:        1                       /* limit granularity (byte/page units) */ },
                    934:        /* Proc 0 TSS descriptor */
1.155     mycroft   935: {      (int) USRSTACK,         /* segment base address */
1.1       cgd       936:        sizeof(tss)-1,          /* length - all address space */
                    937:        SDT_SYS386TSS,          /* segment type */
1.155     mycroft   938:        SEL_KPL,                /* segment descriptor privilege level */
1.1       cgd       939:        1,                      /* segment descriptor present */
1.40      andrew    940:        0, 0,
1.1       cgd       941:        0,                      /* unused - default 32 vs 16 bit size */
1.155     mycroft   942:        0                       /* limit granularity (byte/page units) */ },
1.159     mycroft   943:        /* User LDT descriptor per process */
1.155     mycroft   944: {      (int) ldt,              /* segment base address */
1.49      brezak    945:        (512 * sizeof(union descriptor)-1),             /* length */
                    946:        SDT_SYSLDT,             /* segment type */
1.155     mycroft   947:        0,                      /* segment descriptor privilege level */
1.49      brezak    948:        1,                      /* segment descriptor present */
                    949:        0, 0,
                    950:        0,                      /* unused - default 32 vs 16 bit size */
1.155     mycroft   951:        0                       /* limit granularity (byte/page units) */ },
1.49      brezak    952: };
1.1       cgd       953:
                    954: struct soft_segment_descriptor ldt_segs[] = {
1.159     mycroft   955:        /* Null descriptor - overwritten by call gate */
1.155     mycroft   956: {      0x0,                    /* segment base address */
1.40      andrew    957:        0x0,                    /* length */
1.1       cgd       958:        0,                      /* segment type */
1.155     mycroft   959:        0,                      /* segment descriptor privilege level */
1.1       cgd       960:        0,                      /* segment descriptor present */
1.40      andrew    961:        0, 0,
1.1       cgd       962:        0,                      /* default 32 vs 16 bit size */
1.155     mycroft   963:        0                       /* limit granularity (byte/page units) */ },
1.159     mycroft   964:        /* Null descriptor - overwritten by call gate */
1.155     mycroft   965: {      0x0,                    /* segment base address */
1.40      andrew    966:        0x0,                    /* length */
1.1       cgd       967:        0,                      /* segment type */
1.155     mycroft   968:        0,                      /* segment descriptor privilege level */
1.1       cgd       969:        0,                      /* segment descriptor present */
1.40      andrew    970:        0, 0,
1.1       cgd       971:        0,                      /* default 32 vs 16 bit size */
1.155     mycroft   972:        0                       /* limit granularity (byte/page units) */ },
1.154     mycroft   973:        /* User code descriptor */
1.155     mycroft   974: {      0x0,                    /* segment base address */
1.1       cgd       975:        0xfffff,                /* length - all address space */
                    976:        SDT_MEMERA,             /* segment type */
1.155     mycroft   977:        SEL_UPL,                /* segment descriptor privilege level */
1.1       cgd       978:        1,                      /* segment descriptor present */
1.40      andrew    979:        0, 0,
1.1       cgd       980:        1,                      /* default 32 vs 16 bit size */
1.155     mycroft   981:        1                       /* limit granularity (byte/page units) */ },
1.154     mycroft   982:        /* User data descriptor */
1.155     mycroft   983: {      0x0,                    /* segment base address */
1.1       cgd       984:        0xfffff,                /* length - all address space */
                    985:        SDT_MEMRWA,             /* segment type */
1.155     mycroft   986:        SEL_UPL,                /* segment descriptor privilege level */
1.1       cgd       987:        1,                      /* segment descriptor present */
1.40      andrew    988:        0, 0,
1.1       cgd       989:        1,                      /* default 32 vs 16 bit size */
1.159     mycroft   990:        1                       /* limit granularity (byte/page units) */ },
                    991: };
1.1       cgd       992:
1.59      mycroft   993: void
1.124     mycroft   994: setgate(gdp, func, args, typ, dpl)
                    995:        struct gate_descriptor *gdp;
                    996:        void *func;
                    997:        int args, typ, dpl;
1.59      mycroft   998: {
1.1       cgd       999:
1.124     mycroft  1000:        gdp->gd_looffset = (int)func;
                   1001:        gdp->gd_selector = GSEL(GCODE_SEL, SEL_KPL);
                   1002:        gdp->gd_stkcpy = args;
                   1003:        gdp->gd_xx = 0;
                   1004:        gdp->gd_type = typ;
                   1005:        gdp->gd_dpl = dpl;
                   1006:        gdp->gd_p = 1;
                   1007:        gdp->gd_hioffset = (int)func >> 16;
1.1       cgd      1008: }
                   1009:
                   1010: #define        IDTVEC(name)    __CONCAT(X, name)
1.124     mycroft  1011: extern IDTVEC(div),     IDTVEC(dbg),     IDTVEC(nmi),     IDTVEC(bpt),
                   1012:        IDTVEC(ofl),     IDTVEC(bnd),     IDTVEC(ill),     IDTVEC(dna),
                   1013:        IDTVEC(dble),    IDTVEC(fpusegm), IDTVEC(tss),     IDTVEC(missing),
                   1014:        IDTVEC(stk),     IDTVEC(prot),    IDTVEC(page),    IDTVEC(rsvd),
                   1015:        IDTVEC(fpu),     IDTVEC(align),
                   1016:        IDTVEC(syscall), IDTVEC(osyscall);
1.1       cgd      1017:
1.59      mycroft  1018: void
1.129     mycroft  1019: sdtossd(sd, ssd)
                   1020:        struct segment_descriptor *sd;
                   1021:        struct soft_segment_descriptor *ssd;
                   1022: {
1.148     mycroft  1023:
1.129     mycroft  1024:        ssd->ssd_base = (sd->sd_hibase << 24) | sd->sd_lobase;
                   1025:        ssd->ssd_limit = (sd->sd_hilimit << 16) | sd->sd_lolimit;
                   1026:        ssd->ssd_type = sd->sd_type;
                   1027:        ssd->ssd_dpl = sd->sd_dpl;
                   1028:        ssd->ssd_p = sd->sd_p;
                   1029:        ssd->ssd_def32 = sd->sd_def32;
                   1030:        ssd->ssd_gran = sd->sd_gran;
                   1031: }
                   1032:
                   1033: void
                   1034: ssdtosd(ssd, sd)
                   1035:        struct soft_segment_descriptor *ssd;
                   1036:        struct segment_descriptor *sd;
                   1037: {
1.148     mycroft  1038:
1.129     mycroft  1039:        sd->sd_lobase = ssd->ssd_base;
                   1040:        sd->sd_hibase = ssd->ssd_base >> 24;
                   1041:        sd->sd_lolimit = ssd->ssd_limit;
                   1042:        sd->sd_hilimit = ssd->ssd_limit >> 16;
                   1043:        sd->sd_type = ssd->ssd_type;
                   1044:        sd->sd_dpl = ssd->ssd_dpl;
                   1045:        sd->sd_p = ssd->ssd_p;
                   1046:        sd->sd_def32 = ssd->ssd_def32;
                   1047:        sd->sd_gran = ssd->ssd_gran;
                   1048: }
                   1049:
                   1050: void
1.43      brezak   1051: init386(first_avail)
                   1052:        vm_offset_t first_avail;
1.2       cgd      1053: {
1.148     mycroft  1054:        struct pcb *pcb;
1.132     mycroft  1055:        int x;
1.1       cgd      1056:        unsigned biosbasemem, biosextmem;
1.148     mycroft  1057:        struct region_descriptor region;
1.132     mycroft  1058:        extern char etext[], sigcode[], esigcode[];
1.148     mycroft  1059:        extern void consinit __P((void));
1.154     mycroft  1060:        extern void lgdt();
1.1       cgd      1061:
                   1062:        proc0.p_addr = proc0paddr;
                   1063:
1.84      cgd      1064:        consinit();     /* XXX SHOULD NOT BE DONE HERE */
1.1       cgd      1065:
1.148     mycroft  1066:        /* Set up proc 0's PCB and TSS. */
                   1067:        curpcb = pcb = &proc0.p_addr->u_pcb;
                   1068:        pcb->pcb_flags = 0;
                   1069:        pcb->pcb_tss.tss_esp0 = (int)USRSTACK + USPACE;
                   1070:        pcb->pcb_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL);
                   1071:        pcb->pcb_tss.tss_ioopt = sizeof(struct i386tss) << 16;
                   1072:
1.154     mycroft  1073:
1.148     mycroft  1074: #ifndef LKM
1.59      mycroft  1075:        /* set code segment limit to end of kernel text */
                   1076:        gdt_segs[GCODE_SEL].ssd_limit = i386_btop(i386_round_page(&etext)) - 1;
1.28      cgd      1077: #endif
1.59      mycroft  1078:        for (x = 0; x < NGDT; x++)
1.144     mycroft  1079:                ssdtosd(&gdt_segs[x], &gdt[x].sd);
1.59      mycroft  1080:
1.1       cgd      1081:        /* make ldt memory segments */
1.59      mycroft  1082:        ldt_segs[LUCODE_SEL].ssd_limit = i386_btop(VM_MAXUSER_ADDRESS) - 1;
                   1083:        ldt_segs[LUDATA_SEL].ssd_limit = i386_btop(VM_MAXUSER_ADDRESS) - 1;
                   1084:        for (x = 0; x < NLDT; x++)
1.144     mycroft  1085:                ssdtosd(&ldt_segs[x], &ldt[x].sd);
1.1       cgd      1086:
1.148     mycroft  1087:        /* Set up the old-style call gate descriptor for system calls. */
                   1088:        setgate(&ldt[LSYS5CALLS_SEL].gd, &IDTVEC(osyscall), 1, SDT_SYS386CGT,
                   1089:            SEL_UPL);
                   1090:
1.1       cgd      1091:        /* exceptions */
1.124     mycroft  1092:        for (x = 0; x < NIDT; x++)
                   1093:                setgate(&idt[x], &IDTVEC(rsvd), 0, SDT_SYS386TGT, SEL_KPL);
                   1094:        setgate(&idt[  0], &IDTVEC(div),     0, SDT_SYS386TGT, SEL_KPL);
                   1095:        setgate(&idt[  1], &IDTVEC(dbg),     0, SDT_SYS386TGT, SEL_KPL);
                   1096:        setgate(&idt[  2], &IDTVEC(nmi),     0, SDT_SYS386TGT, SEL_KPL);
                   1097:        setgate(&idt[  3], &IDTVEC(bpt),     0, SDT_SYS386TGT, SEL_UPL);
                   1098:        setgate(&idt[  4], &IDTVEC(ofl),     0, SDT_SYS386TGT, SEL_KPL);
                   1099:        setgate(&idt[  5], &IDTVEC(bnd),     0, SDT_SYS386TGT, SEL_KPL);
                   1100:        setgate(&idt[  6], &IDTVEC(ill),     0, SDT_SYS386TGT, SEL_KPL);
                   1101:        setgate(&idt[  7], &IDTVEC(dna),     0, SDT_SYS386TGT, SEL_KPL);
                   1102:        setgate(&idt[  8], &IDTVEC(dble),    0, SDT_SYS386TGT, SEL_KPL);
                   1103:        setgate(&idt[  9], &IDTVEC(fpusegm), 0, SDT_SYS386TGT, SEL_KPL);
                   1104:        setgate(&idt[ 10], &IDTVEC(tss),     0, SDT_SYS386TGT, SEL_KPL);
                   1105:        setgate(&idt[ 11], &IDTVEC(missing), 0, SDT_SYS386TGT, SEL_KPL);
                   1106:        setgate(&idt[ 12], &IDTVEC(stk),     0, SDT_SYS386TGT, SEL_KPL);
                   1107:        setgate(&idt[ 13], &IDTVEC(prot),    0, SDT_SYS386TGT, SEL_KPL);
                   1108:        setgate(&idt[ 14], &IDTVEC(page),    0, SDT_SYS386TGT, SEL_KPL);
                   1109:        setgate(&idt[ 16], &IDTVEC(fpu),     0, SDT_SYS386TGT, SEL_KPL);
                   1110:        setgate(&idt[ 17], &IDTVEC(align),   0, SDT_SYS386TGT, SEL_KPL);
                   1111:        setgate(&idt[128], &IDTVEC(syscall), 0, SDT_SYS386TGT, SEL_UPL);
1.1       cgd      1112:
1.95      mycroft  1113: #if NISA > 0
1.1       cgd      1114:        isa_defaultirq();
                   1115: #endif
1.124     mycroft  1116:
1.148     mycroft  1117:        region.rd_limit = sizeof(gdt)-1;
                   1118:        region.rd_base = (int) gdt;
                   1119:        lgdt(&region);
                   1120:        region.rd_limit = sizeof(idt)-1;
                   1121:        region.rd_base = (int) idt;
                   1122:        lidt(&region);
1.1       cgd      1123:
1.124     mycroft  1124:        splhigh();
                   1125:        enable_intr();
                   1126:
1.5       glass    1127: #ifdef DDB
1.42      brezak   1128:        ddb_init();
1.1       cgd      1129:        if (boothowto & RB_KDB)
                   1130:                Debugger();
                   1131: #endif
1.43      brezak   1132: #ifdef KGDB
                   1133:        if (boothowto & RB_KDB)
1.59      mycroft  1134:                kgdb_connect(0);
1.43      brezak   1135: #endif
1.1       cgd      1136:
1.59      mycroft  1137:        /*
                   1138:         * Use BIOS values stored in RTC CMOS RAM, since probing
1.1       cgd      1139:         * breaks certain 386 AT relics.
                   1140:         */
1.158     cgd      1141:        biosbasemem = (mc146818_read(NULL, NVRAM_BASEHI) << 8) |
                   1142:            mc146818_read(NULL, NVRAM_BASELO);
                   1143:        biosextmem = (mc146818_read(NULL, NVRAM_EXTHI) << 8) |
                   1144:            mc146818_read(NULL, NVRAM_EXTLO);
1.138     mycroft  1145:
1.148     mycroft  1146:        /* Round down to whole pages. */
1.138     mycroft  1147:        biosbasemem &= -(NBPG / 1024);
                   1148:        biosextmem &= -(NBPG / 1024);
1.59      mycroft  1149:
                   1150:        avail_start = NBPG;     /* BIOS leaves data in low memory */
1.43      brezak   1151:                                /* and VM system doesn't work with phys 0 */
1.59      mycroft  1152:        avail_end = biosextmem ? IOM_END + biosextmem * 1024
1.73      mycroft  1153:            : biosbasemem * 1024;
                   1154:
1.59      mycroft  1155:        /* number of pages of physmem addr space */
                   1156:        physmem = btoc((biosbasemem + biosextmem) * 1024);
1.2       cgd      1157:
1.43      brezak   1158:        /*
1.59      mycroft  1159:         * Initialize for pmap_free_pages and pmap_next_page.
                   1160:         * These guys should be page-aligned.
1.43      brezak   1161:         */
                   1162:        hole_start = biosbasemem * 1024;
1.59      mycroft  1163:        /* we load right after the I/O hole; adjust hole_end to compensate */
1.148     mycroft  1164:        hole_end = round_page(first_avail);
1.43      brezak   1165:        avail_next = avail_start;
1.73      mycroft  1166:
1.139     mycroft  1167:        if (physmem < btoc(2 * 1024 * 1024)) {
1.59      mycroft  1168:                printf("warning: too little memory available; running in degraded mode\n"
1.73      mycroft  1169:                    "press a key to confirm\n\n");
1.20      deraadt  1170:                cngetc();
1.2       cgd      1171:        }
1.59      mycroft  1172:
1.1       cgd      1173:        /* call pmap initialization to make new kernel address space */
1.59      mycroft  1174:        pmap_bootstrap((vm_offset_t)atdevbase + IOM_SIZE);
1.73      mycroft  1175:
1.156     mycroft  1176:        ltr(GSEL(GPROC0_SEL, SEL_KPL));
                   1177:        lldt(currentldt = GSEL(GLDT_SEL, SEL_KPL));
1.1       cgd      1178: }
                   1179:
1.94      mycroft  1180: struct queue {
                   1181:        struct queue *q_next, *q_prev;
                   1182: };
                   1183:
1.1       cgd      1184: /*
1.73      mycroft  1185:  * insert an element into a queue
1.1       cgd      1186:  */
1.94      mycroft  1187: void
                   1188: _insque(elem, head)
                   1189:        register struct queue *elem, *head;
                   1190: {
                   1191:        register struct queue *next;
                   1192:
                   1193:        next = head->q_next;
                   1194:        elem->q_next = next;
                   1195:        head->q_next = elem;
                   1196:        elem->q_prev = head;
                   1197:        next->q_prev = elem;
1.1       cgd      1198: }
                   1199:
                   1200: /*
                   1201:  * remove an element from a queue
                   1202:  */
1.94      mycroft  1203: void
                   1204: _remque(elem)
                   1205:        register struct queue *elem;
                   1206: {
                   1207:        register struct queue *next, *prev;
                   1208:
                   1209:        next = elem->q_next;
                   1210:        prev = elem->q_prev;
                   1211:        next->q_prev = prev;
                   1212:        prev->q_next = next;
                   1213:        elem->q_prev = 0;
1.1       cgd      1214: }
                   1215:
1.107     deraadt  1216:
                   1217: #ifdef COMPAT_NOMID
                   1218: static int
                   1219: exec_nomid(p, epp)
1.59      mycroft  1220:        struct proc *p;
                   1221:        struct exec_package *epp;
1.31      cgd      1222: {
1.59      mycroft  1223:        int error;
                   1224:        u_long midmag, magic;
                   1225:        u_short mid;
1.80      cgd      1226:        struct exec *execp = epp->ep_hdr;
1.31      cgd      1227:
1.80      cgd      1228:        /* check on validity of epp->ep_hdr performed by exec_out_makecmds */
                   1229:
                   1230:        midmag = ntohl(execp->a_midmag);
1.59      mycroft  1231:        mid = (midmag >> 16) & 0xffff;
                   1232:        magic = midmag & 0xffff;
                   1233:
                   1234:        if (magic == 0) {
1.80      cgd      1235:                magic = (execp->a_midmag & 0xffff);
1.59      mycroft  1236:                mid = MID_ZERO;
                   1237:        }
                   1238:
                   1239:        midmag = mid << 16 | magic;
                   1240:
                   1241:        switch (midmag) {
                   1242:        case (MID_ZERO << 16) | ZMAGIC:
                   1243:                /*
                   1244:                 * 386BSD's ZMAGIC format:
                   1245:                 */
                   1246:                error = cpu_exec_aout_prep_oldzmagic(p, epp);
                   1247:                break;
                   1248:
                   1249:        case (MID_ZERO << 16) | QMAGIC:
                   1250:                /*
                   1251:                 * BSDI's QMAGIC format:
                   1252:                 * same as new ZMAGIC format, but with different magic number
                   1253:                 */
                   1254:                error = exec_aout_prep_zmagic(p, epp);
                   1255:                break;
                   1256:
                   1257:        default:
                   1258:                error = ENOEXEC;
                   1259:        }
                   1260:
                   1261:        return error;
1.107     deraadt  1262: }
1.31      cgd      1263: #endif
1.107     deraadt  1264:
                   1265: /*
                   1266:  * cpu_exec_aout_makecmds():
                   1267:  *     cpu-dependent a.out format hook for execve().
                   1268:  *
                   1269:  * Determine of the given exec package refers to something which we
                   1270:  * understand and, if so, set up the vmcmds for it.
                   1271:  *
                   1272:  * On the i386, old (386bsd) ZMAGIC binaries and BSDI QMAGIC binaries
                   1273:  * if COMPAT_NOMID is given as a kernel option.
                   1274:  */
                   1275: int
                   1276: cpu_exec_aout_makecmds(p, epp)
                   1277:        struct proc *p;
                   1278:        struct exec_package *epp;
                   1279: {
                   1280:        int error = ENOEXEC;
                   1281:
                   1282: #ifdef COMPAT_NOMID
                   1283:        if ((error = exec_nomid(p, epp)) == 0)
                   1284:                return error;
                   1285: #endif /* ! COMPAT_NOMID */
                   1286:
                   1287:        return error;
1.31      cgd      1288: }
1.24      cgd      1289:
1.31      cgd      1290: #ifdef COMPAT_NOMID
1.46      cgd      1291: /*
                   1292:  * cpu_exec_aout_prep_oldzmagic():
                   1293:  *     Prepare the vmcmds to build a vmspace for an old (386BSD) ZMAGIC
                   1294:  *     binary.
                   1295:  *
                   1296:  * Cloned from exec_aout_prep_zmagic() in kern/exec_aout.c; a more verbose
                   1297:  * description of operation is there.
                   1298:  */
1.24      cgd      1299: int
1.46      cgd      1300: cpu_exec_aout_prep_oldzmagic(p, epp)
1.59      mycroft  1301:        struct proc *p;
                   1302:        struct exec_package *epp;
1.24      cgd      1303: {
1.80      cgd      1304:        struct exec *execp = epp->ep_hdr;
1.59      mycroft  1305:        struct exec_vmcmd *ccmdp;
1.24      cgd      1306:
1.59      mycroft  1307:        epp->ep_taddr = 0;
                   1308:        epp->ep_tsize = execp->a_text;
                   1309:        epp->ep_daddr = epp->ep_taddr + execp->a_text;
                   1310:        epp->ep_dsize = execp->a_data + execp->a_bss;
                   1311:        epp->ep_entry = execp->a_entry;
                   1312:
                   1313:        /*
                   1314:         * check if vnode is in open for writing, because we want to
                   1315:         * demand-page out of it.  if it is, don't do it, for various
                   1316:         * reasons
                   1317:         */
                   1318:        if ((execp->a_text != 0 || execp->a_data != 0) &&
                   1319:            epp->ep_vp->v_writecount != 0) {
1.31      cgd      1320: #ifdef DIAGNOSTIC
1.59      mycroft  1321:                if (epp->ep_vp->v_flag & VTEXT)
                   1322:                        panic("exec: a VTEXT vnode has writecount != 0\n");
1.31      cgd      1323: #endif
1.59      mycroft  1324:                return ETXTBSY;
                   1325:        }
                   1326:        epp->ep_vp->v_flag |= VTEXT;
                   1327:
                   1328:        /* set up command for text segment */
1.69      cgd      1329:        NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_pagedvn, execp->a_text,
                   1330:            epp->ep_taddr, epp->ep_vp, NBPG, /* XXX should NBPG be CLBYTES? */
                   1331:            VM_PROT_READ|VM_PROT_EXECUTE);
1.59      mycroft  1332:
                   1333:        /* set up command for data segment */
1.69      cgd      1334:        NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_pagedvn, execp->a_data,
                   1335:            epp->ep_daddr, epp->ep_vp,
                   1336:            execp->a_text + NBPG, /* XXX should NBPG be CLBYTES? */
                   1337:            VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
1.59      mycroft  1338:
                   1339:        /* set up command for bss segment */
1.69      cgd      1340:        NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero, execp->a_bss,
1.71      mycroft  1341:            epp->ep_daddr + execp->a_data, NULLVP, 0,
1.69      cgd      1342:            VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
1.24      cgd      1343:
1.69      cgd      1344:        return exec_aout_setup_stack(p, epp);
1.1       cgd      1345: }
1.31      cgd      1346: #endif /* COMPAT_NOMID */
1.43      brezak   1347:
1.139     mycroft  1348: u_int
1.59      mycroft  1349: pmap_free_pages()
                   1350: {
                   1351:
1.139     mycroft  1352:        if (avail_next <= hole_start)
                   1353:                return ((hole_start - avail_next) / NBPG +
                   1354:                        (avail_end - hole_end) / NBPG);
                   1355:        else
                   1356:                return ((avail_end - avail_next) / NBPG);
1.59      mycroft  1357: }
                   1358:
                   1359: int
                   1360: pmap_next_page(addrp)
                   1361:        vm_offset_t *addrp;
                   1362: {
                   1363:
1.139     mycroft  1364:        if (avail_next + NBPG > avail_end)
1.59      mycroft  1365:                return FALSE;
1.73      mycroft  1366:
1.139     mycroft  1367:        if (avail_next + NBPG > hole_start && avail_next < hole_end)
1.59      mycroft  1368:                avail_next = hole_end;
1.73      mycroft  1369:
1.59      mycroft  1370:        *addrp = avail_next;
                   1371:        avail_next += NBPG;
                   1372:        return TRUE;
                   1373: }
                   1374:
1.120     mycroft  1375: u_int
1.59      mycroft  1376: pmap_page_index(pa)
                   1377:        vm_offset_t pa;
                   1378: {
                   1379:
                   1380:        if (pa >= avail_start && pa < hole_start)
                   1381:                return i386_btop(pa - avail_start);
                   1382:        if (pa >= hole_end && pa < avail_end)
                   1383:                return i386_btop(pa - hole_end + hole_start - avail_start);
                   1384:        return -1;
1.84      cgd      1385: }
                   1386:
                   1387: /*
                   1388:  * consinit:
                   1389:  * initialize the system console.
1.94      mycroft  1390:  * XXX - shouldn't deal with this initted thing, but then,
1.84      cgd      1391:  * it shouldn't be called from init386 either.
                   1392:  */
                   1393: void
                   1394: consinit()
                   1395: {
1.94      mycroft  1396:        static int initted;
                   1397:
                   1398:        if (initted)
                   1399:                return;
                   1400:        initted = 1;
                   1401:        cninit();
1.149     mycroft  1402: }
                   1403:
                   1404: void
                   1405: cpu_reset()
                   1406: {
                   1407:        struct region_descriptor region;
                   1408:
                   1409:        /* Toggle the hardware reset line on the keyboard controller. */
                   1410:        outb(KBCMDP, KBC_PULSE0);
1.162   ! mycroft  1411:        delay(20000);
1.149     mycroft  1412:        outb(KBCMDP, KBC_PULSE0);
1.162   ! mycroft  1413:        delay(20000);
1.149     mycroft  1414:
                   1415:        /*
                   1416:         * Try to cause a triple fault and watchdog reset by setting the
                   1417:         * IDT to point to nothing.
                   1418:         */
                   1419:        region.rd_limit = 0;
                   1420:        region.rd_base = 0;
                   1421:        lidt(&region);
                   1422:
                   1423:        /*
                   1424:         * Try to cause a triple fault and watchdog reset by unmapping the
                   1425:         * entire address space.
                   1426:         */
                   1427:        bzero((caddr_t)PTD, NBPG);
                   1428:        pmap_update();
                   1429:
                   1430:        for (;;);
1.45      cgd      1431: }

CVSweb <webmaster@jp.NetBSD.org>