Annotation of src/sys/arch/i386/i386/machdep.c, Revision 1.83
1.1 cgd 1: /*-
1.60 mycroft 2: * Copyright (c) 1993 Charles Hannum.
1.35 cgd 3: * Copyright (c) 1992 Terrence R. Lambert.
1.1 cgd 4: * Copyright (c) 1982, 1987, 1990 The Regents of the University of California.
5: * All rights reserved.
6: *
7: * This code is derived from software contributed to Berkeley by
8: * William Jolitz.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: * 3. All advertising materials mentioning features or use of this software
19: * must display the following acknowledgement:
20: * This product includes software developed by the University of
21: * California, Berkeley and its contributors.
22: * 4. Neither the name of the University nor the names of its contributors
23: * may be used to endorse or promote products derived from this software
24: * without specific prior written permission.
25: *
26: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36: * SUCH DAMAGE.
37: *
1.13 cgd 38: * from: @(#)machdep.c 7.4 (Berkeley) 6/3/91
1.83 ! mycroft 39: * $Id: machdep.c,v 1.82 1994/01/20 21:22:06 ws Exp $
1.1 cgd 40: */
41:
1.27 cgd 42: #include <stddef.h>
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>
1.69 cgd 51: #include <sys/exec_aout.h>
1.59 mycroft 52: #include <sys/buf.h>
53: #include <sys/reboot.h>
54: #include <sys/conf.h>
55: #include <sys/file.h>
56: #include <sys/callout.h>
57: #include <sys/malloc.h>
58: #include <sys/mbuf.h>
59: #include <sys/msgbuf.h>
60: #include <sys/mount.h>
61: #include <sys/vnode.h>
1.57 cgd 62: #ifdef SYSVMSG
1.59 mycroft 63: #include <sys/msg.h>
1.57 cgd 64: #endif
65: #ifdef SYSVSEM
1.59 mycroft 66: #include <sys/sem.h>
67: #endif
68: #ifdef SYSVSHM
69: #include <sys/shm.h>
1.57 cgd 70: #endif
71:
1.59 mycroft 72: #include <vm/vm.h>
73: #include <vm/vm_kern.h>
74: #include <vm/vm_page.h>
1.31 cgd 75:
1.59 mycroft 76: #include <machine/cpu.h>
77: #include <machine/cpufunc.h>
78: #include <machine/psl.h>
79: #include <machine/reg.h>
80: #include <machine/specialreg.h>
1.43 brezak 81:
1.59 mycroft 82: #include <i386/isa/isa.h>
83: #include <i386/isa/rtc.h>
1.43 brezak 84:
1.59 mycroft 85: #include "isa.h"
86: #include "npx.h"
1.2 cgd 87:
1.1 cgd 88: /*
89: * Declare these as initialized data so we can patch them.
90: */
91: int nswbuf = 0;
92: #ifdef NBUF
93: int nbuf = NBUF;
94: #else
95: int nbuf = 0;
96: #endif
97: #ifdef BUFPAGES
98: int bufpages = BUFPAGES;
99: #else
100: int bufpages = 0;
101: #endif
102:
1.59 mycroft 103: int physmem;
104: int boothowto;
105: int cpu_class;
106:
107: struct msgbuf *msgbufp;
108: int msgbufmapped;
109:
110: vm_map_t buffer_map;
1.48 brezak 111:
1.59 mycroft 112: extern vm_offset_t avail_start, avail_end;
113: static vm_offset_t hole_start, hole_end;
114: static vm_offset_t avail_next;
115: static vm_size_t avail_remaining;
1.1 cgd 116:
1.59 mycroft 117: int _udatasel, _ucodesel, _gsel_tss;
1.14 cgd 118:
1.59 mycroft 119: long dumplo;
1.24 cgd 120:
1.32 andrew 121: void dumpsys __P((void));
122:
1.59 mycroft 123: caddr_t allocsys();
124:
125: /*
126: * Machine-dependent startup code
127: */
1.32 andrew 128: void
1.1 cgd 129: cpu_startup()
130: {
1.59 mycroft 131: unsigned i;
132: caddr_t v;
133: int sz;
134: int base, residual;
1.1 cgd 135: vm_offset_t minaddr, maxaddr;
136: vm_size_t size;
137:
138: /*
139: * Initialize error message buffer (at end of core).
140: */
141: /* avail_end was pre-decremented in pmap_bootstrap to compensate */
1.59 mycroft 142: for (i = 0; i < btoc(sizeof(struct msgbuf)); i++)
1.43 brezak 143: pmap_enter(pmap_kernel(), (caddr_t)msgbufp + i * NBPG,
144: avail_end + i * NBPG, VM_PROT_ALL, TRUE);
1.1 cgd 145: msgbufmapped = 1;
146:
1.6 cgd 147: printf(version);
1.16 cgd 148: identifycpu();
1.6 cgd 149: printf("real mem = %d\n", ctob(physmem));
1.1 cgd 150:
151: /*
1.59 mycroft 152: * Find out how much space we need, allocate it,
153: * and then give everything true virtual addresses.
1.1 cgd 154: */
1.59 mycroft 155: sz = (int)allocsys((caddr_t)0);
156: if ((v = (caddr_t)kmem_alloc(kernel_map, round_page(sz))) == 0)
157: panic("startup: no room for tables");
158: if (allocsys(v) - v != sz)
1.1 cgd 159: panic("startup: table size inconsistency");
1.50 cgd 160:
1.36 cgd 161: /*
162: * Now allocate buffers proper. They are different than the above
163: * in that they usually occupy more virtual memory than physical.
164: */
165: size = MAXBSIZE * nbuf;
1.68 mycroft 166: buffer_map = kmem_suballoc(kernel_map, (vm_offset_t *)&buffers,
1.36 cgd 167: &maxaddr, size, FALSE);
168: minaddr = (vm_offset_t)buffers;
169: if (vm_map_find(buffer_map, vm_object_allocate(size), (vm_offset_t)0,
170: &minaddr, size, FALSE) != KERN_SUCCESS)
171: panic("startup: cannot allocate buffers");
1.54 cgd 172: if ((bufpages / nbuf) >= btoc(MAXBSIZE)) {
173: /* don't want to alloc more physical mem than needed */
174: bufpages = btoc(MAXBSIZE) * nbuf;
175: }
1.36 cgd 176: base = bufpages / nbuf;
177: residual = bufpages % nbuf;
178: for (i = 0; i < nbuf; i++) {
179: vm_size_t curbufsize;
180: vm_offset_t curbuf;
181:
182: /*
183: * First <residual> buffers get (base+1) physical pages
184: * allocated for them. The rest get (base) physical pages.
185: *
186: * The rest of each buffer occupies virtual space,
187: * but has no physical memory allocated for it.
188: */
189: curbuf = (vm_offset_t)buffers + i * MAXBSIZE;
190: curbufsize = CLBYTES * (i < residual ? base+1 : base);
191: vm_map_pageable(buffer_map, curbuf, curbuf+curbufsize, FALSE);
192: vm_map_simplify(buffer_map, curbuf);
193: }
1.41 cgd 194:
1.1 cgd 195: /*
1.36 cgd 196: * Allocate a submap for exec arguments. This map effectively
197: * limits the number of processes exec'ing at any time.
1.1 cgd 198: */
1.59 mycroft 199: exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
1.79 mycroft 200: 16*NCARGS, TRUE);
1.59 mycroft 201:
1.1 cgd 202: /*
203: * Allocate a submap for physio
204: */
205: phys_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
206: VM_PHYS_SIZE, TRUE);
207:
208: /*
209: * Finally, allocate mbuf pool. Since mclrefcnt is an off-size
210: * we use the more space efficient malloc in place of kmem_alloc.
211: */
212: mclrefcnt = (char *)malloc(NMBCLUSTERS+CLBYTES/MCLBYTES,
213: M_MBUF, M_NOWAIT);
214: bzero(mclrefcnt, NMBCLUSTERS+CLBYTES/MCLBYTES);
1.68 mycroft 215: mb_map = kmem_suballoc(kernel_map, (vm_offset_t *)&mbutl, &maxaddr,
1.73 mycroft 216: VM_MBUF_SIZE, FALSE);
1.59 mycroft 217:
1.1 cgd 218: /*
219: * Initialize callouts
220: */
221: callfree = callout;
222: for (i = 1; i < ncallout; i++)
223: callout[i-1].c_next = &callout[i];
224:
1.6 cgd 225: printf("avail mem = %d\n", ptoa(vm_page_free_count));
1.36 cgd 226: printf("using %d buffers containing %d bytes of memory\n",
227: nbuf, bufpages * CLBYTES);
1.1 cgd 228:
229: /*
230: * Set up buffers, so they can be used to read disk labels.
231: */
232: bufinit();
233:
234: /*
235: * Configure the system.
236: */
237: configure();
1.16 cgd 238: }
239:
1.59 mycroft 240: /*
241: * Allocate space for system data structures. We are given
242: * a starting virtual address and we return a final virtual
243: * address; along the way we set each data structure pointer.
244: *
245: * We call allocsys() with 0 to find out how much space we want,
246: * allocate that much and fill it with zeroes, and then call
247: * allocsys() again with the correct base virtual address.
248: */
249: caddr_t
250: allocsys(v)
251: register caddr_t v;
252: {
253:
254: #define valloc(name, type, num) \
255: v = (caddr_t)(((name) = (type *)v) + (num))
256: #ifdef REAL_CLISTS
257: valloc(cfree, struct cblock, nclist);
258: #endif
259: valloc(callout, struct callout, ncallout);
260: valloc(swapmap, struct map, nswapmap = maxproc * 2);
261: #ifdef SYSVSHM
262: valloc(shmsegs, struct shmid_ds, shminfo.shmmni);
263: #endif
264: #ifdef SYSVSEM
265: valloc(sema, struct semid_ds, seminfo.semmni);
266: valloc(sem, struct sem, seminfo.semmns);
267: /* This is pretty disgusting! */
268: valloc(semu, int, (seminfo.semmnu * seminfo.semusz) / sizeof(int));
269: #endif
270: #ifdef SYSVMSG
271: valloc(msgpool, char, msginfo.msgmax);
272: valloc(msgmaps, struct msgmap, msginfo.msgseg);
273: valloc(msghdrs, struct msg, msginfo.msgtql);
274: valloc(msqids, struct msqid_ds, msginfo.msgmni);
275: #endif
276:
277: /*
1.77 mycroft 278: * Determine how many buffers to allocate. We use 10% of the
279: * first 2MB of memory, and 5% of the rest, with a minimum of 16
280: * buffers. We allocate 1/2 as many swap buffer headers as file
281: * i/o buffers.
1.59 mycroft 282: */
283: if (bufpages == 0)
1.77 mycroft 284: if (physmem < btoc(2 * 1024 * 1024))
285: bufpages = physmem / (10 * CLSIZE);
286: else
287: bufpages = (btoc(2 * 1024 * 1024) + physmem) /
288: (20 * CLSIZE);
1.59 mycroft 289: if (nbuf == 0) {
290: nbuf = bufpages;
291: if (nbuf < 16)
292: nbuf = 16;
293: }
294: if (nswbuf == 0) {
295: nswbuf = (nbuf / 2) &~ 1; /* force even */
296: if (nswbuf > 256)
297: nswbuf = 256; /* sanity */
298: }
299: valloc(swbuf, struct buf, nswbuf);
300: valloc(buf, struct buf, nbuf);
301: return v;
302: }
1.18 cgd 303:
304: struct cpu_nameclass i386_cpus[] = {
1.59 mycroft 305: { "i386SX", CPUCLASS_386 }, /* CPU_386SX */
306: { "i386DX", CPUCLASS_386 }, /* CPU_386 */
307: { "i486SX", CPUCLASS_486 }, /* CPU_486SX */
308: { "i486DX", CPUCLASS_486 }, /* CPU_486 */
309: { "Pentium", CPUCLASS_586 }, /* CPU_586 */
1.18 cgd 310: };
311:
1.59 mycroft 312: identifycpu()
1.16 cgd 313: {
1.17 cgd 314: printf("CPU: ");
1.59 mycroft 315: #ifdef DIAGNOSTIC
316: if (cpu < 0 || cpu >= (sizeof i386_cpus/sizeof(struct cpu_nameclass)))
1.63 cgd 317: #ifdef notyet /* XXX */
1.59 mycroft 318: panic("unknown cpu type %d\n", cpu);
1.63 cgd 319: #else
320: panic("unknown cpu type\n");
321: #endif
1.59 mycroft 322: #endif
323: printf("%s", i386_cpus[cpu].cpu_name);
324: cpu_class = i386_cpus[cpu].cpu_class;
1.18 cgd 325: printf(" (");
1.24 cgd 326: switch(cpu_class) {
1.18 cgd 327: case CPUCLASS_386:
328: printf("386");
1.17 cgd 329: break;
1.18 cgd 330: case CPUCLASS_486:
331: printf("486");
1.17 cgd 332: break;
1.18 cgd 333: case CPUCLASS_586:
334: printf("586");
1.17 cgd 335: break;
336: default:
1.18 cgd 337: printf("unknown"); /* will panic below... */
1.16 cgd 338: }
1.18 cgd 339: printf("-class CPU)");
1.17 cgd 340: printf("\n"); /* cpu speed would be nice, but how? */
1.18 cgd 341:
1.16 cgd 342: /*
343: * Now that we have told the user what they have,
344: * let them know if that machine type isn't configured.
345: */
1.24 cgd 346: switch (cpu_class) {
1.16 cgd 347: #if !defined(I386_CPU)
1.18 cgd 348: case CPUCLASS_386:
1.16 cgd 349: #endif
350: #if !defined(I486_CPU)
1.18 cgd 351: case CPUCLASS_486:
1.16 cgd 352: #endif
353: #if !defined(I586_CPU)
1.18 cgd 354: case CPUCLASS_586:
1.16 cgd 355: #endif
1.59 mycroft 356: #if !defined(I386_CPU) && !defined(I486_CPU) && !defined(I586_CPU)
357: #error No CPU classes configured.
358: #endif
1.18 cgd 359: panic("CPU class not configured");
1.16 cgd 360: default:
361: break;
362: }
1.1 cgd 363: }
364:
365: #ifdef PGINPROF
366: /*
1.59 mycroft 367: * Return the difference (in microseconds) between the current time and a
368: * previous time as represented by the arguments. If there is a pending
369: * clock interrupt which has not been serviced due to high ipl, return error
370: * code.
1.1 cgd 371: */
372: /*ARGSUSED*/
373: vmtime(otime, olbolt, oicr)
374: register int otime, olbolt, oicr;
375: {
376:
1.59 mycroft 377: return (((time.tv_sec-otime)*HZ + lbolt-olbolt)*(1000000/HZ));
1.1 cgd 378: }
379: #endif
380:
381: /*
382: * Send an interrupt to process.
383: *
384: * Stack is set up to allow sigcode stored
385: * in u. to call routine, followed by kcall
386: * to sigreturn routine below. After sigreturn
387: * resets the signal mask, the stack, and the
388: * frame pointer, it returns to the user
389: * specified pc, psl.
390: */
391: void
392: sendsig(catcher, sig, mask, code)
393: sig_t catcher;
394: int sig, mask;
395: unsigned code;
396: {
397: register struct proc *p = curproc;
1.59 mycroft 398: register struct trapframe *tf;
1.82 ws 399: struct sigframe *fp, frame;
1.1 cgd 400: struct sigacts *ps = p->p_sigacts;
1.48 brezak 401: int oonstack;
1.22 cgd 402: extern char sigcode[], esigcode[];
1.1 cgd 403:
1.59 mycroft 404: tf = (struct trapframe *)p->p_regs;
405: oonstack = ps->ps_onstack;
1.1 cgd 406: /*
1.82 ws 407: * Allocate space for the signal handler context.
1.1 cgd 408: */
1.59 mycroft 409: if (!ps->ps_onstack && (ps->ps_sigonstack & sigmask(sig))) {
1.1 cgd 410: fp = (struct sigframe *)(ps->ps_sigsp
411: - sizeof(struct sigframe));
1.59 mycroft 412: ps->ps_onstack = 1;
1.1 cgd 413: } else {
1.59 mycroft 414: fp = (struct sigframe *)(tf->tf_esp - sizeof(struct sigframe));
1.1 cgd 415: }
416:
1.82 ws 417: /*
418: * Build the argument list for the signal handler.
419: */
420: frame.sf_signum = sig;
421: frame.sf_code = code;
422: frame.sf_scp = &fp->sf_sc;
423: frame.sf_handler = catcher;
424:
425: /*
426: * Build the signal context to be used by sigreturn.
427: */
428: frame.sf_sc.sc_onstack = oonstack;
429: frame.sf_sc.sc_mask = mask;
430: frame.sf_sc.sc_ebp = tf->tf_ebp;
431: frame.sf_sc.sc_esp = tf->tf_esp;
432: frame.sf_sc.sc_eip = tf->tf_eip;
433: frame.sf_sc.sc_efl = tf->tf_eflags;
434: frame.sf_sc.sc_eax = tf->tf_eax;
435: frame.sf_sc.sc_ebx = tf->tf_ebx;
436: frame.sf_sc.sc_ecx = tf->tf_ecx;
437: frame.sf_sc.sc_edx = tf->tf_edx;
438: frame.sf_sc.sc_esi = tf->tf_esi;
439: frame.sf_sc.sc_edi = tf->tf_edi;
440: frame.sf_sc.sc_cs = tf->tf_cs;
441: frame.sf_sc.sc_ds = tf->tf_ds;
442: frame.sf_sc.sc_es = tf->tf_es;
443: frame.sf_sc.sc_ss = tf->tf_ss;
1.1 cgd 444:
1.83 ! mycroft 445: if (copyout(&frame, fp, sizeof(frame)) < 0) {
1.1 cgd 446: /*
447: * Process has trashed its stack; give it an illegal
448: * instruction to halt it in its tracks.
449: */
450: SIGACTION(p, SIGILL) = SIG_DFL;
451: sig = sigmask(SIGILL);
452: p->p_sigignore &= ~sig;
453: p->p_sigcatch &= ~sig;
454: p->p_sigmask &= ~sig;
455: psignal(p, SIGILL);
456: return;
457: }
458:
1.73 mycroft 459: /*
1.59 mycroft 460: * Build context to run handler in.
461: */
462: tf->tf_esp = (int)fp;
463: tf->tf_eip = (int)(((char *)PS_STRINGS) - (esigcode - sigcode));
464: tf->tf_eflags &= ~PSL_VM;
465: tf->tf_cs = _ucodesel;
466: tf->tf_ds = _udatasel;
467: tf->tf_es = _udatasel;
468: tf->tf_ss = _udatasel;
1.1 cgd 469: }
470:
471: /*
472: * System call to cleanup state after a signal
473: * has been taken. Reset signal mask and
474: * stack state from context left by sendsig (above).
475: * Return to previous pc and psl as specified by
476: * context left by sendsig. Check carefully to
477: * make sure that the user has not modified the
478: * psl to gain improper priviledges or to cause
479: * a machine fault.
480: */
1.39 mycroft 481: struct sigreturn_args {
482: struct sigcontext *sigcntxp;
483: };
484:
1.1 cgd 485: sigreturn(p, uap, retval)
486: struct proc *p;
1.39 mycroft 487: struct sigreturn_args *uap;
1.1 cgd 488: int *retval;
489: {
1.82 ws 490: struct sigcontext *scp, context;
1.1 cgd 491: register struct sigframe *fp;
1.59 mycroft 492: register struct trapframe *tf;
1.72 mycroft 493: int eflags;
1.59 mycroft 494:
495: tf = (struct trapframe *)p->p_regs;
1.1 cgd 496:
1.27 cgd 497: /*
1.59 mycroft 498: * The trampoline code hands us the context.
499: * It is unsafe to keep track of it ourselves, in the event that a
500: * program jumps out of a signal handler.
1.27 cgd 501: */
502: scp = uap->sigcntxp;
503: fp = (struct sigframe *)
1.73 mycroft 504: ((caddr_t)scp - offsetof(struct sigframe, sf_sc));
1.1 cgd 505:
1.59 mycroft 506: if (useracc((caddr_t)fp, sizeof(*fp), 0) == 0)
1.72 mycroft 507: return(EFAULT);
1.59 mycroft 508:
1.82 ws 509: if (copyin((caddr_t)scp, &context, sizeof(*scp)) < 0)
1.72 mycroft 510: return(EFAULT);
1.1 cgd 511:
1.82 ws 512: eflags = context.sc_efl;
1.72 mycroft 513: if ((eflags & PSL_USERCLR) != 0 ||
514: (eflags & PSL_USERSET) != PSL_USERSET ||
515: (eflags & PSL_IOPL) > (tf->tf_eflags & PSL_IOPL))
1.1 cgd 516: return(EINVAL);
1.59 mycroft 517:
1.74 brezak 518: /*
519: * Sanity check the user's selectors and error if they
520: * are suspect.
521: */
522: #define max_ldt_sel(pcb) \
1.75 mycroft 523: ((pcb)->pcb_ldt ? (pcb)->pcb_ldt_len : (sizeof(ldt) / sizeof(ldt[0])))
524:
525: #define valid_ldt_sel(sel) \
526: (ISLDT(sel) && ISPL(sel) == SEL_UPL && \
527: IDXSEL(sel) < max_ldt_sel(&p->p_addr->u_pcb))
528:
529: #define null_sel(sel) \
530: (!ISLDT(sel) && IDXSEL(sel) == 0)
531:
1.82 ws 532: if ((context.sc_cs&0xffff != _ucodesel && !valid_ldt_sel(context.sc_cs)) ||
533: (context.sc_ss&0xffff != _udatasel && !valid_ldt_sel(context.sc_ss)) ||
534: (context.sc_ds&0xffff != _udatasel && !valid_ldt_sel(context.sc_ds) &&
535: !null_sel(context.sc_ds)) ||
536: (context.sc_es&0xffff != _udatasel && !valid_ldt_sel(context.sc_es) &&
537: !null_sel(context.sc_es))) {
1.75 mycroft 538: trapsignal(p, SIGBUS, T_PROTFLT);
539: return(EINVAL);
1.74 brezak 540: }
1.75 mycroft 541:
542: #undef max_ldt_sel
543: #undef valid_ldt_sel
544: #undef null_sel
1.59 mycroft 545:
1.82 ws 546: p->p_sigacts->ps_onstack = context.sc_onstack & 01;
547: p->p_sigmask = context.sc_mask &~
1.1 cgd 548: (sigmask(SIGKILL)|sigmask(SIGCONT)|sigmask(SIGSTOP));
1.49 brezak 549:
1.59 mycroft 550: /*
551: * Restore signal context.
552: */
1.82 ws 553: tf->tf_ebp = context.sc_ebp;
554: tf->tf_esp = context.sc_esp;
555: tf->tf_eip = context.sc_eip;
1.72 mycroft 556: tf->tf_eflags = eflags;
1.82 ws 557: tf->tf_eax = context.sc_eax;
558: tf->tf_ebx = context.sc_ebx;
559: tf->tf_ecx = context.sc_ecx;
560: tf->tf_edx = context.sc_edx;
561: tf->tf_esi = context.sc_esi;
562: tf->tf_edi = context.sc_edi;
563: tf->tf_cs = context.sc_cs;
564: tf->tf_ds = context.sc_ds;
565: tf->tf_es = context.sc_es;
566: tf->tf_ss = context.sc_ss;
1.72 mycroft 567:
1.1 cgd 568: return(EJUSTRETURN);
1.37 cgd 569: }
570:
1.1 cgd 571: int waittime = -1;
572: struct pcb dumppcb;
573:
1.32 andrew 574: void
1.1 cgd 575: boot(arghowto)
576: int arghowto;
577: {
578: register long dummy; /* r12 is reserved */
579: register int howto; /* r11 == how to boot */
580: register int devtype; /* r10 == major of root dev */
581: extern int cold;
582:
583: if(cold) {
584: printf("hit reset please");
585: for(;;);
586: }
587: howto = arghowto;
588: if ((howto&RB_NOSYNC) == 0 && waittime < 0 && bfreelist[0].b_forw) {
589: register struct buf *bp;
590: int iter, nbusy;
591:
592: waittime = 0;
593: (void) splnet();
1.25 cgd 594: printf("syncing disks... ");
1.1 cgd 595: /*
596: * Release inodes held by texts before update.
597: */
598: if (panicstr == 0)
599: vnode_pager_umount(NULL);
1.83 ! mycroft 600: sync((struct proc *)0, (void *)0, (int *)0);
1.43 brezak 601: /*
602: * Unmount filesystems
603: */
604: #if 0
605: if (panicstr == 0)
606: vfs_unmountall();
607: #endif
1.1 cgd 608: for (iter = 0; iter < 20; iter++) {
609: nbusy = 0;
610: for (bp = &buf[nbuf]; --bp >= buf; )
611: if ((bp->b_flags & (B_BUSY|B_INVAL)) == B_BUSY)
612: nbusy++;
613: if (nbusy == 0)
614: break;
1.25 cgd 615: printf("%d ", nbusy);
1.1 cgd 616: DELAY(40000 * iter);
617: }
618: if (nbusy)
1.25 cgd 619: printf("giving up\n");
1.26 cgd 620: else
1.25 cgd 621: printf("done\n");
1.59 mycroft 622: /*
623: * If we've been adjusting the clock, the todr
624: * will be out of synch; adjust it now.
625: */
626: resettodr();
1.55 brezak 627:
1.1 cgd 628: DELAY(10000); /* wait for printf to finish */
629: }
630: splhigh();
631: devtype = major(rootdev);
632: if (howto&RB_HALT) {
1.25 cgd 633: printf("\n");
634: printf("The operating system has halted.\n");
635: printf("Please press any key to reboot.\n\n");
1.12 cgd 636: cngetc();
1.1 cgd 637: } else {
638: if (howto & RB_DUMP) {
639: savectx(&dumppcb, 0);
640: dumppcb.pcb_ptd = rcr3();
1.73 mycroft 641: dumpsys();
1.1 cgd 642: /*NOTREACHED*/
643: }
644: }
645: #ifdef lint
646: dummy = 0; dummy = dummy;
647: printf("howto %d, devtype %d\n", arghowto, devtype);
648: #endif
649: cpu_reset();
650: for(;;) ;
651: /*NOTREACHED*/
652: }
653:
1.32 andrew 654: unsigned dumpmag = 0x8fca0101; /* magic number for savecore */
655: int dumpsize = 0; /* also for savecore */
1.1 cgd 656: /*
657: * Doadump comes here after turning off memory management and
658: * getting on the dump stack, either when called above, or by
659: * the auto-restart code.
660: */
1.32 andrew 661: void
1.1 cgd 662: dumpsys()
663: {
664:
665: if (dumpdev == NODEV)
666: return;
667: if ((minor(dumpdev)&07) != 1)
668: return;
669: dumpsize = physmem;
1.35 cgd 670: printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo);
671: printf("dump ");
1.1 cgd 672: switch ((*bdevsw[major(dumpdev)].d_dump)(dumpdev)) {
673:
674: case ENXIO:
1.35 cgd 675: printf("device bad\n");
1.1 cgd 676: break;
677:
678: case EFAULT:
1.35 cgd 679: printf("device not ready\n");
1.1 cgd 680: break;
681:
682: case EINVAL:
1.35 cgd 683: printf("area improper\n");
1.1 cgd 684: break;
685:
686: case EIO:
1.35 cgd 687: printf("i/o error\n");
1.1 cgd 688: break;
689:
690: case EINTR:
1.35 cgd 691: printf("aborted from console\n");
1.1 cgd 692: break;
693:
694: default:
1.35 cgd 695: printf("succeeded\n");
1.1 cgd 696: break;
697: }
1.35 cgd 698: printf("\n\n");
699: DELAY(1000);
1.1 cgd 700: }
701:
1.3 cgd 702: #ifdef HZ
1.7 cgd 703: /*
704: * If HZ is defined we use this code, otherwise the code in
1.59 mycroft 705: * /sys/i386/i386/microtime.s is used. The other code only works
1.7 cgd 706: * for HZ=100.
707: */
1.1 cgd 708: microtime(tvp)
709: register struct timeval *tvp;
710: {
711: int s = splhigh();
712:
713: *tvp = time;
714: tvp->tv_usec += tick;
1.59 mycroft 715: splx(s);
1.1 cgd 716: while (tvp->tv_usec > 1000000) {
717: tvp->tv_sec++;
718: tvp->tv_usec -= 1000000;
719: }
720: }
1.7 cgd 721: #endif /* HZ */
1.1 cgd 722:
723: /*
724: * Clear registers on exec
725: */
1.33 cgd 726: void
727: setregs(p, entry, stack, retval)
1.1 cgd 728: struct proc *p;
729: u_long entry;
1.21 cgd 730: u_long stack;
1.33 cgd 731: int retval[2];
1.1 cgd 732: {
1.59 mycroft 733: register struct trapframe *tf;
734:
735: tf = (struct trapframe *)p->p_regs;
736: tf->tf_ebp = 0; /* bottom of the fp chain */
737: tf->tf_eip = entry;
738: tf->tf_esp = stack;
739: tf->tf_ss = _udatasel;
740: tf->tf_ds = _udatasel;
741: tf->tf_es = _udatasel;
742: tf->tf_cs = _ucodesel;
1.1 cgd 743:
1.21 cgd 744: p->p_addr->u_pcb.pcb_flags &= 0 /* FM_SYSCTRC */; /* no fp at all */
1.65 mycroft 745: lcr0(rcr0() | CR0_TS); /* start emulating */
1.30 brezak 746: #if NNPX > 0
1.1 cgd 747: npxinit(__INITIAL_NPXCW__);
748: #endif
1.59 mycroft 749:
750: retval[1] = 0;
1.1 cgd 751: }
752:
753: /*
754: * Initialize 386 and configure to run kernel
755: */
756:
757: /*
1.55 brezak 758: * Initialize segments and descriptor tables
1.1 cgd 759: */
760:
1.59 mycroft 761: union descriptor gdt[NGDT];
762: union descriptor ldt[NLDT];
763: struct gate_descriptor idt[NIDT];
1.49 brezak 764:
765: int _default_ldt, currentldt;
766:
1.1 cgd 767: struct i386tss tss, panic_tss;
768:
769: extern struct user *proc0paddr;
770:
1.40 andrew 771: /* software prototypes -- in more palatable form */
1.1 cgd 772: struct soft_segment_descriptor gdt_segs[] = {
773: /* Null Descriptor */
774: { 0x0, /* segment base address */
1.40 andrew 775: 0x0, /* length */
1.1 cgd 776: 0, /* segment type */
777: 0, /* segment descriptor priority level */
778: 0, /* segment descriptor present */
1.40 andrew 779: 0, 0,
1.1 cgd 780: 0, /* default 32 vs 16 bit size */
781: 0 /* limit granularity (byte/page units)*/ },
782: /* Code Descriptor for kernel */
783: { 0x0, /* segment base address */
784: 0xfffff, /* length - all address space */
785: SDT_MEMERA, /* segment type */
786: 0, /* segment descriptor priority level */
787: 1, /* segment descriptor present */
1.40 andrew 788: 0, 0,
1.1 cgd 789: 1, /* default 32 vs 16 bit size */
790: 1 /* limit granularity (byte/page units)*/ },
791: /* Data Descriptor for kernel */
792: { 0x0, /* segment base address */
793: 0xfffff, /* length - all address space */
794: SDT_MEMRWA, /* segment type */
795: 0, /* segment descriptor priority level */
796: 1, /* segment descriptor present */
1.40 andrew 797: 0, 0,
1.1 cgd 798: 1, /* default 32 vs 16 bit size */
799: 1 /* limit granularity (byte/page units)*/ },
800: /* LDT Descriptor */
801: { (int) ldt, /* segment base address */
802: sizeof(ldt)-1, /* length - all address space */
803: SDT_SYSLDT, /* segment type */
804: 0, /* segment descriptor priority level */
805: 1, /* segment descriptor present */
1.40 andrew 806: 0, 0,
1.1 cgd 807: 0, /* unused - default 32 vs 16 bit size */
808: 0 /* limit granularity (byte/page units)*/ },
809: /* Null Descriptor - Placeholder */
810: { 0x0, /* segment base address */
1.40 andrew 811: 0x0, /* length */
1.1 cgd 812: 0, /* segment type */
813: 0, /* segment descriptor priority level */
814: 0, /* segment descriptor present */
1.40 andrew 815: 0, 0,
1.1 cgd 816: 0, /* default 32 vs 16 bit size */
817: 0 /* limit granularity (byte/page units)*/ },
818: /* Panic Tss Descriptor */
819: { (int) &panic_tss, /* segment base address */
820: sizeof(tss)-1, /* length - all address space */
821: SDT_SYS386TSS, /* segment type */
822: 0, /* segment descriptor priority level */
823: 1, /* segment descriptor present */
1.40 andrew 824: 0, 0,
1.1 cgd 825: 0, /* unused - default 32 vs 16 bit size */
826: 0 /* limit granularity (byte/page units)*/ },
827: /* Proc 0 Tss Descriptor */
1.59 mycroft 828: { (int) USRSTACK, /* segment base address */
1.1 cgd 829: sizeof(tss)-1, /* length - all address space */
830: SDT_SYS386TSS, /* segment type */
831: 0, /* segment descriptor priority level */
832: 1, /* segment descriptor present */
1.40 andrew 833: 0, 0,
1.1 cgd 834: 0, /* unused - default 32 vs 16 bit size */
1.49 brezak 835: 0 /* limit granularity (byte/page units)*/ },
836: /* User LDT Descriptor per process */
837: { (int) ldt, /* segment base address */
838: (512 * sizeof(union descriptor)-1), /* length */
839: SDT_SYSLDT, /* segment type */
840: 0, /* segment descriptor priority level */
841: 1, /* segment descriptor present */
842: 0, 0,
843: 0, /* unused - default 32 vs 16 bit size */
844: 0 /* limit granularity (byte/page units)*/ },
845: };
1.1 cgd 846:
847: struct soft_segment_descriptor ldt_segs[] = {
848: /* Null Descriptor - overwritten by call gate */
849: { 0x0, /* segment base address */
1.40 andrew 850: 0x0, /* length */
1.1 cgd 851: 0, /* segment type */
852: 0, /* segment descriptor priority level */
853: 0, /* segment descriptor present */
1.40 andrew 854: 0, 0,
1.1 cgd 855: 0, /* default 32 vs 16 bit size */
856: 0 /* limit granularity (byte/page units)*/ },
857: /* Null Descriptor - overwritten by call gate */
858: { 0x0, /* segment base address */
1.40 andrew 859: 0x0, /* length */
1.1 cgd 860: 0, /* segment type */
861: 0, /* segment descriptor priority level */
862: 0, /* segment descriptor present */
1.40 andrew 863: 0, 0,
1.1 cgd 864: 0, /* default 32 vs 16 bit size */
865: 0 /* limit granularity (byte/page units)*/ },
866: /* Null Descriptor - overwritten by call gate */
867: { 0x0, /* segment base address */
1.40 andrew 868: 0x0, /* length */
1.1 cgd 869: 0, /* segment type */
870: 0, /* segment descriptor priority level */
871: 0, /* segment descriptor present */
1.40 andrew 872: 0, 0,
1.1 cgd 873: 0, /* default 32 vs 16 bit size */
874: 0 /* limit granularity (byte/page units)*/ },
875: /* Code Descriptor for user */
876: { 0x0, /* segment base address */
877: 0xfffff, /* length - all address space */
878: SDT_MEMERA, /* segment type */
879: SEL_UPL, /* segment descriptor priority level */
880: 1, /* segment descriptor present */
1.40 andrew 881: 0, 0,
1.1 cgd 882: 1, /* default 32 vs 16 bit size */
883: 1 /* limit granularity (byte/page units)*/ },
884: /* Data Descriptor for user */
885: { 0x0, /* segment base address */
886: 0xfffff, /* length - all address space */
887: SDT_MEMRWA, /* segment type */
888: SEL_UPL, /* segment descriptor priority level */
889: 1, /* segment descriptor present */
1.40 andrew 890: 0, 0,
1.1 cgd 891: 1, /* default 32 vs 16 bit size */
892: 1 /* limit granularity (byte/page units)*/ } };
893:
1.59 mycroft 894: void
895: setidt(idx, func, typ, dpl)
896: int idx;
897: char *func;
898: int typ, dpl;
899: {
1.1 cgd 900: struct gate_descriptor *ip = idt + idx;
901:
902: ip->gd_looffset = (int)func;
903: ip->gd_selector = 8;
904: ip->gd_stkcpy = 0;
905: ip->gd_xx = 0;
906: ip->gd_type = typ;
907: ip->gd_dpl = dpl;
908: ip->gd_p = 1;
1.59 mycroft 909: ip->gd_hioffset = ((int)func)>>16;
1.1 cgd 910: }
911:
912: #define IDTVEC(name) __CONCAT(X, name)
913: extern IDTVEC(div), IDTVEC(dbg), IDTVEC(nmi), IDTVEC(bpt), IDTVEC(ofl),
914: IDTVEC(bnd), IDTVEC(ill), IDTVEC(dna), IDTVEC(dble), IDTVEC(fpusegm),
915: IDTVEC(tss), IDTVEC(missing), IDTVEC(stk), IDTVEC(prot),
1.62 mycroft 916: IDTVEC(page), IDTVEC(rsvd), IDTVEC(fpu), IDTVEC(align),
1.1 cgd 917: IDTVEC(rsvd1), IDTVEC(rsvd2), IDTVEC(rsvd3), IDTVEC(rsvd4),
918: IDTVEC(rsvd5), IDTVEC(rsvd6), IDTVEC(rsvd7), IDTVEC(rsvd8),
919: IDTVEC(rsvd9), IDTVEC(rsvd10), IDTVEC(rsvd11), IDTVEC(rsvd12),
920: IDTVEC(rsvd13), IDTVEC(rsvd14), IDTVEC(rsvd14), IDTVEC(syscall);
921:
1.59 mycroft 922: void
1.43 brezak 923: init386(first_avail)
924: vm_offset_t first_avail;
1.2 cgd 925: {
1.73 mycroft 926: extern ssdtosd(), lgdt(), etext;
1.1 cgd 927: int x, *pi;
928: unsigned biosbasemem, biosextmem;
929: struct gate_descriptor *gdp;
1.22 cgd 930: extern char sigcode[], esigcode[];
1.1 cgd 931: /* table descriptors - used to load tables by microp */
932: struct region_descriptor r_gdt, r_idt;
933:
934: proc0.p_addr = proc0paddr;
935:
1.59 mycroft 936: cninit(); /* XXXX should be consinit() */
1.1 cgd 937:
1.28 cgd 938: #ifndef LKM /* don't do this if we're using LKM's */
1.59 mycroft 939: /* set code segment limit to end of kernel text */
940: gdt_segs[GCODE_SEL].ssd_limit = i386_btop(i386_round_page(&etext)) - 1;
1.28 cgd 941: #endif
942:
1.59 mycroft 943: for (x = 0; x < NGDT; x++)
944: ssdtosd(gdt_segs + x, gdt + x);
945:
1.1 cgd 946: /* make ldt memory segments */
1.59 mycroft 947: ldt_segs[LUCODE_SEL].ssd_limit = i386_btop(VM_MAXUSER_ADDRESS) - 1;
948: ldt_segs[LUDATA_SEL].ssd_limit = i386_btop(VM_MAXUSER_ADDRESS) - 1;
949: for (x = 0; x < NLDT; x++)
950: ssdtosd(ldt_segs + x, ldt + x);
1.1 cgd 951:
952: /* exceptions */
1.59 mycroft 953: setidt(0, &IDTVEC(div), SDT_SYS386TGT, SEL_KPL);
954: setidt(1, &IDTVEC(dbg), SDT_SYS386TGT, SEL_KPL);
955: setidt(2, &IDTVEC(nmi), SDT_SYS386TGT, SEL_KPL);
1.73 mycroft 956: setidt(3, &IDTVEC(bpt), SDT_SYS386TGT, SEL_UPL); /* XXXX */
1.59 mycroft 957: setidt(4, &IDTVEC(ofl), SDT_SYS386TGT, SEL_KPL);
958: setidt(5, &IDTVEC(bnd), SDT_SYS386TGT, SEL_KPL);
959: setidt(6, &IDTVEC(ill), SDT_SYS386TGT, SEL_KPL);
960: setidt(7, &IDTVEC(dna), SDT_SYS386TGT, SEL_KPL);
961: setidt(8, &IDTVEC(dble), SDT_SYS386TGT, SEL_KPL);
962: setidt(9, &IDTVEC(fpusegm), SDT_SYS386TGT, SEL_KPL);
963: setidt(10, &IDTVEC(tss), SDT_SYS386TGT, SEL_KPL);
964: setidt(11, &IDTVEC(missing), SDT_SYS386TGT, SEL_KPL);
965: setidt(12, &IDTVEC(stk), SDT_SYS386TGT, SEL_KPL);
966: setidt(13, &IDTVEC(prot), SDT_SYS386TGT, SEL_KPL);
967: setidt(14, &IDTVEC(page), SDT_SYS386TGT, SEL_KPL);
968: setidt(15, &IDTVEC(rsvd), SDT_SYS386TGT, SEL_KPL);
969: setidt(16, &IDTVEC(fpu), SDT_SYS386TGT, SEL_KPL);
1.62 mycroft 970: setidt(17, &IDTVEC(align), SDT_SYS386TGT, SEL_KPL);
1.59 mycroft 971: setidt(18, &IDTVEC(rsvd1), SDT_SYS386TGT, SEL_KPL);
972: setidt(19, &IDTVEC(rsvd2), SDT_SYS386TGT, SEL_KPL);
973: setidt(20, &IDTVEC(rsvd3), SDT_SYS386TGT, SEL_KPL);
974: setidt(21, &IDTVEC(rsvd4), SDT_SYS386TGT, SEL_KPL);
975: setidt(22, &IDTVEC(rsvd5), SDT_SYS386TGT, SEL_KPL);
976: setidt(23, &IDTVEC(rsvd6), SDT_SYS386TGT, SEL_KPL);
977: setidt(24, &IDTVEC(rsvd7), SDT_SYS386TGT, SEL_KPL);
978: setidt(25, &IDTVEC(rsvd8), SDT_SYS386TGT, SEL_KPL);
979: setidt(26, &IDTVEC(rsvd9), SDT_SYS386TGT, SEL_KPL);
980: setidt(27, &IDTVEC(rsvd10), SDT_SYS386TGT, SEL_KPL);
981: setidt(28, &IDTVEC(rsvd11), SDT_SYS386TGT, SEL_KPL);
982: setidt(29, &IDTVEC(rsvd12), SDT_SYS386TGT, SEL_KPL);
983: setidt(30, &IDTVEC(rsvd13), SDT_SYS386TGT, SEL_KPL);
984: setidt(31, &IDTVEC(rsvd14), SDT_SYS386TGT, SEL_KPL);
1.1 cgd 985:
986: #if NISA >0
987: isa_defaultirq();
988: #endif
989: r_gdt.rd_limit = sizeof(gdt)-1;
990: r_gdt.rd_base = (int) gdt;
991: lgdt(&r_gdt);
992: r_idt.rd_limit = sizeof(idt)-1;
993: r_idt.rd_base = (int) idt;
994: lidt(&r_idt);
1.59 mycroft 995: _default_ldt = GSEL(GLDT_SEL, SEL_KPL);
1.49 brezak 996: lldt(_default_ldt);
1.59 mycroft 997: currentldt = _default_ldt;
1.1 cgd 998:
1.5 glass 999: #ifdef DDB
1.42 brezak 1000: ddb_init();
1.1 cgd 1001: if (boothowto & RB_KDB)
1002: Debugger();
1003: #endif
1.43 brezak 1004: #ifdef KGDB
1005: if (boothowto & RB_KDB)
1.59 mycroft 1006: kgdb_connect(0);
1.43 brezak 1007: #endif
1.1 cgd 1008:
1.59 mycroft 1009: /*
1010: * Use BIOS values stored in RTC CMOS RAM, since probing
1.1 cgd 1011: * breaks certain 386 AT relics.
1012: */
1.73 mycroft 1013: biosbasemem = (rtcin(RTC_BASEHI)<<8) | (rtcin(RTC_BASELO));
1014: biosextmem = (rtcin(RTC_EXTHI)<<8) | (rtcin(RTC_EXTLO));
1.59 mycroft 1015:
1016: #ifndef BIOS_BASEMEM
1017: #define BIOS_BASEMEM 640
1018: #endif
1.2 cgd 1019:
1.59 mycroft 1020: if (biosbasemem == 0 || biosbasemem > 640) {
1021: printf("warning: nvram reports %dk base memory; assuming %dk\n",
1.73 mycroft 1022: biosbasemem, BIOS_BASEMEM);
1.59 mycroft 1023: biosbasemem = BIOS_BASEMEM;
1.2 cgd 1024: }
1025:
1.59 mycroft 1026: avail_start = NBPG; /* BIOS leaves data in low memory */
1.43 brezak 1027: /* and VM system doesn't work with phys 0 */
1.59 mycroft 1028: avail_end = biosextmem ? IOM_END + biosextmem * 1024
1.73 mycroft 1029: : biosbasemem * 1024;
1030:
1.59 mycroft 1031: /* number of pages of physmem addr space */
1032: physmem = btoc((biosbasemem + biosextmem) * 1024);
1.2 cgd 1033:
1.43 brezak 1034: /*
1.59 mycroft 1035: * Initialize for pmap_free_pages and pmap_next_page.
1036: * These guys should be page-aligned.
1.43 brezak 1037: */
1038: hole_start = biosbasemem * 1024;
1.59 mycroft 1039: /* we load right after the I/O hole; adjust hole_end to compensate */
1.43 brezak 1040: hole_end = round_page((vm_offset_t)first_avail);
1041: avail_next = avail_start;
1.59 mycroft 1042: avail_remaining = i386_btop((avail_end - avail_start) -
1043: (hole_end - hole_start));
1.73 mycroft 1044:
1.59 mycroft 1045: if (avail_remaining < i386_btop(2 * 1024 * 1024)) {
1046: printf("warning: too little memory available; running in degraded mode\n"
1.73 mycroft 1047: "press a key to confirm\n\n");
1.2 cgd 1048: /*
1.59 mycroft 1049: * People with less than 2 Meg have to press a key; this way
1.2 cgd 1050: * we see the messages and can tell them why they blow up later.
1.59 mycroft 1051: * If they get working well enough to recompile, they can remove
1052: * this; otherwise, it's a toy and they have to lump it.
1.2 cgd 1053: */
1.20 deraadt 1054: cngetc();
1.2 cgd 1055: }
1.59 mycroft 1056:
1.1 cgd 1057: /* call pmap initialization to make new kernel address space */
1.59 mycroft 1058: pmap_bootstrap((vm_offset_t)atdevbase + IOM_SIZE);
1.73 mycroft 1059:
1.1 cgd 1060: /* now running on new page tables, configured,and u/iom is accessible */
1061:
1062: /* make a initial tss so microp can get interrupt stack on syscall! */
1.59 mycroft 1063: proc0.p_addr->u_pcb.pcb_tss.tss_esp0 = (int) USRSTACK + UPAGES*NBPG;
1064: proc0.p_addr->u_pcb.pcb_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL);
1.1 cgd 1065: _gsel_tss = GSEL(GPROC0_SEL, SEL_KPL);
1.11 cgd 1066:
1.73 mycroft 1067: ((struct i386tss *)gdt_segs[GPROC0_SEL].ssd_base)->tss_ioopt =
1.11 cgd 1068: (sizeof(tss))<<16;
1069:
1.1 cgd 1070: ltr(_gsel_tss);
1071:
1072: /* make a call gate to reenter kernel with */
1073: gdp = &ldt[LSYS5CALLS_SEL].gd;
1.73 mycroft 1074:
1.1 cgd 1075: x = (int) &IDTVEC(syscall);
1076: gdp->gd_looffset = x++;
1.83 ! mycroft 1077: gdp->gd_selector = GSEL(GCODE_SEL, SEL_KPL);
1.59 mycroft 1078: gdp->gd_stkcpy = 1; /* leaves room for eflags like a trap */
1.1 cgd 1079: gdp->gd_type = SDT_SYS386CGT;
1080: gdp->gd_dpl = SEL_UPL;
1081: gdp->gd_p = 1;
1082: gdp->gd_hioffset = ((int) &IDTVEC(syscall)) >>16;
1083:
1084: /* transfer to user mode */
1085: _ucodesel = LSEL(LUCODE_SEL, SEL_UPL);
1086: _udatasel = LSEL(LUDATA_SEL, SEL_UPL);
1087:
1088: /* setup proc 0's pcb */
1089: proc0.p_addr->u_pcb.pcb_flags = 0;
1090: proc0.p_addr->u_pcb.pcb_ptd = IdlePTD;
1091: }
1092:
1093: /*
1.73 mycroft 1094: * insert an element into a queue
1.1 cgd 1095: */
1096: #undef insque
1097: _insque(element, head)
1098: register struct prochd *element, *head;
1099: {
1100: element->ph_link = head->ph_link;
1101: head->ph_link = (struct proc *)element;
1102: element->ph_rlink = (struct proc *)head;
1103: ((struct prochd *)(element->ph_link))->ph_rlink=(struct proc *)element;
1104: }
1105:
1106: /*
1107: * remove an element from a queue
1108: */
1109: #undef remque
1110: _remque(element)
1111: register struct prochd *element;
1112: {
1113: ((struct prochd *)(element->ph_link))->ph_rlink = element->ph_rlink;
1114: ((struct prochd *)(element->ph_rlink))->ph_link = element->ph_link;
1115: element->ph_rlink = (struct proc *)0;
1116: }
1117:
1.46 cgd 1118: /*
1119: * cpu_exec_aout_makecmds():
1120: * cpu-dependent a.out format hook for execve().
1.73 mycroft 1121: *
1.46 cgd 1122: * Determine of the given exec package refers to something which we
1123: * understand and, if so, set up the vmcmds for it.
1124: *
1125: * On the i386, old (386bsd) ZMAGIC binaries and BSDI QMAGIC binaries
1126: * if COMPAT_NOMID is given as a kernel option.
1127: */
1.67 mycroft 1128: int
1.46 cgd 1129: cpu_exec_aout_makecmds(p, epp)
1.59 mycroft 1130: struct proc *p;
1131: struct exec_package *epp;
1.31 cgd 1132: {
1133: #ifdef COMPAT_NOMID
1.59 mycroft 1134: int error;
1135: u_long midmag, magic;
1136: u_short mid;
1.80 cgd 1137: struct exec *execp = epp->ep_hdr;
1.31 cgd 1138:
1.80 cgd 1139: /* check on validity of epp->ep_hdr performed by exec_out_makecmds */
1140:
1141: midmag = ntohl(execp->a_midmag);
1.59 mycroft 1142: mid = (midmag >> 16) & 0xffff;
1143: magic = midmag & 0xffff;
1144:
1145: if (magic == 0) {
1.80 cgd 1146: magic = (execp->a_midmag & 0xffff);
1.59 mycroft 1147: mid = MID_ZERO;
1148: }
1149:
1150: midmag = mid << 16 | magic;
1151:
1152: switch (midmag) {
1153: case (MID_ZERO << 16) | ZMAGIC:
1154: /*
1155: * 386BSD's ZMAGIC format:
1156: */
1157: error = cpu_exec_aout_prep_oldzmagic(p, epp);
1158: break;
1159:
1160: case (MID_ZERO << 16) | QMAGIC:
1161: /*
1162: * BSDI's QMAGIC format:
1163: * same as new ZMAGIC format, but with different magic number
1164: */
1165: error = exec_aout_prep_zmagic(p, epp);
1166: break;
1167:
1168: default:
1169: error = ENOEXEC;
1170: }
1171:
1172: return error;
1.31 cgd 1173: #else /* ! COMPAT_NOMID */
1.59 mycroft 1174: return ENOEXEC;
1.31 cgd 1175: #endif
1176: }
1.24 cgd 1177:
1.31 cgd 1178: #ifdef COMPAT_NOMID
1.46 cgd 1179: /*
1180: * cpu_exec_aout_prep_oldzmagic():
1181: * Prepare the vmcmds to build a vmspace for an old (386BSD) ZMAGIC
1182: * binary.
1183: *
1184: * Cloned from exec_aout_prep_zmagic() in kern/exec_aout.c; a more verbose
1185: * description of operation is there.
1186: */
1.24 cgd 1187: int
1.46 cgd 1188: cpu_exec_aout_prep_oldzmagic(p, epp)
1.59 mycroft 1189: struct proc *p;
1190: struct exec_package *epp;
1.24 cgd 1191: {
1.80 cgd 1192: struct exec *execp = epp->ep_hdr;
1.59 mycroft 1193: struct exec_vmcmd *ccmdp;
1.24 cgd 1194:
1.59 mycroft 1195: epp->ep_taddr = 0;
1196: epp->ep_tsize = execp->a_text;
1197: epp->ep_daddr = epp->ep_taddr + execp->a_text;
1198: epp->ep_dsize = execp->a_data + execp->a_bss;
1199: epp->ep_entry = execp->a_entry;
1200:
1201: /*
1202: * check if vnode is in open for writing, because we want to
1203: * demand-page out of it. if it is, don't do it, for various
1204: * reasons
1205: */
1206: if ((execp->a_text != 0 || execp->a_data != 0) &&
1207: epp->ep_vp->v_writecount != 0) {
1.31 cgd 1208: #ifdef DIAGNOSTIC
1.59 mycroft 1209: if (epp->ep_vp->v_flag & VTEXT)
1210: panic("exec: a VTEXT vnode has writecount != 0\n");
1.31 cgd 1211: #endif
1.59 mycroft 1212: return ETXTBSY;
1213: }
1214: epp->ep_vp->v_flag |= VTEXT;
1215:
1216: /* set up command for text segment */
1.69 cgd 1217: NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_pagedvn, execp->a_text,
1218: epp->ep_taddr, epp->ep_vp, NBPG, /* XXX should NBPG be CLBYTES? */
1219: VM_PROT_READ|VM_PROT_EXECUTE);
1.59 mycroft 1220:
1221: /* set up command for data segment */
1.69 cgd 1222: NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_pagedvn, execp->a_data,
1223: epp->ep_daddr, epp->ep_vp,
1224: execp->a_text + NBPG, /* XXX should NBPG be CLBYTES? */
1225: VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
1.59 mycroft 1226:
1227: /* set up command for bss segment */
1.69 cgd 1228: NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero, execp->a_bss,
1.71 mycroft 1229: epp->ep_daddr + execp->a_data, NULLVP, 0,
1.69 cgd 1230: VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
1.24 cgd 1231:
1.69 cgd 1232: return exec_aout_setup_stack(p, epp);
1.1 cgd 1233: }
1.31 cgd 1234: #endif /* COMPAT_NOMID */
1.43 brezak 1235:
1.59 mycroft 1236: unsigned int
1237: pmap_free_pages()
1238: {
1239:
1240: return avail_remaining;
1241: }
1242:
1243: int
1244: pmap_next_page(addrp)
1245: vm_offset_t *addrp;
1246: {
1247:
1248: if (avail_next == avail_end)
1249: return FALSE;
1.73 mycroft 1250:
1.59 mycroft 1251: /* skip the hole */
1252: if (avail_next == hole_start)
1253: avail_next = hole_end;
1.73 mycroft 1254:
1.59 mycroft 1255: *addrp = avail_next;
1256: avail_next += NBPG;
1257: avail_remaining--;
1258: return TRUE;
1259: }
1260:
1261: unsigned int
1262: pmap_page_index(pa)
1263: vm_offset_t pa;
1264: {
1265:
1266: if (pa >= avail_start && pa < hole_start)
1267: return i386_btop(pa - avail_start);
1268: if (pa >= hole_end && pa < avail_end)
1269: return i386_btop(pa - hole_end + hole_start - avail_start);
1270: return -1;
1.45 cgd 1271: }
CVSweb <webmaster@jp.NetBSD.org>