xref: /original-bsd/sys/i386/i386/machdep.c (revision e0707c81)
1 /*-
2  * Copyright (c) 1982, 1987, 1990 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * William Jolitz.
7  *
8  * %sccs.include.redist.c%
9  *
10  *	@(#)machdep.c	7.16 (Berkeley) 05/21/93
11  */
12 
13 #include <sys/param.h>
14 #include <sys/systm.h>
15 #include <sys/signalvar.h>
16 #include <sys/kernel.h>
17 #include <sys/map.h>
18 #include <sys/proc.h>
19 #include <sys/user.h>
20 #include <sys/buf.h>
21 #include <sys/reboot.h>
22 #include <sys/conf.h>
23 #include <sys/file.h>
24 #include <sys/clist.h>
25 #include <sys/callout.h>
26 #include <sys/malloc.h>
27 #include <sys/mbuf.h>
28 #include <sys/msgbuf.h>
29 
30 #include <net/netisr.h>
31 
32 #include <vm/vm.h>
33 #include <vm/vm_kern.h>
34 #include <vm/vm_page.h>
35 
36 vm_map_t buffer_map;
37 extern vm_offset_t avail_end;
38 
39 #include <machine/cpu.h>
40 #include <machine/reg.h>
41 #include <machine/psl.h>
42 #include <machine/specialreg.h>
43 #include <i386/isa/rtc.h>
44 
45 /*
46  * Declare these as initialized data so we can patch them.
47  */
48 int	nswbuf = 0;
49 #ifdef	NBUF
50 int	nbuf = NBUF;
51 #else
52 int	nbuf = 0;
53 #endif
54 #ifdef	BUFPAGES
55 int	bufpages = BUFPAGES;
56 #else
57 int	bufpages = 0;
58 #endif
59 int	msgbufmapped;		/* set when safe to use msgbuf */
60 
61 /*
62  * Machine-dependent startup code
63  */
64 int boothowto = 0, Maxmem = 0;
65 long dumplo;
66 int physmem, maxmem;
67 extern int bootdev;
68 #ifdef SMALL
69 extern int forcemaxmem;
70 #endif
71 int biosmem;
72 
73 extern cyloffset;
74 
75 cpu_startup(firstaddr)
76 	int firstaddr;
77 {
78 	register int unixsize;
79 	register unsigned i;
80 	register struct pte *pte;
81 	int mapaddr, j;
82 	register caddr_t v;
83 	int maxbufs, base, residual;
84 	extern long Usrptsize;
85 	vm_offset_t minaddr, maxaddr;
86 	vm_size_t size;
87 
88 	/*
89 	 * Initialize error message buffer (at end of core).
90 	 */
91 
92 	/* avail_end was pre-decremented in pmap_bootstrap to compensate */
93 	for (i = 0; i < btoc(sizeof (struct msgbuf)); i++)
94 		pmap_enter(kernel_pmap, msgbufp, avail_end + i * NBPG,
95 			   VM_PROT_ALL, TRUE);
96 	msgbufmapped = 1;
97 
98 #ifdef KDB
99 	kdb_init();			/* startup kernel debugger */
100 #endif
101 	/*
102 	 * Good {morning,afternoon,evening,night}.
103 	 */
104 	printf(version);
105 	printf("real mem  = %d\n", ctob(physmem));
106 
107 	/*
108 	 * Allocate space for system data structures.
109 	 * The first available real memory address is in "firstaddr".
110 	 * The first available kernel virtual address is in "v".
111 	 * As pages of kernel virtual memory are allocated, "v" is incremented.
112 	 * As pages of memory are allocated and cleared,
113 	 * "firstaddr" is incremented.
114 	 * An index into the kernel page table corresponding to the
115 	 * virtual memory address maintained in "v" is kept in "mapaddr".
116 	 */
117 
118 	/*
119 	 * Make two passes.  The first pass calculates how much memory is
120 	 * needed and allocates it.  The second pass assigns virtual
121 	 * addresses to the various data structures.
122 	 */
123 	firstaddr = 0;
124 again:
125 	v = (caddr_t)firstaddr;
126 
127 #define	valloc(name, type, num) \
128 	    (name) = (type *)v; v = (caddr_t)((name)+(num))
129 #define	valloclim(name, type, num, lim) \
130 	    (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num)))
131 	valloc(cfree, struct cblock, nclist);
132 	valloc(callout, struct callout, ncallout);
133 	valloc(swapmap, struct map, nswapmap = maxproc * 2);
134 #ifdef SYSVSHM
135 	valloc(shmsegs, struct shmid_ds, shminfo.shmmni);
136 #endif
137 	/*
138 	 * Determine how many buffers to allocate.
139 	 * Use 10% of memory for the first 2 Meg, 5% of the remaining
140 	 * memory. Insure a minimum of 16 buffers.
141 	 * We allocate 1/2 as many swap buffer headers as file i/o buffers.
142 	 */
143 	if (bufpages == 0)
144 		if (physmem < (2 * 1024 * 1024))
145 			bufpages = physmem / 10 / CLSIZE;
146 		else
147 			bufpages = ((2 * 1024 * 1024 + physmem) / 20) / CLSIZE;
148 	if (nbuf == 0) {
149 		nbuf = bufpages / 2;
150 		if (nbuf < 16)
151 			nbuf = 16;
152 	}
153 	if (nswbuf == 0) {
154 		nswbuf = (nbuf / 2) &~ 1;	/* force even */
155 		if (nswbuf > 256)
156 			nswbuf = 256;		/* sanity */
157 	}
158 	valloc(swbuf, struct buf, nswbuf);
159 	valloc(buf, struct buf, nbuf);
160 
161 	/*
162 	 * End of first pass, size has been calculated so allocate memory
163 	 */
164 	if (firstaddr == 0) {
165 		size = (vm_size_t)(v - firstaddr);
166 		firstaddr = (int)kmem_alloc(kernel_map, round_page(size));
167 		if (firstaddr == 0)
168 			panic("startup: no room for tables");
169 		goto again;
170 	}
171 	/*
172 	 * End of second pass, addresses have been assigned
173 	 */
174 	if ((vm_size_t)(v - firstaddr) != size)
175 		panic("startup: table size inconsistency");
176 	/*
177 	 * Now allocate buffers proper.  They are different than the above
178 	 * in that they usually occupy more virtual memory than physical.
179 	 */
180 	size = MAXBSIZE * nbuf;
181 	buffer_map = kmem_suballoc(kernel_map, (vm_offset_t)&buffers,
182 				   &maxaddr, size, FALSE);
183 	minaddr = (vm_offset_t)buffers;
184 	if (vm_map_find(buffer_map, vm_object_allocate(size), (vm_offset_t)0,
185 			&minaddr, size, FALSE) != KERN_SUCCESS)
186 		panic("startup: cannot allocate buffers");
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 	}
205 	/*
206 	 * Allocate a submap for exec arguments.  This map effectively
207 	 * limits the number of processes exec'ing at any time.
208 	 */
209 	exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
210 				 16*NCARGS, TRUE);
211 	/*
212 	 * Allocate a submap for physio
213 	 */
214 	phys_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
215 				 VM_PHYS_SIZE, TRUE);
216 
217 	/*
218 	 * Finally, allocate mbuf pool.  Since mclrefcnt is an off-size
219 	 * we use the more space efficient malloc in place of kmem_alloc.
220 	 */
221 	mclrefcnt = (char *)malloc(NMBCLUSTERS+CLBYTES/MCLBYTES,
222 				   M_MBUF, M_NOWAIT);
223 	bzero(mclrefcnt, NMBCLUSTERS+CLBYTES/MCLBYTES);
224 	mb_map = kmem_suballoc(kernel_map, (vm_offset_t)&mbutl, &maxaddr,
225 			       VM_MBUF_SIZE, FALSE);
226 	/*
227 	 * Initialize callouts
228 	 */
229 	callfree = callout;
230 	for (i = 1; i < ncallout; i++)
231 		callout[i-1].c_next = &callout[i];
232 	callout[i-1].c_next = NULL;
233 
234 	/*printf("avail mem = %d\n", ptoa(vm_page_free_count));*/
235 	printf("using %d buffers containing %d bytes of memory\n",
236 		nbuf, bufpages * CLBYTES);
237 
238 	/*
239 	 * Set up CPU-specific registers, cache, etc.
240 	 */
241 	initcpu();
242 
243 	/*
244 	 * Set up buffers, so they can be used to read disk labels.
245 	 */
246 	bufinit();
247 
248 	/*
249 	 * Configure the system.
250 	 */
251 	configure();
252 }
253 
254 #ifdef PGINPROF
255 /*
256  * Return the difference (in microseconds)
257  * between the  current time and a previous
258  * time as represented  by the arguments.
259  * If there is a pending clock interrupt
260  * which has not been serviced due to high
261  * ipl, return error code.
262  */
263 /*ARGSUSED*/
264 vmtime(otime, olbolt, oicr)
265 	register int otime, olbolt, oicr;
266 {
267 
268 	return (((time.tv_sec-otime)*60 + lbolt-olbolt)*16667);
269 }
270 #endif
271 
272 struct sigframe {
273 	int	sf_signum;
274 	int	sf_code;
275 	struct	sigcontext *sf_scp;
276 	sig_t	sf_handler;
277 	int	sf_eax;
278 	int	sf_edx;
279 	int	sf_ecx;
280 	struct	sigcontext sf_sc;
281 } ;
282 
283 extern int kstack[];
284 
285 /*
286  * Send an interrupt to process.
287  *
288  * Stack is set up to allow sigcode stored
289  * in u. to call routine, followed by kcall
290  * to sigreturn routine below.  After sigreturn
291  * resets the signal mask, the stack, and the
292  * frame pointer, it returns to the user
293  * specified pc, psl.
294  */
295 void
296 sendsig(catcher, sig, mask, code)
297 	sig_t catcher;
298 	int sig, mask;
299 	unsigned code;
300 {
301 	register struct proc *p = curproc;
302 	register int *regs;
303 	register struct sigframe *fp;
304 	struct sigacts *psp = p->p_sigacts;
305 	int oonstack, frmtrap;
306 
307 	regs = p->p_md.md_regs;
308         oonstack = psp->ps_sigstk.ss_flags & SA_ONSTACK;
309 	frmtrap = curpcb->pcb_flags & FM_TRAP;
310 	/*
311 	 * Allocate and validate space for the signal handler
312 	 * context. Note that if the stack is in P0 space, the
313 	 * call to grow() is a nop, and the useracc() check
314 	 * will fail if the process has not already allocated
315 	 * the space with a `brk'.
316 	 */
317 	if ((psp->ps_flags & SAS_ALTSTACK) &&
318 	    (psp->ps_sigstk.ss_flags & SA_ONSTACK) == 0 &&
319 	    (psp->ps_sigonstack & sigmask(sig))) {
320 		fp = (struct sigframe *)(psp->ps_sigstk.ss_base +
321 		    psp->ps_sigstk.ss_size - sizeof(struct sigframe));
322 		psp->ps_sigstk.ss_flags |= SA_ONSTACK;
323 	} else {
324 		if (frmtrap)
325 			fp = (struct sigframe *)(regs[tESP]
326 				- sizeof(struct sigframe));
327 		else
328 			fp = (struct sigframe *)(regs[sESP]
329 				- sizeof(struct sigframe));
330 	}
331 
332 	if ((unsigned)fp <= USRSTACK - ctob(p->p_vmspace->vm_ssize))
333 		(void)grow(p, (unsigned)fp);
334 
335 	if (useracc((caddr_t)fp, sizeof (struct sigframe), B_WRITE) == 0) {
336 		/*
337 		 * Process has trashed its stack; give it an illegal
338 		 * instruction to halt it in its tracks.
339 		 */
340 		SIGACTION(p, SIGILL) = SIG_DFL;
341 		sig = sigmask(SIGILL);
342 		p->p_sigignore &= ~sig;
343 		p->p_sigcatch &= ~sig;
344 		p->p_sigmask &= ~sig;
345 		psignal(p, SIGILL);
346 		return;
347 	}
348 
349 	/*
350 	 * Build the argument list for the signal handler.
351 	 */
352 	fp->sf_signum = sig;
353 	fp->sf_code = code;
354 	fp->sf_scp = &fp->sf_sc;
355 	fp->sf_handler = catcher;
356 
357 	/* save scratch registers */
358 	if(frmtrap) {
359 		fp->sf_eax = regs[tEAX];
360 		fp->sf_edx = regs[tEDX];
361 		fp->sf_ecx = regs[tECX];
362 	} else {
363 		fp->sf_eax = regs[sEAX];
364 		fp->sf_edx = regs[sEDX];
365 		fp->sf_ecx = regs[sECX];
366 	}
367 	/*
368 	 * Build the signal context to be used by sigreturn.
369 	 */
370 	fp->sf_sc.sc_onstack = oonstack;
371 	fp->sf_sc.sc_mask = mask;
372 	if(frmtrap) {
373 		fp->sf_sc.sc_sp = regs[tESP];
374 		fp->sf_sc.sc_fp = regs[tEBP];
375 		fp->sf_sc.sc_pc = regs[tEIP];
376 		fp->sf_sc.sc_ps = regs[tEFLAGS];
377 		regs[tESP] = (int)fp;
378 		regs[tEIP] = (int)((struct pcb *)kstack)->pcb_sigc;
379 	} else {
380 		fp->sf_sc.sc_sp = regs[sESP];
381 		fp->sf_sc.sc_fp = regs[sEBP];
382 		fp->sf_sc.sc_pc = regs[sEIP];
383 		fp->sf_sc.sc_ps = regs[sEFLAGS];
384 		regs[sESP] = (int)fp;
385 		regs[sEIP] = (int)((struct pcb *)kstack)->pcb_sigc;
386 	}
387 }
388 
389 /*
390  * System call to cleanup state after a signal
391  * has been taken.  Reset signal mask and
392  * stack state from context left by sendsig (above).
393  * Return to previous pc and psl as specified by
394  * context left by sendsig. Check carefully to
395  * make sure that the user has not modified the
396  * psl to gain improper priviledges or to cause
397  * a machine fault.
398  */
399 struct sigreturn_args {
400 	struct sigcontext *sigcntxp;
401 };
402 sigreturn(p, uap, retval)
403 	struct proc *p;
404 	struct sigreturn_args *uap;
405 	int *retval;
406 {
407 	register struct sigcontext *scp;
408 	register struct sigframe *fp;
409 	register int *regs = p->p_md.md_regs;
410 
411 
412 	fp = (struct sigframe *) regs[sESP] ;
413 
414 	if (useracc((caddr_t)fp, sizeof (*fp), 0) == 0)
415 		return(EINVAL);
416 
417 	/* restore scratch registers */
418 	regs[sEAX] = fp->sf_eax ;
419 	regs[sEDX] = fp->sf_edx ;
420 	regs[sECX] = fp->sf_ecx ;
421 
422 	scp = fp->sf_scp;
423 	if (useracc((caddr_t)scp, sizeof (*scp), 0) == 0)
424 		return(EINVAL);
425 #ifdef notyet
426 	if ((scp->sc_ps & PSL_MBZ) != 0 || (scp->sc_ps & PSL_MBO) != PSL_MBO) {
427 		return(EINVAL);
428 	}
429 #endif
430 	if (scp->sc_onstack & 01)
431 		p->p_sigacts->ps_sigstk.ss_flags |= SA_ONSTACK;
432 	else
433 		p->p_sigacts->ps_sigstk.ss_flags &= ~SA_ONSTACK;
434 	p->p_sigmask = scp->sc_mask &~
435 	    (sigmask(SIGKILL)|sigmask(SIGCONT)|sigmask(SIGSTOP));
436 	regs[sEBP] = scp->sc_fp;
437 	regs[sESP] = scp->sc_sp;
438 	regs[sEIP] = scp->sc_pc;
439 	regs[sEFLAGS] = scp->sc_ps;
440 	return(EJUSTRETURN);
441 }
442 
443 int	waittime = -1;
444 
445 boot(arghowto)
446 	int arghowto;
447 {
448 	register long dummy;		/* r12 is reserved */
449 	register int howto;		/* r11 == how to boot */
450 	register int devtype;		/* r10 == major of root dev */
451 	extern char *panicstr;
452 extern int cold;
453 
454 	howto = arghowto;
455 	if ((howto&RB_NOSYNC) == 0 && waittime < 0 && bfreelist[0].b_forw) {
456 		register struct buf *bp;
457 		int iter, nbusy;
458 
459 		waittime = 0;
460 		(void) splnet();
461 		printf("syncing disks... ");
462 		/*
463 		 * Release inodes held by texts before update.
464 		 */
465 		if (panicstr == 0)
466 			vnode_pager_umount(NULL);
467 		sync((struct sigcontext *)0);
468 
469 		for (iter = 0; iter < 20; iter++) {
470 			nbusy = 0;
471 			for (bp = &buf[nbuf]; --bp >= buf; )
472 				if ((bp->b_flags & (B_BUSY|B_INVAL)) == B_BUSY)
473 					nbusy++;
474 			if (nbusy == 0)
475 				break;
476 			printf("%d ", nbusy);
477 			DELAY(40000 * iter);
478 		}
479 		if (nbusy)
480 			printf("giving up\n");
481 		else
482 			printf("done\n");
483 		DELAY(10000);			/* wait for printf to finish */
484 	}
485 	splhigh();
486 	devtype = major(rootdev);
487 	if (howto&RB_HALT) {
488 		printf("halting (in tight loop); hit reset\n\n");
489 		splx(0xfffd);	/* all but keyboard XXX */
490 		for (;;) ;
491 	} else {
492 		if (howto & RB_DUMP) {
493 			dumpsys();
494 			/*NOTREACHED*/
495 		}
496 	}
497 #ifdef lint
498 	dummy = 0; dummy = dummy;
499 	printf("howto %d, devtype %d\n", arghowto, devtype);
500 #endif
501 #ifdef	notdef
502 	pg("pausing (hit any key to reset)");
503 #endif
504 	reset_cpu();
505 	for(;;) ;
506 	/*NOTREACHED*/
507 }
508 
509 int	dumpmag = 0x8fca0101;	/* magic number for savecore */
510 int	dumpsize = 0;		/* also for savecore */
511 /*
512  * Doadump comes here after turning off memory management and
513  * getting on the dump stack, either when called above, or by
514  * the auto-restart code.
515  */
516 dumpsys()
517 {
518 
519 	if (dumpdev == NODEV)
520 		return;
521 	if ((minor(dumpdev)&07) != 1)
522 		return;
523 	dumpsize = physmem;
524 	printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo);
525 	printf("dump ");
526 	switch ((*bdevsw[major(dumpdev)].d_dump)(dumpdev)) {
527 
528 	case ENXIO:
529 		printf("device bad\n");
530 		break;
531 
532 	case EFAULT:
533 		printf("device not ready\n");
534 		break;
535 
536 	case EINVAL:
537 		printf("area improper\n");
538 		break;
539 
540 	case EIO:
541 		printf("i/o error\n");
542 		break;
543 
544 	default:
545 		printf("succeeded\n");
546 		break;
547 	}
548 	printf("\n\n");
549 	DELAY(1000);
550 }
551 
552 microtime(tvp)
553 	register struct timeval *tvp;
554 {
555 	int s = splhigh();
556 
557 	*tvp = time;
558 	tvp->tv_usec += tick;
559 	while (tvp->tv_usec > 1000000) {
560 		tvp->tv_sec++;
561 		tvp->tv_usec -= 1000000;
562 	}
563 	splx(s);
564 }
565 
566 physstrat(bp, strat, prio)
567 	struct buf *bp;
568 	int (*strat)(), prio;
569 {
570 	register int s;
571 	caddr_t baddr;
572 
573 	/*
574 	 * vmapbuf clobbers b_addr so we must remember it so that it
575 	 * can be restored after vunmapbuf.  This is truely rude, we
576 	 * should really be storing this in a field in the buf struct
577 	 * but none are available and I didn't want to add one at
578 	 * this time.  Note that b_addr for dirty page pushes is
579 	 * restored in vunmapbuf. (ugh!)
580 	 */
581 	baddr = bp->b_un.b_addr;
582 	vmapbuf(bp);
583 	(*strat)(bp);
584 	/* pageout daemon doesn't wait for pushed pages */
585 	if (bp->b_flags & B_DIRTY)
586 		return;
587 	s = splbio();
588 	while ((bp->b_flags & B_DONE) == 0)
589 		sleep((caddr_t)bp, prio);
590 	splx(s);
591 	vunmapbuf(bp);
592 	bp->b_un.b_addr = baddr;
593 }
594 
595 initcpu()
596 {
597 }
598 
599 /*
600  * Clear registers on exec
601  */
602 setregs(p, entry, retval)
603 	register struct proc *p;
604 	u_long entry;
605 	int retval[2];
606 {
607 	p->p_md.md_regs[sEBP] = 0;	/* bottom of the fp chain */
608 	p->p_md.md_regs[sEIP] = entry;
609 
610 	p->p_addr->u_pcb.pcb_flags = 0;	/* no fp at all */
611 	load_cr0(rcr0() | CR0_EM);	/* start emulating */
612 #include "npx.h"
613 #if NNPX > 0
614 	npxinit(0x262);
615 #endif
616 }
617 
618 /*
619  * machine dependent system variables.
620  */
621 cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
622 	int *name;
623 	u_int namelen;
624 	void *oldp;
625 	size_t *oldlenp;
626 	void *newp;
627 	size_t newlen;
628 	struct proc *p;
629 {
630 
631 	/* all sysctl names at this level are terminal */
632 	if (namelen != 1)
633 		return (ENOTDIR);		/* overloaded */
634 
635 	switch (name[0]) {
636 	case CPU_CONSDEV:
637 		return (sysctl_rdstruct(oldp, oldlenp, newp, &cn_tty->t_dev,
638 		    sizeof cn_tty->t_dev));
639 	default:
640 		return (EOPNOTSUPP);
641 	}
642 	/* NOTREACHED */
643 }
644 
645 /*
646  * Initialize 386 and configure to run kernel
647  */
648 
649 /*
650  * Initialize segments & interrupt table
651  */
652 
653 
654 #define	GNULL_SEL	0	/* Null Descriptor */
655 #define	GCODE_SEL	1	/* Kernel Code Descriptor */
656 #define	GDATA_SEL	2	/* Kernel Data Descriptor */
657 #define	GLDT_SEL	3	/* LDT - eventually one per process */
658 #define	GTGATE_SEL	4	/* Process task switch gate */
659 #define	GPANIC_SEL	5	/* Task state to consider panic from */
660 #define	GPROC0_SEL	6	/* Task state process slot zero and up */
661 #define NGDT 	GPROC0_SEL+1
662 
663 union descriptor gdt[GPROC0_SEL+1];
664 
665 /* interrupt descriptor table */
666 struct gate_descriptor idt[32+16];
667 
668 /* local descriptor table */
669 union descriptor ldt[5];
670 #define	LSYS5CALLS_SEL	0	/* forced by intel BCS */
671 #define	LSYS5SIGR_SEL	1
672 
673 #define	L43BSDCALLS_SEL	2	/* notyet */
674 #define	LUCODE_SEL	3
675 #define	LUDATA_SEL	4
676 /* seperate stack, es,fs,gs sels ? */
677 /* #define	LPOSIXCALLS_SEL	5	/* notyet */
678 
679 struct	i386tss	tss, panic_tss;
680 
681 extern  struct user *proc0paddr;
682 
683 /* software prototypes -- in more palitable form */
684 struct soft_segment_descriptor gdt_segs[] = {
685 	/* Null Descriptor */
686 {	0x0,			/* segment base address  */
687 	0x0,			/* length - all address space */
688 	0,			/* segment type */
689 	0,			/* segment descriptor priority level */
690 	0,			/* segment descriptor present */
691 	0,0,
692 	0,			/* default 32 vs 16 bit size */
693 	0  			/* limit granularity (byte/page units)*/ },
694 	/* Code Descriptor for kernel */
695 {	0x0,			/* segment base address  */
696 	0xfffff,		/* length - all address space */
697 	SDT_MEMERA,		/* segment type */
698 	0,			/* segment descriptor priority level */
699 	1,			/* segment descriptor present */
700 	0,0,
701 	1,			/* default 32 vs 16 bit size */
702 	1  			/* limit granularity (byte/page units)*/ },
703 	/* Data Descriptor for kernel */
704 {	0x0,			/* segment base address  */
705 	0xfffff,		/* length - all address space */
706 	SDT_MEMRWA,		/* segment type */
707 	0,			/* segment descriptor priority level */
708 	1,			/* segment descriptor present */
709 	0,0,
710 	1,			/* default 32 vs 16 bit size */
711 	1  			/* limit granularity (byte/page units)*/ },
712 	/* LDT Descriptor */
713 {	(int) ldt,			/* segment base address  */
714 	sizeof(ldt)-1,		/* length - all address space */
715 	SDT_SYSLDT,		/* segment type */
716 	0,			/* segment descriptor priority level */
717 	1,			/* segment descriptor present */
718 	0,0,
719 	0,			/* unused - default 32 vs 16 bit size */
720 	0  			/* limit granularity (byte/page units)*/ },
721 	/* Null Descriptor - Placeholder */
722 {	0x0,			/* segment base address  */
723 	0x0,			/* length - all address space */
724 	0,			/* segment type */
725 	0,			/* segment descriptor priority level */
726 	0,			/* segment descriptor present */
727 	0,0,
728 	0,			/* default 32 vs 16 bit size */
729 	0  			/* limit granularity (byte/page units)*/ },
730 	/* Panic Tss Descriptor */
731 {	(int) &panic_tss,		/* segment base address  */
732 	sizeof(tss)-1,		/* length - all address space */
733 	SDT_SYS386TSS,		/* segment type */
734 	0,			/* segment descriptor priority level */
735 	1,			/* segment descriptor present */
736 	0,0,
737 	0,			/* unused - default 32 vs 16 bit size */
738 	0  			/* limit granularity (byte/page units)*/ },
739 	/* Proc 0 Tss Descriptor */
740 {	(int) kstack,			/* segment base address  */
741 	sizeof(tss)-1,		/* length - all address space */
742 	SDT_SYS386TSS,		/* segment type */
743 	0,			/* segment descriptor priority level */
744 	1,			/* segment descriptor present */
745 	0,0,
746 	0,			/* unused - default 32 vs 16 bit size */
747 	0  			/* limit granularity (byte/page units)*/ }};
748 
749 struct soft_segment_descriptor ldt_segs[] = {
750 	/* Null Descriptor - overwritten by call gate */
751 {	0x0,			/* segment base address  */
752 	0x0,			/* length - all address space */
753 	0,			/* segment type */
754 	0,			/* segment descriptor priority level */
755 	0,			/* segment descriptor present */
756 	0,0,
757 	0,			/* default 32 vs 16 bit size */
758 	0  			/* limit granularity (byte/page units)*/ },
759 	/* Null Descriptor - overwritten by call gate */
760 {	0x0,			/* segment base address  */
761 	0x0,			/* length - all address space */
762 	0,			/* segment type */
763 	0,			/* segment descriptor priority level */
764 	0,			/* segment descriptor present */
765 	0,0,
766 	0,			/* default 32 vs 16 bit size */
767 	0  			/* limit granularity (byte/page units)*/ },
768 	/* Null Descriptor - overwritten by call gate */
769 {	0x0,			/* segment base address  */
770 	0x0,			/* length - all address space */
771 	0,			/* segment type */
772 	0,			/* segment descriptor priority level */
773 	0,			/* segment descriptor present */
774 	0,0,
775 	0,			/* default 32 vs 16 bit size */
776 	0  			/* limit granularity (byte/page units)*/ },
777 	/* Code Descriptor for user */
778 {	0x0,			/* segment base address  */
779 	0xfffff,		/* length - all address space */
780 	SDT_MEMERA,		/* segment type */
781 	SEL_UPL,		/* segment descriptor priority level */
782 	1,			/* segment descriptor present */
783 	0,0,
784 	1,			/* default 32 vs 16 bit size */
785 	1  			/* limit granularity (byte/page units)*/ },
786 	/* Data Descriptor for user */
787 {	0x0,			/* segment base address  */
788 	0xfffff,		/* length - all address space */
789 	SDT_MEMRWA,		/* segment type */
790 	SEL_UPL,		/* segment descriptor priority level */
791 	1,			/* segment descriptor present */
792 	0,0,
793 	1,			/* default 32 vs 16 bit size */
794 	1  			/* limit granularity (byte/page units)*/ } };
795 
796 /* table descriptors - used to load tables by microp */
797 struct region_descriptor r_gdt = {
798 	sizeof(gdt)-1,(char *)gdt
799 };
800 
801 struct region_descriptor r_idt = {
802 	sizeof(idt)-1,(char *)idt
803 };
804 
805 setidt(idx, func, typ, dpl) char *func; {
806 	struct gate_descriptor *ip = idt + idx;
807 
808 	ip->gd_looffset = (int)func;
809 	ip->gd_selector = 8;
810 	ip->gd_stkcpy = 0;
811 	ip->gd_xx = 0;
812 	ip->gd_type = typ;
813 	ip->gd_dpl = dpl;
814 	ip->gd_p = 1;
815 	ip->gd_hioffset = ((int)func)>>16 ;
816 }
817 
818 #define	IDTVEC(name)	__CONCAT(X, name)
819 extern	IDTVEC(div), IDTVEC(dbg), IDTVEC(nmi), IDTVEC(bpt), IDTVEC(ofl),
820 	IDTVEC(bnd), IDTVEC(ill), IDTVEC(dna), IDTVEC(dble), IDTVEC(fpusegm),
821 	IDTVEC(tss), IDTVEC(missing), IDTVEC(stk), IDTVEC(prot),
822 	IDTVEC(page), IDTVEC(rsvd), IDTVEC(fpu), IDTVEC(rsvd0),
823 	IDTVEC(rsvd1), IDTVEC(rsvd2), IDTVEC(rsvd3), IDTVEC(rsvd4),
824 	IDTVEC(rsvd5), IDTVEC(rsvd6), IDTVEC(rsvd7), IDTVEC(rsvd8),
825 	IDTVEC(rsvd9), IDTVEC(rsvd10), IDTVEC(rsvd11), IDTVEC(rsvd12),
826 	IDTVEC(rsvd13), IDTVEC(rsvd14), IDTVEC(rsvd14), IDTVEC(syscall);
827 
828 int lcr0(), lcr3(), rcr0(), rcr2();
829 int _udatasel, _ucodesel, _gsel_tss;
830 
831 init386(first) { extern ssdtosd(), lgdt(), lidt(), lldt(), etext;
832 	int x, *pi;
833 	unsigned biosbasemem, biosextmem;
834 	struct gate_descriptor *gdp;
835 	extern int sigcode,szsigcode;
836 
837 	proc0.p_addr = proc0paddr;
838 
839 	/*
840 	 * Initialize the console before we print anything out.
841 	 */
842 
843 	cninit (KERNBASE+0xa0000);
844 
845 	/* make gdt memory segments */
846 	gdt_segs[GCODE_SEL].ssd_limit = btoc((int) &etext + NBPG);
847 	for (x=0; x < NGDT; x++) ssdtosd(gdt_segs+x, gdt+x);
848 	/* make ldt memory segments */
849 	ldt_segs[LUCODE_SEL].ssd_limit = btoc(UPT_MIN_ADDRESS);
850 	ldt_segs[LUDATA_SEL].ssd_limit = btoc(UPT_MIN_ADDRESS);
851 	/* Note. eventually want private ldts per process */
852 	for (x=0; x < 5; x++) ssdtosd(ldt_segs+x, ldt+x);
853 
854 	/* exceptions */
855 	setidt(0, &IDTVEC(div),  SDT_SYS386TGT, SEL_KPL);
856 	setidt(1, &IDTVEC(dbg),  SDT_SYS386TGT, SEL_KPL);
857 	setidt(2, &IDTVEC(nmi),  SDT_SYS386TGT, SEL_KPL);
858  	setidt(3, &IDTVEC(bpt),  SDT_SYS386TGT, SEL_UPL);
859 	setidt(4, &IDTVEC(ofl),  SDT_SYS386TGT, SEL_KPL);
860 	setidt(5, &IDTVEC(bnd),  SDT_SYS386TGT, SEL_KPL);
861 	setidt(6, &IDTVEC(ill),  SDT_SYS386TGT, SEL_KPL);
862 	setidt(7, &IDTVEC(dna),  SDT_SYS386TGT, SEL_KPL);
863 	setidt(8, &IDTVEC(dble),  SDT_SYS386TGT, SEL_KPL);
864 	setidt(9, &IDTVEC(fpusegm),  SDT_SYS386TGT, SEL_KPL);
865 	setidt(10, &IDTVEC(tss),  SDT_SYS386TGT, SEL_KPL);
866 	setidt(11, &IDTVEC(missing),  SDT_SYS386TGT, SEL_KPL);
867 	setidt(12, &IDTVEC(stk),  SDT_SYS386TGT, SEL_KPL);
868 	setidt(13, &IDTVEC(prot),  SDT_SYS386TGT, SEL_KPL);
869 	setidt(14, &IDTVEC(page),  SDT_SYS386TGT, SEL_KPL);
870 	setidt(15, &IDTVEC(rsvd),  SDT_SYS386TGT, SEL_KPL);
871 	setidt(16, &IDTVEC(fpu),  SDT_SYS386TGT, SEL_KPL);
872 	setidt(17, &IDTVEC(rsvd0),  SDT_SYS386TGT, SEL_KPL);
873 	setidt(18, &IDTVEC(rsvd1),  SDT_SYS386TGT, SEL_KPL);
874 	setidt(19, &IDTVEC(rsvd2),  SDT_SYS386TGT, SEL_KPL);
875 	setidt(20, &IDTVEC(rsvd3),  SDT_SYS386TGT, SEL_KPL);
876 	setidt(21, &IDTVEC(rsvd4),  SDT_SYS386TGT, SEL_KPL);
877 	setidt(22, &IDTVEC(rsvd5),  SDT_SYS386TGT, SEL_KPL);
878 	setidt(23, &IDTVEC(rsvd6),  SDT_SYS386TGT, SEL_KPL);
879 	setidt(24, &IDTVEC(rsvd7),  SDT_SYS386TGT, SEL_KPL);
880 	setidt(25, &IDTVEC(rsvd8),  SDT_SYS386TGT, SEL_KPL);
881 	setidt(26, &IDTVEC(rsvd9),  SDT_SYS386TGT, SEL_KPL);
882 	setidt(27, &IDTVEC(rsvd10),  SDT_SYS386TGT, SEL_KPL);
883 	setidt(28, &IDTVEC(rsvd11),  SDT_SYS386TGT, SEL_KPL);
884 	setidt(29, &IDTVEC(rsvd12),  SDT_SYS386TGT, SEL_KPL);
885 	setidt(30, &IDTVEC(rsvd13),  SDT_SYS386TGT, SEL_KPL);
886 	setidt(31, &IDTVEC(rsvd14),  SDT_SYS386TGT, SEL_KPL);
887 
888 #include "isa.h"
889 #if	NISA >0
890 	isa_defaultirq();
891 #endif
892 
893 	lgdt(gdt, sizeof(gdt)-1);
894 	lidt(idt, sizeof(idt)-1);
895 	lldt(GSEL(GLDT_SEL, SEL_KPL));
896 
897 	/*
898 	 * This memory size stuff is a real mess.  Here is a simple
899 	 * setup that just believes the BIOS.  After the rest of
900 	 * the system is a little more stable, we'll come back to
901 	 * this and deal with issues if incorrect BIOS information,
902 	 * and when physical memory is > 16 megabytes.
903 	 */
904 	biosbasemem = rtcin(RTC_BASELO)+ (rtcin(RTC_BASEHI)<<8);
905 	biosextmem = rtcin(RTC_EXTLO)+ (rtcin(RTC_EXTHI)<<8);
906 	Maxmem = btoc ((biosextmem + 1024) * 1024);
907 	maxmem = Maxmem - 1;
908 	physmem = btoc (biosbasemem * 1024 + (biosextmem - 1) * 1024);
909 	printf ("bios %dK+%dK. maxmem %x, physmem %x\n",
910 		biosbasemem, biosextmem, ctob (maxmem), ctob (physmem));
911 
912 	vm_set_page_size();
913 	/* call pmap initialization to make new kernel address space */
914 	pmap_bootstrap (first, 0);
915 	/* now running on new page tables, configured,and u/iom is accessible */
916 
917 	/* make a initial tss so microp can get interrupt stack on syscall! */
918 	proc0.p_addr->u_pcb.pcb_tss.tss_esp0 = (int) kstack + UPAGES*NBPG;
919 	proc0.p_addr->u_pcb.pcb_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL) ;
920 	_gsel_tss = GSEL(GPROC0_SEL, SEL_KPL);
921 	ltr(_gsel_tss);
922 
923 	/* make a call gate to reenter kernel with */
924 	gdp = &ldt[LSYS5CALLS_SEL].gd;
925 
926 	x = (int) &IDTVEC(syscall);
927 	gdp->gd_looffset = x++;
928 	gdp->gd_selector = GSEL(GCODE_SEL,SEL_KPL);
929 	gdp->gd_stkcpy = 0;
930 	gdp->gd_type = SDT_SYS386CGT;
931 	gdp->gd_dpl = SEL_UPL;
932 	gdp->gd_p = 1;
933 	gdp->gd_hioffset = ((int) &IDTVEC(syscall)) >>16;
934 
935 	/* transfer to user mode */
936 
937 	_ucodesel = LSEL(LUCODE_SEL, SEL_UPL);
938 	_udatasel = LSEL(LUDATA_SEL, SEL_UPL);
939 
940 	/* setup proc 0's pcb */
941 	bcopy(&sigcode, proc0.p_addr->u_pcb.pcb_sigc, szsigcode);
942 	proc0.p_addr->u_pcb.pcb_flags = 0;
943 	proc0.p_addr->u_pcb.pcb_ptd = IdlePTD;
944 }
945 
946 extern struct pte	*CMAP1, *CMAP2;
947 extern caddr_t		CADDR1, CADDR2;
948 /*
949  * zero out physical memory
950  * specified in relocation units (NBPG bytes)
951  */
952 clearseg(n) {
953 
954 	*(int *)CMAP2 = PG_V | PG_KW | ctob(n);
955 	load_cr3(rcr3());
956 	bzero(CADDR2,NBPG);
957 	*(int *) CADDR2 = 0;
958 }
959 
960 /*
961  * copy a page of physical memory
962  * specified in relocation units (NBPG bytes)
963  */
964 copyseg(frm, n) {
965 
966 	*(int *)CMAP2 = PG_V | PG_KW | ctob(n);
967 	load_cr3(rcr3());
968 	bcopy((void *)frm, (void *)CADDR2, NBPG);
969 }
970 
971 /*
972  * copy a page of physical memory
973  * specified in relocation units (NBPG bytes)
974  */
975 physcopyseg(frm, to) {
976 
977 	*(int *)CMAP1 = PG_V | PG_KW | ctob(frm);
978 	*(int *)CMAP2 = PG_V | PG_KW | ctob(to);
979 	load_cr3(rcr3());
980 	bcopy(CADDR1, CADDR2, NBPG);
981 }
982 
983 /*aston() {
984 	schednetisr(NETISR_AST);
985 }*/
986 
987 setsoftclock() {
988 	schednetisr(NETISR_SCLK);
989 }
990 
991 /*
992  * insert an element into a queue
993  */
994 #undef insque
995 _insque(element, head)
996 	register struct prochd *element, *head;
997 {
998 	element->ph_link = head->ph_link;
999 	head->ph_link = (struct proc *)element;
1000 	element->ph_rlink = (struct proc *)head;
1001 	((struct prochd *)(element->ph_link))->ph_rlink=(struct proc *)element;
1002 }
1003 
1004 /*
1005  * remove an element from a queue
1006  */
1007 #undef remque
1008 _remque(element)
1009 	register struct prochd *element;
1010 {
1011 	((struct prochd *)(element->ph_link))->ph_rlink = element->ph_rlink;
1012 	((struct prochd *)(element->ph_rlink))->ph_link = element->ph_link;
1013 	element->ph_rlink = (struct proc *)0;
1014 }
1015 
1016 vmunaccess() {}
1017 
1018 /*
1019  * Below written in C to allow access to debugging code
1020  */
1021 copyinstr(fromaddr, toaddr, maxlength, lencopied) u_int *lencopied, maxlength;
1022 	void *toaddr, *fromaddr; {
1023 	int c,tally;
1024 
1025 	tally = 0;
1026 	while (maxlength--) {
1027 		c = fubyte(fromaddr++);
1028 		if (c == -1) {
1029 			if(lencopied) *lencopied = tally;
1030 			return(EFAULT);
1031 		}
1032 		tally++;
1033 		*(char *)toaddr++ = (char) c;
1034 		if (c == 0){
1035 			if(lencopied) *lencopied = tally;
1036 			return(0);
1037 		}
1038 	}
1039 	if(lencopied) *lencopied = tally;
1040 	return(ENAMETOOLONG);
1041 }
1042 
1043 copyoutstr(fromaddr, toaddr, maxlength, lencopied) u_int *lencopied, maxlength;
1044 	void *fromaddr, *toaddr; {
1045 	int c;
1046 	int tally;
1047 
1048 	tally = 0;
1049 	while (maxlength--) {
1050 		c = subyte(toaddr++, *(char *)fromaddr);
1051 		if (c == -1) return(EFAULT);
1052 		tally++;
1053 		if (*(char *)fromaddr++ == 0){
1054 			if(lencopied) *lencopied = tally;
1055 			return(0);
1056 		}
1057 	}
1058 	if(lencopied) *lencopied = tally;
1059 	return(ENAMETOOLONG);
1060 }
1061 
1062 copystr(fromaddr, toaddr, maxlength, lencopied) u_int *lencopied, maxlength;
1063 	void *fromaddr, *toaddr; {
1064 	u_int tally;
1065 
1066 	tally = 0;
1067 	while (maxlength--) {
1068 		*(u_char *)toaddr = *(u_char *)fromaddr++;
1069 		tally++;
1070 		if (*(u_char *)toaddr++ == 0) {
1071 			if(lencopied) *lencopied = tally;
1072 			return(0);
1073 		}
1074 	}
1075 	if(lencopied) *lencopied = tally;
1076 	return(ENAMETOOLONG);
1077 }
1078