Annotation of src/sys/arch/i386/i386/machdep.c, Revision 1.425
1.425 ! jdolecek 1: /* $NetBSD: machdep.c,v 1.424 2000/12/21 05:20:24 enami Exp $ */
1.231 thorpej 2:
3: /*-
1.401 thorpej 4: * Copyright (c) 1996, 1997, 1998, 2000 The NetBSD Foundation, Inc.
1.231 thorpej 5: * All rights reserved.
6: *
7: * This code is derived from software contributed to The NetBSD Foundation
1.316 mycroft 8: * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace
9: * Simulation Facility, NASA Ames Research Center.
1.231 thorpej 10: *
11: * Redistribution and use in source and binary forms, with or without
12: * modification, are permitted provided that the following conditions
13: * are met:
14: * 1. Redistributions of source code must retain the above copyright
15: * notice, this list of conditions and the following disclaimer.
16: * 2. Redistributions in binary form must reproduce the above copyright
17: * notice, this list of conditions and the following disclaimer in the
18: * documentation and/or other materials provided with the distribution.
19: * 3. All advertising materials mentioning features or use of this software
20: * must display the following acknowledgement:
21: * This product includes software developed by the NetBSD
22: * Foundation, Inc. and its contributors.
23: * 4. Neither the name of The NetBSD Foundation nor the names of its
24: * contributors may be used to endorse or promote products derived
25: * from this software without specific prior written permission.
26: *
27: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37: * POSSIBILITY OF SUCH DAMAGE.
38: */
1.125 cgd 39:
1.1 cgd 40: /*-
41: * Copyright (c) 1982, 1987, 1990 The Regents of the University of California.
42: * All rights reserved.
43: *
44: * This code is derived from software contributed to Berkeley by
45: * William Jolitz.
46: *
47: * Redistribution and use in source and binary forms, with or without
48: * modification, are permitted provided that the following conditions
49: * are met:
50: * 1. Redistributions of source code must retain the above copyright
51: * notice, this list of conditions and the following disclaimer.
52: * 2. Redistributions in binary form must reproduce the above copyright
53: * notice, this list of conditions and the following disclaimer in the
54: * documentation and/or other materials provided with the distribution.
55: * 3. All advertising materials mentioning features or use of this software
56: * must display the following acknowledgement:
57: * This product includes software developed by the University of
58: * California, Berkeley and its contributors.
59: * 4. Neither the name of the University nor the names of its contributors
60: * may be used to endorse or promote products derived from this software
61: * without specific prior written permission.
62: *
63: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
64: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
65: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
66: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
67: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
68: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
69: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
70: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
71: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
72: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
73: * SUCH DAMAGE.
74: *
1.125 cgd 75: * @(#)machdep.c 7.4 (Berkeley) 6/3/91
1.1 cgd 76: */
1.271 thorpej 77:
78: #include "opt_cputype.h"
1.309 jonathan 79: #include "opt_ddb.h"
1.377 ws 80: #include "opt_ipkdb.h"
1.272 thorpej 81: #include "opt_vm86.h"
1.274 thorpej 82: #include "opt_user_ldt.h"
1.310 jonathan 83: #include "opt_compat_netbsd.h"
1.327 bouyer 84: #include "opt_cpureset_delay.h"
1.333 christos 85: #include "opt_compat_svr4.h"
1.1 cgd 86:
1.59 mycroft 87: #include <sys/param.h>
88: #include <sys/systm.h>
89: #include <sys/signalvar.h>
90: #include <sys/kernel.h>
91: #include <sys/map.h>
92: #include <sys/proc.h>
93: #include <sys/user.h>
94: #include <sys/exec.h>
95: #include <sys/buf.h>
96: #include <sys/reboot.h>
97: #include <sys/conf.h>
98: #include <sys/file.h>
99: #include <sys/malloc.h>
100: #include <sys/mbuf.h>
101: #include <sys/msgbuf.h>
102: #include <sys/mount.h>
103: #include <sys/vnode.h>
1.204 thorpej 104: #include <sys/extent.h>
1.123 cgd 105: #include <sys/syscallargs.h>
1.291 thorpej 106: #include <sys/core.h>
107: #include <sys/kcore.h>
108: #include <machine/kcore.h>
1.57 cgd 109:
1.377 ws 110: #ifdef IPKDB
111: #include <ipkdb/ipkdb.h>
112: #endif
113:
1.235 thorpej 114: #ifdef KGDB
115: #include <sys/kgdb.h>
116: #endif
117:
1.104 cgd 118: #include <dev/cons.h>
1.390 mrg 119:
120: #include <uvm/uvm_extern.h>
1.393 fvdl 121: #include <uvm/uvm_page.h>
1.284 mrg 122:
1.200 christos 123: #include <sys/sysctl.h>
124:
1.59 mycroft 125: #include <machine/cpu.h>
126: #include <machine/cpufunc.h>
1.178 mycroft 127: #include <machine/gdt.h>
1.149 mycroft 128: #include <machine/pio.h>
1.59 mycroft 129: #include <machine/psl.h>
130: #include <machine/reg.h>
131: #include <machine/specialreg.h>
1.255 drochner 132: #include <machine/bootinfo.h>
1.43 brezak 133:
1.146 cgd 134: #include <dev/isa/isareg.h>
1.372 drochner 135: #include <machine/isa_machdep.h>
1.164 cgd 136: #include <dev/ic/i8042reg.h>
1.43 brezak 137:
1.200 christos 138: #ifdef DDB
139: #include <machine/db_machdep.h>
140: #include <ddb/db_extern.h>
141: #endif
142:
1.184 mycroft 143: #ifdef VM86
144: #include <machine/vm86.h>
145: #endif
146:
1.207 jtk 147: #include "apm.h"
1.258 jtk 148: #include "bioscall.h"
1.207 jtk 149:
1.259 jtk 150: #if NBIOSCALL > 0
151: #include <machine/bioscall.h>
152: #endif
153:
1.207 jtk 154: #if NAPM > 0
155: #include <machine/apmvar.h>
1.258 jtk 156: #endif
157:
1.59 mycroft 158: #include "isa.h"
1.231 thorpej 159: #include "isadma.h"
1.59 mycroft 160: #include "npx.h"
1.161 mycroft 161: #if NNPX > 0
162: extern struct proc *npxproc;
163: #endif
1.2 cgd 164:
1.384 jdolecek 165: #include "mca.h"
166: #if NMCA > 0
167: #include <machine/mca_machdep.h> /* for mca_busprobe() */
168: #endif
169:
1.104 cgd 170: /* the following is used externally (sysctl_hw) */
171: char machine[] = "i386"; /* cpu "architecture" */
1.232 veego 172: char machine_arch[] = "i386"; /* machine == machine_arch */
1.104 cgd 173:
1.402 explorer 174: u_int cpu_serial[3];
175:
1.255 drochner 176: char bootinfo[BOOTINFO_MAXSIZE];
1.386 thorpej 177:
178: /* Our exported CPU info; we have only one right now. */
179: struct cpu_info cpu_info_store;
1.255 drochner 180:
1.343 fvdl 181: struct bi_devmatch *i386_alldisks = NULL;
182: int i386_ndisks = 0;
1.342 fvdl 183:
1.328 bouyer 184: #ifdef CPURESET_DELAY
185: int cpureset_delay = CPURESET_DELAY;
186: #else
187: int cpureset_delay = 2000; /* default to 2s */
188: #endif
189:
1.1 cgd 190:
1.59 mycroft 191: int physmem;
1.163 cgd 192: int dumpmem_low;
193: int dumpmem_high;
1.59 mycroft 194: int boothowto;
195: int cpu_class;
1.366 fvdl 196: int i386_fpu_present = 0;
1.59 mycroft 197:
1.379 jdolecek 198: #define CPUID2MODEL(cpuid) (((cpuid) >> 4) & 15)
199:
1.314 thorpej 200: vaddr_t msgbuf_vaddr;
201: paddr_t msgbuf_paddr;
202:
203: vaddr_t idt_vaddr;
204: paddr_t idt_paddr;
205:
1.264 mycroft 206: #ifdef I586_CPU
1.314 thorpej 207: vaddr_t pentium_idt_vaddr;
1.264 mycroft 208: #endif
1.59 mycroft 209:
1.284 mrg 210: vm_map_t exec_map = NULL;
211: vm_map_t mb_map = NULL;
212: vm_map_t phys_map = NULL;
1.48 brezak 213:
1.314 thorpej 214: extern paddr_t avail_start, avail_end;
1.1 cgd 215:
1.204 thorpej 216: /*
1.291 thorpej 217: * Size of memory segments, before any memory is stolen.
218: */
219: phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX];
220: int mem_cluster_cnt;
221:
1.408 thorpej 222: /*
223: * The number of CPU cycles in one second.
224: */
225: u_int64_t cpu_tsc_freq;
226:
1.291 thorpej 227: int cpu_dump __P((void));
228: int cpu_dumpsize __P((void));
229: u_long cpu_dump_mempagecnt __P((void));
1.200 christos 230: void dumpsys __P((void));
231: void identifycpu __P((void));
1.314 thorpej 232: void init386 __P((paddr_t));
1.255 drochner 233:
1.397 thorpej 234: const struct i386_cache_info *cpu_itlb_info, *cpu_dtlb_info, *cpu_icache_info,
235: *cpu_dcache_info, *cpu_l2cache_info;
236:
237: const struct i386_cache_info {
238: u_int8_t cai_desc;
239: const struct i386_cache_info **cai_var;
240: const char *cai_string;
241: u_int cai_totalsize;
242: u_int cai_linesize;
243: } i386_cache_info[] = {
244: { 0x01, &cpu_itlb_info, "32 4K entries 4-way",
245: 32, 4 * 1024 },
246: { 0x02, &cpu_itlb_info, "2 4M entries",
247: 2, 4 * 1024 * 1024 },
248: { 0x03, &cpu_dtlb_info, "64 4K entries 4-way",
249: 64, 4 * 1024 },
250: { 0x04, &cpu_dtlb_info, "8 4M entries 4-way",
251: 8, 4 * 1024 * 1024 },
252: { 0x06, &cpu_icache_info, "8K 32b/line 4-way",
253: 8 * 1024, 32 },
254: { 0x08, &cpu_icache_info, "16K 32b/line 4-way",
255: 16 * 1024, 32 },
256: { 0x0a, &cpu_dcache_info, "8K 32b/line 2-way",
257: 8 * 1024, 32 },
258: { 0x0c, &cpu_dcache_info, "16K 32b/line 2/4-way",
259: 16 * 1024, 32 },
260: { 0x40, &cpu_l2cache_info, "not present",
261: 0, 0 },
262: { 0x41, &cpu_l2cache_info, "128K 32b/line 4-way",
263: 128 * 1024, 32 },
264: { 0x42, &cpu_l2cache_info, "256K 32b/line 4-way",
265: 256 * 1024, 32 },
266: { 0x43, &cpu_l2cache_info, "512K 32b/line 4-way",
267: 512 * 1024, 32 },
268: { 0x44, &cpu_l2cache_info, "1M 32b/line 4-way",
269: 1 * 1024 * 1024, 32 },
270: { 0x45, &cpu_l2cache_info, "2M 32b/line 4-way",
1.400 enami 271: 2 * 1024 * 1024, 32 },
272: { 0x82, &cpu_l2cache_info, "256K 32b/line 8-way",
273: 256 * 1024, 32 },
274: { 0x84, &cpu_l2cache_info, "1M 32b/line 8-way",
275: 1 * 1024 * 1024, 32 },
276: { 0x85, &cpu_l2cache_info, "2M 32b/line 8-way",
1.397 thorpej 277: 2 * 1024 * 1024, 32 },
278:
279: { 0, NULL, NULL, 0, 0 },
280: };
281:
282: const struct i386_cache_info *i386_cache_info_lookup __P((u_int8_t));
283:
1.417 jdolecek 284: /*
285: * Map Brand ID from cpuid instruction to brand name.
286: * Source: Intel Processor Identification and the CPUID Instruction, AP-485
287: */
288: const char * const i386_p3_brand[] = {
1.419 jdolecek 289: "", /* Unsupported */
1.417 jdolecek 290: "Celeron", /* Intel (R) Celeron (TM) processor */
291: "", /* Intel (R) Pentium (R) III processor */
292: "Xeon", /* Intel (R) Pentium (R) III Xeon (TM) processor */
293: };
294:
1.200 christos 295: #ifdef COMPAT_NOMID
296: static int exec_nomid __P((struct proc *, struct exec_package *));
297: #endif
1.59 mycroft 298:
1.267 bouyer 299: void cyrix6x86_cpu_setup __P((void));
1.379 jdolecek 300: void winchip_cpu_setup __P((void));
1.267 bouyer 301:
302: static __inline u_char
303: cyrix_read_reg(u_char reg)
304: {
305: outb(0x22, reg);
306: return inb(0x23);
307: }
308:
309: static __inline void
310: cyrix_write_reg(u_char reg, u_char data)
311: {
312: outb(0x22, reg);
313: outb(0x23, data);
314: }
315:
1.59 mycroft 316: /*
317: * Machine-dependent startup code
318: */
1.32 andrew 319: void
1.1 cgd 320: cpu_startup()
321: {
1.59 mycroft 322: caddr_t v;
1.349 thorpej 323: int sz, x;
1.314 thorpej 324: vaddr_t minaddr, maxaddr;
325: vsize_t size;
1.424 enami 326: char buf[160]; /* about 2 line */
1.354 lukem 327: char pbuf[9];
1.258 jtk 328: #if NBIOSCALL > 0
1.207 jtk 329: extern int biostramp_image_size;
330: extern u_char biostramp_image[];
331: #endif
1.1 cgd 332:
1.284 mrg 333: /*
334: * Initialize error message buffer (et end of core).
335: */
1.354 lukem 336: msgbuf_vaddr = uvm_km_valloc(kernel_map, i386_round_page(MSGBUFSIZE));
1.385 thorpej 337: if (msgbuf_vaddr == 0)
1.284 mrg 338: panic("failed to valloc msgbuf_vaddr");
1.359 thorpej 339:
1.284 mrg 340: /* msgbuf_paddr was init'd in pmap */
341: for (x = 0; x < btoc(MSGBUFSIZE); x++)
1.414 thorpej 342: pmap_kenter_pa((vaddr_t)msgbuf_vaddr + x * PAGE_SIZE,
343: msgbuf_paddr + x * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE);
1.359 thorpej 344:
1.284 mrg 345: initmsgbuf((caddr_t)msgbuf_vaddr, round_page(MSGBUFSIZE));
346:
1.392 sommerfe 347: printf("%s", version);
1.393 fvdl 348:
1.408 thorpej 349: printf("cpu0: %s", cpu_model);
350: if (cpu_tsc_freq != 0)
351: printf(", %qd.%02qd MHz", (cpu_tsc_freq + 4999) / 1000000,
352: ((cpu_tsc_freq + 4999) / 10000) % 100);
353: printf("\n");
1.397 thorpej 354: if (cpu_icache_info != NULL || cpu_dcache_info != NULL) {
355: printf("cpu0:");
356: if (cpu_icache_info)
357: printf(" I-cache %s", cpu_icache_info->cai_string);
358: if (cpu_dcache_info)
359: printf("%sD-cache %s",
360: (cpu_icache_info != NULL) ? ", " : " ",
361: cpu_dcache_info->cai_string);
362: printf("\n");
363: }
364: if (cpu_l2cache_info)
365: printf("cpu0: L2 cache %s\n", cpu_l2cache_info->cai_string);
1.424 enami 366: if ((cpu_feature & CPUID_MASK1) != 0) {
367: bitmask_snprintf(cpu_feature, CPUID_FLAGS1,
368: buf, sizeof(buf));
369: printf("cpu0: features %s\n", buf);
370: }
371: if ((cpu_feature & CPUID_MASK2) != 0) {
372: bitmask_snprintf(cpu_feature, CPUID_FLAGS2,
373: buf, sizeof(buf));
374: printf("cpu0: features %s\n", buf);
1.395 thorpej 375: }
1.267 bouyer 376:
1.420 jdolecek 377: if (cpuid_level >= 3 && ((cpu_feature & CPUID_PN) != 0)) {
378: printf("cpu0: serial number %04X-%04X-%04X-%04X-%04X-%04X\n",
379: cpu_serial[0] / 65536, cpu_serial[0] % 65536,
380: cpu_serial[1] / 65536, cpu_serial[1] % 65536,
381: cpu_serial[2] / 65536, cpu_serial[2] % 65536);
382: }
1.402 explorer 383:
1.382 mycroft 384: format_bytes(pbuf, sizeof(pbuf), ptoa(physmem));
1.354 lukem 385: printf("total memory = %s\n", pbuf);
1.1 cgd 386:
387: /*
1.59 mycroft 388: * Find out how much space we need, allocate it,
389: * and then give everything true virtual addresses.
1.1 cgd 390: */
1.354 lukem 391: sz = (int)allocsys(NULL, NULL);
1.284 mrg 392: if ((v = (caddr_t)uvm_km_zalloc(kernel_map, round_page(sz))) == 0)
393: panic("startup: no room for tables");
1.354 lukem 394: if (allocsys(v, NULL) - v != sz)
1.1 cgd 395: panic("startup: table size inconsistency");
1.50 cgd 396:
1.36 cgd 397: /*
1.284 mrg 398: * Allocate virtual address space for the buffers. The area
399: * is not managed by the VM system.
1.36 cgd 400: */
401: size = MAXBSIZE * nbuf;
1.314 thorpej 402: if (uvm_map(kernel_map, (vaddr_t *) &buffers, round_page(size),
1.398 thorpej 403: NULL, UVM_UNKNOWN_OFFSET, 0,
1.284 mrg 404: UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE,
405: UVM_ADV_NORMAL, 0)) != KERN_SUCCESS)
406: panic("cpu_startup: cannot allocate VM for buffers");
1.314 thorpej 407: minaddr = (vaddr_t)buffers;
1.54 cgd 408: if ((bufpages / nbuf) >= btoc(MAXBSIZE)) {
409: /* don't want to alloc more physical mem than needed */
410: bufpages = btoc(MAXBSIZE) * nbuf;
411: }
1.36 cgd 412:
1.268 thorpej 413: /*
414: * XXX We defer allocation of physical pages for buffers until
415: * XXX after autoconfiguration has run. We must do this because
416: * XXX on system with large amounts of memory or with large
417: * XXX user-configured buffer caches, the buffer cache will eat
418: * XXX up all of the lower 16M of RAM. This prevents ISA DMA
419: * XXX maps from allocating bounce pages.
420: *
421: * XXX Note that nothing can use buffer cache buffers until after
422: * XXX autoconfiguration completes!!
423: *
424: * XXX This is a hack, and needs to be replaced with a better
425: * XXX solution! --thorpej@netbsd.org, December 6, 1997
426: */
1.41 cgd 427:
1.1 cgd 428: /*
1.36 cgd 429: * Allocate a submap for exec arguments. This map effectively
430: * limits the number of processes exec'ing at any time.
1.1 cgd 431: */
1.284 mrg 432: exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
1.358 thorpej 433: 16*NCARGS, VM_MAP_PAGEABLE, FALSE, NULL);
1.59 mycroft 434:
1.1 cgd 435: /*
436: * Allocate a submap for physio
437: */
1.284 mrg 438: phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
1.358 thorpej 439: VM_PHYS_SIZE, 0, FALSE, NULL);
1.1 cgd 440:
441: /*
1.229 thorpej 442: * Finally, allocate mbuf cluster submap.
1.1 cgd 443: */
1.334 thorpej 444: mb_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
1.358 thorpej 445: nmbclusters * mclbytes, VM_MAP_INTRSAFE, FALSE, NULL);
1.1 cgd 446:
1.284 mrg 447: /*
448: * XXX Buffer cache pages haven't yet been allocated, so
449: * XXX we need to account for those pages when printing
450: * XXX the amount of free memory.
451: */
1.354 lukem 452: format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free - bufpages));
453: printf("avail memory = %s\n", pbuf);
1.414 thorpej 454: format_bytes(pbuf, sizeof(pbuf), bufpages * PAGE_SIZE);
1.354 lukem 455: printf("using %d buffers containing %s of memory\n", nbuf, pbuf);
1.1 cgd 456:
1.258 jtk 457: #if NBIOSCALL > 0
1.207 jtk 458: /*
459: * this should be caught at kernel build time, but put it here
460: * in case someone tries to fake it out...
461: */
462: #ifdef DIAGNOSTIC
1.414 thorpej 463: if (biostramp_image_size > PAGE_SIZE)
1.207 jtk 464: panic("biostramp_image_size too big: %x vs. %x\n",
1.414 thorpej 465: biostramp_image_size, PAGE_SIZE);
1.207 jtk 466: #endif
1.314 thorpej 467: pmap_kenter_pa((vaddr_t)BIOSTRAMP_BASE, /* virtual */
468: (paddr_t)BIOSTRAMP_BASE, /* physical */
469: VM_PROT_ALL); /* protection */
1.313 perry 470: memcpy((caddr_t)BIOSTRAMP_BASE, biostramp_image, biostramp_image_size);
1.207 jtk 471: #ifdef DEBUG
1.258 jtk 472: printf("biostramp installed @ %x\n", BIOSTRAMP_BASE);
1.207 jtk 473: #endif
474: #endif
1.263 mycroft 475:
1.375 drochner 476: /* Safe for i/o port / memory space allocation to use malloc now. */
477: i386_bus_space_mallocok();
1.349 thorpej 478: }
479:
480: /*
481: * Set up proc0's TSS and LDT.
482: */
483: void
484: i386_proc0_tss_ldt_init()
485: {
486: struct pcb *pcb;
487: int x;
1.268 thorpej 488:
1.326 thorpej 489: gdt_init();
490: curpcb = pcb = &proc0.p_addr->u_pcb;
491: pcb->pcb_flags = 0;
492: pcb->pcb_tss.tss_ioopt =
493: ((caddr_t)pcb->pcb_iomap - (caddr_t)&pcb->pcb_tss) << 16;
494: for (x = 0; x < sizeof(pcb->pcb_iomap) / 4; x++)
495: pcb->pcb_iomap[x] = 0xffffffff;
496:
1.394 thorpej 497: pcb->pcb_ldt_sel = pmap_kernel()->pm_ldt_sel = GSEL(GLDT_SEL, SEL_KPL);
1.326 thorpej 498: pcb->pcb_cr0 = rcr0();
499: pcb->pcb_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL);
500: pcb->pcb_tss.tss_esp0 = (int)proc0.p_addr + USPACE - 16;
1.394 thorpej 501: tss_alloc(&proc0);
1.326 thorpej 502:
1.394 thorpej 503: ltr(proc0.p_md.md_tss_sel);
1.326 thorpej 504: lldt(pcb->pcb_ldt_sel);
505:
506: proc0.p_md.md_regs = (struct trapframe *)pcb->pcb_tss.tss_esp0 - 1;
507: }
508:
509: /*
510: * XXX Finish up the deferred buffer cache allocation and initialization.
511: */
512: void
513: i386_bufinit()
514: {
515: int i, base, residual;
516:
1.268 thorpej 517: base = bufpages / nbuf;
518: residual = bufpages % nbuf;
519: for (i = 0; i < nbuf; i++) {
1.314 thorpej 520: vsize_t curbufsize;
521: vaddr_t curbuf;
1.284 mrg 522: struct vm_page *pg;
523:
524: /*
525: * Each buffer has MAXBSIZE bytes of VM space allocated. Of
526: * that MAXBSIZE space, we allocate and map (base+1) pages
527: * for the first "residual" buffers, and then we allocate
528: * "base" pages for the rest.
529: */
1.314 thorpej 530: curbuf = (vaddr_t) buffers + (i * MAXBSIZE);
1.414 thorpej 531: curbufsize = PAGE_SIZE * ((i < residual) ? (base+1) : base);
1.284 mrg 532:
533: while (curbufsize) {
1.311 thorpej 534: /*
535: * Attempt to allocate buffers from the first
536: * 16M of RAM to avoid bouncing file system
537: * transfers.
538: */
1.350 chs 539: pg = uvm_pagealloc_strat(NULL, 0, NULL, 0,
1.311 thorpej 540: UVM_PGA_STRAT_FALLBACK, VM_FREELIST_FIRST16);
1.284 mrg 541: if (pg == NULL)
542: panic("cpu_startup: not enough memory for "
543: "buffer cache");
544: pmap_kenter_pgs(curbuf, &pg, 1);
545: curbuf += PAGE_SIZE;
546: curbufsize -= PAGE_SIZE;
547: }
1.268 thorpej 548: }
549:
550: /*
551: * Set up buffers, so they can be used to read disk labels.
552: */
553: bufinit();
1.16 cgd 554: }
555:
1.397 thorpej 556: const struct i386_cache_info *
557: i386_cache_info_lookup(u_int8_t desc)
558: {
559: const struct i386_cache_info *cai;
560:
561: for (cai = i386_cache_info; cai->cai_string != NULL; cai++) {
562: if (cai->cai_desc == desc)
563: return (cai);
564: }
565:
566: return (NULL);
567: }
568:
1.104 cgd 569: /*
570: * Info for CTL_HW
571: */
572: char cpu_model[120];
573:
1.216 fvdl 574: /*
575: * Note: these are just the ones that may not have a cpuid instruction.
576: * We deal with the rest in a different way.
577: */
1.418 jdolecek 578: const struct cpu_nocpuid_nameclass i386_nocpuid_cpus[] = {
1.267 bouyer 579: { CPUVENDOR_INTEL, "Intel", "386SX", CPUCLASS_386,
580: NULL}, /* CPU_386SX */
581: { CPUVENDOR_INTEL, "Intel", "386DX", CPUCLASS_386,
582: NULL}, /* CPU_386 */
583: { CPUVENDOR_INTEL, "Intel", "486SX", CPUCLASS_486,
584: NULL}, /* CPU_486SX */
585: { CPUVENDOR_INTEL, "Intel", "486DX", CPUCLASS_486,
586: NULL}, /* CPU_486 */
587: { CPUVENDOR_CYRIX, "Cyrix", "486DLC", CPUCLASS_486,
588: NULL}, /* CPU_486DLC */
589: { CPUVENDOR_CYRIX, "Cyrix", "6x86", CPUCLASS_486,
590: cyrix6x86_cpu_setup}, /* CPU_6x86 */
591: { CPUVENDOR_NEXGEN,"NexGen","586", CPUCLASS_386,
592: NULL}, /* CPU_NX586 */
1.216 fvdl 593: };
594:
595: const char *classnames[] = {
596: "386",
597: "486",
598: "586",
599: "686"
600: };
601:
602: const char *modifiers[] = {
603: "",
604: "OverDrive ",
605: "Dual ",
606: ""
1.18 cgd 607: };
608:
1.418 jdolecek 609: const struct cpu_cpuid_nameclass i386_cpuid_cpus[] = {
1.216 fvdl 610: {
611: "GenuineIntel",
612: CPUVENDOR_INTEL,
613: "Intel",
614: /* Family 4 */
615: { {
616: CPUCLASS_486,
617: {
1.219 perry 618: "486DX", "486DX", "486SX", "486DX2", "486SL",
1.216 fvdl 619: "486SX2", 0, "486DX2 W/B Enhanced",
620: "486DX4", 0, 0, 0, 0, 0, 0, 0,
621: "486" /* Default */
1.267 bouyer 622: },
623: NULL
1.216 fvdl 624: },
625: /* Family 5 */
626: {
627: CPUCLASS_586,
628: {
1.361 tron 629: "Pentium (P5 A-step)", "Pentium (P5)",
630: "Pentium (P54C)", "Pentium (P24T)",
631: "Pentium/MMX", "Pentium", 0,
632: "Pentium (P54C)", "Pentium/MMX (Tillamook)",
633: 0, 0, 0, 0, 0, 0, 0,
1.216 fvdl 634: "Pentium" /* Default */
1.267 bouyer 635: },
636: NULL
1.216 fvdl 637: },
638: /* Family 6 */
639: {
640: CPUCLASS_686,
641: {
1.361 tron 642: "Pentium Pro (A-step)", "Pentium Pro", 0,
643: "Pentium II (Klamath)", "Pentium Pro",
1.416 jdolecek 644: "Pentium II/Celeron (Deschutes)",
645: "Celeron (Mendocino)",
646: "Pentium III (Katmai)",
647: "Pentium III (Coppermine)",
1.419 jdolecek 648: 0, "Pentium III (Cascades)", 0, 0,
1.416 jdolecek 649: 0, 0,
1.340 fvdl 650: "Pentium Pro, II or III" /* Default */
1.267 bouyer 651: },
652: NULL
1.406 fvdl 653: },
654: /* Family > 6 */
655: {
656: CPUCLASS_686,
657: {
658: 0, 0, 0, 0, 0, 0, 0,
659: 0, 0, 0, 0, 0, 0, 0, 0, 0,
660: "Pentium 4" /* Default */
661: },
662: NULL
1.216 fvdl 663: } }
664: },
665: {
666: "AuthenticAMD",
667: CPUVENDOR_AMD,
668: "AMD",
669: /* Family 4 */
670: { {
671: CPUCLASS_486,
672: {
673: 0, 0, 0, "Am486DX2 W/T",
674: 0, 0, 0, "Am486DX2 W/B",
675: "Am486DX4 W/T or Am5x86 W/T 150",
676: "Am486DX4 W/B or Am5x86 W/B 150", 0, 0,
677: 0, 0, "Am5x86 W/T 133/160",
678: "Am5x86 W/B 133/160",
679: "Am486 or Am5x86" /* Default */
680: },
1.267 bouyer 681: NULL
1.216 fvdl 682: },
683: /* Family 5 */
684: {
685: CPUCLASS_586,
686: {
1.241 fvdl 687: "K5", "K5", "K5", "K5", 0, 0, "K6",
1.416 jdolecek 688: "K6", "K6-2", "K6-III", 0, 0, 0,
689: "K6-2+/III+", 0, 0,
1.267 bouyer 690: "K5 or K6" /* Default */
1.216 fvdl 691: },
1.267 bouyer 692: NULL
1.216 fvdl 693: },
1.363 fvdl 694: /* Family 6 */
1.216 fvdl 695: {
696: CPUCLASS_686,
697: {
1.416 jdolecek 698: 0, "Athlon Model 1", "Athlon Model 2",
699: "Duron", "Athlon Model 4 (Thunderbird)",
700: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1.362 fvdl 701: "K7 (Athlon)" /* Default */
1.216 fvdl 702: },
1.267 bouyer 703: NULL
1.406 fvdl 704: },
705: /* Family > 6 */
706: {
707: CPUCLASS_686,
708: {
709: 0, 0, 0, 0, 0, 0, 0,
710: 0, 0, 0, 0, 0, 0, 0, 0, 0,
711: "Unknown K7 (Athlon)" /* Default */
712: },
713: NULL
1.216 fvdl 714: } }
715: },
716: {
717: "CyrixInstead",
718: CPUVENDOR_CYRIX,
719: "Cyrix",
720: /* Family 4 */
721: { {
722: CPUCLASS_486,
723: {
1.376 minoura 724: 0, 0, 0,
725: "MediaGX",
726: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1.216 fvdl 727: "486" /* Default */
728: },
1.267 bouyer 729: NULL
1.216 fvdl 730: },
731: /* Family 5 */
732: {
733: CPUCLASS_586,
734: {
1.376 minoura 735: 0, 0, "6x86", 0,
736: "MMX-enhanced MediaGX (GXm)", /* or Geode? */
737: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1.216 fvdl 738: "6x86" /* Default */
1.267 bouyer 739: },
740: cyrix6x86_cpu_setup
1.216 fvdl 741: },
1.278 bouyer 742: /* Family 6 */
1.216 fvdl 743: {
744: CPUCLASS_686,
745: {
1.278 bouyer 746: "6x86MX", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
747: "6x86MX" /* Default */
1.329 bad 748: },
1.368 drochner 749: cyrix6x86_cpu_setup
1.406 fvdl 750: },
751: /* Family > 6 */
752: {
753: CPUCLASS_686,
754: {
755: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
756: "Unknown 6x86MX" /* Default */
757: },
758: NULL
1.329 bad 759: } }
760: },
761: {
762: "CentaurHauls",
763: CPUVENDOR_IDT,
764: "IDT",
765: /* Family 4, IDT never had any of these */
766: { {
767: CPUCLASS_486,
768: {
769: 0, 0, 0, 0, 0, 0, 0,
770: 0, 0, 0, 0, 0, 0, 0, 0, 0,
771: "486 compatible" /* Default */
772: },
773: NULL
774: },
775: /* Family 5 */
776: {
777: CPUCLASS_586,
778: {
779: 0, 0, 0, 0, "WinChip C6", 0, 0, 0,
1.379 jdolecek 780: "WinChip 2", "WinChip 3", 0, 0, 0, 0, 0, 0,
1.329 bad 781: "WinChip" /* Default */
782: },
1.379 jdolecek 783: winchip_cpu_setup
1.329 bad 784: },
785: /* Family 6, not yet available from IDT */
1.406 fvdl 786: {
787: CPUCLASS_686,
788: {
789: 0, 0, 0, 0, 0, 0, 0,
790: 0, 0, 0, 0, 0, 0, 0, 0, 0,
791: "Pentium Pro compatible" /* Default */
792: },
793: NULL
794: },
795: /* Family > 6, not yet available from IDT */
1.329 bad 796: {
797: CPUCLASS_686,
798: {
799: 0, 0, 0, 0, 0, 0, 0,
800: 0, 0, 0, 0, 0, 0, 0, 0, 0,
801: "Pentium Pro compatible" /* Default */
1.267 bouyer 802: },
803: NULL
1.216 fvdl 804: } }
805: }
806: };
807:
1.195 mycroft 808: void
1.267 bouyer 809: cyrix6x86_cpu_setup()
810: {
811: /* set up various cyrix registers */
812: /* Enable suspend on halt */
813: cyrix_write_reg(0xc2, cyrix_read_reg(0xc2) | 0x08);
814: /* enable access to ccr4/ccr5 */
815: cyrix_write_reg(0xC3, cyrix_read_reg(0xC3) | 0x10);
816: /* cyrix's workaround for the "coma bug" */
817: cyrix_write_reg(0x31, cyrix_read_reg(0x31) | 0xf8);
818: cyrix_write_reg(0x32, cyrix_read_reg(0x32) | 0x7f);
819: cyrix_write_reg(0x33, cyrix_read_reg(0x33) & ~0xff);
820: cyrix_write_reg(0x3c, cyrix_read_reg(0x3c) | 0x87);
821: /* disable access to ccr4/ccr5 */
822: cyrix_write_reg(0xC3, cyrix_read_reg(0xC3) & ~0x10);
1.393 fvdl 823:
824: /*
825: * XXX disable page zero in the idle loop, it seems to
826: * cause panics on these CPUs.
827: */
828: vm_page_zero_enable = FALSE;
1.267 bouyer 829: }
830:
831: void
1.379 jdolecek 832: winchip_cpu_setup()
833: {
1.380 jdolecek 834: #if defined(I586_CPU)
1.379 jdolecek 835: extern int cpu_id;
836:
837: switch (CPUID2MODEL(cpu_id)) { /* model */
838: case 4: /* WinChip C6 */
839: cpu_feature &= ~CPUID_TSC;
840: printf("WARNING: WinChip C6: broken TSC disabled\n");
841: }
842: #endif
843: }
844:
1.397 thorpej 845: static void
846: do_cpuid(u_int which, u_int *rv)
847: {
848: register u_int eax __asm("%eax") = which;
849:
850: __asm __volatile(
851: " cpuid ;"
852: " movl %%eax,0(%2) ;"
853: " movl %%ebx,4(%2) ;"
854: " movl %%ecx,8(%2) ;"
855: " movl %%edx,12(%2) "
856: : "=a" (eax)
857: : "0" (eax), "S" (rv)
858: : "ebx", "ecx", "edx");
859: }
860:
1.402 explorer 861: static void
862: do_cpuid_serial(u_int *serial)
863: {
864: __asm __volatile(
865: " movl $1,%%eax ;"
866: " cpuid ;"
867: " movl %%eax,0(%0) ;"
868: " movl $3,%%eax ;"
869: " cpuid ;"
870: " movl %%edx,4(%0) ;"
871: " movl %%ecx,8(%0) "
872: : /* no imputs */
873: : "S" (serial)
874: : "eax", "ebx", "ecx", "edx");
875: }
876:
1.379 jdolecek 877: void
1.59 mycroft 878: identifycpu()
1.16 cgd 879: {
1.86 mycroft 880: extern char cpu_vendor[];
1.216 fvdl 881: extern int cpu_id;
1.417 jdolecek 882: extern int cpu_brand_id;
883: const char *name, *modifier, *vendorname, *brand = "";
1.216 fvdl 884: int class = CPUCLASS_386, vendor, i, max;
885: int family, model, step, modif;
1.418 jdolecek 886: const struct cpu_cpuid_nameclass *cpup = NULL;
1.267 bouyer 887: void (*cpu_setup) __P((void));
1.86 mycroft 888:
1.216 fvdl 889: if (cpuid_level == -1) {
1.59 mycroft 890: #ifdef DIAGNOSTIC
1.216 fvdl 891: if (cpu < 0 || cpu >=
892: (sizeof i386_nocpuid_cpus/sizeof(struct cpu_nocpuid_nameclass)))
893: panic("unknown cpu type %d\n", cpu);
894: #endif
895: name = i386_nocpuid_cpus[cpu].cpu_name;
896: vendor = i386_nocpuid_cpus[cpu].cpu_vendor;
897: vendorname = i386_nocpuid_cpus[cpu].cpu_vendorname;
898: class = i386_nocpuid_cpus[cpu].cpu_class;
1.267 bouyer 899: cpu_setup = i386_nocpuid_cpus[cpu].cpu_setup;
1.216 fvdl 900: modifier = "";
901: } else {
902: max = sizeof (i386_cpuid_cpus) / sizeof (i386_cpuid_cpus[0]);
903: modif = (cpu_id >> 12) & 3;
904: family = (cpu_id >> 8) & 15;
905: if (family < CPU_MINFAMILY)
906: panic("identifycpu: strange family value");
1.379 jdolecek 907: model = CPUID2MODEL(cpu_id);
1.216 fvdl 908: step = cpu_id & 15;
909: #ifdef CPUDEBUG
910: printf("cpu0: family %x model %x step %x\n", family, model,
911: step);
912: #endif
913:
914: for (i = 0; i < max; i++) {
915: if (!strncmp(cpu_vendor,
916: i386_cpuid_cpus[i].cpu_id, 12)) {
917: cpup = &i386_cpuid_cpus[i];
918: break;
919: }
920: }
921:
922: if (cpup == NULL) {
923: vendor = CPUVENDOR_UNKNOWN;
924: if (cpu_vendor[0] != '\0')
925: vendorname = &cpu_vendor[0];
926: else
927: vendorname = "Unknown";
928: if (family > CPU_MAXFAMILY)
929: family = CPU_MAXFAMILY;
930: class = family - 3;
931: modifier = "";
932: name = "";
1.267 bouyer 933: cpu_setup = NULL;
1.216 fvdl 934: } else {
935: vendor = cpup->cpu_vendor;
936: vendorname = cpup->cpu_vendorname;
937: modifier = modifiers[modif];
938: if (family > CPU_MAXFAMILY) {
939: family = CPU_MAXFAMILY;
940: model = CPU_DEFMODEL;
941: } else if (model > CPU_MAXMODEL)
942: model = CPU_DEFMODEL;
943: i = family - CPU_MINFAMILY;
944: name = cpup->cpu_family[i].cpu_models[model];
945: if (name == NULL)
946: name = cpup->cpu_family[i].cpu_models[CPU_DEFMODEL];
947: class = cpup->cpu_family[i].cpu_class;
1.267 bouyer 948: cpu_setup = cpup->cpu_family[i].cpu_setup;
1.417 jdolecek 949:
950: /*
951: * Intel processors family >= 6, model 8 allow to
952: * recognize brand by Brand ID value.
953: */
954: if (vendor == CPUVENDOR_INTEL && family >= 6
955: && model >= 8 && cpu_brand_id && cpu_brand_id <= 3)
956: brand = i386_p3_brand[cpu_brand_id];
1.216 fvdl 957: }
1.104 cgd 958: }
959:
1.417 jdolecek 960: sprintf(cpu_model, "%s %s%s%s%s (%s-class)", vendorname, modifier, name,
1.419 jdolecek 961: (*brand) ? " " : "", brand,
1.241 fvdl 962: classnames[class]);
1.216 fvdl 963:
964: cpu_class = class;
1.397 thorpej 965:
966: /*
967: * Parse the cache info from `cpuid', if we have it.
968: * XXX This is kinda ugly, but hey, so is the architecture...
969: */
970: if (cpuid_level != -1) {
971: const struct i386_cache_info *cai;
972: u_int descs[4];
973: int iterations, j;
974: u_int8_t desc;
975:
1.399 enami 976: do_cpuid(2, descs);
977: iterations = descs[0] & 0xff;
978: while (iterations-- > 0) {
1.397 thorpej 979: for (i = 0; i < 4; i++) {
980: if (descs[i] & 0x80000000)
981: continue;
982: for (j = 0; j < 4; j++) {
1.399 enami 983: if (i == 0 && j == 0)
984: continue;
1.397 thorpej 985: desc = (descs[i] >> (j * 8)) & 0xff;
986: cai = i386_cache_info_lookup(desc);
987: if (cai != NULL)
988: *cai->cai_var = cai;
989: }
990: }
1.399 enami 991:
992: do_cpuid(2, descs);
993: }
1.397 thorpej 994: }
1.402 explorer 995:
996: /*
997: * If the processor serial number misfeature is present and supported,
998: * extract it here.
999: */
1000: if (cpuid_level >= 3 && (cpu_feature & CPUID_PN) != 0)
1001: do_cpuid_serial(cpu_serial);
1.18 cgd 1002:
1.16 cgd 1003: /*
1004: * Now that we have told the user what they have,
1005: * let them know if that machine type isn't configured.
1006: */
1.24 cgd 1007: switch (cpu_class) {
1.216 fvdl 1008: #if !defined(I386_CPU) && !defined(I486_CPU) && !defined(I586_CPU) && !defined(I686_CPU)
1.100 mycroft 1009: #error No CPU classes configured.
1010: #endif
1.216 fvdl 1011: #ifndef I686_CPU
1012: case CPUCLASS_686:
1013: printf("NOTICE: this kernel does not support Pentium Pro CPU class\n");
1014: #ifdef I586_CPU
1015: printf("NOTICE: lowering CPU class to i586\n");
1016: cpu_class = CPUCLASS_586;
1017: break;
1018: #endif
1019: #endif
1.165 mycroft 1020: #ifndef I586_CPU
1.118 mycroft 1021: case CPUCLASS_586:
1.210 christos 1022: printf("NOTICE: this kernel does not support Pentium CPU class\n");
1.165 mycroft 1023: #ifdef I486_CPU
1.210 christos 1024: printf("NOTICE: lowering CPU class to i486\n");
1.118 mycroft 1025: cpu_class = CPUCLASS_486;
1026: break;
1.16 cgd 1027: #endif
1.165 mycroft 1028: #endif
1029: #ifndef I486_CPU
1.18 cgd 1030: case CPUCLASS_486:
1.210 christos 1031: printf("NOTICE: this kernel does not support i486 CPU class\n");
1.165 mycroft 1032: #ifdef I386_CPU
1.210 christos 1033: printf("NOTICE: lowering CPU class to i386\n");
1.118 mycroft 1034: cpu_class = CPUCLASS_386;
1035: break;
1036: #endif
1.165 mycroft 1037: #endif
1038: #ifndef I386_CPU
1.118 mycroft 1039: case CPUCLASS_386:
1.210 christos 1040: printf("NOTICE: this kernel does not support i386 CPU class\n");
1.187 mycroft 1041: panic("no appropriate CPU class available");
1.59 mycroft 1042: #endif
1.16 cgd 1043: default:
1044: break;
1.121 mycroft 1045: }
1046:
1.267 bouyer 1047: /* configure the CPU if needed */
1048: if (cpu_setup != NULL)
1049: cpu_setup();
1.121 mycroft 1050: if (cpu == CPU_486DLC) {
1051: #ifndef CYRIX_CACHE_WORKS
1.210 christos 1052: printf("WARNING: CYRIX 486DLC CACHE UNCHANGED.\n");
1.121 mycroft 1053: #else
1054: #ifndef CYRIX_CACHE_REALLY_WORKS
1.210 christos 1055: printf("WARNING: CYRIX 486DLC CACHE ENABLED IN HOLD-FLUSH MODE.\n");
1.121 mycroft 1056: #else
1.210 christos 1057: printf("WARNING: CYRIX 486DLC CACHE ENABLED.\n");
1.121 mycroft 1058: #endif
1059: #endif
1.16 cgd 1060: }
1.147 mycroft 1061:
1.216 fvdl 1062: #if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
1.147 mycroft 1063: /*
1.199 mycroft 1064: * On a 486 or above, enable ring 0 write protection.
1.147 mycroft 1065: */
1066: if (cpu_class >= CPUCLASS_486)
1.199 mycroft 1067: lcr0(rcr0() | CR0_WP);
1.408 thorpej 1068: #endif
1069:
1070: #if defined(I586_CPU) || defined(I686_CPU)
1071: /*
1072: * If we have a cycle counter, compute the approximate
1073: * CPU speed in MHz.
1074: */
1075: if (cpu_feature & CPUID_TSC) {
1076: u_int64_t last_tsc;
1077:
1078: last_tsc = rdtsc();
1.413 jdolecek 1079: delay(100000);
1080: cpu_tsc_freq = (rdtsc() - last_tsc) * 10;
1.408 thorpej 1081: }
1.147 mycroft 1082: #endif
1.1 cgd 1083: }
1084:
1.104 cgd 1085: /*
1086: * machine dependent system variables.
1087: */
1.195 mycroft 1088: int
1.104 cgd 1089: cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
1090: int *name;
1091: u_int namelen;
1092: void *oldp;
1093: size_t *oldlenp;
1094: void *newp;
1095: size_t newlen;
1096: struct proc *p;
1097: {
1098: dev_t consdev;
1.255 drochner 1099: struct btinfo_bootpath *bibp;
1.104 cgd 1100:
1101: /* all sysctl names at this level are terminal */
1102: if (namelen != 1)
1103: return (ENOTDIR); /* overloaded */
1104:
1105: switch (name[0]) {
1106: case CPU_CONSDEV:
1107: if (cn_tab != NULL)
1108: consdev = cn_tab->cn_dev;
1109: else
1110: consdev = NODEV;
1111: return (sysctl_rdstruct(oldp, oldlenp, newp, &consdev,
1112: sizeof consdev));
1.215 fvdl 1113:
1114: case CPU_BIOSBASEMEM:
1115: return (sysctl_rdint(oldp, oldlenp, newp, biosbasemem));
1116:
1117: case CPU_BIOSEXTMEM:
1118: return (sysctl_rdint(oldp, oldlenp, newp, biosextmem));
1119:
1120: case CPU_NKPDE:
1121: return (sysctl_rdint(oldp, oldlenp, newp, nkpde));
1.366 fvdl 1122:
1123: case CPU_FPU_PRESENT:
1124: return (sysctl_rdint(oldp, oldlenp, newp, i386_fpu_present));
1.215 fvdl 1125:
1.255 drochner 1126: case CPU_BOOTED_KERNEL:
1127: bibp = lookup_bootinfo(BTINFO_BOOTPATH);
1128: if(!bibp)
1129: return(ENOENT); /* ??? */
1130: return (sysctl_rdstring(oldp, oldlenp, newp, bibp->bootpath));
1.343 fvdl 1131: case CPU_DISKINFO:
1132: if (i386_alldisks == NULL)
1.339 fvdl 1133: return (ENOENT);
1.343 fvdl 1134: return (sysctl_rdstruct(oldp, oldlenp, newp, i386_alldisks,
1135: sizeof (struct disklist) +
1136: (i386_ndisks - 1) * sizeof (struct nativedisk_info)));
1.104 cgd 1137: default:
1138: return (EOPNOTSUPP);
1139: }
1140: /* NOTREACHED */
1141: }
1.151 christos 1142:
1.1 cgd 1143: /*
1144: * Send an interrupt to process.
1145: *
1146: * Stack is set up to allow sigcode stored
1147: * in u. to call routine, followed by kcall
1148: * to sigreturn routine below. After sigreturn
1149: * resets the signal mask, the stack, and the
1150: * frame pointer, it returns to the user
1151: * specified pc, psl.
1152: */
1153: void
1154: sendsig(catcher, sig, mask, code)
1155: sig_t catcher;
1.319 mycroft 1156: int sig;
1157: sigset_t *mask;
1.126 cgd 1158: u_long code;
1.1 cgd 1159: {
1.298 mycroft 1160: struct proc *p = curproc;
1161: struct trapframe *tf;
1.82 ws 1162: struct sigframe *fp, frame;
1.319 mycroft 1163: int onstack;
1.1 cgd 1164:
1.319 mycroft 1165: tf = p->p_md.md_regs;
1.135 christos 1166:
1.319 mycroft 1167: /* Do we need to jump onto the signal stack? */
1168: onstack =
1.425 ! jdolecek 1169: (p->p_sigctx.ps_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 &&
! 1170: (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0;
1.135 christos 1171:
1.319 mycroft 1172: /* Allocate space for the signal handler context. */
1173: if (onstack)
1.425 ! jdolecek 1174: fp = (struct sigframe *)((caddr_t)p->p_sigctx.ps_sigstk.ss_sp +
! 1175: p->p_sigctx.ps_sigstk.ss_size);
1.319 mycroft 1176: else
1177: fp = (struct sigframe *)tf->tf_esp;
1178: fp--;
1.1 cgd 1179:
1.319 mycroft 1180: /* Build stack frame for signal trampoline. */
1181: frame.sf_signum = sig;
1.82 ws 1182: frame.sf_code = code;
1183: frame.sf_scp = &fp->sf_sc;
1184: frame.sf_handler = catcher;
1185:
1.319 mycroft 1186: /* Save register context. */
1.157 mycroft 1187: #ifdef VM86
1188: if (tf->tf_eflags & PSL_VM) {
1189: frame.sf_sc.sc_gs = tf->tf_vm86_gs;
1190: frame.sf_sc.sc_fs = tf->tf_vm86_fs;
1191: frame.sf_sc.sc_es = tf->tf_vm86_es;
1192: frame.sf_sc.sc_ds = tf->tf_vm86_ds;
1.196 mycroft 1193: frame.sf_sc.sc_eflags = get_vflags(p);
1.422 mycroft 1194: (*p->p_emul->e_syscall_intern)(p);
1.157 mycroft 1195: } else
1196: #endif
1197: {
1198: __asm("movl %%gs,%w0" : "=r" (frame.sf_sc.sc_gs));
1199: __asm("movl %%fs,%w0" : "=r" (frame.sf_sc.sc_fs));
1200: frame.sf_sc.sc_es = tf->tf_es;
1201: frame.sf_sc.sc_ds = tf->tf_ds;
1.184 mycroft 1202: frame.sf_sc.sc_eflags = tf->tf_eflags;
1.157 mycroft 1203: }
1.184 mycroft 1204: frame.sf_sc.sc_edi = tf->tf_edi;
1205: frame.sf_sc.sc_esi = tf->tf_esi;
1206: frame.sf_sc.sc_ebp = tf->tf_ebp;
1207: frame.sf_sc.sc_ebx = tf->tf_ebx;
1208: frame.sf_sc.sc_edx = tf->tf_edx;
1209: frame.sf_sc.sc_ecx = tf->tf_ecx;
1210: frame.sf_sc.sc_eax = tf->tf_eax;
1211: frame.sf_sc.sc_eip = tf->tf_eip;
1212: frame.sf_sc.sc_cs = tf->tf_cs;
1213: frame.sf_sc.sc_esp = tf->tf_esp;
1214: frame.sf_sc.sc_ss = tf->tf_ss;
1.319 mycroft 1215: frame.sf_sc.sc_trapno = tf->tf_trapno;
1216: frame.sf_sc.sc_err = tf->tf_err;
1217:
1218: /* Save signal stack. */
1.425 ! jdolecek 1219: frame.sf_sc.sc_onstack = p->p_sigctx.ps_sigstk.ss_flags & SS_ONSTACK;
1.319 mycroft 1220:
1221: /* Save signal mask. */
1222: frame.sf_sc.sc_mask = *mask;
1.322 thorpej 1223:
1224: #ifdef COMPAT_13
1225: /*
1226: * XXX We always have to save an old style signal mask because
1227: * XXX we might be delivering a signal to a process which will
1228: * XXX escape from the signal in a non-standard way and invoke
1229: * XXX sigreturn() directly.
1230: */
1231: native_sigset_to_sigset13(mask, &frame.sf_sc.__sc_mask13);
1232: #endif
1.1 cgd 1233:
1.87 mycroft 1234: if (copyout(&frame, fp, sizeof(frame)) != 0) {
1.1 cgd 1235: /*
1236: * Process has trashed its stack; give it an illegal
1237: * instruction to halt it in its tracks.
1238: */
1.93 mycroft 1239: sigexit(p, SIGILL);
1240: /* NOTREACHED */
1.1 cgd 1241: }
1242:
1.73 mycroft 1243: /*
1.59 mycroft 1244: * Build context to run handler in.
1245: */
1.185 mycroft 1246: __asm("movl %w0,%%gs" : : "r" (GSEL(GUDATA_SEL, SEL_UPL)));
1247: __asm("movl %w0,%%fs" : : "r" (GSEL(GUDATA_SEL, SEL_UPL)));
1248: tf->tf_es = GSEL(GUDATA_SEL, SEL_UPL);
1249: tf->tf_ds = GSEL(GUDATA_SEL, SEL_UPL);
1.425 ! jdolecek 1250: tf->tf_eip = (int)p->p_sigctx.ps_sigcode;
1.185 mycroft 1251: tf->tf_cs = GSEL(GUCODE_SEL, SEL_UPL);
1.198 mycroft 1252: tf->tf_eflags &= ~(PSL_T|PSL_VM|PSL_AC);
1.185 mycroft 1253: tf->tf_esp = (int)fp;
1.177 mycroft 1254: tf->tf_ss = GSEL(GUDATA_SEL, SEL_UPL);
1.319 mycroft 1255:
1256: /* Remember that we're now on the signal stack. */
1257: if (onstack)
1.425 ! jdolecek 1258: p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK;
1.1 cgd 1259: }
1260:
1261: /*
1262: * System call to cleanup state after a signal
1263: * has been taken. Reset signal mask and
1264: * stack state from context left by sendsig (above).
1265: * Return to previous pc and psl as specified by
1266: * context left by sendsig. Check carefully to
1267: * make sure that the user has not modified the
1.110 mycroft 1268: * psl to gain improper privileges or to cause
1.1 cgd 1269: * a machine fault.
1270: */
1.195 mycroft 1271: int
1.320 mycroft 1272: sys___sigreturn14(p, v, retval)
1.1 cgd 1273: struct proc *p;
1.172 thorpej 1274: void *v;
1275: register_t *retval;
1276: {
1.320 mycroft 1277: struct sys___sigreturn14_args /* {
1.123 cgd 1278: syscallarg(struct sigcontext *) sigcntxp;
1.172 thorpej 1279: } */ *uap = v;
1.82 ws 1280: struct sigcontext *scp, context;
1.298 mycroft 1281: struct trapframe *tf;
1.59 mycroft 1282:
1.27 cgd 1283: /*
1.59 mycroft 1284: * The trampoline code hands us the context.
1285: * It is unsafe to keep track of it ourselves, in the event that a
1286: * program jumps out of a signal handler.
1.27 cgd 1287: */
1.123 cgd 1288: scp = SCARG(uap, sigcntxp);
1.87 mycroft 1289: if (copyin((caddr_t)scp, &context, sizeof(*scp)) != 0)
1.122 mycroft 1290: return (EFAULT);
1.1 cgd 1291:
1.319 mycroft 1292: /* Restore register context. */
1293: tf = p->p_md.md_regs;
1.157 mycroft 1294: #ifdef VM86
1295: if (context.sc_eflags & PSL_VM) {
1.422 mycroft 1296: void syscall_vm86 __P((struct trapframe));
1297:
1.157 mycroft 1298: tf->tf_vm86_gs = context.sc_gs;
1299: tf->tf_vm86_fs = context.sc_fs;
1300: tf->tf_vm86_es = context.sc_es;
1301: tf->tf_vm86_ds = context.sc_ds;
1.196 mycroft 1302: set_vflags(p, context.sc_eflags);
1.422 mycroft 1303: p->p_md.md_syscall = syscall_vm86;
1.157 mycroft 1304: } else
1305: #endif
1306: {
1.196 mycroft 1307: /*
1308: * Check for security violations. If we're returning to
1309: * protected mode, the CPU will validate the segment registers
1310: * automatically and generate a trap on violations. We handle
1311: * the trap, rather than doing all of the checking here.
1312: */
1313: if (((context.sc_eflags ^ tf->tf_eflags) & PSL_USERSTATIC) != 0 ||
1314: !USERMODE(context.sc_cs, context.sc_eflags))
1315: return (EINVAL);
1316:
1.157 mycroft 1317: /* %fs and %gs were restored by the trampoline. */
1318: tf->tf_es = context.sc_es;
1319: tf->tf_ds = context.sc_ds;
1.184 mycroft 1320: tf->tf_eflags = context.sc_eflags;
1.157 mycroft 1321: }
1.184 mycroft 1322: tf->tf_edi = context.sc_edi;
1323: tf->tf_esi = context.sc_esi;
1324: tf->tf_ebp = context.sc_ebp;
1325: tf->tf_ebx = context.sc_ebx;
1326: tf->tf_edx = context.sc_edx;
1327: tf->tf_ecx = context.sc_ecx;
1328: tf->tf_eax = context.sc_eax;
1329: tf->tf_eip = context.sc_eip;
1330: tf->tf_cs = context.sc_cs;
1331: tf->tf_esp = context.sc_esp;
1332: tf->tf_ss = context.sc_ss;
1.196 mycroft 1333:
1.319 mycroft 1334: /* Restore signal stack. */
1335: if (context.sc_onstack & SS_ONSTACK)
1.425 ! jdolecek 1336: p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK;
1.196 mycroft 1337: else
1.425 ! jdolecek 1338: p->p_sigctx.ps_sigstk.ss_flags &= ~SS_ONSTACK;
1.319 mycroft 1339:
1340: /* Restore signal mask. */
1341: (void) sigprocmask1(p, SIG_SETMASK, &context.sc_mask, 0);
1.72 mycroft 1342:
1.122 mycroft 1343: return (EJUSTRETURN);
1.37 cgd 1344: }
1345:
1.1 cgd 1346: int waittime = -1;
1347: struct pcb dumppcb;
1348:
1.32 andrew 1349: void
1.228 gwr 1350: cpu_reboot(howto, bootstr)
1.193 mycroft 1351: int howto;
1.206 mrg 1352: char *bootstr;
1.1 cgd 1353: {
1354:
1.106 mycroft 1355: if (cold) {
1.193 mycroft 1356: howto |= RB_HALT;
1357: goto haltsys;
1.1 cgd 1358: }
1.193 mycroft 1359:
1.106 mycroft 1360: boothowto = howto;
1.193 mycroft 1361: if ((howto & RB_NOSYNC) == 0 && waittime < 0) {
1.1 cgd 1362: waittime = 0;
1.150 mycroft 1363: vfs_shutdown();
1.59 mycroft 1364: /*
1365: * If we've been adjusting the clock, the todr
1366: * will be out of synch; adjust it now.
1367: */
1368: resettodr();
1.1 cgd 1369: }
1.193 mycroft 1370:
1371: /* Disable interrupts. */
1.1 cgd 1372: splhigh();
1.193 mycroft 1373:
1374: /* Do a dump if requested. */
1375: if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP)
1376: dumpsys();
1377:
1378: haltsys:
1379: doshutdownhooks();
1380:
1.307 thorpej 1381: if ((howto & RB_POWERDOWN) == RB_POWERDOWN) {
1.208 jtk 1382: #if NAPM > 0 && !defined(APM_NO_POWEROFF)
1383: /* turn off, if we can. But try to turn disk off and
1384: * wait a bit first--some disk drives are slow to clean up
1385: * and users have reported disk corruption.
1386: */
1387: delay(500000);
1388: apm_set_powstate(APM_DEV_DISK(0xff), APM_SYS_OFF);
1389: delay(500000);
1390: apm_set_powstate(APM_DEV_ALLDEVS, APM_SYS_OFF);
1.307 thorpej 1391: printf("WARNING: powerdown failed!\n");
1392: /*
1393: * RB_POWERDOWN implies RB_HALT... fall into it...
1394: */
1.208 jtk 1395: #endif
1.307 thorpej 1396: }
1397:
1398: if (howto & RB_HALT) {
1.210 christos 1399: printf("\n");
1400: printf("The operating system has halted.\n");
1401: printf("Please press any key to reboot.\n\n");
1.300 drochner 1402: cnpollc(1); /* for proper keyboard command handling */
1.12 cgd 1403: cngetc();
1.300 drochner 1404: cnpollc(0);
1.1 cgd 1405: }
1.193 mycroft 1406:
1.210 christos 1407: printf("rebooting...\n");
1.328 bouyer 1408: if (cpureset_delay > 0)
1409: delay(cpureset_delay * 1000);
1.1 cgd 1410: cpu_reset();
1411: for(;;) ;
1412: /*NOTREACHED*/
1413: }
1414:
1.116 gwr 1415: /*
1416: * These variables are needed by /sbin/savecore
1417: */
1418: u_long dumpmag = 0x8fca0101; /* magic number */
1419: int dumpsize = 0; /* pages */
1420: long dumplo = 0; /* blocks */
1421:
1422: /*
1.291 thorpej 1423: * cpu_dumpsize: calculate size of machine-dependent kernel core dump headers.
1424: */
1425: int
1426: cpu_dumpsize()
1427: {
1428: int size;
1429:
1430: size = ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t)) +
1431: ALIGN(mem_cluster_cnt * sizeof(phys_ram_seg_t));
1432: if (roundup(size, dbtob(1)) != dbtob(1))
1433: return (-1);
1434:
1435: return (1);
1436: }
1437:
1438: /*
1439: * cpu_dump_mempagecnt: calculate the size of RAM (in pages) to be dumped.
1440: */
1441: u_long
1442: cpu_dump_mempagecnt()
1443: {
1444: u_long i, n;
1445:
1446: n = 0;
1447: for (i = 0; i < mem_cluster_cnt; i++)
1448: n += atop(mem_clusters[i].size);
1449: return (n);
1450: }
1451:
1452: /*
1453: * cpu_dump: dump the machine-dependent kernel core dump headers.
1454: */
1455: int
1456: cpu_dump()
1457: {
1458: int (*dump) __P((dev_t, daddr_t, caddr_t, size_t));
1459: char buf[dbtob(1)];
1460: kcore_seg_t *segp;
1461: cpu_kcore_hdr_t *cpuhdrp;
1462: phys_ram_seg_t *memsegp;
1463: int i;
1464:
1465: dump = bdevsw[major(dumpdev)].d_dump;
1466:
1.313 perry 1467: memset(buf, 0, sizeof buf);
1.291 thorpej 1468: segp = (kcore_seg_t *)buf;
1469: cpuhdrp = (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(*segp))];
1470: memsegp = (phys_ram_seg_t *)&buf[ ALIGN(sizeof(*segp)) +
1471: ALIGN(sizeof(*cpuhdrp))];
1472:
1473: /*
1474: * Generate a segment header.
1475: */
1476: CORE_SETMAGIC(*segp, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
1477: segp->c_size = dbtob(1) - ALIGN(sizeof(*segp));
1478:
1479: /*
1480: * Add the machine-dependent header info.
1481: */
1482: cpuhdrp->ptdpaddr = PTDpaddr;
1483: cpuhdrp->nmemsegs = mem_cluster_cnt;
1484:
1485: /*
1486: * Fill in the memory segment descriptors.
1487: */
1488: for (i = 0; i < mem_cluster_cnt; i++) {
1489: memsegp[i].start = mem_clusters[i].start;
1490: memsegp[i].size = mem_clusters[i].size;
1491: }
1492:
1493: return (dump(dumpdev, dumplo, (caddr_t)buf, dbtob(1)));
1494: }
1495:
1496: /*
1.228 gwr 1497: * This is called by main to set dumplo and dumpsize.
1.414 thorpej 1498: * Dumps always skip the first PAGE_SIZE of disk space
1.116 gwr 1499: * in case there might be a disk label stored there.
1500: * If there is extra space, put dump at the end to
1501: * reduce the chance that swapping trashes it.
1502: */
1503: void
1.228 gwr 1504: cpu_dumpconf()
1.116 gwr 1505: {
1.291 thorpej 1506: int nblks, dumpblks; /* size of dump area */
1.116 gwr 1507: int maj;
1508:
1509: if (dumpdev == NODEV)
1.291 thorpej 1510: goto bad;
1.116 gwr 1511: maj = major(dumpdev);
1512: if (maj < 0 || maj >= nblkdev)
1513: panic("dumpconf: bad dumpdev=0x%x", dumpdev);
1.134 mycroft 1514: if (bdevsw[maj].d_psize == NULL)
1.291 thorpej 1515: goto bad;
1.134 mycroft 1516: nblks = (*bdevsw[maj].d_psize)(dumpdev);
1.116 gwr 1517: if (nblks <= ctod(1))
1.291 thorpej 1518: goto bad;
1.116 gwr 1519:
1.291 thorpej 1520: dumpblks = cpu_dumpsize();
1521: if (dumpblks < 0)
1522: goto bad;
1523: dumpblks += ctod(cpu_dump_mempagecnt());
1524:
1525: /* If dump won't fit (incl. room for possible label), punt. */
1526: if (dumpblks > (nblks - ctod(1)))
1527: goto bad;
1528:
1529: /* Put dump at end of partition */
1530: dumplo = nblks - dumpblks;
1531:
1532: /* dumpsize is in page units, and doesn't include headers. */
1533: dumpsize = cpu_dump_mempagecnt();
1534: return;
1.116 gwr 1535:
1.291 thorpej 1536: bad:
1537: dumpsize = 0;
1.116 gwr 1538: }
1539:
1.1 cgd 1540: /*
1541: * Doadump comes here after turning off memory management and
1542: * getting on the dump stack, either when called above, or by
1543: * the auto-restart code.
1544: */
1.414 thorpej 1545: #define BYTES_PER_DUMP PAGE_SIZE /* must be a multiple of pagesize XXX small */
1.314 thorpej 1546: static vaddr_t dumpspace;
1.163 cgd 1547:
1.314 thorpej 1548: vaddr_t
1.163 cgd 1549: reserve_dumppages(p)
1.314 thorpej 1550: vaddr_t p;
1.163 cgd 1551: {
1552:
1553: dumpspace = p;
1554: return (p + BYTES_PER_DUMP);
1555: }
1556:
1.32 andrew 1557: void
1.1 cgd 1558: dumpsys()
1559: {
1.291 thorpej 1560: u_long totalbytesleft, bytes, i, n, memseg;
1561: u_long maddr;
1562: int psize;
1.163 cgd 1563: daddr_t blkno;
1564: int (*dump) __P((dev_t, daddr_t, caddr_t, size_t));
1.200 christos 1565: int error;
1.193 mycroft 1566:
1567: /* Save registers. */
1568: savectx(&dumppcb);
1.1 cgd 1569:
1570: if (dumpdev == NODEV)
1571: return;
1.163 cgd 1572:
1573: /*
1574: * For dumps during autoconfiguration,
1575: * if dump device has already configured...
1576: */
1577: if (dumpsize == 0)
1.228 gwr 1578: cpu_dumpconf();
1.330 jtk 1579: if (dumplo <= 0 || dumpsize == 0) {
1.275 mycroft 1580: printf("\ndump to dev %u,%u not possible\n", major(dumpdev),
1581: minor(dumpdev));
1.163 cgd 1582: return;
1.275 mycroft 1583: }
1584: printf("\ndumping to dev %u,%u offset %ld\n", major(dumpdev),
1585: minor(dumpdev), dumplo);
1.134 mycroft 1586:
1.163 cgd 1587: psize = (*bdevsw[major(dumpdev)].d_psize)(dumpdev);
1.210 christos 1588: printf("dump ");
1.163 cgd 1589: if (psize == -1) {
1.210 christos 1590: printf("area unavailable\n");
1.163 cgd 1591: return;
1592: }
1593:
1594: #if 0 /* XXX this doesn't work. grr. */
1595: /* toss any characters present prior to dump */
1596: while (sget() != NULL); /*syscons and pccons differ */
1597: #endif
1598:
1.291 thorpej 1599: if ((error = cpu_dump()) != 0)
1600: goto err;
1601:
1602: totalbytesleft = ptoa(cpu_dump_mempagecnt());
1603: blkno = dumplo + cpu_dumpsize();
1.163 cgd 1604: dump = bdevsw[major(dumpdev)].d_dump;
1.200 christos 1605: error = 0;
1.291 thorpej 1606:
1607: for (memseg = 0; memseg < mem_cluster_cnt; memseg++) {
1608: maddr = mem_clusters[memseg].start;
1609: bytes = mem_clusters[memseg].size;
1610:
1611: for (i = 0; i < bytes; i += n, totalbytesleft -= n) {
1612: /* Print out how many MBs we have left to go. */
1613: if ((totalbytesleft % (1024*1024)) == 0)
1614: printf("%ld ", totalbytesleft / (1024 * 1024));
1615:
1616: /* Limit size for next transfer. */
1617: n = bytes - i;
1618: if (n > BYTES_PER_DUMP)
1619: n = BYTES_PER_DUMP;
1620:
1621: (void) pmap_map(dumpspace, maddr, maddr + n,
1622: VM_PROT_READ);
1623:
1624: error = (*dump)(dumpdev, blkno, (caddr_t)dumpspace, n);
1625: if (error)
1626: goto err;
1.163 cgd 1627: maddr += n;
1.291 thorpej 1628: blkno += btodb(n); /* XXX? */
1.163 cgd 1629:
1630: #if 0 /* XXX this doesn't work. grr. */
1.291 thorpej 1631: /* operator aborting dump? */
1632: if (sget() != NULL) {
1633: error = EINTR;
1634: break;
1635: }
1636: #endif
1.163 cgd 1637: }
1638: }
1639:
1.291 thorpej 1640: err:
1.163 cgd 1641: switch (error) {
1.1 cgd 1642:
1643: case ENXIO:
1.210 christos 1644: printf("device bad\n");
1.1 cgd 1645: break;
1646:
1647: case EFAULT:
1.210 christos 1648: printf("device not ready\n");
1.1 cgd 1649: break;
1650:
1651: case EINVAL:
1.210 christos 1652: printf("area improper\n");
1.1 cgd 1653: break;
1654:
1655: case EIO:
1.210 christos 1656: printf("i/o error\n");
1.1 cgd 1657: break;
1658:
1659: case EINTR:
1.210 christos 1660: printf("aborted from console\n");
1.1 cgd 1661: break;
1662:
1.163 cgd 1663: case 0:
1.210 christos 1664: printf("succeeded\n");
1.163 cgd 1665: break;
1666:
1.1 cgd 1667: default:
1.210 christos 1668: printf("error %d\n", error);
1.1 cgd 1669: break;
1670: }
1.210 christos 1671: printf("\n\n");
1.163 cgd 1672: delay(5000000); /* 5 seconds */
1.1 cgd 1673: }
1674:
1675: /*
1676: * Clear registers on exec
1677: */
1.33 cgd 1678: void
1.251 mycroft 1679: setregs(p, pack, stack)
1.1 cgd 1680: struct proc *p;
1.151 christos 1681: struct exec_package *pack;
1.21 cgd 1682: u_long stack;
1.1 cgd 1683: {
1.298 mycroft 1684: struct pcb *pcb = &p->p_addr->u_pcb;
1685: struct trapframe *tf;
1.1 cgd 1686:
1.161 mycroft 1687: #if NNPX > 0
1688: /* If we were using the FPU, forget about it. */
1689: if (npxproc == p)
1.166 mycroft 1690: npxdrop();
1.161 mycroft 1691: #endif
1.166 mycroft 1692:
1.178 mycroft 1693: #ifdef USER_LDT
1.353 thorpej 1694: pmap_ldt_cleanup(p);
1.178 mycroft 1695: #endif
1696:
1.167 mycroft 1697: p->p_md.md_flags &= ~MDP_USEDFPU;
1.178 mycroft 1698: pcb->pcb_flags = 0;
1.276 mycroft 1699: pcb->pcb_savefpu.sv_env.en_cw = __NetBSD_NPXCW__;
1.59 mycroft 1700:
1.154 mycroft 1701: tf = p->p_md.md_regs;
1.178 mycroft 1702: __asm("movl %w0,%%gs" : : "r" (LSEL(LUDATA_SEL, SEL_UPL)));
1703: __asm("movl %w0,%%fs" : : "r" (LSEL(LUDATA_SEL, SEL_UPL)));
1.154 mycroft 1704: tf->tf_es = LSEL(LUDATA_SEL, SEL_UPL);
1705: tf->tf_ds = LSEL(LUDATA_SEL, SEL_UPL);
1.252 mycroft 1706: tf->tf_edi = 0;
1707: tf->tf_esi = 0;
1.154 mycroft 1708: tf->tf_ebp = 0;
1.160 mycroft 1709: tf->tf_ebx = (int)PS_STRINGS;
1.252 mycroft 1710: tf->tf_edx = 0;
1711: tf->tf_ecx = 0;
1712: tf->tf_eax = 0;
1.154 mycroft 1713: tf->tf_eip = pack->ep_entry;
1714: tf->tf_cs = LSEL(LUCODE_SEL, SEL_UPL);
1715: tf->tf_eflags = PSL_USERSET;
1716: tf->tf_esp = stack;
1717: tf->tf_ss = LSEL(LUDATA_SEL, SEL_UPL);
1.1 cgd 1718: }
1719:
1720: /*
1.55 brezak 1721: * Initialize segments and descriptor tables
1.1 cgd 1722: */
1723:
1.275 mycroft 1724: union descriptor *idt, *gdt, *ldt;
1725: #ifdef I586_CPU
1726: union descriptor *pentium_idt;
1727: #endif
1.178 mycroft 1728: extern struct user *proc0paddr;
1.49 brezak 1729:
1.178 mycroft 1730: void
1731: setgate(gd, func, args, type, dpl)
1732: struct gate_descriptor *gd;
1733: void *func;
1734: int args, type, dpl;
1735: {
1.1 cgd 1736:
1.178 mycroft 1737: gd->gd_looffset = (int)func;
1738: gd->gd_selector = GSEL(GCODE_SEL, SEL_KPL);
1739: gd->gd_stkcpy = args;
1740: gd->gd_xx = 0;
1741: gd->gd_type = type;
1742: gd->gd_dpl = dpl;
1743: gd->gd_p = 1;
1744: gd->gd_hioffset = (int)func >> 16;
1745: }
1746:
1747: void
1748: setregion(rd, base, limit)
1749: struct region_descriptor *rd;
1750: void *base;
1751: size_t limit;
1752: {
1753:
1754: rd->rd_limit = (int)limit;
1755: rd->rd_base = (int)base;
1756: }
1.1 cgd 1757:
1.174 mycroft 1758: void
1759: setsegment(sd, base, limit, type, dpl, def32, gran)
1760: struct segment_descriptor *sd;
1761: void *base;
1762: size_t limit;
1763: int type, dpl, def32, gran;
1764: {
1.1 cgd 1765:
1.174 mycroft 1766: sd->sd_lolimit = (int)limit;
1767: sd->sd_lobase = (int)base;
1768: sd->sd_type = type;
1769: sd->sd_dpl = dpl;
1770: sd->sd_p = 1;
1771: sd->sd_hilimit = (int)limit >> 16;
1772: sd->sd_xx = 0;
1773: sd->sd_def32 = def32;
1774: sd->sd_gran = gran;
1775: sd->sd_hibase = (int)base >> 24;
1776: }
1.1 cgd 1777:
1778: #define IDTVEC(name) __CONCAT(X, name)
1.299 mycroft 1779: typedef void (vector) __P((void));
1780: extern vector IDTVEC(syscall);
1781: extern vector IDTVEC(osyscall);
1782: extern vector *IDTVEC(exceptions)[];
1.333 christos 1783: #ifdef COMPAT_SVR4
1784: extern vector IDTVEC(svr4_fasttrap);
1785: #endif /* COMPAT_SVR4 */
1.1 cgd 1786:
1.381 thorpej 1787: #define KBTOB(x) ((size_t)(x) * 1024UL)
1788:
1.59 mycroft 1789: void
1.43 brezak 1790: init386(first_avail)
1.314 thorpej 1791: vaddr_t first_avail;
1.2 cgd 1792: {
1.148 mycroft 1793: extern void consinit __P((void));
1.375 drochner 1794: extern struct extent *iomem_ex;
1.401 thorpej 1795: struct btinfo_memmap *bim;
1.381 thorpej 1796: struct region_descriptor region;
1.401 thorpej 1797: int x, first16q;
1798: u_int64_t seg_start, seg_end;
1799: u_int64_t seg_start1, seg_end1;
1.1 cgd 1800:
1801: proc0.p_addr = proc0paddr;
1.284 mrg 1802: curpcb = &proc0.p_addr->u_pcb;
1.275 mycroft 1803:
1.375 drochner 1804: i386_bus_space_init();
1.204 thorpej 1805:
1.84 cgd 1806: consinit(); /* XXX SHOULD NOT BE DONE HERE */
1.1 cgd 1807:
1.401 thorpej 1808: /*
1809: * Initailize PAGE_SIZE-dependent variables.
1810: */
1811: uvm_setpagesize();
1.275 mycroft 1812:
1.401 thorpej 1813: /*
1814: * A quick sanity check.
1815: */
1816: if (PAGE_SIZE != NBPG)
1817: panic("init386: PAGE_SIZE != NBPG");
1818:
1.414 thorpej 1819: #if NBIOSCALL > 0
1820: avail_start = 3*PAGE_SIZE; /* save us a page for trampoline code and
1821: one additional PT page! */
1822: #else
1823: avail_start = PAGE_SIZE; /* BIOS leaves data in low memory */
1824: /* and VM system doesn't work with phys 0 */
1825: #endif
1826:
1.401 thorpej 1827: /*
1828: * Call pmap initialization to make new kernel address space.
1829: * We must do this before loading pages into the VM system.
1830: */
1.314 thorpej 1831: pmap_bootstrap((vaddr_t)atdevbase + IOM_SIZE);
1.2 cgd 1832:
1.401 thorpej 1833: /*
1834: * Check to see if we have a memory map from the BIOS (passed
1835: * to us by the boot program.
1836: */
1837: bim = lookup_bootinfo(BTINFO_MEMMAP);
1.407 enami 1838: if (bim != NULL && bim->num > 0) {
1.409 kim 1839: #if DEBUG_MEMLOAD
1.401 thorpej 1840: printf("BIOS MEMORY MAP (%d ENTRIES):\n", bim->num);
1841: #endif
1842: for (x = 0; x < bim->num; x++) {
1.409 kim 1843: #if DEBUG_MEMLOAD
1.401 thorpej 1844: printf(" addr 0x%qx size 0x%qx type 0x%x\n",
1845: bim->entry[x].addr,
1846: bim->entry[x].size,
1847: bim->entry[x].type);
1848: #endif
1849:
1850: /*
1851: * If the segment is not memory, skip it.
1852: */
1853: switch (bim->entry[x].type) {
1854: case BIM_Memory:
1855: case BIM_ACPI:
1856: case BIM_NVS:
1857: break;
1858: default:
1859: continue;
1860: }
1861:
1862: /*
1863: * Sanity check the entry.
1864: * XXX Need to handle uint64_t in extent code
1865: * XXX and 64-bit physical addresses in i386
1866: * XXX port.
1867: */
1868: seg_start = bim->entry[x].addr;
1869: seg_end = bim->entry[x].addr + bim->entry[x].size;
1870:
1871: if (seg_end > 0x100000000ULL) {
1872: printf("WARNING: skipping large "
1873: "memory map entry: "
1874: "0x%qx/0x%qx/0x%x\n",
1875: bim->entry[x].addr,
1876: bim->entry[x].size,
1877: bim->entry[x].type);
1878: continue;
1879: }
1880:
1881: /*
1882: * XXX Chop the last page off the size so that
1883: * XXX it can fit in avail_end.
1884: */
1885: if (seg_end == 0x100000000ULL)
1886: seg_end -= PAGE_SIZE;
1887:
1888: /*
1889: * Allocate the physical addresses used by RAM
1890: * from the iomem extent map. This is done before
1891: * the addresses are page rounded just to make
1892: * sure we get them all.
1893: */
1894: if (extent_alloc_region(iomem_ex, seg_start,
1895: seg_end - seg_start, EX_NOWAIT)) {
1896: /* XXX What should we do? */
1897: printf("WARNING: CAN'T ALLOCATE "
1898: "MEMORY SEGMENT %d "
1899: "(0x%qx/0x%qx/0x%x) FROM "
1900: "IOMEM EXTENT MAP!\n",
1901: x, seg_start, seg_end - seg_start,
1902: bim->entry[x].type);
1903: }
1904:
1905: /*
1906: * If it's not free memory, skip it.
1907: */
1908: if (bim->entry[x].type != BIM_Memory)
1909: continue;
1910:
1911: /* XXX XXX XXX */
1912: if (mem_cluster_cnt >= VM_PHYSSEG_MAX)
1913: panic("init386: too many memory segments");
1914:
1915: seg_start = round_page(seg_start);
1916: seg_end = trunc_page(seg_end);
1917:
1918: if (seg_start == seg_end)
1919: continue;
1920:
1921: mem_clusters[mem_cluster_cnt].start = seg_start;
1922: mem_clusters[mem_cluster_cnt].size =
1923: seg_end - seg_start;
1924:
1925: if (avail_end < seg_end)
1926: avail_end = seg_end;
1927: physmem += atop(mem_clusters[mem_cluster_cnt].size);
1928: mem_cluster_cnt++;
1929: }
1.421 aymeric 1930: }
1931:
1932: /*
1933: * If the loop above didn't find any valid segment, fall back to
1934: * former code.
1935: */
1936: if (mem_cluster_cnt == 0) {
1.401 thorpej 1937: /*
1938: * Allocate the physical addresses used by RAM from the iomem
1939: * extent map. This is done before the addresses are
1940: * page rounded just to make sure we get them all.
1941: */
1942: if (extent_alloc_region(iomem_ex, 0, KBTOB(biosbasemem),
1943: EX_NOWAIT)) {
1944: /* XXX What should we do? */
1945: printf("WARNING: CAN'T ALLOCATE BASE MEMORY FROM "
1946: "IOMEM EXTENT MAP!\n");
1947: }
1948: mem_clusters[0].start = 0;
1949: mem_clusters[0].size = trunc_page(KBTOB(biosbasemem));
1950: physmem += atop(mem_clusters[0].size);
1951: if (extent_alloc_region(iomem_ex, IOM_END, KBTOB(biosextmem),
1952: EX_NOWAIT)) {
1953: /* XXX What should we do? */
1954: printf("WARNING: CAN'T ALLOCATE EXTENDED MEMORY FROM "
1955: "IOMEM EXTENT MAP!\n");
1956: }
1957: #if NISADMA > 0
1958: /*
1959: * Some motherboards/BIOSes remap the 384K of RAM that would
1960: * normally be covered by the ISA hole to the end of memory
1961: * so that it can be used. However, on a 16M system, this
1962: * would cause bounce buffers to be allocated and used.
1963: * This is not desirable behaviour, as more than 384K of
1964: * bounce buffers might be allocated. As a work-around,
1965: * we round memory down to the nearest 1M boundary if
1966: * we're using any isadma devices and the remapped memory
1967: * is what puts us over 16M.
1968: */
1969: if (biosextmem > (15*1024) && biosextmem < (16*1024)) {
1970: char pbuf[9];
1971:
1972: format_bytes(pbuf, sizeof(pbuf),
1973: biosextmem - (15*1024));
1974: printf("Warning: ignoring %s of remapped memory\n",
1975: pbuf);
1976: biosextmem = (15*1024);
1977: }
1978: #endif
1979: mem_clusters[1].start = IOM_END;
1980: mem_clusters[1].size = trunc_page(KBTOB(biosextmem));
1981: physmem += atop(mem_clusters[1].size);
1982:
1983: mem_cluster_cnt = 2;
1984:
1985: avail_end = IOM_END + trunc_page(KBTOB(biosextmem));
1986: }
1987:
1988: /*
1989: * If we have 16M of RAM or less, just put it all on
1990: * the default free list. Otherwise, put the first
1991: * 16M of RAM on a lower priority free list (so that
1992: * all of the ISA DMA'able memory won't be eaten up
1993: * first-off).
1994: */
1995: if (avail_end <= (16 * 1024 * 1024))
1996: first16q = VM_FREELIST_DEFAULT;
1997: else
1998: first16q = VM_FREELIST_FIRST16;
1999:
2000: /* Make sure the end of the space used by the kernel is rounded. */
2001: first_avail = round_page(first_avail);
2002:
2003: /*
2004: * Now, load the memory clusters (which have already been
2005: * rounded and truncated) into the VM system.
2006: *
2007: * NOTE: WE ASSUME THAT MEMORY STARTS AT 0 AND THAT THE KERNEL
2008: * IS LOADED AT IOM_END (1M).
2009: */
2010: for (x = 0; x < mem_cluster_cnt; x++) {
2011: seg_start = mem_clusters[x].start;
2012: seg_end = mem_clusters[x].start + mem_clusters[x].size;
2013: seg_start1 = 0;
2014: seg_end1 = 0;
2015:
2016: /*
2017: * Skip memory before our available starting point.
2018: */
2019: if (seg_end <= avail_start)
2020: continue;
2021:
2022: if (avail_start >= seg_start && avail_start < seg_end) {
2023: if (seg_start != 0)
2024: panic("init386: memory doesn't start at 0");
2025: seg_start = avail_start;
2026: if (seg_start == seg_end)
2027: continue;
2028: }
2029:
2030: /*
2031: * If this segment contains the kernel, split it
2032: * in two, around the kernel.
2033: */
2034: if (seg_start <= IOM_END && first_avail <= seg_end) {
2035: seg_start1 = first_avail;
2036: seg_end1 = seg_end;
2037: seg_end = IOM_END;
2038: }
2039:
2040: /* First hunk */
2041: if (seg_start != seg_end) {
2042: if (seg_start <= (16 * 1024 * 1024) &&
2043: first16q != VM_FREELIST_DEFAULT) {
2044: u_int64_t tmp;
2045:
2046: if (seg_end > (16 * 1024 * 1024))
2047: tmp = (16 * 1024 * 1024);
2048: else
2049: tmp = seg_end;
1.409 kim 2050: #if DEBUG_MEMLOAD
1.401 thorpej 2051: printf("loading 0x%qx-0x%qx (0x%lx-0x%lx)\n",
2052: seg_start, tmp,
2053: atop(seg_start), atop(tmp));
2054: #endif
2055: uvm_page_physload(atop(seg_start),
2056: atop(tmp), atop(seg_start),
2057: atop(tmp), first16q);
2058: seg_start = tmp;
2059: }
1.411 enami 2060:
2061: if (seg_start != seg_end) {
1.409 kim 2062: #if DEBUG_MEMLOAD
1.411 enami 2063: printf("loading 0x%qx-0x%qx (0x%lx-0x%lx)\n",
2064: seg_start, seg_end,
2065: atop(seg_start), atop(seg_end));
2066: #endif
2067: uvm_page_physload(atop(seg_start),
2068: atop(seg_end), atop(seg_start),
2069: atop(seg_end), VM_FREELIST_DEFAULT);
2070: }
1.401 thorpej 2071: }
2072:
2073: /* Second hunk */
2074: if (seg_start1 != seg_end1) {
2075: if (seg_start1 <= (16 * 1024 * 1024) &&
2076: first16q != VM_FREELIST_DEFAULT) {
2077: u_int64_t tmp;
2078:
2079: if (seg_end1 > (16 * 1024 * 1024))
2080: tmp = (16 * 1024 * 1024);
2081: else
2082: tmp = seg_end1;
1.409 kim 2083: #if DEBUG_MEMLOAD
1.401 thorpej 2084: printf("loading 0x%qx-0x%qx (0x%lx-0x%lx)\n",
2085: seg_start1, tmp,
2086: atop(seg_start1), atop(tmp));
2087: #endif
2088: uvm_page_physload(atop(seg_start1),
2089: atop(tmp), atop(seg_start1),
2090: atop(tmp), first16q);
2091: seg_start1 = tmp;
2092: }
1.412 enami 2093:
2094: if (seg_start1 != seg_end1) {
1.409 kim 2095: #if DEBUG_MEMLOAD
1.412 enami 2096: printf("loading 0x%qx-0x%qx (0x%lx-0x%lx)\n",
2097: seg_start1, seg_end1,
2098: atop(seg_start1), atop(seg_end1));
2099: #endif
2100: uvm_page_physload(atop(seg_start1),
2101: atop(seg_end1), atop(seg_start1),
2102: atop(seg_end1), VM_FREELIST_DEFAULT);
2103: }
1.401 thorpej 2104: }
2105: }
2106:
2107: /*
2108: * Steal memory for the message buffer (at end of core).
2109: */
2110: {
2111: struct vm_physseg *vps;
2112: psize_t sz = round_page(MSGBUFSIZE);
2113: psize_t reqsz = sz;
2114:
2115: for (x = 0; x < vm_nphysseg; x++) {
2116: vps = &vm_physmem[x];
2117: if (ptoa(vps->avail_end) == avail_end)
2118: break;
2119: }
2120: if (x == vm_nphysseg)
1.410 christos 2121: panic("init386: can't find end of memory");
1.401 thorpej 2122:
2123: /* Shrink so it'll fit in the last segment. */
2124: if ((vps->avail_end - vps->avail_start) < atop(sz))
2125: sz = ptoa(vps->avail_end - vps->avail_start);
2126:
2127: vps->avail_end -= atop(sz);
2128: vps->end -= atop(sz);
2129: msgbuf_paddr = ptoa(vps->avail_end);
2130:
2131: /* Remove the last segment if it now has no pages. */
2132: if (vps->start == vps->end) {
2133: for (vm_nphysseg--; x < vm_nphysseg; x++)
2134: vm_physmem[x] = vm_physmem[x + 1];
2135: }
2136:
2137: /* Now find where the new avail_end is. */
2138: for (avail_end = 0, x = 0; x < vm_nphysseg; x++)
2139: if (vm_physmem[x].avail_end > avail_end)
2140: avail_end = vm_physmem[x].avail_end;
2141: avail_end = ptoa(avail_end);
2142:
2143: /* Warn if the message buffer had to be shrunk. */
2144: if (sz != reqsz)
2145: printf("WARNING: %ld bytes not available for msgbuf "
2146: "in last cluster (%ld used)\n", reqsz, sz);
2147: }
2148:
1.295 drochner 2149: #if NBIOSCALL > 0
2150: /* install page 2 (reserved above) as PT page for first 4M */
1.414 thorpej 2151: pmap_enter(pmap_kernel(), (vaddr_t)vtopte(0), 2*PAGE_SIZE,
1.367 thorpej 2152: VM_PROT_READ|VM_PROT_WRITE, PMAP_WIRED|VM_PROT_READ|VM_PROT_WRITE);
1.414 thorpej 2153: memset(vtopte(0), 0, PAGE_SIZE);/* make sure it is clean before using */
1.295 drochner 2154: #endif
1.59 mycroft 2155:
1.346 mycroft 2156: pmap_enter(pmap_kernel(), idt_vaddr, idt_paddr,
1.367 thorpej 2157: VM_PROT_READ|VM_PROT_WRITE, PMAP_WIRED|VM_PROT_READ|VM_PROT_WRITE);
1.275 mycroft 2158: idt = (union descriptor *)idt_vaddr;
2159: #ifdef I586_CPU
1.346 mycroft 2160: pmap_enter(pmap_kernel(), pentium_idt_vaddr, idt_paddr,
1.367 thorpej 2161: VM_PROT_READ, PMAP_WIRED|VM_PROT_READ);
1.275 mycroft 2162: pentium_idt = (union descriptor *)pentium_idt_vaddr;
2163: #endif
2164: gdt = idt + NIDT;
2165: ldt = gdt + NGDT;
2166:
2167:
2168: /* make gdt gates and memory segments */
2169: setsegment(&gdt[GCODE_SEL].sd, 0, 0xfffff, SDT_MEMERA, SEL_KPL, 1, 1);
2170: setsegment(&gdt[GDATA_SEL].sd, 0, 0xfffff, SDT_MEMRWA, SEL_KPL, 1, 1);
2171: setsegment(&gdt[GLDT_SEL].sd, ldt, NLDT * sizeof(ldt[0]) - 1,
2172: SDT_SYSLDT, SEL_KPL, 0, 0);
2173: setsegment(&gdt[GUCODE_SEL].sd, 0, i386_btop(VM_MAXUSER_ADDRESS) - 1,
2174: SDT_MEMERA, SEL_UPL, 1, 1);
2175: setsegment(&gdt[GUDATA_SEL].sd, 0, i386_btop(VM_MAXUSER_ADDRESS) - 1,
2176: SDT_MEMRWA, SEL_UPL, 1, 1);
2177: #if NBIOSCALL > 0
2178: /* bios trampoline GDT entries */
2179: setsegment(&gdt[GBIOSCODE_SEL].sd, 0, 0xfffff, SDT_MEMERA, SEL_KPL, 0,
2180: 0);
2181: setsegment(&gdt[GBIOSDATA_SEL].sd, 0, 0xfffff, SDT_MEMRWA, SEL_KPL, 0,
2182: 0);
2183: #endif
2184:
2185: /* make ldt gates and memory segments */
2186: setgate(&ldt[LSYS5CALLS_SEL].gd, &IDTVEC(osyscall), 1,
2187: SDT_SYS386CGT, SEL_UPL);
2188: ldt[LUCODE_SEL] = gdt[GUCODE_SEL];
2189: ldt[LUDATA_SEL] = gdt[GUDATA_SEL];
1.324 christos 2190: ldt[LSOL26CALLS_SEL] = ldt[LBSDICALLS_SEL] = ldt[LSYS5CALLS_SEL];
1.275 mycroft 2191:
2192: /* exceptions */
2193: for (x = 0; x < 32; x++)
2194: setgate(&idt[x].gd, IDTVEC(exceptions)[x], 0, SDT_SYS386TGT,
2195: (x == 3 || x == 4) ? SEL_UPL : SEL_KPL);
1.257 thorpej 2196:
1.275 mycroft 2197: /* new-style interrupt gate for syscalls */
2198: setgate(&idt[128].gd, &IDTVEC(syscall), 0, SDT_SYS386TGT, SEL_UPL);
1.333 christos 2199: #ifdef COMPAT_SVR4
2200: setgate(&idt[0xd2].gd, &IDTVEC(svr4_fasttrap), 0, SDT_SYS386TGT,
2201: SEL_UPL);
2202: #endif /* COMPAT_SVR4 */
1.264 mycroft 2203:
1.275 mycroft 2204: setregion(®ion, gdt, NGDT * sizeof(gdt[0]) - 1);
2205: lgdt(®ion);
1.264 mycroft 2206: #ifdef I586_CPU
1.275 mycroft 2207: setregion(®ion, pentium_idt, NIDT * sizeof(idt[0]) - 1);
2208: #else
2209: setregion(®ion, idt, NIDT * sizeof(idt[0]) - 1);
2210: #endif
2211: lidt(®ion);
1.264 mycroft 2212:
1.190 mycroft 2213:
2214: #ifdef DDB
1.308 tv 2215: {
2216: extern int end;
2217: extern int *esym;
1.336 christos 2218: struct btinfo_symtab *symtab;
1.308 tv 2219:
1.336 christos 2220: symtab = lookup_bootinfo(BTINFO_SYMTAB);
2221: if (symtab) {
2222: symtab->ssym += KERNBASE;
2223: symtab->esym += KERNBASE;
2224: ddb_init(symtab->nsym, (int *)symtab->ssym,
2225: (int *)symtab->esym);
2226: }
2227: else
2228: ddb_init(*(int *)&end, ((int *)&end) + 1, esym);
1.308 tv 2229: }
1.190 mycroft 2230: if (boothowto & RB_KDB)
2231: Debugger();
1.377 ws 2232: #endif
2233: #ifdef IPKDB
2234: ipkdb_init();
2235: if (boothowto & RB_KDB)
2236: ipkdb_connect(0);
1.190 mycroft 2237: #endif
2238: #ifdef KGDB
1.243 drochner 2239: kgdb_port_init();
1.235 thorpej 2240: if (boothowto & RB_KDB) {
2241: kgdb_debug_init = 1;
1.242 drochner 2242: kgdb_connect(1);
1.235 thorpej 2243: }
1.384 jdolecek 2244: #endif
2245:
2246: #if NMCA > 0
2247: /* check for MCA bus, needed to be done before ISA stuff - if
2248: * MCA is detected, ISA needs to use level triggered interrupts
2249: * by default */
2250: mca_busprobe();
1.190 mycroft 2251: #endif
1.275 mycroft 2252:
2253: #if NISA > 0
2254: isa_defaultirq();
2255: #endif
2256:
2257: splraise(-1);
2258: enable_intr();
2259:
2260: if (physmem < btoc(2 * 1024 * 1024)) {
2261: printf("warning: too little memory available; "
1.383 mycroft 2262: "have %lu bytes, want %lu bytes\n"
1.275 mycroft 2263: "running in degraded mode\n"
2264: "press a key to confirm\n\n",
1.383 mycroft 2265: ptoa(physmem), 2*1024*1024UL);
1.275 mycroft 2266: cngetc();
2267: }
1.393 fvdl 2268:
2269: identifycpu();
1.1 cgd 2270: }
2271:
1.94 mycroft 2272: struct queue {
2273: struct queue *q_next, *q_prev;
2274: };
2275:
1.1 cgd 2276: /*
1.73 mycroft 2277: * insert an element into a queue
1.1 cgd 2278: */
1.94 mycroft 2279: void
1.188 christos 2280: _insque(v1, v2)
2281: void *v1;
2282: void *v2;
1.94 mycroft 2283: {
1.298 mycroft 2284: struct queue *elem = v1, *head = v2;
2285: struct queue *next;
1.94 mycroft 2286:
2287: next = head->q_next;
2288: elem->q_next = next;
2289: head->q_next = elem;
2290: elem->q_prev = head;
2291: next->q_prev = elem;
1.1 cgd 2292: }
2293:
2294: /*
2295: * remove an element from a queue
2296: */
1.94 mycroft 2297: void
1.188 christos 2298: _remque(v)
2299: void *v;
1.94 mycroft 2300: {
1.298 mycroft 2301: struct queue *elem = v;
2302: struct queue *next, *prev;
1.94 mycroft 2303:
2304: next = elem->q_next;
2305: prev = elem->q_prev;
2306: next->q_prev = prev;
2307: prev->q_next = next;
2308: elem->q_prev = 0;
1.1 cgd 2309: }
2310:
1.107 deraadt 2311: #ifdef COMPAT_NOMID
2312: static int
2313: exec_nomid(p, epp)
1.59 mycroft 2314: struct proc *p;
2315: struct exec_package *epp;
1.31 cgd 2316: {
1.59 mycroft 2317: int error;
2318: u_long midmag, magic;
2319: u_short mid;
1.80 cgd 2320: struct exec *execp = epp->ep_hdr;
1.31 cgd 2321:
1.80 cgd 2322: /* check on validity of epp->ep_hdr performed by exec_out_makecmds */
2323:
2324: midmag = ntohl(execp->a_midmag);
1.59 mycroft 2325: mid = (midmag >> 16) & 0xffff;
2326: magic = midmag & 0xffff;
2327:
2328: if (magic == 0) {
1.80 cgd 2329: magic = (execp->a_midmag & 0xffff);
1.59 mycroft 2330: mid = MID_ZERO;
2331: }
2332:
2333: midmag = mid << 16 | magic;
2334:
2335: switch (midmag) {
2336: case (MID_ZERO << 16) | ZMAGIC:
2337: /*
2338: * 386BSD's ZMAGIC format:
2339: */
1.202 christos 2340: error = exec_aout_prep_oldzmagic(p, epp);
1.59 mycroft 2341: break;
2342:
2343: case (MID_ZERO << 16) | QMAGIC:
2344: /*
2345: * BSDI's QMAGIC format:
2346: * same as new ZMAGIC format, but with different magic number
2347: */
2348: error = exec_aout_prep_zmagic(p, epp);
2349: break;
2350:
1.202 christos 2351: case (MID_ZERO << 16) | NMAGIC:
2352: /*
2353: * BSDI's NMAGIC format:
2354: * same as NMAGIC format, but with different magic number
2355: * and with text starting at 0.
2356: */
2357: error = exec_aout_prep_oldnmagic(p, epp);
2358: break;
2359:
2360: case (MID_ZERO << 16) | OMAGIC:
2361: /*
2362: * BSDI's OMAGIC format:
2363: * same as OMAGIC format, but with different magic number
2364: * and with text starting at 0.
2365: */
2366: error = exec_aout_prep_oldomagic(p, epp);
2367: break;
2368:
1.59 mycroft 2369: default:
2370: error = ENOEXEC;
2371: }
2372:
2373: return error;
1.107 deraadt 2374: }
1.31 cgd 2375: #endif
1.107 deraadt 2376:
2377: /*
2378: * cpu_exec_aout_makecmds():
2379: * cpu-dependent a.out format hook for execve().
2380: *
2381: * Determine of the given exec package refers to something which we
2382: * understand and, if so, set up the vmcmds for it.
2383: *
2384: * On the i386, old (386bsd) ZMAGIC binaries and BSDI QMAGIC binaries
2385: * if COMPAT_NOMID is given as a kernel option.
2386: */
2387: int
2388: cpu_exec_aout_makecmds(p, epp)
2389: struct proc *p;
2390: struct exec_package *epp;
2391: {
2392: int error = ENOEXEC;
2393:
2394: #ifdef COMPAT_NOMID
2395: if ((error = exec_nomid(p, epp)) == 0)
2396: return error;
2397: #endif /* ! COMPAT_NOMID */
2398:
2399: return error;
1.31 cgd 2400: }
1.84 cgd 2401:
1.255 drochner 2402: void *
2403: lookup_bootinfo(type)
2404: int type;
2405: {
2406: struct btinfo_common *help;
2407: int n = *(int*)bootinfo;
2408: help = (struct btinfo_common *)(bootinfo + sizeof(int));
2409: while(n--) {
2410: if(help->type == type)
2411: return(help);
2412: help = (struct btinfo_common *)((char*)help + help->len);
2413: }
2414: return(0);
2415: }
1.149 mycroft 2416:
2417: void
2418: cpu_reset()
2419: {
2420:
1.224 mycroft 2421: disable_intr();
2422:
1.227 mycroft 2423: /*
2424: * The keyboard controller has 4 random output pins, one of which is
2425: * connected to the RESET pin on the CPU in many PCs. We tell the
2426: * keyboard controller to pulse this line a couple of times.
2427: */
1.273 drochner 2428: outb(IO_KBD + KBCMDP, KBC_PULSE0);
1.226 mycroft 2429: delay(100000);
1.273 drochner 2430: outb(IO_KBD + KBCMDP, KBC_PULSE0);
1.226 mycroft 2431: delay(100000);
1.149 mycroft 2432:
2433: /*
1.224 mycroft 2434: * Try to cause a triple fault and watchdog reset by making the IDT
2435: * invalid and causing a fault.
1.149 mycroft 2436: */
1.313 perry 2437: memset((caddr_t)idt, 0, NIDT * sizeof(idt[0]));
1.224 mycroft 2438: __asm __volatile("divl %0,%1" : : "q" (0), "a" (0));
1.149 mycroft 2439:
1.224 mycroft 2440: #if 0
1.149 mycroft 2441: /*
2442: * Try to cause a triple fault and watchdog reset by unmapping the
1.224 mycroft 2443: * entire address space and doing a TLB flush.
1.149 mycroft 2444: */
1.414 thorpej 2445: memset((caddr_t)PTD, 0, PAGE_SIZE);
1.149 mycroft 2446: pmap_update();
1.224 mycroft 2447: #endif
1.149 mycroft 2448:
2449: for (;;);
1.45 cgd 2450: }
CVSweb <webmaster@jp.NetBSD.org>