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