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