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