Annotation of src/sys/arch/i386/i386/machdep.c, Revision 1.162
1.162 ! mycroft 1: /* $NetBSD: machdep.c,v 1.161 1995/05/18 18:59:16 mycroft Exp $ */
1.125 cgd 2:
1.1 cgd 3: /*-
1.148 mycroft 4: * Copyright (c) 1993, 1994, 1995 Charles M. Hannum. All rights reserved.
1.35 cgd 5: * Copyright (c) 1992 Terrence R. Lambert.
1.1 cgd 6: * Copyright (c) 1982, 1987, 1990 The Regents of the University of California.
7: * All rights reserved.
8: *
9: * This code is derived from software contributed to Berkeley by
10: * William Jolitz.
11: *
12: * Redistribution and use in source and binary forms, with or without
13: * modification, are permitted provided that the following conditions
14: * are met:
15: * 1. Redistributions of source code must retain the above copyright
16: * notice, this list of conditions and the following disclaimer.
17: * 2. Redistributions in binary form must reproduce the above copyright
18: * notice, this list of conditions and the following disclaimer in the
19: * documentation and/or other materials provided with the distribution.
20: * 3. All advertising materials mentioning features or use of this software
21: * must display the following acknowledgement:
22: * This product includes software developed by the University of
23: * California, Berkeley and its contributors.
24: * 4. Neither the name of the University nor the names of its contributors
25: * may be used to endorse or promote products derived from this software
26: * without specific prior written permission.
27: *
28: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38: * SUCH DAMAGE.
39: *
1.125 cgd 40: * @(#)machdep.c 7.4 (Berkeley) 6/3/91
1.1 cgd 41: */
42:
1.59 mycroft 43: #include <sys/param.h>
44: #include <sys/systm.h>
45: #include <sys/signalvar.h>
46: #include <sys/kernel.h>
47: #include <sys/map.h>
48: #include <sys/proc.h>
49: #include <sys/user.h>
50: #include <sys/exec.h>
51: #include <sys/buf.h>
52: #include <sys/reboot.h>
53: #include <sys/conf.h>
54: #include <sys/file.h>
55: #include <sys/callout.h>
56: #include <sys/malloc.h>
57: #include <sys/mbuf.h>
58: #include <sys/msgbuf.h>
59: #include <sys/mount.h>
60: #include <sys/vnode.h>
1.92 mycroft 61: #include <sys/device.h>
1.104 cgd 62: #include <sys/sysctl.h>
1.123 cgd 63: #include <sys/syscallargs.h>
1.57 cgd 64: #ifdef SYSVMSG
1.59 mycroft 65: #include <sys/msg.h>
1.57 cgd 66: #endif
67: #ifdef SYSVSEM
1.59 mycroft 68: #include <sys/sem.h>
69: #endif
70: #ifdef SYSVSHM
71: #include <sys/shm.h>
1.57 cgd 72: #endif
73:
1.104 cgd 74: #include <dev/cons.h>
75:
1.59 mycroft 76: #include <vm/vm.h>
77: #include <vm/vm_kern.h>
78: #include <vm/vm_page.h>
1.31 cgd 79:
1.59 mycroft 80: #include <machine/cpu.h>
81: #include <machine/cpufunc.h>
1.149 mycroft 82: #include <machine/pio.h>
1.59 mycroft 83: #include <machine/psl.h>
84: #include <machine/reg.h>
85: #include <machine/specialreg.h>
1.43 brezak 86:
1.146 cgd 87: #include <dev/isa/isareg.h>
88: #include <dev/isa/isavar.h>
1.149 mycroft 89: #include <dev/ic/i8042.h>
1.158 cgd 90: #include <dev/ic/mc146818.h>
1.146 cgd 91: #include <i386/isa/isa_machdep.h>
1.158 cgd 92: #include <i386/isa/nvram.h>
1.43 brezak 93:
1.59 mycroft 94: #include "isa.h"
95: #include "npx.h"
1.161 mycroft 96: #if NNPX > 0
97: extern struct proc *npxproc;
98: #endif
1.2 cgd 99:
1.104 cgd 100: /* the following is used externally (sysctl_hw) */
101: char machine[] = "i386"; /* cpu "architecture" */
102:
1.1 cgd 103: /*
104: * Declare these as initialized data so we can patch them.
105: */
106: int nswbuf = 0;
107: #ifdef NBUF
108: int nbuf = NBUF;
109: #else
110: int nbuf = 0;
111: #endif
112: #ifdef BUFPAGES
113: int bufpages = BUFPAGES;
114: #else
115: int bufpages = 0;
116: #endif
117:
1.59 mycroft 118: int physmem;
119: int boothowto;
120: int cpu_class;
121:
122: struct msgbuf *msgbufp;
123: int msgbufmapped;
124:
125: vm_map_t buffer_map;
1.48 brezak 126:
1.59 mycroft 127: extern vm_offset_t avail_start, avail_end;
128: static vm_offset_t hole_start, hole_end;
129: static vm_offset_t avail_next;
1.1 cgd 130:
1.149 mycroft 131: caddr_t allocsys __P((caddr_t));
1.32 andrew 132: void dumpsys __P((void));
1.149 mycroft 133: void cpu_reset __P((void));
1.59 mycroft 134:
135: /*
136: * Machine-dependent startup code
137: */
1.32 andrew 138: void
1.1 cgd 139: cpu_startup()
140: {
1.59 mycroft 141: unsigned i;
142: caddr_t v;
143: int sz;
144: int base, residual;
1.1 cgd 145: vm_offset_t minaddr, maxaddr;
146: vm_size_t size;
147:
148: /*
149: * Initialize error message buffer (at end of core).
150: */
151: /* avail_end was pre-decremented in pmap_bootstrap to compensate */
1.59 mycroft 152: for (i = 0; i < btoc(sizeof(struct msgbuf)); i++)
1.143 mycroft 153: pmap_enter(pmap_kernel(),
1.108 cgd 154: (vm_offset_t)((caddr_t)msgbufp + i * NBPG),
155: avail_end + i * NBPG, VM_PROT_ALL, TRUE);
1.1 cgd 156: msgbufmapped = 1;
157:
1.6 cgd 158: printf(version);
1.16 cgd 159: identifycpu();
1.6 cgd 160: printf("real mem = %d\n", ctob(physmem));
1.1 cgd 161:
162: /*
1.59 mycroft 163: * Find out how much space we need, allocate it,
164: * and then give everything true virtual addresses.
1.1 cgd 165: */
1.59 mycroft 166: sz = (int)allocsys((caddr_t)0);
167: if ((v = (caddr_t)kmem_alloc(kernel_map, round_page(sz))) == 0)
168: panic("startup: no room for tables");
169: if (allocsys(v) - v != sz)
1.1 cgd 170: panic("startup: table size inconsistency");
1.50 cgd 171:
1.36 cgd 172: /*
173: * Now allocate buffers proper. They are different than the above
174: * in that they usually occupy more virtual memory than physical.
175: */
176: size = MAXBSIZE * nbuf;
1.68 mycroft 177: buffer_map = kmem_suballoc(kernel_map, (vm_offset_t *)&buffers,
1.108 cgd 178: &maxaddr, size, TRUE);
1.36 cgd 179: minaddr = (vm_offset_t)buffers;
180: if (vm_map_find(buffer_map, vm_object_allocate(size), (vm_offset_t)0,
181: &minaddr, size, FALSE) != KERN_SUCCESS)
182: panic("startup: cannot allocate buffers");
1.54 cgd 183: if ((bufpages / nbuf) >= btoc(MAXBSIZE)) {
184: /* don't want to alloc more physical mem than needed */
185: bufpages = btoc(MAXBSIZE) * nbuf;
186: }
1.36 cgd 187: base = bufpages / nbuf;
188: residual = bufpages % nbuf;
189: for (i = 0; i < nbuf; i++) {
190: vm_size_t curbufsize;
191: vm_offset_t curbuf;
192:
193: /*
194: * First <residual> buffers get (base+1) physical pages
195: * allocated for them. The rest get (base) physical pages.
196: *
197: * The rest of each buffer occupies virtual space,
198: * but has no physical memory allocated for it.
199: */
200: curbuf = (vm_offset_t)buffers + i * MAXBSIZE;
201: curbufsize = CLBYTES * (i < residual ? base+1 : base);
202: vm_map_pageable(buffer_map, curbuf, curbuf+curbufsize, FALSE);
203: vm_map_simplify(buffer_map, curbuf);
204: }
1.41 cgd 205:
1.1 cgd 206: /*
1.36 cgd 207: * Allocate a submap for exec arguments. This map effectively
208: * limits the number of processes exec'ing at any time.
1.1 cgd 209: */
1.59 mycroft 210: exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
1.79 mycroft 211: 16*NCARGS, TRUE);
1.59 mycroft 212:
1.1 cgd 213: /*
214: * Allocate a submap for physio
215: */
216: phys_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
217: VM_PHYS_SIZE, TRUE);
218:
219: /*
220: * Finally, allocate mbuf pool. Since mclrefcnt is an off-size
221: * we use the more space efficient malloc in place of kmem_alloc.
222: */
223: mclrefcnt = (char *)malloc(NMBCLUSTERS+CLBYTES/MCLBYTES,
224: M_MBUF, M_NOWAIT);
225: bzero(mclrefcnt, NMBCLUSTERS+CLBYTES/MCLBYTES);
1.68 mycroft 226: mb_map = kmem_suballoc(kernel_map, (vm_offset_t *)&mbutl, &maxaddr,
1.73 mycroft 227: VM_MBUF_SIZE, FALSE);
1.59 mycroft 228:
1.1 cgd 229: /*
230: * Initialize callouts
231: */
232: callfree = callout;
233: for (i = 1; i < ncallout; i++)
234: callout[i-1].c_next = &callout[i];
235:
1.98 cgd 236: printf("avail mem = %d\n", ptoa(cnt.v_free_count));
1.36 cgd 237: printf("using %d buffers containing %d bytes of memory\n",
238: nbuf, bufpages * CLBYTES);
1.1 cgd 239:
240: /*
241: * Set up buffers, so they can be used to read disk labels.
242: */
243: bufinit();
244:
245: /*
246: * Configure the system.
247: */
248: configure();
1.153 mycroft 249:
250: /*
251: * After configuring npx, etc., save the value of cr0 so it can
252: * be reloaded quickly.
253: */
254: proc0.p_addr->u_pcb.pcb_cr0 = rcr0();
1.16 cgd 255: }
256:
1.59 mycroft 257: /*
258: * Allocate space for system data structures. We are given
259: * a starting virtual address and we return a final virtual
260: * address; along the way we set each data structure pointer.
261: *
262: * We call allocsys() with 0 to find out how much space we want,
263: * allocate that much and fill it with zeroes, and then call
264: * allocsys() again with the correct base virtual address.
265: */
266: caddr_t
267: allocsys(v)
268: register caddr_t v;
269: {
270:
271: #define valloc(name, type, num) \
272: v = (caddr_t)(((name) = (type *)v) + (num))
273: #ifdef REAL_CLISTS
274: valloc(cfree, struct cblock, nclist);
275: #endif
276: valloc(callout, struct callout, ncallout);
277: valloc(swapmap, struct map, nswapmap = maxproc * 2);
278: #ifdef SYSVSHM
279: valloc(shmsegs, struct shmid_ds, shminfo.shmmni);
280: #endif
281: #ifdef SYSVSEM
282: valloc(sema, struct semid_ds, seminfo.semmni);
283: valloc(sem, struct sem, seminfo.semmns);
284: /* This is pretty disgusting! */
285: valloc(semu, int, (seminfo.semmnu * seminfo.semusz) / sizeof(int));
286: #endif
287: #ifdef SYSVMSG
288: valloc(msgpool, char, msginfo.msgmax);
289: valloc(msgmaps, struct msgmap, msginfo.msgseg);
290: valloc(msghdrs, struct msg, msginfo.msgtql);
291: valloc(msqids, struct msqid_ds, msginfo.msgmni);
292: #endif
293:
294: /*
1.77 mycroft 295: * Determine how many buffers to allocate. We use 10% of the
296: * first 2MB of memory, and 5% of the rest, with a minimum of 16
297: * buffers. We allocate 1/2 as many swap buffer headers as file
298: * i/o buffers.
1.59 mycroft 299: */
300: if (bufpages == 0)
1.77 mycroft 301: if (physmem < btoc(2 * 1024 * 1024))
302: bufpages = physmem / (10 * CLSIZE);
303: else
304: bufpages = (btoc(2 * 1024 * 1024) + physmem) /
305: (20 * CLSIZE);
1.59 mycroft 306: if (nbuf == 0) {
307: nbuf = bufpages;
308: if (nbuf < 16)
309: nbuf = 16;
310: }
311: if (nswbuf == 0) {
312: nswbuf = (nbuf / 2) &~ 1; /* force even */
313: if (nswbuf > 256)
314: nswbuf = 256; /* sanity */
315: }
316: valloc(swbuf, struct buf, nswbuf);
317: valloc(buf, struct buf, nbuf);
318: return v;
319: }
1.18 cgd 320:
1.104 cgd 321: /*
322: * Info for CTL_HW
323: */
324: char cpu_model[120];
325: extern char version[];
326:
1.18 cgd 327: struct cpu_nameclass i386_cpus[] = {
1.59 mycroft 328: { "i386SX", CPUCLASS_386 }, /* CPU_386SX */
329: { "i386DX", CPUCLASS_386 }, /* CPU_386 */
330: { "i486SX", CPUCLASS_486 }, /* CPU_486SX */
331: { "i486DX", CPUCLASS_486 }, /* CPU_486 */
332: { "Pentium", CPUCLASS_586 }, /* CPU_586 */
1.109 deraadt 333: { "Cx486DLC", CPUCLASS_486 }, /* CPU_486DLC (Cyrix) */
1.18 cgd 334: };
335:
1.59 mycroft 336: identifycpu()
1.16 cgd 337: {
1.104 cgd 338: int len;
1.86 mycroft 339: extern char cpu_vendor[];
340:
1.17 cgd 341: printf("CPU: ");
1.59 mycroft 342: #ifdef DIAGNOSTIC
343: if (cpu < 0 || cpu >= (sizeof i386_cpus/sizeof(struct cpu_nameclass)))
344: panic("unknown cpu type %d\n", cpu);
345: #endif
1.104 cgd 346: sprintf(cpu_model, "%s (", i386_cpus[cpu].cpu_name);
347: if (cpu_vendor[0] != '\0') {
348: strcat(cpu_model, cpu_vendor);
349: strcat(cpu_model, " ");
350: }
351:
1.59 mycroft 352: cpu_class = i386_cpus[cpu].cpu_class;
1.24 cgd 353: switch(cpu_class) {
1.18 cgd 354: case CPUCLASS_386:
1.104 cgd 355: strcat(cpu_model, "386");
1.17 cgd 356: break;
1.18 cgd 357: case CPUCLASS_486:
1.104 cgd 358: strcat(cpu_model, "486");
1.17 cgd 359: break;
1.18 cgd 360: case CPUCLASS_586:
1.104 cgd 361: strcat(cpu_model, "586");
1.17 cgd 362: break;
363: default:
1.104 cgd 364: strcat(cpu_model, "unknown"); /* will panic below... */
1.148 mycroft 365: break;
1.16 cgd 366: }
1.104 cgd 367: strcat(cpu_model, "-class CPU)");
368: printf("%s\n", cpu_model); /* cpu speed would be nice, but how? */
1.18 cgd 369:
1.16 cgd 370: /*
371: * Now that we have told the user what they have,
372: * let them know if that machine type isn't configured.
373: */
1.24 cgd 374: switch (cpu_class) {
1.100 mycroft 375: #if !defined(I386_CPU) && !defined(I486_CPU) && !defined(I586_CPU)
376: #error No CPU classes configured.
377: #endif
1.118 mycroft 378: #if !defined(I586_CPU)
379: case CPUCLASS_586:
380: #endif
381: #if defined(I486_CPU) && (!defined(I586_CPU))
382: printf("NOTICE: lowering CPU class to i486\n");
383: cpu_class = CPUCLASS_486;
384: break;
1.16 cgd 385: #endif
386: #if !defined(I486_CPU)
1.18 cgd 387: case CPUCLASS_486:
1.16 cgd 388: #endif
1.118 mycroft 389: #if defined(I386_CPU) && (!defined(I586_CPU) || !defined(I486_CPU))
390: printf("NOTICE: lowering CPU class to i386\n");
391: cpu_class = CPUCLASS_386;
392: break;
393: #endif
394: #if !defined(I386_CPU)
395: case CPUCLASS_386:
1.16 cgd 396: #endif
1.118 mycroft 397: #if !defined(I586_CPU) || !defined(I486_CPU) || !defined(I386_CPU)
1.100 mycroft 398: panic("CPU class not configured");
1.59 mycroft 399: #endif
1.16 cgd 400: default:
401: break;
1.121 mycroft 402: }
403:
404: if (cpu == CPU_486DLC) {
405: #ifndef CYRIX_CACHE_WORKS
406: printf("WARNING: CYRIX 486DLC CACHE UNCHANGED.\n");
407: #else
408: #ifndef CYRIX_CACHE_REALLY_WORKS
409: printf("WARNING: CYRIX 486DLC CACHE ENABLED IN HOLD-FLUSH MODE.\n");
410: #else
411: printf("WARNING: CYRIX 486DLC CACHE ENABLED.\n");
412: #endif
413: #endif
1.16 cgd 414: }
1.147 mycroft 415:
416: #if defined(I486_CPU) || defined(I586_CPU)
417: /*
418: * On a 486 or above, enable ring 0 write protection and outer ring
419: * alignment checking.
420: */
421: if (cpu_class >= CPUCLASS_486)
422: lcr0(rcr0() | CR0_WP | CR0_AM);
423: #endif
1.1 cgd 424: }
425:
1.104 cgd 426: /*
427: * machine dependent system variables.
428: */
429: cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
430: int *name;
431: u_int namelen;
432: void *oldp;
433: size_t *oldlenp;
434: void *newp;
435: size_t newlen;
436: struct proc *p;
437: {
438: dev_t consdev;
439:
440: /* all sysctl names at this level are terminal */
441: if (namelen != 1)
442: return (ENOTDIR); /* overloaded */
443:
444: switch (name[0]) {
445: case CPU_CONSDEV:
446: if (cn_tab != NULL)
447: consdev = cn_tab->cn_dev;
448: else
449: consdev = NODEV;
450: return (sysctl_rdstruct(oldp, oldlenp, newp, &consdev,
451: sizeof consdev));
452: default:
453: return (EOPNOTSUPP);
454: }
455: /* NOTREACHED */
456: }
457:
1.1 cgd 458: #ifdef PGINPROF
459: /*
1.59 mycroft 460: * Return the difference (in microseconds) between the current time and a
461: * previous time as represented by the arguments. If there is a pending
462: * clock interrupt which has not been serviced due to high ipl, return error
463: * code.
1.1 cgd 464: */
465: /*ARGSUSED*/
466: vmtime(otime, olbolt, oicr)
467: register int otime, olbolt, oicr;
468: {
469:
1.59 mycroft 470: return (((time.tv_sec-otime)*HZ + lbolt-olbolt)*(1000000/HZ));
1.1 cgd 471: }
472: #endif
473:
1.151 christos 474: #ifdef COMPAT_IBCS2
475: void
476: ibcs2_sendsig(catcher, sig, mask, code)
477: sig_t catcher;
478: int sig, mask;
479: u_long code;
480: {
481: sendsig(catcher, bsd2ibcs_sig(sig), mask, code);
482: }
483: #endif
484:
1.1 cgd 485: /*
486: * Send an interrupt to process.
487: *
488: * Stack is set up to allow sigcode stored
489: * in u. to call routine, followed by kcall
490: * to sigreturn routine below. After sigreturn
491: * resets the signal mask, the stack, and the
492: * frame pointer, it returns to the user
493: * specified pc, psl.
494: */
495: void
496: sendsig(catcher, sig, mask, code)
497: sig_t catcher;
498: int sig, mask;
1.126 cgd 499: u_long code;
1.1 cgd 500: {
501: register struct proc *p = curproc;
1.59 mycroft 502: register struct trapframe *tf;
1.82 ws 503: struct sigframe *fp, frame;
1.104 cgd 504: struct sigacts *psp = p->p_sigacts;
1.48 brezak 505: int oonstack;
1.22 cgd 506: extern char sigcode[], esigcode[];
1.1 cgd 507:
1.135 christos 508: /*
509: * Build the argument list for the signal handler.
510: */
1.151 christos 511: frame.sf_signum = sig;
1.135 christos 512:
1.154 mycroft 513: tf = p->p_md.md_regs;
1.104 cgd 514: oonstack = psp->ps_sigstk.ss_flags & SA_ONSTACK;
1.135 christos 515:
1.1 cgd 516: /*
1.82 ws 517: * Allocate space for the signal handler context.
1.1 cgd 518: */
1.105 mycroft 519: if ((psp->ps_flags & SAS_ALTSTACK) && !oonstack &&
1.104 cgd 520: (psp->ps_sigonstack & sigmask(sig))) {
521: fp = (struct sigframe *)(psp->ps_sigstk.ss_base +
522: psp->ps_sigstk.ss_size - sizeof(struct sigframe));
523: psp->ps_sigstk.ss_flags |= SA_ONSTACK;
1.1 cgd 524: } else {
1.91 mycroft 525: fp = (struct sigframe *)tf->tf_esp - 1;
1.1 cgd 526: }
527:
1.82 ws 528: frame.sf_code = code;
529: frame.sf_scp = &fp->sf_sc;
530: frame.sf_handler = catcher;
531:
532: /*
533: * Build the signal context to be used by sigreturn.
534: */
535: frame.sf_sc.sc_onstack = oonstack;
536: frame.sf_sc.sc_mask = mask;
1.157 mycroft 537: #ifdef VM86
538: if (tf->tf_eflags & PSL_VM) {
539: frame.sf_sc.sc_gs = tf->tf_vm86_gs;
540: frame.sf_sc.sc_fs = tf->tf_vm86_fs;
541: frame.sf_sc.sc_es = tf->tf_vm86_es;
542: frame.sf_sc.sc_ds = tf->tf_vm86_ds;
543: } else
544: #endif
545: {
546: __asm("movl %%gs,%w0" : "=r" (frame.sf_sc.sc_gs));
547: __asm("movl %%fs,%w0" : "=r" (frame.sf_sc.sc_fs));
548: frame.sf_sc.sc_es = tf->tf_es;
549: frame.sf_sc.sc_ds = tf->tf_ds;
550: }
1.122 mycroft 551: frame.sf_sc.sc_edi = tf->tf_edi;
552: frame.sf_sc.sc_esi = tf->tf_esi;
553: frame.sf_sc.sc_ebp = tf->tf_ebp;
554: frame.sf_sc.sc_ebx = tf->tf_ebx;
555: frame.sf_sc.sc_edx = tf->tf_edx;
556: frame.sf_sc.sc_ecx = tf->tf_ecx;
557: frame.sf_sc.sc_eax = tf->tf_eax;
558: frame.sf_sc.sc_eip = tf->tf_eip;
559: frame.sf_sc.sc_cs = tf->tf_cs;
560: frame.sf_sc.sc_eflags = tf->tf_eflags;
561: frame.sf_sc.sc_esp = tf->tf_esp;
562: frame.sf_sc.sc_ss = tf->tf_ss;
1.1 cgd 563:
1.87 mycroft 564: if (copyout(&frame, fp, sizeof(frame)) != 0) {
1.1 cgd 565: /*
566: * Process has trashed its stack; give it an illegal
567: * instruction to halt it in its tracks.
568: */
1.93 mycroft 569: sigexit(p, SIGILL);
570: /* NOTREACHED */
1.1 cgd 571: }
572:
1.73 mycroft 573: /*
1.59 mycroft 574: * Build context to run handler in.
575: */
576: tf->tf_esp = (int)fp;
577: tf->tf_eip = (int)(((char *)PS_STRINGS) - (esigcode - sigcode));
1.154 mycroft 578: #ifdef VM86
1.59 mycroft 579: tf->tf_eflags &= ~PSL_VM;
1.154 mycroft 580: #endif
581: tf->tf_cs = LSEL(LUCODE_SEL, SEL_UPL);
582: tf->tf_ds = LSEL(LUDATA_SEL, SEL_UPL);
583: tf->tf_es = LSEL(LUDATA_SEL, SEL_UPL);
584: tf->tf_ss = LSEL(LUDATA_SEL, SEL_UPL);
1.1 cgd 585: }
586:
587: /*
588: * System call to cleanup state after a signal
589: * has been taken. Reset signal mask and
590: * stack state from context left by sendsig (above).
591: * Return to previous pc and psl as specified by
592: * context left by sendsig. Check carefully to
593: * make sure that the user has not modified the
1.110 mycroft 594: * psl to gain improper privileges or to cause
1.1 cgd 595: * a machine fault.
596: */
597: sigreturn(p, uap, retval)
598: struct proc *p;
1.123 cgd 599: struct sigreturn_args /* {
600: syscallarg(struct sigcontext *) sigcntxp;
601: } */ *uap;
602: register_t *retval;
1.1 cgd 603: {
1.82 ws 604: struct sigcontext *scp, context;
1.59 mycroft 605: register struct trapframe *tf;
606:
1.154 mycroft 607: tf = p->p_md.md_regs;
1.1 cgd 608:
1.27 cgd 609: /*
1.59 mycroft 610: * The trampoline code hands us the context.
611: * It is unsafe to keep track of it ourselves, in the event that a
612: * program jumps out of a signal handler.
1.27 cgd 613: */
1.123 cgd 614: scp = SCARG(uap, sigcntxp);
1.87 mycroft 615: if (copyin((caddr_t)scp, &context, sizeof(*scp)) != 0)
1.122 mycroft 616: return (EFAULT);
1.1 cgd 617:
1.74 brezak 618: /*
1.154 mycroft 619: * Check for security violations. If we're returning to protected
620: * mode, the CPU will validate the segment registers automatically
621: * and generate a trap on violations. We handle the trap, rather
622: * than doing all of the checking here.
1.136 mycroft 623: */
624: if (((context.sc_eflags ^ tf->tf_eflags) & PSL_USERSTATIC) != 0 ||
625: ISPL(context.sc_cs) != SEL_UPL)
1.122 mycroft 626: return (EINVAL);
1.59 mycroft 627:
1.104 cgd 628: if (context.sc_onstack & 01)
629: p->p_sigacts->ps_sigstk.ss_flags |= SA_ONSTACK;
630: else
631: p->p_sigacts->ps_sigstk.ss_flags &= ~SA_ONSTACK;
1.131 mycroft 632: p->p_sigmask = context.sc_mask & ~sigcantmask;
1.49 brezak 633:
1.59 mycroft 634: /*
635: * Restore signal context.
636: */
1.157 mycroft 637: #ifdef VM86
638: if (context.sc_eflags & PSL_VM) {
639: tf->tf_vm86_gs = context.sc_gs;
640: tf->tf_vm86_fs = context.sc_fs;
641: tf->tf_vm86_es = context.sc_es;
642: tf->tf_vm86_ds = context.sc_ds;
643: } else
644: #endif
645: {
646: /* %fs and %gs were restored by the trampoline. */
647: tf->tf_es = context.sc_es;
648: tf->tf_ds = context.sc_ds;
649: }
1.122 mycroft 650: tf->tf_edi = context.sc_edi;
651: tf->tf_esi = context.sc_esi;
652: tf->tf_ebp = context.sc_ebp;
653: tf->tf_ebx = context.sc_ebx;
654: tf->tf_edx = context.sc_edx;
655: tf->tf_ecx = context.sc_ecx;
656: tf->tf_eax = context.sc_eax;
657: tf->tf_eip = context.sc_eip;
658: tf->tf_cs = context.sc_cs;
1.136 mycroft 659: tf->tf_eflags = context.sc_eflags;
1.122 mycroft 660: tf->tf_esp = context.sc_esp;
661: tf->tf_ss = context.sc_ss;
1.72 mycroft 662:
1.122 mycroft 663: return (EJUSTRETURN);
1.37 cgd 664: }
665:
1.1 cgd 666: int waittime = -1;
667: struct pcb dumppcb;
668:
1.32 andrew 669: void
1.106 mycroft 670: boot(howto)
671: register int howto;
1.1 cgd 672: {
673: extern int cold;
674:
1.106 mycroft 675: if (cold) {
1.1 cgd 676: printf("hit reset please");
677: for(;;);
678: }
1.106 mycroft 679: boothowto = howto;
1.101 cgd 680: if ((howto&RB_NOSYNC) == 0 && waittime < 0) {
1.1 cgd 681: waittime = 0;
1.150 mycroft 682: vfs_shutdown();
1.59 mycroft 683: /*
684: * If we've been adjusting the clock, the todr
685: * will be out of synch; adjust it now.
686: */
687: resettodr();
1.1 cgd 688: }
689: splhigh();
1.152 cgd 690: if (howto & RB_HALT) {
1.25 cgd 691: printf("\n");
692: printf("The operating system has halted.\n");
693: printf("Please press any key to reboot.\n\n");
1.12 cgd 694: cngetc();
1.1 cgd 695: } else {
696: if (howto & RB_DUMP) {
697: savectx(&dumppcb, 0);
1.154 mycroft 698: dumppcb.pcb_cr3 = rcr3();
1.73 mycroft 699: dumpsys();
1.1 cgd 700: }
701: }
1.110 mycroft 702: printf("rebooting...\n");
1.1 cgd 703: cpu_reset();
704: for(;;) ;
705: /*NOTREACHED*/
706: }
707:
1.116 gwr 708: /*
709: * These variables are needed by /sbin/savecore
710: */
711: u_long dumpmag = 0x8fca0101; /* magic number */
712: int dumpsize = 0; /* pages */
713: long dumplo = 0; /* blocks */
714:
715: /*
1.134 mycroft 716: * This is called by configure to set dumplo and dumpsize.
1.116 gwr 717: * Dumps always skip the first CLBYTES of disk space
718: * in case there might be a disk label stored there.
719: * If there is extra space, put dump at the end to
720: * reduce the chance that swapping trashes it.
721: */
722: void
723: dumpconf()
724: {
725: int nblks; /* size of dump area */
726: int maj;
727:
728: if (dumpdev == NODEV)
729: return;
730: maj = major(dumpdev);
731: if (maj < 0 || maj >= nblkdev)
732: panic("dumpconf: bad dumpdev=0x%x", dumpdev);
1.134 mycroft 733: if (bdevsw[maj].d_psize == NULL)
1.116 gwr 734: return;
1.134 mycroft 735: nblks = (*bdevsw[maj].d_psize)(dumpdev);
1.116 gwr 736: if (nblks <= ctod(1))
737: return;
738:
1.134 mycroft 739: dumpsize = physmem;
1.116 gwr 740:
1.134 mycroft 741: /* Always skip the first CLBYTES, in case there is a label there. */
742: if (dumplo < ctod(1))
1.116 gwr 743: dumplo = ctod(1);
1.134 mycroft 744:
745: /* Put dump at end of partition, and make it fit. */
746: if (dumpsize > dtoc(nblks - dumplo))
1.116 gwr 747: dumpsize = dtoc(nblks - dumplo);
1.134 mycroft 748: if (dumplo < nblks - ctod(dumpsize))
749: dumplo = nblks - ctod(dumpsize);
1.116 gwr 750: }
751:
1.1 cgd 752: /*
753: * Doadump comes here after turning off memory management and
754: * getting on the dump stack, either when called above, or by
755: * the auto-restart code.
756: */
1.32 andrew 757: void
1.1 cgd 758: dumpsys()
759: {
760:
1.141 mycroft 761: msgbufmapped = 0;
1.1 cgd 762: if (dumpdev == NODEV)
763: return;
1.134 mycroft 764: if (dumpsize == 0) {
765: dumpconf();
766: if (dumpsize == 0)
767: return;
768: }
1.35 cgd 769: printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo);
1.134 mycroft 770:
1.35 cgd 771: printf("dump ");
1.1 cgd 772: switch ((*bdevsw[major(dumpdev)].d_dump)(dumpdev)) {
773:
774: case ENXIO:
1.35 cgd 775: printf("device bad\n");
1.1 cgd 776: break;
777:
778: case EFAULT:
1.35 cgd 779: printf("device not ready\n");
1.1 cgd 780: break;
781:
782: case EINVAL:
1.35 cgd 783: printf("area improper\n");
1.1 cgd 784: break;
785:
786: case EIO:
1.35 cgd 787: printf("i/o error\n");
1.1 cgd 788: break;
789:
790: case EINTR:
1.35 cgd 791: printf("aborted from console\n");
1.1 cgd 792: break;
793:
794: default:
1.35 cgd 795: printf("succeeded\n");
1.1 cgd 796: break;
797: }
1.35 cgd 798: printf("\n\n");
1.90 mycroft 799: delay(1000);
1.1 cgd 800: }
801:
1.3 cgd 802: #ifdef HZ
1.7 cgd 803: /*
804: * If HZ is defined we use this code, otherwise the code in
1.59 mycroft 805: * /sys/i386/i386/microtime.s is used. The other code only works
1.7 cgd 806: * for HZ=100.
807: */
1.1 cgd 808: microtime(tvp)
809: register struct timeval *tvp;
810: {
811: int s = splhigh();
812:
813: *tvp = time;
814: tvp->tv_usec += tick;
1.59 mycroft 815: splx(s);
1.1 cgd 816: while (tvp->tv_usec > 1000000) {
817: tvp->tv_sec++;
818: tvp->tv_usec -= 1000000;
819: }
820: }
1.7 cgd 821: #endif /* HZ */
1.1 cgd 822:
823: /*
824: * Clear registers on exec
825: */
1.33 cgd 826: void
1.151 christos 827: setregs(p, pack, stack, retval)
1.1 cgd 828: struct proc *p;
1.151 christos 829: struct exec_package *pack;
1.21 cgd 830: u_long stack;
1.123 cgd 831: register_t *retval;
1.1 cgd 832: {
1.154 mycroft 833: register struct pcb *pcb;
1.59 mycroft 834: register struct trapframe *tf;
1.1 cgd 835:
1.153 mycroft 836: pcb = &p->p_addr->u_pcb;
1.161 mycroft 837: lcr0(pcb->pcb_cr0 |= CR0_EM|CR0_TS);
1.153 mycroft 838: pcb->pcb_flags = 0;
1.161 mycroft 839:
840: #if NNPX > 0
841: /* If we were using the FPU, forget about it. */
842: if (npxproc == p)
843: npxproc = 0;
844: #endif
1.59 mycroft 845:
1.154 mycroft 846: tf = p->p_md.md_regs;
847: tf->tf_es = LSEL(LUDATA_SEL, SEL_UPL);
848: tf->tf_ds = LSEL(LUDATA_SEL, SEL_UPL);
849: tf->tf_ebp = 0;
1.160 mycroft 850: tf->tf_ebx = (int)PS_STRINGS;
1.154 mycroft 851: tf->tf_eip = pack->ep_entry;
852: tf->tf_cs = LSEL(LUCODE_SEL, SEL_UPL);
853: tf->tf_eflags = PSL_USERSET;
854: tf->tf_esp = stack;
855: tf->tf_ss = LSEL(LUDATA_SEL, SEL_UPL);
856:
1.59 mycroft 857: retval[1] = 0;
1.1 cgd 858: }
859:
860: /*
861: * Initialize 386 and configure to run kernel
862: */
863:
864: /*
1.55 brezak 865: * Initialize segments and descriptor tables
1.1 cgd 866: */
867:
1.59 mycroft 868: union descriptor gdt[NGDT];
869: union descriptor ldt[NLDT];
870: struct gate_descriptor idt[NIDT];
1.49 brezak 871:
1.156 mycroft 872: int currentldt;
1.49 brezak 873:
1.154 mycroft 874: struct i386tss tss;
1.1 cgd 875:
876: extern struct user *proc0paddr;
877:
1.40 andrew 878: /* software prototypes -- in more palatable form */
1.1 cgd 879: struct soft_segment_descriptor gdt_segs[] = {
1.154 mycroft 880: /* Null descriptor */
1.155 mycroft 881: { 0x0, /* segment base address */
1.40 andrew 882: 0x0, /* length */
1.1 cgd 883: 0, /* segment type */
1.155 mycroft 884: 0, /* segment descriptor privilege level */
1.1 cgd 885: 0, /* segment descriptor present */
1.40 andrew 886: 0, 0,
1.1 cgd 887: 0, /* default 32 vs 16 bit size */
1.155 mycroft 888: 0 /* limit granularity (byte/page units) */ },
1.154 mycroft 889: /* Kernel code descriptor */
1.155 mycroft 890: { 0x0, /* segment base address */
1.1 cgd 891: 0xfffff, /* length - all address space */
892: SDT_MEMERA, /* segment type */
1.155 mycroft 893: SEL_KPL, /* segment descriptor privilege level */
1.1 cgd 894: 1, /* segment descriptor present */
1.40 andrew 895: 0, 0,
1.1 cgd 896: 1, /* default 32 vs 16 bit size */
1.155 mycroft 897: 1 /* limit granularity (byte/page units) */ },
1.154 mycroft 898: /* Kernel data descriptor */
1.155 mycroft 899: { 0x0, /* segment base address */
1.1 cgd 900: 0xfffff, /* length - all address space */
901: SDT_MEMRWA, /* segment type */
1.155 mycroft 902: SEL_KPL, /* segment descriptor privilege level */
1.1 cgd 903: 1, /* segment descriptor present */
1.40 andrew 904: 0, 0,
1.1 cgd 905: 1, /* default 32 vs 16 bit size */
1.155 mycroft 906: 1 /* limit granularity (byte/page units) */ },
1.159 mycroft 907: /* LDT descriptor */
1.155 mycroft 908: { (int) ldt, /* segment base address */
1.1 cgd 909: sizeof(ldt)-1, /* length - all address space */
910: SDT_SYSLDT, /* segment type */
1.155 mycroft 911: 0, /* segment descriptor privilege level */
1.1 cgd 912: 1, /* segment descriptor present */
1.40 andrew 913: 0, 0,
1.1 cgd 914: 0, /* unused - default 32 vs 16 bit size */
1.155 mycroft 915: 0 /* limit granularity (byte/page units) */ },
1.159 mycroft 916: /* User code descriptor */
917: { 0x0, /* segment base address */
918: 0xfffff, /* length - all address space */
919: SDT_MEMERA, /* segment type */
920: SEL_UPL, /* segment descriptor privilege level */
921: 1, /* segment descriptor present */
922: 0, 0,
923: 1, /* default 32 vs 16 bit size */
924: 1 /* limit granularity (byte/page units) */ },
925: /* User data descriptor */
926: { 0x0, /* segment base address */
927: 0xfffff, /* length - all address space */
928: SDT_MEMRWA, /* segment type */
929: SEL_UPL, /* segment descriptor privilege level */
930: 1, /* segment descriptor present */
931: 0, 0,
932: 1, /* default 32 vs 16 bit size */
933: 1 /* limit granularity (byte/page units) */ },
934: /* Proc 0 TSS descriptor */
1.155 mycroft 935: { (int) USRSTACK, /* segment base address */
1.1 cgd 936: sizeof(tss)-1, /* length - all address space */
937: SDT_SYS386TSS, /* segment type */
1.155 mycroft 938: SEL_KPL, /* segment descriptor privilege level */
1.1 cgd 939: 1, /* segment descriptor present */
1.40 andrew 940: 0, 0,
1.1 cgd 941: 0, /* unused - default 32 vs 16 bit size */
1.155 mycroft 942: 0 /* limit granularity (byte/page units) */ },
1.159 mycroft 943: /* User LDT descriptor per process */
1.155 mycroft 944: { (int) ldt, /* segment base address */
1.49 brezak 945: (512 * sizeof(union descriptor)-1), /* length */
946: SDT_SYSLDT, /* segment type */
1.155 mycroft 947: 0, /* segment descriptor privilege level */
1.49 brezak 948: 1, /* segment descriptor present */
949: 0, 0,
950: 0, /* unused - default 32 vs 16 bit size */
1.155 mycroft 951: 0 /* limit granularity (byte/page units) */ },
1.49 brezak 952: };
1.1 cgd 953:
954: struct soft_segment_descriptor ldt_segs[] = {
1.159 mycroft 955: /* Null descriptor - overwritten by call gate */
1.155 mycroft 956: { 0x0, /* segment base address */
1.40 andrew 957: 0x0, /* length */
1.1 cgd 958: 0, /* segment type */
1.155 mycroft 959: 0, /* segment descriptor privilege level */
1.1 cgd 960: 0, /* segment descriptor present */
1.40 andrew 961: 0, 0,
1.1 cgd 962: 0, /* default 32 vs 16 bit size */
1.155 mycroft 963: 0 /* limit granularity (byte/page units) */ },
1.159 mycroft 964: /* Null descriptor - overwritten by call gate */
1.155 mycroft 965: { 0x0, /* segment base address */
1.40 andrew 966: 0x0, /* length */
1.1 cgd 967: 0, /* segment type */
1.155 mycroft 968: 0, /* segment descriptor privilege level */
1.1 cgd 969: 0, /* segment descriptor present */
1.40 andrew 970: 0, 0,
1.1 cgd 971: 0, /* default 32 vs 16 bit size */
1.155 mycroft 972: 0 /* limit granularity (byte/page units) */ },
1.154 mycroft 973: /* User code descriptor */
1.155 mycroft 974: { 0x0, /* segment base address */
1.1 cgd 975: 0xfffff, /* length - all address space */
976: SDT_MEMERA, /* segment type */
1.155 mycroft 977: SEL_UPL, /* segment descriptor privilege level */
1.1 cgd 978: 1, /* segment descriptor present */
1.40 andrew 979: 0, 0,
1.1 cgd 980: 1, /* default 32 vs 16 bit size */
1.155 mycroft 981: 1 /* limit granularity (byte/page units) */ },
1.154 mycroft 982: /* User data descriptor */
1.155 mycroft 983: { 0x0, /* segment base address */
1.1 cgd 984: 0xfffff, /* length - all address space */
985: SDT_MEMRWA, /* segment type */
1.155 mycroft 986: SEL_UPL, /* segment descriptor privilege level */
1.1 cgd 987: 1, /* segment descriptor present */
1.40 andrew 988: 0, 0,
1.1 cgd 989: 1, /* default 32 vs 16 bit size */
1.159 mycroft 990: 1 /* limit granularity (byte/page units) */ },
991: };
1.1 cgd 992:
1.59 mycroft 993: void
1.124 mycroft 994: setgate(gdp, func, args, typ, dpl)
995: struct gate_descriptor *gdp;
996: void *func;
997: int args, typ, dpl;
1.59 mycroft 998: {
1.1 cgd 999:
1.124 mycroft 1000: gdp->gd_looffset = (int)func;
1001: gdp->gd_selector = GSEL(GCODE_SEL, SEL_KPL);
1002: gdp->gd_stkcpy = args;
1003: gdp->gd_xx = 0;
1004: gdp->gd_type = typ;
1005: gdp->gd_dpl = dpl;
1006: gdp->gd_p = 1;
1007: gdp->gd_hioffset = (int)func >> 16;
1.1 cgd 1008: }
1009:
1010: #define IDTVEC(name) __CONCAT(X, name)
1.124 mycroft 1011: extern IDTVEC(div), IDTVEC(dbg), IDTVEC(nmi), IDTVEC(bpt),
1012: IDTVEC(ofl), IDTVEC(bnd), IDTVEC(ill), IDTVEC(dna),
1013: IDTVEC(dble), IDTVEC(fpusegm), IDTVEC(tss), IDTVEC(missing),
1014: IDTVEC(stk), IDTVEC(prot), IDTVEC(page), IDTVEC(rsvd),
1015: IDTVEC(fpu), IDTVEC(align),
1016: IDTVEC(syscall), IDTVEC(osyscall);
1.1 cgd 1017:
1.59 mycroft 1018: void
1.129 mycroft 1019: sdtossd(sd, ssd)
1020: struct segment_descriptor *sd;
1021: struct soft_segment_descriptor *ssd;
1022: {
1.148 mycroft 1023:
1.129 mycroft 1024: ssd->ssd_base = (sd->sd_hibase << 24) | sd->sd_lobase;
1025: ssd->ssd_limit = (sd->sd_hilimit << 16) | sd->sd_lolimit;
1026: ssd->ssd_type = sd->sd_type;
1027: ssd->ssd_dpl = sd->sd_dpl;
1028: ssd->ssd_p = sd->sd_p;
1029: ssd->ssd_def32 = sd->sd_def32;
1030: ssd->ssd_gran = sd->sd_gran;
1031: }
1032:
1033: void
1034: ssdtosd(ssd, sd)
1035: struct soft_segment_descriptor *ssd;
1036: struct segment_descriptor *sd;
1037: {
1.148 mycroft 1038:
1.129 mycroft 1039: sd->sd_lobase = ssd->ssd_base;
1040: sd->sd_hibase = ssd->ssd_base >> 24;
1041: sd->sd_lolimit = ssd->ssd_limit;
1042: sd->sd_hilimit = ssd->ssd_limit >> 16;
1043: sd->sd_type = ssd->ssd_type;
1044: sd->sd_dpl = ssd->ssd_dpl;
1045: sd->sd_p = ssd->ssd_p;
1046: sd->sd_def32 = ssd->ssd_def32;
1047: sd->sd_gran = ssd->ssd_gran;
1048: }
1049:
1050: void
1.43 brezak 1051: init386(first_avail)
1052: vm_offset_t first_avail;
1.2 cgd 1053: {
1.148 mycroft 1054: struct pcb *pcb;
1.132 mycroft 1055: int x;
1.1 cgd 1056: unsigned biosbasemem, biosextmem;
1.148 mycroft 1057: struct region_descriptor region;
1.132 mycroft 1058: extern char etext[], sigcode[], esigcode[];
1.148 mycroft 1059: extern void consinit __P((void));
1.154 mycroft 1060: extern void lgdt();
1.1 cgd 1061:
1062: proc0.p_addr = proc0paddr;
1063:
1.84 cgd 1064: consinit(); /* XXX SHOULD NOT BE DONE HERE */
1.1 cgd 1065:
1.148 mycroft 1066: /* Set up proc 0's PCB and TSS. */
1067: curpcb = pcb = &proc0.p_addr->u_pcb;
1068: pcb->pcb_flags = 0;
1069: pcb->pcb_tss.tss_esp0 = (int)USRSTACK + USPACE;
1070: pcb->pcb_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL);
1071: pcb->pcb_tss.tss_ioopt = sizeof(struct i386tss) << 16;
1072:
1.154 mycroft 1073:
1.148 mycroft 1074: #ifndef LKM
1.59 mycroft 1075: /* set code segment limit to end of kernel text */
1076: gdt_segs[GCODE_SEL].ssd_limit = i386_btop(i386_round_page(&etext)) - 1;
1.28 cgd 1077: #endif
1.59 mycroft 1078: for (x = 0; x < NGDT; x++)
1.144 mycroft 1079: ssdtosd(&gdt_segs[x], &gdt[x].sd);
1.59 mycroft 1080:
1.1 cgd 1081: /* make ldt memory segments */
1.59 mycroft 1082: ldt_segs[LUCODE_SEL].ssd_limit = i386_btop(VM_MAXUSER_ADDRESS) - 1;
1083: ldt_segs[LUDATA_SEL].ssd_limit = i386_btop(VM_MAXUSER_ADDRESS) - 1;
1084: for (x = 0; x < NLDT; x++)
1.144 mycroft 1085: ssdtosd(&ldt_segs[x], &ldt[x].sd);
1.1 cgd 1086:
1.148 mycroft 1087: /* Set up the old-style call gate descriptor for system calls. */
1088: setgate(&ldt[LSYS5CALLS_SEL].gd, &IDTVEC(osyscall), 1, SDT_SYS386CGT,
1089: SEL_UPL);
1090:
1.1 cgd 1091: /* exceptions */
1.124 mycroft 1092: for (x = 0; x < NIDT; x++)
1093: setgate(&idt[x], &IDTVEC(rsvd), 0, SDT_SYS386TGT, SEL_KPL);
1094: setgate(&idt[ 0], &IDTVEC(div), 0, SDT_SYS386TGT, SEL_KPL);
1095: setgate(&idt[ 1], &IDTVEC(dbg), 0, SDT_SYS386TGT, SEL_KPL);
1096: setgate(&idt[ 2], &IDTVEC(nmi), 0, SDT_SYS386TGT, SEL_KPL);
1097: setgate(&idt[ 3], &IDTVEC(bpt), 0, SDT_SYS386TGT, SEL_UPL);
1098: setgate(&idt[ 4], &IDTVEC(ofl), 0, SDT_SYS386TGT, SEL_KPL);
1099: setgate(&idt[ 5], &IDTVEC(bnd), 0, SDT_SYS386TGT, SEL_KPL);
1100: setgate(&idt[ 6], &IDTVEC(ill), 0, SDT_SYS386TGT, SEL_KPL);
1101: setgate(&idt[ 7], &IDTVEC(dna), 0, SDT_SYS386TGT, SEL_KPL);
1102: setgate(&idt[ 8], &IDTVEC(dble), 0, SDT_SYS386TGT, SEL_KPL);
1103: setgate(&idt[ 9], &IDTVEC(fpusegm), 0, SDT_SYS386TGT, SEL_KPL);
1104: setgate(&idt[ 10], &IDTVEC(tss), 0, SDT_SYS386TGT, SEL_KPL);
1105: setgate(&idt[ 11], &IDTVEC(missing), 0, SDT_SYS386TGT, SEL_KPL);
1106: setgate(&idt[ 12], &IDTVEC(stk), 0, SDT_SYS386TGT, SEL_KPL);
1107: setgate(&idt[ 13], &IDTVEC(prot), 0, SDT_SYS386TGT, SEL_KPL);
1108: setgate(&idt[ 14], &IDTVEC(page), 0, SDT_SYS386TGT, SEL_KPL);
1109: setgate(&idt[ 16], &IDTVEC(fpu), 0, SDT_SYS386TGT, SEL_KPL);
1110: setgate(&idt[ 17], &IDTVEC(align), 0, SDT_SYS386TGT, SEL_KPL);
1111: setgate(&idt[128], &IDTVEC(syscall), 0, SDT_SYS386TGT, SEL_UPL);
1.1 cgd 1112:
1.95 mycroft 1113: #if NISA > 0
1.1 cgd 1114: isa_defaultirq();
1115: #endif
1.124 mycroft 1116:
1.148 mycroft 1117: region.rd_limit = sizeof(gdt)-1;
1118: region.rd_base = (int) gdt;
1119: lgdt(®ion);
1120: region.rd_limit = sizeof(idt)-1;
1121: region.rd_base = (int) idt;
1122: lidt(®ion);
1.1 cgd 1123:
1.124 mycroft 1124: splhigh();
1125: enable_intr();
1126:
1.5 glass 1127: #ifdef DDB
1.42 brezak 1128: ddb_init();
1.1 cgd 1129: if (boothowto & RB_KDB)
1130: Debugger();
1131: #endif
1.43 brezak 1132: #ifdef KGDB
1133: if (boothowto & RB_KDB)
1.59 mycroft 1134: kgdb_connect(0);
1.43 brezak 1135: #endif
1.1 cgd 1136:
1.59 mycroft 1137: /*
1138: * Use BIOS values stored in RTC CMOS RAM, since probing
1.1 cgd 1139: * breaks certain 386 AT relics.
1140: */
1.158 cgd 1141: biosbasemem = (mc146818_read(NULL, NVRAM_BASEHI) << 8) |
1142: mc146818_read(NULL, NVRAM_BASELO);
1143: biosextmem = (mc146818_read(NULL, NVRAM_EXTHI) << 8) |
1144: mc146818_read(NULL, NVRAM_EXTLO);
1.138 mycroft 1145:
1.148 mycroft 1146: /* Round down to whole pages. */
1.138 mycroft 1147: biosbasemem &= -(NBPG / 1024);
1148: biosextmem &= -(NBPG / 1024);
1.59 mycroft 1149:
1150: avail_start = NBPG; /* BIOS leaves data in low memory */
1.43 brezak 1151: /* and VM system doesn't work with phys 0 */
1.59 mycroft 1152: avail_end = biosextmem ? IOM_END + biosextmem * 1024
1.73 mycroft 1153: : biosbasemem * 1024;
1154:
1.59 mycroft 1155: /* number of pages of physmem addr space */
1156: physmem = btoc((biosbasemem + biosextmem) * 1024);
1.2 cgd 1157:
1.43 brezak 1158: /*
1.59 mycroft 1159: * Initialize for pmap_free_pages and pmap_next_page.
1160: * These guys should be page-aligned.
1.43 brezak 1161: */
1162: hole_start = biosbasemem * 1024;
1.59 mycroft 1163: /* we load right after the I/O hole; adjust hole_end to compensate */
1.148 mycroft 1164: hole_end = round_page(first_avail);
1.43 brezak 1165: avail_next = avail_start;
1.73 mycroft 1166:
1.139 mycroft 1167: if (physmem < btoc(2 * 1024 * 1024)) {
1.59 mycroft 1168: printf("warning: too little memory available; running in degraded mode\n"
1.73 mycroft 1169: "press a key to confirm\n\n");
1.20 deraadt 1170: cngetc();
1.2 cgd 1171: }
1.59 mycroft 1172:
1.1 cgd 1173: /* call pmap initialization to make new kernel address space */
1.59 mycroft 1174: pmap_bootstrap((vm_offset_t)atdevbase + IOM_SIZE);
1.73 mycroft 1175:
1.156 mycroft 1176: ltr(GSEL(GPROC0_SEL, SEL_KPL));
1177: lldt(currentldt = GSEL(GLDT_SEL, SEL_KPL));
1.1 cgd 1178: }
1179:
1.94 mycroft 1180: struct queue {
1181: struct queue *q_next, *q_prev;
1182: };
1183:
1.1 cgd 1184: /*
1.73 mycroft 1185: * insert an element into a queue
1.1 cgd 1186: */
1.94 mycroft 1187: void
1188: _insque(elem, head)
1189: register struct queue *elem, *head;
1190: {
1191: register struct queue *next;
1192:
1193: next = head->q_next;
1194: elem->q_next = next;
1195: head->q_next = elem;
1196: elem->q_prev = head;
1197: next->q_prev = elem;
1.1 cgd 1198: }
1199:
1200: /*
1201: * remove an element from a queue
1202: */
1.94 mycroft 1203: void
1204: _remque(elem)
1205: register struct queue *elem;
1206: {
1207: register struct queue *next, *prev;
1208:
1209: next = elem->q_next;
1210: prev = elem->q_prev;
1211: next->q_prev = prev;
1212: prev->q_next = next;
1213: elem->q_prev = 0;
1.1 cgd 1214: }
1215:
1.107 deraadt 1216:
1217: #ifdef COMPAT_NOMID
1218: static int
1219: exec_nomid(p, epp)
1.59 mycroft 1220: struct proc *p;
1221: struct exec_package *epp;
1.31 cgd 1222: {
1.59 mycroft 1223: int error;
1224: u_long midmag, magic;
1225: u_short mid;
1.80 cgd 1226: struct exec *execp = epp->ep_hdr;
1.31 cgd 1227:
1.80 cgd 1228: /* check on validity of epp->ep_hdr performed by exec_out_makecmds */
1229:
1230: midmag = ntohl(execp->a_midmag);
1.59 mycroft 1231: mid = (midmag >> 16) & 0xffff;
1232: magic = midmag & 0xffff;
1233:
1234: if (magic == 0) {
1.80 cgd 1235: magic = (execp->a_midmag & 0xffff);
1.59 mycroft 1236: mid = MID_ZERO;
1237: }
1238:
1239: midmag = mid << 16 | magic;
1240:
1241: switch (midmag) {
1242: case (MID_ZERO << 16) | ZMAGIC:
1243: /*
1244: * 386BSD's ZMAGIC format:
1245: */
1246: error = cpu_exec_aout_prep_oldzmagic(p, epp);
1247: break;
1248:
1249: case (MID_ZERO << 16) | QMAGIC:
1250: /*
1251: * BSDI's QMAGIC format:
1252: * same as new ZMAGIC format, but with different magic number
1253: */
1254: error = exec_aout_prep_zmagic(p, epp);
1255: break;
1256:
1257: default:
1258: error = ENOEXEC;
1259: }
1260:
1261: return error;
1.107 deraadt 1262: }
1.31 cgd 1263: #endif
1.107 deraadt 1264:
1265: /*
1266: * cpu_exec_aout_makecmds():
1267: * cpu-dependent a.out format hook for execve().
1268: *
1269: * Determine of the given exec package refers to something which we
1270: * understand and, if so, set up the vmcmds for it.
1271: *
1272: * On the i386, old (386bsd) ZMAGIC binaries and BSDI QMAGIC binaries
1273: * if COMPAT_NOMID is given as a kernel option.
1274: */
1275: int
1276: cpu_exec_aout_makecmds(p, epp)
1277: struct proc *p;
1278: struct exec_package *epp;
1279: {
1280: int error = ENOEXEC;
1281:
1282: #ifdef COMPAT_NOMID
1283: if ((error = exec_nomid(p, epp)) == 0)
1284: return error;
1285: #endif /* ! COMPAT_NOMID */
1286:
1287: return error;
1.31 cgd 1288: }
1.24 cgd 1289:
1.31 cgd 1290: #ifdef COMPAT_NOMID
1.46 cgd 1291: /*
1292: * cpu_exec_aout_prep_oldzmagic():
1293: * Prepare the vmcmds to build a vmspace for an old (386BSD) ZMAGIC
1294: * binary.
1295: *
1296: * Cloned from exec_aout_prep_zmagic() in kern/exec_aout.c; a more verbose
1297: * description of operation is there.
1298: */
1.24 cgd 1299: int
1.46 cgd 1300: cpu_exec_aout_prep_oldzmagic(p, epp)
1.59 mycroft 1301: struct proc *p;
1302: struct exec_package *epp;
1.24 cgd 1303: {
1.80 cgd 1304: struct exec *execp = epp->ep_hdr;
1.59 mycroft 1305: struct exec_vmcmd *ccmdp;
1.24 cgd 1306:
1.59 mycroft 1307: epp->ep_taddr = 0;
1308: epp->ep_tsize = execp->a_text;
1309: epp->ep_daddr = epp->ep_taddr + execp->a_text;
1310: epp->ep_dsize = execp->a_data + execp->a_bss;
1311: epp->ep_entry = execp->a_entry;
1312:
1313: /*
1314: * check if vnode is in open for writing, because we want to
1315: * demand-page out of it. if it is, don't do it, for various
1316: * reasons
1317: */
1318: if ((execp->a_text != 0 || execp->a_data != 0) &&
1319: epp->ep_vp->v_writecount != 0) {
1.31 cgd 1320: #ifdef DIAGNOSTIC
1.59 mycroft 1321: if (epp->ep_vp->v_flag & VTEXT)
1322: panic("exec: a VTEXT vnode has writecount != 0\n");
1.31 cgd 1323: #endif
1.59 mycroft 1324: return ETXTBSY;
1325: }
1326: epp->ep_vp->v_flag |= VTEXT;
1327:
1328: /* set up command for text segment */
1.69 cgd 1329: NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_pagedvn, execp->a_text,
1330: epp->ep_taddr, epp->ep_vp, NBPG, /* XXX should NBPG be CLBYTES? */
1331: VM_PROT_READ|VM_PROT_EXECUTE);
1.59 mycroft 1332:
1333: /* set up command for data segment */
1.69 cgd 1334: NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_pagedvn, execp->a_data,
1335: epp->ep_daddr, epp->ep_vp,
1336: execp->a_text + NBPG, /* XXX should NBPG be CLBYTES? */
1337: VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
1.59 mycroft 1338:
1339: /* set up command for bss segment */
1.69 cgd 1340: NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero, execp->a_bss,
1.71 mycroft 1341: epp->ep_daddr + execp->a_data, NULLVP, 0,
1.69 cgd 1342: VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
1.24 cgd 1343:
1.69 cgd 1344: return exec_aout_setup_stack(p, epp);
1.1 cgd 1345: }
1.31 cgd 1346: #endif /* COMPAT_NOMID */
1.43 brezak 1347:
1.139 mycroft 1348: u_int
1.59 mycroft 1349: pmap_free_pages()
1350: {
1351:
1.139 mycroft 1352: if (avail_next <= hole_start)
1353: return ((hole_start - avail_next) / NBPG +
1354: (avail_end - hole_end) / NBPG);
1355: else
1356: return ((avail_end - avail_next) / NBPG);
1.59 mycroft 1357: }
1358:
1359: int
1360: pmap_next_page(addrp)
1361: vm_offset_t *addrp;
1362: {
1363:
1.139 mycroft 1364: if (avail_next + NBPG > avail_end)
1.59 mycroft 1365: return FALSE;
1.73 mycroft 1366:
1.139 mycroft 1367: if (avail_next + NBPG > hole_start && avail_next < hole_end)
1.59 mycroft 1368: avail_next = hole_end;
1.73 mycroft 1369:
1.59 mycroft 1370: *addrp = avail_next;
1371: avail_next += NBPG;
1372: return TRUE;
1373: }
1374:
1.120 mycroft 1375: u_int
1.59 mycroft 1376: pmap_page_index(pa)
1377: vm_offset_t pa;
1378: {
1379:
1380: if (pa >= avail_start && pa < hole_start)
1381: return i386_btop(pa - avail_start);
1382: if (pa >= hole_end && pa < avail_end)
1383: return i386_btop(pa - hole_end + hole_start - avail_start);
1384: return -1;
1.84 cgd 1385: }
1386:
1387: /*
1388: * consinit:
1389: * initialize the system console.
1.94 mycroft 1390: * XXX - shouldn't deal with this initted thing, but then,
1.84 cgd 1391: * it shouldn't be called from init386 either.
1392: */
1393: void
1394: consinit()
1395: {
1.94 mycroft 1396: static int initted;
1397:
1398: if (initted)
1399: return;
1400: initted = 1;
1401: cninit();
1.149 mycroft 1402: }
1403:
1404: void
1405: cpu_reset()
1406: {
1407: struct region_descriptor region;
1408:
1409: /* Toggle the hardware reset line on the keyboard controller. */
1410: outb(KBCMDP, KBC_PULSE0);
1.162 ! mycroft 1411: delay(20000);
1.149 mycroft 1412: outb(KBCMDP, KBC_PULSE0);
1.162 ! mycroft 1413: delay(20000);
1.149 mycroft 1414:
1415: /*
1416: * Try to cause a triple fault and watchdog reset by setting the
1417: * IDT to point to nothing.
1418: */
1419: region.rd_limit = 0;
1420: region.rd_base = 0;
1421: lidt(®ion);
1422:
1423: /*
1424: * Try to cause a triple fault and watchdog reset by unmapping the
1425: * entire address space.
1426: */
1427: bzero((caddr_t)PTD, NBPG);
1428: pmap_update();
1429:
1430: for (;;);
1.45 cgd 1431: }
CVSweb <webmaster@jp.NetBSD.org>