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

1.425   ! jdolecek    1: /*     $NetBSD: machdep.c,v 1.424 2000/12/21 05:20:24 enami Exp $      */
1.231     thorpej     2:
                      3: /*-
1.401     thorpej     4:  * Copyright (c) 1996, 1997, 1998, 2000 The NetBSD Foundation, Inc.
1.231     thorpej     5:  * All rights reserved.
                      6:  *
                      7:  * This code is derived from software contributed to The NetBSD Foundation
1.316     mycroft     8:  * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace
                      9:  * Simulation Facility, NASA Ames Research Center.
1.231     thorpej    10:  *
                     11:  * Redistribution and use in source and binary forms, with or without
                     12:  * modification, are permitted provided that the following conditions
                     13:  * are met:
                     14:  * 1. Redistributions of source code must retain the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer.
                     16:  * 2. Redistributions in binary form must reproduce the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer in the
                     18:  *    documentation and/or other materials provided with the distribution.
                     19:  * 3. All advertising materials mentioning features or use of this software
                     20:  *    must display the following acknowledgement:
                     21:  *     This product includes software developed by the NetBSD
                     22:  *     Foundation, Inc. and its contributors.
                     23:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     24:  *    contributors may be used to endorse or promote products derived
                     25:  *    from this software without specific prior written permission.
                     26:  *
                     27:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     28:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     29:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     30:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     31:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     32:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     33:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     34:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     35:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     36:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     37:  * POSSIBILITY OF SUCH DAMAGE.
                     38:  */
1.125     cgd        39:
1.1       cgd        40: /*-
                     41:  * Copyright (c) 1982, 1987, 1990 The Regents of the University of California.
                     42:  * All rights reserved.
                     43:  *
                     44:  * This code is derived from software contributed to Berkeley by
                     45:  * William Jolitz.
                     46:  *
                     47:  * Redistribution and use in source and binary forms, with or without
                     48:  * modification, are permitted provided that the following conditions
                     49:  * are met:
                     50:  * 1. Redistributions of source code must retain the above copyright
                     51:  *    notice, this list of conditions and the following disclaimer.
                     52:  * 2. Redistributions in binary form must reproduce the above copyright
                     53:  *    notice, this list of conditions and the following disclaimer in the
                     54:  *    documentation and/or other materials provided with the distribution.
                     55:  * 3. All advertising materials mentioning features or use of this software
                     56:  *    must display the following acknowledgement:
                     57:  *     This product includes software developed by the University of
                     58:  *     California, Berkeley and its contributors.
                     59:  * 4. Neither the name of the University nor the names of its contributors
                     60:  *    may be used to endorse or promote products derived from this software
                     61:  *    without specific prior written permission.
                     62:  *
                     63:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     64:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     65:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     66:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     67:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     68:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     69:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     70:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     71:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     72:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     73:  * SUCH DAMAGE.
                     74:  *
1.125     cgd        75:  *     @(#)machdep.c   7.4 (Berkeley) 6/3/91
1.1       cgd        76:  */
1.271     thorpej    77:
                     78: #include "opt_cputype.h"
1.309     jonathan   79: #include "opt_ddb.h"
1.377     ws         80: #include "opt_ipkdb.h"
1.272     thorpej    81: #include "opt_vm86.h"
1.274     thorpej    82: #include "opt_user_ldt.h"
1.310     jonathan   83: #include "opt_compat_netbsd.h"
1.327     bouyer     84: #include "opt_cpureset_delay.h"
1.333     christos   85: #include "opt_compat_svr4.h"
1.1       cgd        86:
1.59      mycroft    87: #include <sys/param.h>
                     88: #include <sys/systm.h>
                     89: #include <sys/signalvar.h>
                     90: #include <sys/kernel.h>
                     91: #include <sys/map.h>
                     92: #include <sys/proc.h>
                     93: #include <sys/user.h>
                     94: #include <sys/exec.h>
                     95: #include <sys/buf.h>
                     96: #include <sys/reboot.h>
                     97: #include <sys/conf.h>
                     98: #include <sys/file.h>
                     99: #include <sys/malloc.h>
                    100: #include <sys/mbuf.h>
                    101: #include <sys/msgbuf.h>
                    102: #include <sys/mount.h>
                    103: #include <sys/vnode.h>
1.204     thorpej   104: #include <sys/extent.h>
1.123     cgd       105: #include <sys/syscallargs.h>
1.291     thorpej   106: #include <sys/core.h>
                    107: #include <sys/kcore.h>
                    108: #include <machine/kcore.h>
1.57      cgd       109:
1.377     ws        110: #ifdef IPKDB
                    111: #include <ipkdb/ipkdb.h>
                    112: #endif
                    113:
1.235     thorpej   114: #ifdef KGDB
                    115: #include <sys/kgdb.h>
                    116: #endif
                    117:
1.104     cgd       118: #include <dev/cons.h>
1.390     mrg       119:
                    120: #include <uvm/uvm_extern.h>
1.393     fvdl      121: #include <uvm/uvm_page.h>
1.284     mrg       122:
1.200     christos  123: #include <sys/sysctl.h>
                    124:
1.59      mycroft   125: #include <machine/cpu.h>
                    126: #include <machine/cpufunc.h>
1.178     mycroft   127: #include <machine/gdt.h>
1.149     mycroft   128: #include <machine/pio.h>
1.59      mycroft   129: #include <machine/psl.h>
                    130: #include <machine/reg.h>
                    131: #include <machine/specialreg.h>
1.255     drochner  132: #include <machine/bootinfo.h>
1.43      brezak    133:
1.146     cgd       134: #include <dev/isa/isareg.h>
1.372     drochner  135: #include <machine/isa_machdep.h>
1.164     cgd       136: #include <dev/ic/i8042reg.h>
1.43      brezak    137:
1.200     christos  138: #ifdef DDB
                    139: #include <machine/db_machdep.h>
                    140: #include <ddb/db_extern.h>
                    141: #endif
                    142:
1.184     mycroft   143: #ifdef VM86
                    144: #include <machine/vm86.h>
                    145: #endif
                    146:
1.207     jtk       147: #include "apm.h"
1.258     jtk       148: #include "bioscall.h"
1.207     jtk       149:
1.259     jtk       150: #if NBIOSCALL > 0
                    151: #include <machine/bioscall.h>
                    152: #endif
                    153:
1.207     jtk       154: #if NAPM > 0
                    155: #include <machine/apmvar.h>
1.258     jtk       156: #endif
                    157:
1.59      mycroft   158: #include "isa.h"
1.231     thorpej   159: #include "isadma.h"
1.59      mycroft   160: #include "npx.h"
1.161     mycroft   161: #if NNPX > 0
                    162: extern struct proc *npxproc;
                    163: #endif
1.2       cgd       164:
1.384     jdolecek  165: #include "mca.h"
                    166: #if NMCA > 0
                    167: #include <machine/mca_machdep.h>       /* for mca_busprobe() */
                    168: #endif
                    169:
1.104     cgd       170: /* the following is used externally (sysctl_hw) */
                    171: char machine[] = "i386";               /* cpu "architecture" */
1.232     veego     172: char machine_arch[] = "i386";          /* machine == machine_arch */
1.104     cgd       173:
1.402     explorer  174: u_int cpu_serial[3];
                    175:
1.255     drochner  176: char bootinfo[BOOTINFO_MAXSIZE];
1.386     thorpej   177:
                    178: /* Our exported CPU info; we have only one right now. */
                    179: struct cpu_info cpu_info_store;
1.255     drochner  180:
1.343     fvdl      181: struct bi_devmatch *i386_alldisks = NULL;
                    182: int i386_ndisks = 0;
1.342     fvdl      183:
1.328     bouyer    184: #ifdef CPURESET_DELAY
                    185: int    cpureset_delay = CPURESET_DELAY;
                    186: #else
                    187: int     cpureset_delay = 2000; /* default to 2s */
                    188: #endif
                    189:
1.1       cgd       190:
1.59      mycroft   191: int    physmem;
1.163     cgd       192: int    dumpmem_low;
                    193: int    dumpmem_high;
1.59      mycroft   194: int    boothowto;
                    195: int    cpu_class;
1.366     fvdl      196: int    i386_fpu_present = 0;
1.59      mycroft   197:
1.379     jdolecek  198: #define        CPUID2MODEL(cpuid)      (((cpuid) >> 4) & 15)
                    199:
1.314     thorpej   200: vaddr_t        msgbuf_vaddr;
                    201: paddr_t msgbuf_paddr;
                    202:
                    203: vaddr_t        idt_vaddr;
                    204: paddr_t        idt_paddr;
                    205:
1.264     mycroft   206: #ifdef I586_CPU
1.314     thorpej   207: vaddr_t        pentium_idt_vaddr;
1.264     mycroft   208: #endif
1.59      mycroft   209:
1.284     mrg       210: vm_map_t exec_map = NULL;
                    211: vm_map_t mb_map = NULL;
                    212: vm_map_t phys_map = NULL;
1.48      brezak    213:
1.314     thorpej   214: extern paddr_t avail_start, avail_end;
1.1       cgd       215:
1.204     thorpej   216: /*
1.291     thorpej   217:  * Size of memory segments, before any memory is stolen.
                    218:  */
                    219: phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX];
                    220: int    mem_cluster_cnt;
                    221:
1.408     thorpej   222: /*
                    223:  * The number of CPU cycles in one second.
                    224:  */
                    225: u_int64_t cpu_tsc_freq;
                    226:
1.291     thorpej   227: int    cpu_dump __P((void));
                    228: int    cpu_dumpsize __P((void));
                    229: u_long cpu_dump_mempagecnt __P((void));
1.200     christos  230: void   dumpsys __P((void));
                    231: void   identifycpu __P((void));
1.314     thorpej   232: void   init386 __P((paddr_t));
1.255     drochner  233:
1.397     thorpej   234: const struct i386_cache_info *cpu_itlb_info, *cpu_dtlb_info, *cpu_icache_info,
                    235:     *cpu_dcache_info, *cpu_l2cache_info;
                    236:
                    237: const struct i386_cache_info {
                    238:        u_int8_t        cai_desc;
                    239:        const struct i386_cache_info **cai_var;
                    240:        const char      *cai_string;
                    241:        u_int           cai_totalsize;
                    242:        u_int           cai_linesize;
                    243: } i386_cache_info[] = {
                    244:        { 0x01,         &cpu_itlb_info,         "32 4K entries 4-way",
                    245:          32,           4 * 1024 },
                    246:        { 0x02,         &cpu_itlb_info,         "2 4M entries",
                    247:          2,            4 * 1024 * 1024 },
                    248:        { 0x03,         &cpu_dtlb_info,         "64 4K entries 4-way",
                    249:          64,           4 * 1024 },
                    250:        { 0x04,         &cpu_dtlb_info,         "8 4M entries 4-way",
                    251:          8,            4 * 1024 * 1024 },
                    252:        { 0x06,         &cpu_icache_info,       "8K 32b/line 4-way",
                    253:          8 * 1024,     32 },
                    254:        { 0x08,         &cpu_icache_info,       "16K 32b/line 4-way",
                    255:          16 * 1024,    32 },
                    256:        { 0x0a,         &cpu_dcache_info,       "8K 32b/line 2-way",
                    257:          8 * 1024,     32 },
                    258:        { 0x0c,         &cpu_dcache_info,       "16K 32b/line 2/4-way",
                    259:          16 * 1024,    32 },
                    260:        { 0x40,         &cpu_l2cache_info,      "not present",
                    261:          0,            0 },
                    262:        { 0x41,         &cpu_l2cache_info,      "128K 32b/line 4-way",
                    263:          128 * 1024,   32 },
                    264:        { 0x42,         &cpu_l2cache_info,      "256K 32b/line 4-way",
                    265:          256 * 1024,   32 },
                    266:        { 0x43,         &cpu_l2cache_info,      "512K 32b/line 4-way",
                    267:          512 * 1024,   32 },
                    268:        { 0x44,         &cpu_l2cache_info,      "1M 32b/line 4-way",
                    269:          1 * 1024 * 1024, 32 },
                    270:        { 0x45,         &cpu_l2cache_info,      "2M 32b/line 4-way",
1.400     enami     271:          2 * 1024 * 1024, 32 },
                    272:        { 0x82,         &cpu_l2cache_info,      "256K 32b/line 8-way",
                    273:          256 * 1024,   32 },
                    274:        { 0x84,         &cpu_l2cache_info,      "1M 32b/line 8-way",
                    275:          1 * 1024 * 1024, 32 },
                    276:        { 0x85,         &cpu_l2cache_info,      "2M 32b/line 8-way",
1.397     thorpej   277:          2 * 1024 * 1024, 32 },
                    278:
                    279:        { 0,            NULL,           NULL,   0,      0 },
                    280: };
                    281:
                    282: const struct i386_cache_info *i386_cache_info_lookup __P((u_int8_t));
                    283:
1.417     jdolecek  284: /*
                    285:  * Map Brand ID from cpuid instruction to brand name.
                    286:  * Source: Intel Processor Identification and the CPUID Instruction, AP-485
                    287:  */
                    288: const char * const i386_p3_brand[] = {
1.419     jdolecek  289:        "",             /* Unsupported */
1.417     jdolecek  290:        "Celeron",      /* Intel (R) Celeron (TM) processor */
                    291:        "",             /* Intel (R) Pentium (R) III processor */
                    292:        "Xeon",         /* Intel (R) Pentium (R) III Xeon (TM) processor */
                    293: };
                    294:
1.200     christos  295: #ifdef COMPAT_NOMID
                    296: static int exec_nomid  __P((struct proc *, struct exec_package *));
                    297: #endif
1.59      mycroft   298:
1.267     bouyer    299: void cyrix6x86_cpu_setup __P((void));
1.379     jdolecek  300: void winchip_cpu_setup __P((void));
1.267     bouyer    301:
                    302: static __inline u_char
                    303: cyrix_read_reg(u_char reg)
                    304: {
                    305:        outb(0x22, reg);
                    306:        return inb(0x23);
                    307: }
                    308:
                    309: static __inline void
                    310: cyrix_write_reg(u_char reg, u_char data)
                    311: {
                    312:        outb(0x22, reg);
                    313:        outb(0x23, data);
                    314: }
                    315:
1.59      mycroft   316: /*
                    317:  * Machine-dependent startup code
                    318:  */
1.32      andrew    319: void
1.1       cgd       320: cpu_startup()
                    321: {
1.59      mycroft   322:        caddr_t v;
1.349     thorpej   323:        int sz, x;
1.314     thorpej   324:        vaddr_t minaddr, maxaddr;
                    325:        vsize_t size;
1.424     enami     326:        char buf[160];                          /* about 2 line */
1.354     lukem     327:        char pbuf[9];
1.258     jtk       328: #if NBIOSCALL > 0
1.207     jtk       329:        extern int biostramp_image_size;
                    330:        extern u_char biostramp_image[];
                    331: #endif
1.1       cgd       332:
1.284     mrg       333:        /*
                    334:         * Initialize error message buffer (et end of core).
                    335:         */
1.354     lukem     336:        msgbuf_vaddr = uvm_km_valloc(kernel_map, i386_round_page(MSGBUFSIZE));
1.385     thorpej   337:        if (msgbuf_vaddr == 0)
1.284     mrg       338:                panic("failed to valloc msgbuf_vaddr");
1.359     thorpej   339:
1.284     mrg       340:        /* msgbuf_paddr was init'd in pmap */
                    341:        for (x = 0; x < btoc(MSGBUFSIZE); x++)
1.414     thorpej   342:                pmap_kenter_pa((vaddr_t)msgbuf_vaddr + x * PAGE_SIZE,
                    343:                    msgbuf_paddr + x * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE);
1.359     thorpej   344:
1.284     mrg       345:        initmsgbuf((caddr_t)msgbuf_vaddr, round_page(MSGBUFSIZE));
                    346:
1.392     sommerfe  347:        printf("%s", version);
1.393     fvdl      348:
1.408     thorpej   349:        printf("cpu0: %s", cpu_model);
                    350:        if (cpu_tsc_freq != 0)
                    351:                printf(", %qd.%02qd MHz", (cpu_tsc_freq + 4999) / 1000000,
                    352:                    ((cpu_tsc_freq + 4999) / 10000) % 100);
                    353:        printf("\n");
1.397     thorpej   354:        if (cpu_icache_info != NULL || cpu_dcache_info != NULL) {
                    355:                printf("cpu0:");
                    356:                if (cpu_icache_info)
                    357:                        printf(" I-cache %s", cpu_icache_info->cai_string);
                    358:                if (cpu_dcache_info)
                    359:                        printf("%sD-cache %s",
                    360:                            (cpu_icache_info != NULL) ? ", " : " ",
                    361:                            cpu_dcache_info->cai_string);
                    362:                printf("\n");
                    363:        }
                    364:        if (cpu_l2cache_info)
                    365:                printf("cpu0: L2 cache %s\n", cpu_l2cache_info->cai_string);
1.424     enami     366:        if ((cpu_feature & CPUID_MASK1) != 0) {
                    367:                bitmask_snprintf(cpu_feature, CPUID_FLAGS1,
                    368:                    buf, sizeof(buf));
                    369:                printf("cpu0: features %s\n", buf);
                    370:        }
                    371:        if ((cpu_feature & CPUID_MASK2) != 0) {
                    372:                bitmask_snprintf(cpu_feature, CPUID_FLAGS2,
                    373:                    buf, sizeof(buf));
                    374:                printf("cpu0: features %s\n", buf);
1.395     thorpej   375:        }
1.267     bouyer    376:
1.420     jdolecek  377:        if (cpuid_level >= 3 && ((cpu_feature & CPUID_PN) != 0)) {
                    378:                printf("cpu0: serial number %04X-%04X-%04X-%04X-%04X-%04X\n",
                    379:                        cpu_serial[0] / 65536, cpu_serial[0] % 65536,
                    380:                        cpu_serial[1] / 65536, cpu_serial[1] % 65536,
                    381:                        cpu_serial[2] / 65536, cpu_serial[2] % 65536);
                    382:        }
1.402     explorer  383:
1.382     mycroft   384:        format_bytes(pbuf, sizeof(pbuf), ptoa(physmem));
1.354     lukem     385:        printf("total memory = %s\n", pbuf);
1.1       cgd       386:
                    387:        /*
1.59      mycroft   388:         * Find out how much space we need, allocate it,
                    389:         * and then give everything true virtual addresses.
1.1       cgd       390:         */
1.354     lukem     391:        sz = (int)allocsys(NULL, NULL);
1.284     mrg       392:        if ((v = (caddr_t)uvm_km_zalloc(kernel_map, round_page(sz))) == 0)
                    393:                panic("startup: no room for tables");
1.354     lukem     394:        if (allocsys(v, NULL) - v != sz)
1.1       cgd       395:                panic("startup: table size inconsistency");
1.50      cgd       396:
1.36      cgd       397:        /*
1.284     mrg       398:         * Allocate virtual address space for the buffers.  The area
                    399:         * is not managed by the VM system.
1.36      cgd       400:         */
                    401:        size = MAXBSIZE * nbuf;
1.314     thorpej   402:        if (uvm_map(kernel_map, (vaddr_t *) &buffers, round_page(size),
1.398     thorpej   403:                    NULL, UVM_UNKNOWN_OFFSET, 0,
1.284     mrg       404:                    UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE,
                    405:                                UVM_ADV_NORMAL, 0)) != KERN_SUCCESS)
                    406:                panic("cpu_startup: cannot allocate VM for buffers");
1.314     thorpej   407:        minaddr = (vaddr_t)buffers;
1.54      cgd       408:        if ((bufpages / nbuf) >= btoc(MAXBSIZE)) {
                    409:                /* don't want to alloc more physical mem than needed */
                    410:                bufpages = btoc(MAXBSIZE) * nbuf;
                    411:        }
1.36      cgd       412:
1.268     thorpej   413:        /*
                    414:         * XXX We defer allocation of physical pages for buffers until
                    415:         * XXX after autoconfiguration has run.  We must do this because
                    416:         * XXX on system with large amounts of memory or with large
                    417:         * XXX user-configured buffer caches, the buffer cache will eat
                    418:         * XXX up all of the lower 16M of RAM.  This prevents ISA DMA
                    419:         * XXX maps from allocating bounce pages.
                    420:         *
                    421:         * XXX Note that nothing can use buffer cache buffers until after
                    422:         * XXX autoconfiguration completes!!
                    423:         *
                    424:         * XXX This is a hack, and needs to be replaced with a better
                    425:         * XXX solution!  --thorpej@netbsd.org, December 6, 1997
                    426:         */
1.41      cgd       427:
1.1       cgd       428:        /*
1.36      cgd       429:         * Allocate a submap for exec arguments.  This map effectively
                    430:         * limits the number of processes exec'ing at any time.
1.1       cgd       431:         */
1.284     mrg       432:        exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
1.358     thorpej   433:                                   16*NCARGS, VM_MAP_PAGEABLE, FALSE, NULL);
1.59      mycroft   434:
1.1       cgd       435:        /*
                    436:         * Allocate a submap for physio
                    437:         */
1.284     mrg       438:        phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
1.358     thorpej   439:                                   VM_PHYS_SIZE, 0, FALSE, NULL);
1.1       cgd       440:
                    441:        /*
1.229     thorpej   442:         * Finally, allocate mbuf cluster submap.
1.1       cgd       443:         */
1.334     thorpej   444:        mb_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
1.358     thorpej   445:            nmbclusters * mclbytes, VM_MAP_INTRSAFE, FALSE, NULL);
1.1       cgd       446:
1.284     mrg       447:        /*
                    448:         * XXX Buffer cache pages haven't yet been allocated, so
                    449:         * XXX we need to account for those pages when printing
                    450:         * XXX the amount of free memory.
                    451:         */
1.354     lukem     452:        format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free - bufpages));
                    453:        printf("avail memory = %s\n", pbuf);
1.414     thorpej   454:        format_bytes(pbuf, sizeof(pbuf), bufpages * PAGE_SIZE);
1.354     lukem     455:        printf("using %d buffers containing %s of memory\n", nbuf, pbuf);
1.1       cgd       456:
1.258     jtk       457: #if NBIOSCALL > 0
1.207     jtk       458:        /*
                    459:         * this should be caught at kernel build time, but put it here
                    460:         * in case someone tries to fake it out...
                    461:         */
                    462: #ifdef DIAGNOSTIC
1.414     thorpej   463:        if (biostramp_image_size > PAGE_SIZE)
1.207     jtk       464:            panic("biostramp_image_size too big: %x vs. %x\n",
1.414     thorpej   465:                  biostramp_image_size, PAGE_SIZE);
1.207     jtk       466: #endif
1.314     thorpej   467:        pmap_kenter_pa((vaddr_t)BIOSTRAMP_BASE, /* virtual */
                    468:                       (paddr_t)BIOSTRAMP_BASE, /* physical */
                    469:                       VM_PROT_ALL);            /* protection */
1.313     perry     470:        memcpy((caddr_t)BIOSTRAMP_BASE, biostramp_image, biostramp_image_size);
1.207     jtk       471: #ifdef DEBUG
1.258     jtk       472:        printf("biostramp installed @ %x\n", BIOSTRAMP_BASE);
1.207     jtk       473: #endif
                    474: #endif
1.263     mycroft   475:
1.375     drochner  476:        /* Safe for i/o port / memory space allocation to use malloc now. */
                    477:        i386_bus_space_mallocok();
1.349     thorpej   478: }
                    479:
                    480: /*
                    481:  * Set up proc0's TSS and LDT.
                    482:  */
                    483: void
                    484: i386_proc0_tss_ldt_init()
                    485: {
                    486:        struct pcb *pcb;
                    487:        int x;
1.268     thorpej   488:
1.326     thorpej   489:        gdt_init();
                    490:        curpcb = pcb = &proc0.p_addr->u_pcb;
                    491:        pcb->pcb_flags = 0;
                    492:        pcb->pcb_tss.tss_ioopt =
                    493:            ((caddr_t)pcb->pcb_iomap - (caddr_t)&pcb->pcb_tss) << 16;
                    494:        for (x = 0; x < sizeof(pcb->pcb_iomap) / 4; x++)
                    495:                pcb->pcb_iomap[x] = 0xffffffff;
                    496:
1.394     thorpej   497:        pcb->pcb_ldt_sel = pmap_kernel()->pm_ldt_sel = GSEL(GLDT_SEL, SEL_KPL);
1.326     thorpej   498:        pcb->pcb_cr0 = rcr0();
                    499:        pcb->pcb_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL);
                    500:        pcb->pcb_tss.tss_esp0 = (int)proc0.p_addr + USPACE - 16;
1.394     thorpej   501:        tss_alloc(&proc0);
1.326     thorpej   502:
1.394     thorpej   503:        ltr(proc0.p_md.md_tss_sel);
1.326     thorpej   504:        lldt(pcb->pcb_ldt_sel);
                    505:
                    506:        proc0.p_md.md_regs = (struct trapframe *)pcb->pcb_tss.tss_esp0 - 1;
                    507: }
                    508:
                    509: /*
                    510:  * XXX Finish up the deferred buffer cache allocation and initialization.
                    511:  */
                    512: void
                    513: i386_bufinit()
                    514: {
                    515:        int i, base, residual;
                    516:
1.268     thorpej   517:        base = bufpages / nbuf;
                    518:        residual = bufpages % nbuf;
                    519:        for (i = 0; i < nbuf; i++) {
1.314     thorpej   520:                vsize_t curbufsize;
                    521:                vaddr_t curbuf;
1.284     mrg       522:                struct vm_page *pg;
                    523:
                    524:                /*
                    525:                 * Each buffer has MAXBSIZE bytes of VM space allocated.  Of
                    526:                 * that MAXBSIZE space, we allocate and map (base+1) pages
                    527:                 * for the first "residual" buffers, and then we allocate
                    528:                 * "base" pages for the rest.
                    529:                 */
1.314     thorpej   530:                curbuf = (vaddr_t) buffers + (i * MAXBSIZE);
1.414     thorpej   531:                curbufsize = PAGE_SIZE * ((i < residual) ? (base+1) : base);
1.284     mrg       532:
                    533:                while (curbufsize) {
1.311     thorpej   534:                        /*
                    535:                         * Attempt to allocate buffers from the first
                    536:                         * 16M of RAM to avoid bouncing file system
                    537:                         * transfers.
                    538:                         */
1.350     chs       539:                        pg = uvm_pagealloc_strat(NULL, 0, NULL, 0,
1.311     thorpej   540:                            UVM_PGA_STRAT_FALLBACK, VM_FREELIST_FIRST16);
1.284     mrg       541:                        if (pg == NULL)
                    542:                                panic("cpu_startup: not enough memory for "
                    543:                                    "buffer cache");
                    544:                        pmap_kenter_pgs(curbuf, &pg, 1);
                    545:                        curbuf += PAGE_SIZE;
                    546:                        curbufsize -= PAGE_SIZE;
                    547:                }
1.268     thorpej   548:        }
                    549:
                    550:        /*
                    551:         * Set up buffers, so they can be used to read disk labels.
                    552:         */
                    553:        bufinit();
1.16      cgd       554: }
                    555:
1.397     thorpej   556: const struct i386_cache_info *
                    557: i386_cache_info_lookup(u_int8_t desc)
                    558: {
                    559:        const struct i386_cache_info *cai;
                    560:
                    561:        for (cai = i386_cache_info; cai->cai_string != NULL; cai++) {
                    562:                if (cai->cai_desc == desc)
                    563:                        return (cai);
                    564:        }
                    565:
                    566:        return (NULL);
                    567: }
                    568:
1.104     cgd       569: /*
                    570:  * Info for CTL_HW
                    571:  */
                    572: char   cpu_model[120];
                    573:
1.216     fvdl      574: /*
                    575:  * Note: these are just the ones that may not have a cpuid instruction.
                    576:  * We deal with the rest in a different way.
                    577:  */
1.418     jdolecek  578: const struct cpu_nocpuid_nameclass i386_nocpuid_cpus[] = {
1.267     bouyer    579:        { CPUVENDOR_INTEL, "Intel", "386SX",    CPUCLASS_386,
                    580:                NULL},                          /* CPU_386SX */
                    581:        { CPUVENDOR_INTEL, "Intel", "386DX",    CPUCLASS_386,
                    582:                NULL},                          /* CPU_386   */
                    583:        { CPUVENDOR_INTEL, "Intel", "486SX",    CPUCLASS_486,
                    584:                NULL},                          /* CPU_486SX */
                    585:        { CPUVENDOR_INTEL, "Intel", "486DX",    CPUCLASS_486,
                    586:                NULL},                          /* CPU_486   */
                    587:        { CPUVENDOR_CYRIX, "Cyrix", "486DLC",   CPUCLASS_486,
                    588:                NULL},                          /* CPU_486DLC */
                    589:        { CPUVENDOR_CYRIX, "Cyrix", "6x86",             CPUCLASS_486,
                    590:                cyrix6x86_cpu_setup},   /* CPU_6x86 */
                    591:        { CPUVENDOR_NEXGEN,"NexGen","586",      CPUCLASS_386,
                    592:                NULL},                          /* CPU_NX586 */
1.216     fvdl      593: };
                    594:
                    595: const char *classnames[] = {
                    596:        "386",
                    597:        "486",
                    598:        "586",
                    599:        "686"
                    600: };
                    601:
                    602: const char *modifiers[] = {
                    603:        "",
                    604:        "OverDrive ",
                    605:        "Dual ",
                    606:        ""
1.18      cgd       607: };
                    608:
1.418     jdolecek  609: const struct cpu_cpuid_nameclass i386_cpuid_cpus[] = {
1.216     fvdl      610:        {
                    611:                "GenuineIntel",
                    612:                CPUVENDOR_INTEL,
                    613:                "Intel",
                    614:                /* Family 4 */
                    615:                { {
                    616:                        CPUCLASS_486,
                    617:                        {
1.219     perry     618:                                "486DX", "486DX", "486SX", "486DX2", "486SL",
1.216     fvdl      619:                                "486SX2", 0, "486DX2 W/B Enhanced",
                    620:                                "486DX4", 0, 0, 0, 0, 0, 0, 0,
                    621:                                "486"           /* Default */
1.267     bouyer    622:                        },
                    623:                        NULL
1.216     fvdl      624:                },
                    625:                /* Family 5 */
                    626:                {
                    627:                        CPUCLASS_586,
                    628:                        {
1.361     tron      629:                                "Pentium (P5 A-step)", "Pentium (P5)",
                    630:                                "Pentium (P54C)", "Pentium (P24T)",
                    631:                                "Pentium/MMX", "Pentium", 0,
                    632:                                "Pentium (P54C)", "Pentium/MMX (Tillamook)",
                    633:                                0, 0, 0, 0, 0, 0, 0,
1.216     fvdl      634:                                "Pentium"       /* Default */
1.267     bouyer    635:                        },
                    636:                        NULL
1.216     fvdl      637:                },
                    638:                /* Family 6 */
                    639:                {
                    640:                        CPUCLASS_686,
                    641:                        {
1.361     tron      642:                                "Pentium Pro (A-step)", "Pentium Pro", 0,
                    643:                                "Pentium II (Klamath)", "Pentium Pro",
1.416     jdolecek  644:                                "Pentium II/Celeron (Deschutes)",
                    645:                                "Celeron (Mendocino)",
                    646:                                "Pentium III (Katmai)",
                    647:                                "Pentium III (Coppermine)",
1.419     jdolecek  648:                                0, "Pentium III (Cascades)", 0, 0,
1.416     jdolecek  649:                                0, 0,
1.340     fvdl      650:                                "Pentium Pro, II or III"        /* Default */
1.267     bouyer    651:                        },
                    652:                        NULL
1.406     fvdl      653:                },
                    654:                /* Family > 6 */
                    655:                {
                    656:                        CPUCLASS_686,
                    657:                        {
                    658:                                0, 0, 0, 0, 0, 0, 0,
                    659:                                0, 0, 0, 0, 0, 0, 0, 0, 0,
                    660:                                "Pentium 4"     /* Default */
                    661:                        },
                    662:                        NULL
1.216     fvdl      663:                } }
                    664:        },
                    665:        {
                    666:                "AuthenticAMD",
                    667:                CPUVENDOR_AMD,
                    668:                "AMD",
                    669:                /* Family 4 */
                    670:                { {
                    671:                        CPUCLASS_486,
                    672:                        {
                    673:                                0, 0, 0, "Am486DX2 W/T",
                    674:                                0, 0, 0, "Am486DX2 W/B",
                    675:                                "Am486DX4 W/T or Am5x86 W/T 150",
                    676:                                "Am486DX4 W/B or Am5x86 W/B 150", 0, 0,
                    677:                                0, 0, "Am5x86 W/T 133/160",
                    678:                                "Am5x86 W/B 133/160",
                    679:                                "Am486 or Am5x86"       /* Default */
                    680:                        },
1.267     bouyer    681:                        NULL
1.216     fvdl      682:                },
                    683:                /* Family 5 */
                    684:                {
                    685:                        CPUCLASS_586,
                    686:                        {
1.241     fvdl      687:                                "K5", "K5", "K5", "K5", 0, 0, "K6",
1.416     jdolecek  688:                                "K6", "K6-2", "K6-III", 0, 0, 0,
                    689:                                "K6-2+/III+", 0, 0,
1.267     bouyer    690:                                "K5 or K6"              /* Default */
1.216     fvdl      691:                        },
1.267     bouyer    692:                        NULL
1.216     fvdl      693:                },
1.363     fvdl      694:                /* Family 6 */
1.216     fvdl      695:                {
                    696:                        CPUCLASS_686,
                    697:                        {
1.416     jdolecek  698:                                0, "Athlon Model 1", "Athlon Model 2",
                    699:                                "Duron", "Athlon Model 4 (Thunderbird)",
                    700:                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1.362     fvdl      701:                                "K7 (Athlon)"   /* Default */
1.216     fvdl      702:                        },
1.267     bouyer    703:                        NULL
1.406     fvdl      704:                },
                    705:                /* Family > 6 */
                    706:                {
                    707:                        CPUCLASS_686,
                    708:                        {
                    709:                                0, 0, 0, 0, 0, 0, 0,
                    710:                                0, 0, 0, 0, 0, 0, 0, 0, 0,
                    711:                                "Unknown K7 (Athlon)"   /* Default */
                    712:                        },
                    713:                        NULL
1.216     fvdl      714:                } }
                    715:        },
                    716:        {
                    717:                "CyrixInstead",
                    718:                CPUVENDOR_CYRIX,
                    719:                "Cyrix",
                    720:                /* Family 4 */
                    721:                { {
                    722:                        CPUCLASS_486,
                    723:                        {
1.376     minoura   724:                                0, 0, 0,
                    725:                                "MediaGX",
                    726:                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1.216     fvdl      727:                                "486"           /* Default */
                    728:                        },
1.267     bouyer    729:                        NULL
1.216     fvdl      730:                },
                    731:                /* Family 5 */
                    732:                {
                    733:                        CPUCLASS_586,
                    734:                        {
1.376     minoura   735:                                0, 0, "6x86", 0,
                    736:                                "MMX-enhanced MediaGX (GXm)", /* or Geode? */
                    737:                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1.216     fvdl      738:                                "6x86"          /* Default */
1.267     bouyer    739:                        },
                    740:                        cyrix6x86_cpu_setup
1.216     fvdl      741:                },
1.278     bouyer    742:                /* Family 6 */
1.216     fvdl      743:                {
                    744:                        CPUCLASS_686,
                    745:                        {
1.278     bouyer    746:                                "6x86MX", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                    747:                                "6x86MX"                /* Default */
1.329     bad       748:                        },
1.368     drochner  749:                        cyrix6x86_cpu_setup
1.406     fvdl      750:                },
                    751:                /* Family > 6 */
                    752:                {
                    753:                        CPUCLASS_686,
                    754:                        {
                    755:                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                    756:                                "Unknown 6x86MX"                /* Default */
                    757:                        },
                    758:                        NULL
1.329     bad       759:                } }
                    760:        },
                    761:        {
                    762:                "CentaurHauls",
                    763:                CPUVENDOR_IDT,
                    764:                "IDT",
                    765:                /* Family 4, IDT never had any of these */
                    766:                { {
                    767:                        CPUCLASS_486,
                    768:                        {
                    769:                                0, 0, 0, 0, 0, 0, 0,
                    770:                                0, 0, 0, 0, 0, 0, 0, 0, 0,
                    771:                                "486 compatible"        /* Default */
                    772:                        },
                    773:                        NULL
                    774:                },
                    775:                /* Family 5 */
                    776:                {
                    777:                        CPUCLASS_586,
                    778:                        {
                    779:                                0, 0, 0, 0, "WinChip C6", 0, 0, 0,
1.379     jdolecek  780:                                "WinChip 2", "WinChip 3", 0, 0, 0, 0, 0, 0,
1.329     bad       781:                                "WinChip"               /* Default */
                    782:                        },
1.379     jdolecek  783:                        winchip_cpu_setup
1.329     bad       784:                },
                    785:                /* Family 6, not yet available from IDT */
1.406     fvdl      786:                {
                    787:                        CPUCLASS_686,
                    788:                        {
                    789:                                0, 0, 0, 0, 0, 0, 0,
                    790:                                0, 0, 0, 0, 0, 0, 0, 0, 0,
                    791:                                "Pentium Pro compatible"        /* Default */
                    792:                        },
                    793:                        NULL
                    794:                },
                    795:                /* Family > 6, not yet available from IDT */
1.329     bad       796:                {
                    797:                        CPUCLASS_686,
                    798:                        {
                    799:                                0, 0, 0, 0, 0, 0, 0,
                    800:                                0, 0, 0, 0, 0, 0, 0, 0, 0,
                    801:                                "Pentium Pro compatible"        /* Default */
1.267     bouyer    802:                        },
                    803:                        NULL
1.216     fvdl      804:                } }
                    805:        }
                    806: };
                    807:
1.195     mycroft   808: void
1.267     bouyer    809: cyrix6x86_cpu_setup()
                    810: {
                    811:        /* set up various cyrix registers */
                    812:        /* Enable suspend on halt */
                    813:        cyrix_write_reg(0xc2, cyrix_read_reg(0xc2) | 0x08);
                    814:        /* enable access to ccr4/ccr5 */
                    815:        cyrix_write_reg(0xC3, cyrix_read_reg(0xC3) | 0x10);
                    816:        /* cyrix's workaround  for the "coma bug" */
                    817:        cyrix_write_reg(0x31, cyrix_read_reg(0x31) | 0xf8);
                    818:        cyrix_write_reg(0x32, cyrix_read_reg(0x32) | 0x7f);
                    819:        cyrix_write_reg(0x33, cyrix_read_reg(0x33) & ~0xff);
                    820:        cyrix_write_reg(0x3c, cyrix_read_reg(0x3c) | 0x87);
                    821:        /* disable access to ccr4/ccr5 */
                    822:        cyrix_write_reg(0xC3, cyrix_read_reg(0xC3) & ~0x10);
1.393     fvdl      823:
                    824:        /*
                    825:         * XXX disable page zero in the idle loop, it seems to
                    826:         * cause panics on these CPUs.
                    827:         */
                    828:        vm_page_zero_enable = FALSE;
1.267     bouyer    829: }
                    830:
                    831: void
1.379     jdolecek  832: winchip_cpu_setup()
                    833: {
1.380     jdolecek  834: #if defined(I586_CPU)
1.379     jdolecek  835:        extern int cpu_id;
                    836:
                    837:        switch (CPUID2MODEL(cpu_id)) { /* model */
                    838:        case 4: /* WinChip C6 */
                    839:                cpu_feature &= ~CPUID_TSC;
                    840:                printf("WARNING: WinChip C6: broken TSC disabled\n");
                    841:        }
                    842: #endif
                    843: }
                    844:
1.397     thorpej   845: static void
                    846: do_cpuid(u_int which, u_int *rv)
                    847: {
                    848:        register u_int eax __asm("%eax") = which;
                    849:
                    850:        __asm __volatile(
                    851:        "       cpuid                   ;"
                    852:        "       movl    %%eax,0(%2)     ;"
                    853:        "       movl    %%ebx,4(%2)     ;"
                    854:        "       movl    %%ecx,8(%2)     ;"
                    855:        "       movl    %%edx,12(%2)    "
                    856:        : "=a" (eax)
                    857:        : "0" (eax), "S" (rv)
                    858:        : "ebx", "ecx", "edx");
                    859: }
                    860:
1.402     explorer  861: static void
                    862: do_cpuid_serial(u_int *serial)
                    863: {
                    864:        __asm __volatile(
                    865:        "       movl    $1,%%eax        ;"
                    866:        "       cpuid                   ;"
                    867:        "       movl    %%eax,0(%0)     ;"
                    868:        "       movl    $3,%%eax        ;"
                    869:        "       cpuid                   ;"
                    870:        "       movl    %%edx,4(%0)     ;"
                    871:        "       movl    %%ecx,8(%0)     "
                    872:        : /* no imputs */
                    873:        : "S" (serial)
                    874:        : "eax", "ebx", "ecx", "edx");
                    875: }
                    876:
1.379     jdolecek  877: void
1.59      mycroft   878: identifycpu()
1.16      cgd       879: {
1.86      mycroft   880:        extern char cpu_vendor[];
1.216     fvdl      881:        extern int cpu_id;
1.417     jdolecek  882:        extern int cpu_brand_id;
                    883:        const char *name, *modifier, *vendorname, *brand = "";
1.216     fvdl      884:        int class = CPUCLASS_386, vendor, i, max;
                    885:        int family, model, step, modif;
1.418     jdolecek  886:        const struct cpu_cpuid_nameclass *cpup = NULL;
1.267     bouyer    887:        void (*cpu_setup) __P((void));
1.86      mycroft   888:
1.216     fvdl      889:        if (cpuid_level == -1) {
1.59      mycroft   890: #ifdef DIAGNOSTIC
1.216     fvdl      891:                if (cpu < 0 || cpu >=
                    892:                    (sizeof i386_nocpuid_cpus/sizeof(struct cpu_nocpuid_nameclass)))
                    893:                        panic("unknown cpu type %d\n", cpu);
                    894: #endif
                    895:                name = i386_nocpuid_cpus[cpu].cpu_name;
                    896:                vendor = i386_nocpuid_cpus[cpu].cpu_vendor;
                    897:                vendorname = i386_nocpuid_cpus[cpu].cpu_vendorname;
                    898:                class = i386_nocpuid_cpus[cpu].cpu_class;
1.267     bouyer    899:                cpu_setup = i386_nocpuid_cpus[cpu].cpu_setup;
1.216     fvdl      900:                modifier = "";
                    901:        } else {
                    902:                max = sizeof (i386_cpuid_cpus) / sizeof (i386_cpuid_cpus[0]);
                    903:                modif = (cpu_id >> 12) & 3;
                    904:                family = (cpu_id >> 8) & 15;
                    905:                if (family < CPU_MINFAMILY)
                    906:                        panic("identifycpu: strange family value");
1.379     jdolecek  907:                model = CPUID2MODEL(cpu_id);
1.216     fvdl      908:                step = cpu_id & 15;
                    909: #ifdef CPUDEBUG
                    910:                printf("cpu0: family %x model %x step %x\n", family, model,
                    911:                        step);
                    912: #endif
                    913:
                    914:                for (i = 0; i < max; i++) {
                    915:                        if (!strncmp(cpu_vendor,
                    916:                            i386_cpuid_cpus[i].cpu_id, 12)) {
                    917:                                cpup = &i386_cpuid_cpus[i];
                    918:                                break;
                    919:                        }
                    920:                }
                    921:
                    922:                if (cpup == NULL) {
                    923:                        vendor = CPUVENDOR_UNKNOWN;
                    924:                        if (cpu_vendor[0] != '\0')
                    925:                                vendorname = &cpu_vendor[0];
                    926:                        else
                    927:                                vendorname = "Unknown";
                    928:                        if (family > CPU_MAXFAMILY)
                    929:                                family = CPU_MAXFAMILY;
                    930:                        class = family - 3;
                    931:                        modifier = "";
                    932:                        name = "";
1.267     bouyer    933:                        cpu_setup = NULL;
1.216     fvdl      934:                } else {
                    935:                        vendor = cpup->cpu_vendor;
                    936:                        vendorname = cpup->cpu_vendorname;
                    937:                        modifier = modifiers[modif];
                    938:                        if (family > CPU_MAXFAMILY) {
                    939:                                family = CPU_MAXFAMILY;
                    940:                                model = CPU_DEFMODEL;
                    941:                        } else if (model > CPU_MAXMODEL)
                    942:                                model = CPU_DEFMODEL;
                    943:                        i = family - CPU_MINFAMILY;
                    944:                        name = cpup->cpu_family[i].cpu_models[model];
                    945:                        if (name == NULL)
                    946:                            name = cpup->cpu_family[i].cpu_models[CPU_DEFMODEL];
                    947:                        class = cpup->cpu_family[i].cpu_class;
1.267     bouyer    948:                        cpu_setup = cpup->cpu_family[i].cpu_setup;
1.417     jdolecek  949:
                    950:                        /*
                    951:                         * Intel processors family >= 6, model 8 allow to
                    952:                         * recognize brand by Brand ID value.
                    953:                         */
                    954:                        if (vendor == CPUVENDOR_INTEL && family >= 6
                    955:                            && model >= 8 && cpu_brand_id && cpu_brand_id <= 3)
                    956:                                brand = i386_p3_brand[cpu_brand_id];
1.216     fvdl      957:                }
1.104     cgd       958:        }
                    959:
1.417     jdolecek  960:        sprintf(cpu_model, "%s %s%s%s%s (%s-class)", vendorname, modifier, name,
1.419     jdolecek  961:                (*brand) ? " " : "", brand,
1.241     fvdl      962:                classnames[class]);
1.216     fvdl      963:
                    964:        cpu_class = class;
1.397     thorpej   965:
                    966:        /*
                    967:         * Parse the cache info from `cpuid', if we have it.
                    968:         * XXX This is kinda ugly, but hey, so is the architecture...
                    969:         */
                    970:        if (cpuid_level != -1) {
                    971:                const struct i386_cache_info *cai;
                    972:                u_int descs[4];
                    973:                int iterations, j;
                    974:                u_int8_t desc;
                    975:
1.399     enami     976:                do_cpuid(2, descs);
                    977:                iterations = descs[0] & 0xff;
                    978:                while (iterations-- > 0) {
1.397     thorpej   979:                        for (i = 0; i < 4; i++) {
                    980:                                if (descs[i] & 0x80000000)
                    981:                                        continue;
                    982:                                for (j = 0; j < 4; j++) {
1.399     enami     983:                                        if (i == 0 && j == 0)
                    984:                                                continue;
1.397     thorpej   985:                                        desc = (descs[i] >> (j * 8)) & 0xff;
                    986:                                        cai = i386_cache_info_lookup(desc);
                    987:                                        if (cai != NULL)
                    988:                                                *cai->cai_var = cai;
                    989:                                }
                    990:                        }
1.399     enami     991:
                    992:                        do_cpuid(2, descs);
                    993:                }
1.397     thorpej   994:        }
1.402     explorer  995:
                    996:        /*
                    997:         * If the processor serial number misfeature is present and supported,
                    998:         * extract it here.
                    999:         */
                   1000:        if (cpuid_level >= 3 && (cpu_feature & CPUID_PN) != 0)
                   1001:                do_cpuid_serial(cpu_serial);
1.18      cgd      1002:
1.16      cgd      1003:        /*
                   1004:         * Now that we have told the user what they have,
                   1005:         * let them know if that machine type isn't configured.
                   1006:         */
1.24      cgd      1007:        switch (cpu_class) {
1.216     fvdl     1008: #if !defined(I386_CPU) && !defined(I486_CPU) && !defined(I586_CPU) && !defined(I686_CPU)
1.100     mycroft  1009: #error No CPU classes configured.
                   1010: #endif
1.216     fvdl     1011: #ifndef I686_CPU
                   1012:        case CPUCLASS_686:
                   1013:                printf("NOTICE: this kernel does not support Pentium Pro CPU class\n");
                   1014: #ifdef I586_CPU
                   1015:                printf("NOTICE: lowering CPU class to i586\n");
                   1016:                cpu_class = CPUCLASS_586;
                   1017:                break;
                   1018: #endif
                   1019: #endif
1.165     mycroft  1020: #ifndef I586_CPU
1.118     mycroft  1021:        case CPUCLASS_586:
1.210     christos 1022:                printf("NOTICE: this kernel does not support Pentium CPU class\n");
1.165     mycroft  1023: #ifdef I486_CPU
1.210     christos 1024:                printf("NOTICE: lowering CPU class to i486\n");
1.118     mycroft  1025:                cpu_class = CPUCLASS_486;
                   1026:                break;
1.16      cgd      1027: #endif
1.165     mycroft  1028: #endif
                   1029: #ifndef I486_CPU
1.18      cgd      1030:        case CPUCLASS_486:
1.210     christos 1031:                printf("NOTICE: this kernel does not support i486 CPU class\n");
1.165     mycroft  1032: #ifdef I386_CPU
1.210     christos 1033:                printf("NOTICE: lowering CPU class to i386\n");
1.118     mycroft  1034:                cpu_class = CPUCLASS_386;
                   1035:                break;
                   1036: #endif
1.165     mycroft  1037: #endif
                   1038: #ifndef I386_CPU
1.118     mycroft  1039:        case CPUCLASS_386:
1.210     christos 1040:                printf("NOTICE: this kernel does not support i386 CPU class\n");
1.187     mycroft  1041:                panic("no appropriate CPU class available");
1.59      mycroft  1042: #endif
1.16      cgd      1043:        default:
                   1044:                break;
1.121     mycroft  1045:        }
                   1046:
1.267     bouyer   1047:        /* configure the CPU if needed */
                   1048:        if (cpu_setup != NULL)
                   1049:                cpu_setup();
1.121     mycroft  1050:        if (cpu == CPU_486DLC) {
                   1051: #ifndef CYRIX_CACHE_WORKS
1.210     christos 1052:                printf("WARNING: CYRIX 486DLC CACHE UNCHANGED.\n");
1.121     mycroft  1053: #else
                   1054: #ifndef CYRIX_CACHE_REALLY_WORKS
1.210     christos 1055:                printf("WARNING: CYRIX 486DLC CACHE ENABLED IN HOLD-FLUSH MODE.\n");
1.121     mycroft  1056: #else
1.210     christos 1057:                printf("WARNING: CYRIX 486DLC CACHE ENABLED.\n");
1.121     mycroft  1058: #endif
                   1059: #endif
1.16      cgd      1060:        }
1.147     mycroft  1061:
1.216     fvdl     1062: #if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
1.147     mycroft  1063:        /*
1.199     mycroft  1064:         * On a 486 or above, enable ring 0 write protection.
1.147     mycroft  1065:         */
                   1066:        if (cpu_class >= CPUCLASS_486)
1.199     mycroft  1067:                lcr0(rcr0() | CR0_WP);
1.408     thorpej  1068: #endif
                   1069:
                   1070: #if defined(I586_CPU) || defined(I686_CPU)
                   1071:        /*
                   1072:         * If we have a cycle counter, compute the approximate
                   1073:         * CPU speed in MHz.
                   1074:         */
                   1075:        if (cpu_feature & CPUID_TSC) {
                   1076:                u_int64_t last_tsc;
                   1077:
                   1078:                last_tsc = rdtsc();
1.413     jdolecek 1079:                delay(100000);
                   1080:                cpu_tsc_freq = (rdtsc() - last_tsc) * 10;
1.408     thorpej  1081:        }
1.147     mycroft  1082: #endif
1.1       cgd      1083: }
                   1084:
1.104     cgd      1085: /*
                   1086:  * machine dependent system variables.
                   1087:  */
1.195     mycroft  1088: int
1.104     cgd      1089: cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
                   1090:        int *name;
                   1091:        u_int namelen;
                   1092:        void *oldp;
                   1093:        size_t *oldlenp;
                   1094:        void *newp;
                   1095:        size_t newlen;
                   1096:        struct proc *p;
                   1097: {
                   1098:        dev_t consdev;
1.255     drochner 1099:        struct btinfo_bootpath *bibp;
1.104     cgd      1100:
                   1101:        /* all sysctl names at this level are terminal */
                   1102:        if (namelen != 1)
                   1103:                return (ENOTDIR);               /* overloaded */
                   1104:
                   1105:        switch (name[0]) {
                   1106:        case CPU_CONSDEV:
                   1107:                if (cn_tab != NULL)
                   1108:                        consdev = cn_tab->cn_dev;
                   1109:                else
                   1110:                        consdev = NODEV;
                   1111:                return (sysctl_rdstruct(oldp, oldlenp, newp, &consdev,
                   1112:                    sizeof consdev));
1.215     fvdl     1113:
                   1114:        case CPU_BIOSBASEMEM:
                   1115:                return (sysctl_rdint(oldp, oldlenp, newp, biosbasemem));
                   1116:
                   1117:        case CPU_BIOSEXTMEM:
                   1118:                return (sysctl_rdint(oldp, oldlenp, newp, biosextmem));
                   1119:
                   1120:        case CPU_NKPDE:
                   1121:                return (sysctl_rdint(oldp, oldlenp, newp, nkpde));
1.366     fvdl     1122:
                   1123:        case CPU_FPU_PRESENT:
                   1124:                return (sysctl_rdint(oldp, oldlenp, newp, i386_fpu_present));
1.215     fvdl     1125:
1.255     drochner 1126:        case CPU_BOOTED_KERNEL:
                   1127:                bibp = lookup_bootinfo(BTINFO_BOOTPATH);
                   1128:                if(!bibp)
                   1129:                        return(ENOENT); /* ??? */
                   1130:                return (sysctl_rdstring(oldp, oldlenp, newp, bibp->bootpath));
1.343     fvdl     1131:        case CPU_DISKINFO:
                   1132:                if (i386_alldisks == NULL)
1.339     fvdl     1133:                        return (ENOENT);
1.343     fvdl     1134:                return (sysctl_rdstruct(oldp, oldlenp, newp, i386_alldisks,
                   1135:                    sizeof (struct disklist) +
                   1136:                        (i386_ndisks - 1) * sizeof (struct nativedisk_info)));
1.104     cgd      1137:        default:
                   1138:                return (EOPNOTSUPP);
                   1139:        }
                   1140:        /* NOTREACHED */
                   1141: }
1.151     christos 1142:
1.1       cgd      1143: /*
                   1144:  * Send an interrupt to process.
                   1145:  *
                   1146:  * Stack is set up to allow sigcode stored
                   1147:  * in u. to call routine, followed by kcall
                   1148:  * to sigreturn routine below.  After sigreturn
                   1149:  * resets the signal mask, the stack, and the
                   1150:  * frame pointer, it returns to the user
                   1151:  * specified pc, psl.
                   1152:  */
                   1153: void
                   1154: sendsig(catcher, sig, mask, code)
                   1155:        sig_t catcher;
1.319     mycroft  1156:        int sig;
                   1157:        sigset_t *mask;
1.126     cgd      1158:        u_long code;
1.1       cgd      1159: {
1.298     mycroft  1160:        struct proc *p = curproc;
                   1161:        struct trapframe *tf;
1.82      ws       1162:        struct sigframe *fp, frame;
1.319     mycroft  1163:        int onstack;
1.1       cgd      1164:
1.319     mycroft  1165:        tf = p->p_md.md_regs;
1.135     christos 1166:
1.319     mycroft  1167:        /* Do we need to jump onto the signal stack? */
                   1168:        onstack =
1.425   ! jdolecek 1169:            (p->p_sigctx.ps_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 &&
        !          1170:            (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0;
1.135     christos 1171:
1.319     mycroft  1172:        /* Allocate space for the signal handler context. */
                   1173:        if (onstack)
1.425   ! jdolecek 1174:                fp = (struct sigframe *)((caddr_t)p->p_sigctx.ps_sigstk.ss_sp +
        !          1175:                                          p->p_sigctx.ps_sigstk.ss_size);
1.319     mycroft  1176:        else
                   1177:                fp = (struct sigframe *)tf->tf_esp;
                   1178:        fp--;
1.1       cgd      1179:
1.319     mycroft  1180:        /* Build stack frame for signal trampoline. */
                   1181:        frame.sf_signum = sig;
1.82      ws       1182:        frame.sf_code = code;
                   1183:        frame.sf_scp = &fp->sf_sc;
                   1184:        frame.sf_handler = catcher;
                   1185:
1.319     mycroft  1186:        /* Save register context. */
1.157     mycroft  1187: #ifdef VM86
                   1188:        if (tf->tf_eflags & PSL_VM) {
                   1189:                frame.sf_sc.sc_gs = tf->tf_vm86_gs;
                   1190:                frame.sf_sc.sc_fs = tf->tf_vm86_fs;
                   1191:                frame.sf_sc.sc_es = tf->tf_vm86_es;
                   1192:                frame.sf_sc.sc_ds = tf->tf_vm86_ds;
1.196     mycroft  1193:                frame.sf_sc.sc_eflags = get_vflags(p);
1.422     mycroft  1194:                (*p->p_emul->e_syscall_intern)(p);
1.157     mycroft  1195:        } else
                   1196: #endif
                   1197:        {
                   1198:                __asm("movl %%gs,%w0" : "=r" (frame.sf_sc.sc_gs));
                   1199:                __asm("movl %%fs,%w0" : "=r" (frame.sf_sc.sc_fs));
                   1200:                frame.sf_sc.sc_es = tf->tf_es;
                   1201:                frame.sf_sc.sc_ds = tf->tf_ds;
1.184     mycroft  1202:                frame.sf_sc.sc_eflags = tf->tf_eflags;
1.157     mycroft  1203:        }
1.184     mycroft  1204:        frame.sf_sc.sc_edi = tf->tf_edi;
                   1205:        frame.sf_sc.sc_esi = tf->tf_esi;
                   1206:        frame.sf_sc.sc_ebp = tf->tf_ebp;
                   1207:        frame.sf_sc.sc_ebx = tf->tf_ebx;
                   1208:        frame.sf_sc.sc_edx = tf->tf_edx;
                   1209:        frame.sf_sc.sc_ecx = tf->tf_ecx;
                   1210:        frame.sf_sc.sc_eax = tf->tf_eax;
                   1211:        frame.sf_sc.sc_eip = tf->tf_eip;
                   1212:        frame.sf_sc.sc_cs = tf->tf_cs;
                   1213:        frame.sf_sc.sc_esp = tf->tf_esp;
                   1214:        frame.sf_sc.sc_ss = tf->tf_ss;
1.319     mycroft  1215:        frame.sf_sc.sc_trapno = tf->tf_trapno;
                   1216:        frame.sf_sc.sc_err = tf->tf_err;
                   1217:
                   1218:        /* Save signal stack. */
1.425   ! jdolecek 1219:        frame.sf_sc.sc_onstack = p->p_sigctx.ps_sigstk.ss_flags & SS_ONSTACK;
1.319     mycroft  1220:
                   1221:        /* Save signal mask. */
                   1222:        frame.sf_sc.sc_mask = *mask;
1.322     thorpej  1223:
                   1224: #ifdef COMPAT_13
                   1225:        /*
                   1226:         * XXX We always have to save an old style signal mask because
                   1227:         * XXX we might be delivering a signal to a process which will
                   1228:         * XXX escape from the signal in a non-standard way and invoke
                   1229:         * XXX sigreturn() directly.
                   1230:         */
                   1231:        native_sigset_to_sigset13(mask, &frame.sf_sc.__sc_mask13);
                   1232: #endif
1.1       cgd      1233:
1.87      mycroft  1234:        if (copyout(&frame, fp, sizeof(frame)) != 0) {
1.1       cgd      1235:                /*
                   1236:                 * Process has trashed its stack; give it an illegal
                   1237:                 * instruction to halt it in its tracks.
                   1238:                 */
1.93      mycroft  1239:                sigexit(p, SIGILL);
                   1240:                /* NOTREACHED */
1.1       cgd      1241:        }
                   1242:
1.73      mycroft  1243:        /*
1.59      mycroft  1244:         * Build context to run handler in.
                   1245:         */
1.185     mycroft  1246:        __asm("movl %w0,%%gs" : : "r" (GSEL(GUDATA_SEL, SEL_UPL)));
                   1247:        __asm("movl %w0,%%fs" : : "r" (GSEL(GUDATA_SEL, SEL_UPL)));
                   1248:        tf->tf_es = GSEL(GUDATA_SEL, SEL_UPL);
                   1249:        tf->tf_ds = GSEL(GUDATA_SEL, SEL_UPL);
1.425   ! jdolecek 1250:        tf->tf_eip = (int)p->p_sigctx.ps_sigcode;
1.185     mycroft  1251:        tf->tf_cs = GSEL(GUCODE_SEL, SEL_UPL);
1.198     mycroft  1252:        tf->tf_eflags &= ~(PSL_T|PSL_VM|PSL_AC);
1.185     mycroft  1253:        tf->tf_esp = (int)fp;
1.177     mycroft  1254:        tf->tf_ss = GSEL(GUDATA_SEL, SEL_UPL);
1.319     mycroft  1255:
                   1256:        /* Remember that we're now on the signal stack. */
                   1257:        if (onstack)
1.425   ! jdolecek 1258:                p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK;
1.1       cgd      1259: }
                   1260:
                   1261: /*
                   1262:  * System call to cleanup state after a signal
                   1263:  * has been taken.  Reset signal mask and
                   1264:  * stack state from context left by sendsig (above).
                   1265:  * Return to previous pc and psl as specified by
                   1266:  * context left by sendsig. Check carefully to
                   1267:  * make sure that the user has not modified the
1.110     mycroft  1268:  * psl to gain improper privileges or to cause
1.1       cgd      1269:  * a machine fault.
                   1270:  */
1.195     mycroft  1271: int
1.320     mycroft  1272: sys___sigreturn14(p, v, retval)
1.1       cgd      1273:        struct proc *p;
1.172     thorpej  1274:        void *v;
                   1275:        register_t *retval;
                   1276: {
1.320     mycroft  1277:        struct sys___sigreturn14_args /* {
1.123     cgd      1278:                syscallarg(struct sigcontext *) sigcntxp;
1.172     thorpej  1279:        } */ *uap = v;
1.82      ws       1280:        struct sigcontext *scp, context;
1.298     mycroft  1281:        struct trapframe *tf;
1.59      mycroft  1282:
1.27      cgd      1283:        /*
1.59      mycroft  1284:         * The trampoline code hands us the context.
                   1285:         * It is unsafe to keep track of it ourselves, in the event that a
                   1286:         * program jumps out of a signal handler.
1.27      cgd      1287:         */
1.123     cgd      1288:        scp = SCARG(uap, sigcntxp);
1.87      mycroft  1289:        if (copyin((caddr_t)scp, &context, sizeof(*scp)) != 0)
1.122     mycroft  1290:                return (EFAULT);
1.1       cgd      1291:
1.319     mycroft  1292:        /* Restore register context. */
                   1293:        tf = p->p_md.md_regs;
1.157     mycroft  1294: #ifdef VM86
                   1295:        if (context.sc_eflags & PSL_VM) {
1.422     mycroft  1296:                void syscall_vm86 __P((struct trapframe));
                   1297:
1.157     mycroft  1298:                tf->tf_vm86_gs = context.sc_gs;
                   1299:                tf->tf_vm86_fs = context.sc_fs;
                   1300:                tf->tf_vm86_es = context.sc_es;
                   1301:                tf->tf_vm86_ds = context.sc_ds;
1.196     mycroft  1302:                set_vflags(p, context.sc_eflags);
1.422     mycroft  1303:                p->p_md.md_syscall = syscall_vm86;
1.157     mycroft  1304:        } else
                   1305: #endif
                   1306:        {
1.196     mycroft  1307:                /*
                   1308:                 * Check for security violations.  If we're returning to
                   1309:                 * protected mode, the CPU will validate the segment registers
                   1310:                 * automatically and generate a trap on violations.  We handle
                   1311:                 * the trap, rather than doing all of the checking here.
                   1312:                 */
                   1313:                if (((context.sc_eflags ^ tf->tf_eflags) & PSL_USERSTATIC) != 0 ||
                   1314:                    !USERMODE(context.sc_cs, context.sc_eflags))
                   1315:                        return (EINVAL);
                   1316:
1.157     mycroft  1317:                /* %fs and %gs were restored by the trampoline. */
                   1318:                tf->tf_es = context.sc_es;
                   1319:                tf->tf_ds = context.sc_ds;
1.184     mycroft  1320:                tf->tf_eflags = context.sc_eflags;
1.157     mycroft  1321:        }
1.184     mycroft  1322:        tf->tf_edi = context.sc_edi;
                   1323:        tf->tf_esi = context.sc_esi;
                   1324:        tf->tf_ebp = context.sc_ebp;
                   1325:        tf->tf_ebx = context.sc_ebx;
                   1326:        tf->tf_edx = context.sc_edx;
                   1327:        tf->tf_ecx = context.sc_ecx;
                   1328:        tf->tf_eax = context.sc_eax;
                   1329:        tf->tf_eip = context.sc_eip;
                   1330:        tf->tf_cs = context.sc_cs;
                   1331:        tf->tf_esp = context.sc_esp;
                   1332:        tf->tf_ss = context.sc_ss;
1.196     mycroft  1333:
1.319     mycroft  1334:        /* Restore signal stack. */
                   1335:        if (context.sc_onstack & SS_ONSTACK)
1.425   ! jdolecek 1336:                p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK;
1.196     mycroft  1337:        else
1.425   ! jdolecek 1338:                p->p_sigctx.ps_sigstk.ss_flags &= ~SS_ONSTACK;
1.319     mycroft  1339:
                   1340:        /* Restore signal mask. */
                   1341:        (void) sigprocmask1(p, SIG_SETMASK, &context.sc_mask, 0);
1.72      mycroft  1342:
1.122     mycroft  1343:        return (EJUSTRETURN);
1.37      cgd      1344: }
                   1345:
1.1       cgd      1346: int    waittime = -1;
                   1347: struct pcb dumppcb;
                   1348:
1.32      andrew   1349: void
1.228     gwr      1350: cpu_reboot(howto, bootstr)
1.193     mycroft  1351:        int howto;
1.206     mrg      1352:        char *bootstr;
1.1       cgd      1353: {
                   1354:
1.106     mycroft  1355:        if (cold) {
1.193     mycroft  1356:                howto |= RB_HALT;
                   1357:                goto haltsys;
1.1       cgd      1358:        }
1.193     mycroft  1359:
1.106     mycroft  1360:        boothowto = howto;
1.193     mycroft  1361:        if ((howto & RB_NOSYNC) == 0 && waittime < 0) {
1.1       cgd      1362:                waittime = 0;
1.150     mycroft  1363:                vfs_shutdown();
1.59      mycroft  1364:                /*
                   1365:                 * If we've been adjusting the clock, the todr
                   1366:                 * will be out of synch; adjust it now.
                   1367:                 */
                   1368:                resettodr();
1.1       cgd      1369:        }
1.193     mycroft  1370:
                   1371:        /* Disable interrupts. */
1.1       cgd      1372:        splhigh();
1.193     mycroft  1373:
                   1374:        /* Do a dump if requested. */
                   1375:        if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP)
                   1376:                dumpsys();
                   1377:
                   1378: haltsys:
                   1379:        doshutdownhooks();
                   1380:
1.307     thorpej  1381:        if ((howto & RB_POWERDOWN) == RB_POWERDOWN) {
1.208     jtk      1382: #if NAPM > 0 && !defined(APM_NO_POWEROFF)
                   1383:                /* turn off, if we can.  But try to turn disk off and
                   1384:                 * wait a bit first--some disk drives are slow to clean up
                   1385:                 * and users have reported disk corruption.
                   1386:                 */
                   1387:                delay(500000);
                   1388:                apm_set_powstate(APM_DEV_DISK(0xff), APM_SYS_OFF);
                   1389:                delay(500000);
                   1390:                apm_set_powstate(APM_DEV_ALLDEVS, APM_SYS_OFF);
1.307     thorpej  1391:                printf("WARNING: powerdown failed!\n");
                   1392:                /*
                   1393:                 * RB_POWERDOWN implies RB_HALT... fall into it...
                   1394:                 */
1.208     jtk      1395: #endif
1.307     thorpej  1396:        }
                   1397:
                   1398:        if (howto & RB_HALT) {
1.210     christos 1399:                printf("\n");
                   1400:                printf("The operating system has halted.\n");
                   1401:                printf("Please press any key to reboot.\n\n");
1.300     drochner 1402:                cnpollc(1);     /* for proper keyboard command handling */
1.12      cgd      1403:                cngetc();
1.300     drochner 1404:                cnpollc(0);
1.1       cgd      1405:        }
1.193     mycroft  1406:
1.210     christos 1407:        printf("rebooting...\n");
1.328     bouyer   1408:        if (cpureset_delay > 0)
                   1409:                delay(cpureset_delay * 1000);
1.1       cgd      1410:        cpu_reset();
                   1411:        for(;;) ;
                   1412:        /*NOTREACHED*/
                   1413: }
                   1414:
1.116     gwr      1415: /*
                   1416:  * These variables are needed by /sbin/savecore
                   1417:  */
                   1418: u_long dumpmag = 0x8fca0101;   /* magic number */
                   1419: int    dumpsize = 0;           /* pages */
                   1420: long   dumplo = 0;             /* blocks */
                   1421:
                   1422: /*
1.291     thorpej  1423:  * cpu_dumpsize: calculate size of machine-dependent kernel core dump headers.
                   1424:  */
                   1425: int
                   1426: cpu_dumpsize()
                   1427: {
                   1428:        int size;
                   1429:
                   1430:        size = ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t)) +
                   1431:            ALIGN(mem_cluster_cnt * sizeof(phys_ram_seg_t));
                   1432:        if (roundup(size, dbtob(1)) != dbtob(1))
                   1433:                return (-1);
                   1434:
                   1435:        return (1);
                   1436: }
                   1437:
                   1438: /*
                   1439:  * cpu_dump_mempagecnt: calculate the size of RAM (in pages) to be dumped.
                   1440:  */
                   1441: u_long
                   1442: cpu_dump_mempagecnt()
                   1443: {
                   1444:        u_long i, n;
                   1445:
                   1446:        n = 0;
                   1447:        for (i = 0; i < mem_cluster_cnt; i++)
                   1448:                n += atop(mem_clusters[i].size);
                   1449:        return (n);
                   1450: }
                   1451:
                   1452: /*
                   1453:  * cpu_dump: dump the machine-dependent kernel core dump headers.
                   1454:  */
                   1455: int
                   1456: cpu_dump()
                   1457: {
                   1458:        int (*dump) __P((dev_t, daddr_t, caddr_t, size_t));
                   1459:        char buf[dbtob(1)];
                   1460:        kcore_seg_t *segp;
                   1461:        cpu_kcore_hdr_t *cpuhdrp;
                   1462:        phys_ram_seg_t *memsegp;
                   1463:        int i;
                   1464:
                   1465:        dump = bdevsw[major(dumpdev)].d_dump;
                   1466:
1.313     perry    1467:        memset(buf, 0, sizeof buf);
1.291     thorpej  1468:        segp = (kcore_seg_t *)buf;
                   1469:        cpuhdrp = (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(*segp))];
                   1470:        memsegp = (phys_ram_seg_t *)&buf[ ALIGN(sizeof(*segp)) +
                   1471:            ALIGN(sizeof(*cpuhdrp))];
                   1472:
                   1473:        /*
                   1474:         * Generate a segment header.
                   1475:         */
                   1476:        CORE_SETMAGIC(*segp, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
                   1477:        segp->c_size = dbtob(1) - ALIGN(sizeof(*segp));
                   1478:
                   1479:        /*
                   1480:         * Add the machine-dependent header info.
                   1481:         */
                   1482:        cpuhdrp->ptdpaddr = PTDpaddr;
                   1483:        cpuhdrp->nmemsegs = mem_cluster_cnt;
                   1484:
                   1485:        /*
                   1486:         * Fill in the memory segment descriptors.
                   1487:         */
                   1488:        for (i = 0; i < mem_cluster_cnt; i++) {
                   1489:                memsegp[i].start = mem_clusters[i].start;
                   1490:                memsegp[i].size = mem_clusters[i].size;
                   1491:        }
                   1492:
                   1493:        return (dump(dumpdev, dumplo, (caddr_t)buf, dbtob(1)));
                   1494: }
                   1495:
                   1496: /*
1.228     gwr      1497:  * This is called by main to set dumplo and dumpsize.
1.414     thorpej  1498:  * Dumps always skip the first PAGE_SIZE of disk space
1.116     gwr      1499:  * in case there might be a disk label stored there.
                   1500:  * If there is extra space, put dump at the end to
                   1501:  * reduce the chance that swapping trashes it.
                   1502:  */
                   1503: void
1.228     gwr      1504: cpu_dumpconf()
1.116     gwr      1505: {
1.291     thorpej  1506:        int nblks, dumpblks;    /* size of dump area */
1.116     gwr      1507:        int maj;
                   1508:
                   1509:        if (dumpdev == NODEV)
1.291     thorpej  1510:                goto bad;
1.116     gwr      1511:        maj = major(dumpdev);
                   1512:        if (maj < 0 || maj >= nblkdev)
                   1513:                panic("dumpconf: bad dumpdev=0x%x", dumpdev);
1.134     mycroft  1514:        if (bdevsw[maj].d_psize == NULL)
1.291     thorpej  1515:                goto bad;
1.134     mycroft  1516:        nblks = (*bdevsw[maj].d_psize)(dumpdev);
1.116     gwr      1517:        if (nblks <= ctod(1))
1.291     thorpej  1518:                goto bad;
1.116     gwr      1519:
1.291     thorpej  1520:        dumpblks = cpu_dumpsize();
                   1521:        if (dumpblks < 0)
                   1522:                goto bad;
                   1523:        dumpblks += ctod(cpu_dump_mempagecnt());
                   1524:
                   1525:        /* If dump won't fit (incl. room for possible label), punt. */
                   1526:        if (dumpblks > (nblks - ctod(1)))
                   1527:                goto bad;
                   1528:
                   1529:        /* Put dump at end of partition */
                   1530:        dumplo = nblks - dumpblks;
                   1531:
                   1532:        /* dumpsize is in page units, and doesn't include headers. */
                   1533:        dumpsize = cpu_dump_mempagecnt();
                   1534:        return;
1.116     gwr      1535:
1.291     thorpej  1536:  bad:
                   1537:        dumpsize = 0;
1.116     gwr      1538: }
                   1539:
1.1       cgd      1540: /*
                   1541:  * Doadump comes here after turning off memory management and
                   1542:  * getting on the dump stack, either when called above, or by
                   1543:  * the auto-restart code.
                   1544:  */
1.414     thorpej  1545: #define BYTES_PER_DUMP  PAGE_SIZE /* must be a multiple of pagesize XXX small */
1.314     thorpej  1546: static vaddr_t dumpspace;
1.163     cgd      1547:
1.314     thorpej  1548: vaddr_t
1.163     cgd      1549: reserve_dumppages(p)
1.314     thorpej  1550:        vaddr_t p;
1.163     cgd      1551: {
                   1552:
                   1553:        dumpspace = p;
                   1554:        return (p + BYTES_PER_DUMP);
                   1555: }
                   1556:
1.32      andrew   1557: void
1.1       cgd      1558: dumpsys()
                   1559: {
1.291     thorpej  1560:        u_long totalbytesleft, bytes, i, n, memseg;
                   1561:        u_long maddr;
                   1562:        int psize;
1.163     cgd      1563:        daddr_t blkno;
                   1564:        int (*dump) __P((dev_t, daddr_t, caddr_t, size_t));
1.200     christos 1565:        int error;
1.193     mycroft  1566:
                   1567:        /* Save registers. */
                   1568:        savectx(&dumppcb);
1.1       cgd      1569:
                   1570:        if (dumpdev == NODEV)
                   1571:                return;
1.163     cgd      1572:
                   1573:        /*
                   1574:         * For dumps during autoconfiguration,
                   1575:         * if dump device has already configured...
                   1576:         */
                   1577:        if (dumpsize == 0)
1.228     gwr      1578:                cpu_dumpconf();
1.330     jtk      1579:        if (dumplo <= 0 || dumpsize == 0) {
1.275     mycroft  1580:                printf("\ndump to dev %u,%u not possible\n", major(dumpdev),
                   1581:                    minor(dumpdev));
1.163     cgd      1582:                return;
1.275     mycroft  1583:        }
                   1584:        printf("\ndumping to dev %u,%u offset %ld\n", major(dumpdev),
                   1585:            minor(dumpdev), dumplo);
1.134     mycroft  1586:
1.163     cgd      1587:        psize = (*bdevsw[major(dumpdev)].d_psize)(dumpdev);
1.210     christos 1588:        printf("dump ");
1.163     cgd      1589:        if (psize == -1) {
1.210     christos 1590:                printf("area unavailable\n");
1.163     cgd      1591:                return;
                   1592:        }
                   1593:
                   1594: #if 0  /* XXX this doesn't work.  grr. */
                   1595:         /* toss any characters present prior to dump */
                   1596:        while (sget() != NULL); /*syscons and pccons differ */
                   1597: #endif
                   1598:
1.291     thorpej  1599:        if ((error = cpu_dump()) != 0)
                   1600:                goto err;
                   1601:
                   1602:        totalbytesleft = ptoa(cpu_dump_mempagecnt());
                   1603:        blkno = dumplo + cpu_dumpsize();
1.163     cgd      1604:        dump = bdevsw[major(dumpdev)].d_dump;
1.200     christos 1605:        error = 0;
1.291     thorpej  1606:
                   1607:        for (memseg = 0; memseg < mem_cluster_cnt; memseg++) {
                   1608:                maddr = mem_clusters[memseg].start;
                   1609:                bytes = mem_clusters[memseg].size;
                   1610:
                   1611:                for (i = 0; i < bytes; i += n, totalbytesleft -= n) {
                   1612:                        /* Print out how many MBs we have left to go. */
                   1613:                        if ((totalbytesleft % (1024*1024)) == 0)
                   1614:                                printf("%ld ", totalbytesleft / (1024 * 1024));
                   1615:
                   1616:                        /* Limit size for next transfer. */
                   1617:                        n = bytes - i;
                   1618:                        if (n > BYTES_PER_DUMP)
                   1619:                                n = BYTES_PER_DUMP;
                   1620:
                   1621:                        (void) pmap_map(dumpspace, maddr, maddr + n,
                   1622:                            VM_PROT_READ);
                   1623:
                   1624:                        error = (*dump)(dumpdev, blkno, (caddr_t)dumpspace, n);
                   1625:                        if (error)
                   1626:                                goto err;
1.163     cgd      1627:                        maddr += n;
1.291     thorpej  1628:                        blkno += btodb(n);              /* XXX? */
1.163     cgd      1629:
                   1630: #if 0  /* XXX this doesn't work.  grr. */
1.291     thorpej  1631:                        /* operator aborting dump? */
                   1632:                        if (sget() != NULL) {
                   1633:                                error = EINTR;
                   1634:                                break;
                   1635:                        }
                   1636: #endif
1.163     cgd      1637:                }
                   1638:        }
                   1639:
1.291     thorpej  1640:  err:
1.163     cgd      1641:        switch (error) {
1.1       cgd      1642:
                   1643:        case ENXIO:
1.210     christos 1644:                printf("device bad\n");
1.1       cgd      1645:                break;
                   1646:
                   1647:        case EFAULT:
1.210     christos 1648:                printf("device not ready\n");
1.1       cgd      1649:                break;
                   1650:
                   1651:        case EINVAL:
1.210     christos 1652:                printf("area improper\n");
1.1       cgd      1653:                break;
                   1654:
                   1655:        case EIO:
1.210     christos 1656:                printf("i/o error\n");
1.1       cgd      1657:                break;
                   1658:
                   1659:        case EINTR:
1.210     christos 1660:                printf("aborted from console\n");
1.1       cgd      1661:                break;
                   1662:
1.163     cgd      1663:        case 0:
1.210     christos 1664:                printf("succeeded\n");
1.163     cgd      1665:                break;
                   1666:
1.1       cgd      1667:        default:
1.210     christos 1668:                printf("error %d\n", error);
1.1       cgd      1669:                break;
                   1670:        }
1.210     christos 1671:        printf("\n\n");
1.163     cgd      1672:        delay(5000000);         /* 5 seconds */
1.1       cgd      1673: }
                   1674:
                   1675: /*
                   1676:  * Clear registers on exec
                   1677:  */
1.33      cgd      1678: void
1.251     mycroft  1679: setregs(p, pack, stack)
1.1       cgd      1680:        struct proc *p;
1.151     christos 1681:        struct exec_package *pack;
1.21      cgd      1682:        u_long stack;
1.1       cgd      1683: {
1.298     mycroft  1684:        struct pcb *pcb = &p->p_addr->u_pcb;
                   1685:        struct trapframe *tf;
1.1       cgd      1686:
1.161     mycroft  1687: #if NNPX > 0
                   1688:        /* If we were using the FPU, forget about it. */
                   1689:        if (npxproc == p)
1.166     mycroft  1690:                npxdrop();
1.161     mycroft  1691: #endif
1.166     mycroft  1692:
1.178     mycroft  1693: #ifdef USER_LDT
1.353     thorpej  1694:        pmap_ldt_cleanup(p);
1.178     mycroft  1695: #endif
                   1696:
1.167     mycroft  1697:        p->p_md.md_flags &= ~MDP_USEDFPU;
1.178     mycroft  1698:        pcb->pcb_flags = 0;
1.276     mycroft  1699:        pcb->pcb_savefpu.sv_env.en_cw = __NetBSD_NPXCW__;
1.59      mycroft  1700:
1.154     mycroft  1701:        tf = p->p_md.md_regs;
1.178     mycroft  1702:        __asm("movl %w0,%%gs" : : "r" (LSEL(LUDATA_SEL, SEL_UPL)));
                   1703:        __asm("movl %w0,%%fs" : : "r" (LSEL(LUDATA_SEL, SEL_UPL)));
1.154     mycroft  1704:        tf->tf_es = LSEL(LUDATA_SEL, SEL_UPL);
                   1705:        tf->tf_ds = LSEL(LUDATA_SEL, SEL_UPL);
1.252     mycroft  1706:        tf->tf_edi = 0;
                   1707:        tf->tf_esi = 0;
1.154     mycroft  1708:        tf->tf_ebp = 0;
1.160     mycroft  1709:        tf->tf_ebx = (int)PS_STRINGS;
1.252     mycroft  1710:        tf->tf_edx = 0;
                   1711:        tf->tf_ecx = 0;
                   1712:        tf->tf_eax = 0;
1.154     mycroft  1713:        tf->tf_eip = pack->ep_entry;
                   1714:        tf->tf_cs = LSEL(LUCODE_SEL, SEL_UPL);
                   1715:        tf->tf_eflags = PSL_USERSET;
                   1716:        tf->tf_esp = stack;
                   1717:        tf->tf_ss = LSEL(LUDATA_SEL, SEL_UPL);
1.1       cgd      1718: }
                   1719:
                   1720: /*
1.55      brezak   1721:  * Initialize segments and descriptor tables
1.1       cgd      1722:  */
                   1723:
1.275     mycroft  1724: union  descriptor *idt, *gdt, *ldt;
                   1725: #ifdef I586_CPU
                   1726: union  descriptor *pentium_idt;
                   1727: #endif
1.178     mycroft  1728: extern  struct user *proc0paddr;
1.49      brezak   1729:
1.178     mycroft  1730: void
                   1731: setgate(gd, func, args, type, dpl)
                   1732:        struct gate_descriptor *gd;
                   1733:        void *func;
                   1734:        int args, type, dpl;
                   1735: {
1.1       cgd      1736:
1.178     mycroft  1737:        gd->gd_looffset = (int)func;
                   1738:        gd->gd_selector = GSEL(GCODE_SEL, SEL_KPL);
                   1739:        gd->gd_stkcpy = args;
                   1740:        gd->gd_xx = 0;
                   1741:        gd->gd_type = type;
                   1742:        gd->gd_dpl = dpl;
                   1743:        gd->gd_p = 1;
                   1744:        gd->gd_hioffset = (int)func >> 16;
                   1745: }
                   1746:
                   1747: void
                   1748: setregion(rd, base, limit)
                   1749:        struct region_descriptor *rd;
                   1750:        void *base;
                   1751:        size_t limit;
                   1752: {
                   1753:
                   1754:        rd->rd_limit = (int)limit;
                   1755:        rd->rd_base = (int)base;
                   1756: }
1.1       cgd      1757:
1.174     mycroft  1758: void
                   1759: setsegment(sd, base, limit, type, dpl, def32, gran)
                   1760:        struct segment_descriptor *sd;
                   1761:        void *base;
                   1762:        size_t limit;
                   1763:        int type, dpl, def32, gran;
                   1764: {
1.1       cgd      1765:
1.174     mycroft  1766:        sd->sd_lolimit = (int)limit;
                   1767:        sd->sd_lobase = (int)base;
                   1768:        sd->sd_type = type;
                   1769:        sd->sd_dpl = dpl;
                   1770:        sd->sd_p = 1;
                   1771:        sd->sd_hilimit = (int)limit >> 16;
                   1772:        sd->sd_xx = 0;
                   1773:        sd->sd_def32 = def32;
                   1774:        sd->sd_gran = gran;
                   1775:        sd->sd_hibase = (int)base >> 24;
                   1776: }
1.1       cgd      1777:
                   1778: #define        IDTVEC(name)    __CONCAT(X, name)
1.299     mycroft  1779: typedef void (vector) __P((void));
                   1780: extern vector IDTVEC(syscall);
                   1781: extern vector IDTVEC(osyscall);
                   1782: extern vector *IDTVEC(exceptions)[];
1.333     christos 1783: #ifdef COMPAT_SVR4
                   1784: extern vector IDTVEC(svr4_fasttrap);
                   1785: #endif /* COMPAT_SVR4 */
1.1       cgd      1786:
1.381     thorpej  1787: #define        KBTOB(x)        ((size_t)(x) * 1024UL)
                   1788:
1.59      mycroft  1789: void
1.43      brezak   1790: init386(first_avail)
1.314     thorpej  1791:        vaddr_t first_avail;
1.2       cgd      1792: {
1.148     mycroft  1793:        extern void consinit __P((void));
1.375     drochner 1794:        extern struct extent *iomem_ex;
1.401     thorpej  1795:        struct btinfo_memmap *bim;
1.381     thorpej  1796:        struct region_descriptor region;
1.401     thorpej  1797:        int x, first16q;
                   1798:        u_int64_t seg_start, seg_end;
                   1799:        u_int64_t seg_start1, seg_end1;
1.1       cgd      1800:
                   1801:        proc0.p_addr = proc0paddr;
1.284     mrg      1802:        curpcb = &proc0.p_addr->u_pcb;
1.275     mycroft  1803:
1.375     drochner 1804:        i386_bus_space_init();
1.204     thorpej  1805:
1.84      cgd      1806:        consinit();     /* XXX SHOULD NOT BE DONE HERE */
1.1       cgd      1807:
1.401     thorpej  1808:        /*
                   1809:         * Initailize PAGE_SIZE-dependent variables.
                   1810:         */
                   1811:        uvm_setpagesize();
1.275     mycroft  1812:
1.401     thorpej  1813:        /*
                   1814:         * A quick sanity check.
                   1815:         */
                   1816:        if (PAGE_SIZE != NBPG)
                   1817:                panic("init386: PAGE_SIZE != NBPG");
                   1818:
1.414     thorpej  1819: #if NBIOSCALL > 0
                   1820:        avail_start = 3*PAGE_SIZE; /* save us a page for trampoline code and
                   1821:                                      one additional PT page! */
                   1822: #else
                   1823:        avail_start = PAGE_SIZE; /* BIOS leaves data in low memory */
                   1824:                                 /* and VM system doesn't work with phys 0 */
                   1825: #endif
                   1826:
1.401     thorpej  1827:        /*
                   1828:         * Call pmap initialization to make new kernel address space.
                   1829:         * We must do this before loading pages into the VM system.
                   1830:         */
1.314     thorpej  1831:        pmap_bootstrap((vaddr_t)atdevbase + IOM_SIZE);
1.2       cgd      1832:
1.401     thorpej  1833:        /*
                   1834:         * Check to see if we have a memory map from the BIOS (passed
                   1835:         * to us by the boot program.
                   1836:         */
                   1837:        bim = lookup_bootinfo(BTINFO_MEMMAP);
1.407     enami    1838:        if (bim != NULL && bim->num > 0) {
1.409     kim      1839: #if DEBUG_MEMLOAD
1.401     thorpej  1840:                printf("BIOS MEMORY MAP (%d ENTRIES):\n", bim->num);
                   1841: #endif
                   1842:                for (x = 0; x < bim->num; x++) {
1.409     kim      1843: #if DEBUG_MEMLOAD
1.401     thorpej  1844:                        printf("    addr 0x%qx  size 0x%qx  type 0x%x\n",
                   1845:                            bim->entry[x].addr,
                   1846:                            bim->entry[x].size,
                   1847:                            bim->entry[x].type);
                   1848: #endif
                   1849:
                   1850:                        /*
                   1851:                         * If the segment is not memory, skip it.
                   1852:                         */
                   1853:                        switch (bim->entry[x].type) {
                   1854:                        case BIM_Memory:
                   1855:                        case BIM_ACPI:
                   1856:                        case BIM_NVS:
                   1857:                                break;
                   1858:                        default:
                   1859:                                continue;
                   1860:                        }
                   1861:
                   1862:                        /*
                   1863:                         * Sanity check the entry.
                   1864:                         * XXX Need to handle uint64_t in extent code
                   1865:                         * XXX and 64-bit physical addresses in i386
                   1866:                         * XXX port.
                   1867:                         */
                   1868:                        seg_start = bim->entry[x].addr;
                   1869:                        seg_end = bim->entry[x].addr + bim->entry[x].size;
                   1870:
                   1871:                        if (seg_end > 0x100000000ULL) {
                   1872:                                printf("WARNING: skipping large "
                   1873:                                    "memory map entry: "
                   1874:                                    "0x%qx/0x%qx/0x%x\n",
                   1875:                                    bim->entry[x].addr,
                   1876:                                    bim->entry[x].size,
                   1877:                                    bim->entry[x].type);
                   1878:                                continue;
                   1879:                        }
                   1880:
                   1881:                        /*
                   1882:                         * XXX Chop the last page off the size so that
                   1883:                         * XXX it can fit in avail_end.
                   1884:                         */
                   1885:                        if (seg_end == 0x100000000ULL)
                   1886:                                seg_end -= PAGE_SIZE;
                   1887:
                   1888:                        /*
                   1889:                         * Allocate the physical addresses used by RAM
                   1890:                         * from the iomem extent map.  This is done before
                   1891:                         * the addresses are page rounded just to make
                   1892:                         * sure we get them all.
                   1893:                         */
                   1894:                        if (extent_alloc_region(iomem_ex, seg_start,
                   1895:                            seg_end - seg_start, EX_NOWAIT)) {
                   1896:                                /* XXX What should we do? */
                   1897:                                printf("WARNING: CAN'T ALLOCATE "
                   1898:                                    "MEMORY SEGMENT %d "
                   1899:                                    "(0x%qx/0x%qx/0x%x) FROM "
                   1900:                                    "IOMEM EXTENT MAP!\n",
                   1901:                                    x, seg_start, seg_end - seg_start,
                   1902:                                    bim->entry[x].type);
                   1903:                        }
                   1904:
                   1905:                        /*
                   1906:                         * If it's not free memory, skip it.
                   1907:                         */
                   1908:                        if (bim->entry[x].type != BIM_Memory)
                   1909:                                continue;
                   1910:
                   1911:                        /* XXX XXX XXX */
                   1912:                        if (mem_cluster_cnt >= VM_PHYSSEG_MAX)
                   1913:                                panic("init386: too many memory segments");
                   1914:
                   1915:                        seg_start = round_page(seg_start);
                   1916:                        seg_end = trunc_page(seg_end);
                   1917:
                   1918:                        if (seg_start == seg_end)
                   1919:                                continue;
                   1920:
                   1921:                        mem_clusters[mem_cluster_cnt].start = seg_start;
                   1922:                        mem_clusters[mem_cluster_cnt].size =
                   1923:                            seg_end - seg_start;
                   1924:
                   1925:                        if (avail_end < seg_end)
                   1926:                                avail_end = seg_end;
                   1927:                        physmem += atop(mem_clusters[mem_cluster_cnt].size);
                   1928:                        mem_cluster_cnt++;
                   1929:                }
1.421     aymeric  1930:        }
                   1931:
                   1932:        /*
                   1933:         * If the loop above didn't find any valid segment, fall back to
                   1934:         * former code.
                   1935:         */
                   1936:        if (mem_cluster_cnt == 0) {
1.401     thorpej  1937:                /*
                   1938:                 * Allocate the physical addresses used by RAM from the iomem
                   1939:                 * extent map.  This is done before the addresses are
                   1940:                 * page rounded just to make sure we get them all.
                   1941:                 */
                   1942:                if (extent_alloc_region(iomem_ex, 0, KBTOB(biosbasemem),
                   1943:                    EX_NOWAIT)) {
                   1944:                        /* XXX What should we do? */
                   1945:                        printf("WARNING: CAN'T ALLOCATE BASE MEMORY FROM "
                   1946:                            "IOMEM EXTENT MAP!\n");
                   1947:                }
                   1948:                mem_clusters[0].start = 0;
                   1949:                mem_clusters[0].size = trunc_page(KBTOB(biosbasemem));
                   1950:                physmem += atop(mem_clusters[0].size);
                   1951:                if (extent_alloc_region(iomem_ex, IOM_END, KBTOB(biosextmem),
                   1952:                    EX_NOWAIT)) {
                   1953:                        /* XXX What should we do? */
                   1954:                        printf("WARNING: CAN'T ALLOCATE EXTENDED MEMORY FROM "
                   1955:                            "IOMEM EXTENT MAP!\n");
                   1956:                }
                   1957: #if NISADMA > 0
                   1958:                /*
                   1959:                 * Some motherboards/BIOSes remap the 384K of RAM that would
                   1960:                 * normally be covered by the ISA hole to the end of memory
                   1961:                 * so that it can be used.  However, on a 16M system, this
                   1962:                 * would cause bounce buffers to be allocated and used.
                   1963:                 * This is not desirable behaviour, as more than 384K of
                   1964:                 * bounce buffers might be allocated.  As a work-around,
                   1965:                 * we round memory down to the nearest 1M boundary if
                   1966:                 * we're using any isadma devices and the remapped memory
                   1967:                 * is what puts us over 16M.
                   1968:                 */
                   1969:                if (biosextmem > (15*1024) && biosextmem < (16*1024)) {
                   1970:                        char pbuf[9];
                   1971:
                   1972:                        format_bytes(pbuf, sizeof(pbuf),
                   1973:                            biosextmem - (15*1024));
                   1974:                        printf("Warning: ignoring %s of remapped memory\n",
                   1975:                            pbuf);
                   1976:                        biosextmem = (15*1024);
                   1977:                }
                   1978: #endif
                   1979:                mem_clusters[1].start = IOM_END;
                   1980:                mem_clusters[1].size = trunc_page(KBTOB(biosextmem));
                   1981:                physmem += atop(mem_clusters[1].size);
                   1982:
                   1983:                mem_cluster_cnt = 2;
                   1984:
                   1985:                avail_end = IOM_END + trunc_page(KBTOB(biosextmem));
                   1986:        }
                   1987:
                   1988:        /*
                   1989:         * If we have 16M of RAM or less, just put it all on
                   1990:         * the default free list.  Otherwise, put the first
                   1991:         * 16M of RAM on a lower priority free list (so that
                   1992:         * all of the ISA DMA'able memory won't be eaten up
                   1993:         * first-off).
                   1994:         */
                   1995:        if (avail_end <= (16 * 1024 * 1024))
                   1996:                first16q = VM_FREELIST_DEFAULT;
                   1997:        else
                   1998:                first16q = VM_FREELIST_FIRST16;
                   1999:
                   2000:        /* Make sure the end of the space used by the kernel is rounded. */
                   2001:        first_avail = round_page(first_avail);
                   2002:
                   2003:        /*
                   2004:         * Now, load the memory clusters (which have already been
                   2005:         * rounded and truncated) into the VM system.
                   2006:         *
                   2007:         * NOTE: WE ASSUME THAT MEMORY STARTS AT 0 AND THAT THE KERNEL
                   2008:         * IS LOADED AT IOM_END (1M).
                   2009:         */
                   2010:        for (x = 0; x < mem_cluster_cnt; x++) {
                   2011:                seg_start = mem_clusters[x].start;
                   2012:                seg_end = mem_clusters[x].start + mem_clusters[x].size;
                   2013:                seg_start1 = 0;
                   2014:                seg_end1 = 0;
                   2015:
                   2016:                /*
                   2017:                 * Skip memory before our available starting point.
                   2018:                 */
                   2019:                if (seg_end <= avail_start)
                   2020:                        continue;
                   2021:
                   2022:                if (avail_start >= seg_start && avail_start < seg_end) {
                   2023:                        if (seg_start != 0)
                   2024:                                panic("init386: memory doesn't start at 0");
                   2025:                        seg_start = avail_start;
                   2026:                        if (seg_start == seg_end)
                   2027:                                continue;
                   2028:                }
                   2029:
                   2030:                /*
                   2031:                 * If this segment contains the kernel, split it
                   2032:                 * in two, around the kernel.
                   2033:                 */
                   2034:                if (seg_start <= IOM_END && first_avail <= seg_end) {
                   2035:                        seg_start1 = first_avail;
                   2036:                        seg_end1 = seg_end;
                   2037:                        seg_end = IOM_END;
                   2038:                }
                   2039:
                   2040:                /* First hunk */
                   2041:                if (seg_start != seg_end) {
                   2042:                        if (seg_start <= (16 * 1024 * 1024) &&
                   2043:                            first16q != VM_FREELIST_DEFAULT) {
                   2044:                                u_int64_t tmp;
                   2045:
                   2046:                                if (seg_end > (16 * 1024 * 1024))
                   2047:                                        tmp = (16 * 1024 * 1024);
                   2048:                                else
                   2049:                                        tmp = seg_end;
1.409     kim      2050: #if DEBUG_MEMLOAD
1.401     thorpej  2051:                                printf("loading 0x%qx-0x%qx (0x%lx-0x%lx)\n",
                   2052:                                    seg_start, tmp,
                   2053:                                    atop(seg_start), atop(tmp));
                   2054: #endif
                   2055:                                uvm_page_physload(atop(seg_start),
                   2056:                                    atop(tmp), atop(seg_start),
                   2057:                                    atop(tmp), first16q);
                   2058:                                seg_start = tmp;
                   2059:                        }
1.411     enami    2060:
                   2061:                        if (seg_start != seg_end) {
1.409     kim      2062: #if DEBUG_MEMLOAD
1.411     enami    2063:                                printf("loading 0x%qx-0x%qx (0x%lx-0x%lx)\n",
                   2064:                                    seg_start, seg_end,
                   2065:                                    atop(seg_start), atop(seg_end));
                   2066: #endif
                   2067:                                uvm_page_physload(atop(seg_start),
                   2068:                                    atop(seg_end), atop(seg_start),
                   2069:                                    atop(seg_end), VM_FREELIST_DEFAULT);
                   2070:                        }
1.401     thorpej  2071:                }
                   2072:
                   2073:                /* Second hunk */
                   2074:                if (seg_start1 != seg_end1) {
                   2075:                        if (seg_start1 <= (16 * 1024 * 1024) &&
                   2076:                            first16q != VM_FREELIST_DEFAULT) {
                   2077:                                u_int64_t tmp;
                   2078:
                   2079:                                if (seg_end1 > (16 * 1024 * 1024))
                   2080:                                        tmp = (16 * 1024 * 1024);
                   2081:                                else
                   2082:                                        tmp = seg_end1;
1.409     kim      2083: #if DEBUG_MEMLOAD
1.401     thorpej  2084:                                printf("loading 0x%qx-0x%qx (0x%lx-0x%lx)\n",
                   2085:                                    seg_start1, tmp,
                   2086:                                    atop(seg_start1), atop(tmp));
                   2087: #endif
                   2088:                                uvm_page_physload(atop(seg_start1),
                   2089:                                    atop(tmp), atop(seg_start1),
                   2090:                                    atop(tmp), first16q);
                   2091:                                seg_start1 = tmp;
                   2092:                        }
1.412     enami    2093:
                   2094:                        if (seg_start1 != seg_end1) {
1.409     kim      2095: #if DEBUG_MEMLOAD
1.412     enami    2096:                                printf("loading 0x%qx-0x%qx (0x%lx-0x%lx)\n",
                   2097:                                    seg_start1, seg_end1,
                   2098:                                    atop(seg_start1), atop(seg_end1));
                   2099: #endif
                   2100:                                uvm_page_physload(atop(seg_start1),
                   2101:                                    atop(seg_end1), atop(seg_start1),
                   2102:                                    atop(seg_end1), VM_FREELIST_DEFAULT);
                   2103:                        }
1.401     thorpej  2104:                }
                   2105:        }
                   2106:
                   2107:        /*
                   2108:         * Steal memory for the message buffer (at end of core).
                   2109:         */
                   2110:        {
                   2111:                struct vm_physseg *vps;
                   2112:                psize_t sz = round_page(MSGBUFSIZE);
                   2113:                psize_t reqsz = sz;
                   2114:
                   2115:                for (x = 0; x < vm_nphysseg; x++) {
                   2116:                        vps = &vm_physmem[x];
                   2117:                        if (ptoa(vps->avail_end) == avail_end)
                   2118:                                break;
                   2119:                }
                   2120:                if (x == vm_nphysseg)
1.410     christos 2121:                        panic("init386: can't find end of memory");
1.401     thorpej  2122:
                   2123:                /* Shrink so it'll fit in the last segment. */
                   2124:                if ((vps->avail_end - vps->avail_start) < atop(sz))
                   2125:                        sz = ptoa(vps->avail_end - vps->avail_start);
                   2126:
                   2127:                vps->avail_end -= atop(sz);
                   2128:                vps->end -= atop(sz);
                   2129:                msgbuf_paddr = ptoa(vps->avail_end);
                   2130:
                   2131:                /* Remove the last segment if it now has no pages. */
                   2132:                if (vps->start == vps->end) {
                   2133:                        for (vm_nphysseg--; x < vm_nphysseg; x++)
                   2134:                                vm_physmem[x] = vm_physmem[x + 1];
                   2135:                }
                   2136:
                   2137:                /* Now find where the new avail_end is. */
                   2138:                for (avail_end = 0, x = 0; x < vm_nphysseg; x++)
                   2139:                        if (vm_physmem[x].avail_end > avail_end)
                   2140:                                avail_end = vm_physmem[x].avail_end;
                   2141:                avail_end = ptoa(avail_end);
                   2142:
                   2143:                /* Warn if the message buffer had to be shrunk. */
                   2144:                if (sz != reqsz)
                   2145:                        printf("WARNING: %ld bytes not available for msgbuf "
                   2146:                            "in last cluster (%ld used)\n", reqsz, sz);
                   2147:        }
                   2148:
1.295     drochner 2149: #if NBIOSCALL > 0
                   2150:        /* install page 2 (reserved above) as PT page for first 4M */
1.414     thorpej  2151:        pmap_enter(pmap_kernel(), (vaddr_t)vtopte(0), 2*PAGE_SIZE,
1.367     thorpej  2152:            VM_PROT_READ|VM_PROT_WRITE, PMAP_WIRED|VM_PROT_READ|VM_PROT_WRITE);
1.414     thorpej  2153:        memset(vtopte(0), 0, PAGE_SIZE);/* make sure it is clean before using */
1.295     drochner 2154: #endif
1.59      mycroft  2155:
1.346     mycroft  2156:        pmap_enter(pmap_kernel(), idt_vaddr, idt_paddr,
1.367     thorpej  2157:            VM_PROT_READ|VM_PROT_WRITE, PMAP_WIRED|VM_PROT_READ|VM_PROT_WRITE);
1.275     mycroft  2158:        idt = (union descriptor *)idt_vaddr;
                   2159: #ifdef I586_CPU
1.346     mycroft  2160:        pmap_enter(pmap_kernel(), pentium_idt_vaddr, idt_paddr,
1.367     thorpej  2161:            VM_PROT_READ, PMAP_WIRED|VM_PROT_READ);
1.275     mycroft  2162:        pentium_idt = (union descriptor *)pentium_idt_vaddr;
                   2163: #endif
                   2164:        gdt = idt + NIDT;
                   2165:        ldt = gdt + NGDT;
                   2166:
                   2167:
                   2168:        /* make gdt gates and memory segments */
                   2169:        setsegment(&gdt[GCODE_SEL].sd, 0, 0xfffff, SDT_MEMERA, SEL_KPL, 1, 1);
                   2170:        setsegment(&gdt[GDATA_SEL].sd, 0, 0xfffff, SDT_MEMRWA, SEL_KPL, 1, 1);
                   2171:        setsegment(&gdt[GLDT_SEL].sd, ldt, NLDT * sizeof(ldt[0]) - 1,
                   2172:            SDT_SYSLDT, SEL_KPL, 0, 0);
                   2173:        setsegment(&gdt[GUCODE_SEL].sd, 0, i386_btop(VM_MAXUSER_ADDRESS) - 1,
                   2174:            SDT_MEMERA, SEL_UPL, 1, 1);
                   2175:        setsegment(&gdt[GUDATA_SEL].sd, 0, i386_btop(VM_MAXUSER_ADDRESS) - 1,
                   2176:            SDT_MEMRWA, SEL_UPL, 1, 1);
                   2177: #if NBIOSCALL > 0
                   2178:        /* bios trampoline GDT entries */
                   2179:        setsegment(&gdt[GBIOSCODE_SEL].sd, 0, 0xfffff, SDT_MEMERA, SEL_KPL, 0,
                   2180:            0);
                   2181:        setsegment(&gdt[GBIOSDATA_SEL].sd, 0, 0xfffff, SDT_MEMRWA, SEL_KPL, 0,
                   2182:            0);
                   2183: #endif
                   2184:
                   2185:        /* make ldt gates and memory segments */
                   2186:        setgate(&ldt[LSYS5CALLS_SEL].gd, &IDTVEC(osyscall), 1,
                   2187:            SDT_SYS386CGT, SEL_UPL);
                   2188:        ldt[LUCODE_SEL] = gdt[GUCODE_SEL];
                   2189:        ldt[LUDATA_SEL] = gdt[GUDATA_SEL];
1.324     christos 2190:        ldt[LSOL26CALLS_SEL] = ldt[LBSDICALLS_SEL] = ldt[LSYS5CALLS_SEL];
1.275     mycroft  2191:
                   2192:        /* exceptions */
                   2193:        for (x = 0; x < 32; x++)
                   2194:                setgate(&idt[x].gd, IDTVEC(exceptions)[x], 0, SDT_SYS386TGT,
                   2195:                    (x == 3 || x == 4) ? SEL_UPL : SEL_KPL);
1.257     thorpej  2196:
1.275     mycroft  2197:        /* new-style interrupt gate for syscalls */
                   2198:        setgate(&idt[128].gd, &IDTVEC(syscall), 0, SDT_SYS386TGT, SEL_UPL);
1.333     christos 2199: #ifdef COMPAT_SVR4
                   2200:        setgate(&idt[0xd2].gd, &IDTVEC(svr4_fasttrap), 0, SDT_SYS386TGT,
                   2201:            SEL_UPL);
                   2202: #endif /* COMPAT_SVR4 */
1.264     mycroft  2203:
1.275     mycroft  2204:        setregion(&region, gdt, NGDT * sizeof(gdt[0]) - 1);
                   2205:        lgdt(&region);
1.264     mycroft  2206: #ifdef I586_CPU
1.275     mycroft  2207:        setregion(&region, pentium_idt, NIDT * sizeof(idt[0]) - 1);
                   2208: #else
                   2209:        setregion(&region, idt, NIDT * sizeof(idt[0]) - 1);
                   2210: #endif
                   2211:        lidt(&region);
1.264     mycroft  2212:
1.190     mycroft  2213:
                   2214: #ifdef DDB
1.308     tv       2215:        {
                   2216:                extern int end;
                   2217:                extern int *esym;
1.336     christos 2218:                struct btinfo_symtab *symtab;
1.308     tv       2219:
1.336     christos 2220:                symtab = lookup_bootinfo(BTINFO_SYMTAB);
                   2221:                if (symtab) {
                   2222:                        symtab->ssym += KERNBASE;
                   2223:                        symtab->esym += KERNBASE;
                   2224:                        ddb_init(symtab->nsym, (int *)symtab->ssym,
                   2225:                            (int *)symtab->esym);
                   2226:                }
                   2227:                else
                   2228:                        ddb_init(*(int *)&end, ((int *)&end) + 1, esym);
1.308     tv       2229:        }
1.190     mycroft  2230:        if (boothowto & RB_KDB)
                   2231:                Debugger();
1.377     ws       2232: #endif
                   2233: #ifdef IPKDB
                   2234:        ipkdb_init();
                   2235:        if (boothowto & RB_KDB)
                   2236:                ipkdb_connect(0);
1.190     mycroft  2237: #endif
                   2238: #ifdef KGDB
1.243     drochner 2239:        kgdb_port_init();
1.235     thorpej  2240:        if (boothowto & RB_KDB) {
                   2241:                kgdb_debug_init = 1;
1.242     drochner 2242:                kgdb_connect(1);
1.235     thorpej  2243:        }
1.384     jdolecek 2244: #endif
                   2245:
                   2246: #if NMCA > 0
                   2247:        /* check for MCA bus, needed to be done before ISA stuff - if
                   2248:         * MCA is detected, ISA needs to use level triggered interrupts
                   2249:         * by default */
                   2250:        mca_busprobe();
1.190     mycroft  2251: #endif
1.275     mycroft  2252:
                   2253: #if NISA > 0
                   2254:        isa_defaultirq();
                   2255: #endif
                   2256:
                   2257:        splraise(-1);
                   2258:        enable_intr();
                   2259:
                   2260:        if (physmem < btoc(2 * 1024 * 1024)) {
                   2261:                printf("warning: too little memory available; "
1.383     mycroft  2262:                       "have %lu bytes, want %lu bytes\n"
1.275     mycroft  2263:                       "running in degraded mode\n"
                   2264:                       "press a key to confirm\n\n",
1.383     mycroft  2265:                       ptoa(physmem), 2*1024*1024UL);
1.275     mycroft  2266:                cngetc();
                   2267:        }
1.393     fvdl     2268:
                   2269:        identifycpu();
1.1       cgd      2270: }
                   2271:
1.94      mycroft  2272: struct queue {
                   2273:        struct queue *q_next, *q_prev;
                   2274: };
                   2275:
1.1       cgd      2276: /*
1.73      mycroft  2277:  * insert an element into a queue
1.1       cgd      2278:  */
1.94      mycroft  2279: void
1.188     christos 2280: _insque(v1, v2)
                   2281:        void *v1;
                   2282:        void *v2;
1.94      mycroft  2283: {
1.298     mycroft  2284:        struct queue *elem = v1, *head = v2;
                   2285:        struct queue *next;
1.94      mycroft  2286:
                   2287:        next = head->q_next;
                   2288:        elem->q_next = next;
                   2289:        head->q_next = elem;
                   2290:        elem->q_prev = head;
                   2291:        next->q_prev = elem;
1.1       cgd      2292: }
                   2293:
                   2294: /*
                   2295:  * remove an element from a queue
                   2296:  */
1.94      mycroft  2297: void
1.188     christos 2298: _remque(v)
                   2299:        void *v;
1.94      mycroft  2300: {
1.298     mycroft  2301:        struct queue *elem = v;
                   2302:        struct queue *next, *prev;
1.94      mycroft  2303:
                   2304:        next = elem->q_next;
                   2305:        prev = elem->q_prev;
                   2306:        next->q_prev = prev;
                   2307:        prev->q_next = next;
                   2308:        elem->q_prev = 0;
1.1       cgd      2309: }
                   2310:
1.107     deraadt  2311: #ifdef COMPAT_NOMID
                   2312: static int
                   2313: exec_nomid(p, epp)
1.59      mycroft  2314:        struct proc *p;
                   2315:        struct exec_package *epp;
1.31      cgd      2316: {
1.59      mycroft  2317:        int error;
                   2318:        u_long midmag, magic;
                   2319:        u_short mid;
1.80      cgd      2320:        struct exec *execp = epp->ep_hdr;
1.31      cgd      2321:
1.80      cgd      2322:        /* check on validity of epp->ep_hdr performed by exec_out_makecmds */
                   2323:
                   2324:        midmag = ntohl(execp->a_midmag);
1.59      mycroft  2325:        mid = (midmag >> 16) & 0xffff;
                   2326:        magic = midmag & 0xffff;
                   2327:
                   2328:        if (magic == 0) {
1.80      cgd      2329:                magic = (execp->a_midmag & 0xffff);
1.59      mycroft  2330:                mid = MID_ZERO;
                   2331:        }
                   2332:
                   2333:        midmag = mid << 16 | magic;
                   2334:
                   2335:        switch (midmag) {
                   2336:        case (MID_ZERO << 16) | ZMAGIC:
                   2337:                /*
                   2338:                 * 386BSD's ZMAGIC format:
                   2339:                 */
1.202     christos 2340:                error = exec_aout_prep_oldzmagic(p, epp);
1.59      mycroft  2341:                break;
                   2342:
                   2343:        case (MID_ZERO << 16) | QMAGIC:
                   2344:                /*
                   2345:                 * BSDI's QMAGIC format:
                   2346:                 * same as new ZMAGIC format, but with different magic number
                   2347:                 */
                   2348:                error = exec_aout_prep_zmagic(p, epp);
                   2349:                break;
                   2350:
1.202     christos 2351:        case (MID_ZERO << 16) | NMAGIC:
                   2352:                /*
                   2353:                 * BSDI's NMAGIC format:
                   2354:                 * same as NMAGIC format, but with different magic number
                   2355:                 * and with text starting at 0.
                   2356:                 */
                   2357:                error = exec_aout_prep_oldnmagic(p, epp);
                   2358:                break;
                   2359:
                   2360:        case (MID_ZERO << 16) | OMAGIC:
                   2361:                /*
                   2362:                 * BSDI's OMAGIC format:
                   2363:                 * same as OMAGIC format, but with different magic number
                   2364:                 * and with text starting at 0.
                   2365:                 */
                   2366:                error = exec_aout_prep_oldomagic(p, epp);
                   2367:                break;
                   2368:
1.59      mycroft  2369:        default:
                   2370:                error = ENOEXEC;
                   2371:        }
                   2372:
                   2373:        return error;
1.107     deraadt  2374: }
1.31      cgd      2375: #endif
1.107     deraadt  2376:
                   2377: /*
                   2378:  * cpu_exec_aout_makecmds():
                   2379:  *     cpu-dependent a.out format hook for execve().
                   2380:  *
                   2381:  * Determine of the given exec package refers to something which we
                   2382:  * understand and, if so, set up the vmcmds for it.
                   2383:  *
                   2384:  * On the i386, old (386bsd) ZMAGIC binaries and BSDI QMAGIC binaries
                   2385:  * if COMPAT_NOMID is given as a kernel option.
                   2386:  */
                   2387: int
                   2388: cpu_exec_aout_makecmds(p, epp)
                   2389:        struct proc *p;
                   2390:        struct exec_package *epp;
                   2391: {
                   2392:        int error = ENOEXEC;
                   2393:
                   2394: #ifdef COMPAT_NOMID
                   2395:        if ((error = exec_nomid(p, epp)) == 0)
                   2396:                return error;
                   2397: #endif /* ! COMPAT_NOMID */
                   2398:
                   2399:        return error;
1.31      cgd      2400: }
1.84      cgd      2401:
1.255     drochner 2402: void *
                   2403: lookup_bootinfo(type)
                   2404: int type;
                   2405: {
                   2406:        struct btinfo_common *help;
                   2407:        int n = *(int*)bootinfo;
                   2408:        help = (struct btinfo_common *)(bootinfo + sizeof(int));
                   2409:        while(n--) {
                   2410:                if(help->type == type)
                   2411:                        return(help);
                   2412:                help = (struct btinfo_common *)((char*)help + help->len);
                   2413:        }
                   2414:        return(0);
                   2415: }
1.149     mycroft  2416:
                   2417: void
                   2418: cpu_reset()
                   2419: {
                   2420:
1.224     mycroft  2421:        disable_intr();
                   2422:
1.227     mycroft  2423:        /*
                   2424:         * The keyboard controller has 4 random output pins, one of which is
                   2425:         * connected to the RESET pin on the CPU in many PCs.  We tell the
                   2426:         * keyboard controller to pulse this line a couple of times.
                   2427:         */
1.273     drochner 2428:        outb(IO_KBD + KBCMDP, KBC_PULSE0);
1.226     mycroft  2429:        delay(100000);
1.273     drochner 2430:        outb(IO_KBD + KBCMDP, KBC_PULSE0);
1.226     mycroft  2431:        delay(100000);
1.149     mycroft  2432:
                   2433:        /*
1.224     mycroft  2434:         * Try to cause a triple fault and watchdog reset by making the IDT
                   2435:         * invalid and causing a fault.
1.149     mycroft  2436:         */
1.313     perry    2437:        memset((caddr_t)idt, 0, NIDT * sizeof(idt[0]));
1.224     mycroft  2438:        __asm __volatile("divl %0,%1" : : "q" (0), "a" (0));
1.149     mycroft  2439:
1.224     mycroft  2440: #if 0
1.149     mycroft  2441:        /*
                   2442:         * Try to cause a triple fault and watchdog reset by unmapping the
1.224     mycroft  2443:         * entire address space and doing a TLB flush.
1.149     mycroft  2444:         */
1.414     thorpej  2445:        memset((caddr_t)PTD, 0, PAGE_SIZE);
1.149     mycroft  2446:        pmap_update();
1.224     mycroft  2447: #endif
1.149     mycroft  2448:
                   2449:        for (;;);
1.45      cgd      2450: }

CVSweb <webmaster@jp.NetBSD.org>