machdep.c revision 4
1345153Sdim/*-
2345153Sdim * Copyright (c) 1982, 1987, 1990 The Regents of the University of California.
3345153Sdim * Copyright (c) 1992 Terrence R. Lambert.
4345153Sdim * All rights reserved.
5345153Sdim *
6345153Sdim * This code is derived from software contributed to Berkeley by
7345153Sdim * William Jolitz.
8345153Sdim *
9345153Sdim * Redistribution and use in source and binary forms, with or without
10345153Sdim * modification, are permitted provided that the following conditions
11345153Sdim * are met:
12345153Sdim * 1. Redistributions of source code must retain the above copyright
13345153Sdim *    notice, this list of conditions and the following disclaimer.
14345153Sdim * 2. Redistributions in binary form must reproduce the above copyright
15345153Sdim *    notice, this list of conditions and the following disclaimer in the
16345153Sdim *    documentation and/or other materials provided with the distribution.
17345153Sdim * 3. All advertising materials mentioning features or use of this software
18345153Sdim *    must display the following acknowledgement:
19345153Sdim *	This product includes software developed by the University of
20345153Sdim *	California, Berkeley and its contributors.
21345153Sdim * 4. Neither the name of the University nor the names of its contributors
22345153Sdim *    may be used to endorse or promote products derived from this software
23345153Sdim *    without specific prior written permission.
24345153Sdim *
25345153Sdim * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26345153Sdim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27345153Sdim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28345153Sdim * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29345153Sdim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30345153Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31345153Sdim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32345153Sdim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33345153Sdim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34345153Sdim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35345153Sdim * SUCH DAMAGE.
36345153Sdim *
37345153Sdim *	@(#)machdep.c	7.4 (Berkeley) 6/3/91
38345153Sdim *
39345153Sdim * PATCHES MAGIC		LEVEL	PATCH THAT GOT US HERE
40345153Sdim * --------------------		-----	----------------------
41345153Sdim * CURRENT PATCH LEVEL:		5	00158
42345153Sdim * --------------------		-----	----------------------
43345153Sdim *
44345153Sdim * 15 Aug 92	William Jolitz		Large memory bug
45345153Sdim * 15 Aug 92	Terry Lambert		Fixed CMOS RAM size bug
46345153Sdim * 25 Mar 93	Sean Eric Fagan		Added #ifdef HZ around microtime for
47345153Sdim *					the new microtime.s routine
48345153Sdim * 08 Apr 93	Andrew Herbert		Fixes for kmem_alloc panics
49345153Sdim * 20 Apr 93	Bruce Evans		New npx-0.5 code
50345153Sdim * 25 Apr 93	Bruce Evans		New intr-0.1 code
51345153Sdim */
52345153Sdimstatic char rcsid[] = "$Header: /usr/src/sys.386bsd/i386/i386/RCS/machdep.c,v 1.2 92/01/21 14:22:09 william Exp Locker: root $";
53345153Sdim
54345153Sdim
55345153Sdim#include <stddef.h>
56345153Sdim#include "param.h"
57345153Sdim#include "systm.h"
58345153Sdim#include "signalvar.h"
59345153Sdim#include "kernel.h"
60345153Sdim#include "proc.h"
61345153Sdim#include "user.h"
62345153Sdim#include "buf.h"
63345153Sdim#include "reboot.h"
64345153Sdim#include "conf.h"
65345153Sdim#include "file.h"
66345153Sdim#include "callout.h"
67345153Sdim#include "malloc.h"
68345153Sdim#include "mbuf.h"
69345153Sdim#include "msgbuf.h"
70345153Sdim#include "net/netisr.h"
71345153Sdim
72345153Sdim#include "vm/vm.h"
73345153Sdim#include "vm/vm_kern.h"
74345153Sdim#include "vm/vm_page.h"
75345153Sdim
76345153Sdimextern vm_offset_t avail_end;
77345153Sdim
78345153Sdim#include "machine/cpu.h"
79345153Sdim#include "machine/reg.h"
80345153Sdim#include "machine/psl.h"
81345153Sdim#include "machine/specialreg.h"
82345153Sdim#include "i386/isa/rtc.h"
83345153Sdim
84345153Sdim
85345153Sdim#define	EXPECT_BASEMEM	640	/* The expected base memory*/
86345153Sdim#define	INFORM_WAIT	1	/* Set to pause berfore crash in weird cases*/
87345153Sdim
88345153Sdim/*
89345153Sdim * Declare these as initialized data so we can patch them.
90345153Sdim */
91345153Sdimint	nswbuf = 0;
92345153Sdim#ifdef	NBUF
93345153Sdimint	nbuf = NBUF;
94345153Sdim#else
95345153Sdimint	nbuf = 0;
96345153Sdim#endif
97345153Sdim#ifdef	BUFPAGES
98345153Sdimint	bufpages = BUFPAGES;
99345153Sdim#else
100345153Sdimint	bufpages = 0;
101345153Sdim#endif
102345153Sdimint	msgbufmapped;		/* set when safe to use msgbuf */
103345153Sdimextern int freebufspace;
104345153Sdim
105345153Sdim/*
106345153Sdim * Machine-dependent startup code
107345153Sdim */
108345153Sdimint boothowto = 0, Maxmem = 0;
109345153Sdimlong dumplo;
110345153Sdimint physmem, maxmem;
111345153Sdimextern int bootdev;
112345153Sdim#ifdef SMALL
113345153Sdimextern int forcemaxmem;
114345153Sdim#endif
115345153Sdimint biosmem;
116345153Sdim
117345153Sdimextern cyloffset;
118345153Sdim
119345153Sdimcpu_startup()
120345153Sdim{
121345153Sdim	register int unixsize;
122345153Sdim	register unsigned i;
123345153Sdim	register struct pte *pte;
124345153Sdim	int mapaddr, j;
125345153Sdim	register caddr_t v;
126345153Sdim	int maxbufs, base, residual;
127345153Sdim	extern long Usrptsize;
128345153Sdim	vm_offset_t minaddr, maxaddr;
129345153Sdim	vm_size_t size;
130345153Sdim	int firstaddr;
131345153Sdim
132345153Sdim	/*
133345153Sdim	 * Initialize error message buffer (at end of core).
134345153Sdim	 */
135345153Sdim
136345153Sdim	/* avail_end was pre-decremented in pmap_bootstrap to compensate */
137345153Sdim	for (i = 0; i < btoc(sizeof (struct msgbuf)); i++)
138345153Sdim		pmap_enter(pmap_kernel(), msgbufp, avail_end + i * NBPG,
139345153Sdim			   VM_PROT_ALL, TRUE);
140345153Sdim	msgbufmapped = 1;
141345153Sdim
142345153Sdim#ifdef KDB
143345153Sdim	kdb_init();			/* startup kernel debugger */
144345153Sdim#endif
145345153Sdim	/*
146345153Sdim	 * Good {morning,afternoon,evening,night}.
147345153Sdim	 */
148345153Sdim	/*printf(version);
149345153Sdim	printf("real mem  = %d\n", ctob(physmem));*/
150345153Sdim
151345153Sdim	/*
152345153Sdim	 * Allocate space for system data structures.
153345153Sdim	 * The first available kernel virtual address is in "v".
154345153Sdim	 * As pages of kernel virtual memory are allocated, "v" is incremented.
155345153Sdim	 * As pages of memory are allocated and cleared,
156345153Sdim	 * "firstaddr" is incremented.
157345153Sdim	 * An index into the kernel page table corresponding to the
158345153Sdim	 * virtual memory address maintained in "v" is kept in "mapaddr".
159345153Sdim	 */
160345153Sdim
161345153Sdim	/*
162345153Sdim	 * Make two passes.  The first pass calculates how much memory is
163345153Sdim	 * needed and allocates it.  The second pass assigns virtual
164345153Sdim	 * addresses to the various data structures.
165345153Sdim	 */
166345153Sdim	firstaddr = 0;
167345153Sdimagain:
168345153Sdim	v = (caddr_t)firstaddr;
169345153Sdim
170345153Sdim#define	valloc(name, type, num) \
171345153Sdim	    (name) = (type *)v; v = (caddr_t)((name)+(num))
172345153Sdim#define	valloclim(name, type, num, lim) \
173345153Sdim	    (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num)))
174345153Sdim	valloc(callout, struct callout, ncallout);
175345153Sdim#ifdef SYSVSHM
176345153Sdim	valloc(shmsegs, struct shmid_ds, shminfo.shmmni);
177345153Sdim#endif
178345153Sdim	/*
179345153Sdim	 * Determine how many buffers to allocate.
180345153Sdim	 * Use 10% of memory for the first 2 Meg, 5% of the remaining
181345153Sdim	 * memory. Insure a minimum of 16 buffers.
182345153Sdim	 * We allocate 1/2 as many swap buffer headers as file i/o buffers.
183345153Sdim	 */
184345153Sdim	if (bufpages == 0)
185345153Sdim		if (physmem < (2 * 1024 * 1024))
186345153Sdim			bufpages = physmem / 10 / CLSIZE;
187345153Sdim		else
188345153Sdim			bufpages = ((2 * 1024 * 1024 + physmem) / 20) / CLSIZE;
189345153Sdim	/*
190345153Sdim	 * 15 Aug 92	William Jolitz		bufpages fix for too large
191345153Sdim	 */
192345153Sdim	bufpages = min( NKMEMCLUSTERS*2/5, bufpages);
193345153Sdim
194345153Sdim	if (nbuf == 0) {
195345153Sdim		nbuf = bufpages / 2;
196345153Sdim		if (nbuf < 16)
197345153Sdim			nbuf = 16;
198345153Sdim	}
199345153Sdim	freebufspace = bufpages * NBPG;
200345153Sdim	if (nswbuf == 0) {
201345153Sdim		nswbuf = (nbuf / 2) &~ 1;	/* force even */
202345153Sdim		if (nswbuf > 256)
203345153Sdim			nswbuf = 256;		/* sanity */
204345153Sdim	}
205345153Sdim	valloc(swbuf, struct buf, nswbuf);
206345153Sdim	valloc(buf, struct buf, nbuf);
207345153Sdim
208345153Sdim	/*
209345153Sdim	 * End of first pass, size has been calculated so allocate memory
210345153Sdim	 */
211345153Sdim	if (firstaddr == 0) {
212345153Sdim		size = (vm_size_t)(v - firstaddr);
213345153Sdim		firstaddr = (int)kmem_alloc(kernel_map, round_page(size));
214345153Sdim		if (firstaddr == 0)
215345153Sdim			panic("startup: no room for tables");
216345153Sdim		goto again;
217345153Sdim	}
218345153Sdim	/*
219345153Sdim	 * End of second pass, addresses have been assigned
220345153Sdim	 */
221345153Sdim	if ((vm_size_t)(v - firstaddr) != size)
222345153Sdim		panic("startup: table size inconsistency");
223345153Sdim	/*
224345153Sdim	 * Allocate a submap for buffer space allocations.
225345153Sdim	 */
226345153Sdim	buffer_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
227345153Sdim				 bufpages*NBPG, TRUE);
228345153Sdim	/*
229345153Sdim	 * Allocate a submap for physio
230345153Sdim	 */
231345153Sdim	phys_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
232345153Sdim				 VM_PHYS_SIZE, TRUE);
233345153Sdim
234345153Sdim	/*
235345153Sdim	 * Finally, allocate mbuf pool.  Since mclrefcnt is an off-size
236345153Sdim	 * we use the more space efficient malloc in place of kmem_alloc.
237345153Sdim	 */
238345153Sdim	mclrefcnt = (char *)malloc(NMBCLUSTERS+CLBYTES/MCLBYTES,
239345153Sdim				   M_MBUF, M_NOWAIT);
240345153Sdim	bzero(mclrefcnt, NMBCLUSTERS+CLBYTES/MCLBYTES);
241345153Sdim	mb_map = kmem_suballoc(kernel_map, (vm_offset_t)&mbutl, &maxaddr,
242345153Sdim			       VM_MBUF_SIZE, FALSE);
243345153Sdim	/*
244345153Sdim	 * Initialize callouts
245345153Sdim	 */
246345153Sdim	callfree = callout;
247345153Sdim	for (i = 1; i < ncallout; i++)
248345153Sdim		callout[i-1].c_next = &callout[i];
249345153Sdim
250345153Sdim	/*printf("avail mem = %d\n", ptoa(vm_page_free_count));*/
251345153Sdim
252345153Sdim	/*
253345153Sdim	 * Set up CPU-specific registers, cache, etc.
254345153Sdim	 */
255345153Sdim	initcpu();
256345153Sdim
257345153Sdim	/*
258345153Sdim	 * Set up buffers, so they can be used to read disk labels.
259345153Sdim	 */
260345153Sdim	bufinit();
261345153Sdim
262345153Sdim	/*
263345153Sdim	 * Configure the system.
264345153Sdim	 */
265345153Sdim	configure();
266345153Sdim}
267345153Sdim
268345153Sdim#ifdef PGINPROF
269345153Sdim/*
270345153Sdim * Return the difference (in microseconds)
271345153Sdim * between the  current time and a previous
272345153Sdim * time as represented  by the arguments.
273345153Sdim * If there is a pending clock interrupt
274345153Sdim * which has not been serviced due to high
275345153Sdim * ipl, return error code.
276345153Sdim */
277345153Sdim/*ARGSUSED*/
278345153Sdimvmtime(otime, olbolt, oicr)
279345153Sdim	register int otime, olbolt, oicr;
280345153Sdim{
281345153Sdim
282345153Sdim	return (((time.tv_sec-otime)*60 + lbolt-olbolt)*16667);
283345153Sdim}
284345153Sdim#endif
285345153Sdim
286345153Sdimstruct sigframe {
287345153Sdim	int	sf_signum;
288345153Sdim	int	sf_code;
289345153Sdim	struct	sigcontext *sf_scp;
290345153Sdim	sig_t	sf_handler;
291345153Sdim	int	sf_eax;
292345153Sdim	int	sf_edx;
293345153Sdim	int	sf_ecx;
294345153Sdim	struct	sigcontext sf_sc;
295345153Sdim} ;
296345153Sdim
297345153Sdimextern int kstack[];
298345153Sdim
299345153Sdim/*
300345153Sdim * Send an interrupt to process.
301345153Sdim *
302345153Sdim * Stack is set up to allow sigcode stored
303345153Sdim * in u. to call routine, followed by kcall
304345153Sdim * to sigreturn routine below.  After sigreturn
305345153Sdim * resets the signal mask, the stack, and the
306345153Sdim * frame pointer, it returns to the user
307345153Sdim * specified pc, psl.
308345153Sdim */
309345153Sdimvoid
310345153Sdimsendsig(catcher, sig, mask, code)
311345153Sdim	sig_t catcher;
312345153Sdim	int sig, mask;
313345153Sdim	unsigned code;
314345153Sdim{
315345153Sdim	register struct proc *p = curproc;
316345153Sdim	register int *regs;
317345153Sdim	register struct sigframe *fp;
318345153Sdim	struct sigacts *ps = p->p_sigacts;
319345153Sdim	int oonstack, frmtrap;
320345153Sdim
321345153Sdim	regs = p->p_regs;
322345153Sdim        oonstack = ps->ps_onstack;
323345153Sdim	frmtrap = curpcb->pcb_flags & FM_TRAP;
324345153Sdim	/*
325345153Sdim	 * Allocate and validate space for the signal handler
326345153Sdim	 * context. Note that if the stack is in P0 space, the
327345153Sdim	 * call to grow() is a nop, and the useracc() check
328345153Sdim	 * will fail if the process has not already allocated
329345153Sdim	 * the space with a `brk'.
330345153Sdim	 */
331345153Sdim        if (!ps->ps_onstack && (ps->ps_sigonstack & sigmask(sig))) {
332345153Sdim		fp = (struct sigframe *)(ps->ps_sigsp
333345153Sdim				- sizeof(struct sigframe));
334345153Sdim                ps->ps_onstack = 1;
335345153Sdim	} else {
336345153Sdim		if (frmtrap)
337345153Sdim			fp = (struct sigframe *)(regs[tESP]
338345153Sdim				- sizeof(struct sigframe));
339345153Sdim		else
340345153Sdim			fp = (struct sigframe *)(regs[sESP]
341345153Sdim				- sizeof(struct sigframe));
342345153Sdim	}
343345153Sdim
344345153Sdim	if ((unsigned)fp <= (unsigned)p->p_vmspace->vm_maxsaddr + MAXSSIZ - ctob(p->p_vmspace->vm_ssize))
345345153Sdim		(void)grow(p, (unsigned)fp);
346345153Sdim
347345153Sdim	if (useracc((caddr_t)fp, sizeof (struct sigframe), B_WRITE) == 0) {
348345153Sdim		/*
349345153Sdim		 * Process has trashed its stack; give it an illegal
350345153Sdim		 * instruction to halt it in its tracks.
351345153Sdim		 */
352345153Sdim		SIGACTION(p, SIGILL) = SIG_DFL;
353345153Sdim		sig = sigmask(SIGILL);
354345153Sdim		p->p_sigignore &= ~sig;
355345153Sdim		p->p_sigcatch &= ~sig;
356345153Sdim		p->p_sigmask &= ~sig;
357345153Sdim		psignal(p, SIGILL);
358345153Sdim		return;
359345153Sdim	}
360345153Sdim
361345153Sdim	/*
362345153Sdim	 * Build the argument list for the signal handler.
363345153Sdim	 */
364345153Sdim	fp->sf_signum = sig;
365345153Sdim	fp->sf_code = code;
366345153Sdim	fp->sf_scp = &fp->sf_sc;
367345153Sdim	fp->sf_handler = catcher;
368345153Sdim
369345153Sdim	/* save scratch registers */
370345153Sdim	if(frmtrap) {
371345153Sdim		fp->sf_eax = regs[tEAX];
372345153Sdim		fp->sf_edx = regs[tEDX];
373345153Sdim		fp->sf_ecx = regs[tECX];
374345153Sdim	} else {
375345153Sdim		fp->sf_eax = regs[sEAX];
376345153Sdim		fp->sf_edx = regs[sEDX];
377345153Sdim		fp->sf_ecx = regs[sECX];
378345153Sdim	}
379345153Sdim	/*
380345153Sdim	 * Build the signal context to be used by sigreturn.
381345153Sdim	 */
382345153Sdim	fp->sf_sc.sc_onstack = oonstack;
383345153Sdim	fp->sf_sc.sc_mask = mask;
384345153Sdim	if(frmtrap) {
385345153Sdim		fp->sf_sc.sc_sp = regs[tESP];
386345153Sdim		fp->sf_sc.sc_fp = regs[tEBP];
387345153Sdim		fp->sf_sc.sc_pc = regs[tEIP];
388345153Sdim		fp->sf_sc.sc_ps = regs[tEFLAGS];
389345153Sdim		regs[tESP] = (int)fp;
390345153Sdim		regs[tEIP] = (int)((struct pcb *)kstack)->pcb_sigc;
391345153Sdim	} else {
392345153Sdim		fp->sf_sc.sc_sp = regs[sESP];
393345153Sdim		fp->sf_sc.sc_fp = regs[sEBP];
394345153Sdim		fp->sf_sc.sc_pc = regs[sEIP];
395345153Sdim		fp->sf_sc.sc_ps = regs[sEFLAGS];
396345153Sdim		regs[sESP] = (int)fp;
397345153Sdim		regs[sEIP] = (int)((struct pcb *)kstack)->pcb_sigc;
398345153Sdim	}
399345153Sdim}
400345153Sdim
401345153Sdim/*
402345153Sdim * System call to cleanup state after a signal
403345153Sdim * has been taken.  Reset signal mask and
404345153Sdim * stack state from context left by sendsig (above).
405345153Sdim * Return to previous pc and psl as specified by
406345153Sdim * context left by sendsig. Check carefully to
407345153Sdim * make sure that the user has not modified the
408345153Sdim * psl to gain improper priviledges or to cause
409345153Sdim * a machine fault.
410345153Sdim */
411345153Sdimsigreturn(p, uap, retval)
412345153Sdim	struct proc *p;
413345153Sdim	struct args {
414345153Sdim		struct sigcontext *sigcntxp;
415345153Sdim	} *uap;
416345153Sdim	int *retval;
417345153Sdim{
418345153Sdim	register struct sigcontext *scp;
419345153Sdim	register struct sigframe *fp;
420345153Sdim	register int *regs = p->p_regs;
421345153Sdim
422345153Sdim
423345153Sdim	/*
424345153Sdim	 * (XXX old comment) regs[sESP] points to the return address.
425345153Sdim	 * The user scp pointer is above that.
426345153Sdim	 * The return address is faked in the signal trampoline code
427345153Sdim	 * for consistency.
428345153Sdim	 */
429345153Sdim	scp = uap->sigcntxp;
430345153Sdim	fp = (struct sigframe *)
431345153Sdim	     ((caddr_t)scp - offsetof(struct sigframe, sf_sc));
432345153Sdim
433345153Sdim	if (useracc((caddr_t)fp, sizeof (*fp), 0) == 0)
434345153Sdim		return(EINVAL);
435345153Sdim
436345153Sdim	/* restore scratch registers */
437345153Sdim	regs[sEAX] = fp->sf_eax ;
438345153Sdim	regs[sEDX] = fp->sf_edx ;
439345153Sdim	regs[sECX] = fp->sf_ecx ;
440345153Sdim
441345153Sdim	if (useracc((caddr_t)scp, sizeof (*scp), 0) == 0)
442345153Sdim		return(EINVAL);
443345153Sdim#ifdef notyet
444345153Sdim	if ((scp->sc_ps & PSL_MBZ) != 0 || (scp->sc_ps & PSL_MBO) != PSL_MBO) {
445345153Sdim		return(EINVAL);
446345153Sdim	}
447345153Sdim#endif
448345153Sdim        p->p_sigacts->ps_onstack = scp->sc_onstack & 01;
449345153Sdim	p->p_sigmask = scp->sc_mask &~
450345153Sdim	    (sigmask(SIGKILL)|sigmask(SIGCONT)|sigmask(SIGSTOP));
451345153Sdim	regs[sEBP] = scp->sc_fp;
452345153Sdim	regs[sESP] = scp->sc_sp;
453345153Sdim	regs[sEIP] = scp->sc_pc;
454345153Sdim	regs[sEFLAGS] = scp->sc_ps;
455345153Sdim	return(EJUSTRETURN);
456345153Sdim}
457345153Sdim
458345153Sdimint	waittime = -1;
459345153Sdimstruct pcb dumppcb;
460345153Sdim
461345153Sdimboot(arghowto)
462345153Sdim	int arghowto;
463345153Sdim{
464345153Sdim	register long dummy;		/* r12 is reserved */
465345153Sdim	register int howto;		/* r11 == how to boot */
466345153Sdim	register int devtype;		/* r10 == major of root dev */
467345153Sdim	extern char *panicstr;
468345153Sdim	extern int cold;
469345153Sdim	int nomsg = 1;
470345153Sdim
471345153Sdim	if(cold) {
472345153Sdim		printf("hit reset please");
473345153Sdim		for(;;);
474345153Sdim	}
475345153Sdim	howto = arghowto;
476345153Sdim	if ((howto&RB_NOSYNC) == 0 && waittime < 0 && bfreelist[0].b_forw) {
477345153Sdim		register struct buf *bp;
478345153Sdim		int iter, nbusy;
479345153Sdim
480345153Sdim		waittime = 0;
481345153Sdim		(void) splnet();
482345153Sdim		/*
483345153Sdim		 * Release inodes held by texts before update.
484345153Sdim		 */
485345153Sdim		if (panicstr == 0)
486345153Sdim			vnode_pager_umount(NULL);
487345153Sdim		sync((struct sigcontext *)0);
488345153Sdim
489345153Sdim		for (iter = 0; iter < 20; iter++) {
490345153Sdim			nbusy = 0;
491345153Sdim			for (bp = &buf[nbuf]; --bp >= buf; )
492345153Sdim				if ((bp->b_flags & (B_BUSY|B_INVAL)) == B_BUSY)
493345153Sdim					nbusy++;
494345153Sdim			if (nbusy == 0)
495345153Sdim				break;
496345153Sdim			if (nomsg) {
497345153Sdim				printf("updating disks before rebooting... ");
498345153Sdim				nomsg = 0;
499345153Sdim			}
500345153Sdim			/* printf("%d ", nbusy); */
501345153Sdim			DELAY(40000 * iter);
502345153Sdim		}
503345153Sdim		if (nbusy)
504345153Sdim			printf(" failed!\n");
505345153Sdim		else if (nomsg == 0)
506345153Sdim			printf("succeded.\n");
507345153Sdim		DELAY(10000);			/* wait for printf to finish */
508345153Sdim	}
509345153Sdim	splhigh();
510345153Sdim	devtype = major(rootdev);
511345153Sdim	if (howto&RB_HALT) {
512345153Sdim		pg("\nThe operating system has halted. Please press any key to reboot.\n\n");
513345153Sdim	} else {
514345153Sdim		if (howto & RB_DUMP) {
515345153Sdim			savectx(&dumppcb, 0);
516345153Sdim			dumppcb.pcb_ptd = rcr3();
517345153Sdim			dumpsys();
518345153Sdim			/*NOTREACHED*/
519345153Sdim		}
520345153Sdim	}
521345153Sdim#ifdef lint
522345153Sdim	dummy = 0; dummy = dummy;
523345153Sdim	printf("howto %d, devtype %d\n", arghowto, devtype);
524345153Sdim#endif
525345153Sdim	cpu_reset();
526345153Sdim	for(;;) ;
527345153Sdim	/*NOTREACHED*/
528345153Sdim}
529345153Sdim
530345153Sdimint	dumpmag = 0x8fca0101;	/* magic number for savecore */
531345153Sdimint	dumpsize = 0;		/* also for savecore */
532345153Sdim/*
533345153Sdim * Doadump comes here after turning off memory management and
534345153Sdim * getting on the dump stack, either when called above, or by
535345153Sdim * the auto-restart code.
536345153Sdim */
537345153Sdimdumpsys()
538345153Sdim{
539345153Sdim
540345153Sdim	if (dumpdev == NODEV)
541345153Sdim		return;
542345153Sdim	if ((minor(dumpdev)&07) != 1)
543345153Sdim		return;
544345153Sdim	printf("\nThe operating system is saving a copy of RAM memory to device %x, offset %d\n\
545345153Sdim(hit any key to abort): [ amount left to save (MB) ] ", dumpdev, dumplo);
546345153Sdim	dumpsize = physmem;
547345153Sdim	switch ((*bdevsw[major(dumpdev)].d_dump)(dumpdev)) {
548345153Sdim
549345153Sdim	case ENXIO:
550345153Sdim		printf("-- device bad\n");
551345153Sdim		break;
552345153Sdim
553345153Sdim	case EFAULT:
554345153Sdim		printf("-- device not ready\n");
555345153Sdim		break;
556345153Sdim
557345153Sdim	case EINVAL:
558345153Sdim		printf("-- area improper\n");
559345153Sdim		break;
560345153Sdim
561345153Sdim	case EIO:
562345153Sdim		printf("-- i/o error\n");
563345153Sdim		break;
564345153Sdim
565345153Sdim	case EINTR:
566345153Sdim		printf("-- aborted from console\n");
567345153Sdim		break;
568345153Sdim
569345153Sdim	default:
570345153Sdim		printf(" succeeded\n");
571345153Sdim		break;
572345153Sdim	}
573345153Sdim	printf("system rebooting.\n\n");
574345153Sdim	DELAY(10000);
575345153Sdim}
576345153Sdim
577345153Sdim#ifdef HZ
578345153Sdim/*
579345153Sdim * If HZ is defined we use this code, otherwise the code in
580345153Sdim * /sys/i386/i386/microtime.s is used.  The othercode only works
581345153Sdim * for HZ=100.
582345153Sdim */
583345153Sdimmicrotime(tvp)
584345153Sdim	register struct timeval *tvp;
585345153Sdim{
586345153Sdim	int s = splhigh();
587345153Sdim
588345153Sdim	*tvp = time;
589345153Sdim	tvp->tv_usec += tick;
590345153Sdim	while (tvp->tv_usec > 1000000) {
591345153Sdim		tvp->tv_sec++;
592345153Sdim		tvp->tv_usec -= 1000000;
593345153Sdim	}
594345153Sdim	splx(s);
595345153Sdim}
596345153Sdim#endif /* HZ */
597345153Sdim
598345153Sdimphysstrat(bp, strat, prio)
599345153Sdim	struct buf *bp;
600345153Sdim	int (*strat)(), prio;
601345153Sdim{
602345153Sdim	register int s;
603345153Sdim	caddr_t baddr;
604345153Sdim
605345153Sdim	/*
606345153Sdim	 * vmapbuf clobbers b_addr so we must remember it so that it
607345153Sdim	 * can be restored after vunmapbuf.  This is truely rude, we
608345153Sdim	 * should really be storing this in a field in the buf struct
609345153Sdim	 * but none are available and I didn't want to add one at
610345153Sdim	 * this time.  Note that b_addr for dirty page pushes is
611345153Sdim	 * restored in vunmapbuf. (ugh!)
612345153Sdim	 */
613345153Sdim	baddr = bp->b_un.b_addr;
614345153Sdim	vmapbuf(bp);
615345153Sdim	(*strat)(bp);
616345153Sdim	/* pageout daemon doesn't wait for pushed pages */
617345153Sdim	if (bp->b_flags & B_DIRTY)
618345153Sdim		return;
619345153Sdim	s = splbio();
620345153Sdim	while ((bp->b_flags & B_DONE) == 0)
621345153Sdim		sleep((caddr_t)bp, prio);
622345153Sdim	splx(s);
623345153Sdim	vunmapbuf(bp);
624345153Sdim	bp->b_un.b_addr = baddr;
625345153Sdim}
626345153Sdim
627345153Sdiminitcpu()
628345153Sdim{
629345153Sdim}
630345153Sdim
631345153Sdim/*
632345153Sdim * Clear registers on exec
633345153Sdim */
634345153Sdimsetregs(p, entry)
635345153Sdim	struct proc *p;
636345153Sdim	u_long entry;
637345153Sdim{
638345153Sdim
639345153Sdim	p->p_regs[sEBP] = 0;	/* bottom of the fp chain */
640345153Sdim	p->p_regs[sEIP] = entry;
641345153Sdim
642345153Sdim	p->p_addr->u_pcb.pcb_flags = 0;	/* no fp at all */
643345153Sdim	load_cr0(rcr0() | CR0_TS);	/* start emulating */
644345153Sdim#ifdef	NPX
645345153Sdim	npxinit(__INITIAL_NPXCW__);
646345153Sdim#endif
647345153Sdim}
648345153Sdim
649345153Sdim/*
650345153Sdim * Initialize 386 and configure to run kernel
651345153Sdim */
652345153Sdim
653345153Sdim/*
654345153Sdim * Initialize segments & interrupt table
655345153Sdim */
656345153Sdim
657345153Sdim
658345153Sdim#define	GNULL_SEL	0	/* Null Descriptor */
659345153Sdim#define	GCODE_SEL	1	/* Kernel Code Descriptor */
660345153Sdim#define	GDATA_SEL	2	/* Kernel Data Descriptor */
661345153Sdim#define	GLDT_SEL	3	/* LDT - eventually one per process */
662345153Sdim#define	GTGATE_SEL	4	/* Process task switch gate */
663345153Sdim#define	GPANIC_SEL	5	/* Task state to consider panic from */
664345153Sdim#define	GPROC0_SEL	6	/* Task state process slot zero and up */
665345153Sdim#define NGDT 	GPROC0_SEL+1
666345153Sdim
667345153Sdimunion descriptor gdt[GPROC0_SEL+1];
668345153Sdim
669345153Sdim/* interrupt descriptor table */
670345153Sdimstruct gate_descriptor idt[NIDT];
671345153Sdim
672345153Sdim/* local descriptor table */
673345153Sdimunion descriptor ldt[5];
674345153Sdim#define	LSYS5CALLS_SEL	0	/* forced by intel BCS */
675345153Sdim#define	LSYS5SIGR_SEL	1
676345153Sdim
677345153Sdim#define	L43BSDCALLS_SEL	2	/* notyet */
678345153Sdim#define	LUCODE_SEL	3
679345153Sdim#define	LUDATA_SEL	4
680345153Sdim/* seperate stack, es,fs,gs sels ? */
681345153Sdim/* #define	LPOSIXCALLS_SEL	5	/* notyet */
682345153Sdim
683345153Sdimstruct	i386tss	tss, panic_tss;
684345153Sdim
685345153Sdimextern  struct user *proc0paddr;
686345153Sdim
687345153Sdim/* software prototypes -- in more palitable form */
688345153Sdimstruct soft_segment_descriptor gdt_segs[] = {
689345153Sdim	/* Null Descriptor */
690345153Sdim{	0x0,			/* segment base address  */
691345153Sdim	0x0,			/* length - all address space */
692345153Sdim	0,			/* segment type */
693345153Sdim	0,			/* segment descriptor priority level */
694345153Sdim	0,			/* segment descriptor present */
695345153Sdim	0,0,
696345153Sdim	0,			/* default 32 vs 16 bit size */
697345153Sdim	0  			/* limit granularity (byte/page units)*/ },
698345153Sdim	/* Code Descriptor for kernel */
699345153Sdim{	0x0,			/* segment base address  */
700345153Sdim	0xfffff,		/* length - all address space */
701345153Sdim	SDT_MEMERA,		/* segment type */
702345153Sdim	0,			/* segment descriptor priority level */
703345153Sdim	1,			/* segment descriptor present */
704345153Sdim	0,0,
705345153Sdim	1,			/* default 32 vs 16 bit size */
706345153Sdim	1  			/* limit granularity (byte/page units)*/ },
707345153Sdim	/* Data Descriptor for kernel */
708345153Sdim{	0x0,			/* segment base address  */
709345153Sdim	0xfffff,		/* length - all address space */
710345153Sdim	SDT_MEMRWA,		/* segment type */
711345153Sdim	0,			/* segment descriptor priority level */
712345153Sdim	1,			/* segment descriptor present */
713345153Sdim	0,0,
714345153Sdim	1,			/* default 32 vs 16 bit size */
715345153Sdim	1  			/* limit granularity (byte/page units)*/ },
716345153Sdim	/* LDT Descriptor */
717345153Sdim{	(int) ldt,			/* segment base address  */
718345153Sdim	sizeof(ldt)-1,		/* length - all address space */
719345153Sdim	SDT_SYSLDT,		/* segment type */
720345153Sdim	0,			/* segment descriptor priority level */
721345153Sdim	1,			/* segment descriptor present */
722345153Sdim	0,0,
723345153Sdim	0,			/* unused - default 32 vs 16 bit size */
724345153Sdim	0  			/* limit granularity (byte/page units)*/ },
725345153Sdim	/* Null Descriptor - Placeholder */
726345153Sdim{	0x0,			/* segment base address  */
727345153Sdim	0x0,			/* length - all address space */
728345153Sdim	0,			/* segment type */
729345153Sdim	0,			/* segment descriptor priority level */
730345153Sdim	0,			/* segment descriptor present */
731345153Sdim	0,0,
732345153Sdim	0,			/* default 32 vs 16 bit size */
733345153Sdim	0  			/* limit granularity (byte/page units)*/ },
734345153Sdim	/* Panic Tss Descriptor */
735345153Sdim{	(int) &panic_tss,		/* segment base address  */
736345153Sdim	sizeof(tss)-1,		/* length - all address space */
737345153Sdim	SDT_SYS386TSS,		/* segment type */
738345153Sdim	0,			/* segment descriptor priority level */
739345153Sdim	1,			/* segment descriptor present */
740345153Sdim	0,0,
741345153Sdim	0,			/* unused - default 32 vs 16 bit size */
742345153Sdim	0  			/* limit granularity (byte/page units)*/ },
743345153Sdim	/* Proc 0 Tss Descriptor */
744345153Sdim{	(int) kstack,			/* segment base address  */
745345153Sdim	sizeof(tss)-1,		/* length - all address space */
746345153Sdim	SDT_SYS386TSS,		/* segment type */
747345153Sdim	0,			/* segment descriptor priority level */
748345153Sdim	1,			/* segment descriptor present */
749345153Sdim	0,0,
750345153Sdim	0,			/* unused - default 32 vs 16 bit size */
751345153Sdim	0  			/* limit granularity (byte/page units)*/ }};
752345153Sdim
753345153Sdimstruct soft_segment_descriptor ldt_segs[] = {
754345153Sdim	/* Null Descriptor - overwritten by call gate */
755345153Sdim{	0x0,			/* segment base address  */
756345153Sdim	0x0,			/* length - all address space */
757345153Sdim	0,			/* segment type */
758345153Sdim	0,			/* segment descriptor priority level */
759345153Sdim	0,			/* segment descriptor present */
760345153Sdim	0,0,
761345153Sdim	0,			/* default 32 vs 16 bit size */
762345153Sdim	0  			/* limit granularity (byte/page units)*/ },
763345153Sdim	/* Null Descriptor - overwritten by call gate */
764345153Sdim{	0x0,			/* segment base address  */
765345153Sdim	0x0,			/* length - all address space */
766345153Sdim	0,			/* segment type */
767345153Sdim	0,			/* segment descriptor priority level */
768345153Sdim	0,			/* segment descriptor present */
769345153Sdim	0,0,
770345153Sdim	0,			/* default 32 vs 16 bit size */
771345153Sdim	0  			/* limit granularity (byte/page units)*/ },
772345153Sdim	/* Null Descriptor - overwritten by call gate */
773345153Sdim{	0x0,			/* segment base address  */
774345153Sdim	0x0,			/* length - all address space */
775345153Sdim	0,			/* segment type */
776345153Sdim	0,			/* segment descriptor priority level */
777345153Sdim	0,			/* segment descriptor present */
778345153Sdim	0,0,
779345153Sdim	0,			/* default 32 vs 16 bit size */
780345153Sdim	0  			/* limit granularity (byte/page units)*/ },
781345153Sdim	/* Code Descriptor for user */
782345153Sdim{	0x0,			/* segment base address  */
783345153Sdim	0xfffff,		/* length - all address space */
784345153Sdim	SDT_MEMERA,		/* segment type */
785345153Sdim	SEL_UPL,		/* segment descriptor priority level */
786345153Sdim	1,			/* segment descriptor present */
787345153Sdim	0,0,
788345153Sdim	1,			/* default 32 vs 16 bit size */
789345153Sdim	1  			/* limit granularity (byte/page units)*/ },
790345153Sdim	/* Data Descriptor for user */
791345153Sdim{	0x0,			/* segment base address  */
792345153Sdim	0xfffff,		/* length - all address space */
793345153Sdim	SDT_MEMRWA,		/* segment type */
794345153Sdim	SEL_UPL,		/* segment descriptor priority level */
795345153Sdim	1,			/* segment descriptor present */
796345153Sdim	0,0,
797345153Sdim	1,			/* default 32 vs 16 bit size */
798345153Sdim	1  			/* limit granularity (byte/page units)*/ } };
799345153Sdim
800345153Sdimsetidt(idx, func, typ, dpl) char *func; {
801345153Sdim	struct gate_descriptor *ip = idt + idx;
802345153Sdim
803345153Sdim	ip->gd_looffset = (int)func;
804345153Sdim	ip->gd_selector = 8;
805345153Sdim	ip->gd_stkcpy = 0;
806345153Sdim	ip->gd_xx = 0;
807345153Sdim	ip->gd_type = typ;
808345153Sdim	ip->gd_dpl = dpl;
809345153Sdim	ip->gd_p = 1;
810345153Sdim	ip->gd_hioffset = ((int)func)>>16 ;
811345153Sdim}
812345153Sdim
813345153Sdim#define	IDTVEC(name)	__CONCAT(X, name)
814345153Sdimextern	IDTVEC(div), IDTVEC(dbg), IDTVEC(nmi), IDTVEC(bpt), IDTVEC(ofl),
815345153Sdim	IDTVEC(bnd), IDTVEC(ill), IDTVEC(dna), IDTVEC(dble), IDTVEC(fpusegm),
816345153Sdim	IDTVEC(tss), IDTVEC(missing), IDTVEC(stk), IDTVEC(prot),
817345153Sdim	IDTVEC(page), IDTVEC(rsvd), IDTVEC(fpu), IDTVEC(rsvd0),
818345153Sdim	IDTVEC(rsvd1), IDTVEC(rsvd2), IDTVEC(rsvd3), IDTVEC(rsvd4),
819345153Sdim	IDTVEC(rsvd5), IDTVEC(rsvd6), IDTVEC(rsvd7), IDTVEC(rsvd8),
820345153Sdim	IDTVEC(rsvd9), IDTVEC(rsvd10), IDTVEC(rsvd11), IDTVEC(rsvd12),
821345153Sdim	IDTVEC(rsvd13), IDTVEC(rsvd14), IDTVEC(rsvd14), IDTVEC(syscall);
822345153Sdim
823345153Sdimint lcr0(), lcr3(), rcr0(), rcr2();
824345153Sdimint _udatasel, _ucodesel, _gsel_tss;
825345153Sdim
826345153Sdiminit386(first)
827345153Sdim{
828345153Sdim	extern ssdtosd(), lgdt(), lidt(), lldt(), etext;
829345153Sdim	int x, *pi;
830345153Sdim	unsigned biosbasemem, biosextmem;
831345153Sdim	struct gate_descriptor *gdp;
832345153Sdim	extern int sigcode,szsigcode;
833345153Sdim	/* table descriptors - used to load tables by microp */
834345153Sdim	struct region_descriptor r_gdt, r_idt;
835345153Sdim	int	pagesinbase, pagesinext;
836345153Sdim
837345153Sdim
838345153Sdim	proc0.p_addr = proc0paddr;
839345153Sdim
840345153Sdim	/*
841345153Sdim	 * Initialize the console before we print anything out.
842345153Sdim	 */
843345153Sdim
844345153Sdim	cninit (KERNBASE+0xa0000);
845345153Sdim
846345153Sdim	/* make gdt memory segments */
847345153Sdim	gdt_segs[GCODE_SEL].ssd_limit = btoc((int) &etext + NBPG);
848345153Sdim	for (x=0; x < NGDT; x++) ssdtosd(gdt_segs+x, gdt+x);
849345153Sdim	/* make ldt memory segments */
850345153Sdim	ldt_segs[LUCODE_SEL].ssd_limit = btoc(UPT_MIN_ADDRESS);
851345153Sdim	ldt_segs[LUDATA_SEL].ssd_limit = btoc(UPT_MIN_ADDRESS);
852345153Sdim	/* Note. eventually want private ldts per process */
853345153Sdim	for (x=0; x < 5; x++) ssdtosd(ldt_segs+x, ldt+x);
854345153Sdim
855345153Sdim	/* exceptions */
856345153Sdim	setidt(0, &IDTVEC(div),  SDT_SYS386TGT, SEL_KPL);
857345153Sdim	setidt(1, &IDTVEC(dbg),  SDT_SYS386TGT, SEL_KPL);
858345153Sdim	setidt(2, &IDTVEC(nmi),  SDT_SYS386TGT, SEL_KPL);
859345153Sdim 	setidt(3, &IDTVEC(bpt),  SDT_SYS386TGT, SEL_UPL);
860345153Sdim	setidt(4, &IDTVEC(ofl),  SDT_SYS386TGT, SEL_KPL);
861345153Sdim	setidt(5, &IDTVEC(bnd),  SDT_SYS386TGT, SEL_KPL);
862345153Sdim	setidt(6, &IDTVEC(ill),  SDT_SYS386TGT, SEL_KPL);
863345153Sdim	setidt(7, &IDTVEC(dna),  SDT_SYS386TGT, SEL_KPL);
864345153Sdim	setidt(8, &IDTVEC(dble),  SDT_SYS386TGT, SEL_KPL);
865345153Sdim	setidt(9, &IDTVEC(fpusegm),  SDT_SYS386TGT, SEL_KPL);
866345153Sdim	setidt(10, &IDTVEC(tss),  SDT_SYS386TGT, SEL_KPL);
867345153Sdim	setidt(11, &IDTVEC(missing),  SDT_SYS386TGT, SEL_KPL);
868345153Sdim	setidt(12, &IDTVEC(stk),  SDT_SYS386TGT, SEL_KPL);
869345153Sdim	setidt(13, &IDTVEC(prot),  SDT_SYS386TGT, SEL_KPL);
870345153Sdim	setidt(14, &IDTVEC(page),  SDT_SYS386TGT, SEL_KPL);
871345153Sdim	setidt(15, &IDTVEC(rsvd),  SDT_SYS386TGT, SEL_KPL);
872345153Sdim	setidt(16, &IDTVEC(fpu),  SDT_SYS386TGT, SEL_KPL);
873345153Sdim	setidt(17, &IDTVEC(rsvd0),  SDT_SYS386TGT, SEL_KPL);
874345153Sdim	setidt(18, &IDTVEC(rsvd1),  SDT_SYS386TGT, SEL_KPL);
875345153Sdim	setidt(19, &IDTVEC(rsvd2),  SDT_SYS386TGT, SEL_KPL);
876345153Sdim	setidt(20, &IDTVEC(rsvd3),  SDT_SYS386TGT, SEL_KPL);
877345153Sdim	setidt(21, &IDTVEC(rsvd4),  SDT_SYS386TGT, SEL_KPL);
878345153Sdim	setidt(22, &IDTVEC(rsvd5),  SDT_SYS386TGT, SEL_KPL);
879345153Sdim	setidt(23, &IDTVEC(rsvd6),  SDT_SYS386TGT, SEL_KPL);
880345153Sdim	setidt(24, &IDTVEC(rsvd7),  SDT_SYS386TGT, SEL_KPL);
881345153Sdim	setidt(25, &IDTVEC(rsvd8),  SDT_SYS386TGT, SEL_KPL);
882345153Sdim	setidt(26, &IDTVEC(rsvd9),  SDT_SYS386TGT, SEL_KPL);
883345153Sdim	setidt(27, &IDTVEC(rsvd10),  SDT_SYS386TGT, SEL_KPL);
884345153Sdim	setidt(28, &IDTVEC(rsvd11),  SDT_SYS386TGT, SEL_KPL);
885345153Sdim	setidt(29, &IDTVEC(rsvd12),  SDT_SYS386TGT, SEL_KPL);
886345153Sdim	setidt(30, &IDTVEC(rsvd13),  SDT_SYS386TGT, SEL_KPL);
887345153Sdim	setidt(31, &IDTVEC(rsvd14),  SDT_SYS386TGT, SEL_KPL);
888345153Sdim
889345153Sdim#include	"isa.h"
890345153Sdim#if	NISA >0
891345153Sdim	isa_defaultirq();
892345153Sdim#endif
893345153Sdim
894345153Sdim	r_gdt.rd_limit = sizeof(gdt)-1;
895345153Sdim	r_gdt.rd_base = (int) gdt;
896345153Sdim	lgdt(&r_gdt);
897345153Sdim	r_idt.rd_limit = sizeof(idt)-1;
898345153Sdim	r_idt.rd_base = (int) idt;
899345153Sdim	lidt(&r_idt);
900345153Sdim	lldt(GSEL(GLDT_SEL, SEL_KPL));
901345153Sdim
902345153Sdim#include "ddb.h"
903345153Sdim#if NDDB > 0
904345153Sdim	kdb_init();
905345153Sdim	if (boothowto & RB_KDB)
906345153Sdim		Debugger();
907345153Sdim#endif
908345153Sdim
909345153Sdim	/* Use BIOS values stored in RTC CMOS RAM, since probing
910345153Sdim	 * breaks certain 386 AT relics.
911345153Sdim	 */
912345153Sdim	biosbasemem = rtcin(RTC_BASELO)+ (rtcin(RTC_BASEHI)<<8);
913345153Sdim	biosextmem = rtcin(RTC_EXTLO)+ (rtcin(RTC_EXTHI)<<8);
914345153Sdim/*printf("bios base %d ext %d ", biosbasemem, biosextmem);*/
915345153Sdim
916345153Sdim	/*
917345153Sdim	 * 15 Aug 92	Terry Lambert		The real fix for the CMOS bug
918345153Sdim	 */
919345153Sdim	if( biosbasemem != EXPECT_BASEMEM) {
920345153Sdim		printf( "Warning: Base memory %dK, assuming %dK\n", biosbasemem, EXPECT_BASEMEM);
921345153Sdim		biosbasemem = EXPECT_BASEMEM;		/* assume base*/
922345153Sdim	}
923345153Sdim
924345153Sdim	if( biosextmem > 65536) {
925345153Sdim		printf( "Warning: Extended memory %dK(>64M), assuming 0K\n", biosextmem);
926345153Sdim		biosextmem = 0;				/* assume none*/
927345153Sdim	}
928345153Sdim
929345153Sdim	/*
930345153Sdim	 * Go into normal calculation; Note that we try to run in 640K, and
931345153Sdim	 * that invalid CMOS values of non 0xffff are no longer a cause of
932345153Sdim	 * ptdi problems.  I have found a gutted kernel can run in 640K.
933345153Sdim	 */
934345153Sdim	pagesinbase = 640/4 - first/NBPG;
935345153Sdim	pagesinext = biosextmem/4;
936345153Sdim	/* use greater of either base or extended memory. do this
937345153Sdim	 * until I reinstitue discontiguous allocation of vm_page
938345153Sdim	 * array.
939345153Sdim	 */
940345153Sdim	if (pagesinbase > pagesinext)
941345153Sdim		Maxmem = 640/4;
942345153Sdim	else {
943345153Sdim		Maxmem = pagesinext + 0x100000/NBPG;
944345153Sdim		first = 0x100000; /* skip hole */
945345153Sdim	}
946345153Sdim
947345153Sdim	/* This used to explode, since Maxmem used to be 0 for bas CMOS*/
948345153Sdim	maxmem = Maxmem - 1;	/* highest page of usable memory */
949345153Sdim	physmem = maxmem;	/* number of pages of physmem addr space */
950345153Sdim/*printf("using first 0x%x to 0x%x\n ", first, maxmem*NBPG);*/
951345153Sdim	if (maxmem < 2048/4) {
952345153Sdim		printf("Too little RAM memory. Warning, running in degraded mode.\n");
953345153Sdim#ifdef INFORM_WAIT
954345153Sdim		/*
955345153Sdim		 * People with less than 2 Meg have to hit return; this way
956345153Sdim		 * we see the messages and can tell them why they blow up later.
957345153Sdim		 * If they get working well enough to recompile, they can unset
958345153Sdim		 * the flag; otherwise, it's a toy and they have to lump it.
959345153Sdim		 */
960345153Sdim		getchar();	/* kernel getchar in /sys/i386/isa/pccons.c*/
961345153Sdim#endif	/* !INFORM_WAIT*/
962345153Sdim	}
963345153Sdim	/*
964345153Sdim	 * End of CMOS bux fix
965345153Sdim	 */
966345153Sdim
967345153Sdim	/* call pmap initialization to make new kernel address space */
968345153Sdim	pmap_bootstrap (first, 0);
969345153Sdim	/* now running on new page tables, configured,and u/iom is accessible */
970345153Sdim
971345153Sdim	/* make a initial tss so microp can get interrupt stack on syscall! */
972345153Sdim	proc0.p_addr->u_pcb.pcb_tss.tss_esp0 = (int) kstack + UPAGES*NBPG;
973345153Sdim	proc0.p_addr->u_pcb.pcb_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL) ;
974345153Sdim	_gsel_tss = GSEL(GPROC0_SEL, SEL_KPL);
975345153Sdim	ltr(_gsel_tss);
976345153Sdim
977345153Sdim	/* make a call gate to reenter kernel with */
978345153Sdim	gdp = &ldt[LSYS5CALLS_SEL].gd;
979345153Sdim
980345153Sdim	x = (int) &IDTVEC(syscall);
981345153Sdim	gdp->gd_looffset = x++;
982345153Sdim	gdp->gd_selector = GSEL(GCODE_SEL,SEL_KPL);
983345153Sdim	gdp->gd_stkcpy = 0;
984345153Sdim	gdp->gd_type = SDT_SYS386CGT;
985345153Sdim	gdp->gd_dpl = SEL_UPL;
986345153Sdim	gdp->gd_p = 1;
987345153Sdim	gdp->gd_hioffset = ((int) &IDTVEC(syscall)) >>16;
988345153Sdim
989345153Sdim	/* transfer to user mode */
990345153Sdim
991345153Sdim	_ucodesel = LSEL(LUCODE_SEL, SEL_UPL);
992345153Sdim	_udatasel = LSEL(LUDATA_SEL, SEL_UPL);
993345153Sdim
994345153Sdim	/* setup proc 0's pcb */
995345153Sdim	bcopy(&sigcode, proc0.p_addr->u_pcb.pcb_sigc, szsigcode);
996345153Sdim	proc0.p_addr->u_pcb.pcb_flags = 0;
997345153Sdim	proc0.p_addr->u_pcb.pcb_ptd = IdlePTD;
998345153Sdim}
999345153Sdim
1000345153Sdimextern struct pte	*CMAP1, *CMAP2;
1001345153Sdimextern caddr_t		CADDR1, CADDR2;
1002345153Sdim/*
1003 * zero out physical memory
1004 * specified in relocation units (NBPG bytes)
1005 */
1006clearseg(n) {
1007
1008	*(int *)CMAP2 = PG_V | PG_KW | ctob(n);
1009	load_cr3(rcr3());
1010	bzero(CADDR2,NBPG);
1011	*(int *) CADDR2 = 0;
1012}
1013
1014/*
1015 * copy a page of physical memory
1016 * specified in relocation units (NBPG bytes)
1017 */
1018copyseg(frm, n) {
1019
1020	*(int *)CMAP2 = PG_V | PG_KW | ctob(n);
1021	load_cr3(rcr3());
1022	bcopy((void *)frm, (void *)CADDR2, NBPG);
1023}
1024
1025/*
1026 * copy a page of physical memory
1027 * specified in relocation units (NBPG bytes)
1028 */
1029physcopyseg(frm, to) {
1030
1031	*(int *)CMAP1 = PG_V | PG_KW | ctob(frm);
1032	*(int *)CMAP2 = PG_V | PG_KW | ctob(to);
1033	load_cr3(rcr3());
1034	bcopy(CADDR1, CADDR2, NBPG);
1035}
1036
1037/*aston() {
1038	schednetisr(NETISR_AST);
1039}*/
1040
1041setsoftclock() {
1042	schednetisr(NETISR_SCLK);
1043}
1044
1045/*
1046 * insert an element into a queue
1047 */
1048#undef insque
1049_insque(element, head)
1050	register struct prochd *element, *head;
1051{
1052	element->ph_link = head->ph_link;
1053	head->ph_link = (struct proc *)element;
1054	element->ph_rlink = (struct proc *)head;
1055	((struct prochd *)(element->ph_link))->ph_rlink=(struct proc *)element;
1056}
1057
1058/*
1059 * remove an element from a queue
1060 */
1061#undef remque
1062_remque(element)
1063	register struct prochd *element;
1064{
1065	((struct prochd *)(element->ph_link))->ph_rlink = element->ph_rlink;
1066	((struct prochd *)(element->ph_rlink))->ph_link = element->ph_link;
1067	element->ph_rlink = (struct proc *)0;
1068}
1069
1070vmunaccess() {}
1071
1072/*
1073 * Below written in C to allow access to debugging code
1074 */
1075copyinstr(fromaddr, toaddr, maxlength, lencopied) u_int *lencopied, maxlength;
1076	void *toaddr, *fromaddr; {
1077	int c,tally;
1078
1079	tally = 0;
1080	while (maxlength--) {
1081		c = fubyte(fromaddr++);
1082		if (c == -1) {
1083			if(lencopied) *lencopied = tally;
1084			return(EFAULT);
1085		}
1086		tally++;
1087		*(char *)toaddr++ = (char) c;
1088		if (c == 0){
1089			if(lencopied) *lencopied = (u_int)tally;
1090			return(0);
1091		}
1092	}
1093	if(lencopied) *lencopied = (u_int)tally;
1094	return(ENAMETOOLONG);
1095}
1096
1097copyoutstr(fromaddr, toaddr, maxlength, lencopied) u_int *lencopied, maxlength;
1098	void *fromaddr, *toaddr; {
1099	int c;
1100	int tally;
1101
1102	tally = 0;
1103	while (maxlength--) {
1104		c = subyte(toaddr++, *(char *)fromaddr);
1105		if (c == -1) return(EFAULT);
1106		tally++;
1107		if (*(char *)fromaddr++ == 0){
1108			if(lencopied) *lencopied = tally;
1109			return(0);
1110		}
1111	}
1112	if(lencopied) *lencopied = tally;
1113	return(ENAMETOOLONG);
1114}
1115
1116copystr(fromaddr, toaddr, maxlength, lencopied) u_int *lencopied, maxlength;
1117	void *fromaddr, *toaddr; {
1118	u_int tally;
1119
1120	tally = 0;
1121	while (maxlength--) {
1122		*(u_char *)toaddr = *(u_char *)fromaddr++;
1123		tally++;
1124		if (*(u_char *)toaddr++ == 0) {
1125			if(lencopied) *lencopied = tally;
1126			return(0);
1127		}
1128	}
1129	if(lencopied) *lencopied = tally;
1130	return(ENAMETOOLONG);
1131}
1132