machdep.c revision 683
197403Sobrien/*-
297403Sobrien * Copyright (c) 1992 Terrence R. Lambert.
3169691Skan * Copyright (c) 1982, 1987, 1990 The Regents of the University of California.
497403Sobrien * All rights reserved.
597403Sobrien *
697403Sobrien * This code is derived from software contributed to Berkeley by
797403Sobrien * William Jolitz.
897403Sobrien *
997403Sobrien * Redistribution and use in source and binary forms, with or without
1097403Sobrien * modification, are permitted provided that the following conditions
1197403Sobrien * are met:
1297403Sobrien * 1. Redistributions of source code must retain the above copyright
1397403Sobrien *    notice, this list of conditions and the following disclaimer.
1497403Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1597403Sobrien *    notice, this list of conditions and the following disclaimer in the
1697403Sobrien *    documentation and/or other materials provided with the distribution.
1797403Sobrien * 3. All advertising materials mentioning features or use of this software
18169691Skan *    must display the following acknowledgement:
1997403Sobrien *	This product includes software developed by the University of
2097403Sobrien *	California, Berkeley and its contributors.
2197403Sobrien * 4. Neither the name of the University nor the names of its contributors
2297403Sobrien *    may be used to endorse or promote products derived from this software
2397403Sobrien *    without specific prior written permission.
2497403Sobrien *
2597403Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2697403Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2797403Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2897403Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2997403Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3097403Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3197403Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3297403Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3397403Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3497403Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3597403Sobrien * SUCH DAMAGE.
3697403Sobrien *
3797403Sobrien *	from: @(#)machdep.c	7.4 (Berkeley) 6/3/91
3897403Sobrien *	$Id: machdep.c,v 1.13 1993/10/29 08:58:34 davidg Exp $
3997403Sobrien */
4097403Sobrien
4197403Sobrien#include "npx.h"
4297403Sobrien#include "isa.h"
4397403Sobrien
4497403Sobrien#include <stddef.h>
4597403Sobrien#include "param.h"
4697403Sobrien#include "systm.h"
4797403Sobrien#include "signalvar.h"
4897403Sobrien#include "kernel.h"
4997403Sobrien#include "map.h"
5097403Sobrien#include "proc.h"
5197403Sobrien#include "user.h"
5297403Sobrien#include "exec.h"            /* for PS_STRINGS */
5397403Sobrien#include "buf.h"
5497403Sobrien#include "reboot.h"
5597403Sobrien#include "conf.h"
5697403Sobrien#include "file.h"
5797403Sobrien#include "callout.h"
5897403Sobrien#include "malloc.h"
5997403Sobrien#include "mbuf.h"
6097403Sobrien#include "msgbuf.h"
61132720Skan#include "net/netisr.h"
62132720Skan
6397403Sobrien#ifdef SYSVSHM
6497403Sobrien#include "sys/shm.h"
6597403Sobrien#endif
66169691Skan
6797403Sobrien#include "vm/vm.h"
68132720Skan#include "vm/vm_kern.h"
69132720Skan#include "vm/vm_page.h"
70132720Skan
71132720Skan#include "sys/exec.h"
72132720Skan#include "sys/vnode.h"
73132720Skan
74132720Skan#ifndef MACHINE_NONCONTIG
75132720Skanextern vm_offset_t avail_end;
76132720Skan#else
77132720Skanextern vm_offset_t avail_start, avail_end;
78132720Skanstatic vm_offset_t hole_start, hole_end;
79132720Skanstatic vm_offset_t avail_next;
80132720Skanstatic unsigned int avail_remaining;
81132720Skan#endif /* MACHINE_NONCONTIG */
82132720Skan
83132720Skan#include "machine/cpu.h"
84132720Skan#include "machine/reg.h"
85132720Skan#include "machine/psl.h"
86132720Skan#include "machine/specialreg.h"
87132720Skan#include "machine/sysarch.h"
88169691Skan
89169691Skan#include "i386/isa/isa.h"
90132720Skan#include "i386/isa/rtc.h"
91132720Skan
92132720Skan
93169691Skan#define	EXPECT_BASEMEM	640	/* The expected base memory*/
94132720Skan#define	INFORM_WAIT	1	/* Set to pause berfore crash in weird cases*/
95132720Skan
96132720Skan/*
97169691Skan * Declare these as initialized data so we can patch them.
9897403Sobrien */
99132720Skanint	nswbuf = 0;
100132720Skan#ifdef	NBUF
101132720Skanint	nbuf = NBUF;
102132720Skan#else
103132720Skanint	nbuf = 0;
104132720Skan#endif
105169691Skan#ifdef	BUFPAGES
10697403Sobrienint	bufpages = BUFPAGES;
107132720Skan#else
108132720Skanint	bufpages = 0;
109169691Skan#endif
110169691Skanextern int freebufspace;
111169691Skan
112169691Skanint _udatasel, _ucodesel;
113132720Skan
114132720Skan/*
11597403Sobrien * Machine-dependent startup code
116132720Skan */
117169691Skanint boothowto = 0, Maxmem = 0;
118169691Skanlong dumplo;
119169691Skanint physmem, maxmem;
120169691Skanextern int bootdev;
121132720Skan#ifdef SMALL
122132720Skanextern int forcemaxmem;
123132720Skan#endif
124169691Skanint biosmem;
125169691Skan
126169691Skanextern cyloffset;
127169691Skan
128169691Skanint cpu_class;
129169691Skan
13097403Sobrienvoid dumpsys __P((void));
131169691Skan
13297403Sobrienvoid
133169691Skancpu_startup()
134169691Skan{
135169691Skan	register int unixsize;
136132720Skan	register unsigned i;
137236829Spfg	register struct pte *pte;
13897403Sobrien	int mapaddr, j;
139132720Skan	register caddr_t v;
140132720Skan	int maxbufs, base, residual;
141132720Skan	extern long Usrptsize;
142132720Skan	vm_offset_t minaddr, maxaddr;
14397403Sobrien	vm_size_t size;
144132720Skan	int firstaddr;
145132720Skan
146132720Skan	/*
147132720Skan	 * Initialize error message buffer (at end of core).
148132720Skan	 */
149132720Skan
150132720Skan	/* avail_end was pre-decremented in pmap_bootstrap to compensate */
151132720Skan	for (i = 0; i < btoc(sizeof (struct msgbuf)); i++)
152132720Skan#ifndef MACHINE_NONCONTIG
153132720Skan		pmap_enter(pmap_kernel(), msgbufp, avail_end + i * NBPG,
154132720Skan			   VM_PROT_ALL, TRUE);
155236829Spfg#else
156169691Skan		pmap_enter(pmap_kernel(), (caddr_t)msgbufp + i * NBPG,
15797403Sobrien			   avail_end + i * NBPG, VM_PROT_ALL, TRUE);
158132720Skan#endif
159132720Skan	msgbufmapped = 1;
160132720Skan
161132720Skan	/*
162132720Skan	 * Good {morning,afternoon,evening,night}.
163132720Skan	 */
164132720Skan	printf(version);
165132720Skan	identifycpu();
166132720Skan	printf("real mem  = %d\n", ctob(physmem));
167132720Skan
168132720Skan	/*
169132720Skan	 * Allocate space for system data structures.
170132720Skan	 * The first available kernel virtual address is in "v".
171132720Skan	 * As pages of kernel virtual memory are allocated, "v" is incremented.
172132720Skan	 * As pages of memory are allocated and cleared,
173132720Skan	 * "firstaddr" is incremented.
174169691Skan	 * An index into the kernel page table corresponding to the
17597403Sobrien	 * virtual memory address maintained in "v" is kept in "mapaddr".
176132720Skan	 */
177132720Skan
178132720Skan	/*
179132720Skan	 * Make two passes.  The first pass calculates how much memory is
180132720Skan	 * needed and allocates it.  The second pass assigns virtual
181132720Skan	 * addresses to the various data structures.
182132720Skan	 */
183236829Spfg	firstaddr = 0;
184132720Skanagain:
18597403Sobrien	v = (caddr_t)firstaddr;
186132720Skan
187132720Skan#define	valloc(name, type, num) \
188132720Skan	    (name) = (type *)v; v = (caddr_t)((name)+(num))
189132720Skan#define	valloclim(name, type, num, lim) \
190132720Skan	    (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num)))
191132720Skan/*	valloc(cfree, struct cblock, nclist);  no clists any more!!! - cgd */
192132720Skan	valloc(callout, struct callout, ncallout);
193236829Spfg#ifdef NetBSD
194236829Spfg	valloc(swapmap, struct map, nswapmap = maxproc * 2);
195132720Skan#endif
196132720Skan#ifdef SYSVSHM
197132720Skan	valloc(shmsegs, struct shmid_ds, shminfo.shmmni);
198132720Skan#endif
19997403Sobrien	/*
200132720Skan	 * Determine how many buffers to allocate.
20197403Sobrien	 * Use 20% of memory of memory beyond the first 2MB
202132720Skan	 * Insure a minimum of 16 fs buffers.
203132720Skan	 * We allocate 1/2 as many swap buffer headers as file i/o buffers.
204132720Skan	 */
205132720Skan	if (bufpages == 0)
206132720Skan		bufpages = ((physmem << PGSHIFT) - 3072*1024) / NBPG / 5;
207132720Skan	if (bufpages < 32)
208132720Skan		bufpages = 32;
209132720Skan
210132720Skan	/*
211132720Skan	 * We must still limit the maximum number of buffers to be no
212132720Skan	 * more than 2/5's of the size of the kernal malloc region, this
213132720Skan	 * will only take effect for machines with lots of memory
21497403Sobrien	 */
215132720Skan	bufpages = min(bufpages, (VM_KMEM_SIZE / NBPG) * 2 / 5);
216132720Skan	if (nbuf == 0) {
217132720Skan		nbuf = bufpages / 2;
218132720Skan		if (nbuf < 16)
219132720Skan			nbuf = 16;
220132720Skan	}
221132720Skan	freebufspace = bufpages * NBPG;
222132720Skan	if (nswbuf == 0) {
22397403Sobrien		nswbuf = (nbuf / 2) &~ 1;	/* force even */
224132720Skan		if (nswbuf > 256)
225132720Skan			nswbuf = 256;		/* sanity */
226132720Skan	}
227132720Skan	valloc(swbuf, struct buf, nswbuf);
228132720Skan	valloc(buf, struct buf, nbuf);
229132720Skan
230132720Skan	/*
231132720Skan	 * End of first pass, size has been calculated so allocate memory
23297403Sobrien	 */
233132720Skan	if (firstaddr == 0) {
234132720Skan		size = (vm_size_t)(v - firstaddr);
235132720Skan		firstaddr = (int)kmem_alloc(kernel_map, round_page(size));
236132720Skan		if (firstaddr == 0)
237132720Skan			panic("startup: no room for tables");
238132720Skan		goto again;
239132720Skan	}
240132720Skan	/*
24197403Sobrien	 * End of second pass, addresses have been assigned
242132720Skan	 */
243132720Skan	if ((vm_size_t)(v - firstaddr) != size)
244132720Skan		panic("startup: table size inconsistency");
245132720Skan
246132720Skan	/*
247132720Skan	 * Allocate a submap for buffer space allocations.
248132720Skan	 * XXX we are NOT using buffer_map, but due to
249132720Skan	 * the references to it we will just allocate 1 page of
25097403Sobrien	 * vm (not real memory) to make things happy...
251132720Skan	 */
252132720Skan	buffer_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
253132720Skan				/* bufpages * */NBPG, TRUE);
254132720Skan	/*
25597403Sobrien	 * Allocate a submap for exec arguments.  This map effectively
256132720Skan	 * limits the number of processes exec'ing at any time.
257132720Skan	 */
258132720Skan/*	exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
259132720Skan *				16*NCARGS, TRUE);
26097403Sobrien *	NOT CURRENTLY USED -- cgd
261132720Skan */
262132720Skan	/*
263132720Skan	 * Allocate a submap for physio
264132720Skan	 */
26597403Sobrien	phys_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
266132720Skan				 VM_PHYS_SIZE, TRUE);
267132720Skan
268132720Skan	/*
269132720Skan	 * Finally, allocate mbuf pool.  Since mclrefcnt is an off-size
270132720Skan	 * we use the more space efficient malloc in place of kmem_alloc.
271132720Skan	 */
272132720Skan	mclrefcnt = (char *)malloc(NMBCLUSTERS+CLBYTES/MCLBYTES,
273132720Skan				   M_MBUF, M_NOWAIT);
274132720Skan	bzero(mclrefcnt, NMBCLUSTERS+CLBYTES/MCLBYTES);
275132720Skan	mb_map = kmem_suballoc(kernel_map, (vm_offset_t)&mbutl, &maxaddr,
276132720Skan			       VM_MBUF_SIZE, FALSE);
277132720Skan	/*
278236829Spfg	 * Initialize callouts
279132720Skan	 */
28097403Sobrien	callfree = callout;
281132720Skan	for (i = 1; i < ncallout; i++)
282132720Skan		callout[i-1].c_next = &callout[i];
283132720Skan
284132720Skan	printf("avail mem = %d\n", ptoa(vm_page_free_count));
285132720Skan	printf("using %d buffers containing %d bytes of memory\n",
286132720Skan		nbuf, bufpages * CLBYTES);
287132720Skan
288132720Skan	/*
289132720Skan	 * Set up CPU-specific registers, cache, etc.
290132720Skan	 */
291132720Skan	initcpu();
292132720Skan
293132720Skan	/*
294132720Skan	 * Set up buffers, so they can be used to read disk labels.
295169691Skan	 */
29697403Sobrien	bufinit();
297132720Skan
298132720Skan	/*
299132720Skan	 * Configure the system.
300132720Skan	 */
301132720Skan	configure();
302132720Skan}
303132720Skan
304132720Skan
305132720Skanstruct cpu_nameclass i386_cpus[] = {
306132720Skan	{ "Intel 80286",	CPUCLASS_286 },		/* CPU_286   */
307132720Skan	{ "i386SX",		CPUCLASS_386 },		/* CPU_386SX */
308132720Skan	{ "i386DX",		CPUCLASS_386 },		/* CPU_386   */
309132720Skan	{ "i486SX",		CPUCLASS_486 },		/* CPU_486SX */
310132720Skan	{ "i486DX",		CPUCLASS_486 },		/* CPU_486   */
311132720Skan	{ "i586",		CPUCLASS_586 },		/* CPU_586   */
312132720Skan};
313132720Skan
314132720Skanidentifycpu()	/* translated from hp300 -- cgd */
315132720Skan{
316132720Skan	printf("CPU: ");
317132720Skan	if (cpu >= 0 && cpu < (sizeof i386_cpus/sizeof(struct cpu_nameclass))) {
318132720Skan		printf("%s", i386_cpus[cpu].cpu_name);
319169691Skan		cpu_class = i386_cpus[cpu].cpu_class;
32097403Sobrien	} else {
321132720Skan		printf("unknown cpu type %d\n", cpu);
322132720Skan		panic("startup: bad cpu id");
323132720Skan	}
324132720Skan	printf(" (");
325132720Skan	switch(cpu_class) {
326132720Skan	case CPUCLASS_286:
327132720Skan		printf("286");
328132720Skan		break;
329132720Skan	case CPUCLASS_386:
330132720Skan		printf("386");
331132720Skan		break;
332169691Skan	case CPUCLASS_486:
33397403Sobrien		printf("486");
334132720Skan		break;
335132720Skan	case CPUCLASS_586:
336132720Skan		printf("586");
337132720Skan		break;
338132720Skan	default:
339132720Skan		printf("unknown");	/* will panic below... */
340132720Skan	}
341132720Skan	printf("-class CPU)");
342132720Skan	printf("\n");	/* cpu speed would be nice, but how? */
343132720Skan
344132720Skan	/*
345132720Skan	 * Now that we have told the user what they have,
346169691Skan	 * let them know if that machine type isn't configured.
34797403Sobrien	 */
348132720Skan	switch (cpu_class) {
349132720Skan	case CPUCLASS_286:	/* a 286 should not make it this far, anyway */
350132720Skan#if !defined(I386_CPU) && !defined(I486_CPU) && !defined(I586_CPU)
351132720Skan#error This kernel is not configured for one of the supported CPUs
352132720Skan#endif
353132720Skan#if !defined(I386_CPU)
354132720Skan	case CPUCLASS_386:
355132720Skan#endif
356132720Skan#if !defined(I486_CPU)
357132720Skan	case CPUCLASS_486:
358132720Skan#endif
359132720Skan#if !defined(I586_CPU)
360132720Skan	case CPUCLASS_586:
361132720Skan#endif
36297403Sobrien		panic("CPU class not configured");
363132720Skan	default:
364132720Skan		break;
365132720Skan	}
366132720Skan}
367132720Skan
368132720Skan#ifdef PGINPROF
369132720Skan/*
370132720Skan * Return the difference (in microseconds)
371132720Skan * between the  current time and a previous
372132720Skan * time as represented  by the arguments.
373132720Skan * If there is a pending clock interrupt
374132720Skan * which has not been serviced due to high
375132720Skan * ipl, return error code.
376169691Skan */
37797403Sobrien/*ARGSUSED*/
378132720Skanvmtime(otime, olbolt, oicr)
379132720Skan	register int otime, olbolt, oicr;
380132720Skan{
381132720Skan
382132720Skan	return (((time.tv_sec-otime)*60 + lbolt-olbolt)*16667);
383132720Skan}
384132720Skan#endif
385132720Skan
386132720Skanextern int kstack[];
387132720Skan
388132720Skan/*
389132720Skan * Send an interrupt to process.
390132720Skan *
391132720Skan * Stack is set up to allow sigcode stored
392132720Skan * in u. to call routine, followed by kcall
393132720Skan * to sigreturn routine below.  After sigreturn
394132720Skan * resets the signal mask, the stack, and the
395132720Skan * frame pointer, it returns to the user
396132720Skan * specified pc, psl.
397132720Skan */
398132720Skanvoid
399132720Skansendsig(catcher, sig, mask, code)
400132720Skan	sig_t catcher;
401132720Skan	int sig, mask;
402132720Skan	unsigned code;
403132720Skan{
404132720Skan	register struct proc *p = curproc;
405132720Skan	register int *regs;
406132720Skan	register struct sigframe *fp;
407132720Skan	struct sigacts *ps = p->p_sigacts;
408132720Skan	int oonstack, frmtrap;
409132720Skan
410132720Skan	regs = p->p_regs;
411132720Skan        oonstack = ps->ps_onstack;
412132720Skan	frmtrap = curpcb->pcb_flags & FM_TRAP;
413132720Skan	/*
414132720Skan	 * Allocate and validate space for the signal handler
415132720Skan	 * context. Note that if the stack is in P0 space, the
416132720Skan	 * call to grow() is a nop, and the useracc() check
417132720Skan	 * will fail if the process has not already allocated
418132720Skan	 * the space with a `brk'.
419132720Skan	 */
420132720Skan        if (!ps->ps_onstack && (ps->ps_sigonstack & sigmask(sig))) {
421132720Skan		fp = (struct sigframe *)(ps->ps_sigsp
422132720Skan				- sizeof(struct sigframe));
423132720Skan                ps->ps_onstack = 1;
424132720Skan	} else {
425132720Skan		if (frmtrap)
426132720Skan			fp = (struct sigframe *)(regs[tESP]
427132720Skan				- sizeof(struct sigframe));
428132720Skan		else
429132720Skan			fp = (struct sigframe *)(regs[sESP]
430132720Skan				- sizeof(struct sigframe));
431132720Skan	}
432132720Skan
433132720Skan	if ((unsigned)fp <= (unsigned)p->p_vmspace->vm_maxsaddr + MAXSSIZ - ctob(p->p_vmspace->vm_ssize))
434132720Skan		(void)grow(p, (unsigned)fp);
435132720Skan
436132720Skan	if (useracc((caddr_t)fp, sizeof (struct sigframe), B_WRITE) == 0) {
437132720Skan		/*
438132720Skan		 * Process has trashed its stack; give it an illegal
439132720Skan		 * instruction to halt it in its tracks.
440132720Skan		 */
441132720Skan		SIGACTION(p, SIGILL) = SIG_DFL;
442132720Skan		sig = sigmask(SIGILL);
443132720Skan		p->p_sigignore &= ~sig;
444132720Skan		p->p_sigcatch &= ~sig;
445132720Skan		p->p_sigmask &= ~sig;
446132720Skan		psignal(p, SIGILL);
447132720Skan		return;
448132720Skan	}
449132720Skan
450132720Skan	/*
451132720Skan	 * Build the argument list for the signal handler.
452132720Skan	 */
453132720Skan	fp->sf_signum = sig;
454132720Skan	fp->sf_code = code;
455132720Skan	fp->sf_scp = &fp->sf_sc;
456132720Skan	fp->sf_handler = catcher;
457132720Skan
458132720Skan	/* save scratch registers */
459132720Skan	if(frmtrap) {
460132720Skan		fp->sf_eax = regs[tEAX];
461132720Skan		fp->sf_edx = regs[tEDX];
462132720Skan		fp->sf_ecx = regs[tECX];
463132720Skan	} else {
464132720Skan		fp->sf_eax = regs[sEAX];
465132720Skan		fp->sf_edx = regs[sEDX];
466132720Skan		fp->sf_ecx = regs[sECX];
467132720Skan	}
468132720Skan	/*
469132720Skan	 * Build the signal context to be used by sigreturn.
470132720Skan	 */
471132720Skan	fp->sf_sc.sc_onstack = oonstack;
472132720Skan	fp->sf_sc.sc_mask = mask;
473132720Skan	if(frmtrap) {
474132720Skan		fp->sf_sc.sc_sp = regs[tESP];
475169691Skan		fp->sf_sc.sc_fp = regs[tEBP];
476132720Skan		fp->sf_sc.sc_pc = regs[tEIP];
477132720Skan		fp->sf_sc.sc_ps = regs[tEFLAGS];
478132720Skan		regs[tESP] = (int)fp;
479169691Skan		regs[tEIP] = (int)((struct pcb *)kstack)->pcb_sigc;
480132720Skan	} else {
481132720Skan		fp->sf_sc.sc_sp = regs[sESP];
482132720Skan		fp->sf_sc.sc_fp = regs[sEBP];
483132720Skan		fp->sf_sc.sc_pc = regs[sEIP];
484132720Skan		fp->sf_sc.sc_ps = regs[sEFLAGS];
485169691Skan		regs[sESP] = (int)fp;
486169691Skan		regs[sEIP] = (int)((struct pcb *)kstack)->pcb_sigc;
487132720Skan	}
488132720Skan}
489132720Skan
490169691Skan/*
491169691Skan * System call to cleanup state after a signal
492132720Skan * has been taken.  Reset signal mask and
493132720Skan * stack state from context left by sendsig (above).
494132720Skan * Return to previous pc and psl as specified by
495132720Skan * context left by sendsig. Check carefully to
496132720Skan * make sure that the user has not modified the
497132720Skan * psl to gain improper priviledges or to cause
498132720Skan * a machine fault.
499132720Skan */
500132720Skanstruct sigreturn_args {
501132720Skan	struct sigcontext *sigcntxp;
502132720Skan};
503132720Skan
504132720Skansigreturn(p, uap, retval)
505132720Skan	struct proc *p;
506132720Skan	struct sigreturn_args *uap;
507169691Skan	int *retval;
508169691Skan{
509132720Skan	register struct sigcontext *scp;
510132720Skan	register struct sigframe *fp;
511132720Skan	register int *regs = p->p_regs;
512132720Skan
513132720Skan	/*
514132720Skan	 * (XXX old comment) regs[sESP] points to the return address.
515132720Skan	 * The user scp pointer is above that.
516132720Skan	 * The return address is faked in the signal trampoline code
517132720Skan	 * for consistency.
518132720Skan	 */
519132720Skan	scp = uap->sigcntxp;
520132720Skan	fp = (struct sigframe *)
521132720Skan	     ((caddr_t)scp - offsetof(struct sigframe, sf_sc));
522132720Skan
523132720Skan	if (useracc((caddr_t)fp, sizeof (*fp), 0) == 0)
524169691Skan		return(EINVAL);
525169691Skan
526132720Skan	/* restore scratch registers */
527132720Skan	regs[sEAX] = fp->sf_eax ;
528132720Skan	regs[sEDX] = fp->sf_edx ;
529132720Skan	regs[sECX] = fp->sf_ecx ;
530132720Skan
531169691Skan	if (useracc((caddr_t)scp, sizeof (*scp), 0) == 0)
532169691Skan		return(EINVAL);
533132720Skan#ifdef notyet
534132720Skan	if ((scp->sc_ps & PSL_MBZ) != 0 || (scp->sc_ps & PSL_MBO) != PSL_MBO) {
535132720Skan		return(EINVAL);
536132720Skan	}
537132720Skan#endif
538132720Skan        p->p_sigacts->ps_onstack = scp->sc_onstack & 01;
539132720Skan	p->p_sigmask = scp->sc_mask &~
540132720Skan	    (sigmask(SIGKILL)|sigmask(SIGCONT)|sigmask(SIGSTOP));
541132720Skan	regs[sEBP] = scp->sc_fp;
542132720Skan	regs[sESP] = scp->sc_sp;
543132720Skan	regs[sEIP] = scp->sc_pc;
544132720Skan	regs[sEFLAGS] = scp->sc_ps;
545169691Skan	return(EJUSTRETURN);
546169691Skan}
547132720Skan
548132720Skan/*
549132720Skan * a simple function to make the system panic (and dump a vmcore)
550132720Skan * in a predictable fashion
551132720Skan */
552169691Skanvoid diediedie()
553169691Skan{
554132720Skan	panic("because you said to!");
555132720Skan}
556132720Skan
557132720Skanint	waittime = -1;
558132720Skanstruct pcb dumppcb;
559169691Skan
560169691Skanvoid
561132720Skanboot(arghowto)
562132720Skan	int arghowto;
563169691Skan{
56497403Sobrien	register long dummy;		/* r12 is reserved */
565132720Skan	register int howto;		/* r11 == how to boot */
566	register int devtype;		/* r10 == major of root dev */
567	extern int cold;
568	int nomsg = 1;
569
570	if(cold) {
571		printf("hit reset please");
572		for(;;);
573	}
574	howto = arghowto;
575	if ((howto&RB_NOSYNC) == 0 && waittime < 0 && bfreelist[0].b_forw) {
576		register struct buf *bp;
577		int iter, nbusy;
578
579		waittime = 0;
580		(void) splnet();
581		printf("syncing disks... ");
582		/*
583		 * Release inodes held by texts before update.
584		 */
585		if (panicstr == 0)
586			vnode_pager_umount(NULL);
587		sync((struct sigcontext *)0);
588		/*
589		 * Unmount filesystems
590		 */
591#if 0
592		if (panicstr == 0)
593			vfs_unmountall();
594#endif
595
596		for (iter = 0; iter < 20; iter++) {
597			nbusy = 0;
598			for (bp = &buf[nbuf]; --bp >= buf; )
599				if ((bp->b_flags & (B_BUSY|B_INVAL)) == B_BUSY)
600					nbusy++;
601			if (nbusy == 0)
602				break;
603			if (nomsg) {
604				printf("updating disks before rebooting... ");
605				nomsg = 0;
606			}
607			printf("%d ", nbusy);
608			DELAY(40000 * iter);
609		}
610		if (nbusy)
611			printf("giving up\n");
612		else
613			printf("done\n");
614		DELAY(10000);			/* wait for printf to finish */
615	}
616	splhigh();
617	devtype = major(rootdev);
618	if (howto&RB_HALT) {
619		printf("\n");
620		printf("The operating system has halted.\n");
621		printf("Please press any key to reboot.\n\n");
622		cngetc();
623	} else {
624		if (howto & RB_DUMP) {
625			savectx(&dumppcb, 0);
626			dumppcb.pcb_ptd = rcr3();
627			dumpsys();
628			/*NOTREACHED*/
629		}
630	}
631#ifdef lint
632	dummy = 0; dummy = dummy;
633	printf("howto %d, devtype %d\n", arghowto, devtype);
634#endif
635	cpu_reset();
636	for(;;) ;
637	/*NOTREACHED*/
638}
639
640unsigned	dumpmag = 0x8fca0101;	/* magic number for savecore */
641int		dumpsize = 0;		/* also for savecore */
642/*
643 * Doadump comes here after turning off memory management and
644 * getting on the dump stack, either when called above, or by
645 * the auto-restart code.
646 */
647void
648dumpsys()
649{
650
651	if (dumpdev == NODEV)
652		return;
653	if ((minor(dumpdev)&07) != 1)
654		return;
655	dumpsize = physmem;
656	printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo);
657	printf("dump ");
658	switch ((*bdevsw[major(dumpdev)].d_dump)(dumpdev)) {
659
660	case ENXIO:
661		printf("device bad\n");
662		break;
663
664	case EFAULT:
665		printf("device not ready\n");
666		break;
667
668	case EINVAL:
669		printf("area improper\n");
670		break;
671
672	case EIO:
673		printf("i/o error\n");
674		break;
675
676	case EINTR:
677		printf("aborted from console\n");
678		break;
679
680	default:
681		printf("succeeded\n");
682		break;
683	}
684	printf("\n\n");
685	DELAY(1000);
686}
687
688#ifdef HZ
689/*
690 * If HZ is defined we use this code, otherwise the code in
691 * /sys/i386/i386/microtime.s is used.  The othercode only works
692 * for HZ=100.
693 */
694microtime(tvp)
695	register struct timeval *tvp;
696{
697	int s = splhigh();
698
699	*tvp = time;
700	tvp->tv_usec += tick;
701	while (tvp->tv_usec > 1000000) {
702		tvp->tv_sec++;
703		tvp->tv_usec -= 1000000;
704	}
705	splx(s);
706}
707#endif /* HZ */
708
709physstrat(bp, strat, prio)
710	struct buf *bp;
711	int (*strat)(), prio;
712{
713	register int s;
714	caddr_t baddr;
715
716	/*
717	 * vmapbuf clobbers b_addr so we must remember it so that it
718	 * can be restored after vunmapbuf.  This is truely rude, we
719	 * should really be storing this in a field in the buf struct
720	 * but none are available and I didn't want to add one at
721	 * this time.  Note that b_addr for dirty page pushes is
722	 * restored in vunmapbuf. (ugh!)
723	 */
724	baddr = bp->b_un.b_addr;
725	vmapbuf(bp);
726	(*strat)(bp);
727	/* pageout daemon doesn't wait for pushed pages */
728	if (bp->b_flags & B_DIRTY)
729		return;
730	s = splbio();
731	while ((bp->b_flags & B_DONE) == 0)
732		sleep((caddr_t)bp, prio);
733	splx(s);
734	vunmapbuf(bp);
735	bp->b_un.b_addr = baddr;
736}
737
738initcpu()
739{
740}
741
742/*
743 * Clear registers on exec
744 */
745void
746setregs(p, entry)
747	struct proc *p;
748	u_long entry;
749{
750
751	p->p_regs[sEBP] = 0;	/* bottom of the fp chain */
752	p->p_regs[sEIP] = entry;
753
754	p->p_addr->u_pcb.pcb_flags = 0;	/* no fp at all */
755	load_cr0(rcr0() | CR0_TS);	/* start emulating */
756#if	NNPX > 0
757	npxinit(__INITIAL_NPXCW__);
758#endif	/* NNPX > 0 */
759}
760
761/*
762 * Initialize 386 and configure to run kernel
763 */
764
765/*
766 * Initialize segments & interrupt table
767 */
768#define DESCRIPTOR_SIZE	8
769
770#define	GNULL_SEL	0	/* Null Descriptor */
771#define	GCODE_SEL	1	/* Kernel Code Descriptor */
772#define	GDATA_SEL	2	/* Kernel Data Descriptor */
773#define	GLDT_SEL	3	/* LDT - eventually one per process */
774#define	GTGATE_SEL	4	/* Process task switch gate */
775#define	GPANIC_SEL	5	/* Task state to consider panic from */
776#define	GPROC0_SEL	6	/* Task state process slot zero and up */
777#define NGDT 	GPROC0_SEL+1
778
779unsigned char gdt[GPROC0_SEL+1][DESCRIPTOR_SIZE];
780
781/* interrupt descriptor table */
782struct gate_descriptor idt[NIDT];
783
784/* local descriptor table */
785unsigned char ldt[5][DESCRIPTOR_SIZE];
786#define	LSYS5CALLS_SEL	0	/* forced by intel BCS */
787#define	LSYS5SIGR_SEL	1
788
789#define	L43BSDCALLS_SEL	2	/* notyet */
790#define	LUCODE_SEL	3
791#define	LUDATA_SEL	4
792/* seperate stack, es,fs,gs sels ? */
793/* #define	LPOSIXCALLS_SEL	5	/* notyet */
794
795struct	i386tss	tss, panic_tss;
796
797extern  struct user *proc0paddr;
798
799/* software prototypes -- in more palatable form */
800struct soft_segment_descriptor gdt_segs[] = {
801	/* Null Descriptor */
802{	0x0,			/* segment base address  */
803	0x0,			/* length */
804	0,			/* segment type */
805	0,			/* segment descriptor priority level */
806	0,			/* segment descriptor present */
807	0, 0,
808	0,			/* default 32 vs 16 bit size */
809	0  			/* limit granularity (byte/page units)*/ },
810	/* Code Descriptor for kernel */
811{	0x0,			/* segment base address  */
812	0xfffff,		/* length - all address space */
813	SDT_MEMERA,		/* segment type */
814	0,			/* segment descriptor priority level */
815	1,			/* segment descriptor present */
816	0, 0,
817	1,			/* default 32 vs 16 bit size */
818	1  			/* limit granularity (byte/page units)*/ },
819	/* Data Descriptor for kernel */
820{	0x0,			/* segment base address  */
821	0xfffff,		/* length - all address space */
822	SDT_MEMRWA,		/* segment type */
823	0,			/* segment descriptor priority level */
824	1,			/* segment descriptor present */
825	0, 0,
826	1,			/* default 32 vs 16 bit size */
827	1  			/* limit granularity (byte/page units)*/ },
828	/* LDT Descriptor */
829{	(int) ldt,			/* segment base address  */
830	sizeof(ldt)-1,		/* length - all address space */
831	SDT_SYSLDT,		/* segment type */
832	0,			/* segment descriptor priority level */
833	1,			/* segment descriptor present */
834	0, 0,
835	0,			/* unused - default 32 vs 16 bit size */
836	0  			/* limit granularity (byte/page units)*/ },
837	/* Null Descriptor - Placeholder */
838{	0x0,			/* segment base address  */
839	0x0,			/* length - all address space */
840	0,			/* segment type */
841	0,			/* segment descriptor priority level */
842	0,			/* segment descriptor present */
843	0, 0,
844	0,			/* default 32 vs 16 bit size */
845	0  			/* limit granularity (byte/page units)*/ },
846	/* Panic Tss Descriptor */
847{	(int) &panic_tss,		/* segment base address  */
848	sizeof(tss)-1,		/* length - all address space */
849	SDT_SYS386TSS,		/* segment type */
850	0,			/* segment descriptor priority level */
851	1,			/* segment descriptor present */
852	0, 0,
853	0,			/* unused - default 32 vs 16 bit size */
854	0  			/* limit granularity (byte/page units)*/ },
855	/* Proc 0 Tss Descriptor */
856{	(int) kstack,			/* segment base address  */
857	sizeof(tss)-1,		/* length - all address space */
858	SDT_SYS386TSS,		/* segment type */
859	0,			/* segment descriptor priority level */
860	1,			/* segment descriptor present */
861	0, 0,
862	0,			/* unused - default 32 vs 16 bit size */
863	0  			/* limit granularity (byte/page units)*/ }};
864
865struct soft_segment_descriptor ldt_segs[] = {
866	/* Null Descriptor - overwritten by call gate */
867{	0x0,			/* segment base address  */
868	0x0,			/* length - all address space */
869	0,			/* segment type */
870	0,			/* segment descriptor priority level */
871	0,			/* segment descriptor present */
872	0, 0,
873	0,			/* default 32 vs 16 bit size */
874	0  			/* limit granularity (byte/page units)*/ },
875	/* Null Descriptor - overwritten by call gate */
876{	0x0,			/* segment base address  */
877	0x0,			/* length - all address space */
878	0,			/* segment type */
879	0,			/* segment descriptor priority level */
880	0,			/* segment descriptor present */
881	0, 0,
882	0,			/* default 32 vs 16 bit size */
883	0  			/* limit granularity (byte/page units)*/ },
884	/* Null Descriptor - overwritten by call gate */
885{	0x0,			/* segment base address  */
886	0x0,			/* length - all address space */
887	0,			/* segment type */
888	0,			/* segment descriptor priority level */
889	0,			/* segment descriptor present */
890	0, 0,
891	0,			/* default 32 vs 16 bit size */
892	0  			/* limit granularity (byte/page units)*/ },
893	/* Code Descriptor for user */
894{	0x0,			/* segment base address  */
895	0xfffff,		/* length - all address space */
896	SDT_MEMERA,		/* segment type */
897	SEL_UPL,		/* segment descriptor priority level */
898	1,			/* segment descriptor present */
899	0, 0,
900	1,			/* default 32 vs 16 bit size */
901	1  			/* limit granularity (byte/page units)*/ },
902	/* Data Descriptor for user */
903{	0x0,			/* segment base address  */
904	0xfffff,		/* length - all address space */
905	SDT_MEMRWA,		/* segment type */
906	SEL_UPL,		/* segment descriptor priority level */
907	1,			/* segment descriptor present */
908	0, 0,
909	1,			/* default 32 vs 16 bit size */
910	1  			/* limit granularity (byte/page units)*/ } };
911
912setidt(idx, func, typ, dpl) char *func; {
913	struct gate_descriptor *ip = idt + idx;
914
915	ip->gd_looffset = (int)func;
916	ip->gd_selector = 8;
917	ip->gd_stkcpy = 0;
918	ip->gd_xx = 0;
919	ip->gd_type = typ;
920	ip->gd_dpl = dpl;
921	ip->gd_p = 1;
922	ip->gd_hioffset = ((int)func)>>16 ;
923}
924
925#define	IDTVEC(name)	__CONCAT(X, name)
926extern	IDTVEC(div), IDTVEC(dbg), IDTVEC(nmi), IDTVEC(bpt), IDTVEC(ofl),
927	IDTVEC(bnd), IDTVEC(ill), IDTVEC(dna), IDTVEC(dble), IDTVEC(fpusegm),
928	IDTVEC(tss), IDTVEC(missing), IDTVEC(stk), IDTVEC(prot),
929	IDTVEC(page), IDTVEC(rsvd), IDTVEC(fpu), IDTVEC(rsvd0),
930	IDTVEC(rsvd1), IDTVEC(rsvd2), IDTVEC(rsvd3), IDTVEC(rsvd4),
931	IDTVEC(rsvd5), IDTVEC(rsvd6), IDTVEC(rsvd7), IDTVEC(rsvd8),
932	IDTVEC(rsvd9), IDTVEC(rsvd10), IDTVEC(rsvd11), IDTVEC(rsvd12),
933	IDTVEC(rsvd13), IDTVEC(rsvd14), IDTVEC(rsvd14), IDTVEC(syscall);
934
935int lcr0(), lcr3(), rcr0(), rcr2();
936int _gsel_tss;
937
938init386(first)
939{
940	extern ssdtosd(), lgdt(), lidt(), lldt(), etext;
941	int x, *pi;
942	unsigned biosbasemem, biosextmem;
943	struct gate_descriptor *gdp;
944	extern int sigcode,szsigcode;
945	/* table descriptors - used to load tables by microp */
946	unsigned short	r_gdt[3], r_idt[3];
947	int	pagesinbase, pagesinext;
948
949
950	proc0.p_addr = proc0paddr;
951
952	/*
953	 * Initialize the console before we print anything out.
954	 */
955
956	cninit ();
957
958	/*
959	 * make gdt memory segments, the code segment goes up to end of the
960	 * page with etext in it, the data segment goes to the end of
961	 * the address space
962	 */
963	gdt_segs[GCODE_SEL].ssd_limit = i386_btop(i386_round_page(&etext)) - 1;
964	gdt_segs[GDATA_SEL].ssd_limit = 0xffffffff;	/* XXX constant? */
965	for (x=0; x < NGDT; x++) ssdtosd(gdt_segs+x, gdt+x);
966	/* make ldt memory segments */
967	/*
968	 * The data segment limit must not cover the user area because we
969	 * don't want the user area to be writable in copyout() etc. (page
970	 * level protection is lost in kernel mode on 386's).  Also, we
971	 * don't want the user area to be writable directly (page level
972	 * protection of the user area is not available on 486's with
973	 * CR0_WP set, because there is no user-read/kernel-write mode).
974	 *
975	 * XXX - VM_MAXUSER_ADDRESS is an end address, not a max.  And it
976	 * should be spelled ...MAX_USER...
977	 */
978#define VM_END_USER_RW_ADDRESS	VM_MAXUSER_ADDRESS
979	/*
980	 * The code segment limit has to cover the user area until we move
981	 * the signal trampoline out of the user area.  This is safe because
982	 * the code segment cannot be written to directly.
983	 */
984#define VM_END_USER_R_ADDRESS	(VM_END_USER_RW_ADDRESS + UPAGES * NBPG)
985	ldt_segs[LUCODE_SEL].ssd_limit = i386_btop(VM_END_USER_R_ADDRESS) - 1;
986	ldt_segs[LUDATA_SEL].ssd_limit = i386_btop(VM_END_USER_RW_ADDRESS) - 1;
987	/* Note. eventually want private ldts per process */
988	for (x=0; x < 5; x++) ssdtosd(ldt_segs+x, ldt+x);
989
990	/* exceptions */
991	setidt(0, &IDTVEC(div),  SDT_SYS386TGT, SEL_KPL);
992	setidt(1, &IDTVEC(dbg),  SDT_SYS386TGT, SEL_KPL);
993	setidt(2, &IDTVEC(nmi),  SDT_SYS386TGT, SEL_KPL);
994 	setidt(3, &IDTVEC(bpt),  SDT_SYS386TGT, SEL_UPL);
995	setidt(4, &IDTVEC(ofl),  SDT_SYS386TGT, SEL_KPL);
996	setidt(5, &IDTVEC(bnd),  SDT_SYS386TGT, SEL_KPL);
997	setidt(6, &IDTVEC(ill),  SDT_SYS386TGT, SEL_KPL);
998	setidt(7, &IDTVEC(dna),  SDT_SYS386TGT, SEL_KPL);
999	setidt(8, &IDTVEC(dble),  SDT_SYS386TGT, SEL_KPL);
1000	setidt(9, &IDTVEC(fpusegm),  SDT_SYS386TGT, SEL_KPL);
1001	setidt(10, &IDTVEC(tss),  SDT_SYS386TGT, SEL_KPL);
1002	setidt(11, &IDTVEC(missing),  SDT_SYS386TGT, SEL_KPL);
1003	setidt(12, &IDTVEC(stk),  SDT_SYS386TGT, SEL_KPL);
1004	setidt(13, &IDTVEC(prot),  SDT_SYS386TGT, SEL_KPL);
1005	setidt(14, &IDTVEC(page),  SDT_SYS386TGT, SEL_KPL);
1006	setidt(15, &IDTVEC(rsvd),  SDT_SYS386TGT, SEL_KPL);
1007	setidt(16, &IDTVEC(fpu),  SDT_SYS386TGT, SEL_KPL);
1008	setidt(17, &IDTVEC(rsvd0),  SDT_SYS386TGT, SEL_KPL);
1009	setidt(18, &IDTVEC(rsvd1),  SDT_SYS386TGT, SEL_KPL);
1010	setidt(19, &IDTVEC(rsvd2),  SDT_SYS386TGT, SEL_KPL);
1011	setidt(20, &IDTVEC(rsvd3),  SDT_SYS386TGT, SEL_KPL);
1012	setidt(21, &IDTVEC(rsvd4),  SDT_SYS386TGT, SEL_KPL);
1013	setidt(22, &IDTVEC(rsvd5),  SDT_SYS386TGT, SEL_KPL);
1014	setidt(23, &IDTVEC(rsvd6),  SDT_SYS386TGT, SEL_KPL);
1015	setidt(24, &IDTVEC(rsvd7),  SDT_SYS386TGT, SEL_KPL);
1016	setidt(25, &IDTVEC(rsvd8),  SDT_SYS386TGT, SEL_KPL);
1017	setidt(26, &IDTVEC(rsvd9),  SDT_SYS386TGT, SEL_KPL);
1018	setidt(27, &IDTVEC(rsvd10),  SDT_SYS386TGT, SEL_KPL);
1019	setidt(28, &IDTVEC(rsvd11),  SDT_SYS386TGT, SEL_KPL);
1020	setidt(29, &IDTVEC(rsvd12),  SDT_SYS386TGT, SEL_KPL);
1021	setidt(30, &IDTVEC(rsvd13),  SDT_SYS386TGT, SEL_KPL);
1022	setidt(31, &IDTVEC(rsvd14),  SDT_SYS386TGT, SEL_KPL);
1023
1024#include	"isa.h"
1025#if	NISA >0
1026	isa_defaultirq();
1027#endif
1028
1029	r_gdt[0] = (unsigned short) (sizeof(gdt) - 1);
1030	r_gdt[1] = (unsigned short) ((int) gdt & 0xffff);
1031	r_gdt[2] = (unsigned short) ((int) gdt >> 16);
1032	lgdt(&r_gdt);
1033	r_idt[0] = (unsigned short) (sizeof(idt) - 1);
1034	r_idt[1] = (unsigned short) ((int) idt & 0xfffff);
1035	r_idt[2] = (unsigned short) ((int) idt >> 16);
1036	lidt(&r_idt);
1037	lldt(GSEL(GLDT_SEL, SEL_KPL));
1038
1039#include "ddb.h"
1040#if NDDB > 0
1041	kdb_init();
1042	if (boothowto & RB_KDB)
1043		Debugger();
1044#endif
1045
1046	/* Use BIOS values stored in RTC CMOS RAM, since probing
1047	 * breaks certain 386 AT relics.
1048	 */
1049	biosbasemem = rtcin(RTC_BASELO)+ (rtcin(RTC_BASEHI)<<8);
1050	biosextmem = rtcin(RTC_EXTLO)+ (rtcin(RTC_EXTHI)<<8);
1051/*printf("bios base %d ext %d ", biosbasemem, biosextmem);*/
1052
1053	/*
1054	 * 15 Aug 92	Terry Lambert		The real fix for the CMOS bug
1055	 */
1056	if( biosbasemem != EXPECT_BASEMEM) {
1057		printf( "Warning: Base memory %dK, assuming %dK\n", biosbasemem, EXPECT_BASEMEM);
1058		biosbasemem = EXPECT_BASEMEM;		/* assume base*/
1059	}
1060
1061	if( biosextmem > 65536) {
1062		printf( "Warning: Extended memory %dK(>64M), assuming 0K\n", biosextmem);
1063		biosextmem = 0;				/* assume none*/
1064	}
1065
1066	/*
1067	 * Go into normal calculation; Note that we try to run in 640K, and
1068	 * that invalid CMOS values of non 0xffff are no longer a cause of
1069	 * ptdi problems.  I have found a gutted kernel can run in 640K.
1070	 */
1071	pagesinbase = 640/4 - first/NBPG;
1072	pagesinext = biosextmem/4;
1073	/* use greater of either base or extended memory. do this
1074	 * until I reinstitue discontiguous allocation of vm_page
1075	 * array.
1076	 */
1077	if (pagesinbase > pagesinext)
1078		Maxmem = 640/4;
1079	else {
1080		Maxmem = pagesinext + 0x100000/NBPG;
1081		if (first < 0x100000)
1082			first = 0x100000; /* skip hole */
1083	}
1084
1085	/* This used to explode, since Maxmem used to be 0 for bas CMOS*/
1086	maxmem = Maxmem - 1;	/* highest page of usable memory */
1087	physmem = maxmem;	/* number of pages of physmem addr space */
1088/*printf("using first 0x%x to 0x%x\n ", first, maxmem*NBPG);*/
1089	if (maxmem < 2048/4) {
1090		printf("Too little RAM memory. Warning, running in degraded mode.\n");
1091#ifdef INFORM_WAIT
1092		/*
1093		 * People with less than 2 Meg have to hit return; this way
1094		 * we see the messages and can tell them why they blow up later.
1095		 * If they get working well enough to recompile, they can unset
1096		 * the flag; otherwise, it's a toy and they have to lump it.
1097		 */
1098		cngetc();
1099#endif	/* !INFORM_WAIT*/
1100	}
1101
1102	/* call pmap initialization to make new kernel address space */
1103#ifndef MACHINCE_NONCONTIG
1104	pmap_bootstrap (first, 0);
1105#else
1106	pmap_bootstrap ((vm_offset_t)atdevbase + IOM_SIZE);
1107
1108#endif /* MACHINE_NONCONTIG */
1109	/* now running on new page tables, configured,and u/iom is accessible */
1110
1111	/* make a initial tss so microp can get interrupt stack on syscall! */
1112	proc0.p_addr->u_pcb.pcb_tss.tss_esp0 = (int) kstack + UPAGES*NBPG;
1113	proc0.p_addr->u_pcb.pcb_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL) ;
1114	_gsel_tss = GSEL(GPROC0_SEL, SEL_KPL);
1115
1116	((struct i386tss *)gdt_segs[GPROC0_SEL].ssd_base)->tss_ioopt =
1117		(sizeof(tss))<<16;
1118
1119	ltr(_gsel_tss);
1120
1121	/* make a call gate to reenter kernel with */
1122	gdp = (struct gate_descriptor *) &ldt[LSYS5CALLS_SEL][0];
1123
1124	x = (int) &IDTVEC(syscall);
1125	gdp->gd_looffset = x++;
1126	gdp->gd_selector = GSEL(GCODE_SEL,SEL_KPL);
1127	gdp->gd_stkcpy = 0;
1128	gdp->gd_type = SDT_SYS386CGT;
1129	gdp->gd_dpl = SEL_UPL;
1130	gdp->gd_p = 1;
1131	gdp->gd_hioffset = ((int) &IDTVEC(syscall)) >>16;
1132
1133	/* transfer to user mode */
1134
1135	_ucodesel = LSEL(LUCODE_SEL, SEL_UPL);
1136	_udatasel = LSEL(LUDATA_SEL, SEL_UPL);
1137
1138	/* setup proc 0's pcb */
1139	bcopy(&sigcode, proc0.p_addr->u_pcb.pcb_sigc, szsigcode);
1140	proc0.p_addr->u_pcb.pcb_flags = 0;
1141	proc0.p_addr->u_pcb.pcb_ptd = IdlePTD;
1142}
1143
1144extern struct pte	*CMAP1, *CMAP2;
1145extern caddr_t		CADDR1, CADDR2;
1146/*
1147 * zero out physical memory
1148 * specified in relocation units (NBPG bytes)
1149 */
1150clearseg(n) {
1151
1152	*(int *)CMAP2 = PG_V | PG_KW | ctob(n);
1153	load_cr3(rcr3());
1154	bzero(CADDR2,NBPG);
1155#ifndef MACHINE_NONCONTIG
1156	*(int *) CADDR2 = 0;
1157#endif /* MACHINE_NONCONTIG */
1158}
1159
1160/*
1161 * copy a page of physical memory
1162 * specified in relocation units (NBPG bytes)
1163 */
1164void
1165copyseg(frm, n) {
1166
1167	*(int *)CMAP2 = PG_V | PG_KW | ctob(n);
1168	load_cr3(rcr3());
1169	bcopy((void *)frm, (void *)CADDR2, NBPG);
1170}
1171
1172/*
1173 * copy a page of physical memory
1174 * specified in relocation units (NBPG bytes)
1175 */
1176void
1177physcopyseg(frm, to) {
1178
1179	*(int *)CMAP1 = PG_V | PG_KW | ctob(frm);
1180	*(int *)CMAP2 = PG_V | PG_KW | ctob(to);
1181	load_cr3(rcr3());
1182	bcopy(CADDR1, CADDR2, NBPG);
1183}
1184
1185/*aston() {
1186	schednetisr(NETISR_AST);
1187}*/
1188
1189void
1190setsoftclock() {
1191	schednetisr(NETISR_SCLK);
1192}
1193
1194/*
1195 * insert an element into a queue
1196 */
1197#undef insque
1198_insque(element, head)
1199	register struct prochd *element, *head;
1200{
1201	element->ph_link = head->ph_link;
1202	head->ph_link = (struct proc *)element;
1203	element->ph_rlink = (struct proc *)head;
1204	((struct prochd *)(element->ph_link))->ph_rlink=(struct proc *)element;
1205}
1206
1207/*
1208 * remove an element from a queue
1209 */
1210#undef remque
1211_remque(element)
1212	register struct prochd *element;
1213{
1214	((struct prochd *)(element->ph_link))->ph_rlink = element->ph_rlink;
1215	((struct prochd *)(element->ph_rlink))->ph_link = element->ph_link;
1216	element->ph_rlink = (struct proc *)0;
1217}
1218
1219#ifdef SLOW_OLD_COPYSTRS
1220vmunaccess() {}
1221
1222#if 0		/* assembler versions now in locore.s */
1223/*
1224 * Below written in C to allow access to debugging code
1225 */
1226copyinstr(fromaddr, toaddr, maxlength, lencopied) u_int *lencopied, maxlength;
1227	void *toaddr, *fromaddr; {
1228	int c,tally;
1229
1230	tally = 0;
1231	while (maxlength--) {
1232		c = fubyte(fromaddr++);
1233		if (c == -1) {
1234			if(lencopied) *lencopied = tally;
1235			return(EFAULT);
1236		}
1237		tally++;
1238		*(char *)toaddr++ = (char) c;
1239		if (c == 0){
1240			if(lencopied) *lencopied = (u_int)tally;
1241			return(0);
1242		}
1243	}
1244	if(lencopied) *lencopied = (u_int)tally;
1245	return(ENAMETOOLONG);
1246}
1247
1248copyoutstr(fromaddr, toaddr, maxlength, lencopied) u_int *lencopied, maxlength;
1249	void *fromaddr, *toaddr; {
1250	int c;
1251	int tally;
1252
1253	tally = 0;
1254	while (maxlength--) {
1255		c = subyte(toaddr++, *(char *)fromaddr);
1256		if (c == -1) return(EFAULT);
1257		tally++;
1258		if (*(char *)fromaddr++ == 0){
1259			if(lencopied) *lencopied = tally;
1260			return(0);
1261		}
1262	}
1263	if(lencopied) *lencopied = tally;
1264	return(ENAMETOOLONG);
1265}
1266
1267#endif /* SLOW_OLD_COPYSTRS */
1268
1269copystr(fromaddr, toaddr, maxlength, lencopied) u_int *lencopied, maxlength;
1270	void *fromaddr, *toaddr; {
1271	u_int tally;
1272
1273	tally = 0;
1274	while (maxlength--) {
1275		*(u_char *)toaddr = *(u_char *)fromaddr++;
1276		tally++;
1277		if (*(u_char *)toaddr++ == 0) {
1278			if(lencopied) *lencopied = tally;
1279			return(0);
1280		}
1281	}
1282	if(lencopied) *lencopied = tally;
1283	return(ENAMETOOLONG);
1284}
1285#endif
1286