machdep.c revision 2426
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.58 1994/08/31 06:17:31 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("Pentium") + 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};
358
359static void
360identifycpu()
361{
362	extern u_long cpu_id;
363	extern char cpu_vendor[];
364	printf("CPU: ");
365	if (cpu >= 0
366	    && cpu < (sizeof i386_cpus/sizeof(struct cpu_nameclass))) {
367		printf("%s", i386_cpus[cpu].cpu_name);
368		cpu_class = i386_cpus[cpu].cpu_class;
369		strncpy(cpu_model, i386_cpus[cpu].cpu_name, sizeof cpu_model);
370	} else {
371		printf("unknown cpu type %d\n", cpu);
372		panic("startup: bad cpu id");
373	}
374	printf(" (");
375	switch(cpu_class) {
376	case CPUCLASS_286:
377		printf("286");
378		break;
379	case CPUCLASS_386:
380		printf("386");
381		break;
382	case CPUCLASS_486:
383		printf("486");
384		break;
385	case CPUCLASS_586:
386		printf("Pentium");
387		break;
388	default:
389		printf("unknown");	/* will panic below... */
390	}
391	printf("-class CPU)");
392#ifdef I586_CPU
393	if(cpu_class == CPUCLASS_586) {
394		extern void calibrate_cyclecounter();
395		extern int pentium_mhz;
396		calibrate_cyclecounter();
397		printf(" %d MHz", pentium_mhz);
398	}
399#endif
400	if(cpu_id)
401		printf("  Id = 0x%x",cpu_id);
402	if(*cpu_vendor)
403		printf("  Origin = \"%s\"",cpu_vendor);
404	printf("\n");	/* cpu speed would be nice, but how? */
405
406	/*
407	 * Now that we have told the user what they have,
408	 * let them know if that machine type isn't configured.
409	 */
410	switch (cpu_class) {
411	case CPUCLASS_286:	/* a 286 should not make it this far, anyway */
412#if !defined(I386_CPU) && !defined(I486_CPU) && !defined(I586_CPU)
413#error This kernel is not configured for one of the supported CPUs
414#endif
415#if !defined(I386_CPU)
416	case CPUCLASS_386:
417#endif
418#if !defined(I486_CPU)
419	case CPUCLASS_486:
420#endif
421#if !defined(I586_CPU)
422	case CPUCLASS_586:
423#endif
424		panic("CPU class not configured");
425	default:
426		break;
427	}
428}
429
430#ifdef PGINPROF
431/*
432 * Return the difference (in microseconds)
433 * between the  current time and a previous
434 * time as represented  by the arguments.
435 * If there is a pending clock interrupt
436 * which has not been serviced due to high
437 * ipl, return error code.
438 */
439/*ARGSUSED*/
440vmtime(otime, olbolt, oicr)
441	register int otime, olbolt, oicr;
442{
443
444	return (((time.tv_sec-otime)*60 + lbolt-olbolt)*16667);
445}
446#endif
447
448extern int kstack[];
449
450/*
451 * Send an interrupt to process.
452 *
453 * Stack is set up to allow sigcode stored
454 * in u. to call routine, followed by kcall
455 * to sigreturn routine below.  After sigreturn
456 * resets the signal mask, the stack, and the
457 * frame pointer, it returns to the user
458 * specified pc, psl.
459 */
460void
461sendsig(catcher, sig, mask, code)
462	sig_t catcher;
463	int sig, mask;
464	unsigned code;
465{
466	register struct proc *p = curproc;
467	register int *regs;
468	register struct sigframe *fp;
469	struct sigacts *psp = p->p_sigacts;
470	int oonstack, frmtrap;
471
472	regs = p->p_md.md_regs;
473        oonstack = psp->ps_sigstk.ss_flags & SA_ONSTACK;
474	/*
475	 * Allocate and validate space for the signal handler
476	 * context. Note that if the stack is in P0 space, the
477	 * call to grow() is a nop, and the useracc() check
478	 * will fail if the process has not already allocated
479	 * the space with a `brk'.
480	 */
481        if ((psp->ps_flags & SAS_ALTSTACK) &&
482	    (psp->ps_sigstk.ss_flags & SA_ONSTACK) == 0 &&
483	    (psp->ps_sigonstack & sigmask(sig))) {
484		fp = (struct sigframe *)(psp->ps_sigstk.ss_base +
485		    psp->ps_sigstk.ss_size - sizeof(struct sigframe));
486		psp->ps_sigstk.ss_flags |= SA_ONSTACK;
487	} else {
488		fp = (struct sigframe *)(regs[tESP]
489			- sizeof(struct sigframe));
490	}
491
492	/*
493	 * grow() will return FALSE if the fp will not fit inside the stack
494	 *	and the stack can not be grown. useracc will return FALSE
495	 *	if access is denied.
496	 */
497	if ((grow(p, (int)fp) == FALSE) ||
498	    (useracc((caddr_t)fp, sizeof (struct sigframe), B_WRITE) == FALSE)) {
499		/*
500		 * Process has trashed its stack; give it an illegal
501		 * instruction to halt it in its tracks.
502		 */
503		SIGACTION(p, SIGILL) = SIG_DFL;
504		sig = sigmask(SIGILL);
505		p->p_sigignore &= ~sig;
506		p->p_sigcatch &= ~sig;
507		p->p_sigmask &= ~sig;
508		psignal(p, SIGILL);
509		return;
510	}
511
512	/*
513	 * Build the argument list for the signal handler.
514	 */
515	if (p->p_sysent->sv_sigtbl) {
516		if (sig < p->p_sysent->sv_sigsize)
517			sig = p->p_sysent->sv_sigtbl[sig];
518		else
519			sig = p->p_sysent->sv_sigsize + 1;
520	}
521	fp->sf_signum = sig;
522	fp->sf_code = code;
523	fp->sf_scp = &fp->sf_sc;
524	fp->sf_addr = (char *) regs[tERR];
525	fp->sf_handler = catcher;
526
527	/* save scratch registers */
528	fp->sf_sc.sc_eax = regs[tEAX];
529	fp->sf_sc.sc_ebx = regs[tEBX];
530	fp->sf_sc.sc_ecx = regs[tECX];
531	fp->sf_sc.sc_edx = regs[tEDX];
532	fp->sf_sc.sc_esi = regs[tESI];
533	fp->sf_sc.sc_edi = regs[tEDI];
534	fp->sf_sc.sc_cs = regs[tCS];
535	fp->sf_sc.sc_ds = regs[tDS];
536	fp->sf_sc.sc_ss = regs[tSS];
537	fp->sf_sc.sc_es = regs[tES];
538	fp->sf_sc.sc_isp = regs[tISP];
539
540	/*
541	 * Build the signal context to be used by sigreturn.
542	 */
543	fp->sf_sc.sc_onstack = oonstack;
544	fp->sf_sc.sc_mask = mask;
545	fp->sf_sc.sc_sp = regs[tESP];
546	fp->sf_sc.sc_fp = regs[tEBP];
547	fp->sf_sc.sc_pc = regs[tEIP];
548	fp->sf_sc.sc_ps = regs[tEFLAGS];
549	regs[tESP] = (int)fp;
550	regs[tEIP] = (int)((struct pcb *)kstack)->pcb_sigc;
551	regs[tEFLAGS] &= ~PSL_VM;
552	regs[tCS] = _ucodesel;
553	regs[tDS] = _udatasel;
554	regs[tES] = _udatasel;
555	regs[tSS] = _udatasel;
556}
557
558/*
559 * System call to cleanup state after a signal
560 * has been taken.  Reset signal mask and
561 * stack state from context left by sendsig (above).
562 * Return to previous pc and psl as specified by
563 * context left by sendsig. Check carefully to
564 * make sure that the user has not modified the
565 * psl to gain improper privileges or to cause
566 * a machine fault.
567 */
568struct sigreturn_args {
569	struct sigcontext *sigcntxp;
570};
571
572int
573sigreturn(p, uap, retval)
574	struct proc *p;
575	struct sigreturn_args *uap;
576	int *retval;
577{
578	register struct sigcontext *scp;
579	register struct sigframe *fp;
580	register int *regs = p->p_md.md_regs;
581	int eflags;
582
583	/*
584	 * (XXX old comment) regs[tESP] points to the return address.
585	 * The user scp pointer is above that.
586	 * The return address is faked in the signal trampoline code
587	 * for consistency.
588	 */
589	scp = uap->sigcntxp;
590	fp = (struct sigframe *)
591	     ((caddr_t)scp - offsetof(struct sigframe, sf_sc));
592
593	if (useracc((caddr_t)fp, sizeof (*fp), 0) == 0)
594		return(EINVAL);
595
596	eflags = scp->sc_ps;
597	if ((eflags & PSL_USERCLR) != 0 ||
598	    (eflags & PSL_USERSET) != PSL_USERSET ||
599	    (eflags & PSL_IOPL) < (regs[tEFLAGS] & PSL_IOPL)) {
600#ifdef DEBUG
601    		printf("sigreturn:  eflags=0x%x\n", eflags);
602#endif
603    		return(EINVAL);
604	}
605
606	/*
607	 * Sanity check the user's selectors and error if they
608	 * are suspect.
609	 */
610#define max_ldt_sel(pcb) \
611	((pcb)->pcb_ldt ? (pcb)->pcb_ldt_len : (sizeof(ldt) / sizeof(ldt[0])))
612
613#define valid_ldt_sel(sel) \
614	(ISLDT(sel) && ISPL(sel) == SEL_UPL && \
615	 IDXSEL(sel) < max_ldt_sel(&p->p_addr->u_pcb))
616
617#define null_sel(sel) \
618	(!ISLDT(sel) && IDXSEL(sel) == 0)
619
620	if ((scp->sc_cs&0xffff != _ucodesel && !valid_ldt_sel(scp->sc_cs)) ||
621	    (scp->sc_ss&0xffff != _udatasel && !valid_ldt_sel(scp->sc_ss)) ||
622	    (scp->sc_ds&0xffff != _udatasel && !valid_ldt_sel(scp->sc_ds) &&
623	     !null_sel(scp->sc_ds)) ||
624	    (scp->sc_es&0xffff != _udatasel && !valid_ldt_sel(scp->sc_es) &&
625	     !null_sel(scp->sc_es))) {
626#ifdef DEBUG
627    		printf("sigreturn:  cs=0x%x ss=0x%x ds=0x%x es=0x%x\n",
628			scp->sc_cs, scp->sc_ss, scp->sc_ds, scp->sc_es);
629#endif
630		trapsignal(p, SIGBUS, T_PROTFLT);
631		return(EINVAL);
632	}
633
634#undef max_ldt_sel
635#undef valid_ldt_sel
636#undef null_sel
637
638	/* restore scratch registers */
639	regs[tEAX] = scp->sc_eax;
640	regs[tEBX] = scp->sc_ebx;
641	regs[tECX] = scp->sc_ecx;
642	regs[tEDX] = scp->sc_edx;
643	regs[tESI] = scp->sc_esi;
644	regs[tEDI] = scp->sc_edi;
645	regs[tCS] = scp->sc_cs;
646	regs[tDS] = scp->sc_ds;
647	regs[tES] = scp->sc_es;
648	regs[tSS] = scp->sc_ss;
649	regs[tISP] = scp->sc_isp;
650
651	if (useracc((caddr_t)scp, sizeof (*scp), 0) == 0)
652		return(EINVAL);
653
654	if (scp->sc_onstack & 01)
655		p->p_sigacts->ps_sigstk.ss_flags |= SA_ONSTACK;
656	else
657		p->p_sigacts->ps_sigstk.ss_flags &= ~SA_ONSTACK;
658	p->p_sigmask = scp->sc_mask &~
659	    (sigmask(SIGKILL)|sigmask(SIGCONT)|sigmask(SIGSTOP));
660	regs[tEBP] = scp->sc_fp;
661	regs[tESP] = scp->sc_sp;
662	regs[tEIP] = scp->sc_pc;
663	regs[tEFLAGS] = eflags;
664	return(EJUSTRETURN);
665}
666
667/*
668 * a simple function to make the system panic (and dump a vmcore)
669 * in a predictable fashion
670 */
671void diediedie()
672{
673	panic("because you said to!");
674}
675
676int	waittime = -1;
677struct pcb dumppcb;
678
679__dead void
680boot(arghowto)
681	int arghowto;
682{
683	register long dummy;		/* r12 is reserved */
684	register int howto;		/* r11 == how to boot */
685	register int devtype;		/* r10 == major of root dev */
686	extern int cold;
687
688	if (cold) {
689		printf("hit reset please");
690		for(;;);
691	}
692	howto = arghowto;
693	if ((howto&RB_NOSYNC) == 0 && waittime < 0) {
694		register struct buf *bp;
695		int iter, nbusy;
696
697		waittime = 0;
698		(void) splnet();
699		printf("\nsyncing disks... ");
700		/*
701		 * Release inodes held by texts before update.
702		 */
703		if (panicstr == 0)
704			vnode_pager_umount(NULL);
705		sync(curproc, NULL, NULL);
706
707		for (iter = 0; iter < 20; iter++) {
708			nbusy = 0;
709			for (bp = &buf[nbuf]; --bp >= buf; )
710				if ((bp->b_flags & (B_BUSY|B_INVAL)) == B_BUSY)
711					nbusy++;
712			if (nbusy == 0)
713				break;
714			printf("%d ", nbusy);
715			DELAY(40000 * iter);
716		}
717		if (nbusy) {
718			/*
719			 * Failed to sync all blocks. Indicate this and don't
720			 * unmount filesystems (thus forcing an fsck on reboot).
721			 */
722			printf("giving up\n");
723		} else {
724			printf("done\n");
725			/*
726			 * Unmount filesystems
727			 */
728			if (panicstr == 0)
729				vfs_unmountall();
730		}
731		DELAY(100000);			/* wait for console output to finish */
732	}
733	splhigh();
734	devtype = major(rootdev);
735	if (howto&RB_HALT) {
736		printf("\n");
737		printf("The operating system has halted.\n");
738		printf("Please press any key to reboot.\n\n");
739		cngetc();
740	} else {
741		if (howto & RB_DUMP) {
742			savectx(&dumppcb, 0);
743			dumppcb.pcb_ptd = rcr3();
744			dumpsys();
745
746			if (PANIC_REBOOT_WAIT_TIME != 0) {
747				if (PANIC_REBOOT_WAIT_TIME != -1) {
748					int loop;
749					printf("Automatic reboot in %d seconds - press a key on the console to abort\n",
750						PANIC_REBOOT_WAIT_TIME);
751					for (loop = PANIC_REBOOT_WAIT_TIME; loop > 0; --loop) {
752						DELAY(1000 * 1000); /* one second */
753						if (sgetc(1)) /* Did user type a key? */
754							break;
755					}
756					if (!loop)
757						goto die;
758				}
759			} else { /* zero time specified - reboot NOW */
760				goto die;
761			}
762			printf("--> Press a key on the console to reboot <--\n");
763			cngetc();
764		}
765	}
766#ifdef lint
767	dummy = 0; dummy = dummy;
768	printf("howto %d, devtype %d\n", arghowto, devtype);
769#endif
770die:
771	printf("Rebooting...\n");
772	DELAY(1000000);	/* wait 1 sec for printf's to complete and be read */
773	cpu_reset();
774	for(;;) ;
775	/* NOTREACHED */
776}
777
778unsigned long	dumpmag = 0x8fca0101UL;	/* magic number for savecore */
779int		dumpsize = 0;		/* also for savecore */
780/*
781 * Doadump comes here after turning off memory management and
782 * getting on the dump stack, either when called above, or by
783 * the auto-restart code.
784 */
785void
786dumpsys()
787{
788
789	if (dumpdev == NODEV)
790		return;
791	if ((minor(dumpdev)&07) != 1)
792		return;
793	dumpsize = Maxmem;
794	printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo);
795	printf("dump ");
796	switch ((*bdevsw[major(dumpdev)].d_dump)(dumpdev)) {
797
798	case ENXIO:
799		printf("device bad\n");
800		break;
801
802	case EFAULT:
803		printf("device not ready\n");
804		break;
805
806	case EINVAL:
807		printf("area improper\n");
808		break;
809
810	case EIO:
811		printf("i/o error\n");
812		break;
813
814	case EINTR:
815		printf("aborted from console\n");
816		break;
817
818	default:
819		printf("succeeded\n");
820		break;
821	}
822}
823
824#ifdef HZ
825/*
826 * If HZ is defined we use this code, otherwise the code in
827 * /sys/i386/i386/microtime.s is used.  The othercode only works
828 * for HZ=100.
829 */
830microtime(tvp)
831	register struct timeval *tvp;
832{
833	int s = splhigh();
834
835	*tvp = time;
836	tvp->tv_usec += tick;
837	while (tvp->tv_usec > 1000000) {
838		tvp->tv_sec++;
839		tvp->tv_usec -= 1000000;
840	}
841	splx(s);
842}
843#endif /* HZ */
844
845static void
846initcpu()
847{
848}
849
850/*
851 * Clear registers on exec
852 */
853void
854setregs(p, entry, stack)
855	struct proc *p;
856	u_long entry;
857	u_long stack;
858{
859	p->p_md.md_regs[tEBP] = 0;	/* bottom of the fp chain */
860	p->p_md.md_regs[tEIP] = entry;
861	p->p_md.md_regs[tESP] = stack;
862	p->p_md.md_regs[tSS] = _udatasel;
863	p->p_md.md_regs[tDS] = _udatasel;
864	p->p_md.md_regs[tES] = _udatasel;
865	p->p_md.md_regs[tCS] = _ucodesel;
866
867	p->p_addr->u_pcb.pcb_flags = 0;	/* no fp at all */
868	load_cr0(rcr0() | CR0_TS);	/* start emulating */
869#if	NNPX > 0
870	npxinit(__INITIAL_NPXCW__);
871#endif	/* NNPX > 0 */
872}
873
874/*
875 * machine dependent system variables.
876 */
877int
878cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
879	int *name;
880	u_int namelen;
881	void *oldp;
882	size_t *oldlenp;
883	void *newp;
884	size_t newlen;
885	struct proc *p;
886{
887
888	/* all sysctl names at this level are terminal */
889	if (namelen != 1)
890		return (ENOTDIR);               /* overloaded */
891
892	switch (name[0]) {
893	case CPU_CONSDEV:
894		return (sysctl_rdstruct(oldp, oldlenp, newp, &cn_tty->t_dev,
895		   sizeof cn_tty->t_dev));
896	default:
897		return (EOPNOTSUPP);
898	}
899	/* NOTREACHED */
900}
901
902/*
903 * Initialize 386 and configure to run kernel
904 */
905
906/*
907 * Initialize segments & interrupt table
908 */
909
910union descriptor gdt[NGDT];
911union descriptor ldt[NLDT];		/* local descriptor table */
912struct gate_descriptor idt[NIDT];	/* interrupt descriptor table */
913
914int _default_ldt, currentldt;
915
916struct	i386tss	tss, panic_tss;
917
918extern  struct user *proc0paddr;
919
920/* software prototypes -- in more palatable form */
921struct soft_segment_descriptor gdt_segs[] = {
922	/* Null Descriptor */
923{	0x0,			/* segment base address  */
924	0x0,			/* length */
925	0,			/* segment type */
926	0,			/* segment descriptor priority level */
927	0,			/* segment descriptor present */
928	0, 0,
929	0,			/* default 32 vs 16 bit size */
930	0  			/* limit granularity (byte/page units)*/ },
931	/* Code Descriptor for kernel */
932{	0x0,			/* segment base address  */
933	0xfffff,		/* length - all address space */
934	SDT_MEMERA,		/* segment type */
935	0,			/* segment descriptor priority level */
936	1,			/* segment descriptor present */
937	0, 0,
938	1,			/* default 32 vs 16 bit size */
939	1  			/* limit granularity (byte/page units)*/ },
940	/* Data Descriptor for kernel */
941{	0x0,			/* segment base address  */
942	0xfffff,		/* length - all address space */
943	SDT_MEMRWA,		/* segment type */
944	0,			/* segment descriptor priority level */
945	1,			/* segment descriptor present */
946	0, 0,
947	1,			/* default 32 vs 16 bit size */
948	1  			/* limit granularity (byte/page units)*/ },
949	/* LDT Descriptor */
950{	(int) ldt,			/* segment base address  */
951	sizeof(ldt)-1,		/* length - all address space */
952	SDT_SYSLDT,		/* segment type */
953	0,			/* segment descriptor priority level */
954	1,			/* segment descriptor present */
955	0, 0,
956	0,			/* unused - default 32 vs 16 bit size */
957	0  			/* limit granularity (byte/page units)*/ },
958	/* Null Descriptor - Placeholder */
959{	0x0,			/* segment base address  */
960	0x0,			/* length - all address space */
961	0,			/* segment type */
962	0,			/* segment descriptor priority level */
963	0,			/* segment descriptor present */
964	0, 0,
965	0,			/* default 32 vs 16 bit size */
966	0  			/* limit granularity (byte/page units)*/ },
967	/* Panic Tss Descriptor */
968{	(int) &panic_tss,		/* segment base address  */
969	sizeof(tss)-1,		/* length - all address space */
970	SDT_SYS386TSS,		/* segment type */
971	0,			/* segment descriptor priority level */
972	1,			/* segment descriptor present */
973	0, 0,
974	0,			/* unused - default 32 vs 16 bit size */
975	0  			/* limit granularity (byte/page units)*/ },
976	/* Proc 0 Tss Descriptor */
977{	(int) kstack,			/* segment base address  */
978	sizeof(tss)-1,		/* length - all address space */
979	SDT_SYS386TSS,		/* segment type */
980	0,			/* segment descriptor priority level */
981	1,			/* segment descriptor present */
982	0, 0,
983	0,			/* unused - default 32 vs 16 bit size */
984	0  			/* limit granularity (byte/page units)*/ },
985	/* User LDT Descriptor per process */
986{	(int) ldt,			/* segment base address  */
987	(512 * sizeof(union descriptor)-1),		/* length */
988	SDT_SYSLDT,		/* segment type */
989	0,			/* segment descriptor priority level */
990	1,			/* segment descriptor present */
991	0, 0,
992	0,			/* unused - default 32 vs 16 bit size */
993	0  			/* limit granularity (byte/page units)*/ },
994};
995
996struct soft_segment_descriptor ldt_segs[] = {
997	/* Null Descriptor - overwritten by call gate */
998{	0x0,			/* segment base address  */
999	0x0,			/* length - all address space */
1000	0,			/* segment type */
1001	0,			/* segment descriptor priority level */
1002	0,			/* segment descriptor present */
1003	0, 0,
1004	0,			/* default 32 vs 16 bit size */
1005	0  			/* limit granularity (byte/page units)*/ },
1006	/* Null Descriptor - overwritten by call gate */
1007{	0x0,			/* segment base address  */
1008	0x0,			/* length - all address space */
1009	0,			/* segment type */
1010	0,			/* segment descriptor priority level */
1011	0,			/* segment descriptor present */
1012	0, 0,
1013	0,			/* default 32 vs 16 bit size */
1014	0  			/* limit granularity (byte/page units)*/ },
1015	/* Null Descriptor - overwritten by call gate */
1016{	0x0,			/* segment base address  */
1017	0x0,			/* length - all address space */
1018	0,			/* segment type */
1019	0,			/* segment descriptor priority level */
1020	0,			/* segment descriptor present */
1021	0, 0,
1022	0,			/* default 32 vs 16 bit size */
1023	0  			/* limit granularity (byte/page units)*/ },
1024	/* Code Descriptor for user */
1025{	0x0,			/* segment base address  */
1026	0xfffff,		/* length - all address space */
1027	SDT_MEMERA,		/* segment type */
1028	SEL_UPL,		/* segment descriptor priority level */
1029	1,			/* segment descriptor present */
1030	0, 0,
1031	1,			/* default 32 vs 16 bit size */
1032	1  			/* limit granularity (byte/page units)*/ },
1033	/* Data Descriptor for user */
1034{	0x0,			/* segment base address  */
1035	0xfffff,		/* length - all address space */
1036	SDT_MEMRWA,		/* segment type */
1037	SEL_UPL,		/* segment descriptor priority level */
1038	1,			/* segment descriptor present */
1039	0, 0,
1040	1,			/* default 32 vs 16 bit size */
1041	1  			/* limit granularity (byte/page units)*/ } };
1042
1043void
1044setidt(idx, func, typ, dpl)
1045	int idx;
1046	void (*func)();
1047	int typ;
1048	int dpl;
1049{
1050	struct gate_descriptor *ip = idt + idx;
1051
1052	ip->gd_looffset = (int)func;
1053	ip->gd_selector = 8;
1054	ip->gd_stkcpy = 0;
1055	ip->gd_xx = 0;
1056	ip->gd_type = typ;
1057	ip->gd_dpl = dpl;
1058	ip->gd_p = 1;
1059	ip->gd_hioffset = ((int)func)>>16 ;
1060}
1061
1062#define	IDTVEC(name)	__CONCAT(X,name)
1063typedef void idtvec_t();
1064
1065extern idtvec_t
1066	IDTVEC(div), IDTVEC(dbg), IDTVEC(nmi), IDTVEC(bpt), IDTVEC(ofl),
1067	IDTVEC(bnd), IDTVEC(ill), IDTVEC(dna), IDTVEC(dble), IDTVEC(fpusegm),
1068	IDTVEC(tss), IDTVEC(missing), IDTVEC(stk), IDTVEC(prot),
1069	IDTVEC(page), IDTVEC(rsvd), IDTVEC(fpu), IDTVEC(rsvd0),
1070	IDTVEC(rsvd1), IDTVEC(rsvd2), IDTVEC(rsvd3), IDTVEC(rsvd4),
1071	IDTVEC(rsvd5), IDTVEC(rsvd6), IDTVEC(rsvd7), IDTVEC(rsvd8),
1072	IDTVEC(rsvd9), IDTVEC(rsvd10), IDTVEC(rsvd11), IDTVEC(rsvd12),
1073	IDTVEC(rsvd13), IDTVEC(rsvd14), IDTVEC(syscall);
1074
1075int _gsel_tss;
1076
1077void
1078init386(first)
1079	int first;
1080{
1081	extern lgdt(), lidt(), lldt(), etext;
1082	int x, *pi;
1083	unsigned biosbasemem, biosextmem;
1084	struct gate_descriptor *gdp;
1085	extern int sigcode,szsigcode;
1086	/* table descriptors - used to load tables by microp */
1087	struct region_descriptor r_gdt, r_idt;
1088	int	pagesinbase, pagesinext;
1089	int	target_page;
1090	extern struct pte *CMAP1;
1091	extern caddr_t CADDR1;
1092
1093	proc0.p_addr = proc0paddr;
1094
1095	/*
1096	 * Initialize the console before we print anything out.
1097	 */
1098
1099	cninit ();
1100
1101	/*
1102	 * make gdt memory segments, the code segment goes up to end of the
1103	 * page with etext in it, the data segment goes to the end of
1104	 * the address space
1105	 */
1106	gdt_segs[GCODE_SEL].ssd_limit = i386_btop(0) - 1 /* i386_btop(i386_round_page(&etext)) - 1 */;
1107	gdt_segs[GDATA_SEL].ssd_limit = i386_btop(0) - 1;
1108	for (x=0; x < NGDT; x++) ssdtosd(gdt_segs+x, gdt+x);
1109
1110	/* make ldt memory segments */
1111	/*
1112	 * The data segment limit must not cover the user area because we
1113	 * don't want the user area to be writable in copyout() etc. (page
1114	 * level protection is lost in kernel mode on 386's).  Also, we
1115	 * don't want the user area to be writable directly (page level
1116	 * protection of the user area is not available on 486's with
1117	 * CR0_WP set, because there is no user-read/kernel-write mode).
1118	 *
1119	 * XXX - VM_MAXUSER_ADDRESS is an end address, not a max.  And it
1120	 * should be spelled ...MAX_USER...
1121	 */
1122#define VM_END_USER_RW_ADDRESS	VM_MAXUSER_ADDRESS
1123	/*
1124	 * The code segment limit has to cover the user area until we move
1125	 * the signal trampoline out of the user area.  This is safe because
1126	 * the code segment cannot be written to directly.
1127	 */
1128#define VM_END_USER_R_ADDRESS	(VM_END_USER_RW_ADDRESS + UPAGES * NBPG)
1129	ldt_segs[LUCODE_SEL].ssd_limit = i386_btop(VM_END_USER_R_ADDRESS) - 1;
1130	ldt_segs[LUDATA_SEL].ssd_limit = i386_btop(VM_END_USER_RW_ADDRESS) - 1;
1131	/* Note. eventually want private ldts per process */
1132	for (x=0; x < 5; x++) ssdtosd(ldt_segs+x, ldt+x);
1133
1134	/* exceptions */
1135	setidt(0, &IDTVEC(div),  SDT_SYS386TGT, SEL_KPL);
1136	setidt(1, &IDTVEC(dbg),  SDT_SYS386TGT, SEL_KPL);
1137	setidt(2, &IDTVEC(nmi),  SDT_SYS386TGT, SEL_KPL);
1138 	setidt(3, &IDTVEC(bpt),  SDT_SYS386TGT, SEL_UPL);
1139	setidt(4, &IDTVEC(ofl),  SDT_SYS386TGT, SEL_UPL);
1140	setidt(5, &IDTVEC(bnd),  SDT_SYS386TGT, SEL_KPL);
1141	setidt(6, &IDTVEC(ill),  SDT_SYS386TGT, SEL_KPL);
1142	setidt(7, &IDTVEC(dna),  SDT_SYS386TGT, SEL_KPL);
1143	setidt(8, &IDTVEC(dble),  SDT_SYS386TGT, SEL_KPL);
1144	setidt(9, &IDTVEC(fpusegm),  SDT_SYS386TGT, SEL_KPL);
1145	setidt(10, &IDTVEC(tss),  SDT_SYS386TGT, SEL_KPL);
1146	setidt(11, &IDTVEC(missing),  SDT_SYS386TGT, SEL_KPL);
1147	setidt(12, &IDTVEC(stk),  SDT_SYS386TGT, SEL_KPL);
1148	setidt(13, &IDTVEC(prot),  SDT_SYS386TGT, SEL_KPL);
1149	setidt(14, &IDTVEC(page),  SDT_SYS386TGT, SEL_KPL);
1150	setidt(15, &IDTVEC(rsvd),  SDT_SYS386TGT, SEL_KPL);
1151	setidt(16, &IDTVEC(fpu),  SDT_SYS386TGT, SEL_KPL);
1152	setidt(17, &IDTVEC(rsvd0),  SDT_SYS386TGT, SEL_KPL);
1153	setidt(18, &IDTVEC(rsvd1),  SDT_SYS386TGT, SEL_KPL);
1154	setidt(19, &IDTVEC(rsvd2),  SDT_SYS386TGT, SEL_KPL);
1155	setidt(20, &IDTVEC(rsvd3),  SDT_SYS386TGT, SEL_KPL);
1156	setidt(21, &IDTVEC(rsvd4),  SDT_SYS386TGT, SEL_KPL);
1157	setidt(22, &IDTVEC(rsvd5),  SDT_SYS386TGT, SEL_KPL);
1158	setidt(23, &IDTVEC(rsvd6),  SDT_SYS386TGT, SEL_KPL);
1159	setidt(24, &IDTVEC(rsvd7),  SDT_SYS386TGT, SEL_KPL);
1160	setidt(25, &IDTVEC(rsvd8),  SDT_SYS386TGT, SEL_KPL);
1161	setidt(26, &IDTVEC(rsvd9),  SDT_SYS386TGT, SEL_KPL);
1162	setidt(27, &IDTVEC(rsvd10),  SDT_SYS386TGT, SEL_KPL);
1163	setidt(28, &IDTVEC(rsvd11),  SDT_SYS386TGT, SEL_KPL);
1164	setidt(29, &IDTVEC(rsvd12),  SDT_SYS386TGT, SEL_KPL);
1165	setidt(30, &IDTVEC(rsvd13),  SDT_SYS386TGT, SEL_KPL);
1166	setidt(31, &IDTVEC(rsvd14),  SDT_SYS386TGT, SEL_KPL);
1167
1168#include	"isa.h"
1169#if	NISA >0
1170	isa_defaultirq();
1171#endif
1172
1173	r_gdt.rd_limit = sizeof(gdt) - 1;
1174	r_gdt.rd_base =  (int) gdt;
1175	lgdt(&r_gdt);
1176
1177	r_idt.rd_limit = sizeof(idt) - 1;
1178	r_idt.rd_base = (int) idt;
1179	lidt(&r_idt);
1180
1181	_default_ldt = GSEL(GLDT_SEL, SEL_KPL);
1182	lldt(_default_ldt);
1183	currentldt = _default_ldt;
1184
1185#ifdef DDB
1186	kdb_init();
1187	if (boothowto & RB_KDB)
1188		Debugger("Boot flags requested debugger");
1189#endif
1190
1191	/* Use BIOS values stored in RTC CMOS RAM, since probing
1192	 * breaks certain 386 AT relics.
1193	 */
1194	biosbasemem = rtcin(RTC_BASELO)+ (rtcin(RTC_BASEHI)<<8);
1195	biosextmem = rtcin(RTC_EXTLO)+ (rtcin(RTC_EXTHI)<<8);
1196
1197	/*
1198	 * If BIOS tells us that it has more than 640k in the basemem,
1199	 *	don't believe it - set it to 640k.
1200	 */
1201	if (biosbasemem > 640)
1202		biosbasemem = 640;
1203
1204	/*
1205	 * Some 386 machines might give us a bogus number for extended
1206	 *	mem. If this happens, stop now.
1207	 */
1208#ifndef LARGEMEM
1209	if (biosextmem > 65536) {
1210		panic("extended memory beyond limit of 64MB");
1211		/* NOTREACHED */
1212	}
1213#endif
1214
1215	pagesinbase = biosbasemem * 1024 / NBPG;
1216	pagesinext = biosextmem * 1024 / NBPG;
1217
1218	/*
1219	 * Special hack for chipsets that still remap the 384k hole when
1220	 *	there's 16MB of memory - this really confuses people that
1221	 *	are trying to use bus mastering ISA controllers with the
1222	 *	"16MB limit"; they only have 16MB, but the remapping puts
1223	 *	them beyond the limit.
1224	 * XXX - this should be removed when bounce buffers are
1225	 *	implemented.
1226	 */
1227	/*
1228	 * If extended memory is between 15-16MB (16-17MB phys address range),
1229	 *	chop it to 15MB.
1230	 */
1231	if ((pagesinext > 3840) && (pagesinext < 4096))
1232		pagesinext = 3840;
1233
1234	/*
1235	 * Maxmem isn't the "maximum memory", it's the highest page of
1236	 * of the physical address space. It should be "Maxphyspage".
1237	 */
1238	Maxmem = pagesinext + 0x100000/PAGE_SIZE;
1239
1240#ifdef MAXMEM
1241	if (MAXMEM/4 < Maxmem)
1242		Maxmem = MAXMEM/4;
1243#endif
1244	/*
1245	 * Calculate number of physical pages, but account for Maxmem
1246	 *	limitation above.
1247	 */
1248	physmem = pagesinbase +
1249	    (min(pagesinext + 0x100000/PAGE_SIZE, Maxmem) - 0x100000/PAGE_SIZE);
1250
1251	/* call pmap initialization to make new kernel address space */
1252	pmap_bootstrap (first, 0);
1253
1254	/*
1255	 * Do simple memory test over range of extended memory that BIOS
1256	 *	indicates exists. Adjust Maxmem to the highest page of
1257	 *	good memory.
1258	 */
1259	printf("Testing memory (%dMB)...", ptoa(Maxmem)/1024/1024);
1260
1261	for (target_page = Maxmem - 1; target_page >= atop(first); target_page--) {
1262
1263		/*
1264		 * map page into kernel: valid, read/write, non-cacheable
1265		 */
1266		*(int *)CMAP1 = PG_V | PG_KW | PG_N | ptoa(target_page);
1267		tlbflush();
1268
1269		/*
1270		 * Test for alternating 1's and 0's
1271		 */
1272		filli(0xaaaaaaaa, CADDR1, PAGE_SIZE/sizeof(int));
1273		if (test_page((int *)CADDR1, 0xaaaaaaaa)) {
1274			Maxmem = target_page;
1275			badpages++;
1276			continue;
1277		}
1278		/*
1279		 * Test for alternating 0's and 1's
1280		 */
1281		filli(0x55555555, CADDR1, PAGE_SIZE/sizeof(int));
1282		if (test_page((int *)CADDR1, 0x55555555)) {
1283			Maxmem = target_page;
1284			badpages++;
1285			continue;
1286		}
1287		/*
1288		 * Test for all 1's
1289		 */
1290		filli(0xffffffff, CADDR1, PAGE_SIZE/sizeof(int));
1291		if (test_page((int *)CADDR1, 0xffffffff)) {
1292			Maxmem = target_page;
1293			badpages++;
1294			continue;
1295		}
1296		/*
1297		 * Test zeroing of page
1298		 */
1299		bzero(CADDR1, PAGE_SIZE);
1300		if (test_page((int *)CADDR1, 0)) {
1301			/*
1302			 * test of page failed
1303			 */
1304			Maxmem = target_page;
1305			badpages++;
1306			continue;
1307		}
1308	}
1309	printf("done.\n");
1310
1311	*(int *)CMAP1 = 0;
1312	tlbflush();
1313
1314	avail_end = (Maxmem << PAGE_SHIFT)
1315		    - i386_round_page(sizeof(struct msgbuf));
1316
1317	/*
1318	 * Initialize pointers to the two chunks of memory; for use
1319	 *	later in vm_page_startup.
1320	 */
1321	/* avail_start is initialized in pmap_bootstrap */
1322	x = 0;
1323	if (pagesinbase > 1) {
1324		phys_avail[x++] = NBPG;		/* skip first page of memory */
1325		phys_avail[x++] = pagesinbase * NBPG;	/* memory up to the ISA hole */
1326	}
1327	phys_avail[x++] = avail_start;	/* memory up to the end */
1328	phys_avail[x++] = avail_end;
1329	phys_avail[x++] = 0;		/* no more chunks */
1330	phys_avail[x++] = 0;
1331
1332	/* now running on new page tables, configured,and u/iom is accessible */
1333
1334	/* make a initial tss so microp can get interrupt stack on syscall! */
1335	proc0.p_addr->u_pcb.pcb_tss.tss_esp0 = (int) kstack + UPAGES*NBPG;
1336	proc0.p_addr->u_pcb.pcb_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL) ;
1337	_gsel_tss = GSEL(GPROC0_SEL, SEL_KPL);
1338
1339	((struct i386tss *)gdt_segs[GPROC0_SEL].ssd_base)->tss_ioopt =
1340		(sizeof(tss))<<16;
1341
1342	ltr(_gsel_tss);
1343
1344	/* make a call gate to reenter kernel with */
1345	gdp = &ldt[LSYS5CALLS_SEL].gd;
1346
1347	x = (int) &IDTVEC(syscall);
1348	gdp->gd_looffset = x++;
1349	gdp->gd_selector = GSEL(GCODE_SEL,SEL_KPL);
1350	gdp->gd_stkcpy = 1;
1351	gdp->gd_type = SDT_SYS386CGT;
1352	gdp->gd_dpl = SEL_UPL;
1353	gdp->gd_p = 1;
1354	gdp->gd_hioffset = ((int) &IDTVEC(syscall)) >>16;
1355
1356	/* transfer to user mode */
1357
1358	_ucodesel = LSEL(LUCODE_SEL, SEL_UPL);
1359	_udatasel = LSEL(LUDATA_SEL, SEL_UPL);
1360
1361	/* setup proc 0's pcb */
1362	bcopy(&sigcode, proc0.p_addr->u_pcb.pcb_sigc, szsigcode);
1363	proc0.p_addr->u_pcb.pcb_flags = 0;
1364	proc0.p_addr->u_pcb.pcb_ptd = IdlePTD;
1365}
1366
1367int
1368test_page(address, pattern)
1369	int *address;
1370	int pattern;
1371{
1372	int *x;
1373
1374	for (x = address; x < (int *)((char *)address + PAGE_SIZE); x++) {
1375		if (*x != pattern)
1376			return (1);
1377	}
1378	return(0);
1379}
1380
1381/*
1382 * The registers are in the frame; the frame is in the user area of
1383 * the process in question; when the process is active, the registers
1384 * are in "the kernel stack"; when it's not, they're still there, but
1385 * things get flipped around.  So, since p->p_md.md_regs is the whole address
1386 * of the register set, take its offset from the kernel stack, and
1387 * index into the user block.  Don't you just *love* virtual memory?
1388 * (I'm starting to think seymour is right...)
1389 */
1390
1391int
1392ptrace_set_pc (struct proc *p, unsigned int addr) {
1393	void *regs = (char*)p->p_addr +
1394		((char*) p->p_md.md_regs - (char*) kstack);
1395
1396	((struct trapframe *)regs)->tf_eip = addr;
1397	return 0;
1398}
1399
1400int
1401ptrace_single_step (struct proc *p) {
1402	void *regs = (char*)p->p_addr +
1403		((char*) p->p_md.md_regs - (char*) kstack);
1404
1405	((struct trapframe *)regs)->tf_eflags |= PSL_T;
1406	return 0;
1407}
1408
1409/*
1410 * Copy the registers to user-space.
1411 */
1412
1413int
1414ptrace_getregs (struct proc *p, unsigned int *addr) {
1415	int error;
1416	struct reg regs = {0};
1417
1418	if (error = fill_regs (p, &regs))
1419		return error;
1420
1421	return copyout (&regs, addr, sizeof (regs));
1422}
1423
1424int
1425ptrace_setregs (struct proc *p, unsigned int *addr) {
1426	int error;
1427	struct reg regs = {0};
1428
1429	if (error = copyin (addr, &regs, sizeof(regs)))
1430		return error;
1431
1432	return set_regs (p, &regs);
1433}
1434
1435int
1436fill_regs(struct proc *p, struct reg *regs) {
1437	int error;
1438	struct trapframe *tp;
1439	void *ptr = (char*)p->p_addr +
1440		((char*) p->p_md.md_regs - (char*) kstack);
1441
1442	tp = ptr;
1443	regs->r_es = tp->tf_es;
1444	regs->r_ds = tp->tf_ds;
1445	regs->r_edi = tp->tf_edi;
1446	regs->r_esi = tp->tf_esi;
1447	regs->r_ebp = tp->tf_ebp;
1448	regs->r_ebx = tp->tf_ebx;
1449	regs->r_edx = tp->tf_edx;
1450	regs->r_ecx = tp->tf_ecx;
1451	regs->r_eax = tp->tf_eax;
1452	regs->r_eip = tp->tf_eip;
1453	regs->r_cs = tp->tf_cs;
1454	regs->r_eflags = tp->tf_eflags;
1455	regs->r_esp = tp->tf_esp;
1456	regs->r_ss = tp->tf_ss;
1457	return 0;
1458}
1459
1460int
1461set_regs (struct proc *p, struct reg *regs) {
1462	int error;
1463	struct trapframe *tp;
1464	void *ptr = (char*)p->p_addr +
1465		((char*) p->p_md.md_regs - (char*) kstack);
1466
1467	tp = ptr;
1468	tp->tf_es = regs->r_es;
1469	tp->tf_ds = regs->r_ds;
1470	tp->tf_edi = regs->r_edi;
1471	tp->tf_esi = regs->r_esi;
1472	tp->tf_ebp = regs->r_ebp;
1473	tp->tf_ebx = regs->r_ebx;
1474	tp->tf_edx = regs->r_edx;
1475	tp->tf_ecx = regs->r_ecx;
1476	tp->tf_eax = regs->r_eax;
1477	tp->tf_eip = regs->r_eip;
1478	tp->tf_cs = regs->r_cs;
1479	tp->tf_eflags = regs->r_eflags;
1480	tp->tf_esp = regs->r_esp;
1481	tp->tf_ss = regs->r_ss;
1482	return 0;
1483}
1484
1485#ifndef DDB
1486void
1487Debugger(const char *msg)
1488{
1489	printf("Debugger(\"%s\") called.\n", msg);
1490}
1491#endif /* no DDB */
1492
1493#include <sys/disklabel.h>
1494#define b_cylin	b_resid
1495#define dkpart(dev)              (minor(dev) & 7)
1496/*
1497 * Determine the size of the transfer, and make sure it is
1498 * within the boundaries of the partition. Adjust transfer
1499 * if needed, and signal errors or early completion.
1500 */
1501int
1502bounds_check_with_label(struct buf *bp, struct disklabel *lp, int wlabel)
1503{
1504        struct partition *p = lp->d_partitions + dkpart(bp->b_dev);
1505        int labelsect = lp->d_partitions[0].p_offset;
1506        int maxsz = p->p_size,
1507                sz = (bp->b_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT;
1508
1509        /* overwriting disk label ? */
1510        /* XXX should also protect bootstrap in first 8K */
1511        if (bp->b_blkno + p->p_offset <= LABELSECTOR + labelsect &&
1512#if LABELSECTOR != 0
1513            bp->b_blkno + p->p_offset + sz > LABELSECTOR + labelsect &&
1514#endif
1515            (bp->b_flags & B_READ) == 0 && wlabel == 0) {
1516                bp->b_error = EROFS;
1517                goto bad;
1518        }
1519
1520#if     defined(DOSBBSECTOR) && defined(notyet)
1521        /* overwriting master boot record? */
1522        if (bp->b_blkno + p->p_offset <= DOSBBSECTOR &&
1523            (bp->b_flags & B_READ) == 0 && wlabel == 0) {
1524                bp->b_error = EROFS;
1525                goto bad;
1526        }
1527#endif
1528
1529        /* beyond partition? */
1530        if (bp->b_blkno < 0 || bp->b_blkno + sz > maxsz) {
1531                /* if exactly at end of disk, return an EOF */
1532                if (bp->b_blkno == maxsz) {
1533                        bp->b_resid = bp->b_bcount;
1534                        return(0);
1535                }
1536                /* or truncate if part of it fits */
1537                sz = maxsz - bp->b_blkno;
1538                if (sz <= 0) {
1539                        bp->b_error = EINVAL;
1540                        goto bad;
1541                }
1542                bp->b_bcount = sz << DEV_BSHIFT;
1543        }
1544
1545        /* calculate cylinder for disksort to order transfers with */
1546        bp->b_pblkno = bp->b_blkno + p->p_offset;
1547        bp->b_cylin = bp->b_pblkno / lp->d_secpercyl;
1548        return(1);
1549
1550bad:
1551        bp->b_flags |= B_ERROR;
1552        return(-1);
1553}
1554
1555