[BACK]Return to machdep.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / arch / i386 / i386

Annotation of src/sys/arch/i386/i386/machdep.c, Revision 1.586.2.6

1.586.2.6! bouyer      1: /*     $NetBSD: machdep.c,v 1.586.2.5 2007/08/28 11:46:26 liamjfoy Exp $       */
1.231     thorpej     2:
                      3: /*-
1.571     jmmv        4:  * Copyright (c) 1996, 1997, 1998, 2000, 2004, 2006 The NetBSD Foundation, Inc.
1.231     thorpej     5:  * All rights reserved.
                      6:  *
                      7:  * This code is derived from software contributed to The NetBSD Foundation
1.571     jmmv        8:  * by Charles M. Hannum, by Jason R. Thorpe of the Numerical Aerospace
                      9:  * Simulation Facility, NASA Ames Research Center and by Julio M. Merino Vidal.
1.231     thorpej    10:  *
                     11:  * Redistribution and use in source and binary forms, with or without
                     12:  * modification, are permitted provided that the following conditions
                     13:  * are met:
                     14:  * 1. Redistributions of source code must retain the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer.
                     16:  * 2. Redistributions in binary form must reproduce the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer in the
                     18:  *    documentation and/or other materials provided with the distribution.
                     19:  * 3. All advertising materials mentioning features or use of this software
                     20:  *    must display the following acknowledgement:
                     21:  *     This product includes software developed by the NetBSD
                     22:  *     Foundation, Inc. and its contributors.
                     23:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     24:  *    contributors may be used to endorse or promote products derived
                     25:  *    from this software without specific prior written permission.
                     26:  *
                     27:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     28:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     29:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     30:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     31:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     32:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     33:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     34:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     35:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     36:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     37:  * POSSIBILITY OF SUCH DAMAGE.
                     38:  */
1.125     cgd        39:
1.1       cgd        40: /*-
                     41:  * Copyright (c) 1982, 1987, 1990 The Regents of the University of California.
                     42:  * All rights reserved.
                     43:  *
                     44:  * This code is derived from software contributed to Berkeley by
                     45:  * William Jolitz.
                     46:  *
                     47:  * Redistribution and use in source and binary forms, with or without
                     48:  * modification, are permitted provided that the following conditions
                     49:  * are met:
                     50:  * 1. Redistributions of source code must retain the above copyright
                     51:  *    notice, this list of conditions and the following disclaimer.
                     52:  * 2. Redistributions in binary form must reproduce the above copyright
                     53:  *    notice, this list of conditions and the following disclaimer in the
                     54:  *    documentation and/or other materials provided with the distribution.
1.528     agc        55:  * 3. Neither the name of the University nor the names of its contributors
1.1       cgd        56:  *    may be used to endorse or promote products derived from this software
                     57:  *    without specific prior written permission.
                     58:  *
                     59:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     60:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     61:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     62:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     63:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     64:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     65:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     66:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     67:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     68:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     69:  * SUCH DAMAGE.
                     70:  *
1.125     cgd        71:  *     @(#)machdep.c   7.4 (Berkeley) 6/3/91
1.1       cgd        72:  */
1.460     lukem      73:
                     74: #include <sys/cdefs.h>
1.586.2.6! bouyer     75: __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.586.2.5 2007/08/28 11:46:26 liamjfoy Exp $");
1.271     thorpej    76:
1.538     christos   77: #include "opt_beep.h"
                     78: #include "opt_compat_ibcs2.h"
                     79: #include "opt_compat_mach.h"   /* need to get the right segment def */
                     80: #include "opt_compat_netbsd.h"
                     81: #include "opt_compat_svr4.h"
                     82: #include "opt_cpureset_delay.h"
1.271     thorpej    83: #include "opt_cputype.h"
1.309     jonathan   84: #include "opt_ddb.h"
1.377     ws         85: #include "opt_ipkdb.h"
1.443     lukem      86: #include "opt_kgdb.h"
1.455     fvdl       87: #include "opt_mtrr.h"
1.523     martin     88: #include "opt_multiprocessor.h"
1.538     christos   89: #include "opt_realmem.h"
                     90: #include "opt_user_ldt.h"
                     91: #include "opt_vm86.h"
1.1       cgd        92:
1.59      mycroft    93: #include <sys/param.h>
                     94: #include <sys/systm.h>
1.508     thorpej    95: #include <sys/signal.h>
1.59      mycroft    96: #include <sys/signalvar.h>
                     97: #include <sys/kernel.h>
                     98: #include <sys/proc.h>
                     99: #include <sys/user.h>
                    100: #include <sys/exec.h>
                    101: #include <sys/buf.h>
                    102: #include <sys/reboot.h>
                    103: #include <sys/conf.h>
                    104: #include <sys/file.h>
                    105: #include <sys/malloc.h>
                    106: #include <sys/mbuf.h>
                    107: #include <sys/msgbuf.h>
                    108: #include <sys/mount.h>
                    109: #include <sys/vnode.h>
1.204     thorpej   110: #include <sys/extent.h>
1.123     cgd       111: #include <sys/syscallargs.h>
1.291     thorpej   112: #include <sys/core.h>
                    113: #include <sys/kcore.h>
1.508     thorpej   114: #include <sys/ucontext.h>
1.519     nathanw   115: #include <sys/ras.h>
1.508     thorpej   116: #include <sys/sa.h>
                    117: #include <sys/savar.h>
1.522     ragge     118: #include <sys/ksyms.h>
1.57      cgd       119:
1.377     ws        120: #ifdef IPKDB
                    121: #include <ipkdb/ipkdb.h>
                    122: #endif
                    123:
1.235     thorpej   124: #ifdef KGDB
                    125: #include <sys/kgdb.h>
                    126: #endif
                    127:
1.104     cgd       128: #include <dev/cons.h>
1.390     mrg       129:
                    130: #include <uvm/uvm_extern.h>
1.393     fvdl      131: #include <uvm/uvm_page.h>
1.284     mrg       132:
1.200     christos  133: #include <sys/sysctl.h>
                    134:
1.586.2.4  bouyer    135: #include <x86/cpu_msr.h>
                    136:
1.59      mycroft   137: #include <machine/cpu.h>
                    138: #include <machine/cpufunc.h>
1.484     fvdl      139: #include <machine/cpuvar.h>
1.178     mycroft   140: #include <machine/gdt.h>
1.574     kardel    141: #include <machine/kcore.h>
1.149     mycroft   142: #include <machine/pio.h>
1.59      mycroft   143: #include <machine/psl.h>
                    144: #include <machine/reg.h>
                    145: #include <machine/specialreg.h>
1.255     drochner  146: #include <machine/bootinfo.h>
1.455     fvdl      147: #include <machine/mtrr.h>
1.574     kardel    148: #include <x86/x86/tsc.h>
                    149:
1.570     jmmv      150: #include <machine/multiboot.h>
1.43      brezak    151:
1.146     cgd       152: #include <dev/isa/isareg.h>
1.372     drochner  153: #include <machine/isa_machdep.h>
1.164     cgd       154: #include <dev/ic/i8042reg.h>
1.43      brezak    155:
1.200     christos  156: #ifdef DDB
                    157: #include <machine/db_machdep.h>
                    158: #include <ddb/db_extern.h>
                    159: #endif
                    160:
1.184     mycroft   161: #ifdef VM86
                    162: #include <machine/vm86.h>
                    163: #endif
                    164:
1.473     tshiozak  165: #include "acpi.h"
1.576     christos  166: #include "apmbios.h"
1.258     jtk       167: #include "bioscall.h"
1.207     jtk       168:
1.259     jtk       169: #if NBIOSCALL > 0
                    170: #include <machine/bioscall.h>
                    171: #endif
                    172:
1.473     tshiozak  173: #if NACPI > 0
                    174: #include <dev/acpi/acpivar.h>
                    175: #define ACPI_MACHDEP_PRIVATE
                    176: #include <machine/acpi_machdep.h>
                    177: #endif
                    178:
1.576     christos  179: #if NAPMBIOS > 0
1.207     jtk       180: #include <machine/apmvar.h>
1.258     jtk       181: #endif
                    182:
1.59      mycroft   183: #include "isa.h"
1.231     thorpej   184: #include "isadma.h"
1.59      mycroft   185: #include "npx.h"
1.522     ragge     186: #include "ksyms.h"
1.2       cgd       187:
1.586.2.3  jdc       188: #include "cardbus.h"
                    189: #if NCARDBUS > 0
                    190: /* For rbus_min_start hint. */
                    191: #include <machine/bus.h>
                    192: #include <dev/cardbus/rbus.h>
                    193: #include <machine/rbus_machdep.h>
                    194: #endif
                    195:
1.384     jdolecek  196: #include "mca.h"
                    197: #if NMCA > 0
                    198: #include <machine/mca_machdep.h>       /* for mca_busprobe() */
                    199: #endif
                    200:
1.484     fvdl      201: #ifdef MULTIPROCESSOR          /* XXX */
                    202: #include <machine/mpbiosvar.h> /* XXX */
                    203: #endif                         /* XXX */
                    204:
1.517     jmmv      205: #ifndef BEEP_ONHALT_COUNT
                    206: #define BEEP_ONHALT_COUNT 3
                    207: #endif
                    208: #ifndef BEEP_ONHALT_PITCH
                    209: #define BEEP_ONHALT_PITCH 1500
                    210: #endif
                    211: #ifndef BEEP_ONHALT_PERIOD
                    212: #define BEEP_ONHALT_PERIOD 250
                    213: #endif
                    214:
1.104     cgd       215: /* the following is used externally (sysctl_hw) */
1.549     wiz       216: char machine[] = "i386";               /* CPU "architecture" */
1.232     veego     217: char machine_arch[] = "i386";          /* machine == machine_arch */
1.104     cgd       218:
1.559     thorpej   219: extern struct bi_devmatch *x86_alldisks;
                    220: extern int x86_ndisks;
1.342     fvdl      221:
1.328     bouyer    222: #ifdef CPURESET_DELAY
                    223: int    cpureset_delay = CPURESET_DELAY;
                    224: #else
                    225: int     cpureset_delay = 2000; /* default to 2s */
                    226: #endif
                    227:
1.455     fvdl      228: #ifdef MTRR
1.513     fvdl      229: struct mtrr_funcs *mtrr_funcs;
1.455     fvdl      230: #endif
                    231:
1.515     fvdl      232: #ifdef COMPAT_NOMID
1.566     christos  233: static int exec_nomid(struct lwp *, struct exec_package *);
1.550     junyoung  234: #endif
1.515     fvdl      235:
1.59      mycroft   236: int    physmem;
1.163     cgd       237: int    dumpmem_low;
                    238: int    dumpmem_high;
1.524     drochner  239: unsigned int cpu_feature;
1.553     lukem     240: unsigned int cpu_feature2;
1.59      mycroft   241: int    cpu_class;
1.428     fvdl      242: int    i386_fpu_present;
                    243: int    i386_fpu_exception;
                    244: int    i386_fpu_fdivbug;
1.59      mycroft   245:
1.451     thorpej   246: int    i386_use_fxsave;
                    247: int    i386_has_sse;
                    248: int    i386_has_sse2;
1.450     thorpej   249:
1.461     christos  250: int    tmx86_has_longrun;
                    251:
1.314     thorpej   252: vaddr_t        msgbuf_vaddr;
1.586.2.1  tron      253: struct {
                    254:        paddr_t paddr;
                    255:        psize_t sz;
                    256: } msgbuf_p_seg[VM_PHYSSEG_MAX];
                    257: unsigned int msgbuf_p_cnt = 0;
1.314     thorpej   258:
                    259: vaddr_t        idt_vaddr;
                    260: paddr_t        idt_paddr;
                    261:
1.264     mycroft   262: #ifdef I586_CPU
1.314     thorpej   263: vaddr_t        pentium_idt_vaddr;
1.264     mycroft   264: #endif
1.59      mycroft   265:
1.444     chs       266: struct vm_map *exec_map = NULL;
                    267: struct vm_map *mb_map = NULL;
                    268: struct vm_map *phys_map = NULL;
1.48      brezak    269:
1.314     thorpej   270: extern paddr_t avail_start, avail_end;
1.1       cgd       271:
1.542     junyoung  272: void (*delay_func)(int) = i8254_delay;
                    273: void (*initclock_func)(void) = i8254_initclocks;
1.484     fvdl      274:
1.204     thorpej   275: /*
1.291     thorpej   276:  * Size of memory segments, before any memory is stolen.
                    277:  */
                    278: phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX];
                    279: int    mem_cluster_cnt;
                    280:
1.542     junyoung  281: int    cpu_dump(void);
                    282: int    cpu_dumpsize(void);
                    283: u_long cpu_dump_mempagecnt(void);
                    284: void   dumpsys(void);
                    285: void   init386(paddr_t);
                    286: void   initgdt(union descriptor *);
1.255     drochner  287:
1.568     perry     288: void   add_mem_cluster(uint64_t, uint64_t, uint32_t);
1.433     kanaoka   289:
1.521     dsl       290: extern int time_adjusted;
1.484     fvdl      291:
1.571     jmmv      292: struct bootinfo        bootinfo;
                    293: int *esym;
                    294: extern int boothowto;
                    295:
                    296: /* Base memory reported by BIOS. */
                    297: #ifndef REALBASEMEM
                    298: int    biosbasemem = 0;
                    299: #else
                    300: int    biosbasemem = REALBASEMEM;
                    301: #endif
                    302:
                    303: /* Extended memory reported by BIOS. */
                    304: #ifndef REALEXTMEM
                    305: int    biosextmem = 0;
                    306: #else
                    307: int    biosextmem = REALEXTMEM;
                    308: #endif
                    309:
1.577     mrg       310: /* Set if any boot-loader set biosbasemem/biosextmem. */
                    311: int    biosmem_implicit;
                    312:
1.571     jmmv      313: /* Representation of the bootinfo structure constructed by a NetBSD native
                    314:  * boot loader.  Only be used by native_loader(). */
                    315: struct bootinfo_source {
                    316:        uint32_t bs_naddrs;
                    317:        paddr_t bs_addrs[1]; /* Actually longer. */
                    318: };
                    319:
                    320: /* Only called by locore.h; no need to be in a header file. */
                    321: void   native_loader(int, int, struct bootinfo_source *, paddr_t, int, int);
                    322:
                    323: /*
                    324:  * Called as one of the very first things during system startup (just after
                    325:  * the boot loader gave control to the kernel image), this routine is in
                    326:  * charge of retrieving the parameters passed in by the boot loader and
                    327:  * storing them in the appropriate kernel variables.
                    328:  *
                    329:  * WARNING: Because the kernel has not yet relocated itself to KERNBASE,
                    330:  * special care has to be taken when accessing memory because absolute
                    331:  * addresses (referring to kernel symbols) do not work.  So:
                    332:  *
                    333:  *     1) Avoid jumps to absolute addresses (such as gotos and switches).
                    334:  *     2) To access global variables use their physical address, which
                    335:  *        can be obtained using the RELOC macro.
                    336:  */
                    337: void
1.586     christos  338: native_loader(int bl_boothowto, int bl_bootdev,
1.571     jmmv      339:     struct bootinfo_source *bl_bootinfo, paddr_t bl_esym,
1.572     jmmv      340:     int bl_biosextmem, int bl_biosbasemem)
1.571     jmmv      341: {
                    342: #define RELOC(type, x) ((type)((vaddr_t)(x) - KERNBASE))
                    343:
                    344:        *RELOC(int *, &boothowto) = bl_boothowto;
                    345:
                    346: #ifdef COMPAT_OLDBOOT
                    347:        /*
                    348:         * Pre-1.3 boot loaders gave the boot device as a parameter
                    349:         * (instead of a bootinfo entry).
                    350:         */
                    351:        *RELOC(int *, &bootdev) = bl_bootdev;
                    352: #endif
                    353:
                    354:        /*
                    355:         * The boot loader provides a physical, non-relocated address
                    356:         * for the symbols table's end.  We need to convert it to a
                    357:         * virtual address.
                    358:         */
                    359:        if (bl_esym != 0)
                    360:                *RELOC(int **, &esym) = (int *)((vaddr_t)bl_esym + KERNBASE);
                    361:        else
                    362:                *RELOC(int **, &esym) = 0;
                    363:
                    364:        /*
                    365:         * Copy bootinfo entries (if any) from the boot loader's
                    366:         * representation to the kernel's bootinfo space.
                    367:         */
                    368:        if (bl_bootinfo != NULL) {
                    369:                size_t i;
                    370:                uint8_t *data;
                    371:                struct bootinfo *bidest;
                    372:
                    373:                bidest = RELOC(struct bootinfo *, &bootinfo);
                    374:
                    375:                data = &bidest->bi_data[0];
                    376:
                    377:                for (i = 0; i < bl_bootinfo->bs_naddrs; i++) {
                    378:                        struct btinfo_common *bc;
                    379:
                    380:                        bc = (struct btinfo_common *)(bl_bootinfo->bs_addrs[i]);
                    381:
                    382:                        if ((paddr_t)(data + bc->len) >
                    383:                            (paddr_t)(&bidest->bi_data[0] + BOOTINFO_MAXSIZE))
                    384:                                break;
                    385:
                    386:                        memcpy(data, bc, bc->len);
                    387:                        data += bc->len;
                    388:                }
                    389:                bidest->bi_nentries = i;
                    390:        }
                    391:
                    392:        /*
                    393:         * Configure biosbasemem and biosextmem only if they were not
                    394:         * explicitly given during the kernel's build.
                    395:         */
1.577     mrg       396:        if (*RELOC(int *, &biosbasemem) == 0) {
1.571     jmmv      397:                *RELOC(int *, &biosbasemem) = bl_biosbasemem;
1.577     mrg       398:                *RELOC(int *, &biosmem_implicit) = 1;
                    399:        }
                    400:        if (*RELOC(int *, &biosextmem) == 0) {
1.571     jmmv      401:                *RELOC(int *, &biosextmem) = bl_biosextmem;
1.577     mrg       402:                *RELOC(int *, &biosmem_implicit) = 1;
                    403:        }
1.571     jmmv      404: #undef RELOC
                    405: }
                    406:
1.59      mycroft   407: /*
                    408:  * Machine-dependent startup code
                    409:  */
1.32      andrew    410: void
1.1       cgd       411: cpu_startup()
                    412: {
1.586.2.1  tron      413:        int x, y;
1.314     thorpej   414:        vaddr_t minaddr, maxaddr;
1.586.2.1  tron      415:        psize_t sz;
1.354     lukem     416:        char pbuf[9];
1.1       cgd       417:
1.284     mrg       418:        /*
                    419:         * Initialize error message buffer (et end of core).
                    420:         */
1.586.2.1  tron      421:        if (msgbuf_p_cnt == 0)
                    422:                panic("msgbuf paddr map has not been set up");
                    423:        for (x = 0, sz = 0; x < msgbuf_p_cnt; sz += msgbuf_p_seg[x++].sz)
                    424:                continue;
                    425:        msgbuf_vaddr = uvm_km_alloc(kernel_map, sz, 0, UVM_KMF_VAONLY);
1.385     thorpej   426:        if (msgbuf_vaddr == 0)
1.284     mrg       427:                panic("failed to valloc msgbuf_vaddr");
1.359     thorpej   428:
1.284     mrg       429:        /* msgbuf_paddr was init'd in pmap */
1.586.2.1  tron      430:        for (y = 0, sz = 0; y < msgbuf_p_cnt; y++) {
                    431:                for (x = 0; x < btoc(msgbuf_p_seg[y].sz); x++, sz += PAGE_SIZE)
                    432:                        pmap_kenter_pa((vaddr_t)msgbuf_vaddr + sz,
                    433:                            msgbuf_p_seg[y].paddr + x * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE);
                    434:        }
1.456     chris     435:        pmap_update(pmap_kernel());
1.359     thorpej   436:
1.586.2.1  tron      437:        initmsgbuf((caddr_t)msgbuf_vaddr, sz);
1.284     mrg       438:
1.562     lukem     439:        printf("%s%s", copyright, version);
1.484     fvdl      440:
1.570     jmmv      441: #ifdef MULTIBOOT
                    442:        multiboot_print_info();
                    443: #endif
                    444:
1.484     fvdl      445: #ifdef TRAPLOG
                    446:        /*
                    447:         * Enable recording of branch from/to in MSR's
                    448:         */
                    449:        wrmsr(MSR_DEBUGCTLMSR, 0x1);
                    450: #endif
                    451:
1.382     mycroft   452:        format_bytes(pbuf, sizeof(pbuf), ptoa(physmem));
1.354     lukem     453:        printf("total memory = %s\n", pbuf);
1.1       cgd       454:
1.586.2.3  jdc       455: #if NCARDBUS > 0
                    456:        /* Tell RBUS how much RAM we have, so it can use heuristics. */
                    457:        rbus_min_start_hint(ptoa(physmem));
                    458: #endif
                    459:
1.547     pk        460:        minaddr = 0;
1.41      cgd       461:
1.1       cgd       462:        /*
1.36      cgd       463:         * Allocate a submap for exec arguments.  This map effectively
                    464:         * limits the number of processes exec'ing at any time.
1.1       cgd       465:         */
1.284     mrg       466:        exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
1.358     thorpej   467:                                   16*NCARGS, VM_MAP_PAGEABLE, FALSE, NULL);
1.59      mycroft   468:
1.1       cgd       469:        /*
                    470:         * Allocate a submap for physio
                    471:         */
1.284     mrg       472:        phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
1.358     thorpej   473:                                   VM_PHYS_SIZE, 0, FALSE, NULL);
1.1       cgd       474:
                    475:        /*
1.229     thorpej   476:         * Finally, allocate mbuf cluster submap.
1.1       cgd       477:         */
1.334     thorpej   478:        mb_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
1.358     thorpej   479:            nmbclusters * mclbytes, VM_MAP_INTRSAFE, FALSE, NULL);
1.1       cgd       480:
1.547     pk        481:        format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free));
1.354     lukem     482:        printf("avail memory = %s\n", pbuf);
1.1       cgd       483:
1.375     drochner  484:        /* Safe for i/o port / memory space allocation to use malloc now. */
1.514     fvdl      485:        x86_bus_space_mallocok();
1.586.2.4  bouyer    486:
                    487:        x86_init();
1.349     thorpej   488: }
                    489:
                    490: /*
                    491:  * Set up proc0's TSS and LDT.
                    492:  */
                    493: void
                    494: i386_proc0_tss_ldt_init()
                    495: {
                    496:        struct pcb *pcb;
                    497:        int x;
1.268     thorpej   498:
1.326     thorpej   499:        gdt_init();
1.484     fvdl      500:
1.508     thorpej   501:        cpu_info_primary.ci_curpcb = pcb = &lwp0.l_addr->u_pcb;
1.484     fvdl      502:
1.326     thorpej   503:        pcb->pcb_tss.tss_ioopt =
                    504:            ((caddr_t)pcb->pcb_iomap - (caddr_t)&pcb->pcb_tss) << 16;
1.484     fvdl      505:
1.326     thorpej   506:        for (x = 0; x < sizeof(pcb->pcb_iomap) / 4; x++)
                    507:                pcb->pcb_iomap[x] = 0xffffffff;
                    508:
1.394     thorpej   509:        pcb->pcb_ldt_sel = pmap_kernel()->pm_ldt_sel = GSEL(GLDT_SEL, SEL_KPL);
1.326     thorpej   510:        pcb->pcb_cr0 = rcr0();
                    511:        pcb->pcb_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL);
1.573     yamt      512:        pcb->pcb_tss.tss_esp0 = USER_TO_UAREA(lwp0.l_addr) + KSTACK_SIZE - 16;
1.508     thorpej   513:        lwp0.l_md.md_regs = (struct trapframe *)pcb->pcb_tss.tss_esp0 - 1;
                    514:        lwp0.l_md.md_tss_sel = tss_alloc(pcb);
1.326     thorpej   515:
1.508     thorpej   516:        ltr(lwp0.l_md.md_tss_sel);
1.326     thorpej   517:        lldt(pcb->pcb_ldt_sel);
1.484     fvdl      518: }
                    519:
                    520: /*
                    521:  * Set up TSS and LDT for a new PCB.
                    522:  */
                    523:
                    524: void
1.551     junyoung  525: i386_init_pcb_tss_ldt(struct cpu_info *ci)
1.484     fvdl      526: {
                    527:        int x;
                    528:        struct pcb *pcb = ci->ci_idle_pcb;
1.326     thorpej   529:
1.484     fvdl      530:        pcb->pcb_tss.tss_ioopt =
                    531:            ((caddr_t)pcb->pcb_iomap - (caddr_t)&pcb->pcb_tss) << 16;
                    532:        for (x = 0; x < sizeof(pcb->pcb_iomap) / 4; x++)
                    533:                pcb->pcb_iomap[x] = 0xffffffff;
                    534:
                    535:        pcb->pcb_ldt_sel = pmap_kernel()->pm_ldt_sel = GSEL(GLDT_SEL, SEL_KPL);
                    536:        pcb->pcb_cr0 = rcr0();
                    537:
                    538:        ci->ci_idle_tss_sel = tss_alloc(pcb);
1.326     thorpej   539: }
                    540:
                    541: /*
1.545     atatat    542:  * sysctl helper routine for machdep.tm* nodes.
1.484     fvdl      543:  */
1.545     atatat    544: static int
                    545: sysctl_machdep_tm_longrun(SYSCTLFN_ARGS)
1.104     cgd       546: {
1.545     atatat    547:        struct sysctlnode node;
                    548:        int io, error;
                    549:
                    550:        if (!tmx86_has_longrun)
                    551:                return (EOPNOTSUPP);
                    552:
                    553:        node = *rnode;
                    554:        node.sysctl_data = &io;
1.104     cgd       555:
1.545     atatat    556:        switch (rnode->sysctl_num) {
1.461     christos  557:        case CPU_TMLR_MODE:
1.545     atatat    558:                io = (int)(crusoe_longrun = tmx86_get_longrun_mode());
                    559:                break;
1.461     christos  560:        case CPU_TMLR_FREQUENCY:
                    561:                tmx86_get_longrun_status_all();
1.545     atatat    562:                io = crusoe_frequency;
                    563:                break;
1.461     christos  564:        case CPU_TMLR_VOLTAGE:
                    565:                tmx86_get_longrun_status_all();
1.545     atatat    566:                io = crusoe_voltage;
                    567:                break;
1.461     christos  568:        case CPU_TMLR_PERCENTAGE:
                    569:                tmx86_get_longrun_status_all();
1.545     atatat    570:                io = crusoe_percentage;
                    571:                break;
1.104     cgd       572:        default:
                    573:                return (EOPNOTSUPP);
                    574:        }
1.545     atatat    575:
                    576:        error = sysctl_lookup(SYSCTLFN_CALL(&node));
                    577:        if (error || newp == NULL)
                    578:                return (error);
                    579:
                    580:        if (rnode->sysctl_num == CPU_TMLR_MODE) {
                    581:                if (tmx86_set_longrun_mode(io))
                    582:                        crusoe_longrun = (u_int)io;
                    583:                else
                    584:                        return (EINVAL);
                    585:        }
                    586:
                    587:        return (0);
                    588: }
                    589:
                    590: /*
                    591:  * sysctl helper routine for machdep.booted_kernel
                    592:  */
                    593: static int
                    594: sysctl_machdep_booted_kernel(SYSCTLFN_ARGS)
                    595: {
                    596:        struct btinfo_bootpath *bibp;
                    597:        struct sysctlnode node;
                    598:
                    599:        bibp = lookup_bootinfo(BTINFO_BOOTPATH);
                    600:        if(!bibp)
                    601:                return(ENOENT); /* ??? */
                    602:
                    603:        node = *rnode;
                    604:        node.sysctl_data = bibp->bootpath;
                    605:        node.sysctl_size = sizeof(bibp->bootpath);
                    606:        return (sysctl_lookup(SYSCTLFN_CALL(&node)));
                    607: }
                    608:
                    609: /*
                    610:  * sysctl helper routine for machdep.diskinfo
                    611:  */
                    612: static int
                    613: sysctl_machdep_diskinfo(SYSCTLFN_ARGS)
                    614: {
                    615:        struct sysctlnode node;
                    616:
                    617:        node = *rnode;
1.559     thorpej   618:        if (x86_alldisks == NULL)
1.557     dbj       619:                return(EOPNOTSUPP);
1.559     thorpej   620:        node.sysctl_data = x86_alldisks;
1.545     atatat    621:        node.sysctl_size = sizeof(struct disklist) +
1.559     thorpej   622:            (x86_ndisks - 1) * sizeof(struct nativedisk_info);
1.557     dbj       623:        return (sysctl_lookup(SYSCTLFN_CALL(&node)));
1.545     atatat    624: }
                    625:
                    626: /*
                    627:  * machine dependent system variables.
                    628:  */
                    629: SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup")
                    630: {
                    631:
1.552     atatat    632:        sysctl_createv(clog, 0, NULL, NULL,
                    633:                       CTLFLAG_PERMANENT,
1.545     atatat    634:                       CTLTYPE_NODE, "machdep", NULL,
                    635:                       NULL, 0, NULL, 0,
                    636:                       CTL_MACHDEP, CTL_EOL);
                    637:
1.552     atatat    638:        sysctl_createv(clog, 0, NULL, NULL,
                    639:                       CTLFLAG_PERMANENT,
1.545     atatat    640:                       CTLTYPE_STRUCT, "console_device", NULL,
                    641:                       sysctl_consdev, 0, NULL, sizeof(dev_t),
                    642:                       CTL_MACHDEP, CPU_CONSDEV, CTL_EOL);
1.552     atatat    643:        sysctl_createv(clog, 0, NULL, NULL,
                    644:                       CTLFLAG_PERMANENT,
1.545     atatat    645:                       CTLTYPE_INT, "biosbasemem", NULL,
                    646:                       NULL, 0, &biosbasemem, 0,
                    647:                       CTL_MACHDEP, CPU_BIOSBASEMEM, CTL_EOL);
1.552     atatat    648:        sysctl_createv(clog, 0, NULL, NULL,
                    649:                       CTLFLAG_PERMANENT,
1.545     atatat    650:                       CTLTYPE_INT, "biosextmem", NULL,
                    651:                       NULL, 0, &biosextmem, 0,
                    652:                       CTL_MACHDEP, CPU_BIOSEXTMEM, CTL_EOL);
1.552     atatat    653:        sysctl_createv(clog, 0, NULL, NULL,
                    654:                       CTLFLAG_PERMANENT,
1.545     atatat    655:                       CTLTYPE_INT, "nkpde", NULL,
                    656:                       NULL, 0, &nkpde, 0,
                    657:                       CTL_MACHDEP, CPU_NKPDE, CTL_EOL);
1.552     atatat    658:        sysctl_createv(clog, 0, NULL, NULL,
                    659:                       CTLFLAG_PERMANENT,
1.545     atatat    660:                       CTLTYPE_STRING, "booted_kernel", NULL,
                    661:                       sysctl_machdep_booted_kernel, 0, NULL, 0,
                    662:                       CTL_MACHDEP, CPU_BOOTED_KERNEL, CTL_EOL);
1.552     atatat    663:        sysctl_createv(clog, 0, NULL, NULL,
                    664:                       CTLFLAG_PERMANENT,
1.545     atatat    665:                       CTLTYPE_STRUCT, "diskinfo", NULL,
                    666:                       sysctl_machdep_diskinfo, 0, NULL, 0,
                    667:                       CTL_MACHDEP, CPU_DISKINFO, CTL_EOL);
1.552     atatat    668:        sysctl_createv(clog, 0, NULL, NULL,
                    669:                       CTLFLAG_PERMANENT,
1.545     atatat    670:                       CTLTYPE_INT, "fpu_present", NULL,
                    671:                       NULL, 0, &i386_fpu_present, 0,
                    672:                       CTL_MACHDEP, CPU_FPU_PRESENT, CTL_EOL);
1.552     atatat    673:        sysctl_createv(clog, 0, NULL, NULL,
                    674:                       CTLFLAG_PERMANENT,
1.545     atatat    675:                       CTLTYPE_INT, "osfxsr", NULL,
                    676:                       NULL, 0, &i386_use_fxsave, 0,
                    677:                       CTL_MACHDEP, CPU_OSFXSR, CTL_EOL);
1.552     atatat    678:        sysctl_createv(clog, 0, NULL, NULL,
                    679:                       CTLFLAG_PERMANENT,
1.545     atatat    680:                       CTLTYPE_INT, "sse", NULL,
                    681:                       NULL, 0, &i386_has_sse, 0,
                    682:                       CTL_MACHDEP, CPU_SSE, CTL_EOL);
1.552     atatat    683:        sysctl_createv(clog, 0, NULL, NULL,
                    684:                       CTLFLAG_PERMANENT,
1.545     atatat    685:                       CTLTYPE_INT, "sse2", NULL,
                    686:                       NULL, 0, &i386_has_sse2, 0,
                    687:                       CTL_MACHDEP, CPU_SSE2, CTL_EOL);
1.554     lukem     688:        sysctl_createv(clog, 0, NULL, NULL,
                    689:                       CTLFLAG_PERMANENT,
                    690:                       CTLTYPE_STRING, "cpu_brand", NULL,
                    691:                       NULL, 0, &cpu_brand_string, 0,
                    692:                       CTL_MACHDEP, CTL_CREATE, CTL_EOL);
1.552     atatat    693:        sysctl_createv(clog, 0, NULL, NULL,
                    694:                       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
1.545     atatat    695:                       CTLTYPE_INT, "tm_longrun_mode", NULL,
                    696:                       sysctl_machdep_tm_longrun, 0, NULL, 0,
                    697:                       CTL_MACHDEP, CPU_TMLR_MODE, CTL_EOL);
1.552     atatat    698:        sysctl_createv(clog, 0, NULL, NULL,
                    699:                       CTLFLAG_PERMANENT,
1.545     atatat    700:                       CTLTYPE_INT, "tm_longrun_frequency", NULL,
                    701:                       sysctl_machdep_tm_longrun, 0, NULL, 0,
                    702:                       CTL_MACHDEP, CPU_TMLR_FREQUENCY, CTL_EOL);
1.552     atatat    703:        sysctl_createv(clog, 0, NULL, NULL,
                    704:                       CTLFLAG_PERMANENT,
1.545     atatat    705:                       CTLTYPE_INT, "tm_longrun_voltage", NULL,
                    706:                       sysctl_machdep_tm_longrun, 0, NULL, 0,
                    707:                       CTL_MACHDEP, CPU_TMLR_VOLTAGE, CTL_EOL);
1.552     atatat    708:        sysctl_createv(clog, 0, NULL, NULL,
                    709:                       CTLFLAG_PERMANENT,
1.545     atatat    710:                       CTLTYPE_INT, "tm_longrun_percentage", NULL,
                    711:                       sysctl_machdep_tm_longrun, 0, NULL, 0,
                    712:                       CTL_MACHDEP, CPU_TMLR_PERCENTAGE, CTL_EOL);
1.104     cgd       713: }
1.151     christos  714:
1.534     christos  715: void *
                    716: getframe(struct lwp *l, int sig, int *onstack)
                    717: {
                    718:        struct proc *p = l->l_proc;
                    719:        struct sigctx *ctx = &p->p_sigctx;
                    720:        struct trapframe *tf = l->l_md.md_regs;
                    721:
                    722:        /* Do we need to jump onto the signal stack? */
                    723:        *onstack = (ctx->ps_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0
                    724:            && (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0;
                    725:        if (*onstack)
                    726:                return (char *)ctx->ps_sigstk.ss_sp + ctx->ps_sigstk.ss_size;
                    727: #ifdef VM86
                    728:        if (tf->tf_eflags & PSL_VM)
                    729:                return (void *)(tf->tf_esp + (tf->tf_ss << 4));
                    730:        else
                    731: #endif
                    732:                return (void *)tf->tf_esp;
                    733: }
                    734:
                    735: /*
                    736:  * Build context to run handler in.  We invoke the handler
                    737:  * directly, only returning via the trampoline.  Note the
                    738:  * trampoline version numbers are coordinated with machine-
                    739:  * dependent code in libc.
                    740:  */
                    741: void
                    742: buildcontext(struct lwp *l, int sel, void *catcher, void *fp)
                    743: {
                    744:        struct trapframe *tf = l->l_md.md_regs;
                    745:
                    746:        tf->tf_gs = GSEL(GUDATA_SEL, SEL_UPL);
                    747:        tf->tf_fs = GSEL(GUDATA_SEL, SEL_UPL);
                    748:        tf->tf_es = GSEL(GUDATA_SEL, SEL_UPL);
                    749:        tf->tf_ds = GSEL(GUDATA_SEL, SEL_UPL);
                    750:        tf->tf_eip = (int)catcher;
                    751:        tf->tf_cs = GSEL(sel, SEL_UPL);
                    752:        tf->tf_eflags &= ~(PSL_T|PSL_VM|PSL_AC);
                    753:        tf->tf_esp = (int)fp;
                    754:        tf->tf_ss = GSEL(GUDATA_SEL, SEL_UPL);
                    755: }
                    756:
                    757: static void
1.539     christos  758: sendsig_siginfo(const ksiginfo_t *ksi, const sigset_t *mask)
1.534     christos  759: {
                    760:        struct lwp *l = curlwp;
                    761:        struct proc *p = l->l_proc;
                    762:        struct pmap *pmap = vm_map_pmap(&p->p_vmspace->vm_map);
                    763:        int sel = pmap->pm_hiexec > I386_MAX_EXE_ADDR ?
                    764:            GUCODEBIG_SEL : GUCODE_SEL;
                    765:        struct sigacts *ps = p->p_sigacts;
                    766:        int onstack;
                    767:        int sig = ksi->ksi_signo;
                    768:        struct sigframe_siginfo *fp = getframe(l, sig, &onstack), frame;
                    769:        sig_t catcher = SIGACTION(p, sig).sa_handler;
                    770:        struct trapframe *tf = l->l_md.md_regs;
                    771:
                    772:        fp--;
                    773:
                    774:        /* Build stack frame for signal trampoline. */
                    775:        switch (ps->sa_sigdesc[sig].sd_vers) {
1.537     christos  776:        case 0:         /* handled by sendsig_sigcontext */
                    777:        case 1:         /* handled by sendsig_sigcontext */
1.534     christos  778:        default:        /* unknown version */
                    779:                printf("nsendsig: bad version %d\n",
                    780:                    ps->sa_sigdesc[sig].sd_vers);
                    781:                sigexit(l, SIGILL);
                    782:        case 2:
                    783:                break;
                    784:        }
                    785:
                    786:        frame.sf_ra = (int)ps->sa_sigdesc[sig].sd_tramp;
                    787:        frame.sf_signum = sig;
                    788:        frame.sf_sip = &fp->sf_si;
                    789:        frame.sf_ucp = &fp->sf_uc;
1.540     thorpej   790:        frame.sf_si._info = ksi->ksi_info;
1.534     christos  791:        frame.sf_uc.uc_flags = _UC_SIGMASK|_UC_VM;
                    792:        frame.sf_uc.uc_sigmask = *mask;
                    793:        frame.sf_uc.uc_link = NULL;
                    794:        frame.sf_uc.uc_flags |= (p->p_sigctx.ps_sigstk.ss_flags & SS_ONSTACK)
                    795:            ? _UC_SETSTACK : _UC_CLRSTACK;
                    796:        memset(&frame.sf_uc.uc_stack, 0, sizeof(frame.sf_uc.uc_stack));
                    797:        cpu_getmcontext(l, &frame.sf_uc.uc_mcontext, &frame.sf_uc.uc_flags);
                    798:
                    799:        if (tf->tf_eflags & PSL_VM)
                    800:                (*p->p_emul->e_syscall_intern)(p);
                    801:
                    802:        if (copyout(&frame, fp, sizeof(frame)) != 0) {
                    803:                /*
                    804:                 * Process has trashed its stack; give it an illegal
                    805:                 * instruction to halt it in its tracks.
                    806:                 */
                    807:                sigexit(l, SIGILL);
                    808:                /* NOTREACHED */
                    809:        }
                    810:
                    811:        buildcontext(l, sel, catcher, fp);
1.319     mycroft   812:
1.586.2.6! bouyer    813: #if NNPX > 0
        !           814:        /* make sure we get a clean FPU */
        !           815:        npxsave_lwp(l, 0);
        !           816:        l->l_md.md_flags &= ~MDL_USEDFPU;
        !           817: #endif
        !           818:
1.319     mycroft   819:        /* Remember that we're now on the signal stack. */
                    820:        if (onstack)
1.425     jdolecek  821:                p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK;
1.1       cgd       822: }
                    823:
1.534     christos  824: void
1.539     christos  825: sendsig(const ksiginfo_t *ksi, const sigset_t *mask)
1.534     christos  826: {
                    827: #ifdef COMPAT_16
                    828:        if (curproc->p_sigacts->sa_sigdesc[ksi->ksi_signo].sd_vers < 2)
                    829:                sendsig_sigcontext(ksi, mask);
                    830:        else
                    831: #endif
                    832:                sendsig_siginfo(ksi, mask);
                    833: }
1.508     thorpej   834:
1.550     junyoung  835: void
1.534     christos  836: cpu_upcall(struct lwp *l, int type, int nevents, int ninterrupted, void *sas,
                    837:     void *ap, void *sp, sa_upcall_t upcall)
1.508     thorpej   838: {
1.533     chs       839:        struct pmap *pmap = vm_map_pmap(&l->l_proc->p_vmspace->vm_map);
1.508     thorpej   840:        struct saframe *sf, frame;
                    841:        struct trapframe *tf;
                    842:
                    843:        tf = l->l_md.md_regs;
                    844:
                    845:        /* Finally, copy out the rest of the frame. */
                    846:        frame.sa_type = type;
                    847:        frame.sa_sas = sas;
                    848:        frame.sa_events = nevents;
                    849:        frame.sa_interrupted = ninterrupted;
                    850:        frame.sa_arg = ap;
                    851:        frame.sa_ra = 0;
1.550     junyoung  852:
1.508     thorpej   853:        sf = (struct saframe *)sp - 1;
                    854:        if (copyout(&frame, sf, sizeof(frame)) != 0) {
                    855:                /* Copying onto the stack didn't work. Die. */
                    856:                sigexit(l, SIGILL);
                    857:                /* NOTREACHED */
                    858:        }
                    859:
                    860:        tf->tf_eip = (int) upcall;
                    861:        tf->tf_esp = (int) sf;
                    862:        tf->tf_ebp = 0; /* indicate call-frame-top to debuggers */
                    863:        tf->tf_gs = GSEL(GUDATA_SEL, SEL_UPL);
                    864:        tf->tf_fs = GSEL(GUDATA_SEL, SEL_UPL);
                    865:        tf->tf_es = GSEL(GUDATA_SEL, SEL_UPL);
                    866:        tf->tf_ds = GSEL(GUDATA_SEL, SEL_UPL);
1.533     chs       867:        tf->tf_cs = pmap->pm_hiexec > I386_MAX_EXE_ADDR ?
                    868:            GSEL(GUCODEBIG_SEL, SEL_UPL) : GSEL(GUCODE_SEL, SEL_UPL);
1.508     thorpej   869:        tf->tf_ss = GSEL(GUDATA_SEL, SEL_UPL);
                    870:        tf->tf_eflags &= ~(PSL_T|PSL_VM|PSL_AC);
                    871: }
1.37      cgd       872:
1.1       cgd       873: int    waittime = -1;
                    874: struct pcb dumppcb;
                    875:
1.32      andrew    876: void
1.586     christos  877: cpu_reboot(int howto, char *bootstr)
1.1       cgd       878: {
                    879:
1.106     mycroft   880:        if (cold) {
1.193     mycroft   881:                howto |= RB_HALT;
                    882:                goto haltsys;
1.1       cgd       883:        }
1.193     mycroft   884:
1.106     mycroft   885:        boothowto = howto;
1.193     mycroft   886:        if ((howto & RB_NOSYNC) == 0 && waittime < 0) {
1.1       cgd       887:                waittime = 0;
1.150     mycroft   888:                vfs_shutdown();
1.521     dsl       889:                /*
                    890:                 * If we've been adjusting the clock, the todr
                    891:                 * will be out of synch; adjust it now.
                    892:                 */
                    893:                if (time_adjusted != 0)
                    894:                        resettodr();
1.1       cgd       895:        }
1.193     mycroft   896:
                    897:        /* Disable interrupts. */
1.1       cgd       898:        splhigh();
1.193     mycroft   899:
                    900:        /* Do a dump if requested. */
                    901:        if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP)
                    902:                dumpsys();
                    903:
                    904: haltsys:
                    905:        doshutdownhooks();
                    906:
1.484     fvdl      907: #ifdef MULTIPROCESSOR
1.514     fvdl      908:        x86_broadcast_ipi(X86_IPI_HALT);
1.484     fvdl      909: #endif
                    910:
1.307     thorpej   911:        if ((howto & RB_POWERDOWN) == RB_POWERDOWN) {
1.473     tshiozak  912: #if NACPI > 0
1.530     kochi     913:                if (acpi_softc != NULL) {
                    914:                        delay(500000);
                    915:                        acpi_enter_sleep_state(acpi_softc, ACPI_STATE_S5);
                    916:                        printf("WARNING: ACPI powerdown failed!\n");
                    917:                }
1.473     tshiozak  918: #endif
1.576     christos  919: #if NAPMBIOS > 0 && !defined(APM_NO_POWEROFF)
1.208     jtk       920:                /* turn off, if we can.  But try to turn disk off and
                    921:                 * wait a bit first--some disk drives are slow to clean up
                    922:                 * and users have reported disk corruption.
                    923:                 */
                    924:                delay(500000);
1.578     xtraeme   925:                apm_set_powstate(NULL, APM_DEV_DISK(APM_DEV_ALLUNITS), APM_SYS_OFF);
1.208     jtk       926:                delay(500000);
1.576     christos  927:                apm_set_powstate(NULL, APM_DEV_ALLDEVS, APM_SYS_OFF);
1.531     kochi     928:                printf("WARNING: APM powerdown failed!\n");
1.307     thorpej   929:                /*
                    930:                 * RB_POWERDOWN implies RB_HALT... fall into it...
                    931:                 */
1.208     jtk       932: #endif
1.307     thorpej   933:        }
                    934:
                    935:        if (howto & RB_HALT) {
1.210     christos  936:                printf("\n");
                    937:                printf("The operating system has halted.\n");
                    938:                printf("Please press any key to reboot.\n\n");
1.517     jmmv      939:
                    940: #ifdef BEEP_ONHALT
                    941:                {
                    942:                        int c;
                    943:                        for (c = BEEP_ONHALT_COUNT; c > 0; c--) {
                    944:                                sysbeep(BEEP_ONHALT_PITCH,
1.565     simonb    945:                                        BEEP_ONHALT_PERIOD * hz / 1000);
1.517     jmmv      946:                                delay(BEEP_ONHALT_PERIOD * 1000);
                    947:                                sysbeep(0, BEEP_ONHALT_PERIOD * hz / 1000);
                    948:                                delay(BEEP_ONHALT_PERIOD * 1000);
                    949:                        }
                    950:                }
                    951: #endif
                    952:
1.300     drochner  953:                cnpollc(1);     /* for proper keyboard command handling */
1.512     perry     954:                if (cngetc() == 0) {
                    955:                        /* no console attached, so just hlt */
                    956:                        for(;;) {
1.567     perry     957:                                __asm volatile("hlt");
1.512     perry     958:                        }
                    959:                }
1.300     drochner  960:                cnpollc(0);
1.1       cgd       961:        }
1.193     mycroft   962:
1.210     christos  963:        printf("rebooting...\n");
1.328     bouyer    964:        if (cpureset_delay > 0)
                    965:                delay(cpureset_delay * 1000);
1.1       cgd       966:        cpu_reset();
                    967:        for(;;) ;
                    968:        /*NOTREACHED*/
                    969: }
                    970:
1.116     gwr       971: /*
                    972:  * These variables are needed by /sbin/savecore
                    973:  */
1.568     perry     974: uint32_t dumpmag = 0x8fca0101; /* magic number */
1.116     gwr       975: int    dumpsize = 0;           /* pages */
                    976: long   dumplo = 0;             /* blocks */
                    977:
                    978: /*
1.291     thorpej   979:  * cpu_dumpsize: calculate size of machine-dependent kernel core dump headers.
                    980:  */
                    981: int
                    982: cpu_dumpsize()
                    983: {
                    984:        int size;
                    985:
                    986:        size = ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t)) +
                    987:            ALIGN(mem_cluster_cnt * sizeof(phys_ram_seg_t));
                    988:        if (roundup(size, dbtob(1)) != dbtob(1))
                    989:                return (-1);
                    990:
                    991:        return (1);
                    992: }
                    993:
                    994: /*
                    995:  * cpu_dump_mempagecnt: calculate the size of RAM (in pages) to be dumped.
                    996:  */
                    997: u_long
                    998: cpu_dump_mempagecnt()
                    999: {
                   1000:        u_long i, n;
                   1001:
                   1002:        n = 0;
                   1003:        for (i = 0; i < mem_cluster_cnt; i++)
                   1004:                n += atop(mem_clusters[i].size);
                   1005:        return (n);
                   1006: }
                   1007:
                   1008: /*
                   1009:  * cpu_dump: dump the machine-dependent kernel core dump headers.
                   1010:  */
                   1011: int
                   1012: cpu_dump()
                   1013: {
1.542     junyoung 1014:        int (*dump)(dev_t, daddr_t, caddr_t, size_t);
1.563     christos 1015:        char bf[dbtob(1)];
1.291     thorpej  1016:        kcore_seg_t *segp;
                   1017:        cpu_kcore_hdr_t *cpuhdrp;
                   1018:        phys_ram_seg_t *memsegp;
1.481     gehenna  1019:        const struct bdevsw *bdev;
1.291     thorpej  1020:        int i;
                   1021:
1.481     gehenna  1022:        bdev = bdevsw_lookup(dumpdev);
                   1023:        if (bdev == NULL)
                   1024:                return (ENXIO);
                   1025:        dump = bdev->d_dump;
1.291     thorpej  1026:
1.563     christos 1027:        memset(bf, 0, sizeof bf);
                   1028:        segp = (kcore_seg_t *)bf;
                   1029:        cpuhdrp = (cpu_kcore_hdr_t *)&bf[ALIGN(sizeof(*segp))];
                   1030:        memsegp = (phys_ram_seg_t *)&bf[ ALIGN(sizeof(*segp)) +
1.291     thorpej  1031:            ALIGN(sizeof(*cpuhdrp))];
                   1032:
                   1033:        /*
                   1034:         * Generate a segment header.
                   1035:         */
                   1036:        CORE_SETMAGIC(*segp, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
                   1037:        segp->c_size = dbtob(1) - ALIGN(sizeof(*segp));
                   1038:
                   1039:        /*
                   1040:         * Add the machine-dependent header info.
                   1041:         */
1.558     junyoung 1042:        cpuhdrp->pdppaddr = PDPpaddr;
1.291     thorpej  1043:        cpuhdrp->nmemsegs = mem_cluster_cnt;
                   1044:
                   1045:        /*
                   1046:         * Fill in the memory segment descriptors.
                   1047:         */
                   1048:        for (i = 0; i < mem_cluster_cnt; i++) {
                   1049:                memsegp[i].start = mem_clusters[i].start;
                   1050:                memsegp[i].size = mem_clusters[i].size;
                   1051:        }
                   1052:
1.563     christos 1053:        return (dump(dumpdev, dumplo, (caddr_t)bf, dbtob(1)));
1.291     thorpej  1054: }
                   1055:
                   1056: /*
1.228     gwr      1057:  * This is called by main to set dumplo and dumpsize.
1.414     thorpej  1058:  * Dumps always skip the first PAGE_SIZE of disk space
1.116     gwr      1059:  * in case there might be a disk label stored there.
                   1060:  * If there is extra space, put dump at the end to
                   1061:  * reduce the chance that swapping trashes it.
                   1062:  */
                   1063: void
1.228     gwr      1064: cpu_dumpconf()
1.116     gwr      1065: {
1.481     gehenna  1066:        const struct bdevsw *bdev;
1.291     thorpej  1067:        int nblks, dumpblks;    /* size of dump area */
1.116     gwr      1068:
                   1069:        if (dumpdev == NODEV)
1.291     thorpej  1070:                goto bad;
1.481     gehenna  1071:        bdev = bdevsw_lookup(dumpdev);
1.582     mrg      1072:        if (bdev == NULL) {
                   1073:                dumpdev = NODEV;
1.583     skrll    1074:                goto bad;
1.582     mrg      1075:        }
1.481     gehenna  1076:        if (bdev->d_psize == NULL)
1.291     thorpej  1077:                goto bad;
1.481     gehenna  1078:        nblks = (*bdev->d_psize)(dumpdev);
1.116     gwr      1079:        if (nblks <= ctod(1))
1.291     thorpej  1080:                goto bad;
1.116     gwr      1081:
1.291     thorpej  1082:        dumpblks = cpu_dumpsize();
                   1083:        if (dumpblks < 0)
                   1084:                goto bad;
                   1085:        dumpblks += ctod(cpu_dump_mempagecnt());
                   1086:
                   1087:        /* If dump won't fit (incl. room for possible label), punt. */
                   1088:        if (dumpblks > (nblks - ctod(1)))
                   1089:                goto bad;
                   1090:
                   1091:        /* Put dump at end of partition */
                   1092:        dumplo = nblks - dumpblks;
                   1093:
                   1094:        /* dumpsize is in page units, and doesn't include headers. */
                   1095:        dumpsize = cpu_dump_mempagecnt();
                   1096:        return;
1.116     gwr      1097:
1.291     thorpej  1098:  bad:
                   1099:        dumpsize = 0;
1.116     gwr      1100: }
                   1101:
1.1       cgd      1102: /*
                   1103:  * Doadump comes here after turning off memory management and
                   1104:  * getting on the dump stack, either when called above, or by
                   1105:  * the auto-restart code.
                   1106:  */
1.414     thorpej  1107: #define BYTES_PER_DUMP  PAGE_SIZE /* must be a multiple of pagesize XXX small */
1.314     thorpej  1108: static vaddr_t dumpspace;
1.163     cgd      1109:
1.314     thorpej  1110: vaddr_t
1.551     junyoung 1111: reserve_dumppages(vaddr_t p)
1.163     cgd      1112: {
                   1113:
                   1114:        dumpspace = p;
                   1115:        return (p + BYTES_PER_DUMP);
                   1116: }
                   1117:
1.32      andrew   1118: void
1.1       cgd      1119: dumpsys()
                   1120: {
1.556     mycroft  1121:        u_long totalbytesleft, bytes, i, n, m, memseg;
1.291     thorpej  1122:        u_long maddr;
                   1123:        int psize;
1.163     cgd      1124:        daddr_t blkno;
1.481     gehenna  1125:        const struct bdevsw *bdev;
1.542     junyoung 1126:        int (*dump)(dev_t, daddr_t, caddr_t, size_t);
1.200     christos 1127:        int error;
1.193     mycroft  1128:
                   1129:        /* Save registers. */
                   1130:        savectx(&dumppcb);
1.1       cgd      1131:
                   1132:        if (dumpdev == NODEV)
                   1133:                return;
1.484     fvdl     1134:
1.481     gehenna  1135:        bdev = bdevsw_lookup(dumpdev);
                   1136:        if (bdev == NULL || bdev->d_psize == NULL)
                   1137:                return;
1.163     cgd      1138:
                   1139:        /*
                   1140:         * For dumps during autoconfiguration,
                   1141:         * if dump device has already configured...
                   1142:         */
                   1143:        if (dumpsize == 0)
1.228     gwr      1144:                cpu_dumpconf();
1.330     jtk      1145:        if (dumplo <= 0 || dumpsize == 0) {
1.275     mycroft  1146:                printf("\ndump to dev %u,%u not possible\n", major(dumpdev),
                   1147:                    minor(dumpdev));
1.163     cgd      1148:                return;
1.275     mycroft  1149:        }
                   1150:        printf("\ndumping to dev %u,%u offset %ld\n", major(dumpdev),
                   1151:            minor(dumpdev), dumplo);
1.134     mycroft  1152:
1.481     gehenna  1153:        psize = (*bdev->d_psize)(dumpdev);
1.210     christos 1154:        printf("dump ");
1.163     cgd      1155:        if (psize == -1) {
1.210     christos 1156:                printf("area unavailable\n");
1.163     cgd      1157:                return;
                   1158:        }
                   1159:
                   1160: #if 0  /* XXX this doesn't work.  grr. */
1.565     simonb   1161:        /* toss any characters present prior to dump */
1.163     cgd      1162:        while (sget() != NULL); /*syscons and pccons differ */
                   1163: #endif
                   1164:
1.291     thorpej  1165:        if ((error = cpu_dump()) != 0)
                   1166:                goto err;
                   1167:
                   1168:        totalbytesleft = ptoa(cpu_dump_mempagecnt());
                   1169:        blkno = dumplo + cpu_dumpsize();
1.481     gehenna  1170:        dump = bdev->d_dump;
1.200     christos 1171:        error = 0;
1.291     thorpej  1172:
                   1173:        for (memseg = 0; memseg < mem_cluster_cnt; memseg++) {
                   1174:                maddr = mem_clusters[memseg].start;
                   1175:                bytes = mem_clusters[memseg].size;
                   1176:
                   1177:                for (i = 0; i < bytes; i += n, totalbytesleft -= n) {
                   1178:                        /* Print out how many MBs we have left to go. */
                   1179:                        if ((totalbytesleft % (1024*1024)) == 0)
                   1180:                                printf("%ld ", totalbytesleft / (1024 * 1024));
                   1181:
                   1182:                        /* Limit size for next transfer. */
                   1183:                        n = bytes - i;
                   1184:                        if (n > BYTES_PER_DUMP)
                   1185:                                n = BYTES_PER_DUMP;
                   1186:
1.556     mycroft  1187:                        for (m = 0; m < n; m += NBPG)
                   1188:                                pmap_kenter_pa(dumpspace + m, maddr + m,
                   1189:                                    VM_PROT_READ);
1.291     thorpej  1190:
                   1191:                        error = (*dump)(dumpdev, blkno, (caddr_t)dumpspace, n);
                   1192:                        if (error)
                   1193:                                goto err;
1.163     cgd      1194:                        maddr += n;
1.291     thorpej  1195:                        blkno += btodb(n);              /* XXX? */
1.163     cgd      1196:
                   1197: #if 0  /* XXX this doesn't work.  grr. */
1.291     thorpej  1198:                        /* operator aborting dump? */
                   1199:                        if (sget() != NULL) {
                   1200:                                error = EINTR;
                   1201:                                break;
                   1202:                        }
                   1203: #endif
1.163     cgd      1204:                }
                   1205:        }
                   1206:
1.291     thorpej  1207:  err:
1.163     cgd      1208:        switch (error) {
1.1       cgd      1209:
                   1210:        case ENXIO:
1.210     christos 1211:                printf("device bad\n");
1.1       cgd      1212:                break;
                   1213:
                   1214:        case EFAULT:
1.210     christos 1215:                printf("device not ready\n");
1.1       cgd      1216:                break;
                   1217:
                   1218:        case EINVAL:
1.210     christos 1219:                printf("area improper\n");
1.1       cgd      1220:                break;
                   1221:
                   1222:        case EIO:
1.210     christos 1223:                printf("i/o error\n");
1.1       cgd      1224:                break;
                   1225:
                   1226:        case EINTR:
1.210     christos 1227:                printf("aborted from console\n");
1.1       cgd      1228:                break;
                   1229:
1.163     cgd      1230:        case 0:
1.210     christos 1231:                printf("succeeded\n");
1.163     cgd      1232:                break;
                   1233:
1.1       cgd      1234:        default:
1.210     christos 1235:                printf("error %d\n", error);
1.1       cgd      1236:                break;
                   1237:        }
1.210     christos 1238:        printf("\n\n");
1.163     cgd      1239:        delay(5000000);         /* 5 seconds */
1.1       cgd      1240: }
                   1241:
                   1242: /*
                   1243:  * Clear registers on exec
                   1244:  */
1.33      cgd      1245: void
1.551     junyoung 1246: setregs(struct lwp *l, struct exec_package *pack, u_long stack)
1.1       cgd      1247: {
1.533     chs      1248:        struct pmap *pmap = vm_map_pmap(&l->l_proc->p_vmspace->vm_map);
1.508     thorpej  1249:        struct pcb *pcb = &l->l_addr->u_pcb;
1.298     mycroft  1250:        struct trapframe *tf;
1.1       cgd      1251:
1.161     mycroft  1252: #if NNPX > 0
                   1253:        /* If we were using the FPU, forget about it. */
1.508     thorpej  1254:        if (l->l_addr->u_pcb.pcb_fpcpu != NULL)
                   1255:                npxsave_lwp(l, 0);
1.161     mycroft  1256: #endif
1.166     mycroft  1257:
1.178     mycroft  1258: #ifdef USER_LDT
1.508     thorpej  1259:        pmap_ldt_cleanup(l);
1.178     mycroft  1260: #endif
                   1261:
1.548     yamt     1262:        l->l_md.md_flags &= ~MDL_USEDFPU;
1.452     thorpej  1263:        if (i386_use_fxsave) {
1.450     thorpej  1264:                pcb->pcb_savefpu.sv_xmm.sv_env.en_cw = __NetBSD_NPXCW__;
1.452     thorpej  1265:                pcb->pcb_savefpu.sv_xmm.sv_env.en_mxcsr = __INITIAL_MXCSR__;
                   1266:        } else
1.450     thorpej  1267:                pcb->pcb_savefpu.sv_87.sv_env.en_cw = __NetBSD_NPXCW__;
1.59      mycroft  1268:
1.508     thorpej  1269:        tf = l->l_md.md_regs;
1.445     sommerfe 1270:        tf->tf_gs = LSEL(LUDATA_SEL, SEL_UPL);
                   1271:        tf->tf_fs = LSEL(LUDATA_SEL, SEL_UPL);
1.154     mycroft  1272:        tf->tf_es = LSEL(LUDATA_SEL, SEL_UPL);
                   1273:        tf->tf_ds = LSEL(LUDATA_SEL, SEL_UPL);
1.252     mycroft  1274:        tf->tf_edi = 0;
                   1275:        tf->tf_esi = 0;
1.154     mycroft  1276:        tf->tf_ebp = 0;
1.508     thorpej  1277:        tf->tf_ebx = (int)l->l_proc->p_psstr;
1.252     mycroft  1278:        tf->tf_edx = 0;
                   1279:        tf->tf_ecx = 0;
                   1280:        tf->tf_eax = 0;
1.154     mycroft  1281:        tf->tf_eip = pack->ep_entry;
1.533     chs      1282:        tf->tf_cs = pmap->pm_hiexec > I386_MAX_EXE_ADDR ?
                   1283:            LSEL(LUCODEBIG_SEL, SEL_UPL) : LSEL(LUCODE_SEL, SEL_UPL);
1.154     mycroft  1284:        tf->tf_eflags = PSL_USERSET;
                   1285:        tf->tf_esp = stack;
                   1286:        tf->tf_ss = LSEL(LUDATA_SEL, SEL_UPL);
1.1       cgd      1287: }
                   1288:
                   1289: /*
1.55      brezak   1290:  * Initialize segments and descriptor tables
1.1       cgd      1291:  */
                   1292:
1.516     fvdl     1293: union  descriptor *gdt, *ldt;
                   1294: struct gate_descriptor *idt;
1.498     fvdl     1295: char idt_allocmap[NIDT];
                   1296: struct simplelock idt_lock = SIMPLELOCK_INITIALIZER;
1.275     mycroft  1297: #ifdef I586_CPU
                   1298: union  descriptor *pentium_idt;
                   1299: #endif
1.573     yamt     1300: struct user *proc0paddr;
                   1301: extern vaddr_t proc0uarea;
1.49      brezak   1302:
1.178     mycroft  1303: void
1.551     junyoung 1304: setgate(struct gate_descriptor *gd, void *func, int args, int type, int dpl,
                   1305:     int sel)
1.178     mycroft  1306: {
1.1       cgd      1307:
1.178     mycroft  1308:        gd->gd_looffset = (int)func;
1.489     fvdl     1309:        gd->gd_selector = sel;
1.178     mycroft  1310:        gd->gd_stkcpy = args;
                   1311:        gd->gd_xx = 0;
                   1312:        gd->gd_type = type;
                   1313:        gd->gd_dpl = dpl;
                   1314:        gd->gd_p = 1;
                   1315:        gd->gd_hioffset = (int)func >> 16;
                   1316: }
                   1317:
                   1318: void
1.551     junyoung 1319: unsetgate(struct gate_descriptor *gd)
1.484     fvdl     1320: {
                   1321:        gd->gd_p = 0;
                   1322:        gd->gd_hioffset = 0;
                   1323:        gd->gd_looffset = 0;
                   1324:        gd->gd_selector = 0;
                   1325:        gd->gd_xx = 0;
                   1326:        gd->gd_stkcpy = 0;
                   1327:        gd->gd_type = 0;
                   1328:        gd->gd_dpl = 0;
                   1329: }
                   1330:
                   1331:
                   1332: void
1.551     junyoung 1333: setregion(struct region_descriptor *rd, void *base, size_t limit)
1.178     mycroft  1334: {
                   1335:
                   1336:        rd->rd_limit = (int)limit;
                   1337:        rd->rd_base = (int)base;
                   1338: }
1.1       cgd      1339:
1.174     mycroft  1340: void
1.551     junyoung 1341: setsegment(struct segment_descriptor *sd, void *base, size_t limit, int type,
                   1342:     int dpl, int def32, int gran)
1.174     mycroft  1343: {
1.1       cgd      1344:
1.174     mycroft  1345:        sd->sd_lolimit = (int)limit;
                   1346:        sd->sd_lobase = (int)base;
                   1347:        sd->sd_type = type;
                   1348:        sd->sd_dpl = dpl;
                   1349:        sd->sd_p = 1;
                   1350:        sd->sd_hilimit = (int)limit >> 16;
                   1351:        sd->sd_xx = 0;
                   1352:        sd->sd_def32 = def32;
                   1353:        sd->sd_gran = gran;
                   1354:        sd->sd_hibase = (int)base >> 24;
                   1355: }
1.1       cgd      1356:
                   1357: #define        IDTVEC(name)    __CONCAT(X, name)
1.542     junyoung 1358: typedef void (vector)(void);
1.299     mycroft  1359: extern vector IDTVEC(syscall);
                   1360: extern vector IDTVEC(osyscall);
                   1361: extern vector *IDTVEC(exceptions)[];
1.333     christos 1362: #ifdef COMPAT_SVR4
                   1363: extern vector IDTVEC(svr4_fasttrap);
                   1364: #endif /* COMPAT_SVR4 */
1.447     christos 1365: #ifdef COMPAT_MACH
                   1366: extern vector IDTVEC(mach_trap);
                   1367: #endif
1.1       cgd      1368:
1.381     thorpej  1369: #define        KBTOB(x)        ((size_t)(x) * 1024UL)
                   1370:
1.484     fvdl     1371: void cpu_init_idt()
                   1372: {
                   1373:        struct region_descriptor region;
                   1374: #ifdef I586_CPU
                   1375:        setregion(&region, pentium_idt, NIDT * sizeof(idt[0]) - 1);
                   1376: #else
                   1377:        setregion(&region, idt, NIDT * sizeof(idt[0]) - 1);
                   1378: #endif
1.565     simonb   1379:        lidt(&region);
1.484     fvdl     1380: }
                   1381:
1.433     kanaoka  1382: void
1.568     perry    1383: add_mem_cluster(uint64_t seg_start, uint64_t seg_end, uint32_t type)
1.433     kanaoka  1384: {
                   1385:        extern struct extent *iomem_ex;
1.492     kanaoka  1386:        int i;
1.433     kanaoka  1387:
                   1388:        if (seg_end > 0x100000000ULL) {
                   1389:                printf("WARNING: skipping large "
                   1390:                    "memory map entry: "
                   1391:                    "0x%qx/0x%qx/0x%x\n",
                   1392:                    seg_start,
                   1393:                    (seg_end - seg_start),
                   1394:                    type);
                   1395:                return;
                   1396:        }
                   1397:
                   1398:        /*
                   1399:         * XXX Chop the last page off the size so that
                   1400:         * XXX it can fit in avail_end.
                   1401:         */
                   1402:        if (seg_end == 0x100000000ULL)
                   1403:                seg_end -= PAGE_SIZE;
                   1404:
                   1405:        if (seg_end <= seg_start)
                   1406:                return;
                   1407:
1.492     kanaoka  1408:        for (i = 0; i < mem_cluster_cnt; i++) {
                   1409:                if ((mem_clusters[i].start == round_page(seg_start))
                   1410:                    && (mem_clusters[i].size
                   1411:                            == trunc_page(seg_end) - mem_clusters[i].start)) {
                   1412: #ifdef DEBUG_MEMLOAD
                   1413:                        printf("WARNING: skipping duplicate segment entry\n");
                   1414: #endif
                   1415:                        return;
                   1416:                }
                   1417:        }
                   1418:
1.433     kanaoka  1419:        /*
                   1420:         * Allocate the physical addresses used by RAM
                   1421:         * from the iomem extent map.  This is done before
                   1422:         * the addresses are page rounded just to make
                   1423:         * sure we get them all.
                   1424:         */
                   1425:        if (extent_alloc_region(iomem_ex, seg_start,
                   1426:            seg_end - seg_start, EX_NOWAIT)) {
                   1427:                /* XXX What should we do? */
                   1428:                printf("WARNING: CAN'T ALLOCATE "
                   1429:                    "MEMORY SEGMENT "
                   1430:                    "(0x%qx/0x%qx/0x%x) FROM "
                   1431:                    "IOMEM EXTENT MAP!\n",
                   1432:                    seg_start, seg_end - seg_start, type);
1.492     kanaoka  1433:                return;
1.433     kanaoka  1434:        }
                   1435:
                   1436:        /*
                   1437:         * If it's not free memory, skip it.
                   1438:         */
                   1439:        if (type != BIM_Memory)
                   1440:                return;
                   1441:
                   1442:        /* XXX XXX XXX */
                   1443:        if (mem_cluster_cnt >= VM_PHYSSEG_MAX)
1.579     cube     1444:                panic("init386: too many memory segments "
                   1445:                    "(increase VM_PHYSSEG_MAX)");
1.433     kanaoka  1446:
                   1447:        seg_start = round_page(seg_start);
                   1448:        seg_end = trunc_page(seg_end);
                   1449:
                   1450:        if (seg_start == seg_end)
                   1451:                return;
                   1452:
                   1453:        mem_clusters[mem_cluster_cnt].start = seg_start;
                   1454:        mem_clusters[mem_cluster_cnt].size =
                   1455:            seg_end - seg_start;
                   1456:
                   1457:        if (avail_end < seg_end)
                   1458:                avail_end = seg_end;
                   1459:        physmem += atop(mem_clusters[mem_cluster_cnt].size);
                   1460:        mem_cluster_cnt++;
                   1461: }
                   1462:
1.59      mycroft  1463: void
1.484     fvdl     1464: initgdt(union descriptor *tgdt)
                   1465: {
                   1466:        struct region_descriptor region;
                   1467:        gdt = tgdt;
                   1468:        memset(gdt, 0, NGDT*sizeof(*gdt));
                   1469:        /* make gdt gates and memory segments */
                   1470:        setsegment(&gdt[GCODE_SEL].sd, 0, 0xfffff, SDT_MEMERA, SEL_KPL, 1, 1);
                   1471:        setsegment(&gdt[GDATA_SEL].sd, 0, 0xfffff, SDT_MEMRWA, SEL_KPL, 1, 1);
1.533     chs      1472:        setsegment(&gdt[GUCODE_SEL].sd, 0, x86_btop(I386_MAX_EXE_ADDR) - 1,
                   1473:            SDT_MEMERA, SEL_UPL, 1, 1);
                   1474:        setsegment(&gdt[GUCODEBIG_SEL].sd, 0, x86_btop(VM_MAXUSER_ADDRESS) - 1,
1.484     fvdl     1475:            SDT_MEMERA, SEL_UPL, 1, 1);
1.514     fvdl     1476:        setsegment(&gdt[GUDATA_SEL].sd, 0, x86_btop(VM_MAXUSER_ADDRESS) - 1,
1.484     fvdl     1477:            SDT_MEMRWA, SEL_UPL, 1, 1);
                   1478: #ifdef COMPAT_MACH
                   1479:        setgate(&gdt[GMACHCALLS_SEL].gd, &IDTVEC(mach_trap), 1,
1.489     fvdl     1480:            SDT_SYS386CGT, SEL_UPL, GSEL(GCODE_SEL, SEL_KPL));
1.484     fvdl     1481: #endif
                   1482: #if NBIOSCALL > 0
                   1483:        /* bios trampoline GDT entries */
                   1484:        setsegment(&gdt[GBIOSCODE_SEL].sd, 0, 0xfffff, SDT_MEMERA, SEL_KPL, 0,
                   1485:            0);
                   1486:        setsegment(&gdt[GBIOSDATA_SEL].sd, 0, 0xfffff, SDT_MEMRWA, SEL_KPL, 0,
                   1487:            0);
                   1488: #endif
                   1489:        setsegment(&gdt[GCPU_SEL].sd, &cpu_info_primary,
                   1490:            sizeof(struct cpu_info)-1, SDT_MEMRWA, SEL_KPL, 1, 1);
                   1491:
                   1492:        setregion(&region, gdt, NGDT * sizeof(gdt[0]) - 1);
                   1493:        lgdt(&region);
                   1494: }
                   1495:
                   1496: void
1.551     junyoung 1497: init386(paddr_t first_avail)
1.2       cgd      1498: {
1.484     fvdl     1499:        union descriptor *tgdt;
1.542     junyoung 1500:        extern void consinit(void);
1.375     drochner 1501:        extern struct extent *iomem_ex;
1.401     thorpej  1502:        struct btinfo_memmap *bim;
1.381     thorpej  1503:        struct region_descriptor region;
1.401     thorpej  1504:        int x, first16q;
1.568     perry    1505:        uint64_t seg_start, seg_end;
                   1506:        uint64_t seg_start1, seg_end1;
1.473     tshiozak 1507:        paddr_t realmode_reserved_start;
                   1508:        psize_t realmode_reserved_size;
                   1509:        int needs_earlier_install_pte0;
1.436     jdolecek 1510: #if NBIOSCALL > 0
                   1511:        extern int biostramp_image_size;
                   1512:        extern u_char biostramp_image[];
                   1513: #endif
1.1       cgd      1514:
1.484     fvdl     1515:        cpu_probe_features(&cpu_info_primary);
                   1516:        cpu_feature = cpu_info_primary.ci_feature_flags;
1.553     lukem    1517:        cpu_feature2 = cpu_info_primary.ci_feature2_flags;
1.484     fvdl     1518:
1.573     yamt     1519:        proc0paddr = UAREA_TO_USER(proc0uarea);
1.508     thorpej  1520:        lwp0.l_addr = proc0paddr;
                   1521:        cpu_info_primary.ci_curpcb = &lwp0.l_addr->u_pcb;
1.275     mycroft  1522:
1.514     fvdl     1523:        x86_bus_space_init();
1.84      cgd      1524:        consinit();     /* XXX SHOULD NOT BE DONE HERE */
1.401     thorpej  1525:        /*
                   1526:         * Initailize PAGE_SIZE-dependent variables.
                   1527:         */
                   1528:        uvm_setpagesize();
1.450     thorpej  1529:
                   1530:        /*
                   1531:         * Saving SSE registers won't work if the save area isn't
                   1532:         * 16-byte aligned.
                   1533:         */
                   1534:        if (offsetof(struct user, u_pcb.pcb_savefpu) & 0xf)
                   1535:                panic("init386: pcb_savefpu not 16-byte aligned");
1.440     thorpej  1536:
                   1537:        /*
                   1538:         * Start with 2 color bins -- this is just a guess to get us
                   1539:         * started.  We'll recolor when we determine the largest cache
                   1540:         * sizes on the system.
                   1541:         */
                   1542:        uvmexp.ncolors = 2;
1.401     thorpej  1543:
1.473     tshiozak 1544:        /*
1.484     fvdl     1545:         * BIOS leaves data in physical page 0
                   1546:         * Even if it didn't, our VM system doesn't like using zero as a
                   1547:         * physical page number.
                   1548:         * We may also need pages in low memory (one each) for secondary CPU
                   1549:         * startup, for BIOS calls, and for ACPI, plus a page table page to map
                   1550:         * them into the first few pages of the kernel's pmap.
1.473     tshiozak 1551:         */
                   1552:        avail_start = PAGE_SIZE;
                   1553:
                   1554:        /*
                   1555:         * reserve memory for real-mode call
                   1556:         */
                   1557:        needs_earlier_install_pte0 = 0;
                   1558:        realmode_reserved_start = 0;
                   1559:        realmode_reserved_size = 0;
1.414     thorpej  1560: #if NBIOSCALL > 0
1.473     tshiozak 1561:        /* save us a page for trampoline code */
                   1562:        realmode_reserved_size += PAGE_SIZE;
                   1563:        needs_earlier_install_pte0 = 1;
                   1564: #endif
1.484     fvdl     1565: #ifdef MULTIPROCESSOR                                           /* XXX */
                   1566:        KASSERT(avail_start == PAGE_SIZE);                       /* XXX */
                   1567:        if (realmode_reserved_size < MP_TRAMPOLINE)              /* XXX */
                   1568:                realmode_reserved_size = MP_TRAMPOLINE;          /* XXX */
                   1569:        needs_earlier_install_pte0 = 1;                          /* XXX */
                   1570: #endif                                                          /* XXX */
1.473     tshiozak 1571: #if NACPI > 0
                   1572:        /* trampoline code for wake handler */
                   1573:        realmode_reserved_size += ptoa(acpi_md_get_npages_of_wakecode()+1);
                   1574:        needs_earlier_install_pte0 = 1;
                   1575: #endif
                   1576:        if (needs_earlier_install_pte0) {
                   1577:                /* page table for directory entry 0 */
                   1578:                realmode_reserved_size += PAGE_SIZE;
                   1579:        }
                   1580:        if (realmode_reserved_size>0) {
                   1581:                realmode_reserved_start = avail_start;
                   1582:                avail_start += realmode_reserved_size;
                   1583:        }
1.414     thorpej  1584:
1.492     kanaoka  1585: #ifdef DEBUG_MEMLOAD
                   1586:        printf("mem_cluster_count: %d\n", mem_cluster_cnt);
                   1587: #endif
                   1588:
1.401     thorpej  1589:        /*
                   1590:         * Call pmap initialization to make new kernel address space.
                   1591:         * We must do this before loading pages into the VM system.
                   1592:         */
1.314     thorpej  1593:        pmap_bootstrap((vaddr_t)atdevbase + IOM_SIZE);
1.2       cgd      1594:
1.401     thorpej  1595:        /*
                   1596:         * Check to see if we have a memory map from the BIOS (passed
                   1597:         * to us by the boot program.
                   1598:         */
1.577     mrg      1599:        if ((biosmem_implicit || (biosbasemem == 0 && biosextmem == 0)) &&
1.575     mrg      1600:            (bim = lookup_bootinfo(BTINFO_MEMMAP)) != NULL && bim->num > 0) {
1.463     enami    1601: #ifdef DEBUG_MEMLOAD
1.401     thorpej  1602:                printf("BIOS MEMORY MAP (%d ENTRIES):\n", bim->num);
                   1603: #endif
                   1604:                for (x = 0; x < bim->num; x++) {
1.463     enami    1605: #ifdef DEBUG_MEMLOAD
1.401     thorpej  1606:                        printf("    addr 0x%qx  size 0x%qx  type 0x%x\n",
                   1607:                            bim->entry[x].addr,
                   1608:                            bim->entry[x].size,
                   1609:                            bim->entry[x].type);
                   1610: #endif
                   1611:
                   1612:                        /*
                   1613:                         * If the segment is not memory, skip it.
                   1614:                         */
                   1615:                        switch (bim->entry[x].type) {
                   1616:                        case BIM_Memory:
                   1617:                        case BIM_ACPI:
                   1618:                        case BIM_NVS:
                   1619:                                break;
                   1620:                        default:
                   1621:                                continue;
                   1622:                        }
                   1623:
                   1624:                        /*
1.586.2.5  liamjfoy 1625:                         * If the segment is smaller than a page, skip it.
                   1626:                         */
                   1627:                        if (bim->entry[x].size < NBPG) {
                   1628:                                continue;
                   1629:                        }
                   1630:
                   1631:                        /*
1.401     thorpej  1632:                         * Sanity check the entry.
                   1633:                         * XXX Need to handle uint64_t in extent code
                   1634:                         * XXX and 64-bit physical addresses in i386
                   1635:                         * XXX port.
                   1636:                         */
                   1637:                        seg_start = bim->entry[x].addr;
                   1638:                        seg_end = bim->entry[x].addr + bim->entry[x].size;
                   1639:
1.432     kanaoka  1640:                        /*
1.433     kanaoka  1641:                         *   Avoid Compatibility Holes.
                   1642:                         * XXX  Holes within memory space that allow access
                   1643:                         * XXX to be directed to the PC-compatible frame buffer
1.484     fvdl     1644:                         * XXX (0xa0000-0xbffff),to adapter ROM space
1.433     kanaoka  1645:                         * XXX (0xc0000-0xdffff), and to system BIOS space
                   1646:                         * XXX (0xe0000-0xfffff).
                   1647:                         * XXX  Some laptop(for example,Toshiba Satellite2550X)
                   1648:                         * XXX report this area and occurred problems,
                   1649:                         * XXX so we avoid this area.
1.432     kanaoka  1650:                         */
1.433     kanaoka  1651:                        if (seg_start < 0x100000 && seg_end > 0xa0000) {
                   1652:                                printf("WARNING: memory map entry overlaps "
                   1653:                                    "with ``Compatibility Holes'': "
                   1654:                                    "0x%qx/0x%qx/0x%x\n", seg_start,
                   1655:                                    seg_end - seg_start, bim->entry[x].type);
                   1656:                                add_mem_cluster(seg_start, 0xa0000,
                   1657:                                    bim->entry[x].type);
                   1658:                                add_mem_cluster(0x100000, seg_end,
1.401     thorpej  1659:                                    bim->entry[x].type);
1.433     kanaoka  1660:                        } else
                   1661:                                add_mem_cluster(seg_start, seg_end,
1.401     thorpej  1662:                                    bim->entry[x].type);
                   1663:                }
1.421     aymeric  1664:        }
1.575     mrg      1665:
1.421     aymeric  1666:        /*
                   1667:         * If the loop above didn't find any valid segment, fall back to
                   1668:         * former code.
                   1669:         */
                   1670:        if (mem_cluster_cnt == 0) {
1.401     thorpej  1671:                /*
                   1672:                 * Allocate the physical addresses used by RAM from the iomem
                   1673:                 * extent map.  This is done before the addresses are
                   1674:                 * page rounded just to make sure we get them all.
                   1675:                 */
                   1676:                if (extent_alloc_region(iomem_ex, 0, KBTOB(biosbasemem),
                   1677:                    EX_NOWAIT)) {
                   1678:                        /* XXX What should we do? */
                   1679:                        printf("WARNING: CAN'T ALLOCATE BASE MEMORY FROM "
                   1680:                            "IOMEM EXTENT MAP!\n");
                   1681:                }
                   1682:                mem_clusters[0].start = 0;
                   1683:                mem_clusters[0].size = trunc_page(KBTOB(biosbasemem));
                   1684:                physmem += atop(mem_clusters[0].size);
                   1685:                if (extent_alloc_region(iomem_ex, IOM_END, KBTOB(biosextmem),
                   1686:                    EX_NOWAIT)) {
                   1687:                        /* XXX What should we do? */
                   1688:                        printf("WARNING: CAN'T ALLOCATE EXTENDED MEMORY FROM "
                   1689:                            "IOMEM EXTENT MAP!\n");
                   1690:                }
                   1691: #if NISADMA > 0
                   1692:                /*
                   1693:                 * Some motherboards/BIOSes remap the 384K of RAM that would
                   1694:                 * normally be covered by the ISA hole to the end of memory
                   1695:                 * so that it can be used.  However, on a 16M system, this
                   1696:                 * would cause bounce buffers to be allocated and used.
                   1697:                 * This is not desirable behaviour, as more than 384K of
                   1698:                 * bounce buffers might be allocated.  As a work-around,
                   1699:                 * we round memory down to the nearest 1M boundary if
                   1700:                 * we're using any isadma devices and the remapped memory
                   1701:                 * is what puts us over 16M.
                   1702:                 */
                   1703:                if (biosextmem > (15*1024) && biosextmem < (16*1024)) {
                   1704:                        char pbuf[9];
                   1705:
                   1706:                        format_bytes(pbuf, sizeof(pbuf),
                   1707:                            biosextmem - (15*1024));
                   1708:                        printf("Warning: ignoring %s of remapped memory\n",
                   1709:                            pbuf);
                   1710:                        biosextmem = (15*1024);
                   1711:                }
                   1712: #endif
                   1713:                mem_clusters[1].start = IOM_END;
                   1714:                mem_clusters[1].size = trunc_page(KBTOB(biosextmem));
                   1715:                physmem += atop(mem_clusters[1].size);
                   1716:
                   1717:                mem_cluster_cnt = 2;
                   1718:
                   1719:                avail_end = IOM_END + trunc_page(KBTOB(biosextmem));
                   1720:        }
                   1721:        /*
                   1722:         * If we have 16M of RAM or less, just put it all on
                   1723:         * the default free list.  Otherwise, put the first
                   1724:         * 16M of RAM on a lower priority free list (so that
                   1725:         * all of the ISA DMA'able memory won't be eaten up
                   1726:         * first-off).
                   1727:         */
                   1728:        if (avail_end <= (16 * 1024 * 1024))
                   1729:                first16q = VM_FREELIST_DEFAULT;
                   1730:        else
                   1731:                first16q = VM_FREELIST_FIRST16;
                   1732:
                   1733:        /* Make sure the end of the space used by the kernel is rounded. */
                   1734:        first_avail = round_page(first_avail);
                   1735:
                   1736:        /*
                   1737:         * Now, load the memory clusters (which have already been
                   1738:         * rounded and truncated) into the VM system.
                   1739:         *
                   1740:         * NOTE: WE ASSUME THAT MEMORY STARTS AT 0 AND THAT THE KERNEL
                   1741:         * IS LOADED AT IOM_END (1M).
                   1742:         */
                   1743:        for (x = 0; x < mem_cluster_cnt; x++) {
                   1744:                seg_start = mem_clusters[x].start;
                   1745:                seg_end = mem_clusters[x].start + mem_clusters[x].size;
                   1746:                seg_start1 = 0;
                   1747:                seg_end1 = 0;
                   1748:
                   1749:                /*
                   1750:                 * Skip memory before our available starting point.
                   1751:                 */
                   1752:                if (seg_end <= avail_start)
                   1753:                        continue;
                   1754:
                   1755:                if (avail_start >= seg_start && avail_start < seg_end) {
                   1756:                        if (seg_start != 0)
                   1757:                                panic("init386: memory doesn't start at 0");
                   1758:                        seg_start = avail_start;
                   1759:                        if (seg_start == seg_end)
                   1760:                                continue;
                   1761:                }
                   1762:
                   1763:                /*
                   1764:                 * If this segment contains the kernel, split it
                   1765:                 * in two, around the kernel.
                   1766:                 */
                   1767:                if (seg_start <= IOM_END && first_avail <= seg_end) {
                   1768:                        seg_start1 = first_avail;
                   1769:                        seg_end1 = seg_end;
                   1770:                        seg_end = IOM_END;
                   1771:                }
                   1772:
                   1773:                /* First hunk */
                   1774:                if (seg_start != seg_end) {
1.480     erh      1775:                        if (seg_start < (16 * 1024 * 1024) &&
1.401     thorpej  1776:                            first16q != VM_FREELIST_DEFAULT) {
1.568     perry    1777:                                uint64_t tmp;
1.401     thorpej  1778:
                   1779:                                if (seg_end > (16 * 1024 * 1024))
                   1780:                                        tmp = (16 * 1024 * 1024);
                   1781:                                else
                   1782:                                        tmp = seg_end;
1.492     kanaoka  1783:
                   1784:                                if (tmp != seg_start) {
1.463     enami    1785: #ifdef DEBUG_MEMLOAD
1.492     kanaoka  1786:                                        printf("loading 0x%qx-0x%qx "
                   1787:                                            "(0x%lx-0x%lx)\n",
                   1788:                                            seg_start, tmp,
                   1789:                                            atop(seg_start), atop(tmp));
                   1790: #endif
                   1791:                                        uvm_page_physload(atop(seg_start),
                   1792:                                            atop(tmp), atop(seg_start),
                   1793:                                            atop(tmp), first16q);
                   1794:                                }
1.401     thorpej  1795:                                seg_start = tmp;
                   1796:                        }
1.411     enami    1797:
                   1798:                        if (seg_start != seg_end) {
1.463     enami    1799: #ifdef DEBUG_MEMLOAD
1.411     enami    1800:                                printf("loading 0x%qx-0x%qx (0x%lx-0x%lx)\n",
                   1801:                                    seg_start, seg_end,
                   1802:                                    atop(seg_start), atop(seg_end));
                   1803: #endif
                   1804:                                uvm_page_physload(atop(seg_start),
                   1805:                                    atop(seg_end), atop(seg_start),
                   1806:                                    atop(seg_end), VM_FREELIST_DEFAULT);
                   1807:                        }
1.401     thorpej  1808:                }
                   1809:
                   1810:                /* Second hunk */
                   1811:                if (seg_start1 != seg_end1) {
1.480     erh      1812:                        if (seg_start1 < (16 * 1024 * 1024) &&
1.401     thorpej  1813:                            first16q != VM_FREELIST_DEFAULT) {
1.568     perry    1814:                                uint64_t tmp;
1.401     thorpej  1815:
                   1816:                                if (seg_end1 > (16 * 1024 * 1024))
                   1817:                                        tmp = (16 * 1024 * 1024);
                   1818:                                else
                   1819:                                        tmp = seg_end1;
1.492     kanaoka  1820:
                   1821:                                if (tmp != seg_start1) {
1.463     enami    1822: #ifdef DEBUG_MEMLOAD
1.492     kanaoka  1823:                                        printf("loading 0x%qx-0x%qx "
                   1824:                                            "(0x%lx-0x%lx)\n",
                   1825:                                            seg_start1, tmp,
                   1826:                                            atop(seg_start1), atop(tmp));
                   1827: #endif
                   1828:                                        uvm_page_physload(atop(seg_start1),
                   1829:                                            atop(tmp), atop(seg_start1),
                   1830:                                            atop(tmp), first16q);
                   1831:                                }
1.401     thorpej  1832:                                seg_start1 = tmp;
                   1833:                        }
1.412     enami    1834:
                   1835:                        if (seg_start1 != seg_end1) {
1.463     enami    1836: #ifdef DEBUG_MEMLOAD
1.412     enami    1837:                                printf("loading 0x%qx-0x%qx (0x%lx-0x%lx)\n",
                   1838:                                    seg_start1, seg_end1,
                   1839:                                    atop(seg_start1), atop(seg_end1));
                   1840: #endif
                   1841:                                uvm_page_physload(atop(seg_start1),
                   1842:                                    atop(seg_end1), atop(seg_start1),
                   1843:                                    atop(seg_end1), VM_FREELIST_DEFAULT);
                   1844:                        }
1.401     thorpej  1845:                }
                   1846:        }
                   1847:
                   1848:        /*
                   1849:         * Steal memory for the message buffer (at end of core).
                   1850:         */
                   1851:        {
1.543     mycroft  1852:                struct vm_physseg *vps;
1.401     thorpej  1853:                psize_t sz = round_page(MSGBUFSIZE);
                   1854:                psize_t reqsz = sz;
                   1855:
1.586.2.1  tron     1856:        search_again:
1.401     thorpej  1857:                for (x = 0; x < vm_nphysseg; x++) {
                   1858:                        vps = &vm_physmem[x];
                   1859:                        if (ptoa(vps->avail_end) == avail_end)
1.543     mycroft  1860:                                goto found;
1.401     thorpej  1861:                }
1.543     mycroft  1862:                panic("init386: can't find end of memory");
1.401     thorpej  1863:
1.543     mycroft  1864:        found:
1.401     thorpej  1865:                /* Shrink so it'll fit in the last segment. */
                   1866:                if ((vps->avail_end - vps->avail_start) < atop(sz))
                   1867:                        sz = ptoa(vps->avail_end - vps->avail_start);
                   1868:
                   1869:                vps->avail_end -= atop(sz);
                   1870:                vps->end -= atop(sz);
1.586.2.1  tron     1871:                msgbuf_p_seg[msgbuf_p_cnt].sz = sz;
                   1872:                msgbuf_p_seg[msgbuf_p_cnt++].paddr = ptoa(vps->avail_end);
1.401     thorpej  1873:
                   1874:                /* Remove the last segment if it now has no pages. */
                   1875:                if (vps->start == vps->end) {
                   1876:                        for (vm_nphysseg--; x < vm_nphysseg; x++)
                   1877:                                vm_physmem[x] = vm_physmem[x + 1];
                   1878:                }
                   1879:
                   1880:                /* Now find where the new avail_end is. */
                   1881:                for (avail_end = 0, x = 0; x < vm_nphysseg; x++)
                   1882:                        if (vm_physmem[x].avail_end > avail_end)
                   1883:                                avail_end = vm_physmem[x].avail_end;
                   1884:                avail_end = ptoa(avail_end);
                   1885:
1.586.2.1  tron     1886:                if (sz != reqsz) {
                   1887:                        reqsz -= sz;
                   1888:                        if (msgbuf_p_cnt != VM_PHYSSEG_MAX) {
                   1889:                /* if still segments available, get memory from next one ... */
1.586.2.2  tron     1890:                                sz = reqsz;
                   1891:                                goto search_again;
1.586.2.1  tron     1892:                        }
1.401     thorpej  1893:                /* Warn if the message buffer had to be shrunk. */
                   1894:                        printf("WARNING: %ld bytes not available for msgbuf "
1.586.2.2  tron     1895:                               "in last cluster (%ld used)\n", (long)MSGBUFSIZE, MSGBUFSIZE - reqsz);
1.586.2.1  tron     1896:                }
1.401     thorpej  1897:        }
                   1898:
1.473     tshiozak 1899:        /*
                   1900:         * install PT page for the first 4M if needed.
                   1901:         */
                   1902:        if (needs_earlier_install_pte0) {
                   1903:                paddr_t paddr;
                   1904: #ifdef DIAGNOSTIC
                   1905:                if (realmode_reserved_size < PAGE_SIZE) {
                   1906:                        panic("cannot steal memory for first 4M PT page.");
                   1907:                }
                   1908: #endif
                   1909:                paddr=realmode_reserved_start+realmode_reserved_size-PAGE_SIZE;
1.561     yamt     1910:                pmap_kenter_pa((vaddr_t)vtopte(0), paddr,
                   1911:                           VM_PROT_READ|VM_PROT_WRITE);
1.473     tshiozak 1912:                pmap_update(pmap_kernel());
                   1913:                /* make sure it is clean before using */
                   1914:                memset(vtopte(0), 0, PAGE_SIZE);
                   1915:                realmode_reserved_size -= PAGE_SIZE;
                   1916:        }
                   1917:
1.295     drochner 1918: #if NBIOSCALL > 0
1.436     jdolecek 1919:        /*
                   1920:         * this should be caught at kernel build time, but put it here
                   1921:         * in case someone tries to fake it out...
                   1922:         */
                   1923: #ifdef DIAGNOSTIC
1.473     tshiozak 1924:        if (realmode_reserved_start > BIOSTRAMP_BASE ||
1.474     tron     1925:            (realmode_reserved_start+realmode_reserved_size) < (BIOSTRAMP_BASE+
1.473     tshiozak 1926:                                                               PAGE_SIZE)) {
                   1927:            panic("cannot steal memory for PT page of bioscall.");
                   1928:        }
1.436     jdolecek 1929:        if (biostramp_image_size > PAGE_SIZE)
1.483     provos   1930:            panic("biostramp_image_size too big: %x vs. %x",
1.436     jdolecek 1931:                  biostramp_image_size, PAGE_SIZE);
                   1932: #endif
                   1933:        pmap_kenter_pa((vaddr_t)BIOSTRAMP_BASE, /* virtual */
                   1934:                       (paddr_t)BIOSTRAMP_BASE, /* physical */
                   1935:                       VM_PROT_ALL);            /* protection */
1.456     chris    1936:        pmap_update(pmap_kernel());
1.436     jdolecek 1937:        memcpy((caddr_t)BIOSTRAMP_BASE, biostramp_image, biostramp_image_size);
                   1938: #ifdef DEBUG_BIOSCALL
                   1939:        printf("biostramp installed @ %x\n", BIOSTRAMP_BASE);
                   1940: #endif
1.473     tshiozak 1941:        realmode_reserved_size  -= PAGE_SIZE;
                   1942:        realmode_reserved_start += PAGE_SIZE;
                   1943: #endif
                   1944:
                   1945: #if NACPI > 0
                   1946:        /*
                   1947:         * Steal memory for the acpi wake code
                   1948:         */
                   1949:        {
                   1950:                paddr_t paddr, p;
                   1951:                psize_t sz;
                   1952:                int npg;
                   1953:
                   1954:                paddr = realmode_reserved_start;
                   1955:                npg = acpi_md_get_npages_of_wakecode();
                   1956:                sz = ptoa(npg);
                   1957: #ifdef DIAGNOSTIC
                   1958:                if (realmode_reserved_size < sz) {
                   1959:                        panic("cannot steal memory for ACPI wake code.");
                   1960:                }
                   1961: #endif
                   1962:
                   1963:                /* identical mapping */
                   1964:                p = paddr;
                   1965:                for (x=0; x<npg; x++) {
                   1966:                        printf("kenter: 0x%08X\n", (unsigned)p);
                   1967:                        pmap_kenter_pa((vaddr_t)p, p, VM_PROT_ALL);
                   1968:                        p += PAGE_SIZE;
                   1969:                }
                   1970:                pmap_update(pmap_kernel());
                   1971:
                   1972:                acpi_md_install_wakecode(paddr);
                   1973:
                   1974:                realmode_reserved_size  -= sz;
                   1975:                realmode_reserved_start += sz;
                   1976:        }
1.295     drochner 1977: #endif
1.59      mycroft  1978:
1.561     yamt     1979:        pmap_kenter_pa(idt_vaddr, idt_paddr, VM_PROT_READ|VM_PROT_WRITE);
1.456     chris    1980:        pmap_update(pmap_kernel());
1.484     fvdl     1981:        memset((void *)idt_vaddr, 0, PAGE_SIZE);
                   1982:
1.516     fvdl     1983:        idt = (struct gate_descriptor *)idt_vaddr;
1.275     mycroft  1984: #ifdef I586_CPU
1.561     yamt     1985:        pmap_kenter_pa(pentium_idt_vaddr, idt_paddr, VM_PROT_READ);
1.275     mycroft  1986:        pentium_idt = (union descriptor *)pentium_idt_vaddr;
                   1987: #endif
1.484     fvdl     1988:        pmap_update(pmap_kernel());
                   1989:
                   1990:        tgdt = gdt;
1.516     fvdl     1991:        gdt = (union descriptor *)
                   1992:                    ((char *)idt + NIDT * sizeof (struct gate_descriptor));
1.275     mycroft  1993:        ldt = gdt + NGDT;
                   1994:
1.484     fvdl     1995:        memcpy(gdt, tgdt, NGDT*sizeof(*gdt));
1.275     mycroft  1996:
                   1997:        setsegment(&gdt[GLDT_SEL].sd, ldt, NLDT * sizeof(ldt[0]) - 1,
                   1998:            SDT_SYSLDT, SEL_KPL, 0, 0);
                   1999:
                   2000:        /* make ldt gates and memory segments */
                   2001:        setgate(&ldt[LSYS5CALLS_SEL].gd, &IDTVEC(osyscall), 1,
1.489     fvdl     2002:            SDT_SYS386CGT, SEL_UPL, GSEL(GCODE_SEL, SEL_KPL));
1.447     christos 2003:
1.275     mycroft  2004:        ldt[LUCODE_SEL] = gdt[GUCODE_SEL];
1.533     chs      2005:        ldt[LUCODEBIG_SEL] = gdt[GUCODEBIG_SEL];
1.275     mycroft  2006:        ldt[LUDATA_SEL] = gdt[GUDATA_SEL];
1.324     christos 2007:        ldt[LSOL26CALLS_SEL] = ldt[LBSDICALLS_SEL] = ldt[LSYS5CALLS_SEL];
1.275     mycroft  2008:
                   2009:        /* exceptions */
1.498     fvdl     2010:        for (x = 0; x < 32; x++) {
1.516     fvdl     2011:                setgate(&idt[x], IDTVEC(exceptions)[x], 0, SDT_SYS386TGT,
1.489     fvdl     2012:                    (x == 3 || x == 4) ? SEL_UPL : SEL_KPL,
                   2013:                    GSEL(GCODE_SEL, SEL_KPL));
1.498     fvdl     2014:                idt_allocmap[x] = 1;
                   2015:        }
1.257     thorpej  2016:
1.275     mycroft  2017:        /* new-style interrupt gate for syscalls */
1.516     fvdl     2018:        setgate(&idt[128], &IDTVEC(syscall), 0, SDT_SYS386TGT, SEL_UPL,
1.489     fvdl     2019:            GSEL(GCODE_SEL, SEL_KPL));
1.498     fvdl     2020:        idt_allocmap[128] = 1;
1.333     christos 2021: #ifdef COMPAT_SVR4
1.516     fvdl     2022:        setgate(&idt[0xd2], &IDTVEC(svr4_fasttrap), 0, SDT_SYS386TGT,
1.489     fvdl     2023:            SEL_UPL, GSEL(GCODE_SEL, SEL_KPL));
1.498     fvdl     2024:        idt_allocmap[0xd2] = 1;
1.333     christos 2025: #endif /* COMPAT_SVR4 */
1.264     mycroft  2026:
1.275     mycroft  2027:        setregion(&region, gdt, NGDT * sizeof(gdt[0]) - 1);
                   2028:        lgdt(&region);
1.484     fvdl     2029:
                   2030:        cpu_init_idt();
1.264     mycroft  2031:
1.522     ragge    2032: #if NKSYMS || defined(DDB) || defined(LKM)
1.308     tv       2033:        {
                   2034:                extern int end;
1.585     jmmv     2035:                boolean_t loaded;
1.336     christos 2036:                struct btinfo_symtab *symtab;
1.308     tv       2037:
1.522     ragge    2038: #ifdef DDB
1.484     fvdl     2039:                db_machine_init();
1.522     ragge    2040: #endif
1.484     fvdl     2041:
1.585     jmmv     2042: #if defined(MULTIBOOT)
                   2043:                loaded = multiboot_ksyms_init();
                   2044: #else
                   2045:                loaded = FALSE;
                   2046: #endif
                   2047:                if (!loaded) {
                   2048:                    symtab = lookup_bootinfo(BTINFO_SYMTAB);
                   2049:                    if (symtab) {
                   2050:                            symtab->ssym += KERNBASE;
                   2051:                            symtab->esym += KERNBASE;
                   2052:                            ksyms_init(symtab->nsym, (int *)symtab->ssym,
                   2053:                                (int *)symtab->esym);
                   2054:                    } else
                   2055:                            ksyms_init(*(int *)&end, ((int *)&end) + 1, esym);
1.336     christos 2056:                }
1.308     tv       2057:        }
1.522     ragge    2058: #endif
                   2059: #ifdef DDB
1.190     mycroft  2060:        if (boothowto & RB_KDB)
                   2061:                Debugger();
1.377     ws       2062: #endif
                   2063: #ifdef IPKDB
                   2064:        ipkdb_init();
                   2065:        if (boothowto & RB_KDB)
                   2066:                ipkdb_connect(0);
1.190     mycroft  2067: #endif
                   2068: #ifdef KGDB
1.243     drochner 2069:        kgdb_port_init();
1.235     thorpej  2070:        if (boothowto & RB_KDB) {
                   2071:                kgdb_debug_init = 1;
1.242     drochner 2072:                kgdb_connect(1);
1.235     thorpej  2073:        }
1.384     jdolecek 2074: #endif
                   2075:
                   2076: #if NMCA > 0
                   2077:        /* check for MCA bus, needed to be done before ISA stuff - if
                   2078:         * MCA is detected, ISA needs to use level triggered interrupts
                   2079:         * by default */
                   2080:        mca_busprobe();
1.190     mycroft  2081: #endif
1.275     mycroft  2082:
1.498     fvdl     2083:        intr_default_setup();
1.431     thorpej  2084:
                   2085:        /* Initialize software interrupts. */
                   2086:        softintr_init();
1.275     mycroft  2087:
1.498     fvdl     2088:        splraise(IPL_IPI);
1.275     mycroft  2089:        enable_intr();
                   2090:
                   2091:        if (physmem < btoc(2 * 1024 * 1024)) {
                   2092:                printf("warning: too little memory available; "
1.383     mycroft  2093:                       "have %lu bytes, want %lu bytes\n"
1.275     mycroft  2094:                       "running in degraded mode\n"
                   2095:                       "press a key to confirm\n\n",
1.383     mycroft  2096:                       ptoa(physmem), 2*1024*1024UL);
1.275     mycroft  2097:                cngetc();
                   2098:        }
1.507     jdolecek 2099:
                   2100: #ifdef __HAVE_CPU_MAXPROC
                   2101:        /* Make sure maxproc is sane */
                   2102:        if (maxproc > cpu_maxproc())
                   2103:                maxproc = cpu_maxproc();
                   2104: #endif
1.1       cgd      2105: }
                   2106:
1.107     deraadt  2107: #ifdef COMPAT_NOMID
                   2108: static int
1.566     christos 2109: exec_nomid(struct lwp *l, struct exec_package *epp)
1.31      cgd      2110: {
1.59      mycroft  2111:        int error;
                   2112:        u_long midmag, magic;
                   2113:        u_short mid;
1.80      cgd      2114:        struct exec *execp = epp->ep_hdr;
1.31      cgd      2115:
1.80      cgd      2116:        /* check on validity of epp->ep_hdr performed by exec_out_makecmds */
                   2117:
                   2118:        midmag = ntohl(execp->a_midmag);
1.59      mycroft  2119:        mid = (midmag >> 16) & 0xffff;
                   2120:        magic = midmag & 0xffff;
                   2121:
                   2122:        if (magic == 0) {
1.80      cgd      2123:                magic = (execp->a_midmag & 0xffff);
1.59      mycroft  2124:                mid = MID_ZERO;
                   2125:        }
                   2126:
                   2127:        midmag = mid << 16 | magic;
                   2128:
                   2129:        switch (midmag) {
                   2130:        case (MID_ZERO << 16) | ZMAGIC:
                   2131:                /*
                   2132:                 * 386BSD's ZMAGIC format:
                   2133:                 */
1.566     christos 2134:                error = exec_aout_prep_oldzmagic(l, epp);
1.59      mycroft  2135:                break;
                   2136:
                   2137:        case (MID_ZERO << 16) | QMAGIC:
                   2138:                /*
                   2139:                 * BSDI's QMAGIC format:
                   2140:                 * same as new ZMAGIC format, but with different magic number
                   2141:                 */
1.566     christos 2142:                error = exec_aout_prep_zmagic(l, epp);
1.59      mycroft  2143:                break;
                   2144:
1.202     christos 2145:        case (MID_ZERO << 16) | NMAGIC:
                   2146:                /*
                   2147:                 * BSDI's NMAGIC format:
                   2148:                 * same as NMAGIC format, but with different magic number
                   2149:                 * and with text starting at 0.
                   2150:                 */
1.566     christos 2151:                error = exec_aout_prep_oldnmagic(l, epp);
1.202     christos 2152:                break;
                   2153:
                   2154:        case (MID_ZERO << 16) | OMAGIC:
                   2155:                /*
                   2156:                 * BSDI's OMAGIC format:
                   2157:                 * same as OMAGIC format, but with different magic number
                   2158:                 * and with text starting at 0.
                   2159:                 */
1.566     christos 2160:                error = exec_aout_prep_oldomagic(l, epp);
1.202     christos 2161:                break;
                   2162:
1.59      mycroft  2163:        default:
                   2164:                error = ENOEXEC;
                   2165:        }
                   2166:
                   2167:        return error;
1.107     deraadt  2168: }
1.31      cgd      2169: #endif
1.107     deraadt  2170:
                   2171: /*
                   2172:  * cpu_exec_aout_makecmds():
1.549     wiz      2173:  *     CPU-dependent a.out format hook for execve().
1.107     deraadt  2174:  *
                   2175:  * Determine of the given exec package refers to something which we
                   2176:  * understand and, if so, set up the vmcmds for it.
                   2177:  *
                   2178:  * On the i386, old (386bsd) ZMAGIC binaries and BSDI QMAGIC binaries
                   2179:  * if COMPAT_NOMID is given as a kernel option.
                   2180:  */
                   2181: int
1.566     christos 2182: cpu_exec_aout_makecmds(struct lwp *l, struct exec_package *epp)
1.107     deraadt  2183: {
                   2184:        int error = ENOEXEC;
                   2185:
                   2186: #ifdef COMPAT_NOMID
1.566     christos 2187:        if ((error = exec_nomid(l, epp)) == 0)
1.107     deraadt  2188:                return error;
1.581     thorpej  2189: #else
                   2190:        (void) l;
                   2191:        (void) epp;
1.107     deraadt  2192: #endif /* ! COMPAT_NOMID */
                   2193:
                   2194:        return error;
1.31      cgd      2195: }
1.84      cgd      2196:
1.484     fvdl     2197: #include <dev/ic/mc146818reg.h>                /* for NVRAM POST */
                   2198: #include <i386/isa/nvram.h>            /* for NVRAM POST */
                   2199:
1.149     mycroft  2200: void
                   2201: cpu_reset()
                   2202: {
1.555     mycroft  2203:        struct region_descriptor region;
1.149     mycroft  2204:
1.224     mycroft  2205:        disable_intr();
                   2206:
1.227     mycroft  2207:        /*
1.484     fvdl     2208:         * Ensure the NVRAM reset byte contains something vaguely sane.
                   2209:         */
                   2210:
                   2211:        outb(IO_RTC, NVRAM_RESET);
                   2212:        outb(IO_RTC+1, NVRAM_RESET_RST);
                   2213:
                   2214:        /*
1.564     dyoung   2215:         * Reset AMD Geode SC1100.
                   2216:         *
1.565     simonb   2217:         * 1) Write PCI Configuration Address Register (0xcf8) to
                   2218:         *    select Function 0, Register 0x44: Bridge Configuration,
                   2219:         *    GPIO and LPC Configuration Register Space, Reset
                   2220:         *    Control Register.
1.564     dyoung   2221:         *
1.565     simonb   2222:         * 2) Write 0xf to PCI Configuration Data Register (0xcfc)
                   2223:         *    to reset IDE controller, IDE bus, and PCI bus, and
                   2224:         *    to trigger a system-wide reset.
1.564     dyoung   2225:         *
                   2226:         * See AMD Geode SC1100 Processor Data Book, Revision 2.0,
                   2227:         * sections 6.3.1, 6.3.2, and 6.4.1.
                   2228:         */
                   2229:        if (cpu_info_primary.ci_signature == 0x540) {
                   2230:                outl(0xcf8, 0x80009044ul);
                   2231:                outl(0xcfc, 0xf);
1.565     simonb   2232:        }
1.564     dyoung   2233:
                   2234:        /*
1.227     mycroft  2235:         * The keyboard controller has 4 random output pins, one of which is
                   2236:         * connected to the RESET pin on the CPU in many PCs.  We tell the
                   2237:         * keyboard controller to pulse this line a couple of times.
                   2238:         */
1.273     drochner 2239:        outb(IO_KBD + KBCMDP, KBC_PULSE0);
1.226     mycroft  2240:        delay(100000);
1.273     drochner 2241:        outb(IO_KBD + KBCMDP, KBC_PULSE0);
1.226     mycroft  2242:        delay(100000);
1.149     mycroft  2243:
                   2244:        /*
1.224     mycroft  2245:         * Try to cause a triple fault and watchdog reset by making the IDT
                   2246:         * invalid and causing a fault.
1.149     mycroft  2247:         */
1.313     perry    2248:        memset((caddr_t)idt, 0, NIDT * sizeof(idt[0]));
1.555     mycroft  2249:        setregion(&region, idt, NIDT * sizeof(idt[0]) - 1);
1.565     simonb   2250:        lidt(&region);
1.567     perry    2251:        __asm volatile("divl %0,%1" : : "q" (0), "a" (0));
1.149     mycroft  2252:
1.224     mycroft  2253: #if 0
1.149     mycroft  2254:        /*
                   2255:         * Try to cause a triple fault and watchdog reset by unmapping the
1.224     mycroft  2256:         * entire address space and doing a TLB flush.
1.149     mycroft  2257:         */
1.414     thorpej  2258:        memset((caddr_t)PTD, 0, PAGE_SIZE);
1.484     fvdl     2259:        tlbflush();
1.224     mycroft  2260: #endif
1.149     mycroft  2261:
                   2262:        for (;;);
1.45      cgd      2263: }
1.484     fvdl     2264:
1.499     jdolecek 2265: void
1.551     junyoung 2266: cpu_getmcontext(struct lwp *l, mcontext_t *mcp, unsigned int *flags)
1.508     thorpej  2267: {
                   2268:        const struct trapframe *tf = l->l_md.md_regs;
                   2269:        __greg_t *gr = mcp->__gregs;
1.519     nathanw  2270:        __greg_t ras_eip;
1.508     thorpej  2271:
                   2272:        /* Save register context. */
                   2273: #ifdef VM86
                   2274:        if (tf->tf_eflags & PSL_VM) {
                   2275:                gr[_REG_GS]  = tf->tf_vm86_gs;
                   2276:                gr[_REG_FS]  = tf->tf_vm86_fs;
                   2277:                gr[_REG_ES]  = tf->tf_vm86_es;
                   2278:                gr[_REG_DS]  = tf->tf_vm86_ds;
                   2279:                gr[_REG_EFL] = get_vflags(l);
                   2280:        } else
                   2281: #endif
                   2282:        {
                   2283:                gr[_REG_GS]  = tf->tf_gs;
                   2284:                gr[_REG_FS]  = tf->tf_fs;
                   2285:                gr[_REG_ES]  = tf->tf_es;
                   2286:                gr[_REG_DS]  = tf->tf_ds;
                   2287:                gr[_REG_EFL] = tf->tf_eflags;
                   2288:        }
                   2289:        gr[_REG_EDI]    = tf->tf_edi;
                   2290:        gr[_REG_ESI]    = tf->tf_esi;
                   2291:        gr[_REG_EBP]    = tf->tf_ebp;
                   2292:        gr[_REG_EBX]    = tf->tf_ebx;
                   2293:        gr[_REG_EDX]    = tf->tf_edx;
                   2294:        gr[_REG_ECX]    = tf->tf_ecx;
                   2295:        gr[_REG_EAX]    = tf->tf_eax;
                   2296:        gr[_REG_EIP]    = tf->tf_eip;
                   2297:        gr[_REG_CS]     = tf->tf_cs;
                   2298:        gr[_REG_ESP]    = tf->tf_esp;
                   2299:        gr[_REG_UESP]   = tf->tf_esp;
                   2300:        gr[_REG_SS]     = tf->tf_ss;
                   2301:        gr[_REG_TRAPNO] = tf->tf_trapno;
                   2302:        gr[_REG_ERR]    = tf->tf_err;
1.519     nathanw  2303:
                   2304:        if ((ras_eip = (__greg_t)ras_lookup(l->l_proc,
                   2305:            (caddr_t) gr[_REG_EIP])) != -1)
                   2306:                gr[_REG_EIP] = ras_eip;
                   2307:
1.508     thorpej  2308:        *flags |= _UC_CPU;
                   2309:
                   2310:        /* Save floating point register context, if any. */
1.548     yamt     2311:        if ((l->l_md.md_flags & MDL_USEDFPU) != 0) {
1.508     thorpej  2312: #if NNPX > 0
                   2313:                /*
                   2314:                 * If this process is the current FP owner, dump its
                   2315:                 * context to the PCB first.
                   2316:                 * XXX npxsave() also clears the FPU state; depending on the
                   2317:                 * XXX application this might be a penalty.
                   2318:                 */
                   2319:                if (l->l_addr->u_pcb.pcb_fpcpu) {
                   2320:                        npxsave_lwp(l, 1);
                   2321:                }
                   2322: #endif
                   2323:                if (i386_use_fxsave) {
                   2324:                        memcpy(&mcp->__fpregs.__fp_reg_set.__fp_xmm_state.__fp_xmm,
                   2325:                            &l->l_addr->u_pcb.pcb_savefpu.sv_xmm,
                   2326:                            sizeof (mcp->__fpregs.__fp_reg_set.__fp_xmm_state.__fp_xmm));
                   2327:                        *flags |= _UC_FXSAVE;
                   2328:                } else {
                   2329:                        memcpy(&mcp->__fpregs.__fp_reg_set.__fpchip_state.__fp_state,
                   2330:                            &l->l_addr->u_pcb.pcb_savefpu.sv_87,
                   2331:                            sizeof (mcp->__fpregs.__fp_reg_set.__fpchip_state.__fp_state));
                   2332:                }
                   2333: #if 0
                   2334:                /* Apparently nothing ever touches this. */
                   2335:                ucp->mcp.mc_fp.fp_emcsts = l->l_addr->u_pcb.pcb_saveemc;
                   2336: #endif
                   2337:                *flags |= _UC_FPU;
                   2338:        }
                   2339: }
                   2340:
                   2341: int
1.551     junyoung 2342: cpu_setmcontext(struct lwp *l, const mcontext_t *mcp, unsigned int flags)
1.508     thorpej  2343: {
                   2344:        struct trapframe *tf = l->l_md.md_regs;
1.584     pooka    2345:        const __greg_t *gr = mcp->__gregs;
1.508     thorpej  2346:
                   2347:        /* Restore register context, if any. */
                   2348:        if ((flags & _UC_CPU) != 0) {
                   2349: #ifdef VM86
1.535     drochner 2350:                if (gr[_REG_EFL] & PSL_VM) {
1.508     thorpej  2351:                        tf->tf_vm86_gs = gr[_REG_GS];
                   2352:                        tf->tf_vm86_fs = gr[_REG_FS];
                   2353:                        tf->tf_vm86_es = gr[_REG_ES];
                   2354:                        tf->tf_vm86_ds = gr[_REG_DS];
                   2355:                        set_vflags(l, gr[_REG_EFL]);
1.534     christos 2356:                        if (flags & _UC_VM) {
1.542     junyoung 2357:                                void syscall_vm86(struct trapframe *);
1.534     christos 2358:                                l->l_proc->p_md.md_syscall = syscall_vm86;
                   2359:                        }
1.508     thorpej  2360:                } else
                   2361: #endif
                   2362:                {
                   2363:                        /*
                   2364:                         * Check for security violations.  If we're returning
                   2365:                         * to protected mode, the CPU will validate the segment
                   2366:                         * registers automatically and generate a trap on
                   2367:                         * violations.  We handle the trap, rather than doing
                   2368:                         * all of the checking here.
                   2369:                         */
1.534     christos 2370:                        if (((gr[_REG_EFL] ^ tf->tf_eflags) & PSL_USERSTATIC) ||
                   2371:                            !USERMODE(gr[_REG_CS], gr[_REG_EFL])) {
                   2372:                                printf("cpu_setmcontext error: uc EFL: 0x%08x"
1.535     drochner 2373:                                    " tf EFL: 0x%08x uc CS: 0x%x\n",
1.508     thorpej  2374:                                    gr[_REG_EFL], tf->tf_eflags, gr[_REG_CS]);
                   2375:                                return (EINVAL);
                   2376:                        }
                   2377:                        tf->tf_gs = gr[_REG_GS];
                   2378:                        tf->tf_fs = gr[_REG_FS];
                   2379:                        tf->tf_es = gr[_REG_ES];
                   2380:                        tf->tf_ds = gr[_REG_DS];
                   2381:                        /* Only change the user-alterable part of eflags */
                   2382:                        tf->tf_eflags &= ~PSL_USER;
                   2383:                        tf->tf_eflags |= (gr[_REG_EFL] & PSL_USER);
                   2384:                }
                   2385:                tf->tf_edi    = gr[_REG_EDI];
                   2386:                tf->tf_esi    = gr[_REG_ESI];
                   2387:                tf->tf_ebp    = gr[_REG_EBP];
                   2388:                tf->tf_ebx    = gr[_REG_EBX];
                   2389:                tf->tf_edx    = gr[_REG_EDX];
                   2390:                tf->tf_ecx    = gr[_REG_ECX];
                   2391:                tf->tf_eax    = gr[_REG_EAX];
                   2392:                tf->tf_eip    = gr[_REG_EIP];
                   2393:                tf->tf_cs     = gr[_REG_CS];
                   2394:                tf->tf_esp    = gr[_REG_UESP];
                   2395:                tf->tf_ss     = gr[_REG_SS];
                   2396:        }
                   2397:
                   2398:        /* Restore floating point register context, if any. */
                   2399:        if ((flags & _UC_FPU) != 0) {
                   2400: #if NNPX > 0
                   2401:                /*
                   2402:                 * If we were using the FPU, forget that we were.
                   2403:                 */
                   2404:                if (l->l_addr->u_pcb.pcb_fpcpu != NULL)
                   2405:                        npxsave_lwp(l, 0);
                   2406: #endif
                   2407:                if (flags & _UC_FXSAVE) {
                   2408:                        if (i386_use_fxsave) {
                   2409:                                memcpy(
                   2410:                                        &l->l_addr->u_pcb.pcb_savefpu.sv_xmm,
                   2411:                                        &mcp->__fpregs.__fp_reg_set.__fp_xmm_state.__fp_xmm,
                   2412:                                        sizeof (&l->l_addr->u_pcb.pcb_savefpu.sv_xmm));
                   2413:                        } else {
                   2414:                                /* This is a weird corner case */
                   2415:                                process_xmm_to_s87((struct savexmm *)
                   2416:                                    &mcp->__fpregs.__fp_reg_set.__fp_xmm_state.__fp_xmm,
                   2417:                                    &l->l_addr->u_pcb.pcb_savefpu.sv_87);
                   2418:                        }
                   2419:                } else {
                   2420:                        if (i386_use_fxsave) {
                   2421:                                process_s87_to_xmm((struct save87 *)
                   2422:                                    &mcp->__fpregs.__fp_reg_set.__fpchip_state.__fp_state,
                   2423:                                    &l->l_addr->u_pcb.pcb_savefpu.sv_xmm);
                   2424:                        } else {
                   2425:                                memcpy(&l->l_addr->u_pcb.pcb_savefpu.sv_87,
                   2426:                                    &mcp->__fpregs.__fp_reg_set.__fpchip_state.__fp_state,
                   2427:                                    sizeof (l->l_addr->u_pcb.pcb_savefpu.sv_87));
                   2428:                        }
                   2429:                }
                   2430:                /* If not set already. */
1.548     yamt     2431:                l->l_md.md_flags |= MDL_USEDFPU;
1.508     thorpej  2432: #if 0
                   2433:                /* Apparently unused. */
                   2434:                l->l_addr->u_pcb.pcb_saveemc = mcp->mc_fp.fp_emcsts;
                   2435: #endif
                   2436:        }
1.534     christos 2437:        if (flags & _UC_SETSTACK)
                   2438:                l->l_proc->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK;
                   2439:        if (flags & _UC_CLRSTACK)
                   2440:                l->l_proc->p_sigctx.ps_sigstk.ss_flags &= ~SS_ONSTACK;
1.508     thorpej  2441:        return (0);
                   2442: }
                   2443:
                   2444: void
1.499     jdolecek 2445: cpu_initclocks()
1.484     fvdl     2446: {
1.574     kardel   2447:
1.484     fvdl     2448:        (*initclock_func)();
                   2449: }
                   2450:
                   2451: #ifdef MULTIPROCESSOR
1.499     jdolecek 2452: void
                   2453: need_resched(struct cpu_info *ci)
1.484     fvdl     2454: {
1.546     yamt     2455:
                   2456:        if (ci->ci_want_resched)
                   2457:                return;
                   2458:
1.484     fvdl     2459:        ci->ci_want_resched = 1;
1.508     thorpej  2460:        if ((ci)->ci_curlwp != NULL)
                   2461:                aston((ci)->ci_curlwp->l_proc);
1.546     yamt     2462:        else if (ci != curcpu())
                   2463:                x86_send_ipi(ci, 0);
1.484     fvdl     2464: }
                   2465: #endif
                   2466:
                   2467: /*
                   2468:  * Allocate an IDT vector slot within the given range.
                   2469:  * XXX needs locking to avoid MP allocation races.
                   2470:  */
                   2471:
                   2472: int
1.551     junyoung 2473: idt_vec_alloc(int low, int high)
1.484     fvdl     2474: {
                   2475:        int vec;
                   2476:
1.498     fvdl     2477:        simple_lock(&idt_lock);
                   2478:        for (vec = low; vec <= high; vec++) {
                   2479:                if (idt_allocmap[vec] == 0) {
                   2480:                        idt_allocmap[vec] = 1;
                   2481:                        simple_unlock(&idt_lock);
1.484     fvdl     2482:                        return vec;
1.498     fvdl     2483:                }
                   2484:        }
                   2485:        simple_unlock(&idt_lock);
1.484     fvdl     2486:        return 0;
                   2487: }
                   2488:
1.498     fvdl     2489: void
1.551     junyoung 2490: idt_vec_set(int vec, void (*function)(void))
1.484     fvdl     2491: {
1.498     fvdl     2492:        /*
                   2493:         * Vector should be allocated, so no locking needed.
                   2494:         */
                   2495:        KASSERT(idt_allocmap[vec] == 1);
1.516     fvdl     2496:        setgate(&idt[vec], function, 0, SDT_SYS386IGT, SEL_KPL,
1.489     fvdl     2497:            GSEL(GCODE_SEL, SEL_KPL));
1.484     fvdl     2498: }
                   2499:
                   2500: void
1.551     junyoung 2501: idt_vec_free(int vec)
1.484     fvdl     2502: {
1.498     fvdl     2503:        simple_lock(&idt_lock);
1.516     fvdl     2504:        unsetgate(&idt[vec]);
1.498     fvdl     2505:        idt_allocmap[vec] = 0;
                   2506:        simple_unlock(&idt_lock);
1.507     jdolecek 2507: }
                   2508:
                   2509: /*
                   2510:  * Number of processes is limited by number of available GDT slots.
                   2511:  */
                   2512: int
                   2513: cpu_maxproc(void)
                   2514: {
                   2515: #ifdef USER_LDT
                   2516:        return ((MAXGDTSIZ - NGDT) / 2);
                   2517: #else
                   2518:        return (MAXGDTSIZ - NGDT);
                   2519: #endif
1.484     fvdl     2520: }

CVSweb <webmaster@jp.NetBSD.org>