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