[BACK]Return to machdep.c CVS log [TXT][DIR] Up to [local] / sys / arch / i386 / i386

Annotation of sys/arch/i386/i386/machdep.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: machdep.c,v 1.403 2007/07/20 17:04:14 mk Exp $        */
        !             2: /*     $NetBSD: machdep.c,v 1.214 1996/11/10 03:16:17 thorpej Exp $    */
        !             3:
        !             4: /*-
        !             5:  * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * This code is derived from software contributed to The NetBSD Foundation
        !             9:  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
        !            10:  * NASA Ames Research Center.
        !            11:  *
        !            12:  * Redistribution and use in source and binary forms, with or without
        !            13:  * modification, are permitted provided that the following conditions
        !            14:  * are met:
        !            15:  * 1. Redistributions of source code must retain the above copyright
        !            16:  *    notice, this list of conditions and the following disclaimer.
        !            17:  * 2. Redistributions in binary form must reproduce the above copyright
        !            18:  *    notice, this list of conditions and the following disclaimer in the
        !            19:  *    documentation and/or other materials provided with the distribution.
        !            20:  * 3. All advertising materials mentioning features or use of this software
        !            21:  *    must display the following acknowledgement:
        !            22:  *     This product includes software developed by the NetBSD
        !            23:  *     Foundation, Inc. and its contributors.
        !            24:  * 4. Neither the name of The NetBSD Foundation nor the names of its
        !            25:  *    contributors may be used to endorse or promote products derived
        !            26:  *    from this software without specific prior written permission.
        !            27:  *
        !            28:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
        !            29:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
        !            30:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
        !            31:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
        !            32:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
        !            33:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        !            34:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        !            35:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        !            36:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        !            37:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            38:  * POSSIBILITY OF SUCH DAMAGE.
        !            39:  */
        !            40:
        !            41: /*-
        !            42:  * Copyright (c) 1993, 1994, 1995, 1996 Charles M. Hannum.  All rights reserved.
        !            43:  * Copyright (c) 1992 Terrence R. Lambert.
        !            44:  * Copyright (c) 1982, 1987, 1990 The Regents of the University of California.
        !            45:  * All rights reserved.
        !            46:  *
        !            47:  * This code is derived from software contributed to Berkeley by
        !            48:  * William Jolitz.
        !            49:  *
        !            50:  * Redistribution and use in source and binary forms, with or without
        !            51:  * modification, are permitted provided that the following conditions
        !            52:  * are met:
        !            53:  * 1. Redistributions of source code must retain the above copyright
        !            54:  *    notice, this list of conditions and the following disclaimer.
        !            55:  * 2. Redistributions in binary form must reproduce the above copyright
        !            56:  *    notice, this list of conditions and the following disclaimer in the
        !            57:  *    documentation and/or other materials provided with the distribution.
        !            58:  * 3. Neither the name of the University nor the names of its contributors
        !            59:  *    may be used to endorse or promote products derived from this software
        !            60:  *    without specific prior written permission.
        !            61:  *
        !            62:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            63:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            64:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            65:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            66:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            67:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            68:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            69:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            70:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            71:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            72:  * SUCH DAMAGE.
        !            73:  *
        !            74:  *     @(#)machdep.c   7.4 (Berkeley) 6/3/91
        !            75:  */
        !            76:
        !            77: #include <sys/param.h>
        !            78: #include <sys/systm.h>
        !            79: #include <sys/signalvar.h>
        !            80: #include <sys/kernel.h>
        !            81: #include <sys/proc.h>
        !            82: #include <sys/user.h>
        !            83: #include <sys/exec.h>
        !            84: #include <sys/buf.h>
        !            85: #include <sys/reboot.h>
        !            86: #include <sys/conf.h>
        !            87: #include <sys/file.h>
        !            88: #include <sys/timeout.h>
        !            89: #include <sys/malloc.h>
        !            90: #include <sys/mbuf.h>
        !            91: #include <sys/msgbuf.h>
        !            92: #include <sys/mount.h>
        !            93: #include <sys/vnode.h>
        !            94: #include <sys/device.h>
        !            95: #include <sys/extent.h>
        !            96: #include <sys/sysctl.h>
        !            97: #include <sys/syscallargs.h>
        !            98: #include <sys/core.h>
        !            99: #include <sys/kcore.h>
        !           100: #include <sys/sensors.h>
        !           101: #ifdef SYSVMSG
        !           102: #include <sys/msg.h>
        !           103: #endif
        !           104:
        !           105: #ifdef KGDB
        !           106: #include <sys/kgdb.h>
        !           107: #endif
        !           108:
        !           109: #include <dev/cons.h>
        !           110: #include <stand/boot/bootarg.h>
        !           111:
        !           112: #include <uvm/uvm_extern.h>
        !           113:
        !           114: #define _I386_BUS_DMA_PRIVATE
        !           115: #include <machine/bus.h>
        !           116:
        !           117: #include <machine/cpu.h>
        !           118: #include <machine/cpufunc.h>
        !           119: #include <machine/cpuvar.h>
        !           120: #include <machine/gdt.h>
        !           121: #include <machine/pio.h>
        !           122: #include <machine/bus.h>
        !           123: #include <machine/psl.h>
        !           124: #include <machine/reg.h>
        !           125: #include <machine/specialreg.h>
        !           126: #include <machine/biosvar.h>
        !           127:
        !           128: #include <dev/rndvar.h>
        !           129: #include <dev/isa/isareg.h>
        !           130: #include <dev/isa/isavar.h>
        !           131: #include <dev/ic/i8042reg.h>
        !           132: #include <dev/ic/mc146818reg.h>
        !           133: #include <i386/isa/isa_machdep.h>
        !           134: #include <i386/isa/nvram.h>
        !           135:
        !           136: #include "acpi.h"
        !           137: #if NACPI > 0
        !           138: #include <dev/acpi/acpivar.h>
        !           139: #endif
        !           140:
        !           141: #include "apm.h"
        !           142: #if NAPM > 0
        !           143: #include <machine/apmvar.h>
        !           144: #endif
        !           145:
        !           146: #ifdef DDB
        !           147: #include <machine/db_machdep.h>
        !           148: #include <ddb/db_access.h>
        !           149: #include <ddb/db_sym.h>
        !           150: #include <ddb/db_extern.h>
        !           151: #endif
        !           152:
        !           153: #ifdef VM86
        !           154: #include <machine/vm86.h>
        !           155: #endif
        !           156:
        !           157: #include "isa.h"
        !           158: #include "isadma.h"
        !           159: #include "npx.h"
        !           160: #if NNPX > 0
        !           161: extern struct proc *npxproc;
        !           162: #endif
        !           163:
        !           164: #include "bios.h"
        !           165: #include "com.h"
        !           166: #include "pccom.h"
        !           167:
        !           168: #if NPCCOM > 0
        !           169: #include <sys/termios.h>
        !           170: #include <dev/ic/comreg.h>
        !           171: #if NCOM > 0
        !           172: #include <dev/ic/comvar.h>
        !           173: #elif NPCCOM > 0
        !           174: #include <arch/i386/isa/pccomvar.h>
        !           175: #endif
        !           176: #endif /* NCOM > 0 || NPCCOM > 0 */
        !           177:
        !           178: /* the following is used externally (sysctl_hw) */
        !           179: char machine[] = MACHINE;
        !           180:
        !           181: /*
        !           182:  * Declare these as initialized data so we can patch them.
        !           183:  */
        !           184: #if NAPM > 0
        !           185: int    cpu_apmhalt = 0;        /* sysctl'd to 1 for halt -p hack */
        !           186: #endif
        !           187:
        !           188: #ifdef USER_LDT
        !           189: int    user_ldt_enable = 0;    /* sysctl'd to 1 to enable */
        !           190: #endif
        !           191:
        !           192: #ifndef BUFCACHEPERCENT
        !           193: #define BUFCACHEPERCENT 10
        !           194: #endif
        !           195:
        !           196: #ifdef BUFPAGES
        !           197: int    bufpages = BUFPAGES;
        !           198: #else
        !           199: int    bufpages = 0;
        !           200: #endif
        !           201: int    bufcachepercent = BUFCACHEPERCENT;
        !           202:
        !           203: extern int     boothowto;
        !           204: int    physmem;
        !           205:
        !           206: struct dumpmem {
        !           207:        paddr_t start;
        !           208:        paddr_t end;
        !           209: } dumpmem[VM_PHYSSEG_MAX];
        !           210: u_int ndumpmem;
        !           211:
        !           212: /*
        !           213:  * These variables are needed by /sbin/savecore
        !           214:  */
        !           215: u_long dumpmag = 0x8fca0101;   /* magic number */
        !           216: int    dumpsize = 0;           /* pages */
        !           217: long   dumplo = 0;             /* blocks */
        !           218:
        !           219: int    cpu_class;
        !           220: int    i386_fpu_present;
        !           221: int    i386_fpu_exception;
        !           222: int    i386_fpu_fdivbug;
        !           223:
        !           224: int    i386_use_fxsave;
        !           225: int    i386_has_sse;
        !           226: int    i386_has_sse2;
        !           227: int    i386_has_xcrypt;
        !           228:
        !           229: bootarg_t *bootargp;
        !           230: paddr_t avail_end;
        !           231:
        !           232: struct vm_map *exec_map = NULL;
        !           233: struct vm_map *phys_map = NULL;
        !           234:
        !           235: #if !defined(SMALL_KERNEL) && defined(I686_CPU)
        !           236: int p4_model;
        !           237: int p3_early;
        !           238: void (*update_cpuspeed)(void) = NULL;
        !           239: #endif
        !           240: int kbd_reset;
        !           241:
        !           242: #if !defined(SMALL_KERNEL)
        !           243: int bus_clock;
        !           244: #endif
        !           245: void (*setperf_setup)(struct cpu_info *);
        !           246: int setperf_prio = 0;          /* for concurrent handlers */
        !           247:
        !           248: void (*cpusensors_setup)(struct cpu_info *);
        !           249:
        !           250: void (*delay_func)(int) = i8254_delay;
        !           251: void (*initclock_func)(void) = i8254_initclocks;
        !           252:
        !           253: /*
        !           254:  * Extent maps to manage I/O and ISA memory hole space.  Allocate
        !           255:  * storage for 8 regions in each, initially.  Later, ioport_malloc_safe
        !           256:  * will indicate that it's safe to use malloc() to dynamically allocate
        !           257:  * region descriptors.
        !           258:  *
        !           259:  * N.B. At least two regions are _always_ allocated from the iomem
        !           260:  * extent map; (0 -> ISA hole) and (end of ISA hole -> end of RAM).
        !           261:  *
        !           262:  * The extent maps are not static!  Machine-dependent ISA and EISA
        !           263:  * routines need access to them for bus address space allocation.
        !           264:  */
        !           265: static long ioport_ex_storage[EXTENT_FIXED_STORAGE_SIZE(16) / sizeof(long)];
        !           266: static long iomem_ex_storage[EXTENT_FIXED_STORAGE_SIZE(16) / sizeof(long)];
        !           267: struct extent *ioport_ex;
        !           268: struct extent *iomem_ex;
        !           269: static int ioport_malloc_safe;
        !           270:
        !           271: caddr_t        allocsys(caddr_t);
        !           272: void   setup_buffers(void);
        !           273: void   dumpsys(void);
        !           274: int    cpu_dump(void);
        !           275: void   init386(paddr_t);
        !           276: void   consinit(void);
        !           277: void   (*cpuresetfn)(void);
        !           278:
        !           279: int    bus_mem_add_mapping(bus_addr_t, bus_size_t,
        !           280:            int, bus_space_handle_t *);
        !           281: int    _bus_dmamap_load_buffer(bus_dma_tag_t, bus_dmamap_t, void *,
        !           282:     bus_size_t, struct proc *, int, paddr_t *, int *, int);
        !           283:
        !           284: #ifdef KGDB
        !           285: #ifndef KGDB_DEVNAME
        !           286: #ifdef __i386__
        !           287: #define KGDB_DEVNAME "pccom"
        !           288: #else
        !           289: #define KGDB_DEVNAME "com"
        !           290: #endif
        !           291: #endif /* KGDB_DEVNAME */
        !           292: char kgdb_devname[] = KGDB_DEVNAME;
        !           293: #if (NCOM > 0 || NPCCOM > 0)
        !           294: #ifndef KGDBADDR
        !           295: #define KGDBADDR 0x3f8
        !           296: #endif
        !           297: int comkgdbaddr = KGDBADDR;
        !           298: #ifndef KGDBRATE
        !           299: #define KGDBRATE TTYDEF_SPEED
        !           300: #endif
        !           301: int comkgdbrate = KGDBRATE;
        !           302: #ifndef KGDBMODE
        !           303: #define KGDBMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */
        !           304: #endif
        !           305: int comkgdbmode = KGDBMODE;
        !           306: #endif /* NCOM  || NPCCOM */
        !           307: void kgdb_port_init(void);
        !           308: #endif /* KGDB */
        !           309:
        !           310: #ifdef APERTURE
        !           311: #ifdef INSECURE
        !           312: int allowaperture = 1;
        !           313: #else
        !           314: int allowaperture = 0;
        !           315: #endif
        !           316: #endif
        !           317:
        !           318: void   winchip_cpu_setup(struct cpu_info *);
        !           319: void   amd_family5_setperf_setup(struct cpu_info *);
        !           320: void   amd_family5_setup(struct cpu_info *);
        !           321: void   amd_family6_setperf_setup(struct cpu_info *);
        !           322: void   amd_family6_setup(struct cpu_info *);
        !           323: void   cyrix3_setperf_setup(struct cpu_info *);
        !           324: void   cyrix3_cpu_setup(struct cpu_info *);
        !           325: void   cyrix6x86_cpu_setup(struct cpu_info *);
        !           326: void   natsem6x86_cpu_setup(struct cpu_info *);
        !           327: void   intel586_cpu_setup(struct cpu_info *);
        !           328: void   intel686_cpusensors_setup(struct cpu_info *);
        !           329: void   intel686_setperf_setup(struct cpu_info *);
        !           330: void   intel686_common_cpu_setup(struct cpu_info *);
        !           331: void   intel686_cpu_setup(struct cpu_info *);
        !           332: void   intel686_p4_cpu_setup(struct cpu_info *);
        !           333: void   intelcore_update_sensor(void *);
        !           334: void   tm86_cpu_setup(struct cpu_info *);
        !           335: char * intel686_cpu_name(int);
        !           336: char * cyrix3_cpu_name(int, int);
        !           337: char * tm86_cpu_name(int);
        !           338: void   cyrix3_get_bus_clock(struct cpu_info *);
        !           339: void   p4_get_bus_clock(struct cpu_info *);
        !           340: void   p3_get_bus_clock(struct cpu_info *);
        !           341: void   p4_update_cpuspeed(void);
        !           342: void   p3_update_cpuspeed(void);
        !           343: int    pentium_cpuspeed(int *);
        !           344:
        !           345: static __inline u_char
        !           346: cyrix_read_reg(u_char reg)
        !           347: {
        !           348:        outb(0x22, reg);
        !           349:        return inb(0x23);
        !           350: }
        !           351:
        !           352: static __inline void
        !           353: cyrix_write_reg(u_char reg, u_char data)
        !           354: {
        !           355:        outb(0x22, reg);
        !           356:        outb(0x23, data);
        !           357: }
        !           358:
        !           359: /*
        !           360:  * cpuid instruction.  request in eax, result in eax, ebx, ecx, edx.
        !           361:  * requires caller to provide u_int32_t regs[4] array.
        !           362:  */
        !           363: void
        !           364: cpuid(u_int32_t ax, u_int32_t *regs)
        !           365: {
        !           366:        __asm __volatile(
        !           367:            "cpuid\n\t"
        !           368:            "movl       %%eax, 0(%2)\n\t"
        !           369:            "movl       %%ebx, 4(%2)\n\t"
        !           370:            "movl       %%ecx, 8(%2)\n\t"
        !           371:            "movl       %%edx, 12(%2)\n\t"
        !           372:            :"=a" (ax)
        !           373:            :"0" (ax), "S" (regs)
        !           374:            :"bx", "cx", "dx");
        !           375: }
        !           376:
        !           377: /*
        !           378:  * Machine-dependent startup code
        !           379:  */
        !           380: void
        !           381: cpu_startup()
        !           382: {
        !           383:        unsigned i;
        !           384:        caddr_t v;
        !           385:        int sz;
        !           386:        vaddr_t minaddr, maxaddr, va;
        !           387:        paddr_t pa;
        !           388:
        !           389:        /*
        !           390:         * Initialize error message buffer (at end of core).
        !           391:         * (space reserved in pmap_bootstrap)
        !           392:         */
        !           393:        pa = avail_end;
        !           394:        va = (vaddr_t)msgbufp;
        !           395:        for (i = 0; i < btoc(MSGBUFSIZE); i++) {
        !           396:                pmap_kenter_pa(va, pa, VM_PROT_READ|VM_PROT_WRITE);
        !           397:                va += PAGE_SIZE;
        !           398:                pa += PAGE_SIZE;
        !           399:        }
        !           400:        pmap_update(pmap_kernel());
        !           401:        initmsgbuf((caddr_t)msgbufp, round_page(MSGBUFSIZE));
        !           402:
        !           403:        printf("%s", version);
        !           404:        startrtclock();
        !           405:
        !           406:        /*
        !           407:         * We need to call identifycpu here early, so users have at least some
        !           408:         * basic information, if booting hangs later on.
        !           409:         */
        !           410:        strlcpy(curcpu()->ci_dev.dv_xname, "cpu0",
        !           411:            sizeof(curcpu()->ci_dev.dv_xname));
        !           412:        curcpu()->ci_signature = cpu_id;
        !           413:        curcpu()->ci_feature_flags = cpu_feature;
        !           414:        identifycpu(curcpu());
        !           415:
        !           416:        printf("real mem  = %llu (%lluMB)\n", ctob((unsigned long long)physmem),
        !           417:            ctob((unsigned long long)physmem)/1024U/1024U);
        !           418:
        !           419:        /*
        !           420:         * Find out how much space we need, allocate it,
        !           421:         * and then give everything true virtual addresses.
        !           422:         */
        !           423:        sz = (int)allocsys((caddr_t)0);
        !           424:        if ((v = (caddr_t)uvm_km_zalloc(kernel_map, round_page(sz))) == 0)
        !           425:                panic("startup: no room for tables");
        !           426:        if (allocsys(v) - v != sz)
        !           427:                panic("startup: table size inconsistency");
        !           428:
        !           429:        /*
        !           430:         * Now allocate buffers proper.  They are different than the above
        !           431:         * in that they usually occupy more virtual memory than physical.
        !           432:         */
        !           433:        setup_buffers();
        !           434:
        !           435:        /*
        !           436:         * Allocate a submap for exec arguments.  This map effectively
        !           437:         * limits the number of processes exec'ing at any time.
        !           438:         */
        !           439:        minaddr = vm_map_min(kernel_map);
        !           440:        exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
        !           441:                                   16*NCARGS, VM_MAP_PAGEABLE, FALSE, NULL);
        !           442:
        !           443:        /*
        !           444:         * Allocate a submap for physio
        !           445:         */
        !           446:        phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
        !           447:                                   VM_PHYS_SIZE, 0, FALSE, NULL);
        !           448:
        !           449:        printf("avail mem = %llu (%lluMB)\n",
        !           450:            ptoa((unsigned long long)uvmexp.free),
        !           451:            ptoa((unsigned long long)uvmexp.free)/1024U/1024U);
        !           452:
        !           453:        /*
        !           454:         * Set up buffers, so they can be used to read disk labels.
        !           455:         */
        !           456:        bufinit();
        !           457:
        !           458:        /*
        !           459:         * Configure the system.
        !           460:         */
        !           461:        if (boothowto & RB_CONFIG) {
        !           462: #ifdef BOOT_CONFIG
        !           463:                user_config();
        !           464: #else
        !           465:                printf("kernel does not support -c; continuing..\n");
        !           466: #endif
        !           467:        }
        !           468:        ioport_malloc_safe = 1;
        !           469: }
        !           470:
        !           471: /*
        !           472:  * Set up proc0's TSS and LDT.
        !           473:  */
        !           474: void
        !           475: i386_proc0_tss_ldt_init()
        !           476: {
        !           477:        int x;
        !           478:        struct pcb *pcb;
        !           479:
        !           480:        curpcb = pcb = &proc0.p_addr->u_pcb;
        !           481:
        !           482:        pcb->pcb_tss.tss_ioopt =
        !           483:            ((caddr_t)pcb->pcb_iomap - (caddr_t)&pcb->pcb_tss) << 16;
        !           484:        for (x = 0; x < sizeof(pcb->pcb_iomap) / 4; x++)
        !           485:                pcb->pcb_iomap[x] = 0xffffffff;
        !           486:        pcb->pcb_iomap_pad = 0xff;
        !           487:
        !           488:        pcb->pcb_ldt_sel = pmap_kernel()->pm_ldt_sel = GSEL(GLDT_SEL, SEL_KPL);
        !           489:        pcb->pcb_ldt = ldt;
        !           490:        pcb->pcb_cr0 = rcr0();
        !           491:        pcb->pcb_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL);
        !           492:        pcb->pcb_tss.tss_esp0 = (int)proc0.p_addr + USPACE - 16;
        !           493:        proc0.p_md.md_regs = (struct trapframe *)pcb->pcb_tss.tss_esp0 - 1;
        !           494:        proc0.p_md.md_tss_sel = tss_alloc(pcb);
        !           495:
        !           496:        ltr(proc0.p_md.md_tss_sel);
        !           497:        lldt(pcb->pcb_ldt_sel);
        !           498: }
        !           499:
        !           500: #ifdef MULTIPROCESSOR
        !           501: void
        !           502: i386_init_pcb_tss_ldt(struct cpu_info *ci)
        !           503: {
        !           504:        int x;
        !           505:        struct pcb *pcb = ci->ci_idle_pcb;
        !           506:
        !           507:        pcb->pcb_tss.tss_ioopt =
        !           508:            ((caddr_t)pcb->pcb_iomap - (caddr_t)&pcb->pcb_tss) << 16;
        !           509:        for (x = 0; x < sizeof(pcb->pcb_iomap) / 4; x++)
        !           510:                pcb->pcb_iomap[x] = 0xffffffff;
        !           511:        pcb->pcb_iomap_pad = 0xff;
        !           512:
        !           513:        pcb->pcb_ldt_sel = pmap_kernel()->pm_ldt_sel = GSEL(GLDT_SEL, SEL_KPL);
        !           514:        pcb->pcb_ldt = ci->ci_ldt;
        !           515:        pcb->pcb_cr0 = rcr0();
        !           516:        ci->ci_idle_tss_sel = tss_alloc(pcb);
        !           517: }
        !           518: #endif /* MULTIPROCESSOR */
        !           519:
        !           520:
        !           521: /*
        !           522:  * Allocate space for system data structures.  We are given
        !           523:  * a starting virtual address and we return a final virtual
        !           524:  * address; along the way we set each data structure pointer.
        !           525:  *
        !           526:  * We call allocsys() with 0 to find out how much space we want,
        !           527:  * allocate that much and fill it with zeroes, and then call
        !           528:  * allocsys() again with the correct base virtual address.
        !           529:  */
        !           530: caddr_t
        !           531: allocsys(caddr_t v)
        !           532: {
        !           533:
        !           534: #define        valloc(name, type, num) \
        !           535:            v = (caddr_t)(((name) = (type *)v) + (num))
        !           536:
        !           537: #ifdef SYSVMSG
        !           538:        valloc(msgpool, char, msginfo.msgmax);
        !           539:        valloc(msgmaps, struct msgmap, msginfo.msgseg);
        !           540:        valloc(msghdrs, struct msg, msginfo.msgtql);
        !           541:        valloc(msqids, struct msqid_ds, msginfo.msgmni);
        !           542: #endif
        !           543:
        !           544:        return v;
        !           545: }
        !           546:
        !           547: void
        !           548: setup_buffers()
        !           549: {
        !           550:        /*
        !           551:         * Determine how many buffers to allocate.  We use bufcachepercent%
        !           552:         * of the memory below 4GB.
        !           553:         */
        !           554:        if (bufpages == 0)
        !           555:                bufpages = btoc(avail_end) * bufcachepercent / 100;
        !           556:
        !           557:        /* Restrict to at most 25% filled kvm */
        !           558:        if (bufpages >
        !           559:            (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) / PAGE_SIZE / 4)
        !           560:                bufpages = (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) /
        !           561:                    PAGE_SIZE / 4;
        !           562: }
        !           563:
        !           564: /*
        !           565:  * Info for CTL_HW
        !           566:  */
        !           567: char   cpu_model[120];
        !           568:
        !           569: /*
        !           570:  * Note: these are just the ones that may not have a cpuid instruction.
        !           571:  * We deal with the rest in a different way.
        !           572:  */
        !           573: const struct cpu_nocpuid_nameclass i386_nocpuid_cpus[] = {
        !           574:        { CPUVENDOR_INTEL, "Intel", "386SX",    CPUCLASS_386,
        !           575:                NULL},                          /* CPU_386SX */
        !           576:        { CPUVENDOR_INTEL, "Intel", "386DX",    CPUCLASS_386,
        !           577:                NULL},                          /* CPU_386   */
        !           578:        { CPUVENDOR_INTEL, "Intel", "486SX",    CPUCLASS_486,
        !           579:                NULL},                          /* CPU_486SX */
        !           580:        { CPUVENDOR_INTEL, "Intel", "486DX",    CPUCLASS_486,
        !           581:                NULL},                          /* CPU_486   */
        !           582:        { CPUVENDOR_CYRIX, "Cyrix", "486DLC",   CPUCLASS_486,
        !           583:                NULL},                          /* CPU_486DLC */
        !           584:        { CPUVENDOR_CYRIX, "Cyrix", "6x86",     CPUCLASS_486,
        !           585:                cyrix6x86_cpu_setup},           /* CPU_6x86 */
        !           586:        { CPUVENDOR_NEXGEN,"NexGen","586",      CPUCLASS_386,
        !           587:                NULL},                          /* CPU_NX586 */
        !           588: };
        !           589:
        !           590: const char *classnames[] = {
        !           591:        "386",
        !           592:        "486",
        !           593:        "586",
        !           594:        "686"
        !           595: };
        !           596:
        !           597: const char *modifiers[] = {
        !           598:        "",
        !           599:        "OverDrive ",
        !           600:        "Dual ",
        !           601:        ""
        !           602: };
        !           603:
        !           604: const struct cpu_cpuid_nameclass i386_cpuid_cpus[] = {
        !           605:        {
        !           606:                "GenuineIntel",
        !           607:                CPUVENDOR_INTEL,
        !           608:                "Intel",
        !           609:                /* Family 4 */
        !           610:                { {
        !           611:                        CPUCLASS_486,
        !           612:                        {
        !           613:                                "486DX", "486DX", "486SX", "486DX2", "486SL",
        !           614:                                "486SX2", 0, "486DX2 W/B",
        !           615:                                "486DX4", 0, 0, 0, 0, 0, 0, 0,
        !           616:                                "486"           /* Default */
        !           617:                        },
        !           618:                        NULL
        !           619:                },
        !           620:                /* Family 5 */
        !           621:                {
        !           622:                        CPUCLASS_586,
        !           623:                        {
        !           624:                                "Pentium (A-step)", "Pentium (P5)",
        !           625:                                "Pentium (P54C)", "Pentium (P24T)",
        !           626:                                "Pentium/MMX", "Pentium", 0,
        !           627:                                "Pentium (P54C)", "Pentium/MMX",
        !           628:                                0, 0, 0, 0, 0, 0, 0,
        !           629:                                "Pentium"       /* Default */
        !           630:                        },
        !           631:                        intel586_cpu_setup
        !           632:                },
        !           633:                /* Family 6 */
        !           634:                {
        !           635:                        CPUCLASS_686,
        !           636:                        {
        !           637:                                "Pentium Pro", "Pentium Pro", 0,
        !           638:                                "Pentium II", "Pentium Pro",
        !           639:                                "Pentium II/Celeron",
        !           640:                                "Celeron",
        !           641:                                "Pentium III",
        !           642:                                "Pentium III",
        !           643:                                "Pentium M",
        !           644:                                "Pentium III Xeon",
        !           645:                                "Pentium III", 0,
        !           646:                                "Pentium M",
        !           647:                                "Core Duo/Solo", 0,
        !           648:                                "Pentium Pro, II or III"        /* Default */
        !           649:                        },
        !           650:                        intel686_cpu_setup
        !           651:                },
        !           652:                /* Family 7 */
        !           653:                {
        !           654:                        CPUCLASS_686,
        !           655:                } ,
        !           656:                /* Family 8 */
        !           657:                {
        !           658:                        CPUCLASS_686,
        !           659:                } ,
        !           660:                /* Family 9 */
        !           661:                {
        !           662:                        CPUCLASS_686,
        !           663:                } ,
        !           664:                /* Family A */
        !           665:                {
        !           666:                        CPUCLASS_686,
        !           667:                } ,
        !           668:                /* Family B */
        !           669:                {
        !           670:                        CPUCLASS_686,
        !           671:                } ,
        !           672:                /* Family C */
        !           673:                {
        !           674:                        CPUCLASS_686,
        !           675:                } ,
        !           676:                /* Family D */
        !           677:                {
        !           678:                        CPUCLASS_686,
        !           679:                } ,
        !           680:                /* Family E */
        !           681:                {
        !           682:                        CPUCLASS_686,
        !           683:                } ,
        !           684:                /* Family F */
        !           685:                {
        !           686:                        CPUCLASS_686,
        !           687:                        {
        !           688:                                "Pentium 4", 0, 0, 0,
        !           689:                                0, 0, 0, 0,
        !           690:                                0, 0, 0, 0,
        !           691:                                0, 0, 0, 0,
        !           692:                                "Pentium 4"     /* Default */
        !           693:                        },
        !           694:                        intel686_p4_cpu_setup
        !           695:                } }
        !           696:        },
        !           697:        {
        !           698:                "AuthenticAMD",
        !           699:                CPUVENDOR_AMD,
        !           700:                "AMD",
        !           701:                /* Family 4 */
        !           702:                { {
        !           703:                        CPUCLASS_486,
        !           704:                        {
        !           705:                                0, 0, 0, "Am486DX2 W/T",
        !           706:                                0, 0, 0, "Am486DX2 W/B",
        !           707:                                "Am486DX4 W/T or Am5x86 W/T 150",
        !           708:                                "Am486DX4 W/B or Am5x86 W/B 150", 0, 0,
        !           709:                                0, 0, "Am5x86 W/T 133/160",
        !           710:                                "Am5x86 W/B 133/160",
        !           711:                                "Am486 or Am5x86"       /* Default */
        !           712:                        },
        !           713:                        NULL
        !           714:                },
        !           715:                /* Family 5 */
        !           716:                {
        !           717:                        CPUCLASS_586,
        !           718:                        {
        !           719:                                "K5", "K5", "K5", "K5", 0, 0, "K6",
        !           720:                                "K6", "K6-2", "K6-III", 0, 0, 0,
        !           721:                                "K6-2+/III+", 0, 0,
        !           722:                                "K5 or K6"              /* Default */
        !           723:                        },
        !           724:                        amd_family5_setup
        !           725:                },
        !           726:                /* Family 6 */
        !           727:                {
        !           728:                        CPUCLASS_686,
        !           729:                        {
        !           730:                                0, "Athlon Model 1", "Athlon Model 2",
        !           731:                                "Duron Model 3",
        !           732:                                "Athlon Model 4",
        !           733:                                0, "Athlon XP Model 6",
        !           734:                                "Duron Model 7",
        !           735:                                "Athlon XP Model 8",
        !           736:                                0, "Athlon XP Model 10",
        !           737:                                0, 0, 0, 0, 0,
        !           738:                                "K7"            /* Default */
        !           739:                        },
        !           740:                        amd_family6_setup
        !           741:                },
        !           742:                /* Family 7 */
        !           743:                {
        !           744:                        CPUCLASS_686,
        !           745:                } ,
        !           746:                /* Family 8 */
        !           747:                {
        !           748:                        CPUCLASS_686,
        !           749:                } ,
        !           750:                /* Family 9 */
        !           751:                {
        !           752:                        CPUCLASS_686,
        !           753:                } ,
        !           754:                /* Family A */
        !           755:                {
        !           756:                        CPUCLASS_686,
        !           757:                } ,
        !           758:                /* Family B */
        !           759:                {
        !           760:                        CPUCLASS_686,
        !           761:                } ,
        !           762:                /* Family C */
        !           763:                {
        !           764:                        CPUCLASS_686,
        !           765:                } ,
        !           766:                /* Family D */
        !           767:                {
        !           768:                        CPUCLASS_686,
        !           769:                } ,
        !           770:                /* Family E */
        !           771:                {
        !           772:                        CPUCLASS_686,
        !           773:                } ,
        !           774:                /* Family F */
        !           775:                {
        !           776:                        CPUCLASS_686,
        !           777:                        {
        !           778:                                0, 0, 0, 0, "Athlon64",
        !           779:                                "Opteron or Athlon64FX", 0, 0,
        !           780:                                0, 0, 0, 0, 0, 0, 0, 0,
        !           781:                                "AMD64"                 /* DEFAULT */
        !           782:                        },
        !           783:                        amd_family6_setup
        !           784:                } }
        !           785:        },
        !           786:        {
        !           787:                "CyrixInstead",
        !           788:                CPUVENDOR_CYRIX,
        !           789:                "Cyrix",
        !           790:                /* Family 4 */
        !           791:                { {
        !           792:                        CPUCLASS_486,
        !           793:                        {
        !           794:                                0, 0, 0, "MediaGX", 0, 0, 0, 0, "5x86", 0, 0,
        !           795:                                0, 0, 0, 0,
        !           796:                                "486 class"     /* Default */
        !           797:                        },
        !           798:                        NULL
        !           799:                },
        !           800:                /* Family 5 */
        !           801:                {
        !           802:                        CPUCLASS_586,
        !           803:                        {
        !           804:                                0, 0, "6x86", 0, "GXm", 0, 0, 0, 0, 0,
        !           805:                                0, 0, 0, 0, 0, 0,
        !           806:                                "586 class"     /* Default */
        !           807:                        },
        !           808:                        cyrix6x86_cpu_setup
        !           809:                },
        !           810:                /* Family 6 */
        !           811:                {
        !           812:                        CPUCLASS_686,
        !           813:                        {
        !           814:                                "6x86MX", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        !           815:                                0, 0, 0, 0,
        !           816:                                "686 class"     /* Default */
        !           817:                        },
        !           818:                        NULL
        !           819:                } }
        !           820:        },
        !           821:        {
        !           822:                "CentaurHauls",
        !           823:                CPUVENDOR_IDT,
        !           824:                "IDT",
        !           825:                /* Family 4, not available from IDT */
        !           826:                { {
        !           827:                        CPUCLASS_486,
        !           828:                        {
        !           829:                                0, 0, 0, 0, 0, 0, 0, 0,
        !           830:                                0, 0, 0, 0, 0, 0, 0, 0,
        !           831:                                "486 class"             /* Default */
        !           832:                        },
        !           833:                        NULL
        !           834:                },
        !           835:                /* Family 5 */
        !           836:                {
        !           837:                        CPUCLASS_586,
        !           838:                        {
        !           839:                                0, 0, 0, 0, "WinChip C6", 0, 0, 0,
        !           840:                                "WinChip 2", "WinChip 3", 0, 0, 0, 0, 0, 0,
        !           841:                                "WinChip"               /* Default */
        !           842:                        },
        !           843:                        winchip_cpu_setup
        !           844:                },
        !           845:                /* Family 6 */
        !           846:                {
        !           847:                        CPUCLASS_686,
        !           848:                        {
        !           849:                                0, 0, 0, 0, 0, 0,
        !           850:                                "C3 Samuel",
        !           851:                                "C3 Samuel 2/Ezra",
        !           852:                                "C3 Ezra-T",
        !           853:                                "C3 Nehemiah", "C3 Esther", 0, 0, 0, 0, 0,
        !           854:                                "C3"            /* Default */
        !           855:                        },
        !           856:                        cyrix3_cpu_setup
        !           857:                } }
        !           858:        },
        !           859:        {
        !           860:                "RiseRiseRise",
        !           861:                CPUVENDOR_RISE,
        !           862:                "Rise",
        !           863:                /* Family 4, not available from Rise */
        !           864:                { {
        !           865:                        CPUCLASS_486,
        !           866:                        {
        !           867:                                0, 0, 0, 0, 0, 0, 0, 0,
        !           868:                                0, 0, 0, 0, 0, 0, 0, 0,
        !           869:                                "486 class"             /* Default */
        !           870:                        },
        !           871:                        NULL
        !           872:                },
        !           873:                /* Family 5 */
        !           874:                {
        !           875:                        CPUCLASS_586,
        !           876:                        {
        !           877:                                "mP6", 0, "mP6", 0, 0, 0, 0, 0,
        !           878:                                0, 0, 0, 0, 0, 0, 0, 0,
        !           879:                                "mP6"                   /* Default */
        !           880:                        },
        !           881:                        NULL
        !           882:                },
        !           883:                /* Family 6, not yet available from Rise */
        !           884:                {
        !           885:                        CPUCLASS_686,
        !           886:                        {
        !           887:                                0, 0, 0, 0, 0, 0, 0, 0,
        !           888:                                0, 0, 0, 0, 0, 0, 0, 0,
        !           889:                                "686 class"             /* Default */
        !           890:                        },
        !           891:                        NULL
        !           892:                } }
        !           893:        },
        !           894:        {
        !           895:                "GenuineTMx86",
        !           896:                CPUVENDOR_TRANSMETA,
        !           897:                "Transmeta",
        !           898:                /* Family 4, not available from Transmeta */
        !           899:                { {
        !           900:                        CPUCLASS_486,
        !           901:                        {
        !           902:                                0, 0, 0, 0, 0, 0, 0, 0,
        !           903:                                0, 0, 0, 0, 0, 0, 0, 0,
        !           904:                                "486 class"             /* Default */
        !           905:                        },
        !           906:                        NULL
        !           907:                },
        !           908:                /* Family 5 */
        !           909:                {
        !           910:                        CPUCLASS_586,
        !           911:                        {
        !           912:                                0, 0, 0, 0, "TMS5x00", 0, 0,
        !           913:                                0, 0, 0, 0, 0, 0, 0, 0, 0,
        !           914:                                "TMS5x00"               /* Default */
        !           915:                        },
        !           916:                        tm86_cpu_setup
        !           917:                },
        !           918:                /* Family 6, not yet available from Transmeta */
        !           919:                {
        !           920:                        CPUCLASS_686,
        !           921:                        {
        !           922:                                0, 0, 0, 0, 0, 0, 0, 0,
        !           923:                                0, 0, 0, 0, 0, 0, 0, 0,
        !           924:                                "686 class"             /* Default */
        !           925:                        },
        !           926:                        NULL
        !           927:                } }
        !           928:        },
        !           929:        {
        !           930:                "Geode by NSC",
        !           931:                CPUVENDOR_NS,
        !           932:                "National Semiconductor",
        !           933:                /* Family 4, not available from National Semiconductor */
        !           934:                { {
        !           935:                        CPUCLASS_486,
        !           936:                        {
        !           937:                                0, 0, 0, 0, 0, 0, 0, 0,
        !           938:                                0, 0, 0, 0, 0, 0, 0, 0,
        !           939:                                "486 class"     /* Default */
        !           940:                        },
        !           941:                        NULL
        !           942:                },
        !           943:                /* Family 5 */
        !           944:                {
        !           945:                        CPUCLASS_586,
        !           946:                        {
        !           947:                                0, 0, 0, 0, "Geode GX1", 0, 0, 0, 0, 0,
        !           948:                                0, 0, 0, 0, 0, 0,
        !           949:                                "586 class"     /* Default */
        !           950:                        },
        !           951:                        natsem6x86_cpu_setup
        !           952:                } }
        !           953:        },
        !           954:        {
        !           955:                "SiS SiS SiS ",
        !           956:                CPUVENDOR_SIS,
        !           957:                "SiS",
        !           958:                /* Family 4, not available from SiS */
        !           959:                { {
        !           960:                        CPUCLASS_486,
        !           961:                        {
        !           962:                                0, 0, 0, 0, 0, 0, 0, 0,
        !           963:                                0, 0, 0, 0, 0, 0, 0, 0,
        !           964:                                "486 class"     /* Default */
        !           965:                        },
        !           966:                        NULL
        !           967:                },
        !           968:                /* Family 5 */
        !           969:                {
        !           970:                        CPUCLASS_586,
        !           971:                        {
        !           972:                                "SiS55x", 0, 0, 0, 0, 0, 0, 0, 0, 0,
        !           973:                                0, 0, 0, 0, 0, 0,
        !           974:                                "586 class"     /* Default */
        !           975:                        },
        !           976:                        NULL
        !           977:                } }
        !           978:        }
        !           979: };
        !           980:
        !           981: const struct cpu_cpuid_feature i386_cpuid_features[] = {
        !           982:        { CPUID_FPU,    "FPU" },
        !           983:        { CPUID_VME,    "V86" },
        !           984:        { CPUID_DE,     "DE" },
        !           985:        { CPUID_PSE,    "PSE" },
        !           986:        { CPUID_TSC,    "TSC" },
        !           987:        { CPUID_MSR,    "MSR" },
        !           988:        { CPUID_PAE,    "PAE" },
        !           989:        { CPUID_MCE,    "MCE" },
        !           990:        { CPUID_CX8,    "CX8" },
        !           991:        { CPUID_APIC,   "APIC" },
        !           992:        { CPUID_SYS1,   "SYS" },
        !           993:        { CPUID_SEP,    "SEP" },
        !           994:        { CPUID_MTRR,   "MTRR" },
        !           995:        { CPUID_PGE,    "PGE" },
        !           996:        { CPUID_MCA,    "MCA" },
        !           997:        { CPUID_CMOV,   "CMOV" },
        !           998:        { CPUID_PAT,    "PAT" },
        !           999:        { CPUID_PSE36,  "PSE36" },
        !          1000:        { CPUID_SER,    "SER" },
        !          1001:        { CPUID_CFLUSH, "CFLUSH" },
        !          1002:        { CPUID_DS,     "DS" },
        !          1003:        { CPUID_ACPI,   "ACPI" },
        !          1004:        { CPUID_MMX,    "MMX" },
        !          1005:        { CPUID_FXSR,   "FXSR" },
        !          1006:        { CPUID_SSE,    "SSE" },
        !          1007:        { CPUID_SSE2,   "SSE2" },
        !          1008:        { CPUID_SS,     "SS" },
        !          1009:        { CPUID_HTT,    "HTT" },
        !          1010:        { CPUID_TM,     "TM" },
        !          1011:        { CPUID_SBF,    "SBF" },
        !          1012:        { CPUID_3DNOW,  "3DNOW" },
        !          1013: };
        !          1014:
        !          1015: const struct cpu_cpuid_feature i386_cpuid_ecxfeatures[] = {
        !          1016:        { CPUIDECX_SSE3,        "SSE3" },
        !          1017:        { CPUIDECX_MWAIT,       "MWAIT" },
        !          1018:        { CPUIDECX_DSCPL,       "DS-CPL" },
        !          1019:        { CPUIDECX_VMX,         "VMX" },
        !          1020:        { CPUIDECX_EST,         "EST" },
        !          1021:        { CPUIDECX_TM2,         "TM2" },
        !          1022:        { CPUIDECX_CNXTID,      "CNXT-ID" },
        !          1023:        { CPUIDECX_CX16,        "CX16" },
        !          1024:        { CPUIDECX_XTPR,        "xTPR" },
        !          1025: };
        !          1026:
        !          1027: void
        !          1028: winchip_cpu_setup(struct cpu_info *ci)
        !          1029: {
        !          1030: #if defined(I586_CPU)
        !          1031:
        !          1032:        switch ((ci->ci_signature >> 4) & 15) { /* model */
        !          1033:        case 4: /* WinChip C6 */
        !          1034:                ci->ci_feature_flags &= ~CPUID_TSC;
        !          1035:                /* Disable RDTSC instruction from user-level. */
        !          1036:                lcr4(rcr4() | CR4_TSD);
        !          1037:                printf("%s: TSC disabled\n", ci->ci_dev.dv_xname);
        !          1038:                break;
        !          1039:        }
        !          1040: #endif
        !          1041: }
        !          1042:
        !          1043: #if defined(I686_CPU) && !defined(SMALL_KERNEL)
        !          1044: void
        !          1045: cyrix3_setperf_setup(struct cpu_info *ci)
        !          1046: {
        !          1047:        if (cpu_ecxfeature & CPUIDECX_EST) {
        !          1048:                if (rdmsr(MSR_MISC_ENABLE) & (1 << 16))
        !          1049:                        est_init(ci->ci_dev.dv_xname, CPUVENDOR_VIA);
        !          1050:                else
        !          1051:                        printf("%s: Enhanced SpeedStep disabled by BIOS\n",
        !          1052:                            ci->ci_dev.dv_xname);
        !          1053:        }
        !          1054: }
        !          1055: #endif
        !          1056:
        !          1057: void
        !          1058: cyrix3_cpu_setup(struct cpu_info *ci)
        !          1059: {
        !          1060: #if defined(I686_CPU)
        !          1061:        int model = (ci->ci_signature >> 4) & 15;
        !          1062:        int step = ci->ci_signature & 15;
        !          1063:
        !          1064:        u_int64_t msreg;
        !          1065:        u_int32_t regs[4];
        !          1066:        unsigned int val;
        !          1067: #if !defined(SMALL_KERNEL)
        !          1068:        extern void (*pagezero)(void *, size_t);
        !          1069:        extern void i686_pagezero(void *, size_t);
        !          1070:
        !          1071:        pagezero = i686_pagezero;
        !          1072:
        !          1073:        cyrix3_get_bus_clock(ci);
        !          1074:
        !          1075:        setperf_setup = cyrix3_setperf_setup;
        !          1076: #endif
        !          1077:
        !          1078:        switch (model) {
        !          1079:        case 6: /* C3 Samuel 1 */
        !          1080:        case 7: /* C3 Samuel 2 or C3 Ezra */
        !          1081:        case 8: /* C3 Ezra-T */
        !          1082:                cpuid(0x80000001, regs);
        !          1083:                val = regs[3];
        !          1084:                if (val & (1U << 31)) {
        !          1085:                        cpu_feature |= CPUID_3DNOW;
        !          1086:                } else {
        !          1087:                        cpu_feature &= ~CPUID_3DNOW;
        !          1088:                }
        !          1089:                break;
        !          1090:
        !          1091:        case 9:
        !          1092:                if (step < 3)
        !          1093:                        break;
        !          1094:                /*
        !          1095:                 * C3 Nehemiah: fall through.
        !          1096:                 */
        !          1097:        case 10:
        !          1098:                /*
        !          1099:                 * C3 Nehemiah/Esther:
        !          1100:                 * First we check for extended feature flags, and then
        !          1101:                 * (if present) retrieve the ones at 0xC0000001.  In this
        !          1102:                 * bit 2 tells us if the RNG is present.  Bit 3 tells us
        !          1103:                 * if the RNG has been enabled.  In order to use the RNG
        !          1104:                 * we need 3 things:  We need an RNG, we need the FXSR bit
        !          1105:                 * enabled in cr4 (SSE/SSE2 stuff), and we need to have
        !          1106:                 * Bit 6 of MSR 0x110B set to 1 (the default), which will
        !          1107:                 * show up as bit 3 set here.
        !          1108:                 */
        !          1109:                cpuid(0xC0000000, regs); /* Check for RNG */
        !          1110:                val = regs[0];
        !          1111:                if (val >= 0xC0000001) {
        !          1112:                        cpuid(0xC0000001, regs);
        !          1113:                        val = regs[3];
        !          1114:                } else
        !          1115:                        val = 0;
        !          1116:
        !          1117:                if (val & (C3_CPUID_HAS_RNG | C3_CPUID_HAS_ACE))
        !          1118:                        printf("%s:", ci->ci_dev.dv_xname);
        !          1119:
        !          1120:                /* Enable RNG if present and disabled */
        !          1121:                if (val & C3_CPUID_HAS_RNG) {
        !          1122:                        extern int viac3_rnd_present;
        !          1123:
        !          1124:                        if (!(val & C3_CPUID_DO_RNG)) {
        !          1125:                                msreg = rdmsr(0x110B);
        !          1126:                                msreg |= 0x40;
        !          1127:                                wrmsr(0x110B, msreg);
        !          1128:                        }
        !          1129:                        viac3_rnd_present = 1;
        !          1130:                        printf(" RNG");
        !          1131:                }
        !          1132:
        !          1133:                /* Enable AES engine if present and disabled */
        !          1134:                if (val & C3_CPUID_HAS_ACE) {
        !          1135: #ifdef CRYPTO
        !          1136:                        if (!(val & C3_CPUID_DO_ACE)) {
        !          1137:                                msreg = rdmsr(0x1107);
        !          1138:                                msreg |= (0x01 << 28);
        !          1139:                                wrmsr(0x1107, msreg);
        !          1140:                        }
        !          1141:                        i386_has_xcrypt |= C3_HAS_AES;
        !          1142: #endif /* CRYPTO */
        !          1143:                        printf(" AES");
        !          1144:                }
        !          1145:
        !          1146:                /* Enable ACE2 engine if present and disabled */
        !          1147:                if (val & C3_CPUID_HAS_ACE2) {
        !          1148: #ifdef CRYPTO
        !          1149:                        if (!(val & C3_CPUID_DO_ACE2)) {
        !          1150:                                msreg = rdmsr(0x1107);
        !          1151:                                msreg |= (0x01 << 28);
        !          1152:                                wrmsr(0x1107, msreg);
        !          1153:                        }
        !          1154:                        i386_has_xcrypt |= C3_HAS_AESCTR;
        !          1155: #endif /* CRYPTO */
        !          1156:                        printf(" AES-CTR");
        !          1157:                }
        !          1158:
        !          1159:                /* Enable SHA engine if present and disabled */
        !          1160:                if (val & C3_CPUID_HAS_PHE) {
        !          1161: #ifdef CRYPTO
        !          1162:                        if (!(val & C3_CPUID_DO_PHE)) {
        !          1163:                                msreg = rdmsr(0x1107);
        !          1164:                                msreg |= (0x01 << 28/**/);
        !          1165:                                wrmsr(0x1107, msreg);
        !          1166:                        }
        !          1167:                        i386_has_xcrypt |= C3_HAS_SHA;
        !          1168: #endif /* CRYPTO */
        !          1169:                        printf(" SHA1 SHA256");
        !          1170:                }
        !          1171:
        !          1172:                /* Enable MM engine if present and disabled */
        !          1173:                if (val & C3_CPUID_HAS_PMM) {
        !          1174: #ifdef CRYPTO
        !          1175:                        if (!(val & C3_CPUID_DO_PMM)) {
        !          1176:                                msreg = rdmsr(0x1107);
        !          1177:                                msreg |= (0x01 << 28/**/);
        !          1178:                                wrmsr(0x1107, msreg);
        !          1179:                        }
        !          1180:                        i386_has_xcrypt |= C3_HAS_MM;
        !          1181: #endif /* CRYPTO */
        !          1182:                        printf(" RSA");
        !          1183:                }
        !          1184:
        !          1185:                printf("\n");
        !          1186:                break;
        !          1187:        }
        !          1188: #endif
        !          1189: }
        !          1190:
        !          1191: void
        !          1192: cyrix6x86_cpu_setup(struct cpu_info *ci)
        !          1193: {
        !          1194:        extern int clock_broken_latch;
        !          1195:
        !          1196:        switch ((ci->ci_signature >> 4) & 15) { /* model */
        !          1197:        case -1: /* M1 w/o cpuid */
        !          1198:        case 2: /* M1 */
        !          1199:                /* set up various cyrix registers */
        !          1200:                /* Enable suspend on halt */
        !          1201:                cyrix_write_reg(0xc2, cyrix_read_reg(0xc2) | 0x08);
        !          1202:                /* enable access to ccr4/ccr5 */
        !          1203:                cyrix_write_reg(0xC3, cyrix_read_reg(0xC3) | 0x10);
        !          1204:                /* cyrix's workaround  for the "coma bug" */
        !          1205:                cyrix_write_reg(0x31, cyrix_read_reg(0x31) | 0xf8);
        !          1206:                cyrix_write_reg(0x32, cyrix_read_reg(0x32) | 0x7f);
        !          1207:                cyrix_write_reg(0x33, cyrix_read_reg(0x33) & ~0xff);
        !          1208:                cyrix_write_reg(0x3c, cyrix_read_reg(0x3c) | 0x87);
        !          1209:                /* disable access to ccr4/ccr5 */
        !          1210:                cyrix_write_reg(0xC3, cyrix_read_reg(0xC3) & ~0x10);
        !          1211:
        !          1212:                printf("%s: xchg bug workaround performed\n",
        !          1213:                    ci->ci_dev.dv_xname);
        !          1214:                break;  /* fallthrough? */
        !          1215:        case 4: /* GXm */
        !          1216:                /* Unset the TSC bit until calibrate_delay() gets fixed. */
        !          1217:                clock_broken_latch = 1;
        !          1218:                curcpu()->ci_feature_flags &= ~CPUID_TSC;
        !          1219:                printf("%s: TSC disabled\n", ci->ci_dev.dv_xname);
        !          1220:                break;
        !          1221:        }
        !          1222: }
        !          1223:
        !          1224: void
        !          1225: natsem6x86_cpu_setup(struct cpu_info *ci)
        !          1226: {
        !          1227: #if defined(I586_CPU) || defined(I686_CPU)
        !          1228:        extern int clock_broken_latch;
        !          1229:        int model = (ci->ci_signature >> 4) & 15;
        !          1230:
        !          1231:        clock_broken_latch = 1;
        !          1232:        switch (model) {
        !          1233:        case 4:
        !          1234:                cpu_feature &= ~CPUID_TSC;
        !          1235:                printf("%s: TSC disabled\n", ci->ci_dev.dv_xname);
        !          1236:                break;
        !          1237:        }
        !          1238: #endif
        !          1239: }
        !          1240:
        !          1241: void
        !          1242: intel586_cpu_setup(struct cpu_info *ci)
        !          1243: {
        !          1244: #if defined(I586_CPU)
        !          1245:        if (!cpu_f00f_bug) {
        !          1246:                fix_f00f();
        !          1247:                printf("%s: F00F bug workaround installed\n",
        !          1248:                    ci->ci_dev.dv_xname);
        !          1249:        }
        !          1250: #endif
        !          1251: }
        !          1252:
        !          1253: #if !defined(SMALL_KERNEL) && defined(I586_CPU)
        !          1254: void
        !          1255: amd_family5_setperf_setup(struct cpu_info *ci)
        !          1256: {
        !          1257:        k6_powernow_init();
        !          1258: }
        !          1259: #endif
        !          1260:
        !          1261: void
        !          1262: amd_family5_setup(struct cpu_info *ci)
        !          1263: {
        !          1264:        int model = (ci->ci_signature >> 4) & 15;
        !          1265:
        !          1266:        switch (model) {
        !          1267:        case 0:         /* AMD-K5 Model 0 */
        !          1268:                /*
        !          1269:                 * According to the AMD Processor Recognition App Note,
        !          1270:                 * the AMD-K5 Model 0 uses the wrong bit to indicate
        !          1271:                 * support for global PTEs, instead using bit 9 (APIC)
        !          1272:                 * rather than bit 13 (i.e. "0x200" vs. 0x2000".  Oops!).
        !          1273:                 */
        !          1274:                if (cpu_feature & CPUID_APIC)
        !          1275:                        cpu_feature = (cpu_feature & ~CPUID_APIC) | CPUID_PGE;
        !          1276:                /*
        !          1277:                 * XXX But pmap_pg_g is already initialized -- need to kick
        !          1278:                 * XXX the pmap somehow.  How does the MP branch do this?
        !          1279:                 */
        !          1280:                break;
        !          1281:        case 12:
        !          1282:        case 13:
        !          1283: #if !defined(SMALL_KERNEL) && defined(I586_CPU)
        !          1284:                setperf_setup = amd_family5_setperf_setup;
        !          1285: #endif
        !          1286:                break;
        !          1287:        }
        !          1288: }
        !          1289:
        !          1290: #if !defined(SMALL_KERNEL) && defined(I686_CPU)
        !          1291: void
        !          1292: amd_family6_setperf_setup(struct cpu_info *ci)
        !          1293: {
        !          1294:        int family = (ci->ci_signature >> 8) & 15;
        !          1295:
        !          1296:        switch (family) {
        !          1297:        case 6:
        !          1298:                k7_powernow_init();
        !          1299:                break;
        !          1300:        case 15:
        !          1301:                k8_powernow_init();
        !          1302:                break;
        !          1303:        }
        !          1304: }
        !          1305: #endif /* !SMALL_KERNEL && I686_CPU */
        !          1306:
        !          1307: void
        !          1308: amd_family6_setup(struct cpu_info *ci)
        !          1309: {
        !          1310: #if !defined(SMALL_KERNEL) && defined(I686_CPU)
        !          1311:        extern void (*pagezero)(void *, size_t);
        !          1312:        extern void sse2_pagezero(void *, size_t);
        !          1313:        extern void i686_pagezero(void *, size_t);
        !          1314:
        !          1315:        if (cpu_feature & CPUID_SSE2)
        !          1316:                pagezero = sse2_pagezero;
        !          1317:        else
        !          1318:                pagezero = i686_pagezero;
        !          1319:
        !          1320:        setperf_setup = amd_family6_setperf_setup;
        !          1321: #endif
        !          1322: }
        !          1323:
        !          1324: #if !defined(SMALL_KERNEL) && defined(I686_CPU)
        !          1325: /*
        !          1326:  * Temperature read on the CPU is relative to the maximum
        !          1327:  * temperature supported by the CPU, Tj(Max).
        !          1328:  * Poorly documented, refer to:
        !          1329:  * http://softwarecommunity.intel.com/isn/Community/
        !          1330:  * en-US/forums/thread/30228638.aspx
        !          1331:  * Basically, depending on a bit in one msr, the max is either 85 or 100.
        !          1332:  * Then we subtract the temperature portion of thermal status from
        !          1333:  * max to get current temperature.
        !          1334:  */
        !          1335: void
        !          1336: intelcore_update_sensor(void *args)
        !          1337: {
        !          1338:        struct cpu_info *ci = (struct cpu_info *) args;
        !          1339:        u_int64_t msr;
        !          1340:        int max = 100;
        !          1341:
        !          1342:        if (rdmsr(MSR_TEMPERATURE_TARGET) & MSR_TEMPERATURE_TARGET_LOW_BIT)
        !          1343:                max = 85;
        !          1344:
        !          1345:        msr = rdmsr(MSR_THERM_STATUS);
        !          1346:        if (msr & MSR_THERM_STATUS_VALID_BIT) {
        !          1347:                ci->ci_sensor.value = max - MSR_THERM_STATUS_TEMP(msr);
        !          1348:                /* micro degrees */
        !          1349:                ci->ci_sensor.value *= 1000000;
        !          1350:                /* kelvin */
        !          1351:                ci->ci_sensor.value += 273150000;
        !          1352:                ci->ci_sensor.flags &= ~SENSOR_FINVALID;
        !          1353:        } else {
        !          1354:                ci->ci_sensor.value = 0;
        !          1355:                ci->ci_sensor.flags |= SENSOR_FINVALID;
        !          1356:        }
        !          1357: }
        !          1358:
        !          1359: void
        !          1360: intel686_cpusensors_setup(struct cpu_info *ci)
        !          1361: {
        !          1362:        u_int regs[4];
        !          1363:
        !          1364:        if (cpuid_level < 0x06)
        !          1365:                return;
        !          1366:
        !          1367:        /* CPUID.06H.EAX[0] = 1 tells us if we have on-die sensor */
        !          1368:        cpuid(0x06, regs);
        !          1369:        if ((regs[0] & 0x01) != 1)
        !          1370:                return;
        !          1371:
        !          1372:        /* Setup the sensors structures */
        !          1373:        strlcpy(ci->ci_sensordev.xname, ci->ci_dev.dv_xname,
        !          1374:            sizeof(ci->ci_sensordev.xname));
        !          1375:        ci->ci_sensor.type = SENSOR_TEMP;
        !          1376:        sensor_task_register(ci, intelcore_update_sensor, 5);
        !          1377:        sensor_attach(&ci->ci_sensordev, &ci->ci_sensor);
        !          1378:        sensordev_install(&ci->ci_sensordev);
        !          1379: }
        !          1380: #endif
        !          1381:
        !          1382: #if !defined(SMALL_KERNEL) && defined(I686_CPU)
        !          1383: void
        !          1384: intel686_setperf_setup(struct cpu_info *ci)
        !          1385: {
        !          1386:        int family = (ci->ci_signature >> 8) & 15;
        !          1387:        int step = ci->ci_signature & 15;
        !          1388:
        !          1389:        if (cpu_ecxfeature & CPUIDECX_EST) {
        !          1390:                if (rdmsr(MSR_MISC_ENABLE) & (1 << 16))
        !          1391:                        est_init(ci->ci_dev.dv_xname, CPUVENDOR_INTEL);
        !          1392:                else
        !          1393:                        printf("%s: Enhanced SpeedStep disabled by BIOS\n",
        !          1394:                            ci->ci_dev.dv_xname);
        !          1395:        } else if ((cpu_feature & (CPUID_ACPI | CPUID_TM)) ==
        !          1396:            (CPUID_ACPI | CPUID_TM))
        !          1397:                p4tcc_init(family, step);
        !          1398: }
        !          1399: #endif
        !          1400:
        !          1401: void
        !          1402: intel686_common_cpu_setup(struct cpu_info *ci)
        !          1403: {
        !          1404:
        !          1405: #if !defined(SMALL_KERNEL) && defined(I686_CPU)
        !          1406:        setperf_setup = intel686_setperf_setup;
        !          1407:        cpusensors_setup = intel686_cpusensors_setup;
        !          1408:        {
        !          1409:        extern void (*pagezero)(void *, size_t);
        !          1410:        extern void sse2_pagezero(void *, size_t);
        !          1411:        extern void i686_pagezero(void *, size_t);
        !          1412:
        !          1413:        if (cpu_feature & CPUID_SSE2)
        !          1414:                pagezero = sse2_pagezero;
        !          1415:        else
        !          1416:                pagezero = i686_pagezero;
        !          1417:        }
        !          1418: #endif
        !          1419:        /*
        !          1420:         * Make sure SYSENTER is disabled.
        !          1421:         */
        !          1422:        if (cpu_feature & CPUID_SEP)
        !          1423:                wrmsr(MSR_SYSENTER_CS, 0);
        !          1424: }
        !          1425:
        !          1426: void
        !          1427: intel686_cpu_setup(struct cpu_info *ci)
        !          1428: {
        !          1429:        int model = (ci->ci_signature >> 4) & 15;
        !          1430:        int step = ci->ci_signature & 15;
        !          1431:        u_quad_t msr119;
        !          1432:
        !          1433: #if !defined(SMALL_KERNEL) && defined(I686_CPU)
        !          1434:        p3_get_bus_clock(ci);
        !          1435: #endif
        !          1436:
        !          1437:        intel686_common_cpu_setup(ci);
        !          1438:
        !          1439:        /*
        !          1440:         * Original PPro returns SYSCALL in CPUID but is non-functional.
        !          1441:         * From Intel Application Note #485.
        !          1442:         */
        !          1443:        if ((model == 1) && (step < 3))
        !          1444:                ci->ci_feature_flags &= ~CPUID_SEP;
        !          1445:
        !          1446:        /*
        !          1447:         * Disable the Pentium3 serial number.
        !          1448:         */
        !          1449:        if ((model == 7) && (ci->ci_feature_flags & CPUID_SER)) {
        !          1450:                msr119 = rdmsr(MSR_BBL_CR_CTL);
        !          1451:                msr119 |= 0x0000000000200000LL;
        !          1452:                wrmsr(MSR_BBL_CR_CTL, msr119);
        !          1453:
        !          1454:                printf("%s: disabling processor serial number\n",
        !          1455:                         ci->ci_dev.dv_xname);
        !          1456:                ci->ci_feature_flags &= ~CPUID_SER;
        !          1457:                ci->ci_level = 2;
        !          1458:        }
        !          1459:
        !          1460: #if !defined(SMALL_KERNEL) && defined(I686_CPU)
        !          1461:        p3_early = (model == 8 && step == 1) ? 1 : 0;
        !          1462:        update_cpuspeed = p3_update_cpuspeed;
        !          1463: #endif
        !          1464: }
        !          1465:
        !          1466: void
        !          1467: intel686_p4_cpu_setup(struct cpu_info *ci)
        !          1468: {
        !          1469: #if !defined(SMALL_KERNEL) && defined(I686_CPU)
        !          1470:        p4_get_bus_clock(ci);
        !          1471: #endif
        !          1472:
        !          1473:        intel686_common_cpu_setup(ci);
        !          1474:
        !          1475: #if !defined(SMALL_KERNEL) && defined(I686_CPU)
        !          1476:        p4_model = (ci->ci_signature >> 4) & 15;
        !          1477:        update_cpuspeed = p4_update_cpuspeed;
        !          1478: #endif
        !          1479: }
        !          1480:
        !          1481: void
        !          1482: tm86_cpu_setup(struct cpu_info *ci)
        !          1483: {
        !          1484: #if !defined(SMALL_KERNEL) && defined(I586_CPU)
        !          1485:        longrun_init();
        !          1486: #endif
        !          1487: }
        !          1488:
        !          1489: char *
        !          1490: intel686_cpu_name(int model)
        !          1491: {
        !          1492:        char *ret = NULL;
        !          1493:
        !          1494:        switch (model) {
        !          1495:        case 5:
        !          1496:                switch (cpu_cache_edx & 0xFF) {
        !          1497:                case 0x40:
        !          1498:                case 0x41:
        !          1499:                        ret = "Celeron";
        !          1500:                        break;
        !          1501:                /* 0x42 should not exist in this model. */
        !          1502:                case 0x43:
        !          1503:                        ret = "Pentium II";
        !          1504:                        break;
        !          1505:                case 0x44:
        !          1506:                case 0x45:
        !          1507:                        ret = "Pentium II Xeon";
        !          1508:                        break;
        !          1509:                }
        !          1510:                break;
        !          1511:        case 7:
        !          1512:                switch (cpu_cache_edx & 0xFF) {
        !          1513:                /* 0x40 - 0x42 should not exist in this model. */
        !          1514:                case 0x43:
        !          1515:                        ret = "Pentium III";
        !          1516:                        break;
        !          1517:                case 0x44:
        !          1518:                case 0x45:
        !          1519:                        ret = "Pentium III Xeon";
        !          1520:                        break;
        !          1521:                }
        !          1522:                break;
        !          1523:        }
        !          1524:
        !          1525:        return (ret);
        !          1526: }
        !          1527:
        !          1528: char *
        !          1529: cyrix3_cpu_name(int model, int step)
        !          1530: {
        !          1531:        char    *name = NULL;
        !          1532:
        !          1533:        switch (model) {
        !          1534:        case 7:
        !          1535:                if (step < 8)
        !          1536:                        name = "C3 Samuel 2";
        !          1537:                else
        !          1538:                        name = "C3 Ezra";
        !          1539:                break;
        !          1540:        }
        !          1541:        return name;
        !          1542: }
        !          1543:
        !          1544: /*
        !          1545:  * Print identification for the given CPU.
        !          1546:  * XXX XXX
        !          1547:  * This is not as clean as one might like, because it references
        !          1548:  *
        !          1549:  * the "cpuid_level" and "cpu_vendor" globals.
        !          1550:  * cpuid_level isn't so bad, since both CPU's will hopefully
        !          1551:  * be of the same level.
        !          1552:  *
        !          1553:  * The Intel multiprocessor spec doesn't give us the cpu_vendor
        !          1554:  * information; however, the chance of multi-vendor SMP actually
        !          1555:  * ever *working* is sufficiently low that it's probably safe to assume
        !          1556:  * all processors are of the same vendor.
        !          1557:  */
        !          1558:
        !          1559: void
        !          1560: identifycpu(struct cpu_info *ci)
        !          1561: {
        !          1562:        const char *name, *modifier, *vendorname, *token;
        !          1563:        int class = CPUCLASS_386, vendor, i, max;
        !          1564:        int family, model, step, modif, cachesize;
        !          1565:        const struct cpu_cpuid_nameclass *cpup = NULL;
        !          1566:        char *brandstr_from, *brandstr_to;
        !          1567:        char *cpu_device = ci->ci_dev.dv_xname;
        !          1568:        int skipspace;
        !          1569:
        !          1570:        if (cpuid_level == -1) {
        !          1571: #ifdef DIAGNOSTIC
        !          1572:                if (cpu < 0 || cpu >=
        !          1573:                    (sizeof i386_nocpuid_cpus/sizeof(struct cpu_nocpuid_nameclass)))
        !          1574:                        panic("unknown cpu type %d", cpu);
        !          1575: #endif
        !          1576:                name = i386_nocpuid_cpus[cpu].cpu_name;
        !          1577:                vendor = i386_nocpuid_cpus[cpu].cpu_vendor;
        !          1578:                vendorname = i386_nocpuid_cpus[cpu].cpu_vendorname;
        !          1579:                model = -1;
        !          1580:                step = -1;
        !          1581:                class = i386_nocpuid_cpus[cpu].cpu_class;
        !          1582:                ci->cpu_setup = i386_nocpuid_cpus[cpu].cpu_setup;
        !          1583:                modifier = "";
        !          1584:                token = "";
        !          1585:        } else {
        !          1586:                max = sizeof (i386_cpuid_cpus) / sizeof (i386_cpuid_cpus[0]);
        !          1587:                modif = (ci->ci_signature >> 12) & 3;
        !          1588:                family = (ci->ci_signature >> 8) & 15;
        !          1589:                model = (ci->ci_signature >> 4) & 15;
        !          1590:                step = ci->ci_signature & 15;
        !          1591: #ifdef CPUDEBUG
        !          1592:                printf("%s: family %x model %x step %x\n", cpu_device, family,
        !          1593:                    model, step);
        !          1594:                printf("%s: cpuid level %d cache eax %x ebx %x ecx %x edx %x\n",
        !          1595:                    cpu_device, cpuid_level, cpu_cache_eax, cpu_cache_ebx,
        !          1596:                    cpu_cache_ecx, cpu_cache_edx);
        !          1597: #endif
        !          1598:                if (family < CPU_MINFAMILY)
        !          1599:                        panic("identifycpu: strange family value");
        !          1600:
        !          1601:                for (i = 0; i < max; i++) {
        !          1602:                        if (!strncmp(cpu_vendor,
        !          1603:                            i386_cpuid_cpus[i].cpu_id, 12)) {
        !          1604:                                cpup = &i386_cpuid_cpus[i];
        !          1605:                                break;
        !          1606:                        }
        !          1607:                }
        !          1608:
        !          1609:                if (cpup == NULL) {
        !          1610:                        vendor = CPUVENDOR_UNKNOWN;
        !          1611:                        if (cpu_vendor[0] != '\0')
        !          1612:                                vendorname = &cpu_vendor[0];
        !          1613:                        else
        !          1614:                                vendorname = "Unknown";
        !          1615:                        if (family > CPU_MAXFAMILY)
        !          1616:                                family = CPU_MAXFAMILY;
        !          1617:                        class = family - 3;
        !          1618:                        if (class > CPUCLASS_686)
        !          1619:                                class = CPUCLASS_686;
        !          1620:                        modifier = "";
        !          1621:                        name = "";
        !          1622:                        token = "";
        !          1623:                        ci->cpu_setup = NULL;
        !          1624:                } else {
        !          1625:                        token = cpup->cpu_id;
        !          1626:                        vendor = cpup->cpu_vendor;
        !          1627:                        vendorname = cpup->cpu_vendorname;
        !          1628:                        /*
        !          1629:                         * Special hack for the VIA C3 series.
        !          1630:                         *
        !          1631:                         * VIA bought Centaur Technology from IDT in Aug 1999
        !          1632:                         * and marketed the processors as VIA Cyrix III/C3.
        !          1633:                         */
        !          1634:                        if (vendor == CPUVENDOR_IDT && family >= 6) {
        !          1635:                                vendor = CPUVENDOR_VIA;
        !          1636:                                vendorname = "VIA";
        !          1637:                        }
        !          1638:                        modifier = modifiers[modif];
        !          1639:                        if (family > CPU_MAXFAMILY) {
        !          1640:                                family = CPU_MAXFAMILY;
        !          1641:                                model = CPU_DEFMODEL;
        !          1642:                        } else if (model > CPU_MAXMODEL)
        !          1643:                                model = CPU_DEFMODEL;
        !          1644:                        i = family - CPU_MINFAMILY;
        !          1645:
        !          1646:                        /* Special hack for the PentiumII/III series. */
        !          1647:                        if (vendor == CPUVENDOR_INTEL && family == 6 &&
        !          1648:                            (model == 5 || model == 7)) {
        !          1649:                                name = intel686_cpu_name(model);
        !          1650:                        /* Special hack for the VIA C3 series. */
        !          1651:                        } else if (vendor == CPUVENDOR_VIA && family == 6 &&
        !          1652:                            model == 7) {
        !          1653:                                name = cyrix3_cpu_name(model, step);
        !          1654:                        /* Special hack for the TMS5x00 series. */
        !          1655:                        } else if (vendor == CPUVENDOR_TRANSMETA &&
        !          1656:                            family == 5 && model == 4) {
        !          1657:                                name = tm86_cpu_name(model);
        !          1658:                        } else
        !          1659:                                name = cpup->cpu_family[i].cpu_models[model];
        !          1660:                        if (name == NULL) {
        !          1661:                                name = cpup->cpu_family[i].cpu_models[CPU_DEFMODEL];
        !          1662:                                if (name == NULL)
        !          1663:                                        name = "";
        !          1664:                        }
        !          1665:                        class = cpup->cpu_family[i].cpu_class;
        !          1666:                        ci->cpu_setup = cpup->cpu_family[i].cpu_setup;
        !          1667:                }
        !          1668:        }
        !          1669:
        !          1670:        /* Find the amount of on-chip L2 cache. */
        !          1671:        cachesize = -1;
        !          1672:        if (vendor == CPUVENDOR_INTEL && cpuid_level >= 2 && family < 0xf) {
        !          1673:                int intel_cachetable[] = { 0, 128, 256, 512, 1024, 2048 };
        !          1674:
        !          1675:                if ((cpu_cache_edx & 0xFF) >= 0x40 &&
        !          1676:                    (cpu_cache_edx & 0xFF) <= 0x45)
        !          1677:                        cachesize = intel_cachetable[(cpu_cache_edx & 0xFF) - 0x40];
        !          1678:        } else if (vendor == CPUVENDOR_AMD && class == CPUCLASS_686) {
        !          1679:                u_int regs[4];
        !          1680:                cpuid(0x80000000, regs);
        !          1681:                if (regs[0] >= 0x80000006) {
        !          1682:                        cpuid(0x80000006, regs);
        !          1683:                        cachesize = (regs[2] >> 16);
        !          1684:                }
        !          1685:        }
        !          1686:
        !          1687:        /* Remove leading and duplicated spaces from cpu_brandstr */
        !          1688:        brandstr_from = brandstr_to = cpu_brandstr;
        !          1689:        skipspace = 1;
        !          1690:        while (*brandstr_from != '\0') {
        !          1691:                if (!skipspace || *brandstr_from != ' ') {
        !          1692:                        skipspace = 0;
        !          1693:                        *(brandstr_to++) = *brandstr_from;
        !          1694:                }
        !          1695:                if (*brandstr_from == ' ')
        !          1696:                        skipspace = 1;
        !          1697:                brandstr_from++;
        !          1698:        }
        !          1699:        *brandstr_to = '\0';
        !          1700:
        !          1701:        if (cpu_brandstr[0] == '\0') {
        !          1702:                snprintf(cpu_brandstr, 48 /* sizeof(cpu_brandstr) */,
        !          1703:                    "%s %s%s", vendorname, modifier, name);
        !          1704:        }
        !          1705:
        !          1706:        if ((ci->ci_flags & CPUF_PRIMARY) == 0) {
        !          1707:                if (cachesize > -1) {
        !          1708:                        snprintf(cpu_model, sizeof(cpu_model),
        !          1709:                            "%s (%s%s%s%s-class, %dKB L2 cache)",
        !          1710:                            cpu_brandstr,
        !          1711:                            ((*token) ? "\"" : ""), ((*token) ? token : ""),
        !          1712:                            ((*token) ? "\" " : ""), classnames[class], cachesize);
        !          1713:                } else {
        !          1714:                        snprintf(cpu_model, sizeof(cpu_model),
        !          1715:                            "%s (%s%s%s%s-class)",
        !          1716:                            cpu_brandstr,
        !          1717:                            ((*token) ? "\"" : ""), ((*token) ? token : ""),
        !          1718:                            ((*token) ? "\" " : ""), classnames[class]);
        !          1719:                }
        !          1720:
        !          1721:                printf("%s: %s", cpu_device, cpu_model);
        !          1722:        }
        !          1723:
        !          1724: #if defined(I586_CPU) || defined(I686_CPU)
        !          1725:        if (ci->ci_feature_flags && (ci->ci_feature_flags & CPUID_TSC)) {
        !          1726:                /* Has TSC */
        !          1727:                calibrate_cyclecounter();
        !          1728:                if (cpuspeed > 994) {
        !          1729:                        int ghz, fr;
        !          1730:
        !          1731:                        ghz = (cpuspeed + 9) / 1000;
        !          1732:                        fr = ((cpuspeed + 9) / 10 ) % 100;
        !          1733:                        if ((ci->ci_flags & CPUF_PRIMARY) == 0) {
        !          1734:                                if (fr)
        !          1735:                                        printf(" %d.%02d GHz", ghz, fr);
        !          1736:                                else
        !          1737:                                        printf(" %d GHz", ghz);
        !          1738:                        }
        !          1739:                } else {
        !          1740:                        if ((ci->ci_flags & CPUF_PRIMARY) == 0) {
        !          1741:                                printf(" %d MHz", cpuspeed);
        !          1742:                        }
        !          1743:                }
        !          1744:        }
        !          1745: #endif
        !          1746:        if ((ci->ci_flags & CPUF_PRIMARY) == 0) {
        !          1747:                printf("\n");
        !          1748:
        !          1749:                if (ci->ci_feature_flags) {
        !          1750:                        int numbits = 0;
        !          1751:
        !          1752:                        printf("%s: ", cpu_device);
        !          1753:                        max = sizeof(i386_cpuid_features) /
        !          1754:                            sizeof(i386_cpuid_features[0]);
        !          1755:                        for (i = 0; i < max; i++) {
        !          1756:                                if (ci->ci_feature_flags &
        !          1757:                                    i386_cpuid_features[i].feature_bit) {
        !          1758:                                        printf("%s%s", (numbits == 0 ? "" : ","),
        !          1759:                                            i386_cpuid_features[i].feature_name);
        !          1760:                                        numbits++;
        !          1761:                                }
        !          1762:                        }
        !          1763:                        max = sizeof(i386_cpuid_ecxfeatures)
        !          1764:                                / sizeof(i386_cpuid_ecxfeatures[0]);
        !          1765:                        for (i = 0; i < max; i++) {
        !          1766:                                if (cpu_ecxfeature &
        !          1767:                                    i386_cpuid_ecxfeatures[i].feature_bit) {
        !          1768:                                        printf("%s%s", (numbits == 0 ? "" : ","),
        !          1769:                                            i386_cpuid_ecxfeatures[i].feature_name);
        !          1770:                                        numbits++;
        !          1771:                                }
        !          1772:                        }
        !          1773:                        printf("\n");
        !          1774:                }
        !          1775:        }
        !          1776:
        !          1777: #ifndef MULTIPROCESSOR
        !          1778:        /* configure the CPU if needed */
        !          1779:        if (ci->cpu_setup != NULL)
        !          1780:                (ci->cpu_setup)(ci);
        !          1781: #endif
        !          1782:
        !          1783: #ifndef SMALL_KERNEL
        !          1784: #if defined(I586_CPU) || defined(I686_CPU)
        !          1785:        if (cpuspeed != 0 && cpu_cpuspeed == NULL)
        !          1786:                cpu_cpuspeed = pentium_cpuspeed;
        !          1787: #endif
        !          1788: #endif
        !          1789:
        !          1790:        cpu_class = class;
        !          1791:
        !          1792:        /*
        !          1793:         * Now that we have told the user what they have,
        !          1794:         * let them know if that machine type isn't configured.
        !          1795:         */
        !          1796:        switch (cpu_class) {
        !          1797: #if !defined(I486_CPU) && !defined(I586_CPU) && !defined(I686_CPU)
        !          1798: #error No CPU classes configured.
        !          1799: #endif
        !          1800: #ifndef I686_CPU
        !          1801:        case CPUCLASS_686:
        !          1802:                printf("NOTICE: this kernel does not support Pentium Pro CPU class\n");
        !          1803: #ifdef I586_CPU
        !          1804:                printf("NOTICE: lowering CPU class to i586\n");
        !          1805:                cpu_class = CPUCLASS_586;
        !          1806:                break;
        !          1807: #endif
        !          1808: #endif
        !          1809: #ifndef I586_CPU
        !          1810:        case CPUCLASS_586:
        !          1811:                printf("NOTICE: this kernel does not support Pentium CPU class\n");
        !          1812: #ifdef I486_CPU
        !          1813:                printf("NOTICE: lowering CPU class to i486\n");
        !          1814:                cpu_class = CPUCLASS_486;
        !          1815:                break;
        !          1816: #endif
        !          1817: #endif
        !          1818: #ifndef I486_CPU
        !          1819:        case CPUCLASS_486:
        !          1820:                printf("NOTICE: this kernel does not support i486 CPU class\n");
        !          1821: #endif
        !          1822:        case CPUCLASS_386:
        !          1823:                printf("NOTICE: this kernel does not support i386 CPU class\n");
        !          1824:                panic("no appropriate CPU class available");
        !          1825:        default:
        !          1826:                break;
        !          1827:        }
        !          1828:
        !          1829:        ci->cpu_class = class;
        !          1830:
        !          1831:        if (cpu == CPU_486DLC) {
        !          1832: #ifndef CYRIX_CACHE_WORKS
        !          1833:                printf("WARNING: CYRIX 486DLC CACHE UNCHANGED.\n");
        !          1834: #else
        !          1835: #ifndef CYRIX_CACHE_REALLY_WORKS
        !          1836:                printf("WARNING: CYRIX 486DLC CACHE ENABLED IN HOLD-FLUSH MODE.\n");
        !          1837: #else
        !          1838:                printf("WARNING: CYRIX 486DLC CACHE ENABLED.\n");
        !          1839: #endif
        !          1840: #endif
        !          1841:        }
        !          1842:
        !          1843:        /*
        !          1844:         * Enable ring 0 write protection (486 or above, but 386
        !          1845:         * no longer supported).
        !          1846:         */
        !          1847:        lcr0(rcr0() | CR0_WP);
        !          1848:
        !          1849: #if defined(I686_CPU)
        !          1850:        /*
        !          1851:         * If we have FXSAVE/FXRESTOR, use them.
        !          1852:         */
        !          1853:        if (cpu_feature & CPUID_FXSR) {
        !          1854:                i386_use_fxsave = 1;
        !          1855:                lcr4(rcr4() | CR4_OSFXSR);
        !          1856:
        !          1857:                /*
        !          1858:                 * If we have SSE/SSE2, enable XMM exceptions, and
        !          1859:                 * notify userland.
        !          1860:                 */
        !          1861:                if (cpu_feature & (CPUID_SSE|CPUID_SSE2)) {
        !          1862:                        if (cpu_feature & CPUID_SSE)
        !          1863:                                i386_has_sse = 1;
        !          1864:                        if (cpu_feature & CPUID_SSE2)
        !          1865:                                i386_has_sse2 = 1;
        !          1866:                        lcr4(rcr4() | CR4_OSXMMEXCPT);
        !          1867:                }
        !          1868:        } else
        !          1869:                i386_use_fxsave = 0;
        !          1870:
        !          1871:        if (vendor == CPUVENDOR_AMD)
        !          1872:                amd64_errata(ci);
        !          1873: #endif /* I686_CPU */
        !          1874: }
        !          1875:
        !          1876: char *
        !          1877: tm86_cpu_name(int model)
        !          1878: {
        !          1879:        u_int32_t regs[4];
        !          1880:        char *name = NULL;
        !          1881:
        !          1882:        cpuid(0x80860001, regs);
        !          1883:
        !          1884:        switch (model) {
        !          1885:        case 4:
        !          1886:                if (((regs[1] >> 16) & 0xff) >= 0x3)
        !          1887:                        name = "TMS5800";
        !          1888:                else
        !          1889:                        name = "TMS5600";
        !          1890:        }
        !          1891:
        !          1892:        return name;
        !          1893: }
        !          1894:
        !          1895: #ifndef SMALL_KERNEL
        !          1896: #ifdef I686_CPU
        !          1897: void
        !          1898: cyrix3_get_bus_clock(struct cpu_info *ci)
        !          1899: {
        !          1900:        u_int64_t msr;
        !          1901:        int bus;
        !          1902:
        !          1903:        msr = rdmsr(MSR_EBL_CR_POWERON);
        !          1904:        bus = (msr >> 18) & 0x3;
        !          1905:        switch (bus) {
        !          1906:        case 0:
        !          1907:                bus_clock = BUS100;
        !          1908:                break;
        !          1909:        case 1:
        !          1910:                bus_clock = BUS133;
        !          1911:                break;
        !          1912:        case 2:
        !          1913:                bus_clock = BUS200;
        !          1914:                break;
        !          1915:        case 3:
        !          1916:                bus_clock = BUS166;
        !          1917:                break;
        !          1918:        }
        !          1919: }
        !          1920:
        !          1921: void
        !          1922: p4_get_bus_clock(struct cpu_info *ci)
        !          1923: {
        !          1924:        u_int64_t msr;
        !          1925:        int model, bus;
        !          1926:
        !          1927:        model = (ci->ci_signature >> 4) & 15;
        !          1928:        msr = rdmsr(MSR_EBC_FREQUENCY_ID);
        !          1929:        if (model < 2) {
        !          1930:                bus = (msr >> 21) & 0x7;
        !          1931:                switch (bus) {
        !          1932:                case 0:
        !          1933:                        bus_clock = BUS100;
        !          1934:                        break;
        !          1935:                case 1:
        !          1936:                        bus_clock = BUS133;
        !          1937:                        break;
        !          1938:                default:
        !          1939:                        printf("%s: unknown Pentium 4 (model %d) "
        !          1940:                            "EBC_FREQUENCY_ID value %d\n",
        !          1941:                            ci->ci_dev.dv_xname, model, bus);
        !          1942:                        break;
        !          1943:                }
        !          1944:        } else {
        !          1945:                bus = (msr >> 16) & 0x7;
        !          1946:                switch (bus) {
        !          1947:                case 0:
        !          1948:                        bus_clock = (model == 2) ? BUS100 : BUS266;
        !          1949:                        break;
        !          1950:                case 1:
        !          1951:                        bus_clock = BUS133;
        !          1952:                        break;
        !          1953:                case 2:
        !          1954:                        bus_clock = BUS200;
        !          1955:                        break;
        !          1956:                case 3:
        !          1957:                        bus_clock = BUS166;
        !          1958:                        break;
        !          1959:                default:
        !          1960:                        printf("%s: unknown Pentium 4 (model %d) "
        !          1961:                            "EBC_FREQUENCY_ID value %d\n",
        !          1962:                            ci->ci_dev.dv_xname, model, bus);
        !          1963:                        break;
        !          1964:                }
        !          1965:        }
        !          1966: }
        !          1967:
        !          1968: void
        !          1969: p3_get_bus_clock(struct cpu_info *ci)
        !          1970: {
        !          1971:        u_int64_t msr;
        !          1972:        int model, bus;
        !          1973:
        !          1974:        model = (ci->ci_signature >> 4) & 15;
        !          1975:        switch (model) {
        !          1976:        case 0x9: /* Pentium M (130 nm, Banias) */
        !          1977:                bus_clock = BUS100;
        !          1978:                break;
        !          1979:        case 0xd: /* Pentium M (90 nm, Dothan) */
        !          1980:                msr = rdmsr(MSR_FSB_FREQ);
        !          1981:                bus = (msr >> 0) & 0x7;
        !          1982:                switch (bus) {
        !          1983:                case 0:
        !          1984:                        bus_clock = BUS100;
        !          1985:                        break;
        !          1986:                case 1:
        !          1987:                        bus_clock = BUS133;
        !          1988:                        break;
        !          1989:                default:
        !          1990:                        printf("%s: unknown Pentium M FSB_FREQ value %d",
        !          1991:                            ci->ci_dev.dv_xname, bus);
        !          1992:                        goto print_msr;
        !          1993:                }
        !          1994:                break;
        !          1995:        case 0xe: /* Core Duo/Solo */
        !          1996:        case 0xf: /* Core Xeon */
        !          1997:                msr = rdmsr(MSR_FSB_FREQ);
        !          1998:                bus = (msr >> 0) & 0x7;
        !          1999:                switch (bus) {
        !          2000:                case 5:
        !          2001:                        bus_clock = BUS100;
        !          2002:                        break;
        !          2003:                case 1:
        !          2004:                        bus_clock = BUS133;
        !          2005:                        break;
        !          2006:                case 3:
        !          2007:                        bus_clock = BUS166;
        !          2008:                        break;
        !          2009:                case 2:
        !          2010:                        bus_clock = BUS200;
        !          2011:                        break;
        !          2012:                case 0:
        !          2013:                        bus_clock = BUS266;
        !          2014:                        break;
        !          2015:                case 4:
        !          2016:                        bus_clock = BUS333;
        !          2017:                        break;
        !          2018:                default:
        !          2019:                        printf("%s: unknown Core FSB_FREQ value %d",
        !          2020:                            ci->ci_dev.dv_xname, bus);
        !          2021:                        goto print_msr;
        !          2022:                }
        !          2023:                break;
        !          2024:        case 0x1: /* Pentium Pro, model 1 */
        !          2025:        case 0x3: /* Pentium II, model 3 */
        !          2026:        case 0x5: /* Pentium II, II Xeon, Celeron, model 5 */
        !          2027:        case 0x6: /* Celeron, model 6 */
        !          2028:        case 0x7: /* Pentium III, III Xeon, model 7 */
        !          2029:        case 0x8: /* Pentium III, III Xeon, Celeron, model 8 */
        !          2030:        case 0xa: /* Pentium III Xeon, model A */
        !          2031:        case 0xb: /* Pentium III, model B */
        !          2032:                msr = rdmsr(MSR_EBL_CR_POWERON);
        !          2033:                bus = (msr >> 18) & 0x3;
        !          2034:                switch (bus) {
        !          2035:                case 0:
        !          2036:                        bus_clock = BUS66;
        !          2037:                        break;
        !          2038:                case 1:
        !          2039:                        bus_clock = BUS133;
        !          2040:                        break;
        !          2041:                case 2:
        !          2042:                        bus_clock = BUS100;
        !          2043:                        break;
        !          2044:                default:
        !          2045:                        printf("%s: unknown i686 EBL_CR_POWERON value %d",
        !          2046:                            ci->ci_dev.dv_xname, bus);
        !          2047:                        goto print_msr;
        !          2048:                }
        !          2049:                break;
        !          2050:        default:
        !          2051:                printf("%s: unknown i686 model %d, can't get bus clock",
        !          2052:                    ci->ci_dev.dv_xname, model);
        !          2053: print_msr:
        !          2054:                /*
        !          2055:                 * Show the EBL_CR_POWERON MSR, so we'll at least have
        !          2056:                 * some extra information, such as clock ratio, etc.
        !          2057:                 */
        !          2058:                printf(" (0x%llx)\n", rdmsr(MSR_EBL_CR_POWERON));
        !          2059:                break;
        !          2060:        }
        !          2061: }
        !          2062:
        !          2063: void
        !          2064: p4_update_cpuspeed(void)
        !          2065: {
        !          2066:        u_int64_t msr;
        !          2067:        int mult;
        !          2068:
        !          2069:        if (bus_clock == 0) {
        !          2070:                printf("p4_update_cpuspeed: unknown bus clock\n");
        !          2071:                return;
        !          2072:        }
        !          2073:
        !          2074:        msr = rdmsr(MSR_EBC_FREQUENCY_ID);
        !          2075:        mult = ((msr >> 24) & 0xff);
        !          2076:
        !          2077:        cpuspeed = (bus_clock * mult) / 100;
        !          2078: }
        !          2079:
        !          2080: void
        !          2081: p3_update_cpuspeed(void)
        !          2082: {
        !          2083:        u_int64_t msr;
        !          2084:        int mult;
        !          2085:        const u_int8_t mult_code[] = {
        !          2086:            50, 30, 40, 0, 55, 35, 45, 0, 0, 70, 80, 60, 0, 75, 0, 65 };
        !          2087:
        !          2088:        if (bus_clock == 0) {
        !          2089:                printf("p3_update_cpuspeed: unknown bus clock\n");
        !          2090:                return;
        !          2091:        }
        !          2092:
        !          2093:        msr = rdmsr(MSR_EBL_CR_POWERON);
        !          2094:        mult = (msr >> 22) & 0xf;
        !          2095:        mult = mult_code[mult];
        !          2096:        if (!p3_early)
        !          2097:                mult += ((msr >> 27) & 0x1) * 40;
        !          2098:
        !          2099:        cpuspeed = (bus_clock * mult) / 1000;
        !          2100: }
        !          2101: #endif /* I686_CPU */
        !          2102:
        !          2103: #if defined(I586_CPU) || defined(I686_CPU)
        !          2104: int
        !          2105: pentium_cpuspeed(int *freq)
        !          2106: {
        !          2107:        *freq = cpuspeed;
        !          2108:        return (0);
        !          2109: }
        !          2110: #endif
        !          2111: #endif /* !SMALL_KERNEL */
        !          2112:
        !          2113: #ifdef COMPAT_IBCS2
        !          2114: void ibcs2_sendsig(sig_t, int, int, u_long, int, union sigval);
        !          2115:
        !          2116: void
        !          2117: ibcs2_sendsig(sig_t catcher, int sig, int mask, u_long code, int type,
        !          2118:     union sigval val)
        !          2119: {
        !          2120:        extern int bsd_to_ibcs2_sig[];
        !          2121:
        !          2122:        sendsig(catcher, bsd_to_ibcs2_sig[sig], mask, code, type, val);
        !          2123: }
        !          2124: #endif
        !          2125:
        !          2126: /*
        !          2127:  * To send an AST to a process on another cpu we send an IPI to that cpu,
        !          2128:  * the IPI schedules a special soft interrupt (that does nothing) and then
        !          2129:  * returns through the normal interrupt return path which in turn handles
        !          2130:  * the AST.
        !          2131:  *
        !          2132:  * The IPI can't handle the AST because it usually requires grabbing the
        !          2133:  * biglock and we can't afford spinning in the IPI handler with interrupts
        !          2134:  * unlocked (so that we take further IPIs and grow our stack until it
        !          2135:  * overflows).
        !          2136:  */
        !          2137: void
        !          2138: aston(struct proc *p)
        !          2139: {
        !          2140: #ifdef MULTIPROCESSOR
        !          2141:        if (i386_atomic_testset_i(&p->p_md.md_astpending, 1) == 0 &&
        !          2142:            p->p_cpu != curcpu())
        !          2143:                i386_fast_ipi(p->p_cpu, LAPIC_IPI_AST);
        !          2144: #else
        !          2145:        p->p_md.md_astpending = 1;
        !          2146: #endif
        !          2147: }
        !          2148:
        !          2149: /*
        !          2150:  * Send an interrupt to process.
        !          2151:  *
        !          2152:  * Stack is set up to allow sigcode stored
        !          2153:  * in u. to call routine, followed by kcall
        !          2154:  * to sigreturn routine below.  After sigreturn
        !          2155:  * resets the signal mask, the stack, and the
        !          2156:  * frame pointer, it returns to the user
        !          2157:  * specified pc, psl.
        !          2158:  */
        !          2159: void
        !          2160: sendsig(sig_t catcher, int sig, int mask, u_long code, int type,
        !          2161:     union sigval val)
        !          2162: {
        !          2163: #ifdef I686_CPU
        !          2164:        extern char sigcode, sigcode_xmm;
        !          2165: #endif
        !          2166:        struct proc *p = curproc;
        !          2167:        struct trapframe *tf = p->p_md.md_regs;
        !          2168:        struct sigframe *fp, frame;
        !          2169:        struct sigacts *psp = p->p_sigacts;
        !          2170:        register_t sp;
        !          2171:        int oonstack = psp->ps_sigstk.ss_flags & SS_ONSTACK;
        !          2172:
        !          2173:        /*
        !          2174:         * Build the argument list for the signal handler.
        !          2175:         */
        !          2176:        frame.sf_signum = sig;
        !          2177:
        !          2178:        /*
        !          2179:         * Allocate space for the signal handler context.
        !          2180:         */
        !          2181:        if ((psp->ps_flags & SAS_ALTSTACK) && !oonstack &&
        !          2182:            (psp->ps_sigonstack & sigmask(sig))) {
        !          2183:                sp = (long)psp->ps_sigstk.ss_sp + psp->ps_sigstk.ss_size;
        !          2184:                psp->ps_sigstk.ss_flags |= SS_ONSTACK;
        !          2185:        } else
        !          2186:                sp = tf->tf_esp;
        !          2187:
        !          2188:        frame.sf_fpstate = NULL;
        !          2189:        if (p->p_md.md_flags & MDP_USEDFPU) {
        !          2190:                sp -= sizeof(union savefpu);
        !          2191:                sp &= ~0xf;     /* foe XMM regs */
        !          2192:                frame.sf_fpstate = (void *)sp;
        !          2193:        }
        !          2194:
        !          2195:        fp = (struct sigframe *)sp - 1;
        !          2196:        frame.sf_scp = &fp->sf_sc;
        !          2197:        frame.sf_sip = NULL;
        !          2198:        frame.sf_handler = catcher;
        !          2199:
        !          2200:        /*
        !          2201:         * Build the signal context to be used by sigreturn.
        !          2202:         */
        !          2203:        frame.sf_sc.sc_err = tf->tf_err;
        !          2204:        frame.sf_sc.sc_trapno = tf->tf_trapno;
        !          2205:        frame.sf_sc.sc_onstack = oonstack;
        !          2206:        frame.sf_sc.sc_mask = mask;
        !          2207: #ifdef VM86
        !          2208:        if (tf->tf_eflags & PSL_VM) {
        !          2209:                frame.sf_sc.sc_gs = tf->tf_vm86_gs;
        !          2210:                frame.sf_sc.sc_fs = tf->tf_vm86_fs;
        !          2211:                frame.sf_sc.sc_es = tf->tf_vm86_es;
        !          2212:                frame.sf_sc.sc_ds = tf->tf_vm86_ds;
        !          2213:                frame.sf_sc.sc_eflags = get_vflags(p);
        !          2214:        } else
        !          2215: #endif
        !          2216:        {
        !          2217:                frame.sf_sc.sc_fs = tf->tf_fs;
        !          2218:                frame.sf_sc.sc_gs = tf->tf_gs;
        !          2219:                frame.sf_sc.sc_es = tf->tf_es;
        !          2220:                frame.sf_sc.sc_ds = tf->tf_ds;
        !          2221:                frame.sf_sc.sc_eflags = tf->tf_eflags;
        !          2222:        }
        !          2223:        frame.sf_sc.sc_edi = tf->tf_edi;
        !          2224:        frame.sf_sc.sc_esi = tf->tf_esi;
        !          2225:        frame.sf_sc.sc_ebp = tf->tf_ebp;
        !          2226:        frame.sf_sc.sc_ebx = tf->tf_ebx;
        !          2227:        frame.sf_sc.sc_edx = tf->tf_edx;
        !          2228:        frame.sf_sc.sc_ecx = tf->tf_ecx;
        !          2229:        frame.sf_sc.sc_eax = tf->tf_eax;
        !          2230:        frame.sf_sc.sc_eip = tf->tf_eip;
        !          2231:        frame.sf_sc.sc_cs = tf->tf_cs;
        !          2232:        frame.sf_sc.sc_esp = tf->tf_esp;
        !          2233:        frame.sf_sc.sc_ss = tf->tf_ss;
        !          2234:
        !          2235:        if (psp->ps_siginfo & sigmask(sig)) {
        !          2236:                frame.sf_sip = &fp->sf_si;
        !          2237:                initsiginfo(&frame.sf_si, sig, code, type, val);
        !          2238: #ifdef VM86
        !          2239:                if (sig == SIGURG)      /* VM86 userland trap */
        !          2240:                        frame.sf_si.si_trapno = code;
        !          2241: #endif
        !          2242:        }
        !          2243:
        !          2244:        /* XXX don't copyout siginfo if not needed? */
        !          2245:        if (copyout(&frame, fp, sizeof(frame)) != 0) {
        !          2246:                /*
        !          2247:                 * Process has trashed its stack; give it an illegal
        !          2248:                 * instruction to halt it in its tracks.
        !          2249:                 */
        !          2250:                sigexit(p, SIGILL);
        !          2251:                /* NOTREACHED */
        !          2252:        }
        !          2253:
        !          2254:        /*
        !          2255:         * Build context to run handler in.
        !          2256:         */
        !          2257:        tf->tf_fs = GSEL(GUDATA_SEL, SEL_UPL);
        !          2258:        tf->tf_gs = GSEL(GUDATA_SEL, SEL_UPL);
        !          2259:        tf->tf_es = GSEL(GUDATA_SEL, SEL_UPL);
        !          2260:        tf->tf_ds = GSEL(GUDATA_SEL, SEL_UPL);
        !          2261:        tf->tf_eip = p->p_sigcode;
        !          2262:        tf->tf_cs = GSEL(GUCODE_SEL, SEL_UPL);
        !          2263: #ifdef I686_CPU
        !          2264:        if (i386_use_fxsave)
        !          2265:                tf->tf_eip += &sigcode_xmm - &sigcode;
        !          2266: #endif
        !          2267:        tf->tf_eflags &= ~(PSL_T|PSL_VM|PSL_AC);
        !          2268:        tf->tf_esp = (int)fp;
        !          2269:        tf->tf_ss = GSEL(GUDATA_SEL, SEL_UPL);
        !          2270: }
        !          2271:
        !          2272: /*
        !          2273:  * System call to cleanup state after a signal
        !          2274:  * has been taken.  Reset signal mask and
        !          2275:  * stack state from context left by sendsig (above).
        !          2276:  * Return to previous pc and psl as specified by
        !          2277:  * context left by sendsig. Check carefully to
        !          2278:  * make sure that the user has not modified the
        !          2279:  * psl to gain improper privileges or to cause
        !          2280:  * a machine fault.
        !          2281:  */
        !          2282: int
        !          2283: sys_sigreturn(struct proc *p, void *v, register_t *retval)
        !          2284: {
        !          2285:        struct sys_sigreturn_args /* {
        !          2286:                syscallarg(struct sigcontext *) sigcntxp;
        !          2287:        } */ *uap = v;
        !          2288:        struct sigcontext *scp, context;
        !          2289:        struct trapframe *tf;
        !          2290:
        !          2291:        tf = p->p_md.md_regs;
        !          2292:
        !          2293:        /*
        !          2294:         * The trampoline code hands us the context.
        !          2295:         * It is unsafe to keep track of it ourselves, in the event that a
        !          2296:         * program jumps out of a signal handler.
        !          2297:         */
        !          2298:        scp = SCARG(uap, sigcntxp);
        !          2299:        if (copyin((caddr_t)scp, &context, sizeof(*scp)) != 0)
        !          2300:                return (EFAULT);
        !          2301:
        !          2302:        /*
        !          2303:         * Restore signal context.
        !          2304:         */
        !          2305: #ifdef VM86
        !          2306:        if (context.sc_eflags & PSL_VM) {
        !          2307:                tf->tf_vm86_gs = context.sc_gs;
        !          2308:                tf->tf_vm86_fs = context.sc_fs;
        !          2309:                tf->tf_vm86_es = context.sc_es;
        !          2310:                tf->tf_vm86_ds = context.sc_ds;
        !          2311:                set_vflags(p, context.sc_eflags);
        !          2312:        } else
        !          2313: #endif
        !          2314:        {
        !          2315:                /*
        !          2316:                 * Check for security violations.  If we're returning to
        !          2317:                 * protected mode, the CPU will validate the segment registers
        !          2318:                 * automatically and generate a trap on violations.  We handle
        !          2319:                 * the trap, rather than doing all of the checking here.
        !          2320:                 */
        !          2321:                if (((context.sc_eflags ^ tf->tf_eflags) & PSL_USERSTATIC) != 0 ||
        !          2322:                    !USERMODE(context.sc_cs, context.sc_eflags))
        !          2323:                        return (EINVAL);
        !          2324:
        !          2325:                tf->tf_fs = context.sc_fs;
        !          2326:                tf->tf_gs = context.sc_gs;
        !          2327:                tf->tf_es = context.sc_es;
        !          2328:                tf->tf_ds = context.sc_ds;
        !          2329:                tf->tf_eflags = context.sc_eflags;
        !          2330:        }
        !          2331:        tf->tf_edi = context.sc_edi;
        !          2332:        tf->tf_esi = context.sc_esi;
        !          2333:        tf->tf_ebp = context.sc_ebp;
        !          2334:        tf->tf_ebx = context.sc_ebx;
        !          2335:        tf->tf_edx = context.sc_edx;
        !          2336:        tf->tf_ecx = context.sc_ecx;
        !          2337:        tf->tf_eax = context.sc_eax;
        !          2338:        tf->tf_eip = context.sc_eip;
        !          2339:        tf->tf_cs = context.sc_cs;
        !          2340:        tf->tf_esp = context.sc_esp;
        !          2341:        tf->tf_ss = context.sc_ss;
        !          2342:
        !          2343:        if (context.sc_onstack & 01)
        !          2344:                p->p_sigacts->ps_sigstk.ss_flags |= SS_ONSTACK;
        !          2345:        else
        !          2346:                p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK;
        !          2347:        p->p_sigmask = context.sc_mask & ~sigcantmask;
        !          2348:
        !          2349:        return (EJUSTRETURN);
        !          2350: }
        !          2351:
        !          2352: int    waittime = -1;
        !          2353: struct pcb dumppcb;
        !          2354:
        !          2355: void
        !          2356: boot(int howto)
        !          2357: {
        !          2358:        if (cold) {
        !          2359:                /*
        !          2360:                 * If the system is cold, just halt, unless the user
        !          2361:                 * explicitly asked for reboot.
        !          2362:                 */
        !          2363:                if ((howto & RB_USERREQ) == 0)
        !          2364:                        howto |= RB_HALT;
        !          2365:                goto haltsys;
        !          2366:        }
        !          2367:
        !          2368:        boothowto = howto;
        !          2369:        if ((howto & RB_NOSYNC) == 0 && waittime < 0) {
        !          2370:                extern struct proc proc0;
        !          2371:
        !          2372:                /* protect against curproc->p_stats.foo refs in sync()   XXX */
        !          2373:                if (curproc == NULL)
        !          2374:                        curproc = &proc0;
        !          2375:
        !          2376:                waittime = 0;
        !          2377:                vfs_shutdown();
        !          2378:                /*
        !          2379:                 * If we've been adjusting the clock, the todr
        !          2380:                 * will be out of synch; adjust it now.
        !          2381:                 */
        !          2382:                if ((howto & RB_TIMEBAD) == 0) {
        !          2383:                        resettodr();
        !          2384:                } else {
        !          2385:                        printf("WARNING: not updating battery clock\n");
        !          2386:                }
        !          2387:        }
        !          2388:
        !          2389:        /* Disable interrupts. */
        !          2390:        splhigh();
        !          2391:
        !          2392:        /* Do a dump if requested. */
        !          2393:        if (howto & RB_DUMP)
        !          2394:                dumpsys();
        !          2395:
        !          2396: haltsys:
        !          2397:        doshutdownhooks();
        !          2398:
        !          2399:        if (howto & RB_HALT) {
        !          2400: #if NACPI > 0 && !defined(SMALL_KERNEL)
        !          2401:                extern int acpi_s5, acpi_enabled;
        !          2402:
        !          2403:                if (acpi_enabled) {
        !          2404:                        delay(500000);
        !          2405:                        if ((howto & RB_POWERDOWN) || acpi_s5)
        !          2406:                                acpi_powerdown();
        !          2407:                }
        !          2408: #endif
        !          2409:
        !          2410: #if NAPM > 0
        !          2411:                if (howto & RB_POWERDOWN) {
        !          2412:                        int rv;
        !          2413:
        !          2414:                        printf("\nAttempting to power down...\n");
        !          2415:                        /*
        !          2416:                         * Turn off, if we can.  But try to turn disk off and
        !          2417:                         * wait a bit first--some disk drives are slow to
        !          2418:                         * clean up and users have reported disk corruption.
        !          2419:                         *
        !          2420:                         * If apm_set_powstate() fails the first time, don't
        !          2421:                         * try to turn the system off.
        !          2422:                         */
        !          2423:                        delay(500000);
        !          2424:                        /*
        !          2425:                         * It's been reported that the following bit of code
        !          2426:                         * is required on most systems <mickey@openbsd.org>
        !          2427:                         * but cause powerdown problem on other systems
        !          2428:                         * <smcho@tsp.korea.ac.kr>.  Use sysctl to set
        !          2429:                         * apmhalt to a non-zero value to skip the offending
        !          2430:                         * code.
        !          2431:                         */
        !          2432:                        if (!cpu_apmhalt) {
        !          2433:                                apm_set_powstate(APM_DEV_DISK(0xff),
        !          2434:                                                 APM_SYS_OFF);
        !          2435:                                delay(500000);
        !          2436:                        }
        !          2437:                        rv = apm_set_powstate(APM_DEV_DISK(0xff), APM_SYS_OFF);
        !          2438:                        if (rv == 0 || rv == ENXIO) {
        !          2439:                                delay(500000);
        !          2440:                                (void) apm_set_powstate(APM_DEV_ALLDEVS,
        !          2441:                                                        APM_SYS_OFF);
        !          2442:                        }
        !          2443:                }
        !          2444: #endif
        !          2445:                printf("\n");
        !          2446:                printf("The operating system has halted.\n");
        !          2447:                printf("Please press any key to reboot.\n\n");
        !          2448:                cngetc();
        !          2449:        }
        !          2450:
        !          2451:        printf("rebooting...\n");
        !          2452:        cpu_reset();
        !          2453:        for(;;) ;
        !          2454:        /*NOTREACHED*/
        !          2455: }
        !          2456:
        !          2457: /*
        !          2458:  * This is called by configure to set dumplo and dumpsize.
        !          2459:  * Dumps always skip the first block of disk space
        !          2460:  * in case there might be a disk label stored there.
        !          2461:  * If there is extra space, put dump at the end to
        !          2462:  * reduce the chance that swapping trashes it.
        !          2463:  */
        !          2464: void
        !          2465: dumpconf(void)
        !          2466: {
        !          2467:        int nblks;      /* size of dump area */
        !          2468:        int i;
        !          2469:
        !          2470:        if (dumpdev == NODEV ||
        !          2471:            (nblks = (bdevsw[major(dumpdev)].d_psize)(dumpdev)) == 0)
        !          2472:                return;
        !          2473:        if (nblks <= ctod(1))
        !          2474:                return;
        !          2475:
        !          2476:        /* Always skip the first block, in case there is a label there. */
        !          2477:        if (dumplo < ctod(1))
        !          2478:                dumplo = ctod(1);
        !          2479:
        !          2480:        for (i = 0; i < ndumpmem; i++)
        !          2481:                dumpsize = max(dumpsize, dumpmem[i].end);
        !          2482:
        !          2483:        /* Put dump at end of partition, and make it fit. */
        !          2484:        if (dumpsize > dtoc(nblks - dumplo - 1))
        !          2485:                dumpsize = dtoc(nblks - dumplo - 1);
        !          2486:        if (dumplo < nblks - ctod(dumpsize) - 1)
        !          2487:                dumplo = nblks - ctod(dumpsize) - 1;
        !          2488: }
        !          2489:
        !          2490: /*
        !          2491:  * cpu_dump: dump machine-dependent kernel core dump headers.
        !          2492:  */
        !          2493: int
        !          2494: cpu_dump()
        !          2495: {
        !          2496:        int (*dump)(dev_t, daddr64_t, caddr_t, size_t);
        !          2497:        long buf[dbtob(1) / sizeof (long)];
        !          2498:        kcore_seg_t     *segp;
        !          2499:
        !          2500:        dump = bdevsw[major(dumpdev)].d_dump;
        !          2501:
        !          2502:        segp = (kcore_seg_t *)buf;
        !          2503:
        !          2504:        /*
        !          2505:         * Generate a segment header.
        !          2506:         */
        !          2507:        CORE_SETMAGIC(*segp, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
        !          2508:        segp->c_size = dbtob(1) - ALIGN(sizeof(*segp));
        !          2509:
        !          2510:        return (dump(dumpdev, dumplo, (caddr_t)buf, dbtob(1)));
        !          2511: }
        !          2512:
        !          2513: /*
        !          2514:  * Doadump comes here after turning off memory management and
        !          2515:  * getting on the dump stack, either when called above, or by
        !          2516:  * the auto-restart code.
        !          2517:  */
        !          2518: static vaddr_t dumpspace;
        !          2519:
        !          2520: vaddr_t
        !          2521: reserve_dumppages(vaddr_t p)
        !          2522: {
        !          2523:
        !          2524:        dumpspace = p;
        !          2525:        return (p + PAGE_SIZE);
        !          2526: }
        !          2527:
        !          2528: void
        !          2529: dumpsys()
        !          2530: {
        !          2531:        u_int i, j, npg;
        !          2532:        int maddr;
        !          2533:        daddr64_t blkno;
        !          2534:        int (*dump)(dev_t, daddr64_t, caddr_t, size_t);
        !          2535:        int error;
        !          2536:        char *str;
        !          2537:        extern int msgbufmapped;
        !          2538:
        !          2539:        /* Save registers. */
        !          2540:        savectx(&dumppcb);
        !          2541:
        !          2542:        msgbufmapped = 0;       /* don't record dump msgs in msgbuf */
        !          2543:        if (dumpdev == NODEV)
        !          2544:                return;
        !          2545:
        !          2546:        /*
        !          2547:         * For dumps during autoconfiguration,
        !          2548:         * if dump device has already configured...
        !          2549:         */
        !          2550:        if (dumpsize == 0)
        !          2551:                dumpconf();
        !          2552:        if (dumplo < 0)
        !          2553:                return;
        !          2554:        printf("\ndumping to dev %x, offset %ld\n", dumpdev, dumplo);
        !          2555:
        !          2556:        error = (*bdevsw[major(dumpdev)].d_psize)(dumpdev);
        !          2557:        printf("dump ");
        !          2558:        if (error == -1) {
        !          2559:                printf("area unavailable\n");
        !          2560:                return;
        !          2561:        }
        !          2562:
        !          2563: #if 0  /* XXX this doesn't work.  grr. */
        !          2564:        /* toss any characters present prior to dump */
        !          2565:        while (sget() != NULL); /*syscons and pccons differ */
        !          2566: #endif
        !          2567:
        !          2568:        /* scan through the dumpmem list */
        !          2569:        dump = bdevsw[major(dumpdev)].d_dump;
        !          2570:        error = cpu_dump();
        !          2571:        for (i = 0; !error && i < ndumpmem; i++) {
        !          2572:
        !          2573:                npg = dumpmem[i].end - dumpmem[i].start;
        !          2574:                maddr = ctob(dumpmem[i].start);
        !          2575:                blkno = dumplo + btodb(maddr) + 1;
        !          2576: #if 0
        !          2577:                printf("(%d %lld %d) ", maddr, blkno, npg);
        !          2578: #endif
        !          2579:                for (j = npg; j--; maddr += NBPG, blkno += btodb(NBPG)) {
        !          2580:
        !          2581:                        /* Print out how many MBs we have more to go. */
        !          2582:                        if (dbtob(blkno - dumplo) % (1024 * 1024) < NBPG)
        !          2583:                                printf("%d ",
        !          2584:                                    (ctob(dumpsize) - maddr) / (1024 * 1024));
        !          2585: #if 0
        !          2586:                        printf("(%x %lld) ", maddr, blkno);
        !          2587: #endif
        !          2588:                        pmap_enter(pmap_kernel(), dumpspace, maddr,
        !          2589:                            VM_PROT_READ, PMAP_WIRED);
        !          2590:                        if ((error = (*dump)(dumpdev, blkno,
        !          2591:                            (caddr_t)dumpspace, NBPG)))
        !          2592:                                break;
        !          2593:
        !          2594: #if 0  /* XXX this doesn't work.  grr. */
        !          2595:                        /* operator aborting dump? */
        !          2596:                        if (sget() != NULL) {
        !          2597:                                error = EINTR;
        !          2598:                                break;
        !          2599:                        }
        !          2600: #endif
        !          2601:                }
        !          2602:        }
        !          2603:
        !          2604:        switch (error) {
        !          2605:
        !          2606:        case 0:         str = "succeeded\n\n";                  break;
        !          2607:        case ENXIO:     str = "device bad\n\n";                 break;
        !          2608:        case EFAULT:    str = "device not ready\n\n";           break;
        !          2609:        case EINVAL:    str = "area improper\n\n";              break;
        !          2610:        case EIO:       str = "i/o error\n\n";                  break;
        !          2611:        case EINTR:     str = "aborted from console\n\n";       break;
        !          2612:        default:        str = "error %d\n\n";                   break;
        !          2613:        }
        !          2614:        printf(str, error);
        !          2615:
        !          2616:        delay(5000000);         /* 5 seconds */
        !          2617: }
        !          2618:
        !          2619: /*
        !          2620:  * Clear registers on exec
        !          2621:  */
        !          2622: void
        !          2623: setregs(struct proc *p, struct exec_package *pack, u_long stack,
        !          2624:     register_t *retval)
        !          2625: {
        !          2626:        struct pcb *pcb = &p->p_addr->u_pcb;
        !          2627:        struct pmap *pmap = vm_map_pmap(&p->p_vmspace->vm_map);
        !          2628:        struct trapframe *tf = p->p_md.md_regs;
        !          2629:
        !          2630: #if NNPX > 0
        !          2631:        /* If we were using the FPU, forget about it. */
        !          2632:        if (pcb->pcb_fpcpu != NULL)
        !          2633:                npxsave_proc(p, 0);
        !          2634: #endif
        !          2635:
        !          2636: #ifdef USER_LDT
        !          2637:        pmap_ldt_cleanup(p);
        !          2638: #endif
        !          2639:
        !          2640:        /*
        !          2641:         * Reset the code segment limit to I386_MAX_EXE_ADDR in the pmap;
        !          2642:         * this gets copied into the GDT and LDT for {G,L}UCODE_SEL by
        !          2643:         * pmap_activate().
        !          2644:         */
        !          2645:        setsegment(&pmap->pm_codeseg, 0, atop(I386_MAX_EXE_ADDR) - 1,
        !          2646:            SDT_MEMERA, SEL_UPL, 1, 1);
        !          2647:
        !          2648:        /*
        !          2649:         * And update the GDT and LDT since we return to the user process
        !          2650:         * by leaving the syscall (we don't do another pmap_activate()).
        !          2651:         */
        !          2652:        curcpu()->ci_gdt[GUCODE_SEL].sd = pcb->pcb_ldt[LUCODE_SEL].sd =
        !          2653:            pmap->pm_codeseg;
        !          2654:
        !          2655:        /*
        !          2656:         * And reset the hiexec marker in the pmap.
        !          2657:         */
        !          2658:        pmap->pm_hiexec = 0;
        !          2659:
        !          2660:        p->p_md.md_flags &= ~MDP_USEDFPU;
        !          2661:        if (i386_use_fxsave) {
        !          2662:                pcb->pcb_savefpu.sv_xmm.sv_env.en_cw = __OpenBSD_NPXCW__;
        !          2663:                pcb->pcb_savefpu.sv_xmm.sv_env.en_mxcsr = __INITIAL_MXCSR__;
        !          2664:        } else
        !          2665:                pcb->pcb_savefpu.sv_87.sv_env.en_cw = __OpenBSD_NPXCW__;
        !          2666:
        !          2667:        tf->tf_fs = LSEL(LUDATA_SEL, SEL_UPL);
        !          2668:        tf->tf_gs = LSEL(LUDATA_SEL, SEL_UPL);
        !          2669:        tf->tf_es = LSEL(LUDATA_SEL, SEL_UPL);
        !          2670:        tf->tf_ds = LSEL(LUDATA_SEL, SEL_UPL);
        !          2671:        tf->tf_ebp = 0;
        !          2672:        tf->tf_ebx = (int)PS_STRINGS;
        !          2673:        tf->tf_eip = pack->ep_entry;
        !          2674:        tf->tf_cs = LSEL(LUCODE_SEL, SEL_UPL);
        !          2675:        tf->tf_eflags = PSL_USERSET;
        !          2676:        tf->tf_esp = stack;
        !          2677:        tf->tf_ss = LSEL(LUDATA_SEL, SEL_UPL);
        !          2678:
        !          2679:        retval[1] = 0;
        !          2680: }
        !          2681:
        !          2682: /*
        !          2683:  * Initialize segments and descriptor tables
        !          2684:  */
        !          2685:
        !          2686: union descriptor ldt[NLDT];
        !          2687: struct gate_descriptor idt_region[NIDT];
        !          2688: struct gate_descriptor *idt = idt_region;
        !          2689:
        !          2690: extern  struct user *proc0paddr;
        !          2691:
        !          2692: void
        !          2693: setgate(struct gate_descriptor *gd, void *func, int args, int type, int dpl,
        !          2694:     int seg)
        !          2695: {
        !          2696:
        !          2697:        gd->gd_looffset = (int)func;
        !          2698:        gd->gd_selector = GSEL(seg, SEL_KPL);
        !          2699:        gd->gd_stkcpy = args;
        !          2700:        gd->gd_xx = 0;
        !          2701:        gd->gd_type = type;
        !          2702:        gd->gd_dpl = dpl;
        !          2703:        gd->gd_p = 1;
        !          2704:        gd->gd_hioffset = (int)func >> 16;
        !          2705: }
        !          2706:
        !          2707: void
        !          2708: unsetgate(struct gate_descriptor *gd)
        !          2709: {
        !          2710:        gd->gd_p = 0;
        !          2711:        gd->gd_hioffset = 0;
        !          2712:        gd->gd_looffset = 0;
        !          2713:        gd->gd_selector = 0;
        !          2714:        gd->gd_xx = 0;
        !          2715:        gd->gd_stkcpy = 0;
        !          2716:        gd->gd_type = 0;
        !          2717:        gd->gd_dpl = 0;
        !          2718: }
        !          2719:
        !          2720: void
        !          2721: setregion(struct region_descriptor *rd, void *base, size_t limit)
        !          2722: {
        !          2723:
        !          2724:        rd->rd_limit = (int)limit;
        !          2725:        rd->rd_base = (int)base;
        !          2726: }
        !          2727:
        !          2728: void
        !          2729: setsegment(struct segment_descriptor *sd, void *base, size_t limit, int type,
        !          2730:     int dpl, int def32, int gran)
        !          2731: {
        !          2732:
        !          2733:        sd->sd_lolimit = (int)limit;
        !          2734:        sd->sd_lobase = (int)base;
        !          2735:        sd->sd_type = type;
        !          2736:        sd->sd_dpl = dpl;
        !          2737:        sd->sd_p = 1;
        !          2738:        sd->sd_hilimit = (int)limit >> 16;
        !          2739:        sd->sd_xx = 0;
        !          2740:        sd->sd_def32 = def32;
        !          2741:        sd->sd_gran = gran;
        !          2742:        sd->sd_hibase = (int)base >> 24;
        !          2743: }
        !          2744:
        !          2745: #define        IDTVEC(name)    __CONCAT(X, name)
        !          2746: extern int IDTVEC(div), IDTVEC(dbg), IDTVEC(nmi), IDTVEC(bpt), IDTVEC(ofl),
        !          2747:     IDTVEC(bnd), IDTVEC(ill), IDTVEC(dna), IDTVEC(dble), IDTVEC(fpusegm),
        !          2748:     IDTVEC(tss), IDTVEC(missing), IDTVEC(stk), IDTVEC(prot), IDTVEC(page),
        !          2749:     IDTVEC(rsvd), IDTVEC(fpu), IDTVEC(align), IDTVEC(syscall), IDTVEC(mchk),
        !          2750:     IDTVEC(osyscall), IDTVEC(simd);
        !          2751:
        !          2752: #if defined(I586_CPU)
        !          2753: extern int IDTVEC(f00f_redirect);
        !          2754:
        !          2755: int cpu_f00f_bug = 0;
        !          2756:
        !          2757: void
        !          2758: fix_f00f(void)
        !          2759: {
        !          2760:        struct region_descriptor region;
        !          2761:        vaddr_t va;
        !          2762:        void *p;
        !          2763:        pt_entry_t *pte;
        !          2764:
        !          2765:        /* Allocate two new pages */
        !          2766:        va = uvm_km_zalloc(kernel_map, NBPG*2);
        !          2767:        p = (void *)(va + NBPG - 7*sizeof(*idt));
        !          2768:
        !          2769:        /* Copy over old IDT */
        !          2770:        bcopy(idt, p, sizeof(idt_region));
        !          2771:        idt = p;
        !          2772:
        !          2773:        /* Fix up paging redirect */
        !          2774:        setgate(&idt[ 14], &IDTVEC(f00f_redirect), 0, SDT_SYS386TGT, SEL_KPL,
        !          2775:            GCODE_SEL);
        !          2776:
        !          2777:        /* Map first page RO */
        !          2778:        pte = PTE_BASE + atop(va);
        !          2779:        *pte &= ~PG_RW;
        !          2780:
        !          2781:        /* Reload idtr */
        !          2782:        setregion(&region, idt, sizeof(idt_region) - 1);
        !          2783:        lidt(&region);
        !          2784:
        !          2785:        /* Tell the rest of the world */
        !          2786:        cpu_f00f_bug = 1;
        !          2787: }
        !          2788: #endif
        !          2789:
        !          2790: #ifdef MULTIPROCESSOR
        !          2791: void
        !          2792: cpu_init_idt()
        !          2793: {
        !          2794:        struct region_descriptor region;
        !          2795:        setregion(&region, idt, NIDT * sizeof(idt[0]) - 1);
        !          2796:        lidt(&region);
        !          2797: }
        !          2798:
        !          2799: void
        !          2800: cpu_default_ldt(struct cpu_info *ci)
        !          2801: {
        !          2802:        ci->ci_ldt = ldt;
        !          2803:        ci->ci_ldt_len = sizeof(ldt);
        !          2804: }
        !          2805:
        !          2806: void
        !          2807: cpu_alloc_ldt(struct cpu_info *ci)
        !          2808: {
        !          2809:        union descriptor *cpu_ldt;
        !          2810:        size_t len = sizeof(ldt);
        !          2811:
        !          2812:        cpu_ldt = (union descriptor *)uvm_km_alloc(kernel_map, len);
        !          2813:        bcopy(ldt, cpu_ldt, len);
        !          2814:        ci->ci_ldt = cpu_ldt;
        !          2815:        ci->ci_ldt_len = len;
        !          2816: }
        !          2817:
        !          2818: void
        !          2819: cpu_init_ldt(struct cpu_info *ci)
        !          2820: {
        !          2821:        setsegment(&ci->ci_gdt[GLDT_SEL].sd, ci->ci_ldt, ci->ci_ldt_len - 1,
        !          2822:            SDT_SYSLDT, SEL_KPL, 0, 0);
        !          2823: }
        !          2824: #endif /* MULTIPROCESSOR */
        !          2825:
        !          2826: void
        !          2827: init386(paddr_t first_avail)
        !          2828: {
        !          2829:        int i, kb;
        !          2830:        struct region_descriptor region;
        !          2831:        bios_memmap_t *im;
        !          2832:
        !          2833:        proc0.p_addr = proc0paddr;
        !          2834:        cpu_info_primary.ci_self = &cpu_info_primary;
        !          2835:        cpu_info_primary.ci_curpcb = &proc0.p_addr->u_pcb;
        !          2836:
        !          2837:        /*
        !          2838:         * Initialize the I/O port and I/O mem extent maps.
        !          2839:         * Note: we don't have to check the return value since
        !          2840:         * creation of a fixed extent map will never fail (since
        !          2841:         * descriptor storage has already been allocated).
        !          2842:         *
        !          2843:         * N.B. The iomem extent manages _all_ physical addresses
        !          2844:         * on the machine.  When the amount of RAM is found, the two
        !          2845:         * extents of RAM are allocated from the map (0 -> ISA hole
        !          2846:         * and end of ISA hole -> end of RAM).
        !          2847:         */
        !          2848:        ioport_ex = extent_create("ioport", 0x0, 0xffff, M_DEVBUF,
        !          2849:            (caddr_t)ioport_ex_storage, sizeof(ioport_ex_storage),
        !          2850:            EX_NOCOALESCE|EX_NOWAIT);
        !          2851:        iomem_ex = extent_create("iomem", 0x0, 0xffffffff, M_DEVBUF,
        !          2852:            (caddr_t)iomem_ex_storage, sizeof(iomem_ex_storage),
        !          2853:            EX_NOCOALESCE|EX_NOWAIT);
        !          2854:
        !          2855:        /* make bootstrap gdt gates and memory segments */
        !          2856:        setsegment(&gdt[GCODE_SEL].sd, 0, 0xfffff, SDT_MEMERA, SEL_KPL, 1, 1);
        !          2857:        setsegment(&gdt[GICODE_SEL].sd, 0, 0xfffff, SDT_MEMERA, SEL_KPL, 1, 1);
        !          2858:        setsegment(&gdt[GDATA_SEL].sd, 0, 0xfffff, SDT_MEMRWA, SEL_KPL, 1, 1);
        !          2859:        setsegment(&gdt[GLDT_SEL].sd, ldt, sizeof(ldt) - 1, SDT_SYSLDT,
        !          2860:            SEL_KPL, 0, 0);
        !          2861:        setsegment(&gdt[GUCODE_SEL].sd, 0, atop(I386_MAX_EXE_ADDR) - 1,
        !          2862:            SDT_MEMERA, SEL_UPL, 1, 1);
        !          2863:        setsegment(&gdt[GUDATA_SEL].sd, 0, atop(VM_MAXUSER_ADDRESS) - 1,
        !          2864:            SDT_MEMRWA, SEL_UPL, 1, 1);
        !          2865:        setsegment(&gdt[GCPU_SEL].sd, &cpu_info_primary,
        !          2866:            sizeof(struct cpu_info)-1, SDT_MEMRWA, SEL_KPL, 0, 0);
        !          2867:
        !          2868:        /* make ldt gates and memory segments */
        !          2869:        setgate(&ldt[LSYS5CALLS_SEL].gd, &IDTVEC(osyscall), 1, SDT_SYS386CGT,
        !          2870:            SEL_UPL, GCODE_SEL);
        !          2871:        ldt[LUCODE_SEL] = gdt[GUCODE_SEL];
        !          2872:        ldt[LUDATA_SEL] = gdt[GUDATA_SEL];
        !          2873:        ldt[LBSDICALLS_SEL] = ldt[LSYS5CALLS_SEL];
        !          2874:
        !          2875:        /* exceptions */
        !          2876:        setgate(&idt[  0], &IDTVEC(div),     0, SDT_SYS386TGT, SEL_KPL, GCODE_SEL);
        !          2877:        setgate(&idt[  1], &IDTVEC(dbg),     0, SDT_SYS386TGT, SEL_KPL, GCODE_SEL);
        !          2878:        setgate(&idt[  2], &IDTVEC(nmi),     0, SDT_SYS386TGT, SEL_KPL, GCODE_SEL);
        !          2879:        setgate(&idt[  3], &IDTVEC(bpt),     0, SDT_SYS386TGT, SEL_UPL, GCODE_SEL);
        !          2880:        setgate(&idt[  4], &IDTVEC(ofl),     0, SDT_SYS386TGT, SEL_UPL, GCODE_SEL);
        !          2881:        setgate(&idt[  5], &IDTVEC(bnd),     0, SDT_SYS386TGT, SEL_KPL, GCODE_SEL);
        !          2882:        setgate(&idt[  6], &IDTVEC(ill),     0, SDT_SYS386TGT, SEL_KPL, GCODE_SEL);
        !          2883:        setgate(&idt[  7], &IDTVEC(dna),     0, SDT_SYS386TGT, SEL_KPL, GCODE_SEL);
        !          2884:        setgate(&idt[  8], &IDTVEC(dble),    0, SDT_SYS386TGT, SEL_KPL, GCODE_SEL);
        !          2885:        setgate(&idt[  9], &IDTVEC(fpusegm), 0, SDT_SYS386TGT, SEL_KPL, GCODE_SEL);
        !          2886:        setgate(&idt[ 10], &IDTVEC(tss),     0, SDT_SYS386TGT, SEL_KPL, GCODE_SEL);
        !          2887:        setgate(&idt[ 11], &IDTVEC(missing), 0, SDT_SYS386TGT, SEL_KPL, GCODE_SEL);
        !          2888:        setgate(&idt[ 12], &IDTVEC(stk),     0, SDT_SYS386TGT, SEL_KPL, GCODE_SEL);
        !          2889:        setgate(&idt[ 13], &IDTVEC(prot),    0, SDT_SYS386TGT, SEL_KPL, GCODE_SEL);
        !          2890:        setgate(&idt[ 14], &IDTVEC(page),    0, SDT_SYS386TGT, SEL_KPL, GCODE_SEL);
        !          2891:        setgate(&idt[ 15], &IDTVEC(rsvd),    0, SDT_SYS386TGT, SEL_KPL, GCODE_SEL);
        !          2892:        setgate(&idt[ 16], &IDTVEC(fpu),     0, SDT_SYS386TGT, SEL_KPL, GCODE_SEL);
        !          2893:        setgate(&idt[ 17], &IDTVEC(align),   0, SDT_SYS386TGT, SEL_KPL, GCODE_SEL);
        !          2894:        setgate(&idt[ 18], &IDTVEC(mchk),    0, SDT_SYS386TGT, SEL_KPL, GCODE_SEL);
        !          2895:        setgate(&idt[ 19], &IDTVEC(simd),    0, SDT_SYS386TGT, SEL_KPL, GCODE_SEL);
        !          2896:        for (i = 20; i < NRSVIDT; i++)
        !          2897:                setgate(&idt[i], &IDTVEC(rsvd), 0, SDT_SYS386TGT, SEL_KPL, GCODE_SEL);
        !          2898:        for (i = NRSVIDT; i < NIDT; i++)
        !          2899:                unsetgate(&idt[i]);
        !          2900:        setgate(&idt[128], &IDTVEC(syscall), 0, SDT_SYS386TGT, SEL_UPL, GCODE_SEL);
        !          2901:
        !          2902:        setregion(&region, gdt, NGDT * sizeof(union descriptor) - 1);
        !          2903:        lgdt(&region);
        !          2904:        setregion(&region, idt, sizeof(idt_region) - 1);
        !          2905:        lidt(&region);
        !          2906:
        !          2907: #if NISA > 0
        !          2908:        isa_defaultirq();
        !          2909: #endif
        !          2910:
        !          2911:        consinit();     /* XXX SHOULD NOT BE DONE HERE */
        !          2912:                        /* XXX here, until we can use bios for printfs */
        !          2913:
        !          2914:        /*
        !          2915:         * Saving SSE registers won't work if the save area isn't
        !          2916:         * 16-byte aligned.
        !          2917:         */
        !          2918:        if (offsetof(struct user, u_pcb.pcb_savefpu) & 0xf)
        !          2919:                panic("init386: pcb_savefpu not 16-byte aligned");
        !          2920:
        !          2921:        /* call pmap initialization to make new kernel address space */
        !          2922:        pmap_bootstrap((vaddr_t)atdevbase + IOM_SIZE);
        !          2923:
        !          2924:        /*
        !          2925:         * Boot arguments are in a single page specified by /boot.
        !          2926:         *
        !          2927:         * We require the "new" vector form, as well as memory ranges
        !          2928:         * to be given in bytes rather than KB.
        !          2929:         */
        !          2930:        if ((bootapiver & (BAPIV_VECTOR | BAPIV_BMEMMAP)) ==
        !          2931:            (BAPIV_VECTOR | BAPIV_BMEMMAP)) {
        !          2932:                if (bootargc > NBPG)
        !          2933:                        panic("too many boot args");
        !          2934:
        !          2935:                if (extent_alloc_region(iomem_ex, (paddr_t)bootargv, bootargc,
        !          2936:                    EX_NOWAIT))
        !          2937:                        panic("cannot reserve /boot args memory");
        !          2938:
        !          2939:                pmap_enter(pmap_kernel(), (vaddr_t)bootargp, (paddr_t)bootargv,
        !          2940:                    VM_PROT_READ|VM_PROT_WRITE,
        !          2941:                    VM_PROT_READ|VM_PROT_WRITE|PMAP_WIRED);
        !          2942:
        !          2943:                bios_getopt();
        !          2944:
        !          2945:        } else
        !          2946:                panic("/boot too old: upgrade!");
        !          2947:
        !          2948: #ifdef DIAGNOSTIC
        !          2949:        if (bios_memmap == NULL)
        !          2950:                panic("no BIOS memory map supplied");
        !          2951: #endif
        !          2952:
        !          2953: #if defined(MULTIPROCESSOR)
        !          2954:        /* install the page after boot args as PT page for first 4M */
        !          2955:        pmap_enter(pmap_kernel(), (u_long)vtopte(0),
        !          2956:           round_page((vaddr_t)(bootargv + bootargc)),
        !          2957:                VM_PROT_READ|VM_PROT_WRITE,
        !          2958:                VM_PROT_READ|VM_PROT_WRITE|PMAP_WIRED);
        !          2959:        memset(vtopte(0), 0, NBPG);  /* make sure it is clean before using */
        !          2960: #endif
        !          2961:
        !          2962:        /*
        !          2963:         * account all the memory passed in the map from /boot
        !          2964:         * calculate avail_end and count the physmem.
        !          2965:         */
        !          2966:        avail_end = 0;
        !          2967:        physmem = 0;
        !          2968: #ifdef DEBUG
        !          2969:        printf("memmap:");
        !          2970: #endif
        !          2971:        for(i = 0, im = bios_memmap; im->type != BIOS_MAP_END; im++)
        !          2972:                if (im->type == BIOS_MAP_FREE) {
        !          2973:                        paddr_t a, e;
        !          2974: #ifdef DEBUG
        !          2975:                        printf(" %llx-%llx", im->addr, im->addr + im->size);
        !          2976: #endif
        !          2977:
        !          2978:                        if (im->addr >= 0x100000000ULL) {
        !          2979: #ifdef DEBUG
        !          2980:                                printf("-H");
        !          2981: #endif
        !          2982:                                continue;
        !          2983:                        }
        !          2984:
        !          2985:                        a = round_page(im->addr);
        !          2986:                        if (im->addr + im->size <= 0xfffff000ULL)
        !          2987:                                e = trunc_page(im->addr + im->size);
        !          2988:                        else {
        !          2989: #ifdef DEBUG
        !          2990:                                printf("-T");
        !          2991: #endif
        !          2992:                                e = 0xfffff000;
        !          2993:                        }
        !          2994:
        !          2995:                        /* skip first eight pages */
        !          2996:                        if (a < 8 * NBPG)
        !          2997:                                a = 8 * NBPG;
        !          2998:
        !          2999:                        /* skip shorter than page regions */
        !          3000:                        if (a >= e || (e - a) < NBPG) {
        !          3001: #ifdef DEBUG
        !          3002:                                printf("-S");
        !          3003: #endif
        !          3004:                                continue;
        !          3005:                        }
        !          3006:                        if ((a > IOM_BEGIN && a < IOM_END) ||
        !          3007:                            (e > IOM_BEGIN && e < IOM_END)) {
        !          3008: #ifdef DEBUG
        !          3009:                                printf("-I");
        !          3010: #endif
        !          3011:                                continue;
        !          3012:                        }
        !          3013:
        !          3014:                        if (extent_alloc_region(iomem_ex, a, e - a, EX_NOWAIT))
        !          3015:                                /* XXX What should we do? */
        !          3016:                                printf("\nWARNING: CAN'T ALLOCATE RAM (%x-%x)"
        !          3017:                                    " FROM IOMEM EXTENT MAP!\n", a, e);
        !          3018:
        !          3019:                        physmem += atop(e - a);
        !          3020:                        dumpmem[i].start = atop(a);
        !          3021:                        dumpmem[i].end = atop(e);
        !          3022:                        i++;
        !          3023:                        avail_end = max(avail_end, e);
        !          3024:                }
        !          3025:
        !          3026:        ndumpmem = i;
        !          3027:        avail_end -= round_page(MSGBUFSIZE);
        !          3028:
        !          3029: #ifdef DEBUG
        !          3030:        printf(": %lx\n", avail_end);
        !          3031: #endif
        !          3032:        if (physmem < atop(4 * 1024 * 1024)) {
        !          3033:                printf("\awarning: too little memory available;"
        !          3034:                    "running in degraded mode\npress a key to confirm\n\n");
        !          3035:                cngetc();
        !          3036:        }
        !          3037:
        !          3038: #ifdef DEBUG
        !          3039:        printf("physload: ");
        !          3040: #endif
        !          3041:        kb = atop(KERNTEXTOFF - KERNBASE);
        !          3042:        if (kb > atop(0x100000)) {
        !          3043:                paddr_t lim = atop(0x100000);
        !          3044: #ifdef DEBUG
        !          3045:                printf(" %x-%x (<16M)", lim, kb);
        !          3046: #endif
        !          3047:                uvm_page_physload(lim, kb, lim, kb, VM_FREELIST_FIRST16);
        !          3048:        }
        !          3049:
        !          3050:        for (i = 0; i < ndumpmem; i++) {
        !          3051:                paddr_t a, e;
        !          3052:                paddr_t lim;
        !          3053:
        !          3054:                a = dumpmem[i].start;
        !          3055:                e = dumpmem[i].end;
        !          3056:                if (a < atop(first_avail) && e > atop(first_avail))
        !          3057:                        a = atop(first_avail);
        !          3058:                if (e > atop(avail_end))
        !          3059:                        e = atop(avail_end);
        !          3060:
        !          3061:                if (a < e) {
        !          3062:                        if (a < atop(16 * 1024 * 1024)) {
        !          3063:                                lim = MIN(atop(16 * 1024 * 1024), e);
        !          3064: #ifdef DEBUG
        !          3065: -                              printf(" %x-%x (<16M)", a, lim);
        !          3066: #endif
        !          3067:                                uvm_page_physload(a, lim, a, lim,
        !          3068:                                    VM_FREELIST_FIRST16);
        !          3069:                                if (e > lim) {
        !          3070: #ifdef DEBUG
        !          3071: -                                      printf(" %x-%x", lim, e);
        !          3072: #endif
        !          3073:                                        uvm_page_physload(lim, e, lim, e,
        !          3074:                                            VM_FREELIST_DEFAULT);
        !          3075:                                }
        !          3076:                        } else {
        !          3077: #ifdef DEBUG
        !          3078: -                              printf(" %x-%x", a, e);
        !          3079: #endif
        !          3080:                                uvm_page_physload(a, e, a, e,
        !          3081:                                    VM_FREELIST_DEFAULT);
        !          3082:                        }
        !          3083:                }
        !          3084:        }
        !          3085: #ifdef DEBUG
        !          3086:        printf("\n");
        !          3087: #endif
        !          3088:        tlbflush();
        !          3089: #if 0
        !          3090: #if NISADMA > 0
        !          3091:        /*
        !          3092:         * Some motherboards/BIOSes remap the 384K of RAM that would
        !          3093:         * normally be covered by the ISA hole to the end of memory
        !          3094:         * so that it can be used.  However, on a 16M system, this
        !          3095:         * would cause bounce buffers to be allocated and used.
        !          3096:         * This is not desirable behaviour, as more than 384K of
        !          3097:         * bounce buffers might be allocated.  As a work-around,
        !          3098:         * we round memory down to the nearest 1M boundary if
        !          3099:         * we're using any isadma devices and the remapped memory
        !          3100:         * is what puts us over 16M.
        !          3101:         */
        !          3102:        if (extmem > (15*1024) && extmem < (16*1024)) {
        !          3103:                printf("Warning: ignoring %dk of remapped memory\n",
        !          3104:                    extmem - (15*1024));
        !          3105:                extmem = (15*1024);
        !          3106:        }
        !          3107: #endif
        !          3108: #endif
        !          3109:
        !          3110: #ifdef DDB
        !          3111:        db_machine_init();
        !          3112:        ddb_init();
        !          3113:        if (boothowto & RB_KDB)
        !          3114:                Debugger();
        !          3115: #endif
        !          3116: #ifdef KGDB
        !          3117:        kgdb_port_init();
        !          3118:        if (boothowto & RB_KDB) {
        !          3119:                kgdb_debug_init = 1;
        !          3120:                kgdb_connect(1);
        !          3121:        }
        !          3122: #endif /* KGDB */
        !          3123: }
        !          3124:
        !          3125: /*
        !          3126:  * cpu_exec_aout_makecmds():
        !          3127:  *     cpu-dependent a.out format hook for execve().
        !          3128:  *
        !          3129:  * Determine of the given exec package refers to something which we
        !          3130:  * understand and, if so, set up the vmcmds for it.
        !          3131:  */
        !          3132: int
        !          3133: cpu_exec_aout_makecmds(struct proc *p, struct exec_package *epp)
        !          3134: {
        !          3135:        return ENOEXEC;
        !          3136: }
        !          3137:
        !          3138: /*
        !          3139:  * consinit:
        !          3140:  * initialize the system console.
        !          3141:  * XXX - shouldn't deal with this initted thing, but then,
        !          3142:  * it shouldn't be called from init386 either.
        !          3143:  */
        !          3144: void
        !          3145: consinit()
        !          3146: {
        !          3147:        static int initted;
        !          3148:
        !          3149:        if (initted)
        !          3150:                return;
        !          3151:        initted = 1;
        !          3152:        cninit();
        !          3153: }
        !          3154:
        !          3155: #ifdef KGDB
        !          3156: void
        !          3157: kgdb_port_init()
        !          3158: {
        !          3159:
        !          3160: #if (NCOM > 0 || NPCCOM > 0)
        !          3161:        if (!strcmp(kgdb_devname, "com") || !strcmp(kgdb_devname, "pccom")) {
        !          3162:                bus_space_tag_t tag = I386_BUS_SPACE_IO;
        !          3163:                com_kgdb_attach(tag, comkgdbaddr, comkgdbrate, COM_FREQ,
        !          3164:                    comkgdbmode);
        !          3165:        }
        !          3166: #endif
        !          3167: }
        !          3168: #endif /* KGDB */
        !          3169:
        !          3170: void
        !          3171: cpu_reset()
        !          3172: {
        !          3173:        struct region_descriptor region;
        !          3174:
        !          3175:        disable_intr();
        !          3176:
        !          3177:        if (cpuresetfn)
        !          3178:                (*cpuresetfn)();
        !          3179:
        !          3180:        /*
        !          3181:         * The keyboard controller has 4 random output pins, one of which is
        !          3182:         * connected to the RESET pin on the CPU in many PCs.  We tell the
        !          3183:         * keyboard controller to pulse this line a couple of times.
        !          3184:         */
        !          3185:        outb(IO_KBD + KBCMDP, KBC_PULSE0);
        !          3186:        delay(100000);
        !          3187:        outb(IO_KBD + KBCMDP, KBC_PULSE0);
        !          3188:        delay(100000);
        !          3189:
        !          3190:        /*
        !          3191:         * Try to cause a triple fault and watchdog reset by setting the
        !          3192:         * IDT to point to nothing.
        !          3193:         */
        !          3194:        bzero((caddr_t)idt, sizeof(idt_region));
        !          3195:        setregion(&region, idt, sizeof(idt_region) - 1);
        !          3196:        lidt(&region);
        !          3197:        __asm __volatile("divl %0,%1" : : "q" (0), "a" (0));
        !          3198:
        !          3199: #if 1
        !          3200:        /*
        !          3201:         * Try to cause a triple fault and watchdog reset by unmapping the
        !          3202:         * entire address space.
        !          3203:         */
        !          3204:        bzero((caddr_t)PTD, NBPG);
        !          3205:        tlbflush();
        !          3206: #endif
        !          3207:
        !          3208:        for (;;);
        !          3209: }
        !          3210:
        !          3211: void
        !          3212: cpu_initclocks(void)
        !          3213: {
        !          3214:        (*initclock_func)();
        !          3215:
        !          3216:        if (initclock_func == i8254_initclocks)
        !          3217:                i8254_inittimecounter();
        !          3218:        else
        !          3219:                i8254_inittimecounter_simple();
        !          3220: }
        !          3221:
        !          3222: void
        !          3223: need_resched(struct cpu_info *ci)
        !          3224: {
        !          3225:        struct proc *p;
        !          3226:
        !          3227:        ci->ci_want_resched = 1;
        !          3228:
        !          3229:        /*
        !          3230:         * Need to catch the curproc in case it's cleared just
        !          3231:         * between the check and the aston().
        !          3232:         */
        !          3233:        if ((p = ci->ci_curproc) != NULL)
        !          3234:                aston(p);
        !          3235: }
        !          3236:
        !          3237: #ifdef MULTIPROCESSOR
        !          3238: /* Allocate an IDT vector slot within the given range.
        !          3239:  * XXX needs locking to avoid MP allocation races.
        !          3240:  */
        !          3241:
        !          3242: int
        !          3243: idt_vec_alloc(int low, int high)
        !          3244: {
        !          3245:        int vec;
        !          3246:
        !          3247:        for (vec = low; vec <= high; vec++)
        !          3248:                if (idt[vec].gd_p == 0)
        !          3249:                        return (vec);
        !          3250:        return (0);
        !          3251: }
        !          3252:
        !          3253: void
        !          3254: idt_vec_set(int vec, void (*function)(void))
        !          3255: {
        !          3256:        setgate(&idt[vec], function, 0, SDT_SYS386IGT, SEL_KPL, GCODE_SEL);
        !          3257: }
        !          3258:
        !          3259: void
        !          3260: idt_vec_free(int vec)
        !          3261: {
        !          3262:        unsetgate(&idt[vec]);
        !          3263: }
        !          3264: #endif /* MULTIPROCESSOR */
        !          3265:
        !          3266: /*
        !          3267:  * machine dependent system variables.
        !          3268:  */
        !          3269: int
        !          3270: cpu_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
        !          3271:     size_t newlen, struct proc *p)
        !          3272: {
        !          3273:        dev_t dev;
        !          3274:
        !          3275:        switch (name[0]) {
        !          3276:        case CPU_CONSDEV:
        !          3277:                if (namelen != 1)
        !          3278:                        return (ENOTDIR);               /* overloaded */
        !          3279:
        !          3280:                if (cn_tab != NULL)
        !          3281:                        dev = cn_tab->cn_dev;
        !          3282:                else
        !          3283:                        dev = NODEV;
        !          3284:                return sysctl_rdstruct(oldp, oldlenp, newp, &dev, sizeof(dev));
        !          3285: #if NBIOS > 0
        !          3286:        case CPU_BIOS:
        !          3287:                return bios_sysctl(name + 1, namelen - 1, oldp, oldlenp,
        !          3288:                    newp, newlen, p);
        !          3289: #endif
        !          3290:        case CPU_BLK2CHR:
        !          3291:                if (namelen != 2)
        !          3292:                        return (ENOTDIR);               /* overloaded */
        !          3293:                dev = blktochr((dev_t)name[1]);
        !          3294:                return sysctl_rdstruct(oldp, oldlenp, newp, &dev, sizeof(dev));
        !          3295:        case CPU_CHR2BLK:
        !          3296:                if (namelen != 2)
        !          3297:                        return (ENOTDIR);               /* overloaded */
        !          3298:                dev = chrtoblk((dev_t)name[1]);
        !          3299:                return sysctl_rdstruct(oldp, oldlenp, newp, &dev, sizeof(dev));
        !          3300:        case CPU_ALLOWAPERTURE:
        !          3301: #ifdef APERTURE
        !          3302:                if (securelevel > 0)
        !          3303:                        return (sysctl_int_lower(oldp, oldlenp, newp, newlen,
        !          3304:                            &allowaperture));
        !          3305:                else
        !          3306:                        return (sysctl_int(oldp, oldlenp, newp, newlen,
        !          3307:                            &allowaperture));
        !          3308: #else
        !          3309:                return (sysctl_rdint(oldp, oldlenp, newp, 0));
        !          3310: #endif
        !          3311:        case CPU_CPUVENDOR:
        !          3312:                return (sysctl_rdstring(oldp, oldlenp, newp, cpu_vendor));
        !          3313:        case CPU_CPUID:
        !          3314:                return (sysctl_rdint(oldp, oldlenp, newp, cpu_id));
        !          3315:        case CPU_CPUFEATURE:
        !          3316:                return (sysctl_rdint(oldp, oldlenp, newp, curcpu()->ci_feature_flags));
        !          3317: #if NAPM > 0
        !          3318:        case CPU_APMWARN:
        !          3319:                return (sysctl_int(oldp, oldlenp, newp, newlen, &cpu_apmwarn));
        !          3320:        case CPU_APMHALT:
        !          3321:                return (sysctl_int(oldp, oldlenp, newp, newlen, &cpu_apmhalt));
        !          3322: #endif
        !          3323:        case CPU_KBDRESET:
        !          3324:                if (securelevel > 0)
        !          3325:                        return (sysctl_rdint(oldp, oldlenp, newp,
        !          3326:                            kbd_reset));
        !          3327:                else
        !          3328:                        return (sysctl_int(oldp, oldlenp, newp, newlen,
        !          3329:                            &kbd_reset));
        !          3330: #ifdef USER_LDT
        !          3331:        case CPU_USERLDT:
        !          3332:                return (sysctl_int(oldp, oldlenp, newp, newlen,
        !          3333:                    &user_ldt_enable));
        !          3334: #endif
        !          3335:        case CPU_OSFXSR:
        !          3336:                return (sysctl_rdint(oldp, oldlenp, newp, i386_use_fxsave));
        !          3337:        case CPU_SSE:
        !          3338:                return (sysctl_rdint(oldp, oldlenp, newp, i386_has_sse));
        !          3339:        case CPU_SSE2:
        !          3340:                return (sysctl_rdint(oldp, oldlenp, newp, i386_has_sse2));
        !          3341:        case CPU_XCRYPT:
        !          3342:                return (sysctl_rdint(oldp, oldlenp, newp, i386_has_xcrypt));
        !          3343:        default:
        !          3344:                return (EOPNOTSUPP);
        !          3345:        }
        !          3346:        /* NOTREACHED */
        !          3347: }
        !          3348:
        !          3349: int
        !          3350: bus_space_map(bus_space_tag_t t, bus_addr_t bpa, bus_size_t size, int cacheable,
        !          3351:     bus_space_handle_t *bshp)
        !          3352: {
        !          3353:        int error;
        !          3354:        struct extent *ex;
        !          3355:
        !          3356:        /*
        !          3357:         * Pick the appropriate extent map.
        !          3358:         */
        !          3359:        switch (t) {
        !          3360:        case I386_BUS_SPACE_IO:
        !          3361:                ex = ioport_ex;
        !          3362:                break;
        !          3363:
        !          3364:        case I386_BUS_SPACE_MEM:
        !          3365:                ex = iomem_ex;
        !          3366:                break;
        !          3367:
        !          3368:        default:
        !          3369:                panic("bus_space_map: bad bus space tag");
        !          3370:        }
        !          3371:
        !          3372:        /*
        !          3373:         * Before we go any further, let's make sure that this
        !          3374:         * region is available.
        !          3375:         */
        !          3376:        error = extent_alloc_region(ex, bpa, size,
        !          3377:            EX_NOWAIT | (ioport_malloc_safe ? EX_MALLOCOK : 0));
        !          3378:        if (error)
        !          3379:                return (error);
        !          3380:
        !          3381:        /*
        !          3382:         * For I/O space, that's all she wrote.
        !          3383:         */
        !          3384:        if (t == I386_BUS_SPACE_IO) {
        !          3385:                *bshp = bpa;
        !          3386:                return (0);
        !          3387:        }
        !          3388:
        !          3389:        if (IOM_BEGIN <= bpa && bpa <= IOM_END) {
        !          3390:                *bshp = (bus_space_handle_t)ISA_HOLE_VADDR(bpa);
        !          3391:                return (0);
        !          3392:        }
        !          3393:
        !          3394:        /*
        !          3395:         * For memory space, map the bus physical address to
        !          3396:         * a kernel virtual address.
        !          3397:         */
        !          3398:        error = bus_mem_add_mapping(bpa, size, cacheable, bshp);
        !          3399:        if (error) {
        !          3400:                if (extent_free(ex, bpa, size, EX_NOWAIT |
        !          3401:                    (ioport_malloc_safe ? EX_MALLOCOK : 0))) {
        !          3402:                        printf("bus_space_map: pa 0x%lx, size 0x%lx\n",
        !          3403:                            bpa, size);
        !          3404:                        printf("bus_space_map: can't free region\n");
        !          3405:                }
        !          3406:        }
        !          3407:
        !          3408:        return (error);
        !          3409: }
        !          3410:
        !          3411: int
        !          3412: _bus_space_map(bus_space_tag_t t, bus_addr_t bpa, bus_size_t size,
        !          3413:     int cacheable, bus_space_handle_t *bshp)
        !          3414: {
        !          3415:        /*
        !          3416:         * For I/O space, that's all she wrote.
        !          3417:         */
        !          3418:        if (t == I386_BUS_SPACE_IO) {
        !          3419:                *bshp = bpa;
        !          3420:                return (0);
        !          3421:        }
        !          3422:
        !          3423:        /*
        !          3424:         * For memory space, map the bus physical address to
        !          3425:         * a kernel virtual address.
        !          3426:         */
        !          3427:        return (bus_mem_add_mapping(bpa, size, cacheable, bshp));
        !          3428: }
        !          3429:
        !          3430: int
        !          3431: bus_space_alloc(bus_space_tag_t t, bus_addr_t rstart, bus_addr_t rend,
        !          3432:     bus_size_t size, bus_size_t alignment, bus_size_t boundary,
        !          3433:     int cacheable, bus_addr_t *bpap, bus_space_handle_t *bshp)
        !          3434: {
        !          3435:        struct extent *ex;
        !          3436:        u_long bpa;
        !          3437:        int error;
        !          3438:
        !          3439:        /*
        !          3440:         * Pick the appropriate extent map.
        !          3441:         */
        !          3442:        switch (t) {
        !          3443:        case I386_BUS_SPACE_IO:
        !          3444:                ex = ioport_ex;
        !          3445:                break;
        !          3446:
        !          3447:        case I386_BUS_SPACE_MEM:
        !          3448:                ex = iomem_ex;
        !          3449:                break;
        !          3450:
        !          3451:        default:
        !          3452:                panic("bus_space_alloc: bad bus space tag");
        !          3453:        }
        !          3454:
        !          3455:        /*
        !          3456:         * Sanity check the allocation against the extent's boundaries.
        !          3457:         */
        !          3458:        if (rstart < ex->ex_start || rend > ex->ex_end)
        !          3459:                panic("bus_space_alloc: bad region start/end");
        !          3460:
        !          3461:        /*
        !          3462:         * Do the requested allocation.
        !          3463:         */
        !          3464:        error = extent_alloc_subregion(ex, rstart, rend, size, alignment, 0,
        !          3465:            boundary, EX_NOWAIT | (ioport_malloc_safe ?  EX_MALLOCOK : 0),
        !          3466:            &bpa);
        !          3467:
        !          3468:        if (error)
        !          3469:                return (error);
        !          3470:
        !          3471:        /*
        !          3472:         * For I/O space, that's all she wrote.
        !          3473:         */
        !          3474:        if (t == I386_BUS_SPACE_IO) {
        !          3475:                *bshp = *bpap = bpa;
        !          3476:                return (0);
        !          3477:        }
        !          3478:
        !          3479:        /*
        !          3480:         * For memory space, map the bus physical address to
        !          3481:         * a kernel virtual address.
        !          3482:         */
        !          3483:        error = bus_mem_add_mapping(bpa, size, cacheable, bshp);
        !          3484:        if (error) {
        !          3485:                if (extent_free(iomem_ex, bpa, size, EX_NOWAIT |
        !          3486:                    (ioport_malloc_safe ? EX_MALLOCOK : 0))) {
        !          3487:                        printf("bus_space_alloc: pa 0x%lx, size 0x%lx\n",
        !          3488:                            bpa, size);
        !          3489:                        printf("bus_space_alloc: can't free region\n");
        !          3490:                }
        !          3491:        }
        !          3492:
        !          3493:        *bpap = bpa;
        !          3494:
        !          3495:        return (error);
        !          3496: }
        !          3497:
        !          3498: int
        !          3499: bus_mem_add_mapping(bus_addr_t bpa, bus_size_t size, int cacheable,
        !          3500:     bus_space_handle_t *bshp)
        !          3501: {
        !          3502:        u_long pa, endpa;
        !          3503:        vaddr_t va;
        !          3504:        pt_entry_t *pte;
        !          3505:        bus_size_t map_size;
        !          3506:
        !          3507:        pa = trunc_page(bpa);
        !          3508:        endpa = round_page(bpa + size);
        !          3509:
        !          3510: #ifdef DIAGNOSTIC
        !          3511:        if (endpa <= pa && endpa != 0)
        !          3512:                panic("bus_mem_add_mapping: overflow");
        !          3513: #endif
        !          3514:
        !          3515:        map_size = endpa - pa;
        !          3516:
        !          3517:        va = uvm_km_valloc(kernel_map, map_size);
        !          3518:        if (va == 0)
        !          3519:                return (ENOMEM);
        !          3520:
        !          3521:        *bshp = (bus_space_handle_t)(va + (bpa & PGOFSET));
        !          3522:
        !          3523:        for (; map_size > 0;
        !          3524:            pa += PAGE_SIZE, va += PAGE_SIZE, map_size -= PAGE_SIZE) {
        !          3525:                pmap_kenter_pa(va, pa, VM_PROT_READ | VM_PROT_WRITE);
        !          3526:
        !          3527:                pte = kvtopte(va);
        !          3528:                if (cacheable)
        !          3529:                        *pte &= ~PG_N;
        !          3530:                else
        !          3531:                        *pte |= PG_N;
        !          3532:                pmap_tlb_shootpage(pmap_kernel(), va);
        !          3533:        }
        !          3534:
        !          3535:        pmap_tlb_shootwait();
        !          3536:        pmap_update(pmap_kernel());
        !          3537:
        !          3538:        return 0;
        !          3539: }
        !          3540:
        !          3541: void
        !          3542: bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size)
        !          3543: {
        !          3544:        struct extent *ex;
        !          3545:        u_long va, endva;
        !          3546:        bus_addr_t bpa;
        !          3547:
        !          3548:        /*
        !          3549:         * Find the correct extent and bus physical address.
        !          3550:         */
        !          3551:        if (t == I386_BUS_SPACE_IO) {
        !          3552:                ex = ioport_ex;
        !          3553:                bpa = bsh;
        !          3554:        } else if (t == I386_BUS_SPACE_MEM) {
        !          3555:                ex = iomem_ex;
        !          3556:                bpa = (bus_addr_t)ISA_PHYSADDR(bsh);
        !          3557:                if (IOM_BEGIN <= bpa && bpa <= IOM_END)
        !          3558:                        goto ok;
        !          3559:
        !          3560:                va = trunc_page(bsh);
        !          3561:                endva = round_page(bsh + size);
        !          3562:
        !          3563: #ifdef DIAGNOSTIC
        !          3564:                if (endva <= va)
        !          3565:                        panic("bus_space_unmap: overflow");
        !          3566: #endif
        !          3567:
        !          3568:                (void) pmap_extract(pmap_kernel(), va, &bpa);
        !          3569:                bpa += (bsh & PGOFSET);
        !          3570:
        !          3571:                /*
        !          3572:                 * Free the kernel virtual mapping.
        !          3573:                 */
        !          3574:                uvm_km_free(kernel_map, va, endva - va);
        !          3575:        } else
        !          3576:                panic("bus_space_unmap: bad bus space tag");
        !          3577:
        !          3578: ok:
        !          3579:        if (extent_free(ex, bpa, size,
        !          3580:            EX_NOWAIT | (ioport_malloc_safe ? EX_MALLOCOK : 0))) {
        !          3581:                printf("bus_space_unmap: %s 0x%lx, size 0x%lx\n",
        !          3582:                    (t == I386_BUS_SPACE_IO) ? "port" : "pa", bpa, size);
        !          3583:                printf("bus_space_unmap: can't free region\n");
        !          3584:        }
        !          3585: }
        !          3586:
        !          3587: void
        !          3588: _bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size,
        !          3589:     bus_addr_t *adrp)
        !          3590: {
        !          3591:        u_long va, endva;
        !          3592:        bus_addr_t bpa;
        !          3593:
        !          3594:        /*
        !          3595:         * Find the correct bus physical address.
        !          3596:         */
        !          3597:        if (t == I386_BUS_SPACE_IO) {
        !          3598:                bpa = bsh;
        !          3599:        } else if (t == I386_BUS_SPACE_MEM) {
        !          3600:                bpa = (bus_addr_t)ISA_PHYSADDR(bsh);
        !          3601:                if (IOM_BEGIN <= bpa && bpa <= IOM_END)
        !          3602:                        goto ok;
        !          3603:
        !          3604:                va = trunc_page(bsh);
        !          3605:                endva = round_page(bsh + size);
        !          3606:
        !          3607: #ifdef DIAGNOSTIC
        !          3608:                if (endva <= va)
        !          3609:                        panic("_bus_space_unmap: overflow");
        !          3610: #endif
        !          3611:
        !          3612:                (void) pmap_extract(pmap_kernel(), va, &bpa);
        !          3613:                bpa += (bsh & PGOFSET);
        !          3614:
        !          3615:                /*
        !          3616:                 * Free the kernel virtual mapping.
        !          3617:                 */
        !          3618:                uvm_km_free(kernel_map, va, endva - va);
        !          3619:        } else
        !          3620:                panic("bus_space_unmap: bad bus space tag");
        !          3621:
        !          3622: ok:
        !          3623:        if (adrp != NULL)
        !          3624:                *adrp = bpa;
        !          3625: }
        !          3626:
        !          3627: void
        !          3628: bus_space_free(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size)
        !          3629: {
        !          3630:
        !          3631:        /* bus_space_unmap() does all that we need to do. */
        !          3632:        bus_space_unmap(t, bsh, size);
        !          3633: }
        !          3634:
        !          3635: int
        !          3636: bus_space_subregion(bus_space_tag_t t, bus_space_handle_t bsh,
        !          3637:     bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp)
        !          3638: {
        !          3639:        *nbshp = bsh + offset;
        !          3640:        return (0);
        !          3641: }
        !          3642:
        !          3643: /*
        !          3644:  * Common function for DMA map creation.  May be called by bus-specific
        !          3645:  * DMA map creation functions.
        !          3646:  */
        !          3647: int
        !          3648: _bus_dmamap_create(bus_dma_tag_t t, bus_size_t size, int nsegments,
        !          3649:     bus_size_t maxsegsz, bus_size_t boundary, int flags, bus_dmamap_t *dmamp)
        !          3650: {
        !          3651:        struct i386_bus_dmamap *map;
        !          3652:        void *mapstore;
        !          3653:        size_t mapsize;
        !          3654:
        !          3655:        /*
        !          3656:         * Allocate and initialize the DMA map.  The end of the map
        !          3657:         * is a variable-sized array of segments, so we allocate enough
        !          3658:         * room for them in one shot.
        !          3659:         *
        !          3660:         * Note we don't preserve the WAITOK or NOWAIT flags.  Preservation
        !          3661:         * of ALLOCNOW notifies others that we've reserved these resources,
        !          3662:         * and they are not to be freed.
        !          3663:         *
        !          3664:         * The bus_dmamap_t includes one bus_dma_segment_t, hence
        !          3665:         * the (nsegments - 1).
        !          3666:         */
        !          3667:        mapsize = sizeof(struct i386_bus_dmamap) +
        !          3668:            (sizeof(bus_dma_segment_t) * (nsegments - 1));
        !          3669:        if ((mapstore = malloc(mapsize, M_DEVBUF,
        !          3670:            (flags & BUS_DMA_NOWAIT) ? M_NOWAIT : M_WAITOK)) == NULL)
        !          3671:                return (ENOMEM);
        !          3672:
        !          3673:        bzero(mapstore, mapsize);
        !          3674:        map = (struct i386_bus_dmamap *)mapstore;
        !          3675:        map->_dm_size = size;
        !          3676:        map->_dm_segcnt = nsegments;
        !          3677:        map->_dm_maxsegsz = maxsegsz;
        !          3678:        map->_dm_boundary = boundary;
        !          3679:        map->_dm_flags = flags & ~(BUS_DMA_WAITOK|BUS_DMA_NOWAIT);
        !          3680:        map->dm_mapsize = 0;            /* no valid mappings */
        !          3681:        map->dm_nsegs = 0;
        !          3682:
        !          3683:        *dmamp = map;
        !          3684:        return (0);
        !          3685: }
        !          3686:
        !          3687: /*
        !          3688:  * Common function for DMA map destruction.  May be called by bus-specific
        !          3689:  * DMA map destruction functions.
        !          3690:  */
        !          3691: void
        !          3692: _bus_dmamap_destroy(bus_dma_tag_t t, bus_dmamap_t map)
        !          3693: {
        !          3694:
        !          3695:        free(map, M_DEVBUF);
        !          3696: }
        !          3697:
        !          3698: /*
        !          3699:  * Common function for loading a DMA map with a linear buffer.  May
        !          3700:  * be called by bus-specific DMA map load functions.
        !          3701:  */
        !          3702: int
        !          3703: _bus_dmamap_load(bus_dma_tag_t t, bus_dmamap_t map, void *buf,
        !          3704:     bus_size_t buflen, struct proc *p, int flags)
        !          3705: {
        !          3706:        bus_addr_t lastaddr;
        !          3707:        int seg, error;
        !          3708:
        !          3709:        /*
        !          3710:         * Make sure that on error condition we return "no valid mappings".
        !          3711:         */
        !          3712:        map->dm_mapsize = 0;
        !          3713:        map->dm_nsegs = 0;
        !          3714:
        !          3715:        if (buflen > map->_dm_size)
        !          3716:                return (EINVAL);
        !          3717:
        !          3718:        seg = 0;
        !          3719:        error = _bus_dmamap_load_buffer(t, map, buf, buflen, p, flags,
        !          3720:            &lastaddr, &seg, 1);
        !          3721:        if (error == 0) {
        !          3722:                map->dm_mapsize = buflen;
        !          3723:                map->dm_nsegs = seg + 1;
        !          3724:        }
        !          3725:        return (error);
        !          3726: }
        !          3727:
        !          3728: /*
        !          3729:  * Like _bus_dmamap_load(), but for mbufs.
        !          3730:  */
        !          3731: int
        !          3732: _bus_dmamap_load_mbuf(bus_dma_tag_t t, bus_dmamap_t map, struct mbuf *m0,
        !          3733:     int flags)
        !          3734: {
        !          3735:        paddr_t lastaddr;
        !          3736:        int seg, error, first;
        !          3737:        struct mbuf *m;
        !          3738:
        !          3739:        /*
        !          3740:         * Make sure that on error condition we return "no valid mappings".
        !          3741:         */
        !          3742:        map->dm_mapsize = 0;
        !          3743:        map->dm_nsegs = 0;
        !          3744:
        !          3745: #ifdef DIAGNOSTIC
        !          3746:        if ((m0->m_flags & M_PKTHDR) == 0)
        !          3747:                panic("_bus_dmamap_load_mbuf: no packet header");
        !          3748: #endif
        !          3749:
        !          3750:        if (m0->m_pkthdr.len > map->_dm_size)
        !          3751:                return (EINVAL);
        !          3752:
        !          3753:        first = 1;
        !          3754:        seg = 0;
        !          3755:        error = 0;
        !          3756:        for (m = m0; m != NULL && error == 0; m = m->m_next) {
        !          3757:                if (m->m_len == 0)
        !          3758:                        continue;
        !          3759:                error = _bus_dmamap_load_buffer(t, map, m->m_data, m->m_len,
        !          3760:                    NULL, flags, &lastaddr, &seg, first);
        !          3761:                first = 0;
        !          3762:        }
        !          3763:        if (error == 0) {
        !          3764:                map->dm_mapsize = m0->m_pkthdr.len;
        !          3765:                map->dm_nsegs = seg + 1;
        !          3766:        }
        !          3767:        return (error);
        !          3768: }
        !          3769:
        !          3770: /*
        !          3771:  * Like _bus_dmamap_load(), but for uios.
        !          3772:  */
        !          3773: int
        !          3774: _bus_dmamap_load_uio(bus_dma_tag_t t, bus_dmamap_t map, struct uio *uio,
        !          3775:     int flags)
        !          3776: {
        !          3777:        paddr_t lastaddr;
        !          3778:        int seg, i, error, first;
        !          3779:        bus_size_t minlen, resid;
        !          3780:        struct proc *p = NULL;
        !          3781:        struct iovec *iov;
        !          3782:        caddr_t addr;
        !          3783:
        !          3784:        /*
        !          3785:         * Make sure that on error condition we return "no valid mappings".
        !          3786:         */
        !          3787:        map->dm_mapsize = 0;
        !          3788:        map->dm_nsegs = 0;
        !          3789:
        !          3790:        resid = uio->uio_resid;
        !          3791:        iov = uio->uio_iov;
        !          3792:
        !          3793:        if (resid > map->_dm_size)
        !          3794:                return (EINVAL);
        !          3795:
        !          3796:        if (uio->uio_segflg == UIO_USERSPACE) {
        !          3797:                p = uio->uio_procp;
        !          3798: #ifdef DIAGNOSTIC
        !          3799:                if (p == NULL)
        !          3800:                        panic("_bus_dmamap_load_uio: USERSPACE but no proc");
        !          3801: #endif
        !          3802:        }
        !          3803:
        !          3804:        first = 1;
        !          3805:        seg = 0;
        !          3806:        error = 0;
        !          3807:        for (i = 0; i < uio->uio_iovcnt && resid != 0 && error == 0; i++) {
        !          3808:                /*
        !          3809:                 * Now at the first iovec to load.  Load each iovec
        !          3810:                 * until we have exhausted the residual count.
        !          3811:                 */
        !          3812:                minlen = resid < iov[i].iov_len ? resid : iov[i].iov_len;
        !          3813:                addr = (caddr_t)iov[i].iov_base;
        !          3814:
        !          3815:                error = _bus_dmamap_load_buffer(t, map, addr, minlen,
        !          3816:                    p, flags, &lastaddr, &seg, first);
        !          3817:                first = 0;
        !          3818:
        !          3819:                resid -= minlen;
        !          3820:        }
        !          3821:        if (error == 0) {
        !          3822:                map->dm_mapsize = uio->uio_resid;
        !          3823:                map->dm_nsegs = seg + 1;
        !          3824:        }
        !          3825:        return (error);
        !          3826: }
        !          3827:
        !          3828: /*
        !          3829:  * Like _bus_dmamap_load(), but for raw memory allocated with
        !          3830:  * bus_dmamem_alloc().
        !          3831:  */
        !          3832: int
        !          3833: _bus_dmamap_load_raw(bus_dma_tag_t t, bus_dmamap_t map, bus_dma_segment_t *segs,
        !          3834:     int nsegs, bus_size_t size, int flags)
        !          3835: {
        !          3836:        if (nsegs > map->_dm_segcnt || size > map->_dm_size)
        !          3837:                return (EINVAL);
        !          3838:
        !          3839:        /*
        !          3840:         * Make sure we don't cross any boundaries.
        !          3841:         */
        !          3842:        if (map->_dm_boundary) {
        !          3843:                bus_addr_t bmask = ~(map->_dm_boundary - 1);
        !          3844:                int i;
        !          3845:
        !          3846:                for (i = 0; i < nsegs; i++) {
        !          3847:                        if (segs[i].ds_len > map->_dm_maxsegsz)
        !          3848:                                return (EINVAL);
        !          3849:                        if ((segs[i].ds_addr & bmask) !=
        !          3850:                            ((segs[i].ds_addr + segs[i].ds_len - 1) & bmask))
        !          3851:                                return (EINVAL);
        !          3852:                }
        !          3853:        }
        !          3854:
        !          3855:        bcopy(segs, map->dm_segs, nsegs * sizeof(*segs));
        !          3856:        map->dm_nsegs = nsegs;
        !          3857:        return (0);
        !          3858: }
        !          3859:
        !          3860: /*
        !          3861:  * Common function for unloading a DMA map.  May be called by
        !          3862:  * bus-specific DMA map unload functions.
        !          3863:  */
        !          3864: void
        !          3865: _bus_dmamap_unload(bus_dma_tag_t t, bus_dmamap_t map)
        !          3866: {
        !          3867:
        !          3868:        /*
        !          3869:         * No resources to free; just mark the mappings as
        !          3870:         * invalid.
        !          3871:         */
        !          3872:        map->dm_mapsize = 0;
        !          3873:        map->dm_nsegs = 0;
        !          3874: }
        !          3875:
        !          3876: /*
        !          3877:  * Common function for DMA-safe memory allocation.  May be called
        !          3878:  * by bus-specific DMA memory allocation functions.
        !          3879:  */
        !          3880: int
        !          3881: _bus_dmamem_alloc(bus_dma_tag_t t, bus_size_t size, bus_size_t alignment,
        !          3882:     bus_size_t boundary, bus_dma_segment_t *segs, int nsegs, int *rsegs,
        !          3883:     int flags)
        !          3884: {
        !          3885:
        !          3886:        return (_bus_dmamem_alloc_range(t, size, alignment, boundary,
        !          3887:            segs, nsegs, rsegs, flags, 0, trunc_page(avail_end)));
        !          3888: }
        !          3889:
        !          3890: /*
        !          3891:  * Common function for freeing DMA-safe memory.  May be called by
        !          3892:  * bus-specific DMA memory free functions.
        !          3893:  */
        !          3894: void
        !          3895: _bus_dmamem_free(bus_dma_tag_t t, bus_dma_segment_t *segs, int nsegs)
        !          3896: {
        !          3897:        struct vm_page *m;
        !          3898:        bus_addr_t addr;
        !          3899:        struct pglist mlist;
        !          3900:        int curseg;
        !          3901:
        !          3902:        /*
        !          3903:         * Build a list of pages to free back to the VM system.
        !          3904:         */
        !          3905:        TAILQ_INIT(&mlist);
        !          3906:        for (curseg = 0; curseg < nsegs; curseg++) {
        !          3907:                for (addr = segs[curseg].ds_addr;
        !          3908:                    addr < (segs[curseg].ds_addr + segs[curseg].ds_len);
        !          3909:                    addr += PAGE_SIZE) {
        !          3910:                        m = PHYS_TO_VM_PAGE(addr);
        !          3911:                        TAILQ_INSERT_TAIL(&mlist, m, pageq);
        !          3912:                }
        !          3913:        }
        !          3914:
        !          3915:        uvm_pglistfree(&mlist);
        !          3916: }
        !          3917:
        !          3918: /*
        !          3919:  * Common function for mapping DMA-safe memory.  May be called by
        !          3920:  * bus-specific DMA memory map functions.
        !          3921:  */
        !          3922: int
        !          3923: _bus_dmamem_map(bus_dma_tag_t t, bus_dma_segment_t *segs, int nsegs,
        !          3924:     size_t size, caddr_t *kvap, int flags)
        !          3925: {
        !          3926:        vaddr_t va;
        !          3927:        bus_addr_t addr;
        !          3928:        int curseg;
        !          3929:
        !          3930:        size = round_page(size);
        !          3931:        va = uvm_km_valloc(kernel_map, size);
        !          3932:        if (va == 0)
        !          3933:                return (ENOMEM);
        !          3934:
        !          3935:        *kvap = (caddr_t)va;
        !          3936:
        !          3937:        for (curseg = 0; curseg < nsegs; curseg++) {
        !          3938:                for (addr = segs[curseg].ds_addr;
        !          3939:                    addr < (segs[curseg].ds_addr + segs[curseg].ds_len);
        !          3940:                    addr += PAGE_SIZE, va += PAGE_SIZE, size -= PAGE_SIZE) {
        !          3941:                        if (size == 0)
        !          3942:                                panic("_bus_dmamem_map: size botch");
        !          3943:                        pmap_enter(pmap_kernel(), va, addr,
        !          3944:                            VM_PROT_READ | VM_PROT_WRITE,
        !          3945:                            VM_PROT_READ | VM_PROT_WRITE | PMAP_WIRED);
        !          3946:                }
        !          3947:        }
        !          3948:        pmap_update(pmap_kernel());
        !          3949:
        !          3950:        return (0);
        !          3951: }
        !          3952:
        !          3953: /*
        !          3954:  * Common function for unmapping DMA-safe memory.  May be called by
        !          3955:  * bus-specific DMA memory unmapping functions.
        !          3956:  */
        !          3957: void
        !          3958: _bus_dmamem_unmap(bus_dma_tag_t t, caddr_t kva, size_t size)
        !          3959: {
        !          3960:
        !          3961: #ifdef DIAGNOSTIC
        !          3962:        if ((u_long)kva & PGOFSET)
        !          3963:                panic("_bus_dmamem_unmap");
        !          3964: #endif
        !          3965:
        !          3966:        size = round_page(size);
        !          3967:        uvm_km_free(kernel_map, (vaddr_t)kva, size);
        !          3968: }
        !          3969:
        !          3970: /*
        !          3971:  * Common functin for mmap(2)'ing DMA-safe memory.  May be called by
        !          3972:  * bus-specific DMA mmap(2)'ing functions.
        !          3973:  */
        !          3974: paddr_t
        !          3975: _bus_dmamem_mmap(bus_dma_tag_t t, bus_dma_segment_t *segs, int nsegs, off_t off,
        !          3976:     int prot, int flags)
        !          3977: {
        !          3978:        int i;
        !          3979:
        !          3980:        for (i = 0; i < nsegs; i++) {
        !          3981: #ifdef DIAGNOSTIC
        !          3982:                if (off & PGOFSET)
        !          3983:                        panic("_bus_dmamem_mmap: offset unaligned");
        !          3984:                if (segs[i].ds_addr & PGOFSET)
        !          3985:                        panic("_bus_dmamem_mmap: segment unaligned");
        !          3986:                if (segs[i].ds_len & PGOFSET)
        !          3987:                        panic("_bus_dmamem_mmap: segment size not multiple"
        !          3988:                            " of page size");
        !          3989: #endif
        !          3990:                if (off >= segs[i].ds_len) {
        !          3991:                        off -= segs[i].ds_len;
        !          3992:                        continue;
        !          3993:                }
        !          3994:
        !          3995:                return (atop(segs[i].ds_addr + off));
        !          3996:        }
        !          3997:
        !          3998:        /* Page not found. */
        !          3999:        return (-1);
        !          4000: }
        !          4001:
        !          4002: /**********************************************************************
        !          4003:  * DMA utility functions
        !          4004:  **********************************************************************/
        !          4005: /*
        !          4006:  * Utility function to load a linear buffer.  lastaddrp holds state
        !          4007:  * between invocations (for multiple-buffer loads).  segp contains
        !          4008:  * the starting segment on entrance, and the ending segment on exit.
        !          4009:  * first indicates if this is the first invocation of this function.
        !          4010:  */
        !          4011: int
        !          4012: _bus_dmamap_load_buffer(bus_dma_tag_t t, bus_dmamap_t map, void *buf,
        !          4013:     bus_size_t buflen, struct proc *p, int flags, paddr_t *lastaddrp, int *segp,
        !          4014:     int first)
        !          4015: {
        !          4016:        bus_size_t sgsize;
        !          4017:        bus_addr_t curaddr, lastaddr, baddr, bmask;
        !          4018:        vaddr_t vaddr = (vaddr_t)buf;
        !          4019:        int seg;
        !          4020:        pmap_t pmap;
        !          4021:
        !          4022:        if (p != NULL)
        !          4023:                pmap = p->p_vmspace->vm_map.pmap;
        !          4024:        else
        !          4025:                pmap = pmap_kernel();
        !          4026:
        !          4027:        lastaddr = *lastaddrp;
        !          4028:        bmask  = ~(map->_dm_boundary - 1);
        !          4029:
        !          4030:        for (seg = *segp; buflen > 0 ; ) {
        !          4031:                /*
        !          4032:                 * Get the physical address for this segment.
        !          4033:                 */
        !          4034:                pmap_extract(pmap, vaddr, (paddr_t *)&curaddr);
        !          4035:
        !          4036:                /*
        !          4037:                 * Compute the segment size, and adjust counts.
        !          4038:                 */
        !          4039:                sgsize = PAGE_SIZE - ((u_long)vaddr & PGOFSET);
        !          4040:                if (buflen < sgsize)
        !          4041:                        sgsize = buflen;
        !          4042:
        !          4043:                /*
        !          4044:                 * Make sure we don't cross any boundaries.
        !          4045:                 */
        !          4046:                if (map->_dm_boundary > 0) {
        !          4047:                        baddr = (curaddr + map->_dm_boundary) & bmask;
        !          4048:                        if (sgsize > (baddr - curaddr))
        !          4049:                                sgsize = (baddr - curaddr);
        !          4050:                }
        !          4051:
        !          4052:                /*
        !          4053:                 * Insert chunk into a segment, coalescing with
        !          4054:                 * previous segment if possible.
        !          4055:                 */
        !          4056:                if (first) {
        !          4057:                        map->dm_segs[seg].ds_addr = curaddr;
        !          4058:                        map->dm_segs[seg].ds_len = sgsize;
        !          4059:                        first = 0;
        !          4060:                } else {
        !          4061:                        if (curaddr == lastaddr &&
        !          4062:                            (map->dm_segs[seg].ds_len + sgsize) <=
        !          4063:                             map->_dm_maxsegsz &&
        !          4064:                            (map->_dm_boundary == 0 ||
        !          4065:                             (map->dm_segs[seg].ds_addr & bmask) ==
        !          4066:                             (curaddr & bmask)))
        !          4067:                                map->dm_segs[seg].ds_len += sgsize;
        !          4068:                        else {
        !          4069:                                if (++seg >= map->_dm_segcnt)
        !          4070:                                        break;
        !          4071:                                map->dm_segs[seg].ds_addr = curaddr;
        !          4072:                                map->dm_segs[seg].ds_len = sgsize;
        !          4073:                        }
        !          4074:                }
        !          4075:
        !          4076:                lastaddr = curaddr + sgsize;
        !          4077:                vaddr += sgsize;
        !          4078:                buflen -= sgsize;
        !          4079:        }
        !          4080:
        !          4081:        *segp = seg;
        !          4082:        *lastaddrp = lastaddr;
        !          4083:
        !          4084:        /*
        !          4085:         * Did we fit?
        !          4086:         */
        !          4087:        if (buflen != 0)
        !          4088:                return (EFBIG);         /* XXX better return value here? */
        !          4089:        return (0);
        !          4090: }
        !          4091:
        !          4092: /*
        !          4093:  * Allocate physical memory from the given physical address range.
        !          4094:  * Called by DMA-safe memory allocation methods.
        !          4095:  */
        !          4096: int
        !          4097: _bus_dmamem_alloc_range(bus_dma_tag_t t, bus_size_t size, bus_size_t alignment,
        !          4098:     bus_size_t boundary, bus_dma_segment_t *segs, int nsegs, int *rsegs,
        !          4099:     int flags, paddr_t low, paddr_t high)
        !          4100: {
        !          4101:        paddr_t curaddr, lastaddr;
        !          4102:        struct vm_page *m;
        !          4103:        struct pglist mlist;
        !          4104:        int curseg, error;
        !          4105:
        !          4106:        /* Always round the size. */
        !          4107:        size = round_page(size);
        !          4108:
        !          4109:        TAILQ_INIT(&mlist);
        !          4110:        /*
        !          4111:         * Allocate pages from the VM system.
        !          4112:         * For non-ISA mappings first try higher memory segments.
        !          4113:         */
        !          4114:        if (high <= ISA_DMA_BOUNCE_THRESHOLD || (error = uvm_pglistalloc(size,
        !          4115:            round_page(ISA_DMA_BOUNCE_THRESHOLD), high, alignment, boundary,
        !          4116:            &mlist, nsegs, (flags & BUS_DMA_NOWAIT) == 0)))
        !          4117:                error = uvm_pglistalloc(size, low, high, alignment, boundary,
        !          4118:                    &mlist, nsegs, (flags & BUS_DMA_NOWAIT) == 0);
        !          4119:        if (error)
        !          4120:                return (error);
        !          4121:
        !          4122:        /*
        !          4123:         * Compute the location, size, and number of segments actually
        !          4124:         * returned by the VM code.
        !          4125:         */
        !          4126:        m = TAILQ_FIRST(&mlist);
        !          4127:        curseg = 0;
        !          4128:        lastaddr = segs[curseg].ds_addr = VM_PAGE_TO_PHYS(m);
        !          4129:        segs[curseg].ds_len = PAGE_SIZE;
        !          4130:
        !          4131:        for (m = TAILQ_NEXT(m, pageq); m != NULL; m = TAILQ_NEXT(m, pageq)) {
        !          4132:                curaddr = VM_PAGE_TO_PHYS(m);
        !          4133: #ifdef DIAGNOSTIC
        !          4134:                if (curseg == nsegs) {
        !          4135:                        printf("uvm_pglistalloc returned too many\n");
        !          4136:                        panic("_bus_dmamem_alloc_range");
        !          4137:                }
        !          4138:                if (curaddr < low || curaddr >= high) {
        !          4139:                        printf("uvm_pglistalloc returned non-sensical"
        !          4140:                            " address 0x%lx\n", curaddr);
        !          4141:                        panic("_bus_dmamem_alloc_range");
        !          4142:                }
        !          4143: #endif
        !          4144:                if (curaddr == (lastaddr + PAGE_SIZE))
        !          4145:                        segs[curseg].ds_len += PAGE_SIZE;
        !          4146:                else {
        !          4147:                        curseg++;
        !          4148:                        segs[curseg].ds_addr = curaddr;
        !          4149:                        segs[curseg].ds_len = PAGE_SIZE;
        !          4150:                }
        !          4151:                lastaddr = curaddr;
        !          4152:        }
        !          4153:        *rsegs = curseg + 1;
        !          4154:
        !          4155:        return (0);
        !          4156: }
        !          4157:
        !          4158: #ifdef DIAGNOSTIC
        !          4159: void
        !          4160: splassert_check(int wantipl, const char *func)
        !          4161: {
        !          4162:        if (lapic_tpr < wantipl)
        !          4163:                splassert_fail(wantipl, lapic_tpr, func);
        !          4164:        if (wantipl == IPL_NONE && curcpu()->ci_idepth != 0)
        !          4165:                splassert_fail(-1, curcpu()->ci_idepth, func);
        !          4166: }
        !          4167: #endif
        !          4168:
        !          4169: #ifdef MULTIPROCESSOR
        !          4170: void
        !          4171: i386_intlock(int ipl)
        !          4172: {
        !          4173:        if (ipl < IPL_SCHED)
        !          4174:                __mp_lock(&kernel_lock);
        !          4175:
        !          4176:        curcpu()->ci_idepth++;
        !          4177: }
        !          4178:
        !          4179: void
        !          4180: i386_intunlock(int ipl)
        !          4181: {
        !          4182:        curcpu()->ci_idepth--;
        !          4183:
        !          4184:        if (ipl < IPL_SCHED)
        !          4185:                __mp_unlock(&kernel_lock);
        !          4186: }
        !          4187:
        !          4188: void
        !          4189: i386_softintlock(void)
        !          4190: {
        !          4191:        __mp_lock(&kernel_lock);
        !          4192:        curcpu()->ci_idepth++;
        !          4193: }
        !          4194:
        !          4195: void
        !          4196: i386_softintunlock(void)
        !          4197: {
        !          4198:        curcpu()->ci_idepth--;
        !          4199:        __mp_unlock(&kernel_lock);
        !          4200: }
        !          4201: #endif
        !          4202:
        !          4203: /*
        !          4204:  * Software interrupt registration
        !          4205:  *
        !          4206:  * We hand-code this to ensure that it's atomic.
        !          4207:  */
        !          4208: void
        !          4209: softintr(int sir, int vec)
        !          4210: {
        !          4211:        __asm __volatile("orl %1, %0" : "=m" (ipending) : "ir" (sir));
        !          4212: #ifdef MULTIPROCESSOR
        !          4213:        i82489_writereg(LAPIC_ICRLO,
        !          4214:            vec | LAPIC_DLMODE_FIXED | LAPIC_LVL_ASSERT | LAPIC_DEST_SELF);
        !          4215: #endif
        !          4216: }
        !          4217:
        !          4218: /*
        !          4219:  * Raise current interrupt priority level, and return the old one.
        !          4220:  */
        !          4221: int
        !          4222: splraise(int ncpl)
        !          4223: {
        !          4224:        int ocpl;
        !          4225:
        !          4226:        _SPLRAISE(ocpl, ncpl);
        !          4227:        return (ocpl);
        !          4228: }
        !          4229:
        !          4230: /*
        !          4231:  * Restore an old interrupt priority level.  If any thereby unmasked
        !          4232:  * interrupts are pending, call Xspllower() to process them.
        !          4233:  */
        !          4234: void
        !          4235: splx(int ncpl)
        !          4236: {
        !          4237:        _SPLX(ncpl);
        !          4238: }
        !          4239:
        !          4240: /*
        !          4241:  * Same as splx(), but we return the old value of spl, for the
        !          4242:  * benefit of some splsoftclock() callers.
        !          4243:  */
        !          4244: int
        !          4245: spllower(int ncpl)
        !          4246: {
        !          4247:        int ocpl = lapic_tpr;
        !          4248:
        !          4249:        splx(ncpl);
        !          4250:        return (ocpl);
        !          4251: }

CVSweb