machdep.c revision 4463
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.88 1994/11/07 03:51:32 phk 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#ifdef DODUMP
806int		dodump = 1;
807#else
808int		dodump = 0;
809#endif
810/*
811 * Doadump comes here after turning off memory management and
812 * getting on the dump stack, either when called above, or by
813 * the auto-restart code.
814 */
815void
816dumpsys()
817{
818
819	if (!dodump)
820		return;
821	if (dumpdev == NODEV)
822		return;
823	if ((minor(dumpdev)&07) != 1)
824		return;
825	dumpsize = Maxmem;
826	printf("\ndumping to dev %lx, offset %ld\n", dumpdev, dumplo);
827	printf("dump ");
828	switch ((*bdevsw[major(dumpdev)].d_dump)(dumpdev)) {
829
830	case ENXIO:
831		printf("device bad\n");
832		break;
833
834	case EFAULT:
835		printf("device not ready\n");
836		break;
837
838	case EINVAL:
839		printf("area improper\n");
840		break;
841
842	case EIO:
843		printf("i/o error\n");
844		break;
845
846	case EINTR:
847		printf("aborted from console\n");
848		break;
849
850	default:
851		printf("succeeded\n");
852		break;
853	}
854}
855
856static void
857initcpu()
858{
859}
860
861/*
862 * Clear registers on exec
863 */
864void
865setregs(p, entry, stack)
866	struct proc *p;
867	u_long entry;
868	u_long stack;
869{
870	int *regs = p->p_md.md_regs;
871
872	bzero(regs, sizeof(struct trapframe));
873	regs[tEIP] = entry;
874	regs[tESP] = stack;
875	regs[tEFLAGS] = PSL_USERSET | (regs[tEFLAGS] & PSL_T);
876	regs[tSS] = _udatasel;
877	regs[tDS] = _udatasel;
878	regs[tES] = _udatasel;
879	regs[tCS] = _ucodesel;
880
881	p->p_addr->u_pcb.pcb_flags = 0;	/* no fp at all */
882	load_cr0(rcr0() | CR0_TS);	/* start emulating */
883#if	NNPX > 0
884	npxinit(__INITIAL_NPXCW__);
885#endif	/* NNPX > 0 */
886}
887
888/*
889 * machine dependent system variables.
890 */
891int
892cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
893	int *name;
894	u_int namelen;
895	void *oldp;
896	size_t *oldlenp;
897	void *newp;
898	size_t newlen;
899	struct proc *p;
900{
901	int error;
902
903	/* all sysctl names at this level are terminal */
904	if (namelen != 1)
905		return (ENOTDIR);               /* overloaded */
906
907	switch (name[0]) {
908	case CPU_CONSDEV:
909		return (sysctl_rdstruct(oldp, oldlenp, newp, &cn_tty->t_dev,
910		   sizeof cn_tty->t_dev));
911	case CPU_ADJKERNTZ:
912		error = sysctl_int(oldp, oldlenp, newp, newlen, &adjkerntz);
913		if (!error && newp)
914			resettodr();
915		return error;
916	case CPU_DISRTCSET:
917		return (sysctl_int(oldp, oldlenp, newp,	newlen,	&disable_rtc_set));
918	default:
919		return (EOPNOTSUPP);
920	}
921	/* NOTREACHED */
922}
923
924/*
925 * Initialize 386 and configure to run kernel
926 */
927
928/*
929 * Initialize segments & interrupt table
930 */
931
932union descriptor gdt[NGDT];
933union descriptor ldt[NLDT];		/* local descriptor table */
934struct gate_descriptor idt[NIDT];	/* interrupt descriptor table */
935
936int _default_ldt, currentldt;
937
938struct	i386tss	tss, panic_tss;
939
940extern  struct user *proc0paddr;
941
942/* software prototypes -- in more palatable form */
943struct 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	void (*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)
1112typedef void idtvec_t();
1113
1114extern idtvec_t
1115	IDTVEC(div), IDTVEC(dbg), IDTVEC(nmi), IDTVEC(bpt), IDTVEC(ofl),
1116	IDTVEC(bnd), IDTVEC(ill), IDTVEC(dna), IDTVEC(dble), IDTVEC(fpusegm),
1117	IDTVEC(tss), IDTVEC(missing), IDTVEC(stk), IDTVEC(prot),
1118	IDTVEC(page), IDTVEC(rsvd), IDTVEC(fpu), IDTVEC(rsvd0),
1119	IDTVEC(rsvd1), IDTVEC(rsvd2), IDTVEC(rsvd3), IDTVEC(rsvd4),
1120	IDTVEC(rsvd5), IDTVEC(rsvd6), IDTVEC(rsvd7), IDTVEC(rsvd8),
1121	IDTVEC(rsvd9), IDTVEC(rsvd10), IDTVEC(rsvd11), IDTVEC(rsvd12),
1122	IDTVEC(rsvd13), IDTVEC(rsvd14), IDTVEC(syscall);
1123
1124int _gsel_tss;
1125
1126/* added sdtossd() by HOSOKAWA Tatsumi <hosokawa@mt.cs.keio.ac.jp> */
1127int
1128sdtossd(sd, ssd)
1129	struct segment_descriptor *sd;
1130	struct soft_segment_descriptor *ssd;
1131{
1132	ssd->ssd_base  = (sd->sd_hibase << 24) | sd->sd_lobase;
1133	ssd->ssd_limit = (sd->sd_hilimit << 16) | sd->sd_lolimit;
1134	ssd->ssd_type  = sd->sd_type;
1135	ssd->ssd_dpl   = sd->sd_dpl;
1136	ssd->ssd_p     = sd->sd_p;
1137	ssd->ssd_def32 = sd->sd_def32;
1138	ssd->ssd_gran  = sd->sd_gran;
1139	return 0;
1140}
1141
1142void
1143init386(first)
1144	int first;
1145{
1146	extern lgdt(), lidt(), lldt();
1147	int x;
1148	unsigned biosbasemem, biosextmem;
1149	struct gate_descriptor *gdp;
1150	extern int sigcode,szsigcode;
1151	/* table descriptors - used to load tables by microp */
1152	struct region_descriptor r_gdt, r_idt;
1153	int	pagesinbase, pagesinext;
1154	int	target_page;
1155	extern struct pte *CMAP1;
1156	extern caddr_t CADDR1;
1157
1158	proc0.p_addr = proc0paddr;
1159
1160	/*
1161	 * Initialize the console before we print anything out.
1162	 */
1163
1164	cninit ();
1165
1166	/*
1167	 * make gdt memory segments, the code segment goes up to end of the
1168	 * page with etext in it, the data segment goes to the end of
1169	 * the address space
1170	 */
1171	gdt_segs[GCODE_SEL].ssd_limit = i386_btop(0) - 1 /* i386_btop(i386_round_page(&etext)) - 1 */;
1172	gdt_segs[GDATA_SEL].ssd_limit = i386_btop(0) - 1;
1173	for (x=0; x < NGDT; x++) ssdtosd(gdt_segs+x, gdt+x);
1174
1175	/* make ldt memory segments */
1176	/*
1177	 * The data segment limit must not cover the user area because we
1178	 * don't want the user area to be writable in copyout() etc. (page
1179	 * level protection is lost in kernel mode on 386's).  Also, we
1180	 * don't want the user area to be writable directly (page level
1181	 * protection of the user area is not available on 486's with
1182	 * CR0_WP set, because there is no user-read/kernel-write mode).
1183	 *
1184	 * XXX - VM_MAXUSER_ADDRESS is an end address, not a max.  And it
1185	 * should be spelled ...MAX_USER...
1186	 */
1187#define VM_END_USER_RW_ADDRESS	VM_MAXUSER_ADDRESS
1188	/*
1189	 * The code segment limit has to cover the user area until we move
1190	 * the signal trampoline out of the user area.  This is safe because
1191	 * the code segment cannot be written to directly.
1192	 */
1193#define VM_END_USER_R_ADDRESS	(VM_END_USER_RW_ADDRESS + UPAGES * NBPG)
1194	ldt_segs[LUCODE_SEL].ssd_limit = i386_btop(VM_END_USER_R_ADDRESS) - 1;
1195	ldt_segs[LUDATA_SEL].ssd_limit = i386_btop(VM_END_USER_RW_ADDRESS) - 1;
1196	/* Note. eventually want private ldts per process */
1197	for (x=0; x < 5; x++) ssdtosd(ldt_segs+x, ldt+x);
1198
1199	/* exceptions */
1200	setidt(0, &IDTVEC(div),  SDT_SYS386TGT, SEL_KPL);
1201	setidt(1, &IDTVEC(dbg),  SDT_SYS386TGT, SEL_KPL);
1202	setidt(2, &IDTVEC(nmi),  SDT_SYS386TGT, SEL_KPL);
1203 	setidt(3, &IDTVEC(bpt),  SDT_SYS386TGT, SEL_UPL);
1204	setidt(4, &IDTVEC(ofl),  SDT_SYS386TGT, SEL_UPL);
1205	setidt(5, &IDTVEC(bnd),  SDT_SYS386TGT, SEL_KPL);
1206	setidt(6, &IDTVEC(ill),  SDT_SYS386TGT, SEL_KPL);
1207	setidt(7, &IDTVEC(dna),  SDT_SYS386TGT, SEL_KPL);
1208	setidt(8, &IDTVEC(dble),  SDT_SYS386TGT, SEL_KPL);
1209	setidt(9, &IDTVEC(fpusegm),  SDT_SYS386TGT, SEL_KPL);
1210	setidt(10, &IDTVEC(tss),  SDT_SYS386TGT, SEL_KPL);
1211	setidt(11, &IDTVEC(missing),  SDT_SYS386TGT, SEL_KPL);
1212	setidt(12, &IDTVEC(stk),  SDT_SYS386TGT, SEL_KPL);
1213	setidt(13, &IDTVEC(prot),  SDT_SYS386TGT, SEL_KPL);
1214	setidt(14, &IDTVEC(page),  SDT_SYS386TGT, SEL_KPL);
1215	setidt(15, &IDTVEC(rsvd),  SDT_SYS386TGT, SEL_KPL);
1216	setidt(16, &IDTVEC(fpu),  SDT_SYS386TGT, SEL_KPL);
1217	setidt(17, &IDTVEC(rsvd0),  SDT_SYS386TGT, SEL_KPL);
1218	setidt(18, &IDTVEC(rsvd1),  SDT_SYS386TGT, SEL_KPL);
1219	setidt(19, &IDTVEC(rsvd2),  SDT_SYS386TGT, SEL_KPL);
1220	setidt(20, &IDTVEC(rsvd3),  SDT_SYS386TGT, SEL_KPL);
1221	setidt(21, &IDTVEC(rsvd4),  SDT_SYS386TGT, SEL_KPL);
1222	setidt(22, &IDTVEC(rsvd5),  SDT_SYS386TGT, SEL_KPL);
1223	setidt(23, &IDTVEC(rsvd6),  SDT_SYS386TGT, SEL_KPL);
1224	setidt(24, &IDTVEC(rsvd7),  SDT_SYS386TGT, SEL_KPL);
1225	setidt(25, &IDTVEC(rsvd8),  SDT_SYS386TGT, SEL_KPL);
1226	setidt(26, &IDTVEC(rsvd9),  SDT_SYS386TGT, SEL_KPL);
1227	setidt(27, &IDTVEC(rsvd10),  SDT_SYS386TGT, SEL_KPL);
1228	setidt(28, &IDTVEC(rsvd11),  SDT_SYS386TGT, SEL_KPL);
1229	setidt(29, &IDTVEC(rsvd12),  SDT_SYS386TGT, SEL_KPL);
1230	setidt(30, &IDTVEC(rsvd13),  SDT_SYS386TGT, SEL_KPL);
1231	setidt(31, &IDTVEC(rsvd14),  SDT_SYS386TGT, SEL_KPL);
1232
1233#include	"isa.h"
1234#if	NISA >0
1235	isa_defaultirq();
1236#endif
1237
1238	r_gdt.rd_limit = sizeof(gdt) - 1;
1239	r_gdt.rd_base =  (int) gdt;
1240	lgdt(&r_gdt);
1241
1242	r_idt.rd_limit = sizeof(idt) - 1;
1243	r_idt.rd_base = (int) idt;
1244	lidt(&r_idt);
1245
1246	_default_ldt = GSEL(GLDT_SEL, SEL_KPL);
1247	lldt(_default_ldt);
1248	currentldt = _default_ldt;
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