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