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

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

1.1     ! nbrk        1: /*     $OpenBSD: machdep.c,v 1.60 2007/08/02 16:40:27 deraadt Exp $    */
        !             2: /*     $NetBSD: machdep.c,v 1.3 2003/05/07 22:58:18 fvdl Exp $ */
        !             3:
        !             4: /*-
        !             5:  * Copyright (c) 1996, 1997, 1998, 2000 The NetBSD Foundation, Inc.
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * This code is derived from software contributed to The NetBSD Foundation
        !             9:  * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace
        !            10:  * Simulation Facility, 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) 1982, 1987, 1990 The Regents of the University of California.
        !            43:  * All rights reserved.
        !            44:  *
        !            45:  * This code is derived from software contributed to Berkeley by
        !            46:  * William Jolitz.
        !            47:  *
        !            48:  * Redistribution and use in source and binary forms, with or without
        !            49:  * modification, are permitted provided that the following conditions
        !            50:  * are met:
        !            51:  * 1. Redistributions of source code must retain the above copyright
        !            52:  *    notice, this list of conditions and the following disclaimer.
        !            53:  * 2. Redistributions in binary form must reproduce the above copyright
        !            54:  *    notice, this list of conditions and the following disclaimer in the
        !            55:  *    documentation and/or other materials provided with the distribution.
        !            56:  * 3. Neither the name of the University nor the names of its contributors
        !            57:  *    may be used to endorse or promote products derived from this software
        !            58:  *    without specific prior written permission.
        !            59:  *
        !            60:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            61:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            62:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            63:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            64:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            65:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            66:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            67:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            68:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            69:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            70:  * SUCH DAMAGE.
        !            71:  *
        !            72:  *     @(#)machdep.c   7.4 (Berkeley) 6/3/91
        !            73:  */
        !            74:
        !            75: #include <sys/param.h>
        !            76: #include <sys/systm.h>
        !            77: #include <sys/signal.h>
        !            78: #include <sys/signalvar.h>
        !            79: #include <sys/kernel.h>
        !            80: #include <sys/proc.h>
        !            81: #include <sys/user.h>
        !            82: #include <sys/exec.h>
        !            83: #include <sys/buf.h>
        !            84: #include <sys/reboot.h>
        !            85: #include <sys/conf.h>
        !            86: #include <sys/file.h>
        !            87: #include <sys/malloc.h>
        !            88: #include <sys/mbuf.h>
        !            89: #include <sys/msgbuf.h>
        !            90: #include <sys/mount.h>
        !            91: #include <sys/vnode.h>
        !            92: #include <sys/extent.h>
        !            93: #include <sys/core.h>
        !            94: #include <sys/kcore.h>
        !            95: #include <sys/syscallargs.h>
        !            96:
        !            97: #ifdef SYSVMSG
        !            98: #include <sys/msg.h>
        !            99: #endif
        !           100:
        !           101: #ifdef KGDB
        !           102: #include <sys/kgdb.h>
        !           103: #endif
        !           104:
        !           105: #include <dev/cons.h>
        !           106: #include <stand/boot/bootarg.h>
        !           107:
        !           108: #include <uvm/uvm_extern.h>
        !           109: #include <uvm/uvm_page.h>
        !           110:
        !           111: #include <sys/sysctl.h>
        !           112:
        !           113: #include <machine/cpu.h>
        !           114: #include <machine/cpufunc.h>
        !           115: #include <machine/gdt.h>
        !           116: #include <machine/pio.h>
        !           117: #include <machine/psl.h>
        !           118: #include <machine/reg.h>
        !           119: #include <machine/specialreg.h>
        !           120: #include <machine/fpu.h>
        !           121: #include <machine/mtrr.h>
        !           122: #include <machine/biosvar.h>
        !           123: #include <machine/mpbiosvar.h>
        !           124: #include <machine/reg.h>
        !           125: #include <machine/kcore.h>
        !           126:
        !           127: #include <dev/isa/isareg.h>
        !           128: #include <machine/isa_machdep.h>
        !           129: #include <dev/ic/i8042reg.h>
        !           130: #include <amd64/isa/nvram.h>
        !           131:
        !           132: #ifdef DDB
        !           133: #include <machine/db_machdep.h>
        !           134: #include <ddb/db_extern.h>
        !           135: #endif
        !           136:
        !           137: #include "isa.h"
        !           138: #include "isadma.h"
        !           139: #include "ksyms.h"
        !           140:
        !           141: #include "acpi.h"
        !           142: #if NACPI > 0
        !           143: #include <dev/acpi/acpivar.h>
        !           144: #endif
        !           145:
        !           146:
        !           147: /* the following is used externally (sysctl_hw) */
        !           148: char machine[] = MACHINE;
        !           149:
        !           150: /* the following is used externally for concurrent handlers */
        !           151: int setperf_prio = 0;
        !           152:
        !           153: #ifdef CPURESET_DELAY
        !           154: int    cpureset_delay = CPURESET_DELAY;
        !           155: #else
        !           156: int     cpureset_delay = 2000; /* default to 2s */
        !           157: #endif
        !           158:
        !           159: int    physmem;
        !           160: u_int64_t      dumpmem_low;
        !           161: u_int64_t      dumpmem_high;
        !           162: extern int     boothowto;
        !           163: int    cpu_class;
        !           164:
        !           165: char   *ssym = NULL;
        !           166: vaddr_t kern_end;
        !           167:
        !           168: vaddr_t        msgbuf_vaddr;
        !           169: paddr_t msgbuf_paddr;
        !           170:
        !           171: vaddr_t        idt_vaddr;
        !           172: paddr_t        idt_paddr;
        !           173:
        !           174: vaddr_t lo32_vaddr;
        !           175: paddr_t lo32_paddr;
        !           176:
        !           177: int kbd_reset;
        !           178:
        !           179: struct vm_map *exec_map = NULL;
        !           180: struct vm_map *phys_map = NULL;
        !           181:
        !           182: #ifndef BUFCACHEPERCENT
        !           183: #define BUFCACHEPERCENT 10
        !           184: #endif
        !           185:
        !           186: #ifdef BUFPAGES
        !           187: int    bufpages = BUFPAGES;
        !           188: #else
        !           189: int    bufpages = 0;
        !           190: #endif
        !           191: int bufcachepercent = BUFCACHEPERCENT;
        !           192:
        !           193: #ifdef DEBUG
        !           194: int sigdebug = 0;
        !           195: pid_t sigpid = 0;
        !           196: #define SDB_FOLLOW      0x01
        !           197: #endif
        !           198:
        !           199: extern paddr_t avail_start, avail_end;
        !           200:
        !           201: void (*delay_func)(int) = i8254_delay;
        !           202: void (*initclock_func)(void) = i8254_initclocks;
        !           203:
        !           204: struct mtrr_funcs *mtrr_funcs;
        !           205:
        !           206: /*
        !           207:  * Format of boot information passed to us by 32-bit /boot
        !           208:  */
        !           209: typedef struct _boot_args32 {
        !           210:        int     ba_type;
        !           211:        int     ba_size;
        !           212:        int     ba_nextX;       /* a ptr in 32-bit world, but not here */
        !           213:        char    ba_arg[1];
        !           214: } bootarg32_t;
        !           215:
        !           216: #define BOOTARGC_MAX   NBPG    /* one page */
        !           217:
        !           218: #ifdef NFSCLIENT
        !           219: bios_bootmac_t *bios_bootmac;
        !           220: #endif
        !           221:
        !           222: /* locore copies the arguments from /boot to here for us */
        !           223: char bootinfo[BOOTARGC_MAX];
        !           224: int bootinfo_size = BOOTARGC_MAX;
        !           225:
        !           226: void getbootinfo(char *, int);
        !           227:
        !           228: /* Data passed to us by /boot, filled in by getbootinfo() */
        !           229: #if NAPM > 0 || defined(DEBUG)
        !           230: bios_apminfo_t *apm;
        !           231: #endif
        !           232: #if NPCI > 0
        !           233: bios_pciinfo_t *bios_pciinfo;
        !           234: #endif
        !           235: bios_diskinfo_t        *bios_diskinfo;
        !           236: bios_memmap_t  *bios_memmap;
        !           237: u_int32_t      bios_cksumlen;
        !           238:
        !           239: /*
        !           240:  * Size of memory segments, before any memory is stolen.
        !           241:  */
        !           242: phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX];
        !           243: int    mem_cluster_cnt;
        !           244:
        !           245: vaddr_t        allocsys(vaddr_t);
        !           246: void   setup_buffers(void);
        !           247: int    cpu_dump(void);
        !           248: int    cpu_dumpsize(void);
        !           249: u_long cpu_dump_mempagecnt(void);
        !           250: void   dumpsys(void);
        !           251: void   init_x86_64(paddr_t);
        !           252:
        !           253: #ifdef KGDB
        !           254: #ifndef KGDB_DEVNAME
        !           255: #define KGDB_DEVNAME   "com"
        !           256: #endif /* KGDB_DEVNAME */
        !           257: char kgdb_devname[] = KGDB_DEVNAME;
        !           258: #if NCOM > 0
        !           259: #ifndef KGDBADDR
        !           260: #define KGDBADDR       0x3f8
        !           261: #endif /* KGDBADDR */
        !           262: int comkgdbaddr = KGDBADDR;
        !           263: #ifndef KGDBRATE
        !           264: #define KGDBRATE       TTYDEF_SPEED
        !           265: #endif /* KGDBRATE */
        !           266: int comkgdbrate = KGDBRATE;
        !           267: #ifndef KGDBMODE
        !           268: #define KGDBMODE       ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8)
        !           269: #endif /* KGDBMODE */
        !           270: int comkgdbmode = KGDBMODE;
        !           271: #endif /* NCOM */
        !           272: void   kgdb_port_init(void);
        !           273: #endif /* KGDB */
        !           274:
        !           275: #ifdef APERTURE
        !           276: #ifdef INSECURE
        !           277: int allowaperture = 1;
        !           278: #else
        !           279: int allowaperture = 0;
        !           280: #endif
        !           281: #endif
        !           282:
        !           283: /*
        !           284:  * Machine-dependent startup code
        !           285:  */
        !           286: void
        !           287: cpu_startup(void)
        !           288: {
        !           289:        vaddr_t v;
        !           290:        vsize_t sz;
        !           291:        vaddr_t minaddr, maxaddr;
        !           292:
        !           293:        msgbuf_vaddr = PMAP_DIRECT_MAP(msgbuf_paddr);
        !           294:        initmsgbuf((caddr_t)msgbuf_vaddr, round_page(MSGBUFSIZE));
        !           295:
        !           296:        printf("%s", version);
        !           297:
        !           298:        printf("real mem = %u (%uMB)\n", ctob(physmem),
        !           299:            ctob(physmem)/1024/1024);
        !           300:
        !           301:        if (physmem >= btoc(1ULL << 32)) {
        !           302:                extern int amdgart_enable;
        !           303:
        !           304:                amdgart_enable = 1;
        !           305:        }
        !           306:
        !           307:        /*
        !           308:         * Find out how much space we need, allocate it,
        !           309:         * and then give everything true virtual addresses.
        !           310:         */
        !           311:        sz = allocsys(0);
        !           312:        if ((v = uvm_km_zalloc(kernel_map, round_page(sz))) == 0)
        !           313:                panic("startup: no room for tables");
        !           314:        if (allocsys(v) - v != sz)
        !           315:                panic("startup: table size inconsistency");
        !           316:
        !           317:        setup_buffers();
        !           318:
        !           319:        /*
        !           320:         * Allocate a submap for exec arguments.  This map effectively
        !           321:         * limits the number of processes exec'ing at any time.
        !           322:         */
        !           323:        minaddr = vm_map_min(kernel_map);
        !           324:        exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
        !           325:                                   16*NCARGS, VM_MAP_PAGEABLE, FALSE, NULL);
        !           326:
        !           327:        /*
        !           328:         * Allocate a submap for physio
        !           329:         */
        !           330:        minaddr = vm_map_min(kernel_map);
        !           331:        phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
        !           332:                                   VM_PHYS_SIZE, 0, FALSE, NULL);
        !           333:
        !           334:        printf("avail mem = %lu (%luMB)\n", ptoa(uvmexp.free),
        !           335:            ptoa(uvmexp.free)/1024/1024);
        !           336:
        !           337:        bufinit();
        !           338:
        !           339:        if (boothowto & RB_CONFIG) {
        !           340: #ifdef BOOT_CONFIG
        !           341:                user_config();
        !           342: #else
        !           343:                printf("kernel does not support - c; continuing..\n");
        !           344: #endif
        !           345:        }
        !           346:
        !           347:        /* Safe for i/o port / memory space allocation to use malloc now. */
        !           348:        x86_bus_space_mallocok();
        !           349: }
        !           350:
        !           351: /*
        !           352:  * Allocate space for system data structures.  We are given
        !           353:  * a starting virtual address and we return a final virtual
        !           354:  * address; along the way we set each data structure pointer.
        !           355:  *
        !           356:  * We call allocsys() with 0 to find out how much space we want,
        !           357:  * allocate that much and fill it with zeroes, and then call
        !           358:  * allocsys() again with the correct base virtual address.
        !           359:  */
        !           360: vaddr_t
        !           361: allocsys(vaddr_t v)
        !           362: {
        !           363:
        !           364: #define        valloc(name, type, num) \
        !           365:            v = (vaddr_t)(((name) = (type *)v) + (num))
        !           366:
        !           367: #ifdef SYSVMSG
        !           368:        valloc(msgpool, char, msginfo.msgmax);
        !           369:        valloc(msgmaps, struct msgmap, msginfo.msgseg);
        !           370:        valloc(msghdrs, struct msg, msginfo.msgtql);
        !           371:        valloc(msqids, struct msqid_ds, msginfo.msgmni);
        !           372: #endif
        !           373:
        !           374:        return v;
        !           375: }
        !           376:
        !           377: void
        !           378: setup_buffers()
        !           379: {
        !           380:        /*
        !           381:         * Determine how many buffers to allocate.
        !           382:         * We allocate bufcachepercent% of memory for buffer space.
        !           383:         */
        !           384:        if (bufpages == 0)
        !           385:                bufpages = physmem * bufcachepercent / 100;
        !           386:
        !           387:        /* Restrict to at most 25% filled kvm */
        !           388:        if (bufpages >
        !           389:            (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) / PAGE_SIZE / 4)
        !           390:                bufpages = (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) /
        !           391:                    PAGE_SIZE / 4;
        !           392: }
        !           393:
        !           394: /*
        !           395:  * Set up proc0's TSS and LDT.
        !           396:  */
        !           397: void
        !           398: x86_64_proc0_tss_ldt_init(void)
        !           399: {
        !           400:        struct pcb *pcb;
        !           401:        int x;
        !           402:
        !           403:        gdt_init();
        !           404:
        !           405:        cpu_info_primary.ci_curpcb = pcb = &proc0.p_addr->u_pcb;
        !           406:
        !           407:        pcb->pcb_flags = 0;
        !           408:        pcb->pcb_tss.tss_iobase =
        !           409:            (u_int16_t)((caddr_t)pcb->pcb_iomap - (caddr_t)&pcb->pcb_tss);
        !           410:        for (x = 0; x < sizeof(pcb->pcb_iomap) / 4; x++)
        !           411:                pcb->pcb_iomap[x] = 0xffffffff;
        !           412:
        !           413:        pcb->pcb_ldt_sel = pmap_kernel()->pm_ldt_sel =
        !           414:            GSYSSEL(GLDT_SEL, SEL_KPL);
        !           415:        pcb->pcb_cr0 = rcr0();
        !           416:        pcb->pcb_tss.tss_rsp0 = (u_int64_t)proc0.p_addr + USPACE - 16;
        !           417:        pcb->pcb_tss.tss_ist[0] = (u_int64_t)proc0.p_addr + PAGE_SIZE;
        !           418:        proc0.p_md.md_regs = (struct trapframe *)pcb->pcb_tss.tss_rsp0 - 1;
        !           419:        proc0.p_md.md_tss_sel = tss_alloc(pcb);
        !           420:
        !           421:        ltr(proc0.p_md.md_tss_sel);
        !           422:        lldt(pcb->pcb_ldt_sel);
        !           423: }
        !           424:
        !           425: /*
        !           426:  * Set up TSS and LDT for a new PCB.
        !           427:  */
        !           428:
        !           429: #ifdef MULTIPROCESSOR
        !           430: void
        !           431: x86_64_init_pcb_tss_ldt(struct cpu_info *ci)
        !           432: {
        !           433:        int x;
        !           434:        struct pcb *pcb = ci->ci_idle_pcb;
        !           435:
        !           436:        pcb->pcb_tss.tss_iobase =
        !           437:            (u_int16_t)((caddr_t)pcb->pcb_iomap - (caddr_t)&pcb->pcb_tss);
        !           438:        for (x = 0; x < sizeof(pcb->pcb_iomap) / 4; x++)
        !           439:                pcb->pcb_iomap[x] = 0xffffffff;
        !           440:
        !           441:        /* XXXfvdl pmap_kernel not needed */
        !           442:        pcb->pcb_ldt_sel = pmap_kernel()->pm_ldt_sel =
        !           443:            GSYSSEL(GLDT_SEL, SEL_KPL);
        !           444:        pcb->pcb_cr0 = rcr0();
        !           445:
        !           446:         ci->ci_idle_tss_sel = tss_alloc(pcb);
        !           447: }
        !           448: #endif /* MULTIPROCESSOR */
        !           449:
        !           450: bios_diskinfo_t *
        !           451: bios_getdiskinfo(dev_t dev)
        !           452: {
        !           453:        bios_diskinfo_t *pdi;
        !           454:
        !           455:        if (bios_diskinfo == NULL)
        !           456:                return NULL;
        !           457:
        !           458:        for (pdi = bios_diskinfo; pdi->bios_number != -1; pdi++) {
        !           459:                if ((dev & B_MAGICMASK) == B_DEVMAGIC) { /* search by bootdev */
        !           460:                        if (pdi->bsd_dev == dev)
        !           461:                                break;
        !           462:                } else {
        !           463:                        if (pdi->bios_number == dev)
        !           464:                                break;
        !           465:                }
        !           466:        }
        !           467:
        !           468:        if (pdi->bios_number == -1)
        !           469:                return NULL;
        !           470:        else
        !           471:                return pdi;
        !           472: }
        !           473:
        !           474: int
        !           475: bios_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
        !           476:     size_t newlen, struct proc *p)
        !           477: {
        !           478:        bios_diskinfo_t *pdi;
        !           479:        extern dev_t bootdev;
        !           480:        int biosdev;
        !           481:
        !           482:        /* all sysctl names at this level except diskinfo are terminal */
        !           483:        if (namelen != 1 && name[0] != BIOS_DISKINFO)
        !           484:                return (ENOTDIR);              /* overloaded */
        !           485:
        !           486:        if (!(bootapiver & BAPIV_VECTOR))
        !           487:                return EOPNOTSUPP;
        !           488:
        !           489:        switch (name[0]) {
        !           490:        case BIOS_DEV:
        !           491:                if ((pdi = bios_getdiskinfo(bootdev)) == NULL)
        !           492:                        return ENXIO;
        !           493:                biosdev = pdi->bios_number;
        !           494:                return sysctl_rdint(oldp, oldlenp, newp, biosdev);
        !           495:        case BIOS_DISKINFO:
        !           496:                if (namelen != 2)
        !           497:                        return ENOTDIR;
        !           498:                if ((pdi = bios_getdiskinfo(name[1])) == NULL)
        !           499:                        return ENXIO;
        !           500:                return sysctl_rdstruct(oldp, oldlenp, newp, pdi, sizeof(*pdi));
        !           501:        case BIOS_CKSUMLEN:
        !           502:                return sysctl_rdint(oldp, oldlenp, newp, bios_cksumlen);
        !           503:        default:
        !           504:                return EOPNOTSUPP;
        !           505:        }
        !           506:        /* NOTREACHED */
        !           507: }
        !           508:
        !           509: /*
        !           510:  * machine dependent system variables.
        !           511:  */
        !           512: int
        !           513: cpu_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
        !           514:     size_t newlen, struct proc *p)
        !           515: {
        !           516:        dev_t consdev;
        !           517:        dev_t dev;
        !           518:
        !           519:        switch (name[0]) {
        !           520:        case CPU_CONSDEV:
        !           521:                if (namelen != 1)
        !           522:                        return (ENOTDIR);               /* overloaded */
        !           523:                if (cn_tab != NULL)
        !           524:                        consdev = cn_tab->cn_dev;
        !           525:                else
        !           526:                        consdev = NODEV;
        !           527:                return (sysctl_rdstruct(oldp, oldlenp, newp, &consdev,
        !           528:                    sizeof consdev));
        !           529:        case CPU_CHR2BLK:
        !           530:                if (namelen != 2)
        !           531:                        return (ENOTDIR);               /* overloaded */
        !           532:                dev = chrtoblk((dev_t)name[1]);
        !           533:                return sysctl_rdstruct(oldp, oldlenp, newp, &dev, sizeof(dev));
        !           534:        case CPU_BIOS:
        !           535:                return bios_sysctl(name + 1, namelen - 1, oldp, oldlenp,
        !           536:                    newp, newlen, p);
        !           537:        case CPU_CPUVENDOR:
        !           538:                return (sysctl_rdstring(oldp, oldlenp, newp, cpu_vendor));
        !           539:        case CPU_CPUFEATURE:
        !           540:                return (sysctl_rdint(oldp, oldlenp, newp, cpu_feature));
        !           541:        case CPU_KBDRESET:
        !           542:                if (securelevel > 0)
        !           543:                        return (sysctl_rdint(oldp, oldlenp, newp,
        !           544:                            kbd_reset));
        !           545:                else
        !           546:                        return (sysctl_int(oldp, oldlenp, newp, newlen,
        !           547:                            &kbd_reset));
        !           548:        case CPU_ALLOWAPERTURE:
        !           549:                if (namelen != 1)
        !           550:                        return (ENOTDIR);               /* overloaded */
        !           551: #ifdef APERTURE
        !           552:                if (securelevel > 0)
        !           553:                        return (sysctl_int_lower(oldp, oldlenp, newp, newlen,
        !           554:                            &allowaperture));
        !           555:                else
        !           556:                        return (sysctl_int(oldp, oldlenp, newp, newlen,
        !           557:                            &allowaperture));
        !           558: #else
        !           559:                return (sysctl_rdint(oldp, oldlenp, newp, 0));
        !           560: #endif
        !           561:        default:
        !           562:                return (EOPNOTSUPP);
        !           563:        }
        !           564:        /* NOTREACHED */
        !           565: }
        !           566:
        !           567: /*
        !           568:  * Send an interrupt to process.
        !           569:  *
        !           570:  * Stack is set up to allow sigcode stored
        !           571:  * in u. to call routine, followed by kcall
        !           572:  * to sigreturn routine below.  After sigreturn
        !           573:  * resets the signal mask, the stack, and the
        !           574:  * frame pointer, it returns to the user
        !           575:  * specified pc, psl.
        !           576:  */
        !           577: void
        !           578: sendsig(sig_t catcher, int sig, int mask, u_long code, int type,
        !           579:     union sigval val)
        !           580: {
        !           581:        struct proc *p = curproc;
        !           582:        struct trapframe *tf = p->p_md.md_regs;
        !           583:        struct sigacts * psp = p->p_sigacts;
        !           584:        struct sigcontext ksc;
        !           585:        siginfo_t ksi;
        !           586:        register_t sp, scp, sip;
        !           587:        u_long sss;
        !           588:
        !           589: #ifdef DEBUG
        !           590:        if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid))
        !           591:                printf("sendsig: %s[%d] sig %d catcher %p\n",
        !           592:                    p->p_comm, p->p_pid, sig, catcher);
        !           593: #endif
        !           594:
        !           595:        bcopy(tf, &ksc, sizeof(*tf));
        !           596:        ksc.sc_onstack = psp->ps_sigstk.ss_flags & SS_ONSTACK;
        !           597:        ksc.sc_mask = mask;
        !           598:        ksc.sc_fpstate = NULL;
        !           599:
        !           600:        /* Allocate space for the signal handler context. */
        !           601:        if ((psp->ps_flags & SAS_ALTSTACK) && !ksc.sc_onstack &&
        !           602:            (psp->ps_sigonstack & sigmask(sig))) {
        !           603:                sp = (register_t)psp->ps_sigstk.ss_sp + psp->ps_sigstk.ss_size;
        !           604:                psp->ps_sigstk.ss_flags |= SS_ONSTACK;
        !           605:        } else
        !           606:                sp = tf->tf_rsp - 128;
        !           607:
        !           608:        sp &= ~15ULL;   /* just in case */
        !           609:        sss = (sizeof(ksc) + 15) & ~15;
        !           610:
        !           611:        if (p->p_md.md_flags & MDP_USEDFPU) {
        !           612:                fpusave_proc(p, 1);
        !           613:                sp -= sizeof(struct fxsave64);
        !           614:                ksc.sc_fpstate = (struct fxsave64 *)sp;
        !           615:                if (copyout(&p->p_addr->u_pcb.pcb_savefpu.fp_fxsave,
        !           616:                    (void *)sp, sizeof(struct fxsave64)))
        !           617:                        sigexit(p, SIGILL);
        !           618:        }
        !           619:
        !           620:        sip = 0;
        !           621:        if (psp->ps_siginfo & sigmask(sig)) {
        !           622:                sip = sp - ((sizeof(ksi) + 15) & ~15);
        !           623:                sss += (sizeof(ksi) + 15) & ~15;
        !           624:
        !           625:                initsiginfo(&ksi, sig, code, type, val);
        !           626:                if (copyout(&ksi, (void *)sip, sizeof(ksi)))
        !           627:                        sigexit(p, SIGILL);
        !           628:        }
        !           629:        scp = sp - sss;
        !           630:
        !           631:        if (copyout(&ksc, (void *)scp, sizeof(ksc)))
        !           632:                sigexit(p, SIGILL);
        !           633:
        !           634:        /*
        !           635:         * Build context to run handler in.
        !           636:         */
        !           637:        tf->tf_ds = LSEL(LUDATA_SEL, SEL_UPL);
        !           638:        tf->tf_es = LSEL(LUDATA_SEL, SEL_UPL);
        !           639:        tf->tf_fs = LSEL(LUDATA_SEL, SEL_UPL);
        !           640:        tf->tf_gs = LSEL(LUDATA_SEL, SEL_UPL);
        !           641:
        !           642:        tf->tf_rax = (u_int64_t)catcher;
        !           643:        tf->tf_rdi = sig;
        !           644:        tf->tf_rsi = sip;
        !           645:        tf->tf_rdx = scp;
        !           646:
        !           647:        tf->tf_rip = (u_int64_t)p->p_sigcode;
        !           648:        tf->tf_cs = LSEL(LUCODE_SEL, SEL_UPL);
        !           649:        tf->tf_rflags &= ~(PSL_T|PSL_VM|PSL_AC);
        !           650:        tf->tf_rsp = scp;
        !           651:        tf->tf_ss = LSEL(LUDATA_SEL, SEL_UPL);
        !           652:
        !           653: #ifdef DEBUG
        !           654:        if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid))
        !           655:                printf("sendsig(%d): pc 0x%x, catcher 0x%x\n", p->p_pid,
        !           656:                    tf->tf_rip, tf->tf_rax);
        !           657: #endif
        !           658: }
        !           659:
        !           660: /*
        !           661:  * System call to cleanup state after a signal
        !           662:  * has been taken.  Reset signal mask and
        !           663:  * stack state from context left by sendsig (above).
        !           664:  * Return to previous pc and psl as specified by
        !           665:  * context left by sendsig. Check carefully to
        !           666:  * make sure that the user has not modified the
        !           667:  * psl to gain improper privileges or to cause
        !           668:  * a machine fault.
        !           669:  */
        !           670: int
        !           671: sys_sigreturn(struct proc *p, void *v, register_t *retval)
        !           672: {
        !           673:        struct sys_sigreturn_args /* {
        !           674:                syscallarg(struct sigcontext *) sigcntxp;
        !           675:        } */ *uap = v;
        !           676:        struct sigcontext *scp, ksc;
        !           677:        struct trapframe *tf = p->p_md.md_regs;
        !           678:        int error;
        !           679:
        !           680:        scp = SCARG(uap, sigcntxp);
        !           681: #ifdef DEBUG
        !           682:        if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid))
        !           683:                printf("sigreturn: pid %d, scp %p\n", p->p_pid, scp);
        !           684: #endif
        !           685:        if ((error = copyin((caddr_t)scp, &ksc, sizeof ksc)))
        !           686:                return (error);
        !           687:
        !           688:        if (((ksc.sc_rflags ^ tf->tf_rflags) & PSL_USERSTATIC) != 0 ||
        !           689:            !USERMODE(ksc.sc_cs, ksc.sc_eflags))
        !           690:                return (EINVAL);
        !           691:
        !           692:        if (p->p_md.md_flags & MDP_USEDFPU)
        !           693:                fpusave_proc(p, 0);
        !           694:
        !           695:        if (ksc.sc_fpstate && (error = copyin(ksc.sc_fpstate,
        !           696:            &p->p_addr->u_pcb.pcb_savefpu.fp_fxsave, sizeof (struct fxsave64))))
        !           697:                return (error);
        !           698:
        !           699:        ksc.sc_trapno = tf->tf_trapno;
        !           700:        ksc.sc_err = tf->tf_err;
        !           701:        bcopy(&ksc, tf, sizeof(*tf));
        !           702:
        !           703:        /* Restore signal stack. */
        !           704:        if (ksc.sc_onstack)
        !           705:                p->p_sigacts->ps_sigstk.ss_flags |= SS_ONSTACK;
        !           706:        else
        !           707:                p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK;
        !           708:        p->p_sigmask = ksc.sc_mask & ~sigcantmask;
        !           709:
        !           710:        return (EJUSTRETURN);
        !           711: }
        !           712:
        !           713: /*
        !           714:  * Notify the current process (p) that it has a signal pending,
        !           715:  * process as soon as possible.
        !           716:  */
        !           717: void
        !           718: signotify(struct proc *p)
        !           719: {
        !           720:        aston(p);
        !           721: #ifdef MULTIPROCESSOR
        !           722:        if (p->p_cpu != curcpu() && p->p_cpu != NULL)
        !           723:                x86_send_ipi(p->p_cpu, X86_IPI_NOP);
        !           724: #endif
        !           725: }
        !           726:
        !           727: int    waittime = -1;
        !           728: struct pcb dumppcb;
        !           729:
        !           730: void
        !           731: boot(int howto)
        !           732: {
        !           733:
        !           734:        if (cold) {
        !           735:                /*
        !           736:                 * If the system is cold, just halt, unless the user
        !           737:                 * explicitly asked for reboot.
        !           738:                 */
        !           739:                if ((howto & RB_USERREQ) == 0)
        !           740:                        howto |= RB_HALT;
        !           741:                goto haltsys;
        !           742:        }
        !           743:
        !           744:        boothowto = howto;
        !           745:        if ((howto & RB_NOSYNC) == 0 && waittime < 0) {
        !           746:                waittime = 0;
        !           747:
        !           748:                if (curproc == NULL)
        !           749:                        curproc = &proc0;       /* XXX */
        !           750:                vfs_shutdown();
        !           751:                /*
        !           752:                 * If we've been adjusting the clock, the todr
        !           753:                 * will be out of synch; adjust it now.
        !           754:                 */
        !           755:                if ((howto & RB_TIMEBAD) == 0) {
        !           756:                        resettodr();
        !           757:                } else {
        !           758:                        printf("WARNING: not updating battery clock\n");
        !           759:                }
        !           760:        }
        !           761:
        !           762:        /* Disable interrupts. */
        !           763:        splhigh();
        !           764:
        !           765:        /* Do a dump if requested. */
        !           766:        if (howto & RB_DUMP)
        !           767:                dumpsys();
        !           768:
        !           769: haltsys:
        !           770:        doshutdownhooks();
        !           771:
        !           772: #ifdef MULTIPROCESSOR
        !           773:        x86_broadcast_ipi(X86_IPI_HALT);
        !           774: #endif
        !           775:
        !           776:        if (howto & RB_HALT) {
        !           777: #if NACPI > 0 && !defined(SMALL_KERNEL)
        !           778:                extern int acpi_s5, acpi_enabled;
        !           779:
        !           780:                if (acpi_enabled) {
        !           781:                        delay(500000);
        !           782:                        if (howto & RB_POWERDOWN || acpi_s5)
        !           783:                                acpi_powerdown();
        !           784:                }
        !           785: #endif
        !           786:                printf("\n");
        !           787:                printf("The operating system has halted.\n");
        !           788:                printf("Please press any key to reboot.\n\n");
        !           789:                cnpollc(1);     /* for proper keyboard command handling */
        !           790:                cngetc();
        !           791:                cnpollc(0);
        !           792:        }
        !           793:
        !           794:        printf("rebooting...\n");
        !           795:        if (cpureset_delay > 0)
        !           796:                delay(cpureset_delay * 1000);
        !           797:        cpu_reset();
        !           798:        for(;;) ;
        !           799:        /*NOTREACHED*/
        !           800: }
        !           801:
        !           802: /*
        !           803:  * XXXfvdl share dumpcode.
        !           804:  */
        !           805:
        !           806: /*
        !           807:  * These variables are needed by /sbin/savecore
        !           808:  */
        !           809: u_int32_t      dumpmag = 0x8fca0101;   /* magic number */
        !           810: int    dumpsize = 0;           /* pages */
        !           811: long   dumplo = 0;             /* blocks */
        !           812:
        !           813: /*
        !           814:  * cpu_dump: dump the machine-dependent kernel core dump headers.
        !           815:  */
        !           816: int
        !           817: cpu_dump(void)
        !           818: {
        !           819:        int (*dump)(dev_t, daddr64_t, caddr_t, size_t);
        !           820:        char buf[dbtob(1)];
        !           821:        kcore_seg_t *segp;
        !           822:        cpu_kcore_hdr_t *cpuhdrp;
        !           823:        phys_ram_seg_t *memsegp;
        !           824:        int i;
        !           825:
        !           826:        dump = bdevsw[major(dumpdev)].d_dump;
        !           827:
        !           828:        memset(buf, 0, sizeof buf);
        !           829:        segp = (kcore_seg_t *)buf;
        !           830:        cpuhdrp = (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(*segp))];
        !           831:        memsegp = (phys_ram_seg_t *)&buf[ALIGN(sizeof(*segp)) +
        !           832:            ALIGN(sizeof(*cpuhdrp))];
        !           833:
        !           834:        /*
        !           835:         * Generate a segment header.
        !           836:         */
        !           837:        CORE_SETMAGIC(*segp, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
        !           838:        segp->c_size = dbtob(1) - ALIGN(sizeof(*segp));
        !           839:
        !           840:        /*
        !           841:         * Add the machine-dependent header info.
        !           842:         */
        !           843:        cpuhdrp->ptdpaddr = PTDpaddr;
        !           844:        cpuhdrp->nmemsegs = mem_cluster_cnt;
        !           845:
        !           846:        /*
        !           847:         * Fill in the memory segment descriptors.
        !           848:         */
        !           849:        for (i = 0; i < mem_cluster_cnt; i++) {
        !           850:                memsegp[i].start = mem_clusters[i].start;
        !           851:                memsegp[i].size = mem_clusters[i].size & ~PAGE_MASK;
        !           852:        }
        !           853:
        !           854:        return (dump(dumpdev, dumplo, (caddr_t)buf, dbtob(1)));
        !           855: }
        !           856:
        !           857: /*
        !           858:  * This is called by main to set dumplo and dumpsize.
        !           859:  * Dumps always skip the first PAGE_SIZE of disk space
        !           860:  * in case there might be a disk label stored there.
        !           861:  * If there is extra space, put dump at the end to
        !           862:  * reduce the chance that swapping trashes it.
        !           863:  */
        !           864: void
        !           865: dumpconf(void)
        !           866: {
        !           867:        int nblks, dumpblks;    /* size of dump area */
        !           868:
        !           869:        if (dumpdev == NODEV ||
        !           870:            (nblks = (bdevsw[major(dumpdev)].d_psize)(dumpdev)) == 0)
        !           871:                return;
        !           872:        if (nblks <= ctod(1))
        !           873:                return;
        !           874:
        !           875:        dumpblks = cpu_dumpsize();
        !           876:        if (dumpblks < 0)
        !           877:                return;
        !           878:        dumpblks += ctod(cpu_dump_mempagecnt());
        !           879:
        !           880:        /* If dump won't fit (incl. room for possible label), punt. */
        !           881:        if (dumpblks > (nblks - ctod(1)))
        !           882:                return;
        !           883:
        !           884:        /* Put dump at end of partition */
        !           885:        dumplo = nblks - dumpblks;
        !           886:
        !           887:        /* dumpsize is in page units, and doesn't include headers. */
        !           888:        dumpsize = cpu_dump_mempagecnt();
        !           889: }
        !           890:
        !           891: /*
        !           892:  * Doadump comes here after turning off memory management and
        !           893:  * getting on the dump stack, either when called above, or by
        !           894:  * the auto-restart code.
        !           895:  */
        !           896: #define BYTES_PER_DUMP  PAGE_SIZE /* must be a multiple of pagesize XXX small */
        !           897: static vaddr_t dumpspace;
        !           898:
        !           899: vaddr_t
        !           900: reserve_dumppages(vaddr_t p)
        !           901: {
        !           902:
        !           903:        dumpspace = p;
        !           904:        return (p + BYTES_PER_DUMP);
        !           905: }
        !           906:
        !           907: void
        !           908: dumpsys(void)
        !           909: {
        !           910:        u_long totalbytesleft, bytes, i, n, memseg;
        !           911:        u_long maddr;
        !           912:        daddr64_t blkno;
        !           913:        int (*dump)(dev_t, daddr64_t, caddr_t, size_t);
        !           914:        int error;
        !           915:
        !           916:        /* Save registers. */
        !           917:        savectx(&dumppcb);
        !           918:
        !           919:        if (dumpdev == NODEV)
        !           920:                return;
        !           921:
        !           922:        /*
        !           923:         * For dumps during autoconfiguration,
        !           924:         * if dump device has already configured...
        !           925:         */
        !           926:        if (dumpsize == 0)
        !           927:                dumpconf();
        !           928:        if (dumplo <= 0 || dumpsize == 0) {
        !           929:                printf("\ndump to dev %u,%u not possible\n", major(dumpdev),
        !           930:                    minor(dumpdev));
        !           931:                return;
        !           932:        }
        !           933:        printf("\ndumping to dev %u,%u offset %ld\n", major(dumpdev),
        !           934:            minor(dumpdev), dumplo);
        !           935:
        !           936:        error = (*bdevsw[major(dumpdev)].d_psize)(dumpdev);
        !           937:        printf("dump ");
        !           938:        if (error == -1) {
        !           939:                printf("area unavailable\n");
        !           940:                return;
        !           941:        }
        !           942:
        !           943:        if ((error = cpu_dump()) != 0)
        !           944:                goto err;
        !           945:
        !           946:        totalbytesleft = ptoa(cpu_dump_mempagecnt());
        !           947:        blkno = dumplo + cpu_dumpsize();
        !           948:        dump = bdevsw[major(dumpdev)].d_dump;
        !           949:        error = 0;
        !           950:
        !           951:        for (memseg = 0; memseg < mem_cluster_cnt; memseg++) {
        !           952:                maddr = mem_clusters[memseg].start;
        !           953:                bytes = mem_clusters[memseg].size;
        !           954:
        !           955:                for (i = 0; i < bytes; i += n, totalbytesleft -= n) {
        !           956:                        /* Print out how many MBs we have left to go. */
        !           957:                        if ((totalbytesleft % (1024*1024)) == 0)
        !           958:                                printf("%ld ", totalbytesleft / (1024 * 1024));
        !           959:
        !           960:                        /* Limit size for next transfer. */
        !           961:                        n = bytes - i;
        !           962:                        if (n > BYTES_PER_DUMP)
        !           963:                                n = BYTES_PER_DUMP;
        !           964:
        !           965:                        (void) pmap_map(dumpspace, maddr, maddr + n,
        !           966:                            VM_PROT_READ);
        !           967:
        !           968:                        error = (*dump)(dumpdev, blkno, (caddr_t)dumpspace, n);
        !           969:                        if (error)
        !           970:                                goto err;
        !           971:                        maddr += n;
        !           972:                        blkno += btodb(n);              /* XXX? */
        !           973:
        !           974: #if 0  /* XXX this doesn't work.  grr. */
        !           975:                        /* operator aborting dump? */
        !           976:                        if (sget() != NULL) {
        !           977:                                error = EINTR;
        !           978:                                break;
        !           979:                        }
        !           980: #endif
        !           981:                }
        !           982:        }
        !           983:
        !           984:  err:
        !           985:        switch (error) {
        !           986:
        !           987:        case ENXIO:
        !           988:                printf("device bad\n");
        !           989:                break;
        !           990:
        !           991:        case EFAULT:
        !           992:                printf("device not ready\n");
        !           993:                break;
        !           994:
        !           995:        case EINVAL:
        !           996:                printf("area improper\n");
        !           997:                break;
        !           998:
        !           999:        case EIO:
        !          1000:                printf("i/o error\n");
        !          1001:                break;
        !          1002:
        !          1003:        case EINTR:
        !          1004:                printf("aborted from console\n");
        !          1005:                break;
        !          1006:
        !          1007:        case 0:
        !          1008:                printf("succeeded\n");
        !          1009:                break;
        !          1010:
        !          1011:        default:
        !          1012:                printf("error %d\n", error);
        !          1013:                break;
        !          1014:        }
        !          1015:        printf("\n\n");
        !          1016:        delay(5000000);         /* 5 seconds */
        !          1017: }
        !          1018:
        !          1019: /*
        !          1020:  * Clear registers on exec
        !          1021:  */
        !          1022: void
        !          1023: setregs(struct proc *p, struct exec_package *pack, u_long stack,
        !          1024:     register_t *retval)
        !          1025: {
        !          1026:        struct pcb *pcb = &p->p_addr->u_pcb;
        !          1027:        struct trapframe *tf;
        !          1028:
        !          1029:        /* If we were using the FPU, forget about it. */
        !          1030:        if (p->p_addr->u_pcb.pcb_fpcpu != NULL)
        !          1031:                fpusave_proc(p, 0);
        !          1032:
        !          1033: #ifdef USER_LDT
        !          1034:        pmap_ldt_cleanup(p);
        !          1035: #endif
        !          1036:
        !          1037:        p->p_md.md_flags &= ~MDP_USEDFPU;
        !          1038:        pcb->pcb_flags = 0;
        !          1039:        pcb->pcb_savefpu.fp_fxsave.fx_fcw = __INITIAL_NPXCW__;
        !          1040:        pcb->pcb_savefpu.fp_fxsave.fx_mxcsr = __INITIAL_MXCSR__;
        !          1041:        pcb->pcb_savefpu.fp_fxsave.fx_mxcsr_mask = __INITIAL_MXCSR_MASK__;
        !          1042:
        !          1043:        tf = p->p_md.md_regs;
        !          1044:        tf->tf_ds = LSEL(LUDATA_SEL, SEL_UPL);
        !          1045:        tf->tf_es = LSEL(LUDATA_SEL, SEL_UPL);
        !          1046:        tf->tf_fs = LSEL(LUDATA_SEL, SEL_UPL);
        !          1047:        tf->tf_gs = LSEL(LUDATA_SEL, SEL_UPL);
        !          1048:        tf->tf_rdi = 0;
        !          1049:        tf->tf_rsi = 0;
        !          1050:        tf->tf_rbp = 0;
        !          1051:        tf->tf_rbx = 0;
        !          1052:        tf->tf_rdx = 0;
        !          1053:        tf->tf_rcx = 0;
        !          1054:        tf->tf_rax = 0;
        !          1055:        tf->tf_rip = pack->ep_entry;
        !          1056:        tf->tf_cs = LSEL(LUCODE_SEL, SEL_UPL);
        !          1057:        tf->tf_rflags = PSL_USERSET;
        !          1058:        tf->tf_rsp = stack;
        !          1059:        tf->tf_ss = LSEL(LUDATA_SEL, SEL_UPL);
        !          1060:
        !          1061:        retval[1] = 0;
        !          1062: }
        !          1063:
        !          1064: /*
        !          1065:  * Initialize segments and descriptor tables
        !          1066:  */
        !          1067:
        !          1068: struct gate_descriptor *idt;
        !          1069: char idt_allocmap[NIDT];
        !          1070: struct simplelock idt_lock;
        !          1071: char *ldtstore;
        !          1072: char *gdtstore;
        !          1073: extern  struct user *proc0paddr;
        !          1074:
        !          1075: void
        !          1076: setgate(struct gate_descriptor *gd, void *func, int ist, int type, int dpl,
        !          1077:     int sel)
        !          1078: {
        !          1079:        gd->gd_looffset = (u_int64_t)func & 0xffff;
        !          1080:        gd->gd_selector = sel;
        !          1081:        gd->gd_ist = ist;
        !          1082:        gd->gd_type = type;
        !          1083:        gd->gd_dpl = dpl;
        !          1084:        gd->gd_p = 1;
        !          1085:        gd->gd_hioffset = (u_int64_t)func >> 16;
        !          1086:        gd->gd_zero = 0;
        !          1087:        gd->gd_xx1 = 0;
        !          1088:        gd->gd_xx2 = 0;
        !          1089:        gd->gd_xx3 = 0;
        !          1090: }
        !          1091:
        !          1092: void
        !          1093: unsetgate(struct gate_descriptor *gd)
        !          1094: {
        !          1095:        memset(gd, 0, sizeof (*gd));
        !          1096: }
        !          1097:
        !          1098: void
        !          1099: setregion(struct region_descriptor *rd, void *base, u_int16_t limit)
        !          1100: {
        !          1101:        rd->rd_limit = limit;
        !          1102:        rd->rd_base = (u_int64_t)base;
        !          1103: }
        !          1104:
        !          1105: /*
        !          1106:  * Note that the base and limit fields are ignored in long mode.
        !          1107:  */
        !          1108: void
        !          1109: set_mem_segment(struct mem_segment_descriptor *sd, void *base, size_t limit,
        !          1110:     int type, int dpl, int gran, int def32, int is64)
        !          1111: {
        !          1112:        sd->sd_lolimit = (unsigned)limit;
        !          1113:        sd->sd_lobase = (unsigned long)base;
        !          1114:        sd->sd_type = type;
        !          1115:        sd->sd_dpl = dpl;
        !          1116:        sd->sd_p = 1;
        !          1117:        sd->sd_hilimit = (unsigned)limit >> 16;
        !          1118:        sd->sd_avl = 0;
        !          1119:        sd->sd_long = is64;
        !          1120:        sd->sd_def32 = def32;
        !          1121:        sd->sd_gran = gran;
        !          1122:        sd->sd_hibase = (unsigned long)base >> 24;
        !          1123: }
        !          1124:
        !          1125: void
        !          1126: set_sys_segment(struct sys_segment_descriptor *sd, void *base, size_t limit,
        !          1127:     int type, int dpl, int gran)
        !          1128: {
        !          1129:        memset(sd, 0, sizeof *sd);
        !          1130:        sd->sd_lolimit = (unsigned)limit;
        !          1131:        sd->sd_lobase = (u_int64_t)base;
        !          1132:        sd->sd_type = type;
        !          1133:        sd->sd_dpl = dpl;
        !          1134:        sd->sd_p = 1;
        !          1135:        sd->sd_hilimit = (unsigned)limit >> 16;
        !          1136:        sd->sd_gran = gran;
        !          1137:        sd->sd_hibase = (u_int64_t)base >> 24;
        !          1138: }
        !          1139:
        !          1140: void cpu_init_idt(void)
        !          1141: {
        !          1142:        struct region_descriptor region;
        !          1143:
        !          1144:        setregion(&region, idt, NIDT * sizeof(idt[0]) - 1);
        !          1145:        lidt(&region);
        !          1146: }
        !          1147:
        !          1148:
        !          1149: #define        IDTVEC(name)    __CONCAT(X, name)
        !          1150: typedef void (vector)(void);
        !          1151: extern vector IDTVEC(syscall);
        !          1152: extern vector IDTVEC(syscall32);
        !          1153: extern vector IDTVEC(osyscall);
        !          1154: extern vector IDTVEC(oosyscall);
        !          1155: extern vector *IDTVEC(exceptions)[];
        !          1156:
        !          1157: #define        KBTOB(x)        ((size_t)(x) * 1024UL)
        !          1158:
        !          1159: void
        !          1160: init_x86_64(paddr_t first_avail)
        !          1161: {
        !          1162:        extern void consinit(void);
        !          1163:        extern struct extent *iomem_ex;
        !          1164:        struct region_descriptor region;
        !          1165:        struct mem_segment_descriptor *ldt_segp;
        !          1166:        int x, first16q, ist;
        !          1167:        u_int64_t seg_start, seg_end;
        !          1168:        u_int64_t seg_start1, seg_end1;
        !          1169:
        !          1170:        cpu_init_msrs(&cpu_info_primary);
        !          1171:
        !          1172:        proc0.p_addr = proc0paddr;
        !          1173:        cpu_info_primary.ci_curpcb = &proc0.p_addr->u_pcb;
        !          1174:
        !          1175:        x86_bus_space_init();
        !          1176:
        !          1177:        consinit();     /* XXX SHOULD NOT BE DONE HERE */
        !          1178:
        !          1179:        /*
        !          1180:         * Initailize PAGE_SIZE-dependent variables.
        !          1181:         */
        !          1182:        uvm_setpagesize();
        !          1183:
        !          1184: #if 0
        !          1185:        uvmexp.ncolors = 2;
        !          1186: #endif
        !          1187:
        !          1188:        /*
        !          1189:         * Boot arguments are in a single page specified by /boot.
        !          1190:         *
        !          1191:         * We require the "new" vector form, as well as memory ranges
        !          1192:         * to be given in bytes rather than KB.
        !          1193:         *
        !          1194:         * locore copies the data into bootinfo[] for us.
        !          1195:         */
        !          1196:        if ((bootapiver & (BAPIV_VECTOR | BAPIV_BMEMMAP)) ==
        !          1197:            (BAPIV_VECTOR | BAPIV_BMEMMAP)) {
        !          1198:                if (bootinfo_size >= sizeof(bootinfo))
        !          1199:                        panic("boot args too big");
        !          1200:
        !          1201:                getbootinfo(bootinfo, bootinfo_size);
        !          1202:        } else
        !          1203:                panic("invalid /boot");
        !          1204:
        !          1205:        avail_start = PAGE_SIZE; /* BIOS leaves data in low memory */
        !          1206:                                 /* and VM system doesn't work with phys 0 */
        !          1207: #ifdef MULTIPROCESSOR
        !          1208:        if (avail_start < MP_TRAMPOLINE + PAGE_SIZE)
        !          1209:                avail_start = MP_TRAMPOLINE + PAGE_SIZE;
        !          1210: #endif
        !          1211:
        !          1212:        /*
        !          1213:         * Call pmap initialization to make new kernel address space.
        !          1214:         * We must do this before loading pages into the VM system.
        !          1215:         */
        !          1216:        pmap_bootstrap(VM_MIN_KERNEL_ADDRESS,
        !          1217:            IOM_END + trunc_page(KBTOB(biosextmem)));
        !          1218:
        !          1219:        if (avail_start != PAGE_SIZE)
        !          1220:                pmap_prealloc_lowmem_ptps();
        !          1221:
        !          1222:        if (mem_cluster_cnt == 0) {
        !          1223:                /*
        !          1224:                 * Allocate the physical addresses used by RAM from the iomem
        !          1225:                 * extent map.  This is done before the addresses are
        !          1226:                 * page rounded just to make sure we get them all.
        !          1227:                 */
        !          1228:                if (extent_alloc_region(iomem_ex, 0, KBTOB(biosbasemem),
        !          1229:                    EX_NOWAIT)) {
        !          1230:                        /* XXX What should we do? */
        !          1231:                        printf("WARNING: CAN'T ALLOCATE BASE MEMORY FROM "
        !          1232:                            "IOMEM EXTENT MAP!\n");
        !          1233:                }
        !          1234:                mem_clusters[0].start = 0;
        !          1235:                mem_clusters[0].size = trunc_page(KBTOB(biosbasemem));
        !          1236:                physmem += atop(mem_clusters[0].size);
        !          1237:                if (extent_alloc_region(iomem_ex, IOM_END, KBTOB(biosextmem),
        !          1238:                    EX_NOWAIT)) {
        !          1239:                        /* XXX What should we do? */
        !          1240:                        printf("WARNING: CAN'T ALLOCATE EXTENDED MEMORY FROM "
        !          1241:                            "IOMEM EXTENT MAP!\n");
        !          1242:                }
        !          1243: #if 0
        !          1244: #if NISADMA > 0
        !          1245:                /*
        !          1246:                 * Some motherboards/BIOSes remap the 384K of RAM that would
        !          1247:                 * normally be covered by the ISA hole to the end of memory
        !          1248:                 * so that it can be used.  However, on a 16M system, this
        !          1249:                 * would cause bounce buffers to be allocated and used.
        !          1250:                 * This is not desirable behaviour, as more than 384K of
        !          1251:                 * bounce buffers might be allocated.  As a work-around,
        !          1252:                 * we round memory down to the nearest 1M boundary if
        !          1253:                 * we're using any isadma devices and the remapped memory
        !          1254:                 * is what puts us over 16M.
        !          1255:                 */
        !          1256:                if (biosextmem > (15*1024) && biosextmem < (16*1024)) {
        !          1257:                        char pbuf[9];
        !          1258:
        !          1259:                        format_bytes(pbuf, sizeof(pbuf),
        !          1260:                            biosextmem - (15*1024));
        !          1261:                        printf("Warning: ignoring %s of remapped memory\n",
        !          1262:                            pbuf);
        !          1263:                        biosextmem = (15*1024);
        !          1264:                }
        !          1265: #endif
        !          1266: #endif
        !          1267:                mem_clusters[1].start = IOM_END;
        !          1268:                mem_clusters[1].size = trunc_page(KBTOB(biosextmem));
        !          1269:                physmem += atop(mem_clusters[1].size);
        !          1270:
        !          1271:                mem_cluster_cnt = 2;
        !          1272:
        !          1273:                avail_end = IOM_END + trunc_page(KBTOB(biosextmem));
        !          1274:        }
        !          1275:
        !          1276:        /*
        !          1277:         * If we have 16M of RAM or less, just put it all on
        !          1278:         * the default free list.  Otherwise, put the first
        !          1279:         * 16M of RAM on a lower priority free list (so that
        !          1280:         * all of the ISA DMA'able memory won't be eaten up
        !          1281:         * first-off).
        !          1282:         */
        !          1283:        if (avail_end <= (16 * 1024 * 1024))
        !          1284:                first16q = VM_FREELIST_DEFAULT;
        !          1285:        else
        !          1286:                first16q = VM_FREELIST_FIRST16;
        !          1287:
        !          1288:        /* Make sure the end of the space used by the kernel is rounded. */
        !          1289:        first_avail = round_page(first_avail);
        !          1290:        kern_end = KERNBASE + first_avail;
        !          1291:
        !          1292:        /*
        !          1293:         * Now, load the memory clusters (which have already been
        !          1294:         * rounded and truncated) into the VM system.
        !          1295:         *
        !          1296:         * NOTE: WE ASSUME THAT MEMORY STARTS AT 0 AND THAT THE KERNEL
        !          1297:         * IS LOADED AT IOM_END (1M).
        !          1298:         */
        !          1299:        for (x = 0; x < mem_cluster_cnt; x++) {
        !          1300:                seg_start = mem_clusters[x].start;
        !          1301:                seg_end = mem_clusters[x].start + mem_clusters[x].size;
        !          1302:                seg_start1 = 0;
        !          1303:                seg_end1 = 0;
        !          1304:
        !          1305:                if (seg_start > 0xffffffffULL) {
        !          1306:                        printf("skipping %lld bytes of memory above 4GB\n",
        !          1307:                            seg_end - seg_start);
        !          1308:                        continue;
        !          1309:                }
        !          1310:                if (seg_end > 0x100000000ULL) {
        !          1311:                        printf("skipping %lld bytes of memory above 4GB\n",
        !          1312:                            seg_end - 0x100000000ULL);
        !          1313:                        seg_end = 0x100000000ULL;
        !          1314:                }
        !          1315:
        !          1316:                /*
        !          1317:                 * Skip memory before our available starting point.
        !          1318:                 */
        !          1319:                if (seg_end <= avail_start)
        !          1320:                        continue;
        !          1321:
        !          1322:                if (avail_start >= seg_start && avail_start < seg_end) {
        !          1323:                        if (seg_start != 0)
        !          1324:                                panic("init_x86_64: memory doesn't start at 0");
        !          1325:                        seg_start = avail_start;
        !          1326:                        if (seg_start == seg_end)
        !          1327:                                continue;
        !          1328:                }
        !          1329:
        !          1330:                /*
        !          1331:                 * If this segment contains the kernel, split it
        !          1332:                 * in two, around the kernel.
        !          1333:                 */
        !          1334:                if (seg_start <= IOM_END && first_avail <= seg_end) {
        !          1335:                        seg_start1 = first_avail;
        !          1336:                        seg_end1 = seg_end;
        !          1337:                        seg_end = IOM_END;
        !          1338:                }
        !          1339:
        !          1340:                /* First hunk */
        !          1341:                if (seg_start != seg_end) {
        !          1342:                        if (seg_start <= (16 * 1024 * 1024) &&
        !          1343:                            first16q != VM_FREELIST_DEFAULT) {
        !          1344:                                u_int64_t tmp;
        !          1345:
        !          1346:                                if (seg_end > (16 * 1024 * 1024))
        !          1347:                                        tmp = (16 * 1024 * 1024);
        !          1348:                                else
        !          1349:                                        tmp = seg_end;
        !          1350: #if DEBUG_MEMLOAD
        !          1351:                                printf("loading 0x%qx-0x%qx (0x%lx-0x%lx)\n",
        !          1352:                                    (unsigned long long)seg_start,
        !          1353:                                    (unsigned long long)tmp,
        !          1354:                                    atop(seg_start), atop(tmp));
        !          1355: #endif
        !          1356:                                uvm_page_physload(atop(seg_start),
        !          1357:                                    atop(tmp), atop(seg_start),
        !          1358:                                    atop(tmp), first16q);
        !          1359:                                seg_start = tmp;
        !          1360:                        }
        !          1361:
        !          1362:                        if (seg_start != seg_end) {
        !          1363: #if DEBUG_MEMLOAD
        !          1364:                                printf("loading 0x%qx-0x%qx (0x%lx-0x%lx)\n",
        !          1365:                                    (unsigned long long)seg_start,
        !          1366:                                    (unsigned long long)seg_end,
        !          1367:                                    atop(seg_start), atop(seg_end));
        !          1368: #endif
        !          1369:                                uvm_page_physload(atop(seg_start),
        !          1370:                                    atop(seg_end), atop(seg_start),
        !          1371:                                    atop(seg_end), VM_FREELIST_DEFAULT);
        !          1372:                        }
        !          1373:                }
        !          1374:
        !          1375:                /* Second hunk */
        !          1376:                if (seg_start1 != seg_end1) {
        !          1377:                        if (seg_start1 <= (16 * 1024 * 1024) &&
        !          1378:                            first16q != VM_FREELIST_DEFAULT) {
        !          1379:                                u_int64_t tmp;
        !          1380:
        !          1381:                                if (seg_end1 > (16 * 1024 * 1024))
        !          1382:                                        tmp = (16 * 1024 * 1024);
        !          1383:                                else
        !          1384:                                        tmp = seg_end1;
        !          1385: #if DEBUG_MEMLOAD
        !          1386:                                printf("loading 0x%qx-0x%qx (0x%lx-0x%lx)\n",
        !          1387:                                    (unsigned long long)seg_start1,
        !          1388:                                    (unsigned long long)tmp,
        !          1389:                                    atop(seg_start1), atop(tmp));
        !          1390: #endif
        !          1391:                                uvm_page_physload(atop(seg_start1),
        !          1392:                                    atop(tmp), atop(seg_start1),
        !          1393:                                    atop(tmp), first16q);
        !          1394:                                seg_start1 = tmp;
        !          1395:                        }
        !          1396:
        !          1397:                        if (seg_start1 != seg_end1) {
        !          1398: #if DEBUG_MEMLOAD
        !          1399:                                printf("loading 0x%qx-0x%qx (0x%lx-0x%lx)\n",
        !          1400:                                    (unsigned long long)seg_start1,
        !          1401:                                    (unsigned long long)seg_end1,
        !          1402:                                    atop(seg_start1), atop(seg_end1));
        !          1403: #endif
        !          1404:                                uvm_page_physload(atop(seg_start1),
        !          1405:                                    atop(seg_end1), atop(seg_start1),
        !          1406:                                    atop(seg_end1), VM_FREELIST_DEFAULT);
        !          1407:                        }
        !          1408:                }
        !          1409:        }
        !          1410:
        !          1411:        /*
        !          1412:         * Steal memory for the message buffer (at end of core).
        !          1413:         */
        !          1414:        {
        !          1415:                struct vm_physseg *vps = NULL;
        !          1416:                psize_t sz = round_page(MSGBUFSIZE);
        !          1417:                psize_t reqsz = sz;
        !          1418:
        !          1419:                for (x = 0; x < vm_nphysseg; x++) {
        !          1420:                        vps = &vm_physmem[x];
        !          1421:                        if (ptoa(vps->avail_end) == avail_end)
        !          1422:                                break;
        !          1423:                }
        !          1424:                if (x == vm_nphysseg)
        !          1425:                        panic("init_x86_64: can't find end of memory");
        !          1426:
        !          1427:                /* Shrink so it'll fit in the last segment. */
        !          1428:                if ((vps->avail_end - vps->avail_start) < atop(sz))
        !          1429:                        sz = ptoa(vps->avail_end - vps->avail_start);
        !          1430:
        !          1431:                vps->avail_end -= atop(sz);
        !          1432:                vps->end -= atop(sz);
        !          1433:                msgbuf_paddr = ptoa(vps->avail_end);
        !          1434:
        !          1435:                /* Remove the last segment if it now has no pages. */
        !          1436:                if (vps->start == vps->end) {
        !          1437:                        for (vm_nphysseg--; x < vm_nphysseg; x++)
        !          1438:                                vm_physmem[x] = vm_physmem[x + 1];
        !          1439:                }
        !          1440:
        !          1441:                /* Now find where the new avail_end is. */
        !          1442:                for (avail_end = 0, x = 0; x < vm_nphysseg; x++)
        !          1443:                        if (vm_physmem[x].avail_end > avail_end)
        !          1444:                                avail_end = vm_physmem[x].avail_end;
        !          1445:                avail_end = ptoa(avail_end);
        !          1446:
        !          1447:                /* Warn if the message buffer had to be shrunk. */
        !          1448:                if (sz != reqsz)
        !          1449:                        printf("WARNING: %ld bytes not available for msgbuf "
        !          1450:                            "in last cluster (%ld used)\n", reqsz, sz);
        !          1451:        }
        !          1452:
        !          1453:        /*
        !          1454:         * XXXfvdl todo: acpi wakeup code.
        !          1455:         */
        !          1456:
        !          1457:        pmap_growkernel(VM_MIN_KERNEL_ADDRESS + 32 * 1024 * 1024);
        !          1458:
        !          1459:        pmap_kenter_pa(idt_vaddr, idt_paddr, VM_PROT_READ|VM_PROT_WRITE);
        !          1460:        pmap_kenter_pa(idt_vaddr + PAGE_SIZE, idt_paddr + PAGE_SIZE,
        !          1461:            VM_PROT_READ|VM_PROT_WRITE);
        !          1462:
        !          1463:        pmap_kenter_pa(lo32_vaddr, lo32_paddr, VM_PROT_READ|VM_PROT_WRITE);
        !          1464:
        !          1465:        idt = (struct gate_descriptor *)idt_vaddr;
        !          1466:        gdtstore = (char *)(idt + NIDT);
        !          1467:        ldtstore = gdtstore + DYNSEL_START;
        !          1468:
        !          1469:        /* make gdt gates and memory segments */
        !          1470:        set_mem_segment(GDT_ADDR_MEM(gdtstore, GCODE_SEL), 0, 0xfffff, SDT_MEMERA,
        !          1471:            SEL_KPL, 1, 0, 1);
        !          1472:
        !          1473:        set_mem_segment(GDT_ADDR_MEM(gdtstore, GDATA_SEL), 0, 0xfffff, SDT_MEMRWA,
        !          1474:            SEL_KPL, 1, 0, 1);
        !          1475:
        !          1476:        set_sys_segment(GDT_ADDR_SYS(gdtstore, GLDT_SEL), ldtstore, LDT_SIZE - 1,
        !          1477:            SDT_SYSLDT, SEL_KPL, 0);
        !          1478:
        !          1479:        set_mem_segment(GDT_ADDR_MEM(gdtstore, GUCODE_SEL), 0,
        !          1480:            atop(VM_MAXUSER_ADDRESS) - 1, SDT_MEMERA, SEL_UPL, 1, 0, 1);
        !          1481:
        !          1482:        set_mem_segment(GDT_ADDR_MEM(gdtstore, GUDATA_SEL), 0,
        !          1483:            atop(VM_MAXUSER_ADDRESS) - 1, SDT_MEMRWA, SEL_UPL, 1, 0, 1);
        !          1484:
        !          1485:        /* make ldt gates and memory segments */
        !          1486:        setgate((struct gate_descriptor *)(ldtstore + LSYS5CALLS_SEL),
        !          1487:            &IDTVEC(oosyscall), 0, SDT_SYS386CGT, SEL_UPL,
        !          1488:            GSEL(GCODE_SEL, SEL_KPL));
        !          1489:
        !          1490:        *(struct mem_segment_descriptor *)(ldtstore + LUCODE_SEL) =
        !          1491:            *GDT_ADDR_MEM(gdtstore, GUCODE_SEL);
        !          1492:        *(struct mem_segment_descriptor *)(ldtstore + LUDATA_SEL) =
        !          1493:            *GDT_ADDR_MEM(gdtstore, GUDATA_SEL);
        !          1494:
        !          1495:        /*
        !          1496:         * 32 bit GDT entries.
        !          1497:         */
        !          1498:
        !          1499:        set_mem_segment(GDT_ADDR_MEM(gdtstore, GUCODE32_SEL), 0,
        !          1500:            atop(VM_MAXUSER_ADDRESS) - 1, SDT_MEMERA, SEL_UPL, 1, 1, 0);
        !          1501:
        !          1502:        set_mem_segment(GDT_ADDR_MEM(gdtstore, GUDATA32_SEL), 0,
        !          1503:            atop(VM_MAXUSER_ADDRESS) - 1, SDT_MEMRWA, SEL_UPL, 1, 1, 0);
        !          1504:
        !          1505:        /*
        !          1506:         * 32 bit LDT entries.
        !          1507:         */
        !          1508:        ldt_segp = (struct mem_segment_descriptor *)(ldtstore + LUCODE32_SEL);
        !          1509:        set_mem_segment(ldt_segp, 0, atop(VM_MAXUSER_ADDRESS32) - 1,
        !          1510:            SDT_MEMERA, SEL_UPL, 1, 1, 0);
        !          1511:        ldt_segp = (struct mem_segment_descriptor *)(ldtstore + LUDATA32_SEL);
        !          1512:        set_mem_segment(ldt_segp, 0, atop(VM_MAXUSER_ADDRESS32) - 1,
        !          1513:            SDT_MEMRWA, SEL_UPL, 1, 1, 0);
        !          1514:
        !          1515:        /*
        !          1516:         * Other entries.
        !          1517:         */
        !          1518:        memcpy((struct gate_descriptor *)(ldtstore + LSOL26CALLS_SEL),
        !          1519:            (struct gate_descriptor *)(ldtstore + LSYS5CALLS_SEL),
        !          1520:            sizeof (struct gate_descriptor));
        !          1521:        memcpy((struct gate_descriptor *)(ldtstore + LBSDICALLS_SEL),
        !          1522:            (struct gate_descriptor *)(ldtstore + LSYS5CALLS_SEL),
        !          1523:            sizeof (struct gate_descriptor));
        !          1524:
        !          1525:        /* exceptions */
        !          1526:        for (x = 0; x < 32; x++) {
        !          1527:                ist = (x == 8) ? 1 : 0;
        !          1528:                setgate(&idt[x], IDTVEC(exceptions)[x], ist, SDT_SYS386IGT,
        !          1529:                    (x == 3 || x == 4) ? SEL_UPL : SEL_KPL,
        !          1530:                    GSEL(GCODE_SEL, SEL_KPL));
        !          1531:                idt_allocmap[x] = 1;
        !          1532:        }
        !          1533:
        !          1534:        /* new-style interrupt gate for syscalls */
        !          1535:        setgate(&idt[128], &IDTVEC(osyscall), 0, SDT_SYS386IGT, SEL_UPL,
        !          1536:            GSEL(GCODE_SEL, SEL_KPL));
        !          1537:        idt_allocmap[128] = 1;
        !          1538:
        !          1539:        setregion(&region, gdtstore, DYNSEL_START - 1);
        !          1540:        lgdt(&region);
        !          1541:
        !          1542:        cpu_init_idt();
        !          1543:
        !          1544: #ifdef DDB
        !          1545:        db_machine_init();
        !          1546:        ddb_init();
        !          1547:        if (boothowto & RB_KDB)
        !          1548:                Debugger();
        !          1549: #endif
        !          1550: #ifdef KGDB
        !          1551:        kgdb_port_init();
        !          1552:        if (boothowto & RB_KDB) {
        !          1553:                kgdb_debug_init = 1;
        !          1554:                kgdb_connect(1);
        !          1555:        }
        !          1556: #endif
        !          1557:
        !          1558:        intr_default_setup();
        !          1559:
        !          1560:        softintr_init();
        !          1561:        splraise(IPL_IPI);
        !          1562:        enable_intr();
        !          1563:
        !          1564:         /* Make sure maxproc is sane */
        !          1565:         if (maxproc > cpu_maxproc())
        !          1566:                 maxproc = cpu_maxproc();
        !          1567: }
        !          1568:
        !          1569: #ifdef KGDB
        !          1570: void
        !          1571: kgdb_port_init(void)
        !          1572: {
        !          1573: #if NCOM > 0
        !          1574:        if (!strcmp(kgdb_devname, "com")) {
        !          1575:                bus_space_tag_t tag = X86_BUS_SPACE_IO;
        !          1576:                com_kgdb_attach(tag, comkgdbaddr, comkgdbrate, COM_FREQ,
        !          1577:                    comkgdbmode);
        !          1578:        }
        !          1579: #endif
        !          1580: }
        !          1581: #endif /* KGDB */
        !          1582:
        !          1583: void
        !          1584: cpu_reset(void)
        !          1585: {
        !          1586:
        !          1587:        disable_intr();
        !          1588:
        !          1589:        /*
        !          1590:         * The keyboard controller has 4 random output pins, one of which is
        !          1591:         * connected to the RESET pin on the CPU in many PCs.  We tell the
        !          1592:         * keyboard controller to pulse this line a couple of times.
        !          1593:         */
        !          1594:        outb(IO_KBD + KBCMDP, KBC_PULSE0);
        !          1595:        delay(100000);
        !          1596:        outb(IO_KBD + KBCMDP, KBC_PULSE0);
        !          1597:        delay(100000);
        !          1598:
        !          1599:        /*
        !          1600:         * Try to cause a triple fault and watchdog reset by making the IDT
        !          1601:         * invalid and causing a fault.
        !          1602:         */
        !          1603:        memset((caddr_t)idt, 0, NIDT * sizeof(idt[0]));
        !          1604:        __asm __volatile("divl %0,%1" : : "q" (0), "a" (0));
        !          1605:
        !          1606: #if 0
        !          1607:        /*
        !          1608:         * Try to cause a triple fault and watchdog reset by unmapping the
        !          1609:         * entire address space and doing a TLB flush.
        !          1610:         */
        !          1611:        memset((caddr_t)PTD, 0, PAGE_SIZE);
        !          1612:        tlbflush();
        !          1613: #endif
        !          1614:
        !          1615:        for (;;);
        !          1616: }
        !          1617:
        !          1618: /*
        !          1619:  * cpu_dumpsize: calculate size of machine-dependent kernel core dump headers.
        !          1620:  */
        !          1621: int
        !          1622: cpu_dumpsize(void)
        !          1623: {
        !          1624:        int size;
        !          1625:
        !          1626:        size = ALIGN(sizeof(kcore_seg_t)) +
        !          1627:            ALIGN(mem_cluster_cnt * sizeof(phys_ram_seg_t));
        !          1628:        if (roundup(size, dbtob(1)) != dbtob(1))
        !          1629:                return (-1);
        !          1630:
        !          1631:        return (1);
        !          1632: }
        !          1633:
        !          1634: /*
        !          1635:  * cpu_dump_mempagecnt: calculate the size of RAM (in pages) to be dumped.
        !          1636:  */
        !          1637: u_long
        !          1638: cpu_dump_mempagecnt(void)
        !          1639: {
        !          1640:        u_long i, n;
        !          1641:
        !          1642:        n = 0;
        !          1643:        for (i = 0; i < mem_cluster_cnt; i++)
        !          1644:                n += atop(mem_clusters[i].size);
        !          1645:        return (n);
        !          1646: }
        !          1647:
        !          1648: void
        !          1649: cpu_initclocks(void)
        !          1650: {
        !          1651:        (*initclock_func)();
        !          1652:
        !          1653:        if (initclock_func == i8254_initclocks)
        !          1654:                i8254_inittimecounter();
        !          1655:        else
        !          1656:                i8254_inittimecounter_simple();
        !          1657: }
        !          1658:
        !          1659: void
        !          1660: need_resched(struct cpu_info *ci)
        !          1661: {
        !          1662:        ci->ci_want_resched = 1;
        !          1663:        if ((ci)->ci_curproc != NULL)
        !          1664:                aston((ci)->ci_curproc);
        !          1665: }
        !          1666:
        !          1667: /*
        !          1668:  * Allocate an IDT vector slot within the given range.
        !          1669:  * XXX needs locking to avoid MP allocation races.
        !          1670:  * XXXfvdl share idt code
        !          1671:  */
        !          1672:
        !          1673: int
        !          1674: idt_vec_alloc(int low, int high)
        !          1675: {
        !          1676:        int vec;
        !          1677:
        !          1678:        simple_lock(&idt_lock);
        !          1679:        for (vec = low; vec <= high; vec++) {
        !          1680:                if (idt_allocmap[vec] == 0) {
        !          1681:                        idt_allocmap[vec] = 1;
        !          1682:                        simple_unlock(&idt_lock);
        !          1683:                        return vec;
        !          1684:                }
        !          1685:        }
        !          1686:        simple_unlock(&idt_lock);
        !          1687:        return 0;
        !          1688: }
        !          1689:
        !          1690: void
        !          1691: idt_vec_set(int vec, void (*function)(void))
        !          1692: {
        !          1693:        /*
        !          1694:         * Vector should be allocated, so no locking needed.
        !          1695:         */
        !          1696:        KASSERT(idt_allocmap[vec] == 1);
        !          1697:        setgate(&idt[vec], function, 0, SDT_SYS386IGT, SEL_KPL,
        !          1698:            GSEL(GCODE_SEL, SEL_KPL));
        !          1699: }
        !          1700:
        !          1701: void
        !          1702: idt_vec_free(int vec)
        !          1703: {
        !          1704:        simple_lock(&idt_lock);
        !          1705:        unsetgate(&idt[vec]);
        !          1706:        idt_allocmap[vec] = 0;
        !          1707:        simple_unlock(&idt_lock);
        !          1708: }
        !          1709:
        !          1710: /*
        !          1711:  * Number of processes is limited by number of available GDT slots.
        !          1712:  */
        !          1713: int
        !          1714: cpu_maxproc(void)
        !          1715: {
        !          1716: #ifdef USER_LDT
        !          1717:        return ((MAXGDTSIZ - DYNSEL_START) / 32);
        !          1718: #else
        !          1719:        return (MAXGDTSIZ - DYNSEL_START) / 16;
        !          1720: #endif
        !          1721: }
        !          1722:
        !          1723: #ifdef DIAGNOSTIC
        !          1724: void
        !          1725: splassert_check(int wantipl, const char *func)
        !          1726: {
        !          1727:        int cpl = curcpu()->ci_ilevel;
        !          1728:
        !          1729:        if (cpl < wantipl) {
        !          1730:                splassert_fail(wantipl, cpl, func);
        !          1731:        }
        !          1732: }
        !          1733: #endif
        !          1734:
        !          1735: void
        !          1736: getbootinfo(char *bootinfo, int bootinfo_size)
        !          1737: {
        !          1738:        bootarg32_t *q;
        !          1739:
        !          1740: #undef BOOTINFO_DEBUG
        !          1741: #ifdef BOOTINFO_DEBUG
        !          1742:        printf("bootargv:");
        !          1743: #endif
        !          1744:
        !          1745:        for (q = (bootarg32_t *)bootinfo;
        !          1746:            (q->ba_type != BOOTARG_END) &&
        !          1747:            ((((char *)q) - bootinfo) < bootinfo_size);
        !          1748:            q = (bootarg32_t *)(((char *)q) + q->ba_size)) {
        !          1749:
        !          1750:                switch (q->ba_type) {
        !          1751:                case BOOTARG_MEMMAP:
        !          1752:                        bios_memmap = (bios_memmap_t *)q->ba_arg;
        !          1753: #ifdef BOOTINFO_DEBUG
        !          1754:                        printf(" memmap %p", bios_memmap);
        !          1755: #endif
        !          1756:                        break;
        !          1757:                case BOOTARG_DISKINFO:
        !          1758:                        bios_diskinfo = (bios_diskinfo_t *)q->ba_arg;
        !          1759: #ifdef BOOTINFO_DEBUG
        !          1760:                        printf(" diskinfo %p", bios_diskinfo);
        !          1761: #endif
        !          1762:                        break;
        !          1763: #if 0
        !          1764: #if NAPM > 0 || defined(DEBUG)
        !          1765:                case BOOTARG_APMINFO:
        !          1766: #ifdef BOOTINFO_DEBUG
        !          1767:                        printf(" apminfo %p", q->ba_arg);
        !          1768: #endif
        !          1769:                        apm = (bios_apminfo_t *)q->ba_arg;
        !          1770:                        break;
        !          1771: #endif
        !          1772: #endif
        !          1773:                case BOOTARG_CKSUMLEN:
        !          1774:                        bios_cksumlen = *(u_int32_t *)q->ba_arg;
        !          1775: #ifdef BOOTINFO_DEBUG
        !          1776:                        printf(" cksumlen %d", bios_cksumlen);
        !          1777: #endif
        !          1778:                        break;
        !          1779: #if 0
        !          1780: #if NPCI > 0
        !          1781:                case BOOTARG_PCIINFO:
        !          1782:                        bios_pciinfo = (bios_pciinfo_t *)q->ba_arg;
        !          1783: #ifdef BOOTINFO_DEBUG
        !          1784:                        printf(" pciinfo %p", bios_pciinfo);
        !          1785: #endif
        !          1786:                        break;
        !          1787: #endif
        !          1788: #endif
        !          1789:                case BOOTARG_CONSDEV:
        !          1790:                        if (q->ba_size >= sizeof(bios_consdev_t))
        !          1791:                        {
        !          1792:                                bios_consdev_t *cdp =
        !          1793:                                    (bios_consdev_t*)q->ba_arg;
        !          1794: #include "com.h"
        !          1795: #if NCOM > 0
        !          1796:                                extern int comdefaultrate; /* ic/com.c */
        !          1797:                                comdefaultrate = cdp->conspeed;
        !          1798: #endif
        !          1799: #ifdef BOOTINFO_DEBUG
        !          1800:                                printf(" console 0x%x:%d",
        !          1801:                                    cdp->consdev, cdp->conspeed);
        !          1802: #endif
        !          1803:                                cnset(cdp->consdev);
        !          1804:                        }
        !          1805:                        break;
        !          1806: #ifdef NFSCLIENT
        !          1807:                case BOOTARG_BOOTMAC:
        !          1808:                        bios_bootmac = (bios_bootmac_t *)q->ba_arg;
        !          1809:                        break;
        !          1810: #endif
        !          1811:
        !          1812:                default:
        !          1813: #ifdef BOOTINFO_DEBUG
        !          1814:                        printf(" unsupported arg (%d) %p", q->ba_type,
        !          1815:                            q->ba_arg);
        !          1816: #endif
        !          1817:                        break;
        !          1818:                }
        !          1819:        }
        !          1820: #ifdef BOOTINFO_DEBUG
        !          1821:        printf("\n");
        !          1822: #endif
        !          1823: }
        !          1824:
        !          1825: int
        !          1826: check_context(const struct reg *regs, struct trapframe *tf)
        !          1827: {
        !          1828:        uint16_t sel;
        !          1829:
        !          1830:        if (((regs->r_rflags ^ tf->tf_rflags) & PSL_USERSTATIC) != 0)
        !          1831:                return EINVAL;
        !          1832:
        !          1833:        sel = regs->r_es & 0xffff;
        !          1834:        if (sel != 0 && !VALID_USER_DSEL(sel))
        !          1835:                return EINVAL;
        !          1836:
        !          1837:        sel = regs->r_fs & 0xffff;
        !          1838:        if (sel != 0 && !VALID_USER_DSEL(sel))
        !          1839:                return EINVAL;
        !          1840:
        !          1841:        sel = regs->r_gs & 0xffff;
        !          1842:        if (sel != 0 && !VALID_USER_DSEL(sel))
        !          1843:                return EINVAL;
        !          1844:
        !          1845:        sel = regs->r_ds & 0xffff;
        !          1846:        if (!VALID_USER_DSEL(sel))
        !          1847:                return EINVAL;
        !          1848:
        !          1849:        sel = regs->r_ss & 0xffff;
        !          1850:        if (!VALID_USER_DSEL(sel))
        !          1851:                return EINVAL;
        !          1852:
        !          1853:        sel = regs->r_cs & 0xffff;
        !          1854:        if (!VALID_USER_CSEL(sel))
        !          1855:                return EINVAL;
        !          1856:
        !          1857:        if (regs->r_rip >= VM_MAXUSER_ADDRESS)
        !          1858:                return EINVAL;
        !          1859:
        !          1860:        return 0;
        !          1861: }

CVSweb