machdep.c revision 2495
1/*-
2 * Copyright (c) 1992 Terrence R. Lambert.
3 * Copyright (c) 1982, 1987, 1990 The Regents of the University of California.
4 * All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * William Jolitz.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 *    must display the following acknowledgement:
19 *	This product includes software developed by the University of
20 *	California, Berkeley and its contributors.
21 * 4. Neither the name of the University nor the names of its contributors
22 *    may be used to endorse or promote products derived from this software
23 *    without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 *
37 *	from: @(#)machdep.c	7.4 (Berkeley) 6/3/91
38 *	$Id: machdep.c,v 1.60 1994/09/02 04:12:04 davidg Exp $
39 */
40
41#include "npx.h"
42#include "isa.h"
43
44#include <sys/param.h>
45#include <sys/systm.h>
46#include <sys/signalvar.h>
47#include <sys/kernel.h>
48#include <sys/map.h>
49#include <sys/proc.h>
50#include <sys/user.h>
51#include <sys/buf.h>
52#include <sys/reboot.h>
53#include <sys/conf.h>
54#include <sys/file.h>
55#include <sys/callout.h>
56#include <sys/malloc.h>
57#include <sys/mbuf.h>
58#include <sys/msgbuf.h>
59#include <sys/ioctl.h>
60#include <sys/sysent.h>
61#include <sys/tty.h>
62#include <sys/sysctl.h>
63
64#ifdef SYSVSHM
65#include <sys/shm.h>
66#endif
67
68#ifdef SYSVMSG
69#include <sys/msg.h>
70#endif
71
72#ifdef SYSVSEM
73#include <sys/sem.h>
74#endif
75
76#include <vm/vm.h>
77#include <vm/vm_kern.h>
78#include <vm/vm_page.h>
79
80#include <sys/exec.h>
81#include <sys/vnode.h>
82
83extern vm_offset_t avail_start, avail_end;
84
85#include <machine/cpu.h>
86#include <machine/reg.h>
87#include <machine/psl.h>
88#include <machine/specialreg.h>
89#include <machine/sysarch.h>
90#include <machine/cons.h>
91
92#include <i386/isa/isa.h>
93#include <i386/isa/rtc.h>
94
95static void identifycpu(void);
96static void initcpu(void);
97static int test_page(int *, int);
98
99char machine[] = "i386";
100char cpu_model[sizeof("Cy486DLC") + 1];
101
102#ifndef PANIC_REBOOT_WAIT_TIME
103#define PANIC_REBOOT_WAIT_TIME 15 /* default to 15 seconds */
104#endif
105
106/*
107 * Declare these as initialized data so we can patch them.
108 */
109int	nswbuf = 0;
110#ifdef	NBUF
111int	nbuf = NBUF;
112#else
113int	nbuf = 0;
114#endif
115#ifdef	BUFPAGES
116int	bufpages = BUFPAGES;
117#else
118int	bufpages = 0;
119#endif
120
121#ifdef BOUNCE_BUFFERS
122extern char *bouncememory;
123extern int maxbkva;
124#ifdef BOUNCEPAGES
125int	bouncepages = BOUNCEPAGES;
126#else
127int	bouncepages = 0;
128#endif
129#endif	/* BOUNCE_BUFFERS */
130
131extern int freebufspace;
132int	msgbufmapped = 0;		/* set when safe to use msgbuf */
133int _udatasel, _ucodesel;
134
135/*
136 * Machine-dependent startup code
137 */
138int boothowto = 0, Maxmem = 0, badpages = 0, physmem = 0;
139long dumplo;
140extern int bootdev;
141int biosmem;
142
143vm_offset_t	phys_avail[6];
144
145extern cyloffset;
146
147int cpu_class;
148
149void dumpsys __P((void));
150vm_offset_t buffer_sva, buffer_eva;
151vm_offset_t clean_sva, clean_eva;
152vm_offset_t pager_sva, pager_eva;
153extern int pager_map_size;
154
155#define offsetof(type, member)	((size_t)(&((type *)0)->member))
156
157void
158cpu_startup()
159{
160	register int unixsize;
161	register unsigned i;
162	register struct pte *pte;
163	int mapaddr, j;
164	register caddr_t v;
165	int maxbufs, base, residual;
166	extern long Usrptsize;
167	vm_offset_t minaddr, maxaddr;
168	vm_size_t size = 0;
169	int firstaddr;
170
171	/*
172	 * Initialize error message buffer (at end of core).
173	 */
174
175	/* avail_end was pre-decremented in init_386() to compensate */
176	for (i = 0; i < btoc(sizeof (struct msgbuf)); i++)
177		pmap_enter(pmap_kernel(), (vm_offset_t)msgbufp,
178			   avail_end + i * NBPG,
179			   VM_PROT_ALL, TRUE);
180	msgbufmapped = 1;
181
182	/*
183	 * Good {morning,afternoon,evening,night}.
184	 */
185	printf(version);
186	startrtclock();
187	identifycpu();
188	printf("real memory  = %d (%d pages)\n", ptoa(physmem), physmem);
189	if (badpages)
190		printf("bad memory   = %d (%d pages)\n", ptoa(badpages), badpages);
191
192	/*
193	 * Allocate space for system data structures.
194	 * The first available kernel virtual address is in "v".
195	 * As pages of kernel virtual memory are allocated, "v" is incremented.
196	 * As pages of memory are allocated and cleared,
197	 * "firstaddr" is incremented.
198	 * An index into the kernel page table corresponding to the
199	 * virtual memory address maintained in "v" is kept in "mapaddr".
200	 */
201
202	/*
203	 * Make two passes.  The first pass calculates how much memory is
204	 * needed and allocates it.  The second pass assigns virtual
205	 * addresses to the various data structures.
206	 */
207	firstaddr = 0;
208again:
209	v = (caddr_t)firstaddr;
210
211#define	valloc(name, type, num) \
212	    (name) = (type *)v; v = (caddr_t)((name)+(num))
213#define	valloclim(name, type, num, lim) \
214	    (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num)))
215	valloc(callout, struct callout, ncallout);
216#ifdef SYSVSHM
217	valloc(shmsegs, struct shmid_ds, shminfo.shmmni);
218#endif
219#ifdef SYSVSEM
220	valloc(sema, struct semid_ds, seminfo.semmni);
221	valloc(sem, struct sem, seminfo.semmns);
222	/* This is pretty disgusting! */
223	valloc(semu, int, (seminfo.semmnu * seminfo.semusz) / sizeof(int));
224#endif
225#ifdef SYSVMSG
226	valloc(msgpool, char, msginfo.msgmax);
227	valloc(msgmaps, struct msgmap, msginfo.msgseg);
228	valloc(msghdrs, struct msg, msginfo.msgtql);
229	valloc(msqids, struct msqid_ds, msginfo.msgmni);
230#endif
231	/*
232	 * Determine how many buffers to allocate.
233	 * Use 20% of memory of memory beyond the first 2MB
234	 * Insure a minimum of 16 fs buffers.
235	 * We allocate 1/2 as many swap buffer headers as file i/o buffers.
236	 */
237	if (bufpages == 0)
238		bufpages = ((physmem << PGSHIFT) - 2048*1024) / NBPG / 5;
239	if (bufpages < 64)
240		bufpages = 64;
241
242	/*
243	 * We must still limit the maximum number of buffers to be no
244	 * more than 2/5's of the size of the kernal malloc region, this
245	 * will only take effect for machines with lots of memory
246	 */
247	bufpages = min(bufpages, (VM_KMEM_SIZE / NBPG) * 2 / 5);
248	if (nbuf == 0) {
249		nbuf = bufpages / 2;
250		if (nbuf < 32)
251			nbuf = 32;
252	}
253	freebufspace = bufpages * NBPG;
254	if (nswbuf == 0) {
255		nswbuf = (nbuf / 2) &~ 1;	/* force even */
256		if (nswbuf > 64)
257			nswbuf = 64;		/* sanity */
258	}
259	valloc(swbuf, struct buf, nswbuf);
260	valloc(buf, struct buf, nbuf);
261
262#ifdef BOUNCE_BUFFERS
263	/*
264	 * If there is more than 16MB of memory, allocate some bounce buffers
265	 */
266	if (Maxmem > 4096) {
267		if (bouncepages == 0)
268			bouncepages = 96;	/* largest physio size + extra */
269		v = (caddr_t)((vm_offset_t)((vm_offset_t)v + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1));
270		valloc(bouncememory, char, bouncepages * PAGE_SIZE);
271	}
272#endif
273
274	/*
275	 * End of first pass, size has been calculated so allocate memory
276	 */
277	if (firstaddr == 0) {
278		size = (vm_size_t)(v - firstaddr);
279		firstaddr = (int)kmem_alloc(kernel_map, round_page(size));
280		if (firstaddr == 0)
281			panic("startup: no room for tables");
282		goto again;
283	}
284
285	/*
286	 * End of second pass, addresses have been assigned
287	 */
288	if ((vm_size_t)(v - firstaddr) != size)
289		panic("startup: table size inconsistency");
290
291#ifdef BOUNCE_BUFFERS
292	clean_map = kmem_suballoc(kernel_map, &clean_sva, &clean_eva,
293			(nbuf*MAXBSIZE) + (nswbuf*MAXPHYS) +
294				maxbkva + pager_map_size, TRUE);
295	io_map = kmem_suballoc(clean_map, &minaddr, &maxaddr, maxbkva, FALSE);
296#else
297	clean_map = kmem_suballoc(kernel_map, &clean_sva, &clean_eva,
298			(nbuf*MAXBSIZE) + (nswbuf*MAXPHYS) + pager_map_size, TRUE);
299#endif
300	buffer_map = kmem_suballoc(clean_map, &buffer_sva, &buffer_eva,
301				(nbuf*MAXBSIZE), TRUE);
302	pager_map = kmem_suballoc(clean_map, &pager_sva, &pager_eva,
303				(nswbuf*MAXPHYS) + pager_map_size, TRUE);
304
305	/*
306	 * Finally, allocate mbuf pool.  Since mclrefcnt is an off-size
307	 * we use the more space efficient malloc in place of kmem_alloc.
308	 */
309	mclrefcnt = (char *)malloc(NMBCLUSTERS+CLBYTES/MCLBYTES,
310				   M_MBUF, M_NOWAIT);
311	bzero(mclrefcnt, NMBCLUSTERS+CLBYTES/MCLBYTES);
312	mb_map = kmem_suballoc(kmem_map, (vm_offset_t *)&mbutl, &maxaddr,
313			       VM_MBUF_SIZE, FALSE);
314	/*
315	 * Initialize callouts
316	 */
317	callfree = callout;
318	for (i = 1; i < ncallout; i++)
319		callout[i-1].c_next = &callout[i];
320
321	printf("avail memory = %d (%d pages)\n", ptoa(cnt.v_free_count), cnt.v_free_count);
322	printf("using %d buffers containing %d bytes of memory\n",
323		nbuf, bufpages * CLBYTES);
324
325#ifdef BOUNCE_BUFFERS
326	/*
327	 * init bounce buffers
328	 */
329	vm_bounce_init();
330#endif
331
332	/*
333	 * Set up CPU-specific registers, cache, etc.
334	 */
335	initcpu();
336
337	/*
338	 * Set up buffers, so they can be used to read disk labels.
339	 */
340	bufinit();
341	vm_pager_bufferinit();
342
343	/*
344	 * Configure the system.
345	 */
346	configure();
347}
348
349
350struct cpu_nameclass i386_cpus[] = {
351	{ "Intel 80286",	CPUCLASS_286 },		/* CPU_286   */
352	{ "i386SX",		CPUCLASS_386 },		/* CPU_386SX */
353	{ "i386DX",		CPUCLASS_386 },		/* CPU_386   */
354	{ "i486SX",		CPUCLASS_486 },		/* CPU_486SX */
355	{ "i486DX",		CPUCLASS_486 },		/* CPU_486   */
356	{ "Pentium",		CPUCLASS_586 },		/* CPU_586   */
357	{ "Cy486DLC",		CPUCLASS_486 },		/* CPU_486DLC */
358};
359
360static void
361identifycpu()
362{
363	extern u_long cpu_id;
364	extern char cpu_vendor[];
365	printf("CPU: ");
366	if (cpu >= 0
367	    && cpu < (sizeof i386_cpus/sizeof(struct cpu_nameclass))) {
368		printf("%s", i386_cpus[cpu].cpu_name);
369		cpu_class = i386_cpus[cpu].cpu_class;
370		strncpy(cpu_model, i386_cpus[cpu].cpu_name, sizeof cpu_model);
371	} else {
372		printf("unknown cpu type %d\n", cpu);
373		panic("startup: bad cpu id");
374	}
375	printf(" (");
376	switch(cpu_class) {
377	case CPUCLASS_286:
378		printf("286");
379		break;
380	case CPUCLASS_386:
381		printf("386");
382		break;
383	case CPUCLASS_486:
384		printf("486");
385		break;
386	case CPUCLASS_586:
387		printf("Pentium");
388		break;
389	default:
390		printf("unknown");	/* will panic below... */
391	}
392	printf("-class CPU)");
393#ifdef I586_CPU
394	if(cpu_class == CPUCLASS_586) {
395		extern void calibrate_cyclecounter();
396		extern int pentium_mhz;
397		calibrate_cyclecounter();
398		printf(" %d MHz", pentium_mhz);
399	}
400#endif
401	if(cpu_id)
402		printf("  Id = 0x%x",cpu_id);
403	if(*cpu_vendor)
404		printf("  Origin = \"%s\"",cpu_vendor);
405	printf("\n");	/* cpu speed would be nice, but how? */
406
407	/*
408	 * Now that we have told the user what they have,
409	 * let them know if that machine type isn't configured.
410	 */
411	switch (cpu_class) {
412	case CPUCLASS_286:	/* a 286 should not make it this far, anyway */
413#if !defined(I386_CPU) && !defined(I486_CPU) && !defined(I586_CPU)
414#error This kernel is not configured for one of the supported CPUs
415#endif
416#if !defined(I386_CPU)
417	case CPUCLASS_386:
418#endif
419#if !defined(I486_CPU)
420	case CPUCLASS_486:
421#endif
422#if !defined(I586_CPU)
423	case CPUCLASS_586:
424#endif
425		panic("CPU class not configured");
426	default:
427		break;
428	}
429}
430
431#ifdef PGINPROF
432/*
433 * Return the difference (in microseconds)
434 * between the  current time and a previous
435 * time as represented  by the arguments.
436 * If there is a pending clock interrupt
437 * which has not been serviced due to high
438 * ipl, return error code.
439 */
440/*ARGSUSED*/
441vmtime(otime, olbolt, oicr)
442	register int otime, olbolt, oicr;
443{
444
445	return (((time.tv_sec-otime)*60 + lbolt-olbolt)*16667);
446}
447#endif
448
449extern int kstack[];
450
451/*
452 * Send an interrupt to process.
453 *
454 * Stack is set up to allow sigcode stored
455 * in u. to call routine, followed by kcall
456 * to sigreturn routine below.  After sigreturn
457 * resets the signal mask, the stack, and the
458 * frame pointer, it returns to the user
459 * specified pc, psl.
460 */
461void
462sendsig(catcher, sig, mask, code)
463	sig_t catcher;
464	int sig, mask;
465	unsigned code;
466{
467	register struct proc *p = curproc;
468	register int *regs;
469	register struct sigframe *fp;
470	struct sigacts *psp = p->p_sigacts;
471	int oonstack, frmtrap;
472
473	regs = p->p_md.md_regs;
474        oonstack = psp->ps_sigstk.ss_flags & SA_ONSTACK;
475	/*
476	 * Allocate and validate space for the signal handler
477	 * context. Note that if the stack is in P0 space, the
478	 * call to grow() is a nop, and the useracc() check
479	 * will fail if the process has not already allocated
480	 * the space with a `brk'.
481	 */
482        if ((psp->ps_flags & SAS_ALTSTACK) &&
483	    (psp->ps_sigstk.ss_flags & SA_ONSTACK) == 0 &&
484	    (psp->ps_sigonstack & sigmask(sig))) {
485		fp = (struct sigframe *)(psp->ps_sigstk.ss_base +
486		    psp->ps_sigstk.ss_size - sizeof(struct sigframe));
487		psp->ps_sigstk.ss_flags |= SA_ONSTACK;
488	} else {
489		fp = (struct sigframe *)(regs[tESP]
490			- sizeof(struct sigframe));
491	}
492
493	/*
494	 * grow() will return FALSE if the fp will not fit inside the stack
495	 *	and the stack can not be grown. useracc will return FALSE
496	 *	if access is denied.
497	 */
498	if ((grow(p, (int)fp) == FALSE) ||
499	    (useracc((caddr_t)fp, sizeof (struct sigframe), B_WRITE) == FALSE)) {
500		/*
501		 * Process has trashed its stack; give it an illegal
502		 * instruction to halt it in its tracks.
503		 */
504		SIGACTION(p, SIGILL) = SIG_DFL;
505		sig = sigmask(SIGILL);
506		p->p_sigignore &= ~sig;
507		p->p_sigcatch &= ~sig;
508		p->p_sigmask &= ~sig;
509		psignal(p, SIGILL);
510		return;
511	}
512
513	/*
514	 * Build the argument list for the signal handler.
515	 */
516	if (p->p_sysent->sv_sigtbl) {
517		if (sig < p->p_sysent->sv_sigsize)
518			sig = p->p_sysent->sv_sigtbl[sig];
519		else
520			sig = p->p_sysent->sv_sigsize + 1;
521	}
522	fp->sf_signum = sig;
523	fp->sf_code = code;
524	fp->sf_scp = &fp->sf_sc;
525	fp->sf_addr = (char *) regs[tERR];
526	fp->sf_handler = catcher;
527
528	/* save scratch registers */
529	fp->sf_sc.sc_eax = regs[tEAX];
530	fp->sf_sc.sc_ebx = regs[tEBX];
531	fp->sf_sc.sc_ecx = regs[tECX];
532	fp->sf_sc.sc_edx = regs[tEDX];
533	fp->sf_sc.sc_esi = regs[tESI];
534	fp->sf_sc.sc_edi = regs[tEDI];
535	fp->sf_sc.sc_cs = regs[tCS];
536	fp->sf_sc.sc_ds = regs[tDS];
537	fp->sf_sc.sc_ss = regs[tSS];
538	fp->sf_sc.sc_es = regs[tES];
539	fp->sf_sc.sc_isp = regs[tISP];
540
541	/*
542	 * Build the signal context to be used by sigreturn.
543	 */
544	fp->sf_sc.sc_onstack = oonstack;
545	fp->sf_sc.sc_mask = mask;
546	fp->sf_sc.sc_sp = regs[tESP];
547	fp->sf_sc.sc_fp = regs[tEBP];
548	fp->sf_sc.sc_pc = regs[tEIP];
549	fp->sf_sc.sc_ps = regs[tEFLAGS];
550	regs[tESP] = (int)fp;
551	regs[tEIP] = (int)((struct pcb *)kstack)->pcb_sigc;
552	regs[tEFLAGS] &= ~PSL_VM;
553	regs[tCS] = _ucodesel;
554	regs[tDS] = _udatasel;
555	regs[tES] = _udatasel;
556	regs[tSS] = _udatasel;
557}
558
559/*
560 * System call to cleanup state after a signal
561 * has been taken.  Reset signal mask and
562 * stack state from context left by sendsig (above).
563 * Return to previous pc and psl as specified by
564 * context left by sendsig. Check carefully to
565 * make sure that the user has not modified the
566 * psl to gain improper privileges or to cause
567 * a machine fault.
568 */
569struct sigreturn_args {
570	struct sigcontext *sigcntxp;
571};
572
573int
574sigreturn(p, uap, retval)
575	struct proc *p;
576	struct sigreturn_args *uap;
577	int *retval;
578{
579	register struct sigcontext *scp;
580	register struct sigframe *fp;
581	register int *regs = p->p_md.md_regs;
582	int eflags;
583
584	/*
585	 * (XXX old comment) regs[tESP] points to the return address.
586	 * The user scp pointer is above that.
587	 * The return address is faked in the signal trampoline code
588	 * for consistency.
589	 */
590	scp = uap->sigcntxp;
591	fp = (struct sigframe *)
592	     ((caddr_t)scp - offsetof(struct sigframe, sf_sc));
593
594	if (useracc((caddr_t)fp, sizeof (*fp), 0) == 0)
595		return(EINVAL);
596
597	eflags = scp->sc_ps;
598	if ((eflags & PSL_USERCLR) != 0 ||
599	    (eflags & PSL_USERSET) != PSL_USERSET ||
600	    (eflags & PSL_IOPL) < (regs[tEFLAGS] & PSL_IOPL)) {
601#ifdef DEBUG
602    		printf("sigreturn:  eflags=0x%x\n", eflags);
603#endif
604    		return(EINVAL);
605	}
606
607	/*
608	 * Sanity check the user's selectors and error if they
609	 * are suspect.
610	 */
611#define max_ldt_sel(pcb) \
612	((pcb)->pcb_ldt ? (pcb)->pcb_ldt_len : (sizeof(ldt) / sizeof(ldt[0])))
613
614#define valid_ldt_sel(sel) \
615	(ISLDT(sel) && ISPL(sel) == SEL_UPL && \
616	 IDXSEL(sel) < max_ldt_sel(&p->p_addr->u_pcb))
617
618#define null_sel(sel) \
619	(!ISLDT(sel) && IDXSEL(sel) == 0)
620
621	if ((scp->sc_cs&0xffff != _ucodesel && !valid_ldt_sel(scp->sc_cs)) ||
622	    (scp->sc_ss&0xffff != _udatasel && !valid_ldt_sel(scp->sc_ss)) ||
623	    (scp->sc_ds&0xffff != _udatasel && !valid_ldt_sel(scp->sc_ds) &&
624	     !null_sel(scp->sc_ds)) ||
625	    (scp->sc_es&0xffff != _udatasel && !valid_ldt_sel(scp->sc_es) &&
626	     !null_sel(scp->sc_es))) {
627#ifdef DEBUG
628    		printf("sigreturn:  cs=0x%x ss=0x%x ds=0x%x es=0x%x\n",
629			scp->sc_cs, scp->sc_ss, scp->sc_ds, scp->sc_es);
630#endif
631		trapsignal(p, SIGBUS, T_PROTFLT);
632		return(EINVAL);
633	}
634
635#undef max_ldt_sel
636#undef valid_ldt_sel
637#undef null_sel
638
639	/* restore scratch registers */
640	regs[tEAX] = scp->sc_eax;
641	regs[tEBX] = scp->sc_ebx;
642	regs[tECX] = scp->sc_ecx;
643	regs[tEDX] = scp->sc_edx;
644	regs[tESI] = scp->sc_esi;
645	regs[tEDI] = scp->sc_edi;
646	regs[tCS] = scp->sc_cs;
647	regs[tDS] = scp->sc_ds;
648	regs[tES] = scp->sc_es;
649	regs[tSS] = scp->sc_ss;
650	regs[tISP] = scp->sc_isp;
651
652	if (useracc((caddr_t)scp, sizeof (*scp), 0) == 0)
653		return(EINVAL);
654
655	if (scp->sc_onstack & 01)
656		p->p_sigacts->ps_sigstk.ss_flags |= SA_ONSTACK;
657	else
658		p->p_sigacts->ps_sigstk.ss_flags &= ~SA_ONSTACK;
659	p->p_sigmask = scp->sc_mask &~
660	    (sigmask(SIGKILL)|sigmask(SIGCONT)|sigmask(SIGSTOP));
661	regs[tEBP] = scp->sc_fp;
662	regs[tESP] = scp->sc_sp;
663	regs[tEIP] = scp->sc_pc;
664	regs[tEFLAGS] = eflags;
665	return(EJUSTRETURN);
666}
667
668/*
669 * a simple function to make the system panic (and dump a vmcore)
670 * in a predictable fashion
671 */
672void diediedie()
673{
674	panic("because you said to!");
675}
676
677int	waittime = -1;
678struct pcb dumppcb;
679
680__dead void
681boot(arghowto)
682	int arghowto;
683{
684	register long dummy;		/* r12 is reserved */
685	register int howto;		/* r11 == how to boot */
686	register int devtype;		/* r10 == major of root dev */
687	extern int cold;
688
689	if (cold) {
690		printf("hit reset please");
691		for(;;);
692	}
693	howto = arghowto;
694	if ((howto&RB_NOSYNC) == 0 && waittime < 0) {
695		register struct buf *bp;
696		int iter, nbusy;
697
698		waittime = 0;
699		(void) splnet();
700		printf("\nsyncing disks... ");
701		/*
702		 * Release inodes held by texts before update.
703		 */
704		if (panicstr == 0)
705			vnode_pager_umount(NULL);
706		sync(curproc, NULL, NULL);
707
708		for (iter = 0; iter < 20; iter++) {
709			nbusy = 0;
710			for (bp = &buf[nbuf]; --bp >= buf; )
711				if ((bp->b_flags & (B_BUSY|B_INVAL)) == B_BUSY)
712					nbusy++;
713			if (nbusy == 0)
714				break;
715			printf("%d ", nbusy);
716			DELAY(40000 * iter);
717		}
718		if (nbusy) {
719			/*
720			 * Failed to sync all blocks. Indicate this and don't
721			 * unmount filesystems (thus forcing an fsck on reboot).
722			 */
723			printf("giving up\n");
724		} else {
725			printf("done\n");
726			/*
727			 * Unmount filesystems
728			 */
729			if (panicstr == 0)
730				vfs_unmountall();
731		}
732		DELAY(100000);			/* wait for console output to finish */
733	}
734	splhigh();
735	devtype = major(rootdev);
736	if (howto&RB_HALT) {
737		printf("\n");
738		printf("The operating system has halted.\n");
739		printf("Please press any key to reboot.\n\n");
740		cngetc();
741	} else {
742		if (howto & RB_DUMP) {
743			savectx(&dumppcb, 0);
744			dumppcb.pcb_ptd = rcr3();
745			dumpsys();
746
747			if (PANIC_REBOOT_WAIT_TIME != 0) {
748				if (PANIC_REBOOT_WAIT_TIME != -1) {
749					int loop;
750					printf("Automatic reboot in %d seconds - press a key on the console to abort\n",
751						PANIC_REBOOT_WAIT_TIME);
752					for (loop = PANIC_REBOOT_WAIT_TIME; loop > 0; --loop) {
753						DELAY(1000 * 1000); /* one second */
754						if (sgetc(1)) /* Did user type a key? */
755							break;
756					}
757					if (!loop)
758						goto die;
759				}
760			} else { /* zero time specified - reboot NOW */
761				goto die;
762			}
763			printf("--> Press a key on the console to reboot <--\n");
764			cngetc();
765		}
766	}
767#ifdef lint
768	dummy = 0; dummy = dummy;
769	printf("howto %d, devtype %d\n", arghowto, devtype);
770#endif
771die:
772	printf("Rebooting...\n");
773	DELAY(1000000);	/* wait 1 sec for printf's to complete and be read */
774	cpu_reset();
775	for(;;) ;
776	/* NOTREACHED */
777}
778
779unsigned long	dumpmag = 0x8fca0101UL;	/* magic number for savecore */
780int		dumpsize = 0;		/* also for savecore */
781/*
782 * Doadump comes here after turning off memory management and
783 * getting on the dump stack, either when called above, or by
784 * the auto-restart code.
785 */
786void
787dumpsys()
788{
789
790	if (dumpdev == NODEV)
791		return;
792	if ((minor(dumpdev)&07) != 1)
793		return;
794	dumpsize = Maxmem;
795	printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo);
796	printf("dump ");
797	switch ((*bdevsw[major(dumpdev)].d_dump)(dumpdev)) {
798
799	case ENXIO:
800		printf("device bad\n");
801		break;
802
803	case EFAULT:
804		printf("device not ready\n");
805		break;
806
807	case EINVAL:
808		printf("area improper\n");
809		break;
810
811	case EIO:
812		printf("i/o error\n");
813		break;
814
815	case EINTR:
816		printf("aborted from console\n");
817		break;
818
819	default:
820		printf("succeeded\n");
821		break;
822	}
823}
824
825#ifdef HZ
826/*
827 * If HZ is defined we use this code, otherwise the code in
828 * /sys/i386/i386/microtime.s is used.  The othercode only works
829 * for HZ=100.
830 */
831microtime(tvp)
832	register struct timeval *tvp;
833{
834	int s = splhigh();
835
836	*tvp = time;
837	tvp->tv_usec += tick;
838	while (tvp->tv_usec > 1000000) {
839		tvp->tv_sec++;
840		tvp->tv_usec -= 1000000;
841	}
842	splx(s);
843}
844#endif /* HZ */
845
846static void
847initcpu()
848{
849}
850
851/*
852 * Clear registers on exec
853 */
854void
855setregs(p, entry, stack)
856	struct proc *p;
857	u_long entry;
858	u_long stack;
859{
860	p->p_md.md_regs[tEBP] = 0;	/* bottom of the fp chain */
861	p->p_md.md_regs[tEIP] = entry;
862	p->p_md.md_regs[tESP] = stack;
863	p->p_md.md_regs[tSS] = _udatasel;
864	p->p_md.md_regs[tDS] = _udatasel;
865	p->p_md.md_regs[tES] = _udatasel;
866	p->p_md.md_regs[tCS] = _ucodesel;
867
868	p->p_addr->u_pcb.pcb_flags = 0;	/* no fp at all */
869	load_cr0(rcr0() | CR0_TS);	/* start emulating */
870#if	NNPX > 0
871	npxinit(__INITIAL_NPXCW__);
872#endif	/* NNPX > 0 */
873}
874
875/*
876 * machine dependent system variables.
877 */
878int
879cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
880	int *name;
881	u_int namelen;
882	void *oldp;
883	size_t *oldlenp;
884	void *newp;
885	size_t newlen;
886	struct proc *p;
887{
888
889	/* all sysctl names at this level are terminal */
890	if (namelen != 1)
891		return (ENOTDIR);               /* overloaded */
892
893	switch (name[0]) {
894	case CPU_CONSDEV:
895		return (sysctl_rdstruct(oldp, oldlenp, newp, &cn_tty->t_dev,
896		   sizeof cn_tty->t_dev));
897	default:
898		return (EOPNOTSUPP);
899	}
900	/* NOTREACHED */
901}
902
903/*
904 * Initialize 386 and configure to run kernel
905 */
906
907/*
908 * Initialize segments & interrupt table
909 */
910
911union descriptor gdt[NGDT];
912union descriptor ldt[NLDT];		/* local descriptor table */
913struct gate_descriptor idt[NIDT];	/* interrupt descriptor table */
914
915int _default_ldt, currentldt;
916
917struct	i386tss	tss, panic_tss;
918
919extern  struct user *proc0paddr;
920
921/* software prototypes -- in more palatable form */
922struct soft_segment_descriptor gdt_segs[] = {
923	/* Null Descriptor */
924{	0x0,			/* segment base address  */
925	0x0,			/* length */
926	0,			/* segment type */
927	0,			/* segment descriptor priority level */
928	0,			/* segment descriptor present */
929	0, 0,
930	0,			/* default 32 vs 16 bit size */
931	0  			/* limit granularity (byte/page units)*/ },
932	/* Code Descriptor for kernel */
933{	0x0,			/* segment base address  */
934	0xfffff,		/* length - all address space */
935	SDT_MEMERA,		/* segment type */
936	0,			/* segment descriptor priority level */
937	1,			/* segment descriptor present */
938	0, 0,
939	1,			/* default 32 vs 16 bit size */
940	1  			/* limit granularity (byte/page units)*/ },
941	/* Data Descriptor for kernel */
942{	0x0,			/* segment base address  */
943	0xfffff,		/* length - all address space */
944	SDT_MEMRWA,		/* segment type */
945	0,			/* segment descriptor priority level */
946	1,			/* segment descriptor present */
947	0, 0,
948	1,			/* default 32 vs 16 bit size */
949	1  			/* limit granularity (byte/page units)*/ },
950	/* LDT Descriptor */
951{	(int) ldt,			/* segment base address  */
952	sizeof(ldt)-1,		/* length - all address space */
953	SDT_SYSLDT,		/* segment type */
954	0,			/* segment descriptor priority level */
955	1,			/* segment descriptor present */
956	0, 0,
957	0,			/* unused - default 32 vs 16 bit size */
958	0  			/* limit granularity (byte/page units)*/ },
959	/* Null Descriptor - Placeholder */
960{	0x0,			/* segment base address  */
961	0x0,			/* length - all address space */
962	0,			/* segment type */
963	0,			/* segment descriptor priority level */
964	0,			/* segment descriptor present */
965	0, 0,
966	0,			/* default 32 vs 16 bit size */
967	0  			/* limit granularity (byte/page units)*/ },
968	/* Panic Tss Descriptor */
969{	(int) &panic_tss,		/* segment base address  */
970	sizeof(tss)-1,		/* length - all address space */
971	SDT_SYS386TSS,		/* segment type */
972	0,			/* segment descriptor priority level */
973	1,			/* segment descriptor present */
974	0, 0,
975	0,			/* unused - default 32 vs 16 bit size */
976	0  			/* limit granularity (byte/page units)*/ },
977	/* Proc 0 Tss Descriptor */
978{	(int) kstack,			/* segment base address  */
979	sizeof(tss)-1,		/* length - all address space */
980	SDT_SYS386TSS,		/* segment type */
981	0,			/* segment descriptor priority level */
982	1,			/* segment descriptor present */
983	0, 0,
984	0,			/* unused - default 32 vs 16 bit size */
985	0  			/* limit granularity (byte/page units)*/ },
986	/* User LDT Descriptor per process */
987{	(int) ldt,			/* segment base address  */
988	(512 * sizeof(union descriptor)-1),		/* length */
989	SDT_SYSLDT,		/* segment type */
990	0,			/* segment descriptor priority level */
991	1,			/* segment descriptor present */
992	0, 0,
993	0,			/* unused - default 32 vs 16 bit size */
994	0  			/* limit granularity (byte/page units)*/ },
995};
996
997struct soft_segment_descriptor ldt_segs[] = {
998	/* Null Descriptor - overwritten by call gate */
999{	0x0,			/* segment base address  */
1000	0x0,			/* length - all address space */
1001	0,			/* segment type */
1002	0,			/* segment descriptor priority level */
1003	0,			/* segment descriptor present */
1004	0, 0,
1005	0,			/* default 32 vs 16 bit size */
1006	0  			/* limit granularity (byte/page units)*/ },
1007	/* Null Descriptor - overwritten by call gate */
1008{	0x0,			/* segment base address  */
1009	0x0,			/* length - all address space */
1010	0,			/* segment type */
1011	0,			/* segment descriptor priority level */
1012	0,			/* segment descriptor present */
1013	0, 0,
1014	0,			/* default 32 vs 16 bit size */
1015	0  			/* limit granularity (byte/page units)*/ },
1016	/* Null Descriptor - overwritten by call gate */
1017{	0x0,			/* segment base address  */
1018	0x0,			/* length - all address space */
1019	0,			/* segment type */
1020	0,			/* segment descriptor priority level */
1021	0,			/* segment descriptor present */
1022	0, 0,
1023	0,			/* default 32 vs 16 bit size */
1024	0  			/* limit granularity (byte/page units)*/ },
1025	/* Code Descriptor for user */
1026{	0x0,			/* segment base address  */
1027	0xfffff,		/* length - all address space */
1028	SDT_MEMERA,		/* segment type */
1029	SEL_UPL,		/* segment descriptor priority level */
1030	1,			/* segment descriptor present */
1031	0, 0,
1032	1,			/* default 32 vs 16 bit size */
1033	1  			/* limit granularity (byte/page units)*/ },
1034	/* Data Descriptor for user */
1035{	0x0,			/* segment base address  */
1036	0xfffff,		/* length - all address space */
1037	SDT_MEMRWA,		/* segment type */
1038	SEL_UPL,		/* segment descriptor priority level */
1039	1,			/* segment descriptor present */
1040	0, 0,
1041	1,			/* default 32 vs 16 bit size */
1042	1  			/* limit granularity (byte/page units)*/ } };
1043
1044void
1045setidt(idx, func, typ, dpl)
1046	int idx;
1047	void (*func)();
1048	int typ;
1049	int dpl;
1050{
1051	struct gate_descriptor *ip = idt + idx;
1052
1053	ip->gd_looffset = (int)func;
1054	ip->gd_selector = 8;
1055	ip->gd_stkcpy = 0;
1056	ip->gd_xx = 0;
1057	ip->gd_type = typ;
1058	ip->gd_dpl = dpl;
1059	ip->gd_p = 1;
1060	ip->gd_hioffset = ((int)func)>>16 ;
1061}
1062
1063#define	IDTVEC(name)	__CONCAT(X,name)
1064typedef void idtvec_t();
1065
1066extern idtvec_t
1067	IDTVEC(div), IDTVEC(dbg), IDTVEC(nmi), IDTVEC(bpt), IDTVEC(ofl),
1068	IDTVEC(bnd), IDTVEC(ill), IDTVEC(dna), IDTVEC(dble), IDTVEC(fpusegm),
1069	IDTVEC(tss), IDTVEC(missing), IDTVEC(stk), IDTVEC(prot),
1070	IDTVEC(page), IDTVEC(rsvd), IDTVEC(fpu), IDTVEC(rsvd0),
1071	IDTVEC(rsvd1), IDTVEC(rsvd2), IDTVEC(rsvd3), IDTVEC(rsvd4),
1072	IDTVEC(rsvd5), IDTVEC(rsvd6), IDTVEC(rsvd7), IDTVEC(rsvd8),
1073	IDTVEC(rsvd9), IDTVEC(rsvd10), IDTVEC(rsvd11), IDTVEC(rsvd12),
1074	IDTVEC(rsvd13), IDTVEC(rsvd14), IDTVEC(syscall);
1075
1076int _gsel_tss;
1077
1078void
1079init386(first)
1080	int first;
1081{
1082	extern lgdt(), lidt(), lldt(), etext;
1083	int x, *pi;
1084	unsigned biosbasemem, biosextmem;
1085	struct gate_descriptor *gdp;
1086	extern int sigcode,szsigcode;
1087	/* table descriptors - used to load tables by microp */
1088	struct region_descriptor r_gdt, r_idt;
1089	int	pagesinbase, pagesinext;
1090	int	target_page;
1091	extern struct pte *CMAP1;
1092	extern caddr_t CADDR1;
1093
1094	proc0.p_addr = proc0paddr;
1095
1096	/*
1097	 * Initialize the console before we print anything out.
1098	 */
1099
1100	cninit ();
1101
1102	/*
1103	 * make gdt memory segments, the code segment goes up to end of the
1104	 * page with etext in it, the data segment goes to the end of
1105	 * the address space
1106	 */
1107	gdt_segs[GCODE_SEL].ssd_limit = i386_btop(0) - 1 /* i386_btop(i386_round_page(&etext)) - 1 */;
1108	gdt_segs[GDATA_SEL].ssd_limit = i386_btop(0) - 1;
1109	for (x=0; x < NGDT; x++) ssdtosd(gdt_segs+x, gdt+x);
1110
1111	/* make ldt memory segments */
1112	/*
1113	 * The data segment limit must not cover the user area because we
1114	 * don't want the user area to be writable in copyout() etc. (page
1115	 * level protection is lost in kernel mode on 386's).  Also, we
1116	 * don't want the user area to be writable directly (page level
1117	 * protection of the user area is not available on 486's with
1118	 * CR0_WP set, because there is no user-read/kernel-write mode).
1119	 *
1120	 * XXX - VM_MAXUSER_ADDRESS is an end address, not a max.  And it
1121	 * should be spelled ...MAX_USER...
1122	 */
1123#define VM_END_USER_RW_ADDRESS	VM_MAXUSER_ADDRESS
1124	/*
1125	 * The code segment limit has to cover the user area until we move
1126	 * the signal trampoline out of the user area.  This is safe because
1127	 * the code segment cannot be written to directly.
1128	 */
1129#define VM_END_USER_R_ADDRESS	(VM_END_USER_RW_ADDRESS + UPAGES * NBPG)
1130	ldt_segs[LUCODE_SEL].ssd_limit = i386_btop(VM_END_USER_R_ADDRESS) - 1;
1131	ldt_segs[LUDATA_SEL].ssd_limit = i386_btop(VM_END_USER_RW_ADDRESS) - 1;
1132	/* Note. eventually want private ldts per process */
1133	for (x=0; x < 5; x++) ssdtosd(ldt_segs+x, ldt+x);
1134
1135	/* exceptions */
1136	setidt(0, &IDTVEC(div),  SDT_SYS386TGT, SEL_KPL);
1137	setidt(1, &IDTVEC(dbg),  SDT_SYS386TGT, SEL_KPL);
1138	setidt(2, &IDTVEC(nmi),  SDT_SYS386TGT, SEL_KPL);
1139 	setidt(3, &IDTVEC(bpt),  SDT_SYS386TGT, SEL_UPL);
1140	setidt(4, &IDTVEC(ofl),  SDT_SYS386TGT, SEL_UPL);
1141	setidt(5, &IDTVEC(bnd),  SDT_SYS386TGT, SEL_KPL);
1142	setidt(6, &IDTVEC(ill),  SDT_SYS386TGT, SEL_KPL);
1143	setidt(7, &IDTVEC(dna),  SDT_SYS386TGT, SEL_KPL);
1144	setidt(8, &IDTVEC(dble),  SDT_SYS386TGT, SEL_KPL);
1145	setidt(9, &IDTVEC(fpusegm),  SDT_SYS386TGT, SEL_KPL);
1146	setidt(10, &IDTVEC(tss),  SDT_SYS386TGT, SEL_KPL);
1147	setidt(11, &IDTVEC(missing),  SDT_SYS386TGT, SEL_KPL);
1148	setidt(12, &IDTVEC(stk),  SDT_SYS386TGT, SEL_KPL);
1149	setidt(13, &IDTVEC(prot),  SDT_SYS386TGT, SEL_KPL);
1150	setidt(14, &IDTVEC(page),  SDT_SYS386TGT, SEL_KPL);
1151	setidt(15, &IDTVEC(rsvd),  SDT_SYS386TGT, SEL_KPL);
1152	setidt(16, &IDTVEC(fpu),  SDT_SYS386TGT, SEL_KPL);
1153	setidt(17, &IDTVEC(rsvd0),  SDT_SYS386TGT, SEL_KPL);
1154	setidt(18, &IDTVEC(rsvd1),  SDT_SYS386TGT, SEL_KPL);
1155	setidt(19, &IDTVEC(rsvd2),  SDT_SYS386TGT, SEL_KPL);
1156	setidt(20, &IDTVEC(rsvd3),  SDT_SYS386TGT, SEL_KPL);
1157	setidt(21, &IDTVEC(rsvd4),  SDT_SYS386TGT, SEL_KPL);
1158	setidt(22, &IDTVEC(rsvd5),  SDT_SYS386TGT, SEL_KPL);
1159	setidt(23, &IDTVEC(rsvd6),  SDT_SYS386TGT, SEL_KPL);
1160	setidt(24, &IDTVEC(rsvd7),  SDT_SYS386TGT, SEL_KPL);
1161	setidt(25, &IDTVEC(rsvd8),  SDT_SYS386TGT, SEL_KPL);
1162	setidt(26, &IDTVEC(rsvd9),  SDT_SYS386TGT, SEL_KPL);
1163	setidt(27, &IDTVEC(rsvd10),  SDT_SYS386TGT, SEL_KPL);
1164	setidt(28, &IDTVEC(rsvd11),  SDT_SYS386TGT, SEL_KPL);
1165	setidt(29, &IDTVEC(rsvd12),  SDT_SYS386TGT, SEL_KPL);
1166	setidt(30, &IDTVEC(rsvd13),  SDT_SYS386TGT, SEL_KPL);
1167	setidt(31, &IDTVEC(rsvd14),  SDT_SYS386TGT, SEL_KPL);
1168
1169#include	"isa.h"
1170#if	NISA >0
1171	isa_defaultirq();
1172#endif
1173
1174	r_gdt.rd_limit = sizeof(gdt) - 1;
1175	r_gdt.rd_base =  (int) gdt;
1176	lgdt(&r_gdt);
1177
1178	r_idt.rd_limit = sizeof(idt) - 1;
1179	r_idt.rd_base = (int) idt;
1180	lidt(&r_idt);
1181
1182	_default_ldt = GSEL(GLDT_SEL, SEL_KPL);
1183	lldt(_default_ldt);
1184	currentldt = _default_ldt;
1185
1186#ifdef DDB
1187	kdb_init();
1188	if (boothowto & RB_KDB)
1189		Debugger("Boot flags requested debugger");
1190#endif
1191
1192	/* Use BIOS values stored in RTC CMOS RAM, since probing
1193	 * breaks certain 386 AT relics.
1194	 */
1195	biosbasemem = rtcin(RTC_BASELO)+ (rtcin(RTC_BASEHI)<<8);
1196	biosextmem = rtcin(RTC_EXTLO)+ (rtcin(RTC_EXTHI)<<8);
1197
1198	/*
1199	 * If BIOS tells us that it has more than 640k in the basemem,
1200	 *	don't believe it - set it to 640k.
1201	 */
1202	if (biosbasemem > 640)
1203		biosbasemem = 640;
1204
1205	/*
1206	 * Some 386 machines might give us a bogus number for extended
1207	 *	mem. If this happens, stop now.
1208	 */
1209#ifndef LARGEMEM
1210	if (biosextmem > 65536) {
1211		panic("extended memory beyond limit of 64MB");
1212		/* NOTREACHED */
1213	}
1214#endif
1215
1216	pagesinbase = biosbasemem * 1024 / NBPG;
1217	pagesinext = biosextmem * 1024 / NBPG;
1218
1219	/*
1220	 * Special hack for chipsets that still remap the 384k hole when
1221	 *	there's 16MB of memory - this really confuses people that
1222	 *	are trying to use bus mastering ISA controllers with the
1223	 *	"16MB limit"; they only have 16MB, but the remapping puts
1224	 *	them beyond the limit.
1225	 * XXX - this should be removed when bounce buffers are
1226	 *	implemented.
1227	 */
1228	/*
1229	 * If extended memory is between 15-16MB (16-17MB phys address range),
1230	 *	chop it to 15MB.
1231	 */
1232	if ((pagesinext > 3840) && (pagesinext < 4096))
1233		pagesinext = 3840;
1234
1235	/*
1236	 * Maxmem isn't the "maximum memory", it's the highest page of
1237	 * of the physical address space. It should be "Maxphyspage".
1238	 */
1239	Maxmem = pagesinext + 0x100000/PAGE_SIZE;
1240
1241#ifdef MAXMEM
1242	if (MAXMEM/4 < Maxmem)
1243		Maxmem = MAXMEM/4;
1244#endif
1245	/*
1246	 * Calculate number of physical pages, but account for Maxmem
1247	 *	limitation above.
1248	 */
1249	physmem = pagesinbase +
1250	    (min(pagesinext + 0x100000/PAGE_SIZE, Maxmem) - 0x100000/PAGE_SIZE);
1251
1252	/* call pmap initialization to make new kernel address space */
1253	pmap_bootstrap (first, 0);
1254
1255	/*
1256	 * Do simple memory test over range of extended memory that BIOS
1257	 *	indicates exists. Adjust Maxmem to the highest page of
1258	 *	good memory.
1259	 */
1260	printf("Testing memory (%dMB)...", ptoa(Maxmem)/1024/1024);
1261
1262	for (target_page = Maxmem - 1; target_page >= atop(first); target_page--) {
1263
1264		/*
1265		 * map page into kernel: valid, read/write, non-cacheable
1266		 */
1267		*(int *)CMAP1 = PG_V | PG_KW | PG_N | ptoa(target_page);
1268		pmap_update();
1269
1270		/*
1271		 * Test for alternating 1's and 0's
1272		 */
1273		filli(0xaaaaaaaa, CADDR1, PAGE_SIZE/sizeof(int));
1274		if (test_page((int *)CADDR1, 0xaaaaaaaa)) {
1275			Maxmem = target_page;
1276			badpages++;
1277			continue;
1278		}
1279		/*
1280		 * Test for alternating 0's and 1's
1281		 */
1282		filli(0x55555555, CADDR1, PAGE_SIZE/sizeof(int));
1283		if (test_page((int *)CADDR1, 0x55555555)) {
1284			Maxmem = target_page;
1285			badpages++;
1286			continue;
1287		}
1288		/*
1289		 * Test for all 1's
1290		 */
1291		filli(0xffffffff, CADDR1, PAGE_SIZE/sizeof(int));
1292		if (test_page((int *)CADDR1, 0xffffffff)) {
1293			Maxmem = target_page;
1294			badpages++;
1295			continue;
1296		}
1297		/*
1298		 * Test zeroing of page
1299		 */
1300		bzero(CADDR1, PAGE_SIZE);
1301		if (test_page((int *)CADDR1, 0)) {
1302			/*
1303			 * test of page failed
1304			 */
1305			Maxmem = target_page;
1306			badpages++;
1307			continue;
1308		}
1309	}
1310	printf("done.\n");
1311
1312	*(int *)CMAP1 = 0;
1313	pmap_update();
1314
1315	avail_end = (Maxmem << PAGE_SHIFT)
1316		    - i386_round_page(sizeof(struct msgbuf));
1317
1318	/*
1319	 * Initialize pointers to the two chunks of memory; for use
1320	 *	later in vm_page_startup.
1321	 */
1322	/* avail_start is initialized in pmap_bootstrap */
1323	x = 0;
1324	if (pagesinbase > 1) {
1325		phys_avail[x++] = NBPG;		/* skip first page of memory */
1326		phys_avail[x++] = pagesinbase * NBPG;	/* memory up to the ISA hole */
1327	}
1328	phys_avail[x++] = avail_start;	/* memory up to the end */
1329	phys_avail[x++] = avail_end;
1330	phys_avail[x++] = 0;		/* no more chunks */
1331	phys_avail[x++] = 0;
1332
1333	/* now running on new page tables, configured,and u/iom is accessible */
1334
1335	/* make a initial tss so microp can get interrupt stack on syscall! */
1336	proc0.p_addr->u_pcb.pcb_tss.tss_esp0 = (int) kstack + UPAGES*NBPG;
1337	proc0.p_addr->u_pcb.pcb_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL) ;
1338	_gsel_tss = GSEL(GPROC0_SEL, SEL_KPL);
1339
1340	((struct i386tss *)gdt_segs[GPROC0_SEL].ssd_base)->tss_ioopt =
1341		(sizeof(tss))<<16;
1342
1343	ltr(_gsel_tss);
1344
1345	/* make a call gate to reenter kernel with */
1346	gdp = &ldt[LSYS5CALLS_SEL].gd;
1347
1348	x = (int) &IDTVEC(syscall);
1349	gdp->gd_looffset = x++;
1350	gdp->gd_selector = GSEL(GCODE_SEL,SEL_KPL);
1351	gdp->gd_stkcpy = 1;
1352	gdp->gd_type = SDT_SYS386CGT;
1353	gdp->gd_dpl = SEL_UPL;
1354	gdp->gd_p = 1;
1355	gdp->gd_hioffset = ((int) &IDTVEC(syscall)) >>16;
1356
1357	/* transfer to user mode */
1358
1359	_ucodesel = LSEL(LUCODE_SEL, SEL_UPL);
1360	_udatasel = LSEL(LUDATA_SEL, SEL_UPL);
1361
1362	/* setup proc 0's pcb */
1363	bcopy(&sigcode, proc0.p_addr->u_pcb.pcb_sigc, szsigcode);
1364	proc0.p_addr->u_pcb.pcb_flags = 0;
1365	proc0.p_addr->u_pcb.pcb_ptd = IdlePTD;
1366}
1367
1368int
1369test_page(address, pattern)
1370	int *address;
1371	int pattern;
1372{
1373	int *x;
1374
1375	for (x = address; x < (int *)((char *)address + PAGE_SIZE); x++) {
1376		if (*x != pattern)
1377			return (1);
1378	}
1379	return(0);
1380}
1381
1382/*
1383 * The registers are in the frame; the frame is in the user area of
1384 * the process in question; when the process is active, the registers
1385 * are in "the kernel stack"; when it's not, they're still there, but
1386 * things get flipped around.  So, since p->p_md.md_regs is the whole address
1387 * of the register set, take its offset from the kernel stack, and
1388 * index into the user block.  Don't you just *love* virtual memory?
1389 * (I'm starting to think seymour is right...)
1390 */
1391
1392int
1393ptrace_set_pc (struct proc *p, unsigned int addr) {
1394	void *regs = (char*)p->p_addr +
1395		((char*) p->p_md.md_regs - (char*) kstack);
1396
1397	((struct trapframe *)regs)->tf_eip = addr;
1398	return 0;
1399}
1400
1401int
1402ptrace_single_step (struct proc *p) {
1403	void *regs = (char*)p->p_addr +
1404		((char*) p->p_md.md_regs - (char*) kstack);
1405
1406	((struct trapframe *)regs)->tf_eflags |= PSL_T;
1407	return 0;
1408}
1409
1410/*
1411 * Copy the registers to user-space.
1412 */
1413
1414int
1415ptrace_getregs (struct proc *p, unsigned int *addr) {
1416	int error;
1417	struct reg regs = {0};
1418
1419	if (error = fill_regs (p, &regs))
1420		return error;
1421
1422	return copyout (&regs, addr, sizeof (regs));
1423}
1424
1425int
1426ptrace_setregs (struct proc *p, unsigned int *addr) {
1427	int error;
1428	struct reg regs = {0};
1429
1430	if (error = copyin (addr, &regs, sizeof(regs)))
1431		return error;
1432
1433	return set_regs (p, &regs);
1434}
1435
1436int
1437fill_regs(struct proc *p, struct reg *regs) {
1438	int error;
1439	struct trapframe *tp;
1440	void *ptr = (char*)p->p_addr +
1441		((char*) p->p_md.md_regs - (char*) kstack);
1442
1443	tp = ptr;
1444	regs->r_es = tp->tf_es;
1445	regs->r_ds = tp->tf_ds;
1446	regs->r_edi = tp->tf_edi;
1447	regs->r_esi = tp->tf_esi;
1448	regs->r_ebp = tp->tf_ebp;
1449	regs->r_ebx = tp->tf_ebx;
1450	regs->r_edx = tp->tf_edx;
1451	regs->r_ecx = tp->tf_ecx;
1452	regs->r_eax = tp->tf_eax;
1453	regs->r_eip = tp->tf_eip;
1454	regs->r_cs = tp->tf_cs;
1455	regs->r_eflags = tp->tf_eflags;
1456	regs->r_esp = tp->tf_esp;
1457	regs->r_ss = tp->tf_ss;
1458	return 0;
1459}
1460
1461int
1462set_regs (struct proc *p, struct reg *regs) {
1463	int error;
1464	struct trapframe *tp;
1465	void *ptr = (char*)p->p_addr +
1466		((char*) p->p_md.md_regs - (char*) kstack);
1467
1468	tp = ptr;
1469	tp->tf_es = regs->r_es;
1470	tp->tf_ds = regs->r_ds;
1471	tp->tf_edi = regs->r_edi;
1472	tp->tf_esi = regs->r_esi;
1473	tp->tf_ebp = regs->r_ebp;
1474	tp->tf_ebx = regs->r_ebx;
1475	tp->tf_edx = regs->r_edx;
1476	tp->tf_ecx = regs->r_ecx;
1477	tp->tf_eax = regs->r_eax;
1478	tp->tf_eip = regs->r_eip;
1479	tp->tf_cs = regs->r_cs;
1480	tp->tf_eflags = regs->r_eflags;
1481	tp->tf_esp = regs->r_esp;
1482	tp->tf_ss = regs->r_ss;
1483	return 0;
1484}
1485
1486#ifndef DDB
1487void
1488Debugger(const char *msg)
1489{
1490	printf("Debugger(\"%s\") called.\n", msg);
1491}
1492#endif /* no DDB */
1493
1494#include <sys/disklabel.h>
1495#define b_cylin	b_resid
1496#define dkpart(dev)              (minor(dev) & 7)
1497/*
1498 * Determine the size of the transfer, and make sure it is
1499 * within the boundaries of the partition. Adjust transfer
1500 * if needed, and signal errors or early completion.
1501 */
1502int
1503bounds_check_with_label(struct buf *bp, struct disklabel *lp, int wlabel)
1504{
1505        struct partition *p = lp->d_partitions + dkpart(bp->b_dev);
1506        int labelsect = lp->d_partitions[0].p_offset;
1507        int maxsz = p->p_size,
1508                sz = (bp->b_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT;
1509
1510        /* overwriting disk label ? */
1511        /* XXX should also protect bootstrap in first 8K */
1512        if (bp->b_blkno + p->p_offset <= LABELSECTOR + labelsect &&
1513#if LABELSECTOR != 0
1514            bp->b_blkno + p->p_offset + sz > LABELSECTOR + labelsect &&
1515#endif
1516            (bp->b_flags & B_READ) == 0 && wlabel == 0) {
1517                bp->b_error = EROFS;
1518                goto bad;
1519        }
1520
1521#if     defined(DOSBBSECTOR) && defined(notyet)
1522        /* overwriting master boot record? */
1523        if (bp->b_blkno + p->p_offset <= DOSBBSECTOR &&
1524            (bp->b_flags & B_READ) == 0 && wlabel == 0) {
1525                bp->b_error = EROFS;
1526                goto bad;
1527        }
1528#endif
1529
1530        /* beyond partition? */
1531        if (bp->b_blkno < 0 || bp->b_blkno + sz > maxsz) {
1532                /* if exactly at end of disk, return an EOF */
1533                if (bp->b_blkno == maxsz) {
1534                        bp->b_resid = bp->b_bcount;
1535                        return(0);
1536                }
1537                /* or truncate if part of it fits */
1538                sz = maxsz - bp->b_blkno;
1539                if (sz <= 0) {
1540                        bp->b_error = EINVAL;
1541                        goto bad;
1542                }
1543                bp->b_bcount = sz << DEV_BSHIFT;
1544        }
1545
1546        /* calculate cylinder for disksort to order transfers with */
1547        bp->b_pblkno = bp->b_blkno + p->p_offset;
1548        bp->b_cylin = bp->b_pblkno / lp->d_secpercyl;
1549        return(1);
1550
1551bad:
1552        bp->b_flags |= B_ERROR;
1553        return(-1);
1554}
1555
1556