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

1.504   ! junyoung    1: /*     $NetBSD: machdep.c,v 1.503 2002/12/06 14:47:07 junyoung 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.460     lukem      77:
                     78: #include <sys/cdefs.h>
1.504   ! junyoung   79: __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.503 2002/12/06 14:47:07 junyoung Exp $");
1.271     thorpej    80:
                     81: #include "opt_cputype.h"
1.309     jonathan   82: #include "opt_ddb.h"
1.377     ws         83: #include "opt_ipkdb.h"
1.443     lukem      84: #include "opt_kgdb.h"
1.272     thorpej    85: #include "opt_vm86.h"
1.274     thorpej    86: #include "opt_user_ldt.h"
1.310     jonathan   87: #include "opt_compat_netbsd.h"
1.327     bouyer     88: #include "opt_cpureset_delay.h"
1.333     christos   89: #include "opt_compat_svr4.h"
1.429     chs        90: #include "opt_realmem.h"
1.447     christos   91: #include "opt_compat_mach.h"   /* need to get the right segment def */
1.455     fvdl       92: #include "opt_mtrr.h"
1.1       cgd        93:
1.59      mycroft    94: #include <sys/param.h>
                     95: #include <sys/systm.h>
                     96: #include <sys/signalvar.h>
                     97: #include <sys/kernel.h>
                     98: #include <sys/proc.h>
                     99: #include <sys/user.h>
                    100: #include <sys/exec.h>
                    101: #include <sys/buf.h>
                    102: #include <sys/reboot.h>
                    103: #include <sys/conf.h>
                    104: #include <sys/file.h>
                    105: #include <sys/malloc.h>
                    106: #include <sys/mbuf.h>
                    107: #include <sys/msgbuf.h>
                    108: #include <sys/mount.h>
                    109: #include <sys/vnode.h>
1.204     thorpej   110: #include <sys/extent.h>
1.123     cgd       111: #include <sys/syscallargs.h>
1.291     thorpej   112: #include <sys/core.h>
                    113: #include <sys/kcore.h>
                    114: #include <machine/kcore.h>
1.57      cgd       115:
1.377     ws        116: #ifdef IPKDB
                    117: #include <ipkdb/ipkdb.h>
                    118: #endif
                    119:
1.235     thorpej   120: #ifdef KGDB
                    121: #include <sys/kgdb.h>
                    122: #endif
                    123:
1.104     cgd       124: #include <dev/cons.h>
1.390     mrg       125:
                    126: #include <uvm/uvm_extern.h>
1.393     fvdl      127: #include <uvm/uvm_page.h>
1.284     mrg       128:
1.200     christos  129: #include <sys/sysctl.h>
                    130:
1.59      mycroft   131: #include <machine/cpu.h>
                    132: #include <machine/cpufunc.h>
1.484     fvdl      133: #include <machine/cpuvar.h>
1.178     mycroft   134: #include <machine/gdt.h>
1.149     mycroft   135: #include <machine/pio.h>
1.59      mycroft   136: #include <machine/psl.h>
                    137: #include <machine/reg.h>
                    138: #include <machine/specialreg.h>
1.255     drochner  139: #include <machine/bootinfo.h>
1.455     fvdl      140: #include <machine/mtrr.h>
1.43      brezak    141:
1.146     cgd       142: #include <dev/isa/isareg.h>
1.372     drochner  143: #include <machine/isa_machdep.h>
1.164     cgd       144: #include <dev/ic/i8042reg.h>
1.43      brezak    145:
1.200     christos  146: #ifdef DDB
                    147: #include <machine/db_machdep.h>
                    148: #include <ddb/db_extern.h>
                    149: #endif
                    150:
1.184     mycroft   151: #ifdef VM86
                    152: #include <machine/vm86.h>
                    153: #endif
                    154:
1.473     tshiozak  155: #include "acpi.h"
1.207     jtk       156: #include "apm.h"
1.258     jtk       157: #include "bioscall.h"
1.207     jtk       158:
1.259     jtk       159: #if NBIOSCALL > 0
                    160: #include <machine/bioscall.h>
                    161: #endif
                    162:
1.473     tshiozak  163: #if NACPI > 0
                    164: #include <dev/acpi/acpivar.h>
                    165: #define ACPI_MACHDEP_PRIVATE
                    166: #include <machine/acpi_machdep.h>
                    167: #endif
                    168:
1.207     jtk       169: #if NAPM > 0
                    170: #include <machine/apmvar.h>
1.258     jtk       171: #endif
                    172:
1.59      mycroft   173: #include "isa.h"
1.231     thorpej   174: #include "isadma.h"
1.59      mycroft   175: #include "npx.h"
1.2       cgd       176:
1.384     jdolecek  177: #include "mca.h"
                    178: #if NMCA > 0
                    179: #include <machine/mca_machdep.h>       /* for mca_busprobe() */
                    180: #endif
                    181:
1.484     fvdl      182: #ifdef MULTIPROCESSOR          /* XXX */
                    183: #include <machine/mpbiosvar.h> /* XXX */
                    184: #endif                         /* XXX */
                    185:
1.104     cgd       186: /* the following is used externally (sysctl_hw) */
                    187: char machine[] = "i386";               /* cpu "architecture" */
1.232     veego     188: char machine_arch[] = "i386";          /* machine == machine_arch */
1.104     cgd       189:
1.484     fvdl      190: volatile u_int32_t ipending;
1.471     matt      191:
1.484     fvdl      192: int imasks[NIPL];
                    193: int iunmask[NIPL];
1.471     matt      194:
1.402     explorer  195: u_int cpu_serial[3];
                    196:
1.255     drochner  197: char bootinfo[BOOTINFO_MAXSIZE];
1.386     thorpej   198:
1.484     fvdl      199: /* Our exported CPU info; we have only one right now. */
1.386     thorpej   200: struct cpu_info cpu_info_store;
1.255     drochner  201:
1.343     fvdl      202: struct bi_devmatch *i386_alldisks = NULL;
                    203: int i386_ndisks = 0;
1.342     fvdl      204:
1.328     bouyer    205: #ifdef CPURESET_DELAY
                    206: int    cpureset_delay = CPURESET_DELAY;
                    207: #else
                    208: int     cpureset_delay = 2000; /* default to 2s */
                    209: #endif
                    210:
1.455     fvdl      211: #ifdef MTRR
                    212: struct mtrr_funcs *mtrr_funcs;
                    213: #endif
                    214:
1.59      mycroft   215: int    physmem;
1.163     cgd       216: int    dumpmem_low;
                    217: int    dumpmem_high;
1.59      mycroft   218: int    cpu_class;
1.428     fvdl      219: int    i386_fpu_present;
                    220: int    i386_fpu_exception;
                    221: int    i386_fpu_fdivbug;
1.59      mycroft   222:
1.451     thorpej   223: int    i386_use_fxsave;
                    224: int    i386_has_sse;
                    225: int    i386_has_sse2;
1.450     thorpej   226:
1.461     christos  227: int    tmx86_has_longrun;
                    228:
1.314     thorpej   229: vaddr_t        msgbuf_vaddr;
                    230: paddr_t msgbuf_paddr;
                    231:
                    232: vaddr_t        idt_vaddr;
                    233: paddr_t        idt_paddr;
                    234:
1.264     mycroft   235: #ifdef I586_CPU
1.314     thorpej   236: vaddr_t        pentium_idt_vaddr;
1.264     mycroft   237: #endif
1.59      mycroft   238:
1.444     chs       239: struct vm_map *exec_map = NULL;
                    240: struct vm_map *mb_map = NULL;
                    241: struct vm_map *phys_map = NULL;
1.48      brezak    242:
1.314     thorpej   243: extern paddr_t avail_start, avail_end;
1.1       cgd       244:
1.484     fvdl      245: void (*delay_func) __P((int)) = i8254_delay;
                    246: void (*microtime_func) __P((struct timeval *)) = i8254_microtime;
                    247: void (*initclock_func) __P((void)) = i8254_initclocks;
                    248:
1.204     thorpej   249: /*
1.291     thorpej   250:  * Size of memory segments, before any memory is stolen.
                    251:  */
                    252: phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX];
                    253: int    mem_cluster_cnt;
                    254:
                    255: int    cpu_dump __P((void));
                    256: int    cpu_dumpsize __P((void));
                    257: u_long cpu_dump_mempagecnt __P((void));
1.200     christos  258: void   dumpsys __P((void));
1.314     thorpej   259: void   init386 __P((paddr_t));
1.484     fvdl      260: void   initgdt __P((union descriptor *));
1.255     drochner  261:
1.433     kanaoka   262: #if !defined(REALBASEMEM) && !defined(REALEXTMEM)
                    263: void   add_mem_cluster __P((u_int64_t, u_int64_t, u_int32_t));
                    264: #endif /* !defnied(REALBASEMEM) && !defined(REALEXTMEM) */
                    265:
1.484     fvdl      266: static const struct i386_cache_info
                    267: intel_cpuid_cache_info[] = {
                    268:        { CAI_ITLB,     0x01,    4, 32, 4 * 1024 },
                    269:        { CAI_ITLB2,    0x02, 0xff,  2, 4 * 1024 * 1024 },
                    270:        { CAI_DTLB,     0x03,    4, 64, 4 * 1024 },
                    271:        { CAI_DTLB2,    0x04,    4,  8, 4 * 1024 * 1024 },
                    272:        { CAI_ITLB,     0x50, 0xff, 64, 4 * 1024, "4K/4M: 64 entries" },
                    273:        { CAI_ITLB,     0x51, 0xff, 64, 4 * 1024, "4K/4M: 128 entries" },
                    274:        { CAI_ITLB,     0x52, 0xff, 64, 4 * 1024, "4K/4M: 256 entries" },
                    275:        { CAI_DTLB,     0x5b, 0xff, 64, 4 * 1024, "4K/4M: 64 entries" },
                    276:        { CAI_DTLB,     0x5c, 0xff, 64, 4 * 1024, "4K/4M: 128 entries" },
                    277:        { CAI_DTLB,     0x5d, 0xff, 64, 4 * 1024, "4K/4M: 256 entries" },
                    278:
                    279:        { CAI_ICACHE,   0x06,  4,        8 * 1024, 32 },
                    280:        { CAI_ICACHE,   0x08,  4,       16 * 1024, 32 },
                    281:        { CAI_DCACHE,   0x0a,  2,        8 * 1024, 32 },
                    282:        { CAI_DCACHE,   0x0c,  4,       16 * 1024, 32 },
                    283:        { CAI_L2CACHE,  0x40,  0,               0,  0, "not present" },
                    284:        { CAI_L2CACHE,  0x41,  4,      128 * 1024, 32 },
                    285:        { CAI_L2CACHE,  0x42,  4,      256 * 1024, 32 },
                    286:        { CAI_L2CACHE,  0x43,  4,      512 * 1024, 32 },
                    287:        { CAI_L2CACHE,  0x44,  4, 1 * 1024 * 1024, 32 },
                    288:        { CAI_L2CACHE,  0x45,  4, 2 * 1024 * 1024, 32 },
                    289:        { CAI_DCACHE,   0x66,  4,        8 * 1024, 64 },
                    290:        { CAI_DCACHE,   0x67,  4,       16 * 1024, 64 },
                    291:        { CAI_DCACHE,   0x68,  4,       32 * 1024, 64 },
                    292:        { CAI_ICACHE,   0x70,  8,       12 * 1024, 64, "12K uOp cache"},
                    293:        { CAI_ICACHE,   0x71,  8,       16 * 1024, 64, "16K uOp cache"},
                    294:        { CAI_ICACHE,   0x72,  8,       32 * 1024, 64, "32K uOp cache"},
                    295:        { CAI_L2CACHE,  0x79,  8,      128 * 1024, 64 },
                    296:        { CAI_L2CACHE,  0x7a,  8,      256 * 1024, 64 },
                    297:        { CAI_L2CACHE,  0x7b,  8,      512 * 1024, 64 },
                    298:        { CAI_L2CACHE,  0x7c,  8, 1 * 1024 * 1024, 64 },
                    299:        { CAI_L2CACHE,  0x82,  8,      256 * 1024, 32 },
1.491     yamt      300:        { CAI_L2CACHE,  0x83,  8,      512 * 1024, 32 },
1.484     fvdl      301:        { CAI_L2CACHE,  0x84,  8, 1 * 1024 * 1024, 32 },
                    302:        { CAI_L2CACHE,  0x85,  8, 2 * 1024 * 1024, 32 },
                    303:        { 0,               0,  0,               0,  0 },
                    304: };
                    305:
                    306: static const struct i386_cache_info *
                    307: cache_info_lookup(const struct i386_cache_info *cai, u_int8_t desc);
                    308:
1.417     jdolecek  309: /*
                    310:  * Map Brand ID from cpuid instruction to brand name.
                    311:  * Source: Intel Processor Identification and the CPUID Instruction, AP-485
                    312:  */
1.484     fvdl      313: static const char * const i386_intel_brand[] = {
                    314:        "",                 /* Unsupported */
                    315:        "Celeron",          /* Intel (R) Celeron (TM) processor */
                    316:        "Pentium III",      /* Intel (R) Pentium (R) III processor */
                    317:        "Pentium III Xeon", /* Intel (R) Pentium (R) III Xeon (TM) processor */
                    318:        "", "", "",         /* Reserved */
                    319:        "Pentium 4"         /* Intel (R) Pentium (R) 4 processor */
1.417     jdolecek  320: };
                    321:
1.487     junyoung  322: /*
                    323:  * AMD processors don't have Brand IDs, so we need these names for probe.
                    324:  */
                    325: static const char * const amd_brand[] = {
                    326:        "",
                    327:        "Duron",        /* AMD Duron(tm) */
                    328:        "MP",           /* AMD Athlon(tm) MP */
                    329:        "XP",           /* AMD Athlon(tm) XP */
                    330:        "4"             /* AMD Athlon(tm) 4 */
                    331: };
                    332:
                    333: static char amd_brand_name[48];
                    334:
1.200     christos  335: #ifdef COMPAT_NOMID
                    336: static int exec_nomid  __P((struct proc *, struct exec_package *));
                    337: #endif
1.59      mycroft   338:
1.484     fvdl      339: void cyrix6x86_cpu_setup __P((struct cpu_info *));
                    340: void winchip_cpu_setup __P((struct cpu_info *));
                    341: void amd_family5_setup __P((struct cpu_info *));
                    342: void transmeta_cpu_setup __P((struct cpu_info *));
1.267     bouyer    343:
1.501     junyoung  344: static void via_cpu_probe __P((struct cpu_info *));
1.487     junyoung  345: static void amd_family6_probe __P((struct cpu_info *));
                    346:
1.484     fvdl      347: static void transmeta_cpu_info __P((struct cpu_info *));
1.502     junyoung  348: static void amd_cpu_cacheinfo __P((struct cpu_info *));
1.437     thorpej   349:
1.267     bouyer    350: static __inline u_char
                    351: cyrix_read_reg(u_char reg)
                    352: {
                    353:        outb(0x22, reg);
                    354:        return inb(0x23);
                    355: }
                    356:
                    357: static __inline void
                    358: cyrix_write_reg(u_char reg, u_char data)
                    359: {
                    360:        outb(0x22, reg);
                    361:        outb(0x23, data);
                    362: }
                    363:
1.484     fvdl      364: static char *
                    365: print_cache_config(struct cpu_info *ci, int cache_tag, char *name, char *sep)
                    366: {
                    367:        char cbuf[7];
                    368:        struct i386_cache_info *cai = &ci->ci_cinfo[cache_tag];
                    369:
                    370:        if (cai->cai_totalsize == 0)
                    371:                return sep;
                    372:
                    373:        if (sep == NULL)
                    374:                printf("%s: ", ci->ci_dev->dv_xname);
                    375:        else
                    376:                printf("%s", sep);
                    377:        if (name != NULL)
                    378:                printf("%s ", name);
                    379:
                    380:        if (cai->cai_string != NULL) {
                    381:                printf("%s ", cai->cai_string);
                    382:        } else {
                    383:                format_bytes(cbuf, sizeof(cbuf), cai->cai_totalsize);
                    384:                printf("%s %db/line ", cbuf, cai->cai_linesize);
                    385:        }
                    386:        switch (cai->cai_associativity) {
                    387:        case    0:
                    388:                printf("disabled");
                    389:                break;
                    390:        case    1:
                    391:                printf("direct-mapped");
                    392:                break;
                    393:        case 0xff:
                    394:                printf("fully associative");
                    395:                break;
                    396:        default:
                    397:                printf("%d-way", cai->cai_associativity);
                    398:                break;
                    399:        }
                    400:        return ", ";
                    401: }
                    402:
                    403: static char *
                    404: print_tlb_config(struct cpu_info *ci, int cache_tag, char *name, char *sep)
                    405: {
                    406:        char cbuf[7];
                    407:        struct i386_cache_info *cai = &ci->ci_cinfo[cache_tag];
                    408:
                    409:        if (cai->cai_totalsize == 0)
                    410:                return sep;
                    411:
                    412:        if (sep == NULL)
                    413:                printf("%s: ", ci->ci_dev->dv_xname);
                    414:        else
                    415:                printf("%s", sep);
                    416:        if (name != NULL)
                    417:                printf("%s ", name);
                    418:
                    419:        if (cai->cai_string != NULL) {
                    420:                printf("%s", cai->cai_string);
                    421:        } else {
                    422:                format_bytes(cbuf, sizeof(cbuf), cai->cai_linesize);
                    423:                printf("%d %s entries ", cai->cai_totalsize, cbuf);
                    424:                switch (cai->cai_associativity) {
                    425:                case 0:
                    426:                        printf("disabled");
                    427:                        break;
                    428:                case 1:
                    429:                        printf("direct-mapped");
                    430:                        break;
                    431:                case 0xff:
                    432:                        printf("fully associative");
                    433:                        break;
                    434:                default:
                    435:                        printf("%d-way", cai->cai_associativity);
                    436:                        break;
                    437:                }
                    438:        }
                    439:        return ", ";
                    440: }
                    441:
1.59      mycroft   442: /*
                    443:  * Machine-dependent startup code
                    444:  */
1.32      andrew    445: void
1.1       cgd       446: cpu_startup()
                    447: {
1.484     fvdl      448: #if 0
1.437     thorpej   449:        struct cpu_info *ci = curcpu();
1.484     fvdl      450: #endif
1.59      mycroft   451:        caddr_t v;
1.349     thorpej   452:        int sz, x;
1.314     thorpej   453:        vaddr_t minaddr, maxaddr;
                    454:        vsize_t size;
1.354     lukem     455:        char pbuf[9];
1.484     fvdl      456: #if 0
1.440     thorpej   457:        int bigcache, cachesize;
1.484     fvdl      458: #endif
1.1       cgd       459:
1.284     mrg       460:        /*
                    461:         * Initialize error message buffer (et end of core).
                    462:         */
1.354     lukem     463:        msgbuf_vaddr = uvm_km_valloc(kernel_map, i386_round_page(MSGBUFSIZE));
1.385     thorpej   464:        if (msgbuf_vaddr == 0)
1.284     mrg       465:                panic("failed to valloc msgbuf_vaddr");
1.359     thorpej   466:
1.284     mrg       467:        /* msgbuf_paddr was init'd in pmap */
                    468:        for (x = 0; x < btoc(MSGBUFSIZE); x++)
1.414     thorpej   469:                pmap_kenter_pa((vaddr_t)msgbuf_vaddr + x * PAGE_SIZE,
                    470:                    msgbuf_paddr + x * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE);
1.456     chris     471:        pmap_update(pmap_kernel());
1.359     thorpej   472:
1.284     mrg       473:        initmsgbuf((caddr_t)msgbuf_vaddr, round_page(MSGBUFSIZE));
                    474:
1.392     sommerfe  475:        printf("%s", version);
1.484     fvdl      476:
                    477: #ifdef TRAPLOG
                    478:        /*
                    479:         * Enable recording of branch from/to in MSR's
                    480:         */
                    481:        wrmsr(MSR_DEBUGCTLMSR, 0x1);
                    482: #endif
                    483:
1.382     mycroft   484:        format_bytes(pbuf, sizeof(pbuf), ptoa(physmem));
1.354     lukem     485:        printf("total memory = %s\n", pbuf);
1.1       cgd       486:
                    487:        /*
1.59      mycroft   488:         * Find out how much space we need, allocate it,
                    489:         * and then give everything true virtual addresses.
1.1       cgd       490:         */
1.354     lukem     491:        sz = (int)allocsys(NULL, NULL);
1.284     mrg       492:        if ((v = (caddr_t)uvm_km_zalloc(kernel_map, round_page(sz))) == 0)
                    493:                panic("startup: no room for tables");
1.354     lukem     494:        if (allocsys(v, NULL) - v != sz)
1.1       cgd       495:                panic("startup: table size inconsistency");
1.50      cgd       496:
1.36      cgd       497:        /*
1.284     mrg       498:         * Allocate virtual address space for the buffers.  The area
                    499:         * is not managed by the VM system.
1.36      cgd       500:         */
                    501:        size = MAXBSIZE * nbuf;
1.314     thorpej   502:        if (uvm_map(kernel_map, (vaddr_t *) &buffers, round_page(size),
1.398     thorpej   503:                    NULL, UVM_UNKNOWN_OFFSET, 0,
1.284     mrg       504:                    UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE,
1.430     chs       505:                                UVM_ADV_NORMAL, 0)) != 0)
1.284     mrg       506:                panic("cpu_startup: cannot allocate VM for buffers");
1.314     thorpej   507:        minaddr = (vaddr_t)buffers;
1.54      cgd       508:        if ((bufpages / nbuf) >= btoc(MAXBSIZE)) {
                    509:                /* don't want to alloc more physical mem than needed */
                    510:                bufpages = btoc(MAXBSIZE) * nbuf;
                    511:        }
1.36      cgd       512:
1.268     thorpej   513:        /*
                    514:         * XXX We defer allocation of physical pages for buffers until
                    515:         * XXX after autoconfiguration has run.  We must do this because
                    516:         * XXX on system with large amounts of memory or with large
                    517:         * XXX user-configured buffer caches, the buffer cache will eat
                    518:         * XXX up all of the lower 16M of RAM.  This prevents ISA DMA
                    519:         * XXX maps from allocating bounce pages.
                    520:         *
                    521:         * XXX Note that nothing can use buffer cache buffers until after
                    522:         * XXX autoconfiguration completes!!
                    523:         *
                    524:         * XXX This is a hack, and needs to be replaced with a better
                    525:         * XXX solution!  --thorpej@netbsd.org, December 6, 1997
                    526:         */
1.41      cgd       527:
1.1       cgd       528:        /*
1.36      cgd       529:         * Allocate a submap for exec arguments.  This map effectively
                    530:         * limits the number of processes exec'ing at any time.
1.1       cgd       531:         */
1.284     mrg       532:        exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
1.358     thorpej   533:                                   16*NCARGS, VM_MAP_PAGEABLE, FALSE, NULL);
1.59      mycroft   534:
1.1       cgd       535:        /*
                    536:         * Allocate a submap for physio
                    537:         */
1.284     mrg       538:        phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
1.358     thorpej   539:                                   VM_PHYS_SIZE, 0, FALSE, NULL);
1.1       cgd       540:
                    541:        /*
1.229     thorpej   542:         * Finally, allocate mbuf cluster submap.
1.1       cgd       543:         */
1.334     thorpej   544:        mb_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
1.358     thorpej   545:            nmbclusters * mclbytes, VM_MAP_INTRSAFE, FALSE, NULL);
1.1       cgd       546:
1.284     mrg       547:        /*
                    548:         * XXX Buffer cache pages haven't yet been allocated, so
                    549:         * XXX we need to account for those pages when printing
                    550:         * XXX the amount of free memory.
                    551:         */
1.354     lukem     552:        format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free - bufpages));
                    553:        printf("avail memory = %s\n", pbuf);
1.414     thorpej   554:        format_bytes(pbuf, sizeof(pbuf), bufpages * PAGE_SIZE);
1.484     fvdl      555:        printf("using %d buffers containing %s of memory\n", nbuf, pbuf);
1.1       cgd       556:
1.375     drochner  557:        /* Safe for i/o port / memory space allocation to use malloc now. */
                    558:        i386_bus_space_mallocok();
1.349     thorpej   559: }
                    560:
                    561: /*
                    562:  * Set up proc0's TSS and LDT.
                    563:  */
                    564: void
                    565: i386_proc0_tss_ldt_init()
                    566: {
                    567:        struct pcb *pcb;
                    568:        int x;
1.268     thorpej   569:
1.326     thorpej   570:        gdt_init();
1.484     fvdl      571:
                    572:        cpu_info_primary.ci_curpcb = pcb = &proc0.p_addr->u_pcb;
                    573:
1.326     thorpej   574:        pcb->pcb_tss.tss_ioopt =
                    575:            ((caddr_t)pcb->pcb_iomap - (caddr_t)&pcb->pcb_tss) << 16;
1.484     fvdl      576:
1.326     thorpej   577:        for (x = 0; x < sizeof(pcb->pcb_iomap) / 4; x++)
                    578:                pcb->pcb_iomap[x] = 0xffffffff;
                    579:
1.394     thorpej   580:        pcb->pcb_ldt_sel = pmap_kernel()->pm_ldt_sel = GSEL(GLDT_SEL, SEL_KPL);
1.326     thorpej   581:        pcb->pcb_cr0 = rcr0();
                    582:        pcb->pcb_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL);
                    583:        pcb->pcb_tss.tss_esp0 = (int)proc0.p_addr + USPACE - 16;
1.484     fvdl      584:        proc0.p_md.md_regs = (struct trapframe *)pcb->pcb_tss.tss_esp0 - 1;
                    585:        proc0.p_md.md_tss_sel = tss_alloc(pcb);
1.326     thorpej   586:
1.394     thorpej   587:        ltr(proc0.p_md.md_tss_sel);
1.326     thorpej   588:        lldt(pcb->pcb_ldt_sel);
1.484     fvdl      589: }
                    590:
                    591: /*
                    592:  * Set up TSS and LDT for a new PCB.
                    593:  */
                    594:
                    595: void
                    596: i386_init_pcb_tss_ldt(ci)
                    597:        struct cpu_info *ci;
                    598: {
                    599:        int x;
                    600:        struct pcb *pcb = ci->ci_idle_pcb;
1.326     thorpej   601:
1.484     fvdl      602:        pcb->pcb_tss.tss_ioopt =
                    603:            ((caddr_t)pcb->pcb_iomap - (caddr_t)&pcb->pcb_tss) << 16;
                    604:        for (x = 0; x < sizeof(pcb->pcb_iomap) / 4; x++)
                    605:                pcb->pcb_iomap[x] = 0xffffffff;
                    606:
                    607:        pcb->pcb_ldt_sel = pmap_kernel()->pm_ldt_sel = GSEL(GLDT_SEL, SEL_KPL);
                    608:        pcb->pcb_cr0 = rcr0();
                    609:
                    610:        ci->ci_idle_tss_sel = tss_alloc(pcb);
1.326     thorpej   611: }
                    612:
                    613: /*
                    614:  * XXX Finish up the deferred buffer cache allocation and initialization.
                    615:  */
                    616: void
                    617: i386_bufinit()
                    618: {
1.484     fvdl      619:        int i, base, residual;
1.326     thorpej   620:
1.268     thorpej   621:        base = bufpages / nbuf;
                    622:        residual = bufpages % nbuf;
                    623:        for (i = 0; i < nbuf; i++) {
1.314     thorpej   624:                vsize_t curbufsize;
                    625:                vaddr_t curbuf;
1.284     mrg       626:                struct vm_page *pg;
                    627:
                    628:                /*
                    629:                 * Each buffer has MAXBSIZE bytes of VM space allocated.  Of
                    630:                 * that MAXBSIZE space, we allocate and map (base+1) pages
                    631:                 * for the first "residual" buffers, and then we allocate
                    632:                 * "base" pages for the rest.
                    633:                 */
1.314     thorpej   634:                curbuf = (vaddr_t) buffers + (i * MAXBSIZE);
1.414     thorpej   635:                curbufsize = PAGE_SIZE * ((i < residual) ? (base+1) : base);
1.284     mrg       636:
                    637:                while (curbufsize) {
1.311     thorpej   638:                        /*
                    639:                         * Attempt to allocate buffers from the first
                    640:                         * 16M of RAM to avoid bouncing file system
                    641:                         * transfers.
                    642:                         */
1.350     chs       643:                        pg = uvm_pagealloc_strat(NULL, 0, NULL, 0,
1.311     thorpej   644:                            UVM_PGA_STRAT_FALLBACK, VM_FREELIST_FIRST16);
1.284     mrg       645:                        if (pg == NULL)
                    646:                                panic("cpu_startup: not enough memory for "
                    647:                                    "buffer cache");
1.434     thorpej   648:                        pmap_kenter_pa(curbuf, VM_PAGE_TO_PHYS(pg),
                    649:                            VM_PROT_READ|VM_PROT_WRITE);
1.284     mrg       650:                        curbuf += PAGE_SIZE;
                    651:                        curbufsize -= PAGE_SIZE;
                    652:                }
1.268     thorpej   653:        }
1.456     chris     654:        pmap_update(pmap_kernel());
1.268     thorpej   655:
                    656:        /*
                    657:         * Set up buffers, so they can be used to read disk labels.
                    658:         */
                    659:        bufinit();
1.16      cgd       660: }
                    661:
1.484     fvdl      662: /*
1.104     cgd       663:  * Info for CTL_HW
                    664:  */
                    665: char   cpu_model[120];
                    666:
1.216     fvdl      667: /*
                    668:  * Note: these are just the ones that may not have a cpuid instruction.
                    669:  * We deal with the rest in a different way.
                    670:  */
1.418     jdolecek  671: const struct cpu_nocpuid_nameclass i386_nocpuid_cpus[] = {
1.267     bouyer    672:        { CPUVENDOR_INTEL, "Intel", "386SX",    CPUCLASS_386,
1.437     thorpej   673:                NULL, NULL},                    /* CPU_386SX */
1.267     bouyer    674:        { CPUVENDOR_INTEL, "Intel", "386DX",    CPUCLASS_386,
1.437     thorpej   675:                NULL, NULL},                    /* CPU_386   */
1.267     bouyer    676:        { CPUVENDOR_INTEL, "Intel", "486SX",    CPUCLASS_486,
1.437     thorpej   677:                NULL, NULL},                    /* CPU_486SX */
1.267     bouyer    678:        { CPUVENDOR_INTEL, "Intel", "486DX",    CPUCLASS_486,
1.437     thorpej   679:                NULL, NULL},                    /* CPU_486   */
1.267     bouyer    680:        { CPUVENDOR_CYRIX, "Cyrix", "486DLC",   CPUCLASS_486,
1.437     thorpej   681:                NULL, NULL},                    /* CPU_486DLC */
                    682:        { CPUVENDOR_CYRIX, "Cyrix", "6x86",     CPUCLASS_486,
                    683:                cyrix6x86_cpu_setup, NULL},     /* CPU_6x86 */
1.267     bouyer    684:        { CPUVENDOR_NEXGEN,"NexGen","586",      CPUCLASS_386,
1.437     thorpej   685:                NULL, NULL},                    /* CPU_NX586 */
1.216     fvdl      686: };
                    687:
                    688: const char *classnames[] = {
                    689:        "386",
                    690:        "486",
                    691:        "586",
                    692:        "686"
                    693: };
                    694:
                    695: const char *modifiers[] = {
                    696:        "",
1.454     enami     697:        "OverDrive",
                    698:        "Dual",
1.216     fvdl      699:        ""
1.18      cgd       700: };
                    701:
1.418     jdolecek  702: const struct cpu_cpuid_nameclass i386_cpuid_cpus[] = {
1.216     fvdl      703:        {
                    704:                "GenuineIntel",
                    705:                CPUVENDOR_INTEL,
                    706:                "Intel",
                    707:                /* Family 4 */
                    708:                { {
1.484     fvdl      709:                        CPUCLASS_486,
1.216     fvdl      710:                        {
1.219     perry     711:                                "486DX", "486DX", "486SX", "486DX2", "486SL",
1.216     fvdl      712:                                "486SX2", 0, "486DX2 W/B Enhanced",
                    713:                                "486DX4", 0, 0, 0, 0, 0, 0, 0,
                    714:                                "486"           /* Default */
1.267     bouyer    715:                        },
1.437     thorpej   716:                        NULL,
1.484     fvdl      717:                        NULL,
1.464     christos  718:                        NULL,
1.216     fvdl      719:                },
                    720:                /* Family 5 */
                    721:                {
                    722:                        CPUCLASS_586,
                    723:                        {
1.361     tron      724:                                "Pentium (P5 A-step)", "Pentium (P5)",
1.484     fvdl      725:                                "Pentium (P54C)", "Pentium (P24T)",
1.361     tron      726:                                "Pentium/MMX", "Pentium", 0,
                    727:                                "Pentium (P54C)", "Pentium/MMX (Tillamook)",
                    728:                                0, 0, 0, 0, 0, 0, 0,
1.216     fvdl      729:                                "Pentium"       /* Default */
1.267     bouyer    730:                        },
1.437     thorpej   731:                        NULL,
1.484     fvdl      732:                        NULL,
1.464     christos  733:                        NULL,
1.216     fvdl      734:                },
                    735:                /* Family 6 */
                    736:                {
                    737:                        CPUCLASS_686,
                    738:                        {
1.361     tron      739:                                "Pentium Pro (A-step)", "Pentium Pro", 0,
                    740:                                "Pentium II (Klamath)", "Pentium Pro",
1.416     jdolecek  741:                                "Pentium II/Celeron (Deschutes)",
                    742:                                "Celeron (Mendocino)",
                    743:                                "Pentium III (Katmai)",
                    744:                                "Pentium III (Coppermine)",
1.458     jdolecek  745:                                0, "Pentium III (Cascades)",
                    746:                                "Pentium III (Tualatin)", 0, 0, 0, 0,
1.340     fvdl      747:                                "Pentium Pro, II or III"        /* Default */
1.267     bouyer    748:                        },
1.437     thorpej   749:                        NULL,
1.484     fvdl      750:                        NULL,
1.464     christos  751:                        NULL,
1.406     fvdl      752:                },
                    753:                /* Family > 6 */
                    754:                {
                    755:                        CPUCLASS_686,
                    756:                        {
1.459     jdolecek  757:                                0, 0, 0, 0, 0, 0, 0, 0,
                    758:                                0, 0, 0, 0, 0, 0, 0, 0,
1.406     fvdl      759:                                "Pentium 4"     /* Default */
                    760:                        },
1.437     thorpej   761:                        NULL,
1.484     fvdl      762:                        NULL,
1.464     christos  763:                        NULL,
1.216     fvdl      764:                } }
                    765:        },
                    766:        {
                    767:                "AuthenticAMD",
                    768:                CPUVENDOR_AMD,
                    769:                "AMD",
                    770:                /* Family 4 */
                    771:                { {
1.484     fvdl      772:                        CPUCLASS_486,
1.216     fvdl      773:                        {
                    774:                                0, 0, 0, "Am486DX2 W/T",
                    775:                                0, 0, 0, "Am486DX2 W/B",
                    776:                                "Am486DX4 W/T or Am5x86 W/T 150",
                    777:                                "Am486DX4 W/B or Am5x86 W/B 150", 0, 0,
                    778:                                0, 0, "Am5x86 W/T 133/160",
                    779:                                "Am5x86 W/B 133/160",
                    780:                                "Am486 or Am5x86"       /* Default */
                    781:                        },
1.437     thorpej   782:                        NULL,
                    783:                        NULL,
1.464     christos  784:                        NULL,
1.216     fvdl      785:                },
                    786:                /* Family 5 */
                    787:                {
                    788:                        CPUCLASS_586,
                    789:                        {
1.241     fvdl      790:                                "K5", "K5", "K5", "K5", 0, 0, "K6",
1.416     jdolecek  791:                                "K6", "K6-2", "K6-III", 0, 0, 0,
                    792:                                "K6-2+/III+", 0, 0,
1.267     bouyer    793:                                "K5 or K6"              /* Default */
1.216     fvdl      794:                        },
1.441     thorpej   795:                        amd_family5_setup,
1.501     junyoung  796:                        NULL,
1.502     junyoung  797:                        amd_cpu_cacheinfo,
1.216     fvdl      798:                },
1.363     fvdl      799:                /* Family 6 */
1.216     fvdl      800:                {
                    801:                        CPUCLASS_686,
                    802:                        {
1.416     jdolecek  803:                                0, "Athlon Model 1", "Athlon Model 2",
                    804:                                "Duron", "Athlon Model 4 (Thunderbird)",
1.487     junyoung  805:                                0, "Athlon", "Duron", "Athlon", 0, 0, 0,
1.465     drochner  806:                                0, 0, 0, 0,
1.362     fvdl      807:                                "K7 (Athlon)"   /* Default */
1.216     fvdl      808:                        },
1.437     thorpej   809:                        NULL,
1.487     junyoung  810:                        amd_family6_probe,
1.502     junyoung  811:                        amd_cpu_cacheinfo,
1.406     fvdl      812:                },
                    813:                /* Family > 6 */
                    814:                {
                    815:                        CPUCLASS_686,
                    816:                        {
1.459     jdolecek  817:                                0, 0, 0, 0, 0, 0, 0, 0,
                    818:                                0, 0, 0, 0, 0, 0, 0, 0,
1.406     fvdl      819:                                "Unknown K7 (Athlon)"   /* Default */
                    820:                        },
1.437     thorpej   821:                        NULL,
1.501     junyoung  822:                        NULL,
1.464     christos  823:                        NULL,
1.216     fvdl      824:                } }
                    825:        },
                    826:        {
                    827:                "CyrixInstead",
                    828:                CPUVENDOR_CYRIX,
                    829:                "Cyrix",
                    830:                /* Family 4 */
                    831:                { {
                    832:                        CPUCLASS_486,
                    833:                        {
1.376     minoura   834:                                0, 0, 0,
                    835:                                "MediaGX",
1.459     jdolecek  836:                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1.216     fvdl      837:                                "486"           /* Default */
                    838:                        },
1.484     fvdl      839:                        cyrix6x86_cpu_setup, /* XXX ?? */
1.437     thorpej   840:                        NULL,
1.464     christos  841:                        NULL,
1.216     fvdl      842:                },
                    843:                /* Family 5 */
                    844:                {
                    845:                        CPUCLASS_586,
                    846:                        {
1.376     minoura   847:                                0, 0, "6x86", 0,
                    848:                                "MMX-enhanced MediaGX (GXm)", /* or Geode? */
                    849:                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1.216     fvdl      850:                                "6x86"          /* Default */
1.267     bouyer    851:                        },
1.437     thorpej   852:                        cyrix6x86_cpu_setup,
                    853:                        NULL,
1.464     christos  854:                        NULL,
1.216     fvdl      855:                },
1.278     bouyer    856:                /* Family 6 */
1.216     fvdl      857:                {
                    858:                        CPUCLASS_686,
                    859:                        {
1.459     jdolecek  860:                                "6x86MX", 0, 0, 0, 0, 0, 0, 0,
                    861:                                0, 0, 0, 0, 0, 0, 0, 0,
1.278     bouyer    862:                                "6x86MX"                /* Default */
1.329     bad       863:                        },
1.437     thorpej   864:                        cyrix6x86_cpu_setup,
                    865:                        NULL,
1.464     christos  866:                        NULL,
1.406     fvdl      867:                },
                    868:                /* Family > 6 */
                    869:                {
                    870:                        CPUCLASS_686,
                    871:                        {
1.459     jdolecek  872:                                0, 0, 0, 0, 0, 0, 0, 0,
                    873:                                0, 0, 0, 0, 0, 0, 0, 0,
1.406     fvdl      874:                                "Unknown 6x86MX"                /* Default */
1.497     minoura   875:                        },
                    876:                        NULL,
                    877:                        NULL,
                    878:                        NULL,
                    879:                } }
                    880:        },
                    881:        {       /* MediaGX is now owned by National Semiconductor */
                    882:                "Geode by NSC",
                    883:                CPUVENDOR_CYRIX, /* XXX */
                    884:                "National Semiconductor",
                    885:                /* Family 4, NSC never had any of these */
                    886:                { {
                    887:                        CPUCLASS_486,
                    888:                        {
                    889:                                0, 0, 0, 0, 0, 0, 0, 0,
                    890:                                0, 0, 0, 0, 0, 0, 0, 0,
                    891:                                "486 compatible"        /* Default */
                    892:                        },
                    893:                        NULL,
                    894:                        NULL,
                    895:                        NULL,
                    896:                },
                    897:                /* Family 5: Geode family, formerly MediaGX */
                    898:                {
                    899:                        CPUCLASS_586,
                    900:                        {
                    901:                                0, 0, 0, 0,
                    902:                                "Geode GX1",
                    903:                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                    904:                                "Geode"         /* Default */
                    905:                        },
                    906:                        cyrix6x86_cpu_setup,
                    907:                        NULL,
                    908:                        NULL,
                    909:                },
                    910:                /* Family 6, not yet available from NSC */
                    911:                {
                    912:                        CPUCLASS_686,
                    913:                        {
                    914:                                0, 0, 0, 0, 0, 0, 0, 0,
                    915:                                0, 0, 0, 0, 0, 0, 0, 0,
                    916:                                "Pentium Pro compatible" /* Default */
                    917:                        },
                    918:                        NULL,
                    919:                        NULL,
                    920:                        NULL,
                    921:                },
                    922:                /* Family > 6, not yet available from NSC */
                    923:                {
                    924:                        CPUCLASS_686,
                    925:                        {
                    926:                                0, 0, 0, 0, 0, 0, 0, 0,
                    927:                                0, 0, 0, 0, 0, 0, 0, 0,
                    928:                                "Pentium Pro compatible"        /* Default */
1.406     fvdl      929:                        },
1.437     thorpej   930:                        NULL,
                    931:                        NULL,
1.464     christos  932:                        NULL,
1.329     bad       933:                } }
                    934:        },
                    935:        {
                    936:                "CentaurHauls",
                    937:                CPUVENDOR_IDT,
                    938:                "IDT",
                    939:                /* Family 4, IDT never had any of these */
                    940:                { {
1.484     fvdl      941:                        CPUCLASS_486,
1.329     bad       942:                        {
1.459     jdolecek  943:                                0, 0, 0, 0, 0, 0, 0, 0,
                    944:                                0, 0, 0, 0, 0, 0, 0, 0,
1.329     bad       945:                                "486 compatible"        /* Default */
                    946:                        },
1.437     thorpej   947:                        NULL,
                    948:                        NULL,
1.464     christos  949:                        NULL,
1.329     bad       950:                },
                    951:                /* Family 5 */
                    952:                {
                    953:                        CPUCLASS_586,
                    954:                        {
                    955:                                0, 0, 0, 0, "WinChip C6", 0, 0, 0,
1.379     jdolecek  956:                                "WinChip 2", "WinChip 3", 0, 0, 0, 0, 0, 0,
1.329     bad       957:                                "WinChip"               /* Default */
                    958:                        },
1.437     thorpej   959:                        winchip_cpu_setup,
                    960:                        NULL,
1.464     christos  961:                        NULL,
1.329     bad       962:                },
1.500     junyoung  963:                /* Family 6, VIA acquired IDT Centaur design subsidiary */
1.406     fvdl      964:                {
                    965:                        CPUCLASS_686,
                    966:                        {
1.500     junyoung  967:                                0, 0, 0, 0, 0, 0, "C3 Samuel",
                    968:                                "C3 Samuel 2/Ezra", "C3 Ezra-T",
                    969:                                0, 0, 0, 0, 0, 0, 0,
                    970:                                "C3"    /* Default */
1.406     fvdl      971:                        },
1.437     thorpej   972:                        NULL,
1.501     junyoung  973:                        via_cpu_probe,
1.464     christos  974:                        NULL,
1.406     fvdl      975:                },
1.500     junyoung  976:                /* Family > 6, not yet available from VIA */
1.329     bad       977:                {
                    978:                        CPUCLASS_686,
                    979:                        {
1.459     jdolecek  980:                                0, 0, 0, 0, 0, 0, 0, 0,
                    981:                                0, 0, 0, 0, 0, 0, 0, 0,
1.329     bad       982:                                "Pentium Pro compatible"        /* Default */
1.267     bouyer    983:                        },
1.437     thorpej   984:                        NULL,
                    985:                        NULL,
1.464     christos  986:                        NULL,
1.216     fvdl      987:                } }
1.461     christos  988:        },
                    989:        {
                    990:                "GenuineTMx86",
                    991:                CPUVENDOR_TRANSMETA,
                    992:                "Transmeta",
                    993:                /* Family 4, Transmeta never had any of these */
                    994:                { {
1.484     fvdl      995:                        CPUCLASS_486,
1.461     christos  996:                        {
1.462     enami     997:                                0, 0, 0, 0, 0, 0, 0, 0,
                    998:                                0, 0, 0, 0, 0, 0, 0, 0,
1.461     christos  999:                                "486 compatible"        /* Default */
                   1000:                        },
                   1001:                        NULL,
                   1002:                        NULL,
1.464     christos 1003:                        NULL,
1.461     christos 1004:                },
                   1005:                /* Family 5 */
                   1006:                {
                   1007:                        CPUCLASS_586,
                   1008:                        {
1.462     enami    1009:                                0, 0, 0, 0, 0, 0, 0, 0,
                   1010:                                0, 0, 0, 0, 0, 0, 0, 0,
1.461     christos 1011:                                "Crusoe"                /* Default */
                   1012:                        },
                   1013:                        transmeta_cpu_setup,
                   1014:                        NULL,
1.464     christos 1015:                        transmeta_cpu_info,
1.461     christos 1016:                },
                   1017:                /* Family 6, not yet available from Transmeta */
                   1018:                {
                   1019:                        CPUCLASS_686,
                   1020:                        {
1.462     enami    1021:                                0, 0, 0, 0, 0, 0, 0, 0,
                   1022:                                0, 0, 0, 0, 0, 0, 0, 0,
1.461     christos 1023:                                "Pentium Pro compatible"        /* Default */
                   1024:                        },
                   1025:                        NULL,
                   1026:                        NULL,
1.464     christos 1027:                        NULL,
1.461     christos 1028:                },
                   1029:                /* Family > 6, not yet available from Transmeta */
                   1030:                {
                   1031:                        CPUCLASS_686,
                   1032:                        {
1.462     enami    1033:                                0, 0, 0, 0, 0, 0, 0, 0,
                   1034:                                0, 0, 0, 0, 0, 0, 0, 0,
1.461     christos 1035:                                "Pentium Pro compatible"        /* Default */
                   1036:                        },
                   1037:                        NULL,
                   1038:                        NULL,
1.464     christos 1039:                        NULL,
1.461     christos 1040:                } }
1.216     fvdl     1041:        }
                   1042: };
                   1043:
1.484     fvdl     1044: void
                   1045: cyrix6x86_cpu_setup(ci)
                   1046:        struct cpu_info *ci;
1.437     thorpej  1047: {
1.484     fvdl     1048:        /*
                   1049:         * i8254 latch check routine:
                   1050:         *     National Geode (formerly Cyrix MediaGX) has a serious bug in
                   1051:         *     its built-in i8254-compatible clock module.
                   1052:         *     Set the variable 'clock_broken_latch' to indicate it.
                   1053:         */
1.437     thorpej  1054:
1.484     fvdl     1055:        extern int clock_broken_latch;
1.437     thorpej  1056:
1.484     fvdl     1057:        switch (ci->ci_signature) {
                   1058:        case 0x440:     /* Cyrix MediaGX */
                   1059:        case 0x540:     /* GXm */
                   1060:                clock_broken_latch = 1;
                   1061:                break;
                   1062:        }
1.437     thorpej  1063:
1.267     bouyer   1064:        /* set up various cyrix registers */
                   1065:        /* Enable suspend on halt */
                   1066:        cyrix_write_reg(0xc2, cyrix_read_reg(0xc2) | 0x08);
                   1067:        /* enable access to ccr4/ccr5 */
                   1068:        cyrix_write_reg(0xC3, cyrix_read_reg(0xC3) | 0x10);
                   1069:        /* cyrix's workaround  for the "coma bug" */
                   1070:        cyrix_write_reg(0x31, cyrix_read_reg(0x31) | 0xf8);
                   1071:        cyrix_write_reg(0x32, cyrix_read_reg(0x32) | 0x7f);
                   1072:        cyrix_write_reg(0x33, cyrix_read_reg(0x33) & ~0xff);
                   1073:        cyrix_write_reg(0x3c, cyrix_read_reg(0x3c) | 0x87);
                   1074:        /* disable access to ccr4/ccr5 */
                   1075:        cyrix_write_reg(0xC3, cyrix_read_reg(0xC3) & ~0x10);
1.393     fvdl     1076:
1.484     fvdl     1077:        /*
1.393     fvdl     1078:         * XXX disable page zero in the idle loop, it seems to
                   1079:         * cause panics on these CPUs.
                   1080:         */
                   1081:        vm_page_zero_enable = FALSE;
1.267     bouyer   1082: }
                   1083:
                   1084: void
1.484     fvdl     1085: winchip_cpu_setup(ci)
                   1086:        struct cpu_info *ci;
1.379     jdolecek 1087: {
1.380     jdolecek 1088: #if defined(I586_CPU)
1.484     fvdl     1089:        switch (CPUID2MODEL(ci->ci_signature)) { /* model */
1.379     jdolecek 1090:        case 4: /* WinChip C6 */
                   1091:                cpu_feature &= ~CPUID_TSC;
                   1092:                printf("WARNING: WinChip C6: broken TSC disabled\n");
                   1093:        }
                   1094: #endif
1.441     thorpej  1095: }
                   1096:
1.484     fvdl     1097: #define CPUID(code, eax, ebx, ecx, edx)                        \
1.496     perry    1098:        __asm("cpuid"                                           \
1.484     fvdl     1099:            : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)    \
                   1100:            : "a" (code));
                   1101:
1.501     junyoung 1102: void
                   1103: via_cpu_probe(struct cpu_info *ci)
                   1104: {
                   1105:        u_int descs[4];
                   1106:        u_int lfunc;
                   1107:
                   1108:        /*
                   1109:         * Determine the largest extended function value.
                   1110:         */
                   1111:        CPUID(0x80000000, descs[0], descs[1], descs[2], descs[3]);
                   1112:        lfunc = descs[0];
                   1113:
                   1114:        /*
                   1115:         * Determine the extended feature flags.
                   1116:         */
                   1117:        if (lfunc >= 0x80000001) {
                   1118:                CPUID(0x80000001, descs[0], descs[1], descs[2], descs[3]);
                   1119:                ci->ci_feature_flags = descs[3];
                   1120:        }
                   1121: }
                   1122:
1.484     fvdl     1123: static void
                   1124: cpu_probe_base_features(struct cpu_info *ci)
                   1125: {
                   1126:        const struct i386_cache_info *cai;
                   1127:        u_int descs[4];
                   1128:        int iterations, i, j;
                   1129:        u_int8_t desc;
                   1130:        u_int32_t dummy1, dummy2, miscbytes;
                   1131:
                   1132:        if (ci->ci_cpuid_level < 0)
                   1133:                return;
                   1134:
                   1135:        CPUID(0, ci->ci_cpuid_level,
                   1136:            ci->ci_vendor[0],
                   1137:            ci->ci_vendor[2],
                   1138:            ci->ci_vendor[1]);
                   1139:        ci->ci_vendor[3] = 0;
                   1140:
                   1141:        if (ci->ci_cpuid_level < 1)
                   1142:                return;
                   1143:
                   1144:        CPUID(1, ci->ci_signature, miscbytes, dummy1, ci->ci_feature_flags);
                   1145:
                   1146:        /* Brand is low order 8 bits of ebx */
                   1147:        ci->ci_brand_id = miscbytes & 0xff;
                   1148:
                   1149:        /* CLFLUSH line size is next 8 bits */
                   1150:        if (ci->ci_feature_flags & CPUID_CFLUSH)
                   1151:                ci->ci_cflush_lsize = ((miscbytes >> 8) & 0xff) << 3;
                   1152:
                   1153:        if (ci->ci_cpuid_level < 2)
                   1154:                return;
                   1155:
                   1156:        /*
                   1157:         * Parse the cache info from `cpuid', if we have it.
                   1158:         * XXX This is kinda ugly, but hey, so is the architecture...
                   1159:         */
                   1160:
                   1161:        CPUID(2, descs[0], descs[1], descs[2], descs[3]);
                   1162:
                   1163:        iterations = descs[0] & 0xff;
                   1164:        while (iterations-- > 0) {
                   1165:                for (i = 0; i < 4; i++) {
                   1166:                        if (descs[i] & 0x80000000)
                   1167:                                continue;
                   1168:                        for (j = 0; j < 4; j++) {
                   1169:                                if (i == 0 && j == 0)
                   1170:                                        continue;
                   1171:                                desc = (descs[i] >> (j * 8)) & 0xff;
                   1172:                                if (desc == 0)
                   1173:                                        continue;
                   1174:                                cai = cache_info_lookup(intel_cpuid_cache_info,
                   1175:                                    desc);
                   1176:                                if (cai != NULL)
                   1177:                                        ci->ci_cinfo[cai->cai_index] = *cai;
                   1178:                        }
                   1179:                }
                   1180:                CPUID(2, descs[0], descs[1], descs[2], descs[3]);
                   1181:        }
                   1182:
                   1183:        if (ci->ci_cpuid_level < 3)
                   1184:                return;
                   1185:
                   1186:        /*
                   1187:         * If the processor serial number misfeature is present and supported,
                   1188:         * extract it here.
                   1189:         */
                   1190:        if ((ci->ci_feature_flags & CPUID_PN) != 0)
                   1191:        {
                   1192:                ci->ci_cpu_serial[0] = ci->ci_signature;
                   1193:                CPUID(3, dummy1, dummy2,
                   1194:                    ci->ci_cpu_serial[2],
                   1195:                    ci->ci_cpu_serial[1]);
                   1196:        }
                   1197: }
                   1198:
                   1199: void
                   1200: cpu_probe_features(struct cpu_info *ci)
                   1201: {
                   1202:        const struct cpu_cpuid_nameclass *cpup = NULL;
                   1203:        int i, max, family;
                   1204:
                   1205:        cpu_probe_base_features(ci);
                   1206:
                   1207:        if (ci->ci_cpuid_level < 1)
                   1208:                return;
                   1209:
                   1210:        max = sizeof (i386_cpuid_cpus) / sizeof (i386_cpuid_cpus[0]);
                   1211:        for (i = 0; i < max; i++) {
                   1212:                if (!strncmp((char *)ci->ci_vendor,
                   1213:                    i386_cpuid_cpus[i].cpu_id, 12)) {
                   1214:                        cpup = &i386_cpuid_cpus[i];
                   1215:                        break;
                   1216:                }
                   1217:        }
                   1218:
                   1219:        if (cpup == NULL)
                   1220:                return;
                   1221:
                   1222:        family = (ci->ci_signature >> 8) & 0xf;
                   1223:
                   1224:        if (family > CPU_MAXFAMILY) {
                   1225:                family = CPU_MAXFAMILY;
                   1226:        }
                   1227:        i = family - CPU_MINFAMILY;
                   1228:
                   1229:        if (cpup->cpu_family[i].cpu_probe == NULL)
                   1230:                return;
                   1231:
                   1232:        (*cpup->cpu_family[i].cpu_probe)(ci);
                   1233: }
                   1234:
1.487     junyoung 1235: void
                   1236: amd_family6_probe(struct cpu_info *ci)
                   1237: {
1.501     junyoung 1238:        u_int32_t lfunc;
                   1239:        u_int32_t descs[4];
1.487     junyoung 1240:        u_int32_t brand[12];
                   1241:        char *p;
                   1242:        int i;
                   1243:
1.501     junyoung 1244:        CPUID(0x80000000, lfunc, descs[1], descs[2], descs[3]);
                   1245:
                   1246:        /*
                   1247:         * Determine the extended feature flags.
                   1248:         */
                   1249:        if (lfunc >= 0x80000001) {
                   1250:                CPUID(0x80000001, descs[0], descs[1], descs[2], descs[3]);
                   1251:                ci->ci_feature_flags |= descs[3];
                   1252:        }
                   1253:
                   1254:        if (lfunc < 0x80000004)
1.487     junyoung 1255:                return;
                   1256:
                   1257:        CPUID(0x80000002, brand[0], brand[1], brand[2], brand[3]);
                   1258:        CPUID(0x80000003, brand[4], brand[5], brand[6], brand[7]);
                   1259:        CPUID(0x80000004, brand[8], brand[9], brand[10], brand[11]);
                   1260:
                   1261:        for (i = 1; i < sizeof(amd_brand) / sizeof(amd_brand[0]); i++)
                   1262:                if ((p = strstr((char *)brand, amd_brand[i])) != NULL) {
                   1263:                        ci->ci_brand_id = i;
                   1264:                        strcpy(amd_brand_name, p);
                   1265:                        break;
                   1266:                }
                   1267: }
1.484     fvdl     1268:
1.441     thorpej  1269: void
1.484     fvdl     1270: amd_family5_setup(struct cpu_info *ci)
1.441     thorpej  1271: {
                   1272:
1.484     fvdl     1273:        switch (CPUID2MODEL(ci->ci_signature)) {
1.441     thorpej  1274:        case 0:         /* AMD-K5 Model 0 */
                   1275:                /*
                   1276:                 * According to the AMD Processor Recognition App Note,
                   1277:                 * the AMD-K5 Model 0 uses the wrong bit to indicate
                   1278:                 * support for global PTEs, instead using bit 9 (APIC)
                   1279:                 * rather than bit 13 (i.e. "0x200" vs. 0x2000".  Oops!).
                   1280:                 */
                   1281:                if (cpu_feature & CPUID_APIC)
                   1282:                        cpu_feature = (cpu_feature & ~CPUID_APIC) | CPUID_PGE;
                   1283:                /*
                   1284:                 * XXX But pmap_pg_g is already initialized -- need to kick
                   1285:                 * XXX the pmap somehow.  How does the MP branch do this?
                   1286:                 */
                   1287:                break;
                   1288:        }
1.379     jdolecek 1289: }
                   1290:
1.461     christos 1291: /*
                   1292:  * Transmeta Crusoe LongRun Support by Tamotsu Hattori.
                   1293:  * Port from FreeBSD-current(August, 2001) to NetBSD by tshiozak.
                   1294:  */
                   1295:
1.462     enami    1296: #define        MSR_TMx86_LONGRUN               0x80868010
                   1297: #define        MSR_TMx86_LONGRUN_FLAGS         0x80868011
1.461     christos 1298:
1.467     christos 1299: #define        LONGRUN_MODE_MASK(x)            ((x) & 0x0000007f)
1.462     enami    1300: #define        LONGRUN_MODE_RESERVED(x)        ((x) & 0xffffff80)
                   1301: #define        LONGRUN_MODE_WRITE(x, y)        (LONGRUN_MODE_RESERVED(x) | \
                   1302:                                            LONGRUN_MODE_MASK(y))
                   1303:
                   1304: #define        LONGRUN_MODE_MINFREQUENCY       0x00
                   1305: #define        LONGRUN_MODE_ECONOMY            0x01
                   1306: #define        LONGRUN_MODE_PERFORMANCE        0x02
                   1307: #define        LONGRUN_MODE_MAXFREQUENCY       0x03
                   1308: #define        LONGRUN_MODE_UNKNOWN            0x04
                   1309: #define        LONGRUN_MODE_MAX                0x04
1.461     christos 1310:
                   1311: union msrinfo {
                   1312:        u_int64_t       msr;
                   1313:        u_int32_t       regs[2];
                   1314: };
                   1315:
                   1316: u_int32_t longrun_modes[LONGRUN_MODE_MAX][3] = {
                   1317:        /*  MSR low, MSR high, flags bit0 */
                   1318:        {         0,      0,            0},     /* LONGRUN_MODE_MINFREQUENCY */
                   1319:        {         0,    100,            0},     /* LONGRUN_MODE_ECONOMY */
                   1320:        {         0,    100,            1},     /* LONGRUN_MODE_PERFORMANCE */
                   1321:        {       100,    100,            1},     /* LONGRUN_MODE_MAXFREQUENCY */
                   1322: };
                   1323:
1.484     fvdl     1324: static u_int
1.461     christos 1325: tmx86_get_longrun_mode(void)
                   1326: {
                   1327:        u_long          eflags;
                   1328:        union msrinfo   msrinfo;
                   1329:        u_int           low, high, flags, mode;
                   1330:
                   1331:        eflags = read_eflags();
                   1332:        disable_intr();
                   1333:
                   1334:        msrinfo.msr = rdmsr(MSR_TMx86_LONGRUN);
                   1335:        low = LONGRUN_MODE_MASK(msrinfo.regs[0]);
                   1336:        high = LONGRUN_MODE_MASK(msrinfo.regs[1]);
                   1337:        flags = rdmsr(MSR_TMx86_LONGRUN_FLAGS) & 0x01;
                   1338:
                   1339:        for (mode = 0; mode < LONGRUN_MODE_MAX; mode++) {
                   1340:                if (low   == longrun_modes[mode][0] &&
                   1341:                    high  == longrun_modes[mode][1] &&
                   1342:                    flags == longrun_modes[mode][2]) {
                   1343:                        goto out;
                   1344:                }
                   1345:        }
                   1346:        mode = LONGRUN_MODE_UNKNOWN;
                   1347: out:
                   1348:        write_eflags(eflags);
                   1349:        return (mode);
                   1350: }
                   1351:
1.484     fvdl     1352: static u_int
1.462     enami    1353: tmx86_get_longrun_status(u_int *frequency, u_int *voltage, u_int *percentage)
1.461     christos 1354: {
                   1355:        u_long          eflags;
1.484     fvdl     1356:        u_int           eax, ebx, ecx, edx;
1.461     christos 1357:
                   1358:        eflags = read_eflags();
                   1359:        disable_intr();
                   1360:
1.484     fvdl     1361:        CPUID(0x80860007, eax, ebx, ecx, edx);
                   1362:        *frequency = eax;
                   1363:        *voltage = ebx;
                   1364:        *percentage = ecx;
1.461     christos 1365:
                   1366:        write_eflags(eflags);
                   1367:        return (1);
                   1368: }
                   1369:
1.484     fvdl     1370: static u_int
1.461     christos 1371: tmx86_set_longrun_mode(u_int mode)
                   1372: {
                   1373:        u_long          eflags;
                   1374:        union msrinfo   msrinfo;
                   1375:
                   1376:        if (mode >= LONGRUN_MODE_UNKNOWN) {
                   1377:                return (0);
                   1378:        }
                   1379:
                   1380:        eflags = read_eflags();
                   1381:        disable_intr();
                   1382:
                   1383:        /* Write LongRun mode values to Model Specific Register. */
                   1384:        msrinfo.msr = rdmsr(MSR_TMx86_LONGRUN);
                   1385:        msrinfo.regs[0] = LONGRUN_MODE_WRITE(msrinfo.regs[0],
1.462     enami    1386:            longrun_modes[mode][0]);
1.461     christos 1387:        msrinfo.regs[1] = LONGRUN_MODE_WRITE(msrinfo.regs[1],
1.462     enami    1388:            longrun_modes[mode][1]);
1.461     christos 1389:        wrmsr(MSR_TMx86_LONGRUN, msrinfo.msr);
                   1390:
                   1391:        /* Write LongRun mode flags to Model Specific Register. */
                   1392:        msrinfo.msr = rdmsr(MSR_TMx86_LONGRUN_FLAGS);
                   1393:        msrinfo.regs[0] = (msrinfo.regs[0] & ~0x01) | longrun_modes[mode][2];
                   1394:        wrmsr(MSR_TMx86_LONGRUN_FLAGS, msrinfo.msr);
                   1395:
                   1396:        write_eflags(eflags);
                   1397:        return (1);
                   1398: }
                   1399:
                   1400: static u_int                    crusoe_longrun;
                   1401: static u_int                    crusoe_frequency;
                   1402: static u_int                    crusoe_voltage;
                   1403: static u_int                    crusoe_percentage;
                   1404:
                   1405: static void
                   1406: tmx86_get_longrun_status_all(void)
                   1407: {
1.462     enami    1408:
1.461     christos 1409:        tmx86_get_longrun_status(&crusoe_frequency,
1.462     enami    1410:            &crusoe_voltage, &crusoe_percentage);
1.461     christos 1411: }
                   1412:
                   1413:
                   1414: static void
1.484     fvdl     1415: transmeta_cpu_info(struct cpu_info *ci)
1.461     christos 1416: {
1.484     fvdl     1417:        u_int eax, ebx, ecx, edx, nreg = 0;
1.461     christos 1418:
1.484     fvdl     1419:        CPUID(0x80860000, eax, ebx, ecx, edx);
                   1420:        nreg = eax;
1.461     christos 1421:        if (nreg >= 0x80860001) {
1.484     fvdl     1422:                CPUID(0x80860001, eax, ebx, ecx, edx);
                   1423:                printf("%s: Processor revision %u.%u.%u.%u\n",
                   1424:                    ci->ci_dev->dv_xname,
                   1425:                    (ebx >> 24) & 0xff,
                   1426:                    (ebx >> 16) & 0xff,
                   1427:                    (ebx >> 8) & 0xff,
                   1428:                    ebx & 0xff);
1.461     christos 1429:        }
                   1430:        if (nreg >= 0x80860002) {
1.484     fvdl     1431:                CPUID(0x80860002, eax, ebx, ecx, edx);
                   1432:                printf("%s: Code Morphing Software Rev: %u.%u.%u-%u-%u\n",
                   1433:                    ci->ci_dev->dv_xname, (ebx >> 24) & 0xff,
                   1434:                    (ebx >> 16) & 0xff,
                   1435:                    (ebx >> 8) & 0xff,
                   1436:                    ebx & 0xff,
                   1437:                    ecx);
1.461     christos 1438:        }
                   1439:        if (nreg >= 0x80860006) {
1.484     fvdl     1440:                union {
                   1441:                        char text[65];
                   1442:                        struct
                   1443:                        {
                   1444:                                u_int eax;
                   1445:                                u_int ebx;
                   1446:                                u_int ecx;
                   1447:                                u_int edx;
                   1448:                        } regs[4];
                   1449:                } info;
                   1450:                int i;
                   1451:
                   1452:                for (i=0; i<4; i++) {
                   1453:                        CPUID(0x80860003 + i,
                   1454:                            info.regs[i].eax, info.regs[i].ebx,
                   1455:                            info.regs[i].ecx, info.regs[i].edx);
                   1456:                }
                   1457:                info.text[64] = 0;
                   1458:                printf("%s: %s\n", ci->ci_dev->dv_xname, info.text);
1.461     christos 1459:        }
                   1460:
1.493     mycroft  1461:        if (nreg >= 0x80860007) {
                   1462:                crusoe_longrun = tmx86_get_longrun_mode();
                   1463:                tmx86_get_longrun_status(&crusoe_frequency,
                   1464:                    &crusoe_voltage, &crusoe_percentage);
                   1465:                printf("%s: LongRun mode: %d  <%dMHz %dmV %d%%>\n",
                   1466:                    ci->ci_dev->dv_xname,
                   1467:                    crusoe_longrun, crusoe_frequency, crusoe_voltage,
                   1468:                    crusoe_percentage);
                   1469:        }
1.461     christos 1470: }
                   1471:
                   1472: void
1.484     fvdl     1473: transmeta_cpu_setup(struct cpu_info *ci)
1.461     christos 1474: {
1.494     fvdl     1475:        u_int nreg = 0, dummy;
1.462     enami    1476:
1.494     fvdl     1477:        CPUID(0x80860000, nreg, dummy, dummy, dummy);
1.493     mycroft  1478:        if (nreg >= 0x80860007)
                   1479:                tmx86_has_longrun = 1;
1.461     christos 1480: }
                   1481:
                   1482:
                   1483: /* ---------------------------------------------------------------------- */
                   1484:
1.437     thorpej  1485: static const struct i386_cache_info *
1.484     fvdl     1486: cache_info_lookup(const struct i386_cache_info *cai, u_int8_t desc)
1.397     thorpej  1487: {
1.438     thorpej  1488:        int i;
1.397     thorpej  1489:
1.484     fvdl     1490:        for (i = 0; cai[i].cai_desc != 0; i++) {
1.438     thorpej  1491:                if (cai[i].cai_desc == desc)
                   1492:                        return (&cai[i]);
1.437     thorpej  1493:        }
                   1494:
                   1495:        return (NULL);
1.397     thorpej  1496: }
                   1497:
1.438     thorpej  1498: /*
                   1499:  * AMD Cache Info:
                   1500:  *
                   1501:  *     Athlon, Duron:
                   1502:  *
                   1503:  *             Function 8000.0005 L1 TLB/Cache Information
                   1504:  *             EAX -- L1 TLB 2/4MB pages
                   1505:  *             EBX -- L1 TLB 4K pages
                   1506:  *             ECX -- L1 D-cache
                   1507:  *             EDX -- L1 I-cache
                   1508:  *
                   1509:  *             Function 8000.0006 L2 TLB/Cache Information
                   1510:  *             EAX -- L2 TLB 2/4MB pages
                   1511:  *             EBX -- L2 TLB 4K pages
                   1512:  *             ECX -- L2 Unified cache
                   1513:  *             EDX -- reserved
                   1514:  *
                   1515:  *     K5, K6:
                   1516:  *
                   1517:  *             Function 8000.0005 L1 TLB/Cache Information
                   1518:  *             EAX -- reserved
                   1519:  *             EBX -- TLB 4K pages
                   1520:  *             ECX -- L1 D-cache
                   1521:  *             EDX -- L1 I-cache
                   1522:  *
                   1523:  *     K6-III:
                   1524:  *
                   1525:  *             Function 8000.0006 L2 Cache Information
                   1526:  *             EAX -- reserved
                   1527:  *             EBX -- reserved
                   1528:  *             ECX -- L2 Unified cache
                   1529:  *             EDX -- reserved
                   1530:  */
                   1531:
                   1532: /* L1 TLB 2/4MB pages */
                   1533: #define        AMD_L1_EAX_DTLB_ASSOC(x)        (((x) >> 24) & 0xff)
                   1534: #define        AMD_L1_EAX_DTLB_ENTRIES(x)      (((x) >> 16) & 0xff)
                   1535: #define        AMD_L1_EAX_ITLB_ASSOC(x)        (((x) >> 8)  & 0xff)
                   1536: #define        AMD_L1_EAX_ITLB_ENTRIES(x)      ( (x)        & 0xff)
                   1537:
                   1538: /* L1 TLB 4K pages */
                   1539: #define        AMD_L1_EBX_DTLB_ASSOC(x)        (((x) >> 24) & 0xff)
                   1540: #define        AMD_L1_EBX_DTLB_ENTRIES(x)      (((x) >> 16) & 0xff)
                   1541: #define        AMD_L1_EBX_ITLB_ASSOC(x)        (((x) >> 8)  & 0xff)
                   1542: #define        AMD_L1_EBX_ITLB_ENTRIES(x)      ( (x)        & 0xff)
                   1543:
                   1544: /* L1 Data Cache */
                   1545: #define        AMD_L1_ECX_DC_SIZE(x)           ((((x) >> 24) & 0xff) * 1024)
                   1546: #define        AMD_L1_ECX_DC_ASSOC(x)           (((x) >> 16) & 0xff)
                   1547: #define        AMD_L1_ECX_DC_LPT(x)             (((x) >> 8)  & 0xff)
                   1548: #define        AMD_L1_ECX_DC_LS(x)              ( (x)        & 0xff)
                   1549:
                   1550: /* L1 Instruction Cache */
                   1551: #define        AMD_L1_EDX_IC_SIZE(x)           ((((x) >> 24) & 0xff) * 1024)
                   1552: #define        AMD_L1_EDX_IC_ASSOC(x)           (((x) >> 16) & 0xff)
                   1553: #define        AMD_L1_EDX_IC_LPT(x)             (((x) >> 8)  & 0xff)
                   1554: #define        AMD_L1_EDX_IC_LS(x)              ( (x)        & 0xff)
                   1555:
                   1556: /* Note for L2 TLB -- if the upper 16 bits are 0, it is a unified TLB */
                   1557:
                   1558: /* L2 TLB 2/4MB pages */
                   1559: #define        AMD_L2_EAX_DTLB_ASSOC(x)        (((x) >> 28)  & 0xf)
                   1560: #define        AMD_L2_EAX_DTLB_ENTRIES(x)      (((x) >> 16)  & 0xfff)
                   1561: #define        AMD_L2_EAX_IUTLB_ASSOC(x)       (((x) >> 12)  & 0xf)
                   1562: #define        AMD_L2_EAX_IUTLB_ENTRIES(x)     ( (x)         & 0xfff)
                   1563:
                   1564: /* L2 TLB 4K pages */
1.440     thorpej  1565: #define        AMD_L2_EBX_DTLB_ASSOC(x)        (((x) >> 28)  & 0xf)
1.484     fvdl     1566: #define        AMD_L2_EBX_DTLB_ENTRIES(x)      (((x) >> 16)  & 0xfff)
1.440     thorpej  1567: #define        AMD_L2_EBX_IUTLB_ASSOC(x)       (((x) >> 12)  & 0xf)
                   1568: #define        AMD_L2_EBX_IUTLB_ENTRIES(x)     ( (x)         & 0xfff)
1.438     thorpej  1569:
                   1570: /* L2 Cache */
1.440     thorpej  1571: #define        AMD_L2_ECX_C_SIZE(x)            ((((x) >> 16) & 0xffff) * 1024)
                   1572: #define        AMD_L2_ECX_C_ASSOC(x)            (((x) >> 12) & 0xf)
                   1573: #define        AMD_L2_ECX_C_LPT(x)              (((x) >> 8)  & 0xf)
1.438     thorpej  1574: #define        AMD_L2_ECX_C_LS(x)               ( (x)        & 0xff)
                   1575:
                   1576: static const struct i386_cache_info amd_cpuid_l2cache_assoc_info[] = {
1.484     fvdl     1577:        { 0, 0x01,    1 },
                   1578:        { 0, 0x02,    2 },
                   1579:        { 0, 0x04,    4 },
                   1580:        { 0, 0x06,    8 },
                   1581:        { 0, 0x08,   16 },
                   1582:        { 0, 0x0f, 0xff },
                   1583:        { 0, 0x00,    0 },
1.438     thorpej  1584: };
                   1585:
                   1586: void
1.502     junyoung 1587: amd_cpu_cacheinfo(struct cpu_info *ci)
1.438     thorpej  1588: {
                   1589:        const struct i386_cache_info *cp;
                   1590:        struct i386_cache_info *cai;
                   1591:        int family, model;
                   1592:        u_int descs[4];
                   1593:        u_int lfunc;
                   1594:
1.484     fvdl     1595:        family = (ci->ci_signature >> 8) & 15;
1.438     thorpej  1596:        if (family < CPU_MINFAMILY)
1.502     junyoung 1597:                panic("amd_cpu_cacheinfo: strange family value");
1.484     fvdl     1598:        model = CPUID2MODEL(ci->ci_signature);
1.438     thorpej  1599:
                   1600:        /*
                   1601:         * K5 model 0 has none of this info.
                   1602:         */
                   1603:        if (family == 5 && model == 0)
                   1604:                return;
                   1605:
                   1606:        /*
                   1607:         * Determine the largest extended function value.
                   1608:         */
1.484     fvdl     1609:        CPUID(0x80000000, descs[0], descs[1], descs[2], descs[3]);
1.438     thorpej  1610:        lfunc = descs[0];
                   1611:
                   1612:        /*
                   1613:         * Determine L1 cache/TLB info.
                   1614:         */
                   1615:        if (lfunc < 0x80000005) {
                   1616:                /* No L1 cache info available. */
                   1617:                return;
                   1618:        }
                   1619:
1.484     fvdl     1620:        CPUID(0x80000005, descs[0], descs[1], descs[2], descs[3]);
1.438     thorpej  1621:
                   1622:        /*
                   1623:         * K6-III and higher have large page TLBs.
                   1624:         */
                   1625:        if ((family == 5 && model >= 9) || family >= 6) {
                   1626:                cai = &ci->ci_cinfo[CAI_ITLB2];
                   1627:                cai->cai_totalsize = AMD_L1_EAX_ITLB_ENTRIES(descs[0]);
                   1628:                cai->cai_associativity = AMD_L1_EAX_ITLB_ASSOC(descs[0]);
                   1629:                cai->cai_linesize = (4 * 1024 * 1024);
                   1630:
                   1631:                cai = &ci->ci_cinfo[CAI_DTLB2];
                   1632:                cai->cai_totalsize = AMD_L1_EAX_DTLB_ENTRIES(descs[0]);
                   1633:                cai->cai_associativity = AMD_L1_EAX_DTLB_ASSOC(descs[0]);
                   1634:                cai->cai_linesize = (4 * 1024 * 1024);
                   1635:        }
                   1636:
                   1637:        cai = &ci->ci_cinfo[CAI_ITLB];
                   1638:        cai->cai_totalsize = AMD_L1_EBX_ITLB_ENTRIES(descs[1]);
                   1639:        cai->cai_associativity = AMD_L1_EBX_ITLB_ASSOC(descs[1]);
                   1640:        cai->cai_linesize = (4 * 1024);
                   1641:
                   1642:        cai = &ci->ci_cinfo[CAI_DTLB];
                   1643:        cai->cai_totalsize = AMD_L1_EBX_DTLB_ENTRIES(descs[1]);
                   1644:        cai->cai_associativity = AMD_L1_EBX_DTLB_ASSOC(descs[1]);
1.484     fvdl     1645:        cai->cai_linesize = (4 * 1024);
1.438     thorpej  1646:
                   1647:        cai = &ci->ci_cinfo[CAI_DCACHE];
                   1648:        cai->cai_totalsize = AMD_L1_ECX_DC_SIZE(descs[2]);
                   1649:        cai->cai_associativity = AMD_L1_ECX_DC_ASSOC(descs[2]);
                   1650:        cai->cai_linesize = AMD_L1_EDX_IC_LS(descs[2]);
                   1651:
                   1652:        cai = &ci->ci_cinfo[CAI_ICACHE];
                   1653:        cai->cai_totalsize = AMD_L1_EDX_IC_SIZE(descs[3]);
                   1654:        cai->cai_associativity = AMD_L1_EDX_IC_ASSOC(descs[3]);
                   1655:        cai->cai_linesize = AMD_L1_EDX_IC_LS(descs[3]);
                   1656:
                   1657:        /*
                   1658:         * Determine L2 cache/TLB info.
                   1659:         */
                   1660:        if (lfunc < 0x80000006) {
                   1661:                /* No L2 cache info available. */
                   1662:                return;
                   1663:        }
                   1664:
1.484     fvdl     1665:        CPUID(0x80000006, descs[0], descs[1], descs[2], descs[3]);
1.438     thorpej  1666:
                   1667:        cai = &ci->ci_cinfo[CAI_L2CACHE];
                   1668:        cai->cai_totalsize = AMD_L2_ECX_C_SIZE(descs[2]);
                   1669:        cai->cai_associativity = AMD_L2_ECX_C_ASSOC(descs[2]);
                   1670:        cai->cai_linesize = AMD_L2_ECX_C_LS(descs[2]);
                   1671:
                   1672:        cp = cache_info_lookup(amd_cpuid_l2cache_assoc_info,
1.484     fvdl     1673:            cai->cai_associativity);
1.438     thorpej  1674:        if (cp != NULL)
                   1675:                cai->cai_associativity = cp->cai_associativity;
                   1676:        else
                   1677:                cai->cai_associativity = 0;     /* XXX Unknown/reserved */
1.402     explorer 1678: }
                   1679:
1.472     thorpej  1680: static const char n_support[] __attribute__((__unused__)) =
1.467     christos 1681:     "NOTICE: this kernel does not support %s CPU class\n";
1.472     thorpej  1682: static const char n_lower[] __attribute__((__unused__)) =
                   1683:     "NOTICE: lowering CPU class to %s\n";
1.467     christos 1684:
1.379     jdolecek 1685: void
1.437     thorpej  1686: identifycpu(struct cpu_info *ci)
1.16      cgd      1687: {
1.417     jdolecek 1688:        const char *name, *modifier, *vendorname, *brand = "";
1.216     fvdl     1689:        int class = CPUCLASS_386, vendor, i, max;
1.504   ! junyoung 1690:        int modif, family, model, step;
1.418     jdolecek 1691:        const struct cpu_cpuid_nameclass *cpup = NULL;
1.454     enami    1692:        const struct cpu_cpuid_family *cpufam;
1.484     fvdl     1693:        char *cpuname = ci->ci_dev->dv_xname;
                   1694:        char buf[1024];
                   1695:        char *sep;
1.503     junyoung 1696:        char *feature_str[3];
1.86      mycroft  1697:
1.484     fvdl     1698:        if (ci->ci_cpuid_level == -1) {
1.59      mycroft  1699: #ifdef DIAGNOSTIC
1.216     fvdl     1700:                if (cpu < 0 || cpu >=
1.454     enami    1701:                    sizeof(i386_nocpuid_cpus) / sizeof(i386_nocpuid_cpus[0]))
1.483     provos   1702:                        panic("unknown cpu type %d", cpu);
1.216     fvdl     1703: #endif
                   1704:                name = i386_nocpuid_cpus[cpu].cpu_name;
                   1705:                vendor = i386_nocpuid_cpus[cpu].cpu_vendor;
                   1706:                vendorname = i386_nocpuid_cpus[cpu].cpu_vendorname;
                   1707:                class = i386_nocpuid_cpus[cpu].cpu_class;
1.484     fvdl     1708:                ci->cpu_setup = i386_nocpuid_cpus[cpu].cpu_setup;
1.464     christos 1709:                ci->ci_info = i386_nocpuid_cpus[cpu].cpu_info;
1.216     fvdl     1710:                modifier = "";
                   1711:        } else {
                   1712:                max = sizeof (i386_cpuid_cpus) / sizeof (i386_cpuid_cpus[0]);
1.484     fvdl     1713:                modif = (ci->ci_signature >> 12) & 0x3;
                   1714:                family = (ci->ci_signature >> 8) & 0xf;
1.216     fvdl     1715:                if (family < CPU_MINFAMILY)
                   1716:                        panic("identifycpu: strange family value");
1.484     fvdl     1717:                model = CPUID2MODEL(ci->ci_signature);
1.500     junyoung 1718:                step = CPUID2STEPPING(ci->ci_signature);
1.484     fvdl     1719:                printf("%s: family %x model %x step %x\n", cpuname, family,
                   1720:                        model, step);
1.216     fvdl     1721:
                   1722:                for (i = 0; i < max; i++) {
1.484     fvdl     1723:                        if (!strncmp((char *)ci->ci_vendor,
1.216     fvdl     1724:                            i386_cpuid_cpus[i].cpu_id, 12)) {
                   1725:                                cpup = &i386_cpuid_cpus[i];
                   1726:                                break;
                   1727:                        }
                   1728:                }
                   1729:
                   1730:                if (cpup == NULL) {
                   1731:                        vendor = CPUVENDOR_UNKNOWN;
1.484     fvdl     1732:                        if (ci->ci_vendor[0] != '\0')
                   1733:                                vendorname = (char *)&ci->ci_vendor[0];
1.216     fvdl     1734:                        else
                   1735:                                vendorname = "Unknown";
                   1736:                        if (family > CPU_MAXFAMILY)
                   1737:                                family = CPU_MAXFAMILY;
                   1738:                        class = family - 3;
                   1739:                        modifier = "";
                   1740:                        name = "";
1.484     fvdl     1741:                        ci->cpu_setup = NULL;
1.464     christos 1742:                        ci->ci_info = NULL;
1.216     fvdl     1743:                } else {
                   1744:                        vendor = cpup->cpu_vendor;
                   1745:                        vendorname = cpup->cpu_vendorname;
                   1746:                        modifier = modifiers[modif];
                   1747:                        if (family > CPU_MAXFAMILY) {
                   1748:                                family = CPU_MAXFAMILY;
                   1749:                                model = CPU_DEFMODEL;
                   1750:                        } else if (model > CPU_MAXMODEL)
                   1751:                                model = CPU_DEFMODEL;
1.454     enami    1752:                        cpufam = &cpup->cpu_family[family - CPU_MINFAMILY];
                   1753:                        name = cpufam->cpu_models[model];
1.216     fvdl     1754:                        if (name == NULL)
1.484     fvdl     1755:                            name = cpufam->cpu_models[CPU_DEFMODEL];
1.454     enami    1756:                        class = cpufam->cpu_class;
1.484     fvdl     1757:                        ci->cpu_setup = cpufam->cpu_setup;
1.464     christos 1758:                        ci->ci_info = cpufam->cpu_info;
1.417     jdolecek 1759:
                   1760:                        /*
                   1761:                         * Intel processors family >= 6, model 8 allow to
                   1762:                         * recognize brand by Brand ID value.
                   1763:                         */
1.454     enami    1764:                        if (vendor == CPUVENDOR_INTEL && family >= 6 &&
1.484     fvdl     1765:                            model >= 8 && ci->ci_brand_id &&
1.485     fvdl     1766:                            ci->ci_brand_id < 8)
1.484     fvdl     1767:                                brand = i386_intel_brand[ci->ci_brand_id];
1.487     junyoung 1768:
                   1769:                        if (vendor == CPUVENDOR_AMD && family == 6 &&
                   1770:                            model >= 6) {
                   1771:                                if (ci->ci_brand_id == 1)
                   1772:                                        /*
                   1773:                                         * It's Duron. We override the
                   1774:                                         * name, since it might have been
                   1775:                                         * misidentified as Athlon.
                   1776:                                         */
                   1777:                                        name = amd_brand[ci->ci_brand_id];
                   1778:                                else
                   1779:                                        brand = amd_brand_name;
                   1780:                        }
1.500     junyoung 1781:
                   1782:                        if (vendor == CPUVENDOR_IDT && family >= 6)
                   1783:                                vendorname = "VIA";
1.216     fvdl     1784:                }
1.104     cgd      1785:        }
                   1786:
1.484     fvdl     1787:        cpu_class = class;
                   1788:        ci->ci_cpu_class = class;
                   1789:
                   1790: #if defined(I586_CPU) || defined(I686_CPU)
                   1791:        /*
                   1792:         * If we have a cycle counter, compute the approximate
                   1793:         * CPU speed in MHz.
                   1794:         * XXX this needs to run on the CPU being probed..
                   1795:         */
                   1796:        if (ci->ci_feature_flags & CPUID_TSC) {
                   1797:                u_int64_t last_tsc;
                   1798:
                   1799:                last_tsc = rdtsc();
                   1800:                delay(100000);
                   1801:                ci->ci_tsc_freq = (rdtsc() - last_tsc) * 10;
                   1802:                microtime_func = tsc_microtime;
                   1803:        }
                   1804:        /* XXX end XXX */
                   1805: #endif
                   1806:
1.454     enami    1807:        snprintf(cpu_model, sizeof(cpu_model), "%s%s%s%s%s%s%s (%s-class)",
                   1808:            vendorname,
                   1809:            *modifier ? " " : "", modifier,
                   1810:            *name ? " " : "", name,
                   1811:            *brand ? " " : "", brand,
                   1812:            classnames[class]);
1.484     fvdl     1813:        printf("%s: %s", cpuname, cpu_model);
1.216     fvdl     1814:
1.484     fvdl     1815:        if (ci->ci_tsc_freq != 0)
                   1816:                printf(", %qd.%02qd MHz", (ci->ci_tsc_freq + 4999) / 1000000,
                   1817:                    ((ci->ci_tsc_freq + 4999) / 10000) % 100);
                   1818:        printf("\n");
                   1819:
                   1820:        if (ci->ci_info)
                   1821:                (*ci->ci_info)(ci);
                   1822:
1.503     junyoung 1823:        if (vendor == CPUVENDOR_INTEL) {
                   1824:                feature_str[0] = CPUID_FLAGS1;
                   1825:                feature_str[1] = CPUID_FLAGS2;
                   1826:                feature_str[2] = CPUID_FLAGS3;
                   1827:        } else {
                   1828:                feature_str[0] = CPUID_FLAGS1;
                   1829:                feature_str[1] = CPUID_EXT_FLAGS2;
                   1830:                feature_str[2] = CPUID_EXT_FLAGS3;
                   1831:        }
                   1832:
1.484     fvdl     1833:        if (ci->ci_feature_flags) {
                   1834:                if ((ci->ci_feature_flags & CPUID_MASK1) != 0) {
1.501     junyoung 1835:                        bitmask_snprintf(ci->ci_feature_flags,
1.503     junyoung 1836:                            feature_str[0], buf, sizeof(buf));
1.484     fvdl     1837:                        printf("%s: features %s\n", cpuname, buf);
                   1838:                }
                   1839:                if ((ci->ci_feature_flags & CPUID_MASK2) != 0) {
1.501     junyoung 1840:                        bitmask_snprintf(ci->ci_feature_flags,
1.503     junyoung 1841:                            feature_str[1], buf, sizeof(buf));
1.484     fvdl     1842:                        printf("%s: features %s\n", cpuname, buf);
                   1843:                }
                   1844:                if ((ci->ci_feature_flags & CPUID_MASK3) != 0) {
1.501     junyoung 1845:                        bitmask_snprintf(ci->ci_feature_flags,
1.503     junyoung 1846:                            feature_str[2], buf, sizeof(buf));
1.484     fvdl     1847:                        printf("%s: features %s\n", cpuname, buf);
                   1848:                }
                   1849:        }
1.402     explorer 1850:
1.484     fvdl     1851:        if (ci->ci_cinfo[CAI_ICACHE].cai_totalsize != 0 ||
                   1852:            ci->ci_cinfo[CAI_DCACHE].cai_totalsize != 0) {
                   1853:                sep = print_cache_config(ci, CAI_ICACHE, "I-cache", NULL);
                   1854:                sep = print_cache_config(ci, CAI_DCACHE, "D-cache", sep);
                   1855:                if (sep != NULL)
                   1856:                        printf("\n");
                   1857:        }
                   1858:        if (ci->ci_cinfo[CAI_L2CACHE].cai_totalsize != 0) {
                   1859:                sep = print_cache_config(ci, CAI_L2CACHE, "L2 cache", NULL);
                   1860:                if (sep != NULL)
                   1861:                        printf("\n");
                   1862:        }
                   1863:        if (ci->ci_cinfo[CAI_ITLB].cai_totalsize != 0) {
                   1864:                sep = print_tlb_config(ci, CAI_ITLB, "ITLB", NULL);
                   1865:                sep = print_tlb_config(ci, CAI_ITLB2, NULL, sep);
                   1866:                if (sep != NULL)
                   1867:                        printf("\n");
                   1868:        }
                   1869:        if (ci->ci_cinfo[CAI_DTLB].cai_totalsize != 0) {
                   1870:                sep = print_tlb_config(ci, CAI_DTLB, "DTLB", NULL);
                   1871:                sep = print_tlb_config(ci, CAI_DTLB2, NULL, sep);
                   1872:                if (sep != NULL)
                   1873:                        printf("\n");
                   1874:        }
                   1875:
                   1876:        if (ci->ci_cpuid_level >= 3 && (ci->ci_feature_flags & CPUID_PN)) {
                   1877:                printf("%s: serial number %04X-%04X-%04X-%04X-%04X-%04X\n",
                   1878:                    cpuname,
                   1879:                    ci->ci_cpu_serial[0] / 65536, ci->ci_cpu_serial[0] % 65536,
                   1880:                    ci->ci_cpu_serial[1] / 65536, ci->ci_cpu_serial[1] % 65536,
                   1881:                    ci->ci_cpu_serial[2] / 65536, ci->ci_cpu_serial[2] % 65536);
                   1882:        }
1.18      cgd      1883:
1.16      cgd      1884:        /*
                   1885:         * Now that we have told the user what they have,
                   1886:         * let them know if that machine type isn't configured.
                   1887:         */
1.24      cgd      1888:        switch (cpu_class) {
1.216     fvdl     1889: #if !defined(I386_CPU) && !defined(I486_CPU) && !defined(I586_CPU) && !defined(I686_CPU)
1.100     mycroft  1890: #error No CPU classes configured.
                   1891: #endif
1.216     fvdl     1892: #ifndef I686_CPU
                   1893:        case CPUCLASS_686:
1.467     christos 1894:                printf(n_support, "Pentium Pro");
1.216     fvdl     1895: #ifdef I586_CPU
1.467     christos 1896:                printf(n_lower, "i586");
1.216     fvdl     1897:                cpu_class = CPUCLASS_586;
                   1898:                break;
                   1899: #endif
                   1900: #endif
1.165     mycroft  1901: #ifndef I586_CPU
1.118     mycroft  1902:        case CPUCLASS_586:
1.467     christos 1903:                printf(n_support, "Pentium");
1.165     mycroft  1904: #ifdef I486_CPU
1.467     christos 1905:                printf(n_lower, "i486");
1.118     mycroft  1906:                cpu_class = CPUCLASS_486;
                   1907:                break;
1.16      cgd      1908: #endif
1.165     mycroft  1909: #endif
                   1910: #ifndef I486_CPU
1.18      cgd      1911:        case CPUCLASS_486:
1.467     christos 1912:                printf(n_support, "i486");
1.165     mycroft  1913: #ifdef I386_CPU
1.467     christos 1914:                printf(n_lower, "i386");
1.118     mycroft  1915:                cpu_class = CPUCLASS_386;
                   1916:                break;
                   1917: #endif
1.165     mycroft  1918: #endif
                   1919: #ifndef I386_CPU
1.118     mycroft  1920:        case CPUCLASS_386:
1.467     christos 1921:                printf(n_support, "i386");
1.187     mycroft  1922:                panic("no appropriate CPU class available");
1.59      mycroft  1923: #endif
1.16      cgd      1924:        default:
1.448     thorpej  1925:                break;
                   1926:        }
                   1927:
                   1928:        /*
                   1929:         * Now plug in optimized versions of various routines we
                   1930:         * might have.
                   1931:         */
                   1932:        switch (cpu_class) {
                   1933: #if defined(I686_CPU)
                   1934:        case CPUCLASS_686:
                   1935:                copyout_func = i486_copyout;
                   1936:                break;
                   1937: #endif
                   1938: #if defined(I586_CPU)
                   1939:        case CPUCLASS_586:
                   1940:                copyout_func = i486_copyout;
                   1941:                break;
                   1942: #endif
                   1943: #if defined(I486_CPU)
                   1944:        case CPUCLASS_486:
                   1945:                copyout_func = i486_copyout;
                   1946:                break;
                   1947: #endif
                   1948:        default:
                   1949:                /* We just inherit the default i386 versions. */
1.16      cgd      1950:                break;
1.121     mycroft  1951:        }
                   1952:
                   1953:        if (cpu == CPU_486DLC) {
                   1954: #ifndef CYRIX_CACHE_WORKS
1.210     christos 1955:                printf("WARNING: CYRIX 486DLC CACHE UNCHANGED.\n");
1.121     mycroft  1956: #else
                   1957: #ifndef CYRIX_CACHE_REALLY_WORKS
1.210     christos 1958:                printf("WARNING: CYRIX 486DLC CACHE ENABLED IN HOLD-FLUSH MODE.\n");
1.121     mycroft  1959: #else
1.210     christos 1960:                printf("WARNING: CYRIX 486DLC CACHE ENABLED.\n");
1.121     mycroft  1961: #endif
                   1962: #endif
1.16      cgd      1963:        }
1.147     mycroft  1964:
1.450     thorpej  1965: #if defined(I686_CPU)
                   1966:        /*
                   1967:         * If we have FXSAVE/FXRESTOR, use them.
                   1968:         */
                   1969:        if (cpu_feature & CPUID_FXSR) {
1.451     thorpej  1970:                i386_use_fxsave = 1;
1.484     fvdl     1971:
1.451     thorpej  1972:                /*
                   1973:                 * If we have SSE/SSE2, enable XMM exceptions, and
                   1974:                 * notify userland.
                   1975:                 */
                   1976:                if (cpu_feature & (CPUID_SSE|CPUID_SSE2)) {
                   1977:                        if (cpu_feature & CPUID_SSE)
                   1978:                                i386_has_sse = 1;
                   1979:                        if (cpu_feature & CPUID_SSE2)
                   1980:                                i386_has_sse2 = 1;
                   1981:                }
1.450     thorpej  1982:        } else
1.451     thorpej  1983:                i386_use_fxsave = 0;
1.450     thorpej  1984: #endif /* I686_CPU */
1.1       cgd      1985: }
                   1986:
1.484     fvdl     1987: /*
1.104     cgd      1988:  * machine dependent system variables.
1.484     fvdl     1989:  */
1.195     mycroft  1990: int
1.104     cgd      1991: cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
                   1992:        int *name;
                   1993:        u_int namelen;
                   1994:        void *oldp;
                   1995:        size_t *oldlenp;
                   1996:        void *newp;
                   1997:        size_t newlen;
                   1998:        struct proc *p;
                   1999: {
                   2000:        dev_t consdev;
1.255     drochner 2001:        struct btinfo_bootpath *bibp;
1.461     christos 2002:        int error, mode;
1.104     cgd      2003:
                   2004:        /* all sysctl names at this level are terminal */
                   2005:        if (namelen != 1)
                   2006:                return (ENOTDIR);               /* overloaded */
                   2007:
                   2008:        switch (name[0]) {
                   2009:        case CPU_CONSDEV:
                   2010:                if (cn_tab != NULL)
                   2011:                        consdev = cn_tab->cn_dev;
                   2012:                else
                   2013:                        consdev = NODEV;
                   2014:                return (sysctl_rdstruct(oldp, oldlenp, newp, &consdev,
                   2015:                    sizeof consdev));
1.215     fvdl     2016:
                   2017:        case CPU_BIOSBASEMEM:
                   2018:                return (sysctl_rdint(oldp, oldlenp, newp, biosbasemem));
                   2019:
                   2020:        case CPU_BIOSEXTMEM:
                   2021:                return (sysctl_rdint(oldp, oldlenp, newp, biosextmem));
                   2022:
                   2023:        case CPU_NKPDE:
                   2024:                return (sysctl_rdint(oldp, oldlenp, newp, nkpde));
1.366     fvdl     2025:
                   2026:        case CPU_FPU_PRESENT:
                   2027:                return (sysctl_rdint(oldp, oldlenp, newp, i386_fpu_present));
1.215     fvdl     2028:
1.255     drochner 2029:        case CPU_BOOTED_KERNEL:
                   2030:                bibp = lookup_bootinfo(BTINFO_BOOTPATH);
                   2031:                if(!bibp)
                   2032:                        return(ENOENT); /* ??? */
                   2033:                return (sysctl_rdstring(oldp, oldlenp, newp, bibp->bootpath));
1.343     fvdl     2034:        case CPU_DISKINFO:
                   2035:                if (i386_alldisks == NULL)
1.339     fvdl     2036:                        return (ENOENT);
1.343     fvdl     2037:                return (sysctl_rdstruct(oldp, oldlenp, newp, i386_alldisks,
                   2038:                    sizeof (struct disklist) +
                   2039:                        (i386_ndisks - 1) * sizeof (struct nativedisk_info)));
1.451     thorpej  2040:        case CPU_OSFXSR:
                   2041:                return (sysctl_rdint(oldp, oldlenp, newp, i386_use_fxsave));
                   2042:        case CPU_SSE:
                   2043:                return (sysctl_rdint(oldp, oldlenp, newp, i386_has_sse));
                   2044:        case CPU_SSE2:
                   2045:                return (sysctl_rdint(oldp, oldlenp, newp, i386_has_sse2));
1.461     christos 2046:        case CPU_TMLR_MODE:
                   2047:                if (!tmx86_has_longrun)
                   2048:                        return (EOPNOTSUPP);
                   2049:                mode = (int)(crusoe_longrun = tmx86_get_longrun_mode());
                   2050:                error = sysctl_int(oldp, oldlenp, newp, newlen, &mode);
1.462     enami    2051:                if (!error && (u_int)mode != crusoe_longrun) {
1.461     christos 2052:                        if (tmx86_set_longrun_mode(mode)) {
                   2053:                                crusoe_longrun = (u_int)mode;
                   2054:                        } else {
                   2055:                                error = EINVAL;
                   2056:                        }
                   2057:                }
                   2058:                return (error);
                   2059:        case CPU_TMLR_FREQUENCY:
                   2060:                if (!tmx86_has_longrun)
                   2061:                        return (EOPNOTSUPP);
                   2062:                tmx86_get_longrun_status_all();
                   2063:                return (sysctl_rdint(oldp, oldlenp, newp, crusoe_frequency));
                   2064:        case CPU_TMLR_VOLTAGE:
                   2065:                if (!tmx86_has_longrun)
                   2066:                        return (EOPNOTSUPP);
                   2067:                tmx86_get_longrun_status_all();
                   2068:                return (sysctl_rdint(oldp, oldlenp, newp, crusoe_voltage));
                   2069:        case CPU_TMLR_PERCENTAGE:
                   2070:                if (!tmx86_has_longrun)
                   2071:                        return (EOPNOTSUPP);
                   2072:                tmx86_get_longrun_status_all();
                   2073:                return (sysctl_rdint(oldp, oldlenp, newp, crusoe_percentage));
1.104     cgd      2074:        default:
                   2075:                return (EOPNOTSUPP);
                   2076:        }
                   2077:        /* NOTREACHED */
                   2078: }
1.151     christos 2079:
1.1       cgd      2080: /*
                   2081:  * Send an interrupt to process.
                   2082:  *
                   2083:  * Stack is set up to allow sigcode stored
                   2084:  * in u. to call routine, followed by kcall
                   2085:  * to sigreturn routine below.  After sigreturn
                   2086:  * resets the signal mask, the stack, and the
                   2087:  * frame pointer, it returns to the user
                   2088:  * specified pc, psl.
                   2089:  */
                   2090: void
1.477     thorpej  2091: sendsig(sig, mask, code)
1.319     mycroft  2092:        int sig;
                   2093:        sigset_t *mask;
1.126     cgd      2094:        u_long code;
1.1       cgd      2095: {
1.298     mycroft  2096:        struct proc *p = curproc;
1.477     thorpej  2097:        struct sigacts *ps = p->p_sigacts;
1.298     mycroft  2098:        struct trapframe *tf;
1.82      ws       2099:        struct sigframe *fp, frame;
1.319     mycroft  2100:        int onstack;
1.477     thorpej  2101:        sig_t catcher = SIGACTION(p, sig).sa_handler;
1.1       cgd      2102:
1.319     mycroft  2103:        tf = p->p_md.md_regs;
1.135     christos 2104:
1.319     mycroft  2105:        /* Do we need to jump onto the signal stack? */
                   2106:        onstack =
1.425     jdolecek 2107:            (p->p_sigctx.ps_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 &&
                   2108:            (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0;
1.135     christos 2109:
1.319     mycroft  2110:        /* Allocate space for the signal handler context. */
                   2111:        if (onstack)
1.425     jdolecek 2112:                fp = (struct sigframe *)((caddr_t)p->p_sigctx.ps_sigstk.ss_sp +
                   2113:                                          p->p_sigctx.ps_sigstk.ss_size);
1.319     mycroft  2114:        else
                   2115:                fp = (struct sigframe *)tf->tf_esp;
                   2116:        fp--;
1.1       cgd      2117:
1.319     mycroft  2118:        /* Build stack frame for signal trampoline. */
1.477     thorpej  2119:        switch (ps->sa_sigdesc[sig].sd_vers) {
                   2120: #if 1 /* COMPAT_16 */
                   2121:        case 0:         /* legacy on-stack sigtramp */
                   2122:                frame.sf_ra = (int)p->p_sigctx.ps_sigcode;
                   2123:                break;
                   2124: #endif /* COMPAT_16 */
                   2125:
                   2126:        case 1:
                   2127:                frame.sf_ra = (int)ps->sa_sigdesc[sig].sd_tramp;
                   2128:                break;
                   2129:
                   2130:        default:
                   2131:                /* Don't know what trampoline version; kill it. */
                   2132:                sigexit(p, SIGILL);
                   2133:        }
                   2134:
1.319     mycroft  2135:        frame.sf_signum = sig;
1.82      ws       2136:        frame.sf_code = code;
                   2137:        frame.sf_scp = &fp->sf_sc;
                   2138:
1.319     mycroft  2139:        /* Save register context. */
1.157     mycroft  2140: #ifdef VM86
                   2141:        if (tf->tf_eflags & PSL_VM) {
                   2142:                frame.sf_sc.sc_gs = tf->tf_vm86_gs;
                   2143:                frame.sf_sc.sc_fs = tf->tf_vm86_fs;
                   2144:                frame.sf_sc.sc_es = tf->tf_vm86_es;
                   2145:                frame.sf_sc.sc_ds = tf->tf_vm86_ds;
1.196     mycroft  2146:                frame.sf_sc.sc_eflags = get_vflags(p);
1.422     mycroft  2147:                (*p->p_emul->e_syscall_intern)(p);
1.157     mycroft  2148:        } else
                   2149: #endif
                   2150:        {
1.445     sommerfe 2151:                frame.sf_sc.sc_gs = tf->tf_gs;
                   2152:                frame.sf_sc.sc_fs = tf->tf_fs;
1.157     mycroft  2153:                frame.sf_sc.sc_es = tf->tf_es;
                   2154:                frame.sf_sc.sc_ds = tf->tf_ds;
1.184     mycroft  2155:                frame.sf_sc.sc_eflags = tf->tf_eflags;
1.157     mycroft  2156:        }
1.184     mycroft  2157:        frame.sf_sc.sc_edi = tf->tf_edi;
                   2158:        frame.sf_sc.sc_esi = tf->tf_esi;
                   2159:        frame.sf_sc.sc_ebp = tf->tf_ebp;
                   2160:        frame.sf_sc.sc_ebx = tf->tf_ebx;
                   2161:        frame.sf_sc.sc_edx = tf->tf_edx;
                   2162:        frame.sf_sc.sc_ecx = tf->tf_ecx;
                   2163:        frame.sf_sc.sc_eax = tf->tf_eax;
                   2164:        frame.sf_sc.sc_eip = tf->tf_eip;
                   2165:        frame.sf_sc.sc_cs = tf->tf_cs;
                   2166:        frame.sf_sc.sc_esp = tf->tf_esp;
                   2167:        frame.sf_sc.sc_ss = tf->tf_ss;
1.319     mycroft  2168:        frame.sf_sc.sc_trapno = tf->tf_trapno;
                   2169:        frame.sf_sc.sc_err = tf->tf_err;
                   2170:
                   2171:        /* Save signal stack. */
1.425     jdolecek 2172:        frame.sf_sc.sc_onstack = p->p_sigctx.ps_sigstk.ss_flags & SS_ONSTACK;
1.319     mycroft  2173:
                   2174:        /* Save signal mask. */
                   2175:        frame.sf_sc.sc_mask = *mask;
1.322     thorpej  2176:
                   2177: #ifdef COMPAT_13
                   2178:        /*
                   2179:         * XXX We always have to save an old style signal mask because
                   2180:         * XXX we might be delivering a signal to a process which will
                   2181:         * XXX escape from the signal in a non-standard way and invoke
                   2182:         * XXX sigreturn() directly.
                   2183:         */
                   2184:        native_sigset_to_sigset13(mask, &frame.sf_sc.__sc_mask13);
                   2185: #endif
1.1       cgd      2186:
1.87      mycroft  2187:        if (copyout(&frame, fp, sizeof(frame)) != 0) {
1.1       cgd      2188:                /*
                   2189:                 * Process has trashed its stack; give it an illegal
                   2190:                 * instruction to halt it in its tracks.
                   2191:                 */
1.93      mycroft  2192:                sigexit(p, SIGILL);
                   2193:                /* NOTREACHED */
1.1       cgd      2194:        }
                   2195:
1.73      mycroft  2196:        /*
1.475     thorpej  2197:         * Build context to run handler in.  We invoke the handler
1.477     thorpej  2198:         * directly, only returning via the trampoline.  Note the
                   2199:         * trampoline version numbers are coordinated with machine-
                   2200:         * dependent code in libc.
1.59      mycroft  2201:         */
1.445     sommerfe 2202:        tf->tf_gs = GSEL(GUDATA_SEL, SEL_UPL);
                   2203:        tf->tf_fs = GSEL(GUDATA_SEL, SEL_UPL);
1.185     mycroft  2204:        tf->tf_es = GSEL(GUDATA_SEL, SEL_UPL);
                   2205:        tf->tf_ds = GSEL(GUDATA_SEL, SEL_UPL);
1.475     thorpej  2206:        tf->tf_eip = (int)catcher;
1.185     mycroft  2207:        tf->tf_cs = GSEL(GUCODE_SEL, SEL_UPL);
1.198     mycroft  2208:        tf->tf_eflags &= ~(PSL_T|PSL_VM|PSL_AC);
1.185     mycroft  2209:        tf->tf_esp = (int)fp;
1.177     mycroft  2210:        tf->tf_ss = GSEL(GUDATA_SEL, SEL_UPL);
1.319     mycroft  2211:
                   2212:        /* Remember that we're now on the signal stack. */
                   2213:        if (onstack)
1.425     jdolecek 2214:                p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK;
1.1       cgd      2215: }
                   2216:
                   2217: /*
                   2218:  * System call to cleanup state after a signal
                   2219:  * has been taken.  Reset signal mask and
                   2220:  * stack state from context left by sendsig (above).
                   2221:  * Return to previous pc and psl as specified by
                   2222:  * context left by sendsig. Check carefully to
                   2223:  * make sure that the user has not modified the
1.110     mycroft  2224:  * psl to gain improper privileges or to cause
1.1       cgd      2225:  * a machine fault.
                   2226:  */
1.195     mycroft  2227: int
1.320     mycroft  2228: sys___sigreturn14(p, v, retval)
1.1       cgd      2229:        struct proc *p;
1.172     thorpej  2230:        void *v;
                   2231:        register_t *retval;
                   2232: {
1.320     mycroft  2233:        struct sys___sigreturn14_args /* {
1.123     cgd      2234:                syscallarg(struct sigcontext *) sigcntxp;
1.172     thorpej  2235:        } */ *uap = v;
1.82      ws       2236:        struct sigcontext *scp, context;
1.298     mycroft  2237:        struct trapframe *tf;
1.59      mycroft  2238:
1.27      cgd      2239:        /*
1.59      mycroft  2240:         * The trampoline code hands us the context.
                   2241:         * It is unsafe to keep track of it ourselves, in the event that a
                   2242:         * program jumps out of a signal handler.
1.27      cgd      2243:         */
1.123     cgd      2244:        scp = SCARG(uap, sigcntxp);
1.87      mycroft  2245:        if (copyin((caddr_t)scp, &context, sizeof(*scp)) != 0)
1.122     mycroft  2246:                return (EFAULT);
1.1       cgd      2247:
1.319     mycroft  2248:        /* Restore register context. */
                   2249:        tf = p->p_md.md_regs;
1.157     mycroft  2250: #ifdef VM86
                   2251:        if (context.sc_eflags & PSL_VM) {
1.422     mycroft  2252:                void syscall_vm86 __P((struct trapframe));
                   2253:
1.157     mycroft  2254:                tf->tf_vm86_gs = context.sc_gs;
                   2255:                tf->tf_vm86_fs = context.sc_fs;
                   2256:                tf->tf_vm86_es = context.sc_es;
                   2257:                tf->tf_vm86_ds = context.sc_ds;
1.196     mycroft  2258:                set_vflags(p, context.sc_eflags);
1.422     mycroft  2259:                p->p_md.md_syscall = syscall_vm86;
1.157     mycroft  2260:        } else
                   2261: #endif
                   2262:        {
1.196     mycroft  2263:                /*
                   2264:                 * Check for security violations.  If we're returning to
                   2265:                 * protected mode, the CPU will validate the segment registers
                   2266:                 * automatically and generate a trap on violations.  We handle
                   2267:                 * the trap, rather than doing all of the checking here.
                   2268:                 */
                   2269:                if (((context.sc_eflags ^ tf->tf_eflags) & PSL_USERSTATIC) != 0 ||
                   2270:                    !USERMODE(context.sc_cs, context.sc_eflags))
                   2271:                        return (EINVAL);
                   2272:
1.446     sommerfe 2273:                tf->tf_gs = context.sc_gs;
                   2274:                tf->tf_fs = context.sc_fs;
1.157     mycroft  2275:                tf->tf_es = context.sc_es;
                   2276:                tf->tf_ds = context.sc_ds;
1.184     mycroft  2277:                tf->tf_eflags = context.sc_eflags;
1.157     mycroft  2278:        }
1.184     mycroft  2279:        tf->tf_edi = context.sc_edi;
                   2280:        tf->tf_esi = context.sc_esi;
                   2281:        tf->tf_ebp = context.sc_ebp;
                   2282:        tf->tf_ebx = context.sc_ebx;
                   2283:        tf->tf_edx = context.sc_edx;
                   2284:        tf->tf_ecx = context.sc_ecx;
                   2285:        tf->tf_eax = context.sc_eax;
                   2286:        tf->tf_eip = context.sc_eip;
                   2287:        tf->tf_cs = context.sc_cs;
                   2288:        tf->tf_esp = context.sc_esp;
                   2289:        tf->tf_ss = context.sc_ss;
1.196     mycroft  2290:
1.319     mycroft  2291:        /* Restore signal stack. */
                   2292:        if (context.sc_onstack & SS_ONSTACK)
1.425     jdolecek 2293:                p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK;
1.196     mycroft  2294:        else
1.425     jdolecek 2295:                p->p_sigctx.ps_sigstk.ss_flags &= ~SS_ONSTACK;
1.319     mycroft  2296:
                   2297:        /* Restore signal mask. */
                   2298:        (void) sigprocmask1(p, SIG_SETMASK, &context.sc_mask, 0);
1.72      mycroft  2299:
1.122     mycroft  2300:        return (EJUSTRETURN);
1.37      cgd      2301: }
                   2302:
1.1       cgd      2303: int    waittime = -1;
                   2304: struct pcb dumppcb;
                   2305:
1.32      andrew   2306: void
1.228     gwr      2307: cpu_reboot(howto, bootstr)
1.193     mycroft  2308:        int howto;
1.206     mrg      2309:        char *bootstr;
1.1       cgd      2310: {
                   2311:
1.106     mycroft  2312:        if (cold) {
1.193     mycroft  2313:                howto |= RB_HALT;
                   2314:                goto haltsys;
1.1       cgd      2315:        }
1.193     mycroft  2316:
1.106     mycroft  2317:        boothowto = howto;
1.193     mycroft  2318:        if ((howto & RB_NOSYNC) == 0 && waittime < 0) {
1.1       cgd      2319:                waittime = 0;
1.150     mycroft  2320:                vfs_shutdown();
1.59      mycroft  2321:                /*
                   2322:                 * If we've been adjusting the clock, the todr
                   2323:                 * will be out of synch; adjust it now.
                   2324:                 */
                   2325:                resettodr();
1.1       cgd      2326:        }
1.193     mycroft  2327:
                   2328:        /* Disable interrupts. */
1.1       cgd      2329:        splhigh();
1.193     mycroft  2330:
                   2331:        /* Do a dump if requested. */
                   2332:        if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP)
                   2333:                dumpsys();
                   2334:
                   2335: haltsys:
                   2336:        doshutdownhooks();
                   2337:
1.484     fvdl     2338: #ifdef MULTIPROCESSOR
                   2339:        i386_broadcast_ipi(I386_IPI_HALT);
                   2340: #endif
                   2341:
1.307     thorpej  2342:        if ((howto & RB_POWERDOWN) == RB_POWERDOWN) {
1.473     tshiozak 2343: #if NACPI > 0
                   2344:                delay(500000);
                   2345:                acpi_enter_sleep_state(acpi_softc, ACPI_STATE_S5);
                   2346:                printf("WARNING: powerdown failed!\n");
                   2347: #endif
1.208     jtk      2348: #if NAPM > 0 && !defined(APM_NO_POWEROFF)
                   2349:                /* turn off, if we can.  But try to turn disk off and
                   2350:                 * wait a bit first--some disk drives are slow to clean up
                   2351:                 * and users have reported disk corruption.
                   2352:                 */
                   2353:                delay(500000);
                   2354:                apm_set_powstate(APM_DEV_DISK(0xff), APM_SYS_OFF);
                   2355:                delay(500000);
                   2356:                apm_set_powstate(APM_DEV_ALLDEVS, APM_SYS_OFF);
1.307     thorpej  2357:                printf("WARNING: powerdown failed!\n");
                   2358:                /*
                   2359:                 * RB_POWERDOWN implies RB_HALT... fall into it...
                   2360:                 */
1.208     jtk      2361: #endif
1.307     thorpej  2362:        }
                   2363:
                   2364:        if (howto & RB_HALT) {
1.210     christos 2365:                printf("\n");
                   2366:                printf("The operating system has halted.\n");
                   2367:                printf("Please press any key to reboot.\n\n");
1.300     drochner 2368:                cnpollc(1);     /* for proper keyboard command handling */
1.12      cgd      2369:                cngetc();
1.300     drochner 2370:                cnpollc(0);
1.1       cgd      2371:        }
1.193     mycroft  2372:
1.210     christos 2373:        printf("rebooting...\n");
1.328     bouyer   2374:        if (cpureset_delay > 0)
                   2375:                delay(cpureset_delay * 1000);
1.1       cgd      2376:        cpu_reset();
                   2377:        for(;;) ;
                   2378:        /*NOTREACHED*/
                   2379: }
                   2380:
1.116     gwr      2381: /*
                   2382:  * These variables are needed by /sbin/savecore
                   2383:  */
1.468     tsutsui  2384: u_int32_t dumpmag = 0x8fca0101;        /* magic number */
1.116     gwr      2385: int    dumpsize = 0;           /* pages */
                   2386: long   dumplo = 0;             /* blocks */
                   2387:
                   2388: /*
1.291     thorpej  2389:  * cpu_dumpsize: calculate size of machine-dependent kernel core dump headers.
                   2390:  */
                   2391: int
                   2392: cpu_dumpsize()
                   2393: {
                   2394:        int size;
                   2395:
                   2396:        size = ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t)) +
                   2397:            ALIGN(mem_cluster_cnt * sizeof(phys_ram_seg_t));
                   2398:        if (roundup(size, dbtob(1)) != dbtob(1))
                   2399:                return (-1);
                   2400:
                   2401:        return (1);
                   2402: }
                   2403:
                   2404: /*
                   2405:  * cpu_dump_mempagecnt: calculate the size of RAM (in pages) to be dumped.
                   2406:  */
                   2407: u_long
                   2408: cpu_dump_mempagecnt()
                   2409: {
                   2410:        u_long i, n;
                   2411:
                   2412:        n = 0;
                   2413:        for (i = 0; i < mem_cluster_cnt; i++)
                   2414:                n += atop(mem_clusters[i].size);
                   2415:        return (n);
                   2416: }
                   2417:
                   2418: /*
                   2419:  * cpu_dump: dump the machine-dependent kernel core dump headers.
                   2420:  */
                   2421: int
                   2422: cpu_dump()
                   2423: {
                   2424:        int (*dump) __P((dev_t, daddr_t, caddr_t, size_t));
                   2425:        char buf[dbtob(1)];
                   2426:        kcore_seg_t *segp;
                   2427:        cpu_kcore_hdr_t *cpuhdrp;
                   2428:        phys_ram_seg_t *memsegp;
1.481     gehenna  2429:        const struct bdevsw *bdev;
1.291     thorpej  2430:        int i;
                   2431:
1.481     gehenna  2432:        bdev = bdevsw_lookup(dumpdev);
                   2433:        if (bdev == NULL)
                   2434:                return (ENXIO);
                   2435:        dump = bdev->d_dump;
1.291     thorpej  2436:
1.313     perry    2437:        memset(buf, 0, sizeof buf);
1.291     thorpej  2438:        segp = (kcore_seg_t *)buf;
                   2439:        cpuhdrp = (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(*segp))];
                   2440:        memsegp = (phys_ram_seg_t *)&buf[ ALIGN(sizeof(*segp)) +
                   2441:            ALIGN(sizeof(*cpuhdrp))];
                   2442:
                   2443:        /*
                   2444:         * Generate a segment header.
                   2445:         */
                   2446:        CORE_SETMAGIC(*segp, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
                   2447:        segp->c_size = dbtob(1) - ALIGN(sizeof(*segp));
                   2448:
                   2449:        /*
                   2450:         * Add the machine-dependent header info.
                   2451:         */
                   2452:        cpuhdrp->ptdpaddr = PTDpaddr;
                   2453:        cpuhdrp->nmemsegs = mem_cluster_cnt;
                   2454:
                   2455:        /*
                   2456:         * Fill in the memory segment descriptors.
                   2457:         */
                   2458:        for (i = 0; i < mem_cluster_cnt; i++) {
                   2459:                memsegp[i].start = mem_clusters[i].start;
                   2460:                memsegp[i].size = mem_clusters[i].size;
                   2461:        }
                   2462:
                   2463:        return (dump(dumpdev, dumplo, (caddr_t)buf, dbtob(1)));
                   2464: }
                   2465:
                   2466: /*
1.228     gwr      2467:  * This is called by main to set dumplo and dumpsize.
1.414     thorpej  2468:  * Dumps always skip the first PAGE_SIZE of disk space
1.116     gwr      2469:  * in case there might be a disk label stored there.
                   2470:  * If there is extra space, put dump at the end to
                   2471:  * reduce the chance that swapping trashes it.
                   2472:  */
                   2473: void
1.228     gwr      2474: cpu_dumpconf()
1.116     gwr      2475: {
1.481     gehenna  2476:        const struct bdevsw *bdev;
1.291     thorpej  2477:        int nblks, dumpblks;    /* size of dump area */
1.116     gwr      2478:
                   2479:        if (dumpdev == NODEV)
1.291     thorpej  2480:                goto bad;
1.481     gehenna  2481:        bdev = bdevsw_lookup(dumpdev);
                   2482:        if (bdev == NULL)
1.116     gwr      2483:                panic("dumpconf: bad dumpdev=0x%x", dumpdev);
1.481     gehenna  2484:        if (bdev->d_psize == NULL)
1.291     thorpej  2485:                goto bad;
1.481     gehenna  2486:        nblks = (*bdev->d_psize)(dumpdev);
1.116     gwr      2487:        if (nblks <= ctod(1))
1.291     thorpej  2488:                goto bad;
1.116     gwr      2489:
1.291     thorpej  2490:        dumpblks = cpu_dumpsize();
                   2491:        if (dumpblks < 0)
                   2492:                goto bad;
                   2493:        dumpblks += ctod(cpu_dump_mempagecnt());
                   2494:
                   2495:        /* If dump won't fit (incl. room for possible label), punt. */
                   2496:        if (dumpblks > (nblks - ctod(1)))
                   2497:                goto bad;
                   2498:
                   2499:        /* Put dump at end of partition */
                   2500:        dumplo = nblks - dumpblks;
                   2501:
                   2502:        /* dumpsize is in page units, and doesn't include headers. */
                   2503:        dumpsize = cpu_dump_mempagecnt();
                   2504:        return;
1.116     gwr      2505:
1.291     thorpej  2506:  bad:
                   2507:        dumpsize = 0;
1.116     gwr      2508: }
                   2509:
1.1       cgd      2510: /*
                   2511:  * Doadump comes here after turning off memory management and
                   2512:  * getting on the dump stack, either when called above, or by
                   2513:  * the auto-restart code.
                   2514:  */
1.414     thorpej  2515: #define BYTES_PER_DUMP  PAGE_SIZE /* must be a multiple of pagesize XXX small */
1.314     thorpej  2516: static vaddr_t dumpspace;
1.163     cgd      2517:
1.314     thorpej  2518: vaddr_t
1.163     cgd      2519: reserve_dumppages(p)
1.314     thorpej  2520:        vaddr_t p;
1.163     cgd      2521: {
                   2522:
                   2523:        dumpspace = p;
                   2524:        return (p + BYTES_PER_DUMP);
                   2525: }
                   2526:
1.32      andrew   2527: void
1.1       cgd      2528: dumpsys()
                   2529: {
1.291     thorpej  2530:        u_long totalbytesleft, bytes, i, n, memseg;
                   2531:        u_long maddr;
                   2532:        int psize;
1.163     cgd      2533:        daddr_t blkno;
1.481     gehenna  2534:        const struct bdevsw *bdev;
1.163     cgd      2535:        int (*dump) __P((dev_t, daddr_t, caddr_t, size_t));
1.200     christos 2536:        int error;
1.193     mycroft  2537:
                   2538:        /* Save registers. */
                   2539:        savectx(&dumppcb);
1.1       cgd      2540:
                   2541:        if (dumpdev == NODEV)
                   2542:                return;
1.484     fvdl     2543:
1.481     gehenna  2544:        bdev = bdevsw_lookup(dumpdev);
                   2545:        if (bdev == NULL || bdev->d_psize == NULL)
                   2546:                return;
1.163     cgd      2547:
                   2548:        /*
                   2549:         * For dumps during autoconfiguration,
                   2550:         * if dump device has already configured...
                   2551:         */
                   2552:        if (dumpsize == 0)
1.228     gwr      2553:                cpu_dumpconf();
1.330     jtk      2554:        if (dumplo <= 0 || dumpsize == 0) {
1.275     mycroft  2555:                printf("\ndump to dev %u,%u not possible\n", major(dumpdev),
                   2556:                    minor(dumpdev));
1.163     cgd      2557:                return;
1.275     mycroft  2558:        }
                   2559:        printf("\ndumping to dev %u,%u offset %ld\n", major(dumpdev),
                   2560:            minor(dumpdev), dumplo);
1.134     mycroft  2561:
1.481     gehenna  2562:        psize = (*bdev->d_psize)(dumpdev);
1.210     christos 2563:        printf("dump ");
1.163     cgd      2564:        if (psize == -1) {
1.210     christos 2565:                printf("area unavailable\n");
1.163     cgd      2566:                return;
                   2567:        }
                   2568:
                   2569: #if 0  /* XXX this doesn't work.  grr. */
                   2570:         /* toss any characters present prior to dump */
                   2571:        while (sget() != NULL); /*syscons and pccons differ */
                   2572: #endif
                   2573:
1.291     thorpej  2574:        if ((error = cpu_dump()) != 0)
                   2575:                goto err;
                   2576:
                   2577:        totalbytesleft = ptoa(cpu_dump_mempagecnt());
                   2578:        blkno = dumplo + cpu_dumpsize();
1.481     gehenna  2579:        dump = bdev->d_dump;
1.200     christos 2580:        error = 0;
1.291     thorpej  2581:
                   2582:        for (memseg = 0; memseg < mem_cluster_cnt; memseg++) {
                   2583:                maddr = mem_clusters[memseg].start;
                   2584:                bytes = mem_clusters[memseg].size;
                   2585:
                   2586:                for (i = 0; i < bytes; i += n, totalbytesleft -= n) {
                   2587:                        /* Print out how many MBs we have left to go. */
                   2588:                        if ((totalbytesleft % (1024*1024)) == 0)
                   2589:                                printf("%ld ", totalbytesleft / (1024 * 1024));
                   2590:
                   2591:                        /* Limit size for next transfer. */
                   2592:                        n = bytes - i;
                   2593:                        if (n > BYTES_PER_DUMP)
                   2594:                                n = BYTES_PER_DUMP;
                   2595:
                   2596:                        (void) pmap_map(dumpspace, maddr, maddr + n,
                   2597:                            VM_PROT_READ);
                   2598:
                   2599:                        error = (*dump)(dumpdev, blkno, (caddr_t)dumpspace, n);
                   2600:                        if (error)
                   2601:                                goto err;
1.163     cgd      2602:                        maddr += n;
1.291     thorpej  2603:                        blkno += btodb(n);              /* XXX? */
1.163     cgd      2604:
                   2605: #if 0  /* XXX this doesn't work.  grr. */
1.291     thorpej  2606:                        /* operator aborting dump? */
                   2607:                        if (sget() != NULL) {
                   2608:                                error = EINTR;
                   2609:                                break;
                   2610:                        }
                   2611: #endif
1.163     cgd      2612:                }
                   2613:        }
                   2614:
1.291     thorpej  2615:  err:
1.163     cgd      2616:        switch (error) {
1.1       cgd      2617:
                   2618:        case ENXIO:
1.210     christos 2619:                printf("device bad\n");
1.1       cgd      2620:                break;
                   2621:
                   2622:        case EFAULT:
1.210     christos 2623:                printf("device not ready\n");
1.1       cgd      2624:                break;
                   2625:
                   2626:        case EINVAL:
1.210     christos 2627:                printf("area improper\n");
1.1       cgd      2628:                break;
                   2629:
                   2630:        case EIO:
1.210     christos 2631:                printf("i/o error\n");
1.1       cgd      2632:                break;
                   2633:
                   2634:        case EINTR:
1.210     christos 2635:                printf("aborted from console\n");
1.1       cgd      2636:                break;
                   2637:
1.163     cgd      2638:        case 0:
1.210     christos 2639:                printf("succeeded\n");
1.163     cgd      2640:                break;
                   2641:
1.1       cgd      2642:        default:
1.210     christos 2643:                printf("error %d\n", error);
1.1       cgd      2644:                break;
                   2645:        }
1.210     christos 2646:        printf("\n\n");
1.163     cgd      2647:        delay(5000000);         /* 5 seconds */
1.1       cgd      2648: }
                   2649:
                   2650: /*
                   2651:  * Clear registers on exec
                   2652:  */
1.33      cgd      2653: void
1.251     mycroft  2654: setregs(p, pack, stack)
1.1       cgd      2655:        struct proc *p;
1.151     christos 2656:        struct exec_package *pack;
1.21      cgd      2657:        u_long stack;
1.1       cgd      2658: {
1.298     mycroft  2659:        struct pcb *pcb = &p->p_addr->u_pcb;
                   2660:        struct trapframe *tf;
1.1       cgd      2661:
1.161     mycroft  2662: #if NNPX > 0
                   2663:        /* If we were using the FPU, forget about it. */
1.484     fvdl     2664:        if (p->p_addr->u_pcb.pcb_fpcpu != NULL)
                   2665:                npxsave_proc(p, 0);
1.161     mycroft  2666: #endif
1.166     mycroft  2667:
1.178     mycroft  2668: #ifdef USER_LDT
1.353     thorpej  2669:        pmap_ldt_cleanup(p);
1.178     mycroft  2670: #endif
                   2671:
1.167     mycroft  2672:        p->p_md.md_flags &= ~MDP_USEDFPU;
1.452     thorpej  2673:        if (i386_use_fxsave) {
1.450     thorpej  2674:                pcb->pcb_savefpu.sv_xmm.sv_env.en_cw = __NetBSD_NPXCW__;
1.452     thorpej  2675:                pcb->pcb_savefpu.sv_xmm.sv_env.en_mxcsr = __INITIAL_MXCSR__;
                   2676:        } else
1.450     thorpej  2677:                pcb->pcb_savefpu.sv_87.sv_env.en_cw = __NetBSD_NPXCW__;
1.59      mycroft  2678:
1.154     mycroft  2679:        tf = p->p_md.md_regs;
1.445     sommerfe 2680:        tf->tf_gs = LSEL(LUDATA_SEL, SEL_UPL);
                   2681:        tf->tf_fs = LSEL(LUDATA_SEL, SEL_UPL);
1.154     mycroft  2682:        tf->tf_es = LSEL(LUDATA_SEL, SEL_UPL);
                   2683:        tf->tf_ds = LSEL(LUDATA_SEL, SEL_UPL);
1.252     mycroft  2684:        tf->tf_edi = 0;
                   2685:        tf->tf_esi = 0;
1.154     mycroft  2686:        tf->tf_ebp = 0;
1.469     christos 2687:        tf->tf_ebx = (int)p->p_psstr;
1.252     mycroft  2688:        tf->tf_edx = 0;
                   2689:        tf->tf_ecx = 0;
                   2690:        tf->tf_eax = 0;
1.154     mycroft  2691:        tf->tf_eip = pack->ep_entry;
                   2692:        tf->tf_cs = LSEL(LUCODE_SEL, SEL_UPL);
                   2693:        tf->tf_eflags = PSL_USERSET;
                   2694:        tf->tf_esp = stack;
                   2695:        tf->tf_ss = LSEL(LUDATA_SEL, SEL_UPL);
1.1       cgd      2696: }
                   2697:
                   2698: /*
1.55      brezak   2699:  * Initialize segments and descriptor tables
1.1       cgd      2700:  */
                   2701:
1.275     mycroft  2702: union  descriptor *idt, *gdt, *ldt;
1.498     fvdl     2703: char idt_allocmap[NIDT];
                   2704: struct simplelock idt_lock = SIMPLELOCK_INITIALIZER;
1.275     mycroft  2705: #ifdef I586_CPU
                   2706: union  descriptor *pentium_idt;
                   2707: #endif
1.178     mycroft  2708: extern  struct user *proc0paddr;
1.49      brezak   2709:
1.178     mycroft  2710: void
1.489     fvdl     2711: setgate(gd, func, args, type, dpl, sel)
1.178     mycroft  2712:        struct gate_descriptor *gd;
                   2713:        void *func;
1.489     fvdl     2714:        int args, type, dpl, sel;
1.178     mycroft  2715: {
1.1       cgd      2716:
1.178     mycroft  2717:        gd->gd_looffset = (int)func;
1.489     fvdl     2718:        gd->gd_selector = sel;
1.178     mycroft  2719:        gd->gd_stkcpy = args;
                   2720:        gd->gd_xx = 0;
                   2721:        gd->gd_type = type;
                   2722:        gd->gd_dpl = dpl;
                   2723:        gd->gd_p = 1;
                   2724:        gd->gd_hioffset = (int)func >> 16;
                   2725: }
                   2726:
                   2727: void
1.484     fvdl     2728: unsetgate(gd)
                   2729:        struct gate_descriptor *gd;
                   2730: {
                   2731:        gd->gd_p = 0;
                   2732:        gd->gd_hioffset = 0;
                   2733:        gd->gd_looffset = 0;
                   2734:        gd->gd_selector = 0;
                   2735:        gd->gd_xx = 0;
                   2736:        gd->gd_stkcpy = 0;
                   2737:        gd->gd_type = 0;
                   2738:        gd->gd_dpl = 0;
                   2739: }
                   2740:
                   2741:
                   2742: void
1.178     mycroft  2743: setregion(rd, base, limit)
                   2744:        struct region_descriptor *rd;
                   2745:        void *base;
                   2746:        size_t limit;
                   2747: {
                   2748:
                   2749:        rd->rd_limit = (int)limit;
                   2750:        rd->rd_base = (int)base;
                   2751: }
1.1       cgd      2752:
1.174     mycroft  2753: void
                   2754: setsegment(sd, base, limit, type, dpl, def32, gran)
                   2755:        struct segment_descriptor *sd;
                   2756:        void *base;
                   2757:        size_t limit;
                   2758:        int type, dpl, def32, gran;
                   2759: {
1.1       cgd      2760:
1.174     mycroft  2761:        sd->sd_lolimit = (int)limit;
                   2762:        sd->sd_lobase = (int)base;
                   2763:        sd->sd_type = type;
                   2764:        sd->sd_dpl = dpl;
                   2765:        sd->sd_p = 1;
                   2766:        sd->sd_hilimit = (int)limit >> 16;
                   2767:        sd->sd_xx = 0;
                   2768:        sd->sd_def32 = def32;
                   2769:        sd->sd_gran = gran;
                   2770:        sd->sd_hibase = (int)base >> 24;
                   2771: }
1.1       cgd      2772:
                   2773: #define        IDTVEC(name)    __CONCAT(X, name)
1.299     mycroft  2774: typedef void (vector) __P((void));
                   2775: extern vector IDTVEC(syscall);
                   2776: extern vector IDTVEC(osyscall);
                   2777: extern vector *IDTVEC(exceptions)[];
1.333     christos 2778: #ifdef COMPAT_SVR4
                   2779: extern vector IDTVEC(svr4_fasttrap);
                   2780: #endif /* COMPAT_SVR4 */
1.447     christos 2781: #ifdef COMPAT_MACH
                   2782: extern vector IDTVEC(mach_trap);
                   2783: #endif
1.1       cgd      2784:
1.381     thorpej  2785: #define        KBTOB(x)        ((size_t)(x) * 1024UL)
                   2786:
1.484     fvdl     2787: void cpu_init_idt()
                   2788: {
                   2789:        struct region_descriptor region;
                   2790: #ifdef I586_CPU
                   2791:        setregion(&region, pentium_idt, NIDT * sizeof(idt[0]) - 1);
                   2792: #else
                   2793:        setregion(&region, idt, NIDT * sizeof(idt[0]) - 1);
                   2794: #endif
                   2795:         lidt(&region);
                   2796: }
                   2797:
1.433     kanaoka  2798: #if !defined(REALBASEMEM) && !defined(REALEXTMEM)
                   2799: void
                   2800: add_mem_cluster(seg_start, seg_end, type)
                   2801:        u_int64_t seg_start, seg_end;
                   2802:        u_int32_t type;
                   2803: {
                   2804:        extern struct extent *iomem_ex;
1.492     kanaoka  2805:        int i;
1.433     kanaoka  2806:
                   2807:        if (seg_end > 0x100000000ULL) {
                   2808:                printf("WARNING: skipping large "
                   2809:                    "memory map entry: "
                   2810:                    "0x%qx/0x%qx/0x%x\n",
                   2811:                    seg_start,
                   2812:                    (seg_end - seg_start),
                   2813:                    type);
                   2814:                return;
                   2815:        }
                   2816:
                   2817:        /*
                   2818:         * XXX Chop the last page off the size so that
                   2819:         * XXX it can fit in avail_end.
                   2820:         */
                   2821:        if (seg_end == 0x100000000ULL)
                   2822:                seg_end -= PAGE_SIZE;
                   2823:
                   2824:        if (seg_end <= seg_start)
                   2825:                return;
                   2826:
1.492     kanaoka  2827:        for (i = 0; i < mem_cluster_cnt; i++) {
                   2828:                if ((mem_clusters[i].start == round_page(seg_start))
                   2829:                    && (mem_clusters[i].size
                   2830:                            == trunc_page(seg_end) - mem_clusters[i].start)) {
                   2831: #ifdef DEBUG_MEMLOAD
                   2832:                        printf("WARNING: skipping duplicate segment entry\n");
                   2833: #endif
                   2834:                        return;
                   2835:                }
                   2836:        }
                   2837:
1.433     kanaoka  2838:        /*
                   2839:         * Allocate the physical addresses used by RAM
                   2840:         * from the iomem extent map.  This is done before
                   2841:         * the addresses are page rounded just to make
                   2842:         * sure we get them all.
                   2843:         */
                   2844:        if (extent_alloc_region(iomem_ex, seg_start,
                   2845:            seg_end - seg_start, EX_NOWAIT)) {
                   2846:                /* XXX What should we do? */
                   2847:                printf("WARNING: CAN'T ALLOCATE "
                   2848:                    "MEMORY SEGMENT "
                   2849:                    "(0x%qx/0x%qx/0x%x) FROM "
                   2850:                    "IOMEM EXTENT MAP!\n",
                   2851:                    seg_start, seg_end - seg_start, type);
1.492     kanaoka  2852:                return;
1.433     kanaoka  2853:        }
                   2854:
                   2855:        /*
                   2856:         * If it's not free memory, skip it.
                   2857:         */
                   2858:        if (type != BIM_Memory)
                   2859:                return;
                   2860:
                   2861:        /* XXX XXX XXX */
                   2862:        if (mem_cluster_cnt >= VM_PHYSSEG_MAX)
                   2863:                panic("init386: too many memory segments");
                   2864:
                   2865:        seg_start = round_page(seg_start);
                   2866:        seg_end = trunc_page(seg_end);
                   2867:
                   2868:        if (seg_start == seg_end)
                   2869:                return;
                   2870:
                   2871:        mem_clusters[mem_cluster_cnt].start = seg_start;
                   2872:        mem_clusters[mem_cluster_cnt].size =
                   2873:            seg_end - seg_start;
                   2874:
                   2875:        if (avail_end < seg_end)
                   2876:                avail_end = seg_end;
                   2877:        physmem += atop(mem_clusters[mem_cluster_cnt].size);
                   2878:        mem_cluster_cnt++;
                   2879: }
                   2880: #endif /* !defined(REALBASEMEM) && !defined(REALEXTMEM) */
                   2881:
1.59      mycroft  2882: void
1.484     fvdl     2883: initgdt(union descriptor *tgdt)
                   2884: {
                   2885:        struct region_descriptor region;
                   2886:        gdt = tgdt;
                   2887:        memset(gdt, 0, NGDT*sizeof(*gdt));
                   2888:        /* make gdt gates and memory segments */
                   2889:        setsegment(&gdt[GCODE_SEL].sd, 0, 0xfffff, SDT_MEMERA, SEL_KPL, 1, 1);
                   2890:        setsegment(&gdt[GDATA_SEL].sd, 0, 0xfffff, SDT_MEMRWA, SEL_KPL, 1, 1);
                   2891:        setsegment(&gdt[GUCODE_SEL].sd, 0, i386_btop(VM_MAXUSER_ADDRESS) - 1,
                   2892:            SDT_MEMERA, SEL_UPL, 1, 1);
                   2893:        setsegment(&gdt[GUDATA_SEL].sd, 0, i386_btop(VM_MAXUSER_ADDRESS) - 1,
                   2894:            SDT_MEMRWA, SEL_UPL, 1, 1);
                   2895: #ifdef COMPAT_MACH
                   2896:        setgate(&gdt[GMACHCALLS_SEL].gd, &IDTVEC(mach_trap), 1,
1.489     fvdl     2897:            SDT_SYS386CGT, SEL_UPL, GSEL(GCODE_SEL, SEL_KPL));
1.484     fvdl     2898: #endif
                   2899: #if NBIOSCALL > 0
                   2900:        /* bios trampoline GDT entries */
                   2901:        setsegment(&gdt[GBIOSCODE_SEL].sd, 0, 0xfffff, SDT_MEMERA, SEL_KPL, 0,
                   2902:            0);
                   2903:        setsegment(&gdt[GBIOSDATA_SEL].sd, 0, 0xfffff, SDT_MEMRWA, SEL_KPL, 0,
                   2904:            0);
                   2905: #endif
                   2906:        setsegment(&gdt[GCPU_SEL].sd, &cpu_info_primary,
                   2907:            sizeof(struct cpu_info)-1, SDT_MEMRWA, SEL_KPL, 1, 1);
                   2908:
                   2909:        setregion(&region, gdt, NGDT * sizeof(gdt[0]) - 1);
                   2910:        lgdt(&region);
                   2911: }
                   2912:
                   2913: void
1.43      brezak   2914: init386(first_avail)
1.476     fvdl     2915:        paddr_t first_avail;
1.2       cgd      2916: {
1.484     fvdl     2917:        union descriptor *tgdt;
1.148     mycroft  2918:        extern void consinit __P((void));
1.375     drochner 2919:        extern struct extent *iomem_ex;
1.429     chs      2920: #if !defined(REALBASEMEM) && !defined(REALEXTMEM)
1.401     thorpej  2921:        struct btinfo_memmap *bim;
1.429     chs      2922: #endif
1.381     thorpej  2923:        struct region_descriptor region;
1.401     thorpej  2924:        int x, first16q;
                   2925:        u_int64_t seg_start, seg_end;
                   2926:        u_int64_t seg_start1, seg_end1;
1.473     tshiozak 2927:        paddr_t realmode_reserved_start;
                   2928:        psize_t realmode_reserved_size;
                   2929:        int needs_earlier_install_pte0;
1.436     jdolecek 2930: #if NBIOSCALL > 0
                   2931:        extern int biostramp_image_size;
                   2932:        extern u_char biostramp_image[];
                   2933: #endif
1.1       cgd      2934:
1.484     fvdl     2935:        cpu_probe_features(&cpu_info_primary);
                   2936:        cpu_feature = cpu_info_primary.ci_feature_flags;
                   2937:
1.1       cgd      2938:        proc0.p_addr = proc0paddr;
1.484     fvdl     2939:        cpu_info_primary.ci_curpcb = &proc0.p_addr->u_pcb;
1.275     mycroft  2940:
1.375     drochner 2941:        i386_bus_space_init();
1.84      cgd      2942:        consinit();     /* XXX SHOULD NOT BE DONE HERE */
1.401     thorpej  2943:        /*
                   2944:         * Initailize PAGE_SIZE-dependent variables.
                   2945:         */
                   2946:        uvm_setpagesize();
                   2947:        /*
                   2948:         * A quick sanity check.
                   2949:         */
                   2950:        if (PAGE_SIZE != NBPG)
                   2951:                panic("init386: PAGE_SIZE != NBPG");
1.450     thorpej  2952:
                   2953:        /*
                   2954:         * Saving SSE registers won't work if the save area isn't
                   2955:         * 16-byte aligned.
                   2956:         */
                   2957:        if (offsetof(struct user, u_pcb.pcb_savefpu) & 0xf)
                   2958:                panic("init386: pcb_savefpu not 16-byte aligned");
1.440     thorpej  2959:
                   2960:        /*
                   2961:         * Start with 2 color bins -- this is just a guess to get us
                   2962:         * started.  We'll recolor when we determine the largest cache
                   2963:         * sizes on the system.
                   2964:         */
                   2965:        uvmexp.ncolors = 2;
1.401     thorpej  2966:
1.473     tshiozak 2967:        /*
1.484     fvdl     2968:         * BIOS leaves data in physical page 0
                   2969:         * Even if it didn't, our VM system doesn't like using zero as a
                   2970:         * physical page number.
                   2971:         * We may also need pages in low memory (one each) for secondary CPU
                   2972:         * startup, for BIOS calls, and for ACPI, plus a page table page to map
                   2973:         * them into the first few pages of the kernel's pmap.
1.473     tshiozak 2974:         */
                   2975:        avail_start = PAGE_SIZE;
                   2976:
                   2977:        /*
                   2978:         * reserve memory for real-mode call
                   2979:         */
                   2980:        needs_earlier_install_pte0 = 0;
                   2981:        realmode_reserved_start = 0;
                   2982:        realmode_reserved_size = 0;
1.414     thorpej  2983: #if NBIOSCALL > 0
1.473     tshiozak 2984:        /* save us a page for trampoline code */
                   2985:        realmode_reserved_size += PAGE_SIZE;
                   2986:        needs_earlier_install_pte0 = 1;
                   2987: #endif
1.484     fvdl     2988: #ifdef MULTIPROCESSOR                                           /* XXX */
                   2989:        KASSERT(avail_start == PAGE_SIZE);                       /* XXX */
                   2990:        if (realmode_reserved_size < MP_TRAMPOLINE)              /* XXX */
                   2991:                realmode_reserved_size = MP_TRAMPOLINE;          /* XXX */
                   2992:        needs_earlier_install_pte0 = 1;                          /* XXX */
                   2993: #endif                                                          /* XXX */
1.473     tshiozak 2994: #if NACPI > 0
                   2995:        /* trampoline code for wake handler */
                   2996:        realmode_reserved_size += ptoa(acpi_md_get_npages_of_wakecode()+1);
                   2997:        needs_earlier_install_pte0 = 1;
                   2998: #endif
                   2999:        if (needs_earlier_install_pte0) {
                   3000:                /* page table for directory entry 0 */
                   3001:                realmode_reserved_size += PAGE_SIZE;
                   3002:        }
                   3003:        if (realmode_reserved_size>0) {
                   3004:                realmode_reserved_start = avail_start;
                   3005:                avail_start += realmode_reserved_size;
                   3006:        }
1.414     thorpej  3007:
1.492     kanaoka  3008: #ifdef DEBUG_MEMLOAD
                   3009:        printf("mem_cluster_count: %d\n", mem_cluster_cnt);
                   3010: #endif
                   3011:
1.401     thorpej  3012:        /*
                   3013:         * Call pmap initialization to make new kernel address space.
                   3014:         * We must do this before loading pages into the VM system.
                   3015:         */
1.314     thorpej  3016:        pmap_bootstrap((vaddr_t)atdevbase + IOM_SIZE);
1.2       cgd      3017:
1.429     chs      3018: #if !defined(REALBASEMEM) && !defined(REALEXTMEM)
1.401     thorpej  3019:        /*
                   3020:         * Check to see if we have a memory map from the BIOS (passed
                   3021:         * to us by the boot program.
                   3022:         */
                   3023:        bim = lookup_bootinfo(BTINFO_MEMMAP);
1.407     enami    3024:        if (bim != NULL && bim->num > 0) {
1.463     enami    3025: #ifdef DEBUG_MEMLOAD
1.401     thorpej  3026:                printf("BIOS MEMORY MAP (%d ENTRIES):\n", bim->num);
                   3027: #endif
                   3028:                for (x = 0; x < bim->num; x++) {
1.463     enami    3029: #ifdef DEBUG_MEMLOAD
1.401     thorpej  3030:                        printf("    addr 0x%qx  size 0x%qx  type 0x%x\n",
                   3031:                            bim->entry[x].addr,
                   3032:                            bim->entry[x].size,
                   3033:                            bim->entry[x].type);
                   3034: #endif
                   3035:
                   3036:                        /*
                   3037:                         * If the segment is not memory, skip it.
                   3038:                         */
                   3039:                        switch (bim->entry[x].type) {
                   3040:                        case BIM_Memory:
                   3041:                        case BIM_ACPI:
                   3042:                        case BIM_NVS:
                   3043:                                break;
                   3044:                        default:
                   3045:                                continue;
                   3046:                        }
                   3047:
                   3048:                        /*
                   3049:                         * Sanity check the entry.
                   3050:                         * XXX Need to handle uint64_t in extent code
                   3051:                         * XXX and 64-bit physical addresses in i386
                   3052:                         * XXX port.
                   3053:                         */
                   3054:                        seg_start = bim->entry[x].addr;
                   3055:                        seg_end = bim->entry[x].addr + bim->entry[x].size;
                   3056:
1.432     kanaoka  3057:                        /*
1.433     kanaoka  3058:                         *   Avoid Compatibility Holes.
                   3059:                         * XXX  Holes within memory space that allow access
                   3060:                         * XXX to be directed to the PC-compatible frame buffer
1.484     fvdl     3061:                         * XXX (0xa0000-0xbffff),to adapter ROM space
1.433     kanaoka  3062:                         * XXX (0xc0000-0xdffff), and to system BIOS space
                   3063:                         * XXX (0xe0000-0xfffff).
                   3064:                         * XXX  Some laptop(for example,Toshiba Satellite2550X)
                   3065:                         * XXX report this area and occurred problems,
                   3066:                         * XXX so we avoid this area.
1.432     kanaoka  3067:                         */
1.433     kanaoka  3068:                        if (seg_start < 0x100000 && seg_end > 0xa0000) {
                   3069:                                printf("WARNING: memory map entry overlaps "
                   3070:                                    "with ``Compatibility Holes'': "
                   3071:                                    "0x%qx/0x%qx/0x%x\n", seg_start,
                   3072:                                    seg_end - seg_start, bim->entry[x].type);
                   3073:                                add_mem_cluster(seg_start, 0xa0000,
                   3074:                                    bim->entry[x].type);
                   3075:                                add_mem_cluster(0x100000, seg_end,
1.401     thorpej  3076:                                    bim->entry[x].type);
1.433     kanaoka  3077:                        } else
                   3078:                                add_mem_cluster(seg_start, seg_end,
1.401     thorpej  3079:                                    bim->entry[x].type);
                   3080:                }
1.421     aymeric  3081:        }
1.429     chs      3082: #endif /* ! REALBASEMEM && ! REALEXTMEM */
1.421     aymeric  3083:        /*
                   3084:         * If the loop above didn't find any valid segment, fall back to
                   3085:         * former code.
                   3086:         */
                   3087:        if (mem_cluster_cnt == 0) {
1.401     thorpej  3088:                /*
                   3089:                 * Allocate the physical addresses used by RAM from the iomem
                   3090:                 * extent map.  This is done before the addresses are
                   3091:                 * page rounded just to make sure we get them all.
                   3092:                 */
                   3093:                if (extent_alloc_region(iomem_ex, 0, KBTOB(biosbasemem),
                   3094:                    EX_NOWAIT)) {
                   3095:                        /* XXX What should we do? */
                   3096:                        printf("WARNING: CAN'T ALLOCATE BASE MEMORY FROM "
                   3097:                            "IOMEM EXTENT MAP!\n");
                   3098:                }
                   3099:                mem_clusters[0].start = 0;
                   3100:                mem_clusters[0].size = trunc_page(KBTOB(biosbasemem));
                   3101:                physmem += atop(mem_clusters[0].size);
                   3102:                if (extent_alloc_region(iomem_ex, IOM_END, KBTOB(biosextmem),
                   3103:                    EX_NOWAIT)) {
                   3104:                        /* XXX What should we do? */
                   3105:                        printf("WARNING: CAN'T ALLOCATE EXTENDED MEMORY FROM "
                   3106:                            "IOMEM EXTENT MAP!\n");
                   3107:                }
                   3108: #if NISADMA > 0
                   3109:                /*
                   3110:                 * Some motherboards/BIOSes remap the 384K of RAM that would
                   3111:                 * normally be covered by the ISA hole to the end of memory
                   3112:                 * so that it can be used.  However, on a 16M system, this
                   3113:                 * would cause bounce buffers to be allocated and used.
                   3114:                 * This is not desirable behaviour, as more than 384K of
                   3115:                 * bounce buffers might be allocated.  As a work-around,
                   3116:                 * we round memory down to the nearest 1M boundary if
                   3117:                 * we're using any isadma devices and the remapped memory
                   3118:                 * is what puts us over 16M.
                   3119:                 */
                   3120:                if (biosextmem > (15*1024) && biosextmem < (16*1024)) {
                   3121:                        char pbuf[9];
                   3122:
                   3123:                        format_bytes(pbuf, sizeof(pbuf),
                   3124:                            biosextmem - (15*1024));
                   3125:                        printf("Warning: ignoring %s of remapped memory\n",
                   3126:                            pbuf);
                   3127:                        biosextmem = (15*1024);
                   3128:                }
                   3129: #endif
                   3130:                mem_clusters[1].start = IOM_END;
                   3131:                mem_clusters[1].size = trunc_page(KBTOB(biosextmem));
                   3132:                physmem += atop(mem_clusters[1].size);
                   3133:
                   3134:                mem_cluster_cnt = 2;
                   3135:
                   3136:                avail_end = IOM_END + trunc_page(KBTOB(biosextmem));
                   3137:        }
                   3138:        /*
                   3139:         * If we have 16M of RAM or less, just put it all on
                   3140:         * the default free list.  Otherwise, put the first
                   3141:         * 16M of RAM on a lower priority free list (so that
                   3142:         * all of the ISA DMA'able memory won't be eaten up
                   3143:         * first-off).
                   3144:         */
                   3145:        if (avail_end <= (16 * 1024 * 1024))
                   3146:                first16q = VM_FREELIST_DEFAULT;
                   3147:        else
                   3148:                first16q = VM_FREELIST_FIRST16;
                   3149:
                   3150:        /* Make sure the end of the space used by the kernel is rounded. */
                   3151:        first_avail = round_page(first_avail);
                   3152:
                   3153:        /*
                   3154:         * Now, load the memory clusters (which have already been
                   3155:         * rounded and truncated) into the VM system.
                   3156:         *
                   3157:         * NOTE: WE ASSUME THAT MEMORY STARTS AT 0 AND THAT THE KERNEL
                   3158:         * IS LOADED AT IOM_END (1M).
                   3159:         */
                   3160:        for (x = 0; x < mem_cluster_cnt; x++) {
                   3161:                seg_start = mem_clusters[x].start;
                   3162:                seg_end = mem_clusters[x].start + mem_clusters[x].size;
                   3163:                seg_start1 = 0;
                   3164:                seg_end1 = 0;
                   3165:
                   3166:                /*
                   3167:                 * Skip memory before our available starting point.
                   3168:                 */
                   3169:                if (seg_end <= avail_start)
                   3170:                        continue;
                   3171:
                   3172:                if (avail_start >= seg_start && avail_start < seg_end) {
                   3173:                        if (seg_start != 0)
                   3174:                                panic("init386: memory doesn't start at 0");
                   3175:                        seg_start = avail_start;
                   3176:                        if (seg_start == seg_end)
                   3177:                                continue;
                   3178:                }
                   3179:
                   3180:                /*
                   3181:                 * If this segment contains the kernel, split it
                   3182:                 * in two, around the kernel.
                   3183:                 */
                   3184:                if (seg_start <= IOM_END && first_avail <= seg_end) {
                   3185:                        seg_start1 = first_avail;
                   3186:                        seg_end1 = seg_end;
                   3187:                        seg_end = IOM_END;
                   3188:                }
                   3189:
                   3190:                /* First hunk */
                   3191:                if (seg_start != seg_end) {
1.480     erh      3192:                        if (seg_start < (16 * 1024 * 1024) &&
1.401     thorpej  3193:                            first16q != VM_FREELIST_DEFAULT) {
                   3194:                                u_int64_t tmp;
                   3195:
                   3196:                                if (seg_end > (16 * 1024 * 1024))
                   3197:                                        tmp = (16 * 1024 * 1024);
                   3198:                                else
                   3199:                                        tmp = seg_end;
1.492     kanaoka  3200:
                   3201:                                if (tmp != seg_start) {
1.463     enami    3202: #ifdef DEBUG_MEMLOAD
1.492     kanaoka  3203:                                        printf("loading 0x%qx-0x%qx "
                   3204:                                            "(0x%lx-0x%lx)\n",
                   3205:                                            seg_start, tmp,
                   3206:                                            atop(seg_start), atop(tmp));
                   3207: #endif
                   3208:                                        uvm_page_physload(atop(seg_start),
                   3209:                                            atop(tmp), atop(seg_start),
                   3210:                                            atop(tmp), first16q);
                   3211:                                }
1.401     thorpej  3212:                                seg_start = tmp;
                   3213:                        }
1.411     enami    3214:
                   3215:                        if (seg_start != seg_end) {
1.463     enami    3216: #ifdef DEBUG_MEMLOAD
1.411     enami    3217:                                printf("loading 0x%qx-0x%qx (0x%lx-0x%lx)\n",
                   3218:                                    seg_start, seg_end,
                   3219:                                    atop(seg_start), atop(seg_end));
                   3220: #endif
                   3221:                                uvm_page_physload(atop(seg_start),
                   3222:                                    atop(seg_end), atop(seg_start),
                   3223:                                    atop(seg_end), VM_FREELIST_DEFAULT);
                   3224:                        }
1.401     thorpej  3225:                }
                   3226:
                   3227:                /* Second hunk */
                   3228:                if (seg_start1 != seg_end1) {
1.480     erh      3229:                        if (seg_start1 < (16 * 1024 * 1024) &&
1.401     thorpej  3230:                            first16q != VM_FREELIST_DEFAULT) {
                   3231:                                u_int64_t tmp;
                   3232:
                   3233:                                if (seg_end1 > (16 * 1024 * 1024))
                   3234:                                        tmp = (16 * 1024 * 1024);
                   3235:                                else
                   3236:                                        tmp = seg_end1;
1.492     kanaoka  3237:
                   3238:                                if (tmp != seg_start1) {
1.463     enami    3239: #ifdef DEBUG_MEMLOAD
1.492     kanaoka  3240:                                        printf("loading 0x%qx-0x%qx "
                   3241:                                            "(0x%lx-0x%lx)\n",
                   3242:                                            seg_start1, tmp,
                   3243:                                            atop(seg_start1), atop(tmp));
                   3244: #endif
                   3245:                                        uvm_page_physload(atop(seg_start1),
                   3246:                                            atop(tmp), atop(seg_start1),
                   3247:                                            atop(tmp), first16q);
                   3248:                                }
1.401     thorpej  3249:                                seg_start1 = tmp;
                   3250:                        }
1.412     enami    3251:
                   3252:                        if (seg_start1 != seg_end1) {
1.463     enami    3253: #ifdef DEBUG_MEMLOAD
1.412     enami    3254:                                printf("loading 0x%qx-0x%qx (0x%lx-0x%lx)\n",
                   3255:                                    seg_start1, seg_end1,
                   3256:                                    atop(seg_start1), atop(seg_end1));
                   3257: #endif
                   3258:                                uvm_page_physload(atop(seg_start1),
                   3259:                                    atop(seg_end1), atop(seg_start1),
                   3260:                                    atop(seg_end1), VM_FREELIST_DEFAULT);
                   3261:                        }
1.401     thorpej  3262:                }
                   3263:        }
                   3264:
                   3265:        /*
                   3266:         * Steal memory for the message buffer (at end of core).
                   3267:         */
                   3268:        {
                   3269:                struct vm_physseg *vps;
                   3270:                psize_t sz = round_page(MSGBUFSIZE);
                   3271:                psize_t reqsz = sz;
                   3272:
                   3273:                for (x = 0; x < vm_nphysseg; x++) {
                   3274:                        vps = &vm_physmem[x];
                   3275:                        if (ptoa(vps->avail_end) == avail_end)
                   3276:                                break;
                   3277:                }
                   3278:                if (x == vm_nphysseg)
1.410     christos 3279:                        panic("init386: can't find end of memory");
1.401     thorpej  3280:
                   3281:                /* Shrink so it'll fit in the last segment. */
                   3282:                if ((vps->avail_end - vps->avail_start) < atop(sz))
                   3283:                        sz = ptoa(vps->avail_end - vps->avail_start);
                   3284:
                   3285:                vps->avail_end -= atop(sz);
                   3286:                vps->end -= atop(sz);
                   3287:                msgbuf_paddr = ptoa(vps->avail_end);
                   3288:
                   3289:                /* Remove the last segment if it now has no pages. */
                   3290:                if (vps->start == vps->end) {
                   3291:                        for (vm_nphysseg--; x < vm_nphysseg; x++)
                   3292:                                vm_physmem[x] = vm_physmem[x + 1];
                   3293:                }
                   3294:
                   3295:                /* Now find where the new avail_end is. */
                   3296:                for (avail_end = 0, x = 0; x < vm_nphysseg; x++)
                   3297:                        if (vm_physmem[x].avail_end > avail_end)
                   3298:                                avail_end = vm_physmem[x].avail_end;
                   3299:                avail_end = ptoa(avail_end);
                   3300:
                   3301:                /* Warn if the message buffer had to be shrunk. */
                   3302:                if (sz != reqsz)
                   3303:                        printf("WARNING: %ld bytes not available for msgbuf "
                   3304:                            "in last cluster (%ld used)\n", reqsz, sz);
                   3305:        }
                   3306:
1.473     tshiozak 3307:        /*
                   3308:         * install PT page for the first 4M if needed.
                   3309:         */
                   3310:        if (needs_earlier_install_pte0) {
                   3311:                paddr_t paddr;
                   3312: #ifdef DIAGNOSTIC
                   3313:                if (realmode_reserved_size < PAGE_SIZE) {
                   3314:                        panic("cannot steal memory for first 4M PT page.");
                   3315:                }
                   3316: #endif
                   3317:                paddr=realmode_reserved_start+realmode_reserved_size-PAGE_SIZE;
                   3318:                pmap_enter(pmap_kernel(), (vaddr_t)vtopte(0), paddr,
                   3319:                           VM_PROT_READ|VM_PROT_WRITE,
                   3320:                           PMAP_WIRED|VM_PROT_READ|VM_PROT_WRITE);
                   3321:                pmap_update(pmap_kernel());
                   3322:                /* make sure it is clean before using */
                   3323:                memset(vtopte(0), 0, PAGE_SIZE);
                   3324:                realmode_reserved_size -= PAGE_SIZE;
                   3325:        }
                   3326:
1.295     drochner 3327: #if NBIOSCALL > 0
1.436     jdolecek 3328:        /*
                   3329:         * this should be caught at kernel build time, but put it here
                   3330:         * in case someone tries to fake it out...
                   3331:         */
                   3332: #ifdef DIAGNOSTIC
1.473     tshiozak 3333:        if (realmode_reserved_start > BIOSTRAMP_BASE ||
1.474     tron     3334:            (realmode_reserved_start+realmode_reserved_size) < (BIOSTRAMP_BASE+
1.473     tshiozak 3335:                                                               PAGE_SIZE)) {
                   3336:            panic("cannot steal memory for PT page of bioscall.");
                   3337:        }
1.436     jdolecek 3338:        if (biostramp_image_size > PAGE_SIZE)
1.483     provos   3339:            panic("biostramp_image_size too big: %x vs. %x",
1.436     jdolecek 3340:                  biostramp_image_size, PAGE_SIZE);
                   3341: #endif
                   3342:        pmap_kenter_pa((vaddr_t)BIOSTRAMP_BASE, /* virtual */
                   3343:                       (paddr_t)BIOSTRAMP_BASE, /* physical */
                   3344:                       VM_PROT_ALL);            /* protection */
1.456     chris    3345:        pmap_update(pmap_kernel());
1.436     jdolecek 3346:        memcpy((caddr_t)BIOSTRAMP_BASE, biostramp_image, biostramp_image_size);
                   3347: #ifdef DEBUG_BIOSCALL
                   3348:        printf("biostramp installed @ %x\n", BIOSTRAMP_BASE);
                   3349: #endif
1.473     tshiozak 3350:        realmode_reserved_size  -= PAGE_SIZE;
                   3351:        realmode_reserved_start += PAGE_SIZE;
                   3352: #endif
                   3353:
                   3354: #if NACPI > 0
                   3355:        /*
                   3356:         * Steal memory for the acpi wake code
                   3357:         */
                   3358:        {
                   3359:                paddr_t paddr, p;
                   3360:                psize_t sz;
                   3361:                int npg;
                   3362:
                   3363:                paddr = realmode_reserved_start;
                   3364:                npg = acpi_md_get_npages_of_wakecode();
                   3365:                sz = ptoa(npg);
                   3366: #ifdef DIAGNOSTIC
                   3367:                if (realmode_reserved_size < sz) {
                   3368:                        panic("cannot steal memory for ACPI wake code.");
                   3369:                }
                   3370: #endif
                   3371:
                   3372:                /* identical mapping */
                   3373:                p = paddr;
                   3374:                for (x=0; x<npg; x++) {
                   3375:                        printf("kenter: 0x%08X\n", (unsigned)p);
                   3376:                        pmap_kenter_pa((vaddr_t)p, p, VM_PROT_ALL);
                   3377:                        p += PAGE_SIZE;
                   3378:                }
                   3379:                pmap_update(pmap_kernel());
                   3380:
                   3381:                acpi_md_install_wakecode(paddr);
                   3382:
                   3383:                realmode_reserved_size  -= sz;
                   3384:                realmode_reserved_start += sz;
                   3385:        }
1.295     drochner 3386: #endif
1.59      mycroft  3387:
1.346     mycroft  3388:        pmap_enter(pmap_kernel(), idt_vaddr, idt_paddr,
1.367     thorpej  3389:            VM_PROT_READ|VM_PROT_WRITE, PMAP_WIRED|VM_PROT_READ|VM_PROT_WRITE);
1.456     chris    3390:        pmap_update(pmap_kernel());
1.484     fvdl     3391:        memset((void *)idt_vaddr, 0, PAGE_SIZE);
                   3392:
1.275     mycroft  3393:        idt = (union descriptor *)idt_vaddr;
                   3394: #ifdef I586_CPU
1.346     mycroft  3395:        pmap_enter(pmap_kernel(), pentium_idt_vaddr, idt_paddr,
1.367     thorpej  3396:            VM_PROT_READ, PMAP_WIRED|VM_PROT_READ);
1.275     mycroft  3397:        pentium_idt = (union descriptor *)pentium_idt_vaddr;
                   3398: #endif
1.484     fvdl     3399:        pmap_update(pmap_kernel());
                   3400:
                   3401:        tgdt = gdt;
1.275     mycroft  3402:        gdt = idt + NIDT;
                   3403:        ldt = gdt + NGDT;
                   3404:
1.484     fvdl     3405:        memcpy(gdt, tgdt, NGDT*sizeof(*gdt));
1.275     mycroft  3406:
                   3407:        setsegment(&gdt[GLDT_SEL].sd, ldt, NLDT * sizeof(ldt[0]) - 1,
                   3408:            SDT_SYSLDT, SEL_KPL, 0, 0);
                   3409:
                   3410:        /* make ldt gates and memory segments */
                   3411:        setgate(&ldt[LSYS5CALLS_SEL].gd, &IDTVEC(osyscall), 1,
1.489     fvdl     3412:            SDT_SYS386CGT, SEL_UPL, GSEL(GCODE_SEL, SEL_KPL));
1.447     christos 3413:
1.275     mycroft  3414:        ldt[LUCODE_SEL] = gdt[GUCODE_SEL];
                   3415:        ldt[LUDATA_SEL] = gdt[GUDATA_SEL];
1.324     christos 3416:        ldt[LSOL26CALLS_SEL] = ldt[LBSDICALLS_SEL] = ldt[LSYS5CALLS_SEL];
1.275     mycroft  3417:
                   3418:        /* exceptions */
1.498     fvdl     3419:        for (x = 0; x < 32; x++) {
1.275     mycroft  3420:                setgate(&idt[x].gd, IDTVEC(exceptions)[x], 0, SDT_SYS386TGT,
1.489     fvdl     3421:                    (x == 3 || x == 4) ? SEL_UPL : SEL_KPL,
                   3422:                    GSEL(GCODE_SEL, SEL_KPL));
1.498     fvdl     3423:                idt_allocmap[x] = 1;
                   3424:        }
1.257     thorpej  3425:
1.275     mycroft  3426:        /* new-style interrupt gate for syscalls */
1.489     fvdl     3427:        setgate(&idt[128].gd, &IDTVEC(syscall), 0, SDT_SYS386TGT, SEL_UPL,
                   3428:            GSEL(GCODE_SEL, SEL_KPL));
1.498     fvdl     3429:        idt_allocmap[128] = 1;
1.333     christos 3430: #ifdef COMPAT_SVR4
                   3431:        setgate(&idt[0xd2].gd, &IDTVEC(svr4_fasttrap), 0, SDT_SYS386TGT,
1.489     fvdl     3432:            SEL_UPL, GSEL(GCODE_SEL, SEL_KPL));
1.498     fvdl     3433:        idt_allocmap[0xd2] = 1;
1.333     christos 3434: #endif /* COMPAT_SVR4 */
1.264     mycroft  3435:
1.275     mycroft  3436:        setregion(&region, gdt, NGDT * sizeof(gdt[0]) - 1);
                   3437:        lgdt(&region);
1.484     fvdl     3438:
                   3439:        cpu_init_idt();
1.264     mycroft  3440:
1.190     mycroft  3441: #ifdef DDB
1.308     tv       3442:        {
                   3443:                extern int end;
                   3444:                extern int *esym;
1.336     christos 3445:                struct btinfo_symtab *symtab;
1.308     tv       3446:
1.484     fvdl     3447:                db_machine_init();
                   3448:
1.336     christos 3449:                symtab = lookup_bootinfo(BTINFO_SYMTAB);
1.484     fvdl     3450:
1.336     christos 3451:                if (symtab) {
                   3452:                        symtab->ssym += KERNBASE;
                   3453:                        symtab->esym += KERNBASE;
                   3454:                        ddb_init(symtab->nsym, (int *)symtab->ssym,
                   3455:                            (int *)symtab->esym);
                   3456:                }
                   3457:                else
                   3458:                        ddb_init(*(int *)&end, ((int *)&end) + 1, esym);
1.308     tv       3459:        }
1.190     mycroft  3460:        if (boothowto & RB_KDB)
                   3461:                Debugger();
1.377     ws       3462: #endif
                   3463: #ifdef IPKDB
                   3464:        ipkdb_init();
                   3465:        if (boothowto & RB_KDB)
                   3466:                ipkdb_connect(0);
1.190     mycroft  3467: #endif
                   3468: #ifdef KGDB
1.243     drochner 3469:        kgdb_port_init();
1.235     thorpej  3470:        if (boothowto & RB_KDB) {
                   3471:                kgdb_debug_init = 1;
1.242     drochner 3472:                kgdb_connect(1);
1.235     thorpej  3473:        }
1.384     jdolecek 3474: #endif
                   3475:
                   3476: #if NMCA > 0
                   3477:        /* check for MCA bus, needed to be done before ISA stuff - if
                   3478:         * MCA is detected, ISA needs to use level triggered interrupts
                   3479:         * by default */
                   3480:        mca_busprobe();
1.190     mycroft  3481: #endif
1.275     mycroft  3482:
1.498     fvdl     3483:        intr_default_setup();
1.431     thorpej  3484:
                   3485:        /* Initialize software interrupts. */
                   3486:        softintr_init();
1.275     mycroft  3487:
1.498     fvdl     3488:        splraise(IPL_IPI);
1.275     mycroft  3489:        enable_intr();
                   3490:
                   3491:        if (physmem < btoc(2 * 1024 * 1024)) {
                   3492:                printf("warning: too little memory available; "
1.383     mycroft  3493:                       "have %lu bytes, want %lu bytes\n"
1.275     mycroft  3494:                       "running in degraded mode\n"
                   3495:                       "press a key to confirm\n\n",
1.383     mycroft  3496:                       ptoa(physmem), 2*1024*1024UL);
1.275     mycroft  3497:                cngetc();
                   3498:        }
1.1       cgd      3499: }
                   3500:
1.107     deraadt  3501: #ifdef COMPAT_NOMID
                   3502: static int
                   3503: exec_nomid(p, epp)
1.59      mycroft  3504:        struct proc *p;
                   3505:        struct exec_package *epp;
1.31      cgd      3506: {
1.59      mycroft  3507:        int error;
                   3508:        u_long midmag, magic;
                   3509:        u_short mid;
1.80      cgd      3510:        struct exec *execp = epp->ep_hdr;
1.31      cgd      3511:
1.80      cgd      3512:        /* check on validity of epp->ep_hdr performed by exec_out_makecmds */
                   3513:
                   3514:        midmag = ntohl(execp->a_midmag);
1.59      mycroft  3515:        mid = (midmag >> 16) & 0xffff;
                   3516:        magic = midmag & 0xffff;
                   3517:
                   3518:        if (magic == 0) {
1.80      cgd      3519:                magic = (execp->a_midmag & 0xffff);
1.59      mycroft  3520:                mid = MID_ZERO;
                   3521:        }
                   3522:
                   3523:        midmag = mid << 16 | magic;
                   3524:
                   3525:        switch (midmag) {
                   3526:        case (MID_ZERO << 16) | ZMAGIC:
                   3527:                /*
                   3528:                 * 386BSD's ZMAGIC format:
                   3529:                 */
1.202     christos 3530:                error = exec_aout_prep_oldzmagic(p, epp);
1.59      mycroft  3531:                break;
                   3532:
                   3533:        case (MID_ZERO << 16) | QMAGIC:
                   3534:                /*
                   3535:                 * BSDI's QMAGIC format:
                   3536:                 * same as new ZMAGIC format, but with different magic number
                   3537:                 */
                   3538:                error = exec_aout_prep_zmagic(p, epp);
                   3539:                break;
                   3540:
1.202     christos 3541:        case (MID_ZERO << 16) | NMAGIC:
                   3542:                /*
                   3543:                 * BSDI's NMAGIC format:
                   3544:                 * same as NMAGIC format, but with different magic number
                   3545:                 * and with text starting at 0.
                   3546:                 */
                   3547:                error = exec_aout_prep_oldnmagic(p, epp);
                   3548:                break;
                   3549:
                   3550:        case (MID_ZERO << 16) | OMAGIC:
                   3551:                /*
                   3552:                 * BSDI's OMAGIC format:
                   3553:                 * same as OMAGIC format, but with different magic number
                   3554:                 * and with text starting at 0.
                   3555:                 */
                   3556:                error = exec_aout_prep_oldomagic(p, epp);
                   3557:                break;
                   3558:
1.59      mycroft  3559:        default:
                   3560:                error = ENOEXEC;
                   3561:        }
                   3562:
                   3563:        return error;
1.107     deraadt  3564: }
1.31      cgd      3565: #endif
1.107     deraadt  3566:
                   3567: /*
                   3568:  * cpu_exec_aout_makecmds():
                   3569:  *     cpu-dependent a.out format hook for execve().
                   3570:  *
                   3571:  * Determine of the given exec package refers to something which we
                   3572:  * understand and, if so, set up the vmcmds for it.
                   3573:  *
                   3574:  * On the i386, old (386bsd) ZMAGIC binaries and BSDI QMAGIC binaries
                   3575:  * if COMPAT_NOMID is given as a kernel option.
                   3576:  */
                   3577: int
                   3578: cpu_exec_aout_makecmds(p, epp)
                   3579:        struct proc *p;
                   3580:        struct exec_package *epp;
                   3581: {
                   3582:        int error = ENOEXEC;
                   3583:
                   3584: #ifdef COMPAT_NOMID
                   3585:        if ((error = exec_nomid(p, epp)) == 0)
                   3586:                return error;
                   3587: #endif /* ! COMPAT_NOMID */
                   3588:
                   3589:        return error;
1.31      cgd      3590: }
1.84      cgd      3591:
1.255     drochner 3592: void *
                   3593: lookup_bootinfo(type)
                   3594: int type;
                   3595: {
                   3596:        struct btinfo_common *help;
                   3597:        int n = *(int*)bootinfo;
                   3598:        help = (struct btinfo_common *)(bootinfo + sizeof(int));
                   3599:        while(n--) {
                   3600:                if(help->type == type)
                   3601:                        return(help);
                   3602:                help = (struct btinfo_common *)((char*)help + help->len);
                   3603:        }
                   3604:        return(0);
                   3605: }
1.149     mycroft  3606:
1.484     fvdl     3607: #include <dev/ic/mc146818reg.h>                /* for NVRAM POST */
                   3608: #include <i386/isa/nvram.h>            /* for NVRAM POST */
                   3609:
1.149     mycroft  3610: void
                   3611: cpu_reset()
                   3612: {
                   3613:
1.224     mycroft  3614:        disable_intr();
                   3615:
1.227     mycroft  3616:        /*
1.484     fvdl     3617:         * Ensure the NVRAM reset byte contains something vaguely sane.
                   3618:         */
                   3619:
                   3620:        outb(IO_RTC, NVRAM_RESET);
                   3621:        outb(IO_RTC+1, NVRAM_RESET_RST);
                   3622:
                   3623:        /*
1.227     mycroft  3624:         * The keyboard controller has 4 random output pins, one of which is
                   3625:         * connected to the RESET pin on the CPU in many PCs.  We tell the
                   3626:         * keyboard controller to pulse this line a couple of times.
                   3627:         */
1.273     drochner 3628:        outb(IO_KBD + KBCMDP, KBC_PULSE0);
1.226     mycroft  3629:        delay(100000);
1.273     drochner 3630:        outb(IO_KBD + KBCMDP, KBC_PULSE0);
1.226     mycroft  3631:        delay(100000);
1.149     mycroft  3632:
                   3633:        /*
1.224     mycroft  3634:         * Try to cause a triple fault and watchdog reset by making the IDT
                   3635:         * invalid and causing a fault.
1.149     mycroft  3636:         */
1.313     perry    3637:        memset((caddr_t)idt, 0, NIDT * sizeof(idt[0]));
1.484     fvdl     3638:        __asm __volatile("divl %0,%1" : : "q" (0), "a" (0));
1.149     mycroft  3639:
1.224     mycroft  3640: #if 0
1.149     mycroft  3641:        /*
                   3642:         * Try to cause a triple fault and watchdog reset by unmapping the
1.224     mycroft  3643:         * entire address space and doing a TLB flush.
1.149     mycroft  3644:         */
1.414     thorpej  3645:        memset((caddr_t)PTD, 0, PAGE_SIZE);
1.484     fvdl     3646:        tlbflush();
1.224     mycroft  3647: #endif
1.149     mycroft  3648:
                   3649:        for (;;);
1.45      cgd      3650: }
1.484     fvdl     3651:
1.499     jdolecek 3652: void
                   3653: cpu_initclocks()
1.484     fvdl     3654: {
                   3655:        (*initclock_func)();
                   3656: }
                   3657:
                   3658: #ifdef MULTIPROCESSOR
1.499     jdolecek 3659: void
                   3660: need_resched(struct cpu_info *ci)
1.484     fvdl     3661: {
                   3662:        ci->ci_want_resched = 1;
                   3663:        aston(ci);
                   3664: }
                   3665: #endif
                   3666:
                   3667: /*
                   3668:  * Allocate an IDT vector slot within the given range.
                   3669:  * XXX needs locking to avoid MP allocation races.
                   3670:  */
                   3671:
                   3672: int
1.498     fvdl     3673: idt_vec_alloc(low, high)
1.484     fvdl     3674:        int low;
                   3675:        int high;
                   3676: {
                   3677:        int vec;
                   3678:
1.498     fvdl     3679:        simple_lock(&idt_lock);
                   3680:        for (vec = low; vec <= high; vec++) {
                   3681:                if (idt_allocmap[vec] == 0) {
                   3682:                        idt_allocmap[vec] = 1;
                   3683:                        simple_unlock(&idt_lock);
1.484     fvdl     3684:                        return vec;
1.498     fvdl     3685:                }
                   3686:        }
                   3687:        simple_unlock(&idt_lock);
1.484     fvdl     3688:        return 0;
                   3689: }
                   3690:
1.498     fvdl     3691: void
                   3692: idt_vec_set(vec, function)
1.484     fvdl     3693:        int vec;
                   3694:        void (*function) __P((void));
                   3695: {
1.498     fvdl     3696:        /*
                   3697:         * Vector should be allocated, so no locking needed.
                   3698:         */
                   3699:        KASSERT(idt_allocmap[vec] == 1);
1.489     fvdl     3700:        setgate(&idt[vec].gd, function, 0, SDT_SYS386IGT, SEL_KPL,
                   3701:            GSEL(GCODE_SEL, SEL_KPL));
1.484     fvdl     3702: }
                   3703:
                   3704: void
1.498     fvdl     3705: idt_vec_free(vec)
1.484     fvdl     3706:        int vec;
                   3707: {
1.498     fvdl     3708:        simple_lock(&idt_lock);
1.484     fvdl     3709:        unsetgate(&idt[vec].gd);
1.498     fvdl     3710:        idt_allocmap[vec] = 0;
                   3711:        simple_unlock(&idt_lock);
1.484     fvdl     3712: }

CVSweb <webmaster@jp.NetBSD.org>