machdep.c revision 5035
1219820Sjeff/*-
2219820Sjeff * Copyright (c) 1992 Terrence R. Lambert.
3219820Sjeff * Copyright (c) 1982, 1987, 1990 The Regents of the University of California.
4219820Sjeff * All rights reserved.
5219820Sjeff *
6219820Sjeff * This code is derived from software contributed to Berkeley by
7219820Sjeff * William Jolitz.
8219820Sjeff *
9219820Sjeff * Redistribution and use in source and binary forms, with or without
10219820Sjeff * modification, are permitted provided that the following conditions
11219820Sjeff * are met:
12219820Sjeff * 1. Redistributions of source code must retain the above copyright
13219820Sjeff *    notice, this list of conditions and the following disclaimer.
14219820Sjeff * 2. Redistributions in binary form must reproduce the above copyright
15219820Sjeff *    notice, this list of conditions and the following disclaimer in the
16219820Sjeff *    documentation and/or other materials provided with the distribution.
17219820Sjeff * 3. All advertising materials mentioning features or use of this software
18219820Sjeff *    must display the following acknowledgement:
19219820Sjeff *	This product includes software developed by the University of
20219820Sjeff *	California, Berkeley and its contributors.
21219820Sjeff * 4. Neither the name of the University nor the names of its contributors
22219820Sjeff *    may be used to endorse or promote products derived from this software
23219820Sjeff *    without specific prior written permission.
24219820Sjeff *
25219820Sjeff * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26219820Sjeff * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27219820Sjeff * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28219820Sjeff * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29219820Sjeff * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30219820Sjeff * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31219820Sjeff * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32219820Sjeff * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33219820Sjeff * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34219820Sjeff * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35219820Sjeff * SUCH DAMAGE.
36219820Sjeff *
37219820Sjeff *	from: @(#)machdep.c	7.4 (Berkeley) 6/3/91
38219820Sjeff *	$Id: machdep.c,v 1.95 1994/11/27 01:49:39 phk Exp $
39219820Sjeff */
40219820Sjeff
41219820Sjeff#include "npx.h"
42219820Sjeff#include "isa.h"
43219820Sjeff
44219820Sjeff#include <sys/param.h>
45219820Sjeff#include <sys/systm.h>
46219820Sjeff#include <sys/signalvar.h>
47219820Sjeff#include <sys/kernel.h>
48219820Sjeff#include <sys/proc.h>
49219820Sjeff#include <sys/user.h>
50219820Sjeff#include <sys/buf.h>
51219820Sjeff#include <sys/reboot.h>
52219820Sjeff#include <sys/conf.h>
53219820Sjeff#include <sys/file.h>
54219820Sjeff#include <sys/callout.h>
55219820Sjeff#include <sys/malloc.h>
56219820Sjeff#include <sys/mbuf.h>
57219820Sjeff#include <sys/msgbuf.h>
58219820Sjeff#include <sys/ioctl.h>
59219820Sjeff#include <sys/sysent.h>
60219820Sjeff#include <sys/tty.h>
61219820Sjeff#include <sys/sysctl.h>
62219820Sjeff
63219820Sjeff#ifdef SYSVSHM
64219820Sjeff#include <sys/shm.h>
65219820Sjeff#endif
66219820Sjeff
67219820Sjeff#ifdef SYSVMSG
68219820Sjeff#include <sys/msg.h>
69219820Sjeff#endif
70219820Sjeff
71219820Sjeff#ifdef SYSVSEM
72219820Sjeff#include <sys/sem.h>
73219820Sjeff#endif
74219820Sjeff
75219820Sjeff#include <vm/vm.h>
76219820Sjeff#include <vm/vm_kern.h>
77219820Sjeff#include <vm/vm_page.h>
78219820Sjeff
79219820Sjeff#include <sys/exec.h>
80219820Sjeff#include <sys/vnode.h>
81219820Sjeff
82219820Sjeff#include <net/netisr.h>
83219820Sjeff
84219820Sjeffextern vm_offset_t avail_start, avail_end;
85219820Sjeff
86219820Sjeff#include "ether.h"
87219820Sjeff
88219820Sjeff#include <machine/cpu.h>
89219820Sjeff#include <machine/npx.h>
90219820Sjeff#include <machine/reg.h>
91219820Sjeff#include <machine/psl.h>
92219820Sjeff#include <machine/clock.h>
93219820Sjeff#include <machine/specialreg.h>
94219820Sjeff#include <machine/sysarch.h>
95219820Sjeff#include <machine/cons.h>
96219820Sjeff#include <machine/devconf.h>
97219820Sjeff#include <machine/bootinfo.h>
98219820Sjeff
99219820Sjeff#include <i386/isa/isa.h>
100219820Sjeff#include <i386/isa/isa_device.h>
101219820Sjeff#include <i386/isa/rtc.h>
102219820Sjeff
103219820Sjeffstatic void identifycpu(void);
104219820Sjeffstatic void initcpu(void);
105219820Sjeffstatic int test_page(int *, int);
106219820Sjeff
107219820Sjeffchar machine[] = "i386";
108219820Sjeffchar cpu_model[sizeof("Cy486DLC") + 1];
109219820Sjeff
110219820Sjeff#ifndef PANIC_REBOOT_WAIT_TIME
111219820Sjeff#define PANIC_REBOOT_WAIT_TIME 15 /* default to 15 seconds */
112219820Sjeff#endif
113219820Sjeff
114219820Sjeff/*
115219820Sjeff * Declare these as initialized data so we can patch them.
116219820Sjeff */
117219820Sjeffint	nswbuf = 0;
118219820Sjeff#ifdef	NBUF
119219820Sjeffint	nbuf = NBUF;
120219820Sjeff#else
121219820Sjeffint	nbuf = 0;
122219820Sjeff#endif
123219820Sjeff#ifdef	BUFPAGES
124219820Sjeffint	bufpages = BUFPAGES;
125219820Sjeff#else
126219820Sjeffint	bufpages = 0;
127219820Sjeff#endif
128219820Sjeff
129219820Sjeff#ifdef BOUNCE_BUFFERS
130219820Sjeffextern char *bouncememory;
131219820Sjeffextern int maxbkva;
132219820Sjeff#ifdef BOUNCEPAGES
133219820Sjeffint	bouncepages = BOUNCEPAGES;
134219820Sjeff#else
135219820Sjeffint	bouncepages = 0;
136219820Sjeff#endif
137219820Sjeff#endif	/* BOUNCE_BUFFERS */
138219820Sjeff
139219820Sjeffextern int freebufspace;
140219820Sjeffint	msgbufmapped = 0;		/* set when safe to use msgbuf */
141219820Sjeffint _udatasel, _ucodesel;
142219820Sjeff
143219820Sjeff
144219820Sjeff/*
145219820Sjeff * Machine-dependent startup code
146219820Sjeff */
147219820Sjeffint boothowto = 0, bootverbose = 0, Maxmem = 0, badpages = 0, physmem = 0;
148219820Sjefflong dumplo;
149219820Sjeffextern int bootdev;
150219820Sjeffint biosmem;
151219820Sjeff
152219820Sjeffvm_offset_t	phys_avail[6];
153219820Sjeff
154219820Sjeffint cpu_class;
155219820Sjeff
156219820Sjeffvoid dumpsys __P((void));
157219820Sjeffvm_offset_t buffer_sva, buffer_eva;
158219820Sjeffvm_offset_t clean_sva, clean_eva;
159219820Sjeffvm_offset_t pager_sva, pager_eva;
160219820Sjeffextern int pager_map_size;
161219820Sjeff
162219820Sjeff#define offsetof(type, member)	((size_t)(&((type *)0)->member))
163219820Sjeff
164219820Sjeffvoid
165219820Sjeffcpu_startup()
166219820Sjeff{
167219820Sjeff	register unsigned i;
168219820Sjeff	register caddr_t v;
169219820Sjeff	extern void (*netisrs[32])(void);
170219820Sjeff	vm_offset_t maxaddr;
171219820Sjeff	vm_size_t size = 0;
172219820Sjeff	int firstaddr;
173219820Sjeff#ifdef BOUNCE_BUFFERS
174219820Sjeff	vm_offset_t minaddr;
175219820Sjeff#endif /* BOUNCE_BUFFERS */
176219820Sjeff
177219820Sjeff	if (boothowto & RB_VERBOSE)
178219820Sjeff		bootverbose++;
179219820Sjeff
180219820Sjeff	/*
181219820Sjeff	 * Initialize error message buffer (at end of core).
182219820Sjeff	 */
183219820Sjeff
184219820Sjeff	/* avail_end was pre-decremented in init_386() to compensate */
185219820Sjeff	for (i = 0; i < btoc(sizeof (struct msgbuf)); i++)
186219820Sjeff		pmap_enter(pmap_kernel(), (vm_offset_t)msgbufp,
187219820Sjeff			   avail_end + i * NBPG,
188219820Sjeff			   VM_PROT_ALL, TRUE);
189219820Sjeff	msgbufmapped = 1;
190219820Sjeff
191219820Sjeff	/*
192219820Sjeff	 * Good {morning,afternoon,evening,night}.
193219820Sjeff	 */
194219820Sjeff	printf(version);
195219820Sjeff	startrtclock();
196219820Sjeff	identifycpu();
197219820Sjeff	printf("real memory  = %d (%d pages)\n", ptoa(physmem), physmem);
198219820Sjeff	if (badpages)
199219820Sjeff		printf("bad memory   = %d (%d pages)\n", ptoa(badpages), badpages);
200219820Sjeff
201219820Sjeff	/*
202219820Sjeff	 * Quickly wire in netisrs.
203219820Sjeff	 */
204219820Sjeff#define DONET(isr, n) do { extern void isr(void); netisrs[n] = isr; } while(0)
205219820Sjeff#ifdef INET
206219820Sjeff#if NETHER > 0
207219820Sjeff	DONET(arpintr, NETISR_ARP);
208219820Sjeff#endif
209219820Sjeff	DONET(ipintr, NETISR_IP);
210219820Sjeff#endif
211219820Sjeff#ifdef NS
212219820Sjeff	DONET(nsintr, NETISR_NS);
213219820Sjeff#endif
214219820Sjeff#ifdef ISO
215219820Sjeff	DONET(clnlintr, NETISR_ISO);
216219820Sjeff#endif
217219820Sjeff#ifdef CCITT
218219820Sjeff	DONET(ccittintr, NETISR_CCITT);
219219820Sjeff#endif
220219820Sjeff#undef DONET
221219820Sjeff
222219820Sjeff	/*
223219820Sjeff	 * Allocate space for system data structures.
224219820Sjeff	 * The first available kernel virtual address is in "v".
225219820Sjeff	 * As pages of kernel virtual memory are allocated, "v" is incremented.
226219820Sjeff	 * As pages of memory are allocated and cleared,
227219820Sjeff	 * "firstaddr" is incremented.
228219820Sjeff	 * An index into the kernel page table corresponding to the
229219820Sjeff	 * virtual memory address maintained in "v" is kept in "mapaddr".
230219820Sjeff	 */
231219820Sjeff
232219820Sjeff	/*
233219820Sjeff	 * Make two passes.  The first pass calculates how much memory is
234219820Sjeff	 * needed and allocates it.  The second pass assigns virtual
235219820Sjeff	 * addresses to the various data structures.
236219820Sjeff	 */
237219820Sjeff	firstaddr = 0;
238219820Sjeffagain:
239219820Sjeff	v = (caddr_t)firstaddr;
240219820Sjeff
241219820Sjeff#define	valloc(name, type, num) \
242219820Sjeff	    (name) = (type *)v; v = (caddr_t)((name)+(num))
243219820Sjeff#define	valloclim(name, type, num, lim) \
244219820Sjeff	    (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num)))
245219820Sjeff	valloc(callout, struct callout, ncallout);
246219820Sjeff#ifdef SYSVSHM
247219820Sjeff	valloc(shmsegs, struct shmid_ds, shminfo.shmmni);
248219820Sjeff#endif
249219820Sjeff#ifdef SYSVSEM
250219820Sjeff	valloc(sema, struct semid_ds, seminfo.semmni);
251219820Sjeff	valloc(sem, struct sem, seminfo.semmns);
252219820Sjeff	/* This is pretty disgusting! */
253219820Sjeff	valloc(semu, int, (seminfo.semmnu * seminfo.semusz) / sizeof(int));
254219820Sjeff#endif
255219820Sjeff#ifdef SYSVMSG
256219820Sjeff	valloc(msgpool, char, msginfo.msgmax);
257219820Sjeff	valloc(msgmaps, struct msgmap, msginfo.msgseg);
258219820Sjeff	valloc(msghdrs, struct msg, msginfo.msgtql);
259219820Sjeff	valloc(msqids, struct msqid_ds, msginfo.msgmni);
260219820Sjeff#endif
261219820Sjeff	/*
262219820Sjeff	 * Determine how many buffers to allocate.
263219820Sjeff	 * Use 20% of memory of memory beyond the first 2MB
264219820Sjeff	 * Insure a minimum of 16 fs buffers.
265219820Sjeff	 * We allocate 1/2 as many swap buffer headers as file i/o buffers.
266219820Sjeff	 */
267219820Sjeff	if (bufpages == 0)
268219820Sjeff		bufpages = ((physmem << PGSHIFT) - 2048*1024) / NBPG / 6;
269219820Sjeff	if (bufpages < 64)
270219820Sjeff		bufpages = 64;
271219820Sjeff
272219820Sjeff	/*
273219820Sjeff	 * We must still limit the maximum number of buffers to be no
274219820Sjeff	 * more than 750 because we'll run out of kernel VM otherwise.
275219820Sjeff	 */
276219820Sjeff	bufpages = min(bufpages, 1500);
277219820Sjeff	if (nbuf == 0) {
278219820Sjeff		nbuf = bufpages / 2;
279219820Sjeff		if (nbuf < 32)
280219820Sjeff			nbuf = 32;
281219820Sjeff	}
282219820Sjeff	freebufspace = bufpages * NBPG;
283219820Sjeff	if (nswbuf == 0) {
284219820Sjeff		nswbuf = (nbuf / 2) &~ 1;	/* force even */
285219820Sjeff		if (nswbuf > 64)
286219820Sjeff			nswbuf = 64;		/* sanity */
287219820Sjeff	}
288219820Sjeff	valloc(swbuf, struct buf, nswbuf);
289219820Sjeff	valloc(buf, struct buf, nbuf);
290219820Sjeff
291219820Sjeff#ifdef BOUNCE_BUFFERS
292219820Sjeff	/*
293219820Sjeff	 * If there is more than 16MB of memory, allocate some bounce buffers
294219820Sjeff	 */
295219820Sjeff	if (Maxmem > 4096) {
296219820Sjeff		if (bouncepages == 0)
297219820Sjeff			bouncepages = 96;	/* largest physio size + extra */
298219820Sjeff		v = (caddr_t)((vm_offset_t)((vm_offset_t)v + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1));
299219820Sjeff		valloc(bouncememory, char, bouncepages * PAGE_SIZE);
300219820Sjeff	}
301219820Sjeff#endif
302219820Sjeff
303219820Sjeff	/*
304219820Sjeff	 * End of first pass, size has been calculated so allocate memory
305219820Sjeff	 */
306219820Sjeff	if (firstaddr == 0) {
307219820Sjeff		size = (vm_size_t)(v - firstaddr);
308219820Sjeff		firstaddr = (int)kmem_alloc(kernel_map, round_page(size));
309219820Sjeff		if (firstaddr == 0)
310219820Sjeff			panic("startup: no room for tables");
311219820Sjeff		goto again;
312219820Sjeff	}
313219820Sjeff
314219820Sjeff	/*
315219820Sjeff	 * End of second pass, addresses have been assigned
316219820Sjeff	 */
317219820Sjeff	if ((vm_size_t)(v - firstaddr) != size)
318219820Sjeff		panic("startup: table size inconsistency");
319219820Sjeff
320219820Sjeff#ifdef BOUNCE_BUFFERS
321219820Sjeff	clean_map = kmem_suballoc(kernel_map, &clean_sva, &clean_eva,
322219820Sjeff			(nbuf*MAXBSIZE) + (nswbuf*MAXPHYS) +
323219820Sjeff				maxbkva + pager_map_size, TRUE);
324219820Sjeff	io_map = kmem_suballoc(clean_map, &minaddr, &maxaddr, maxbkva, FALSE);
325219820Sjeff#else
326219820Sjeff	clean_map = kmem_suballoc(kernel_map, &clean_sva, &clean_eva,
327219820Sjeff			(nbuf*MAXBSIZE) + (nswbuf*MAXPHYS) + pager_map_size, TRUE);
328219820Sjeff#endif
329219820Sjeff	buffer_map = kmem_suballoc(clean_map, &buffer_sva, &buffer_eva,
330219820Sjeff				(nbuf*MAXBSIZE), TRUE);
331219820Sjeff	pager_map = kmem_suballoc(clean_map, &pager_sva, &pager_eva,
332219820Sjeff				(nswbuf*MAXPHYS) + pager_map_size, TRUE);
333219820Sjeff
334219820Sjeff	/*
335219820Sjeff	 * Finally, allocate mbuf pool.  Since mclrefcnt is an off-size
336219820Sjeff	 * we use the more space efficient malloc in place of kmem_alloc.
337219820Sjeff	 */
338219820Sjeff	mclrefcnt = (char *)malloc(NMBCLUSTERS+CLBYTES/MCLBYTES,
339219820Sjeff				   M_MBUF, M_NOWAIT);
340219820Sjeff	bzero(mclrefcnt, NMBCLUSTERS+CLBYTES/MCLBYTES);
341219820Sjeff	mb_map = kmem_suballoc(kmem_map, (vm_offset_t *)&mbutl, &maxaddr,
342219820Sjeff			       VM_MBUF_SIZE, FALSE);
343219820Sjeff	/*
344219820Sjeff	 * Initialize callouts
345219820Sjeff	 */
346219820Sjeff	callfree = callout;
347219820Sjeff	for (i = 1; i < ncallout; i++)
348219820Sjeff		callout[i-1].c_next = &callout[i];
349219820Sjeff
350219820Sjeff        if (boothowto & RB_CONFIG)
351219820Sjeff		userconfig();
352219820Sjeff	printf("avail memory = %d (%d pages)\n", ptoa(cnt.v_free_count), cnt.v_free_count);
353219820Sjeff	printf("using %d buffers containing %d bytes of memory\n",
354219820Sjeff		nbuf, bufpages * CLBYTES);
355219820Sjeff
356219820Sjeff#ifdef BOUNCE_BUFFERS
357219820Sjeff	/*
358219820Sjeff	 * init bounce buffers
359219820Sjeff	 */
360219820Sjeff	vm_bounce_init();
361219820Sjeff#endif
362219820Sjeff
363219820Sjeff	/*
364219820Sjeff	 * Set up CPU-specific registers, cache, etc.
365219820Sjeff	 */
366219820Sjeff	initcpu();
367219820Sjeff
368219820Sjeff	/*
369219820Sjeff	 * Set up buffers, so they can be used to read disk labels.
370219820Sjeff	 */
371219820Sjeff	bufinit();
372219820Sjeff	vm_pager_bufferinit();
373219820Sjeff
374219820Sjeff	/*
375255932Salfred	 * Configure the system.
376255932Salfred	 */
377255932Salfred	configure();
378255932Salfred	if (bootverbose) {
379255932Salfred		printf("BIOS Geometries:");
380255932Salfred		for (i=0; i < N_BIOS_GEOM; i++)
381255932Salfred			printf(" %x:%x\n", i, bootinfo.bios_geom[i]);
382255932Salfred		printf(" %d accounted for\n",bootinfo.n_bios_used);
383255932Salfred	}
384255932Salfred}
385255932Salfred
386255932Salfred
387255932Salfredstruct cpu_nameclass i386_cpus[] = {
388255932Salfred	{ "Intel 80286",	CPUCLASS_286 },		/* CPU_286   */
389255932Salfred	{ "i386SX",		CPUCLASS_386 },		/* CPU_386SX */
390255932Salfred	{ "i386DX",		CPUCLASS_386 },		/* CPU_386   */
391255932Salfred	{ "i486SX",		CPUCLASS_486 },		/* CPU_486SX */
392255932Salfred	{ "i486DX",		CPUCLASS_486 },		/* CPU_486   */
393255932Salfred	{ "Pentium",		CPUCLASS_586 },		/* CPU_586   */
394255932Salfred	{ "Cy486DLC",		CPUCLASS_486 },		/* CPU_486DLC */
395255932Salfred};
396255932Salfred
397219820Sjeffstatic void
398219820Sjeffidentifycpu()
399219820Sjeff{
400219820Sjeff	extern u_long cpu_id;
401219820Sjeff	extern char cpu_vendor[];
402219820Sjeff	printf("CPU: ");
403219820Sjeff	if (cpu >= 0
404219820Sjeff	    && cpu < (sizeof i386_cpus/sizeof(struct cpu_nameclass))) {
405219820Sjeff		printf("%s", i386_cpus[cpu].cpu_name);
406219820Sjeff		cpu_class = i386_cpus[cpu].cpu_class;
407219820Sjeff		strncpy(cpu_model, i386_cpus[cpu].cpu_name, sizeof cpu_model);
408219820Sjeff	} else {
409219820Sjeff		printf("unknown cpu type %d\n", cpu);
410219820Sjeff		panic("startup: bad cpu id");
411219820Sjeff	}
412219820Sjeff	printf(" (");
413219820Sjeff	switch(cpu_class) {
414219820Sjeff	case CPUCLASS_286:
415219820Sjeff		printf("286");
416219820Sjeff		break;
417219820Sjeff	case CPUCLASS_386:
418219820Sjeff		printf("386");
419219820Sjeff		break;
420219820Sjeff	case CPUCLASS_486:
421219820Sjeff		printf("486");
422219820Sjeff		break;
423219820Sjeff	case CPUCLASS_586:
424219820Sjeff		printf("Pentium");
425219820Sjeff		break;
426219820Sjeff	default:
427219820Sjeff		printf("unknown");	/* will panic below... */
428219820Sjeff	}
429219820Sjeff	printf("-class CPU)");
430219820Sjeff#ifdef I586_CPU
431219820Sjeff	if(cpu_class == CPUCLASS_586) {
432219820Sjeff		calibrate_cyclecounter();
433219820Sjeff		printf(" %d MHz", pentium_mhz);
434219820Sjeff	}
435219820Sjeff#endif
436219820Sjeff	if(cpu_id)
437219820Sjeff		printf("  Id = 0x%lx",cpu_id);
438219820Sjeff	if(*cpu_vendor)
439219820Sjeff		printf("  Origin = \"%s\"",cpu_vendor);
440219820Sjeff	printf("\n");	/* cpu speed would be nice, but how? */
441219820Sjeff
442219820Sjeff	/*
443219820Sjeff	 * Now that we have told the user what they have,
444219820Sjeff	 * let them know if that machine type isn't configured.
445219820Sjeff	 */
446219820Sjeff	switch (cpu_class) {
447219820Sjeff	case CPUCLASS_286:	/* a 286 should not make it this far, anyway */
448219820Sjeff#if !defined(I386_CPU) && !defined(I486_CPU) && !defined(I586_CPU)
449219820Sjeff#error This kernel is not configured for one of the supported CPUs
450219820Sjeff#endif
451219820Sjeff#if !defined(I386_CPU)
452219820Sjeff	case CPUCLASS_386:
453219820Sjeff#endif
454219820Sjeff#if !defined(I486_CPU)
455219820Sjeff	case CPUCLASS_486:
456219820Sjeff#endif
457219820Sjeff#if !defined(I586_CPU)
458219820Sjeff	case CPUCLASS_586:
459219820Sjeff#endif
460219820Sjeff		panic("CPU class not configured");
461219820Sjeff	default:
462219820Sjeff		break;
463219820Sjeff	}
464219820Sjeff}
465219820Sjeff
466219820Sjeff#ifdef PGINPROF
467219820Sjeff/*
468219820Sjeff * Return the difference (in microseconds)
469219820Sjeff * between the  current time and a previous
470219820Sjeff * time as represented  by the arguments.
471219820Sjeff * If there is a pending clock interrupt
472219820Sjeff * which has not been serviced due to high
473219820Sjeff * ipl, return error code.
474219820Sjeff */
475219820Sjeff/*ARGSUSED*/
476219820Sjeffvmtime(otime, olbolt, oicr)
477219820Sjeff	register int otime, olbolt, oicr;
478219820Sjeff{
479219820Sjeff
480219820Sjeff	return (((time.tv_sec-otime)*60 + lbolt-olbolt)*16667);
481219820Sjeff}
482219820Sjeff#endif
483219820Sjeff
484219820Sjeffextern int kstack[];
485219820Sjeff
486219820Sjeff/*
487219820Sjeff * Send an interrupt to process.
488219820Sjeff *
489219820Sjeff * Stack is set up to allow sigcode stored
490219820Sjeff * in u. to call routine, followed by kcall
491219820Sjeff * to sigreturn routine below.  After sigreturn
492219820Sjeff * resets the signal mask, the stack, and the
493219820Sjeff * frame pointer, it returns to the user
494219820Sjeff * specified pc, psl.
495219820Sjeff */
496219820Sjeffvoid
497219820Sjeffsendsig(catcher, sig, mask, code)
498219820Sjeff	sig_t catcher;
499219820Sjeff	int sig, mask;
500219820Sjeff	unsigned code;
501219820Sjeff{
502219820Sjeff	register struct proc *p = curproc;
503219820Sjeff	register int *regs;
504219820Sjeff	register struct sigframe *fp;
505219820Sjeff	struct sigacts *psp = p->p_sigacts;
506219820Sjeff	int oonstack;
507219820Sjeff
508219820Sjeff	regs = p->p_md.md_regs;
509219820Sjeff        oonstack = psp->ps_sigstk.ss_flags & SA_ONSTACK;
510219820Sjeff	/*
511219820Sjeff	 * Allocate and validate space for the signal handler
512219820Sjeff	 * context. Note that if the stack is in P0 space, the
513219820Sjeff	 * call to grow() is a nop, and the useracc() check
514219820Sjeff	 * will fail if the process has not already allocated
515219820Sjeff	 * the space with a `brk'.
516219820Sjeff	 */
517219820Sjeff        if ((psp->ps_flags & SAS_ALTSTACK) &&
518219820Sjeff	    (psp->ps_sigstk.ss_flags & SA_ONSTACK) == 0 &&
519219820Sjeff	    (psp->ps_sigonstack & sigmask(sig))) {
520219820Sjeff		fp = (struct sigframe *)(psp->ps_sigstk.ss_base +
521219820Sjeff		    psp->ps_sigstk.ss_size - sizeof(struct sigframe));
522219820Sjeff		psp->ps_sigstk.ss_flags |= SA_ONSTACK;
523219820Sjeff	} else {
524219820Sjeff		fp = (struct sigframe *)(regs[tESP]
525219820Sjeff			- sizeof(struct sigframe));
526219820Sjeff	}
527219820Sjeff
528219820Sjeff	/*
529219820Sjeff	 * grow() will return FALSE if the fp will not fit inside the stack
530219820Sjeff	 *	and the stack can not be grown. useracc will return FALSE
531219820Sjeff	 *	if access is denied.
532219820Sjeff	 */
533219820Sjeff	if ((grow(p, (int)fp) == FALSE) ||
534219820Sjeff	    (useracc((caddr_t)fp, sizeof (struct sigframe), B_WRITE) == FALSE)) {
535219820Sjeff		/*
536219820Sjeff		 * Process has trashed its stack; give it an illegal
537219820Sjeff		 * instruction to halt it in its tracks.
538219820Sjeff		 */
539219820Sjeff		SIGACTION(p, SIGILL) = SIG_DFL;
540219820Sjeff		sig = sigmask(SIGILL);
541219820Sjeff		p->p_sigignore &= ~sig;
542219820Sjeff		p->p_sigcatch &= ~sig;
543219820Sjeff		p->p_sigmask &= ~sig;
544219820Sjeff		psignal(p, SIGILL);
545219820Sjeff		return;
546219820Sjeff	}
547219820Sjeff
548219820Sjeff	/*
549219820Sjeff	 * Build the argument list for the signal handler.
550219820Sjeff	 */
551219820Sjeff	if (p->p_sysent->sv_sigtbl) {
552219820Sjeff		if (sig < p->p_sysent->sv_sigsize)
553219820Sjeff			sig = p->p_sysent->sv_sigtbl[sig];
554219820Sjeff		else
555219820Sjeff			sig = p->p_sysent->sv_sigsize + 1;
556219820Sjeff	}
557219820Sjeff	fp->sf_signum = sig;
558219820Sjeff	fp->sf_code = code;
559219820Sjeff	fp->sf_scp = &fp->sf_sc;
560219820Sjeff	fp->sf_addr = (char *) regs[tERR];
561219820Sjeff	fp->sf_handler = catcher;
562219820Sjeff
563219820Sjeff	/* save scratch registers */
564219820Sjeff	fp->sf_sc.sc_eax = regs[tEAX];
565219820Sjeff	fp->sf_sc.sc_ebx = regs[tEBX];
566219820Sjeff	fp->sf_sc.sc_ecx = regs[tECX];
567219820Sjeff	fp->sf_sc.sc_edx = regs[tEDX];
568219820Sjeff	fp->sf_sc.sc_esi = regs[tESI];
569219820Sjeff	fp->sf_sc.sc_edi = regs[tEDI];
570219820Sjeff	fp->sf_sc.sc_cs = regs[tCS];
571219820Sjeff	fp->sf_sc.sc_ds = regs[tDS];
572219820Sjeff	fp->sf_sc.sc_ss = regs[tSS];
573219820Sjeff	fp->sf_sc.sc_es = regs[tES];
574219820Sjeff	fp->sf_sc.sc_isp = regs[tISP];
575219820Sjeff
576219820Sjeff	/*
577219820Sjeff	 * Build the signal context to be used by sigreturn.
578219820Sjeff	 */
579219820Sjeff	fp->sf_sc.sc_onstack = oonstack;
580219820Sjeff	fp->sf_sc.sc_mask = mask;
581255932Salfred	fp->sf_sc.sc_sp = regs[tESP];
582255932Salfred	fp->sf_sc.sc_fp = regs[tEBP];
583255932Salfred	fp->sf_sc.sc_pc = regs[tEIP];
584255932Salfred	fp->sf_sc.sc_ps = regs[tEFLAGS];
585255932Salfred	regs[tESP] = (int)fp;
586255932Salfred	regs[tEIP] = (int)((struct pcb *)kstack)->pcb_sigc;
587255932Salfred	regs[tEFLAGS] &= ~PSL_VM;
588255932Salfred	regs[tCS] = _ucodesel;
589255932Salfred	regs[tDS] = _udatasel;
590255932Salfred	regs[tES] = _udatasel;
591255932Salfred	regs[tSS] = _udatasel;
592255932Salfred}
593219820Sjeff
594/*
595 * System call to cleanup state after a signal
596 * has been taken.  Reset signal mask and
597 * stack state from context left by sendsig (above).
598 * Return to previous pc and psl as specified by
599 * context left by sendsig. Check carefully to
600 * make sure that the user has not modified the
601 * psl to gain improper privileges or to cause
602 * a machine fault.
603 */
604struct sigreturn_args {
605	struct sigcontext *sigcntxp;
606};
607
608int
609sigreturn(p, uap, retval)
610	struct proc *p;
611	struct sigreturn_args *uap;
612	int *retval;
613{
614	register struct sigcontext *scp;
615	register struct sigframe *fp;
616	register int *regs = p->p_md.md_regs;
617	int eflags;
618
619	/*
620	 * (XXX old comment) regs[tESP] points to the return address.
621	 * The user scp pointer is above that.
622	 * The return address is faked in the signal trampoline code
623	 * for consistency.
624	 */
625	scp = uap->sigcntxp;
626	fp = (struct sigframe *)
627	     ((caddr_t)scp - offsetof(struct sigframe, sf_sc));
628
629	if (useracc((caddr_t)fp, sizeof (*fp), 0) == 0)
630		return(EINVAL);
631
632	eflags = scp->sc_ps;
633	if ((eflags & PSL_USERCLR) != 0 ||
634	    (eflags & PSL_USERSET) != PSL_USERSET ||
635	    (eflags & PSL_IOPL) < (regs[tEFLAGS] & PSL_IOPL)) {
636#ifdef DEBUG
637    		printf("sigreturn:  eflags=0x%x\n", eflags);
638#endif
639    		return(EINVAL);
640	}
641
642	/*
643	 * Sanity check the user's selectors and error if they
644	 * are suspect.
645	 */
646#define max_ldt_sel(pcb) \
647	((pcb)->pcb_ldt ? (pcb)->pcb_ldt_len : (sizeof(ldt) / sizeof(ldt[0])))
648
649#define valid_ldt_sel(sel) \
650	(ISLDT(sel) && ISPL(sel) == SEL_UPL && \
651	 IDXSEL(sel) < max_ldt_sel(&p->p_addr->u_pcb))
652
653#define null_sel(sel) \
654	(!ISLDT(sel) && IDXSEL(sel) == 0)
655
656	if (((scp->sc_cs&0xffff) != _ucodesel && !valid_ldt_sel(scp->sc_cs)) ||
657	    ((scp->sc_ss&0xffff) != _udatasel && !valid_ldt_sel(scp->sc_ss)) ||
658	    ((scp->sc_ds&0xffff) != _udatasel && !valid_ldt_sel(scp->sc_ds) &&
659	     !null_sel(scp->sc_ds)) ||
660	    ((scp->sc_es&0xffff) != _udatasel && !valid_ldt_sel(scp->sc_es) &&
661	     !null_sel(scp->sc_es))) {
662#ifdef DEBUG
663    		printf("sigreturn:  cs=0x%x ss=0x%x ds=0x%x es=0x%x\n",
664			scp->sc_cs, scp->sc_ss, scp->sc_ds, scp->sc_es);
665#endif
666		trapsignal(p, SIGBUS, T_PROTFLT);
667		return(EINVAL);
668	}
669
670#undef max_ldt_sel
671#undef valid_ldt_sel
672#undef null_sel
673
674	/* restore scratch registers */
675	regs[tEAX] = scp->sc_eax;
676	regs[tEBX] = scp->sc_ebx;
677	regs[tECX] = scp->sc_ecx;
678	regs[tEDX] = scp->sc_edx;
679	regs[tESI] = scp->sc_esi;
680	regs[tEDI] = scp->sc_edi;
681	regs[tCS] = scp->sc_cs;
682	regs[tDS] = scp->sc_ds;
683	regs[tES] = scp->sc_es;
684	regs[tSS] = scp->sc_ss;
685	regs[tISP] = scp->sc_isp;
686
687	if (useracc((caddr_t)scp, sizeof (*scp), 0) == 0)
688		return(EINVAL);
689
690	if (scp->sc_onstack & 01)
691		p->p_sigacts->ps_sigstk.ss_flags |= SA_ONSTACK;
692	else
693		p->p_sigacts->ps_sigstk.ss_flags &= ~SA_ONSTACK;
694	p->p_sigmask = scp->sc_mask &~
695	    (sigmask(SIGKILL)|sigmask(SIGCONT)|sigmask(SIGSTOP));
696	regs[tEBP] = scp->sc_fp;
697	regs[tESP] = scp->sc_sp;
698	regs[tEIP] = scp->sc_pc;
699	regs[tEFLAGS] = eflags;
700	return(EJUSTRETURN);
701}
702
703/*
704 * a simple function to make the system panic (and dump a vmcore)
705 * in a predictable fashion
706 */
707void diediedie()
708{
709	panic("because you said to!");
710}
711
712int	waittime = -1;
713struct pcb dumppcb;
714
715__dead void
716boot(arghowto)
717	int arghowto;
718{
719	register long dummy;		/* r12 is reserved */
720	register int howto;		/* r11 == how to boot */
721	register int devtype;		/* r10 == major of root dev */
722	extern int cold;
723
724	if (cold) {
725		printf("hit reset please");
726		for(;;);
727	}
728	howto = arghowto;
729	if ((howto&RB_NOSYNC) == 0 && waittime < 0) {
730		register struct buf *bp;
731		int iter, nbusy;
732
733		waittime = 0;
734		printf("\nsyncing disks... ");
735		/*
736		 * Release inodes held by texts before update.
737		 */
738		if (panicstr == 0)
739			vnode_pager_umount(NULL);
740		sync(curproc, NULL, NULL);
741
742		for (iter = 0; iter < 20; iter++) {
743			nbusy = 0;
744			for (bp = &buf[nbuf]; --bp >= buf; )
745				if ((bp->b_flags & (B_BUSY|B_INVAL)) == B_BUSY)
746					nbusy++;
747			if (nbusy == 0)
748				break;
749			printf("%d ", nbusy);
750			DELAY(40000 * iter);
751		}
752		if (nbusy) {
753			/*
754			 * Failed to sync all blocks. Indicate this and don't
755			 * unmount filesystems (thus forcing an fsck on reboot).
756			 */
757			printf("giving up\n");
758		} else {
759			printf("done\n");
760			/*
761			 * Unmount filesystems
762			 */
763			if (panicstr == 0)
764				vfs_unmountall();
765		}
766		DELAY(100000);			/* wait for console output to finish */
767	}
768	splhigh();
769	devtype = major(rootdev);
770	if (howto&RB_HALT) {
771		printf("\n");
772		printf("The operating system has halted.\n");
773		printf("Please press any key to reboot.\n\n");
774		cngetc();
775	} else {
776		if (howto & RB_DUMP) {
777			savectx(&dumppcb, 0);
778			dumppcb.pcb_ptd = rcr3();
779			dumpsys();
780
781			if (PANIC_REBOOT_WAIT_TIME != 0) {
782				if (PANIC_REBOOT_WAIT_TIME != -1) {
783					int loop;
784					printf("Automatic reboot in %d seconds - press a key on the console to abort\n",
785						PANIC_REBOOT_WAIT_TIME);
786					for (loop = PANIC_REBOOT_WAIT_TIME; loop > 0; --loop) {
787						DELAY(1000 * 1000); /* one second */
788						if (cncheckc()) /* Did user type a key? */
789							break;
790					}
791					if (!loop)
792						goto die;
793				}
794			} else { /* zero time specified - reboot NOW */
795				goto die;
796			}
797			printf("--> Press a key on the console to reboot <--\n");
798			cngetc();
799		}
800	}
801#ifdef lint
802	dummy = 0; dummy = dummy;
803	printf("howto %d, devtype %d\n", arghowto, devtype);
804#endif
805die:
806	printf("Rebooting...\n");
807	DELAY(1000000);	/* wait 1 sec for printf's to complete and be read */
808	cpu_reset();
809	for(;;) ;
810	/* NOTREACHED */
811}
812
813unsigned long	dumpmag = 0x8fca0101UL;	/* magic number for savecore */
814int		dumpsize = 0;		/* also for savecore */
815
816#ifdef DODUMP
817int		dodump = 1;
818#else
819int		dodump = 0;
820#endif
821/*
822 * Doadump comes here after turning off memory management and
823 * getting on the dump stack, either when called above, or by
824 * the auto-restart code.
825 */
826void
827dumpsys()
828{
829
830	if (!dodump)
831		return;
832	if (dumpdev == NODEV)
833		return;
834	if ((minor(dumpdev)&07) != 1)
835		return;
836	dumpsize = Maxmem;
837	printf("\ndumping to dev %lx, offset %ld\n", dumpdev, dumplo);
838	printf("dump ");
839	switch ((*bdevsw[major(dumpdev)].d_dump)(dumpdev)) {
840
841	case ENXIO:
842		printf("device bad\n");
843		break;
844
845	case EFAULT:
846		printf("device not ready\n");
847		break;
848
849	case EINVAL:
850		printf("area improper\n");
851		break;
852
853	case EIO:
854		printf("i/o error\n");
855		break;
856
857	case EINTR:
858		printf("aborted from console\n");
859		break;
860
861	default:
862		printf("succeeded\n");
863		break;
864	}
865}
866
867static void
868initcpu()
869{
870}
871
872/*
873 * Clear registers on exec
874 */
875void
876setregs(p, entry, stack)
877	struct proc *p;
878	u_long entry;
879	u_long stack;
880{
881	int *regs = p->p_md.md_regs;
882
883	bzero(regs, sizeof(struct trapframe));
884	regs[tEIP] = entry;
885	regs[tESP] = stack;
886	regs[tEFLAGS] = PSL_USERSET | (regs[tEFLAGS] & PSL_T);
887	regs[tSS] = _udatasel;
888	regs[tDS] = _udatasel;
889	regs[tES] = _udatasel;
890	regs[tCS] = _ucodesel;
891
892	p->p_addr->u_pcb.pcb_flags = 0;	/* no fp at all */
893	load_cr0(rcr0() | CR0_TS);	/* start emulating */
894#if	NNPX > 0
895	npxinit(__INITIAL_NPXCW__);
896#endif	/* NNPX > 0 */
897}
898
899/*
900 * machine dependent system variables.
901 */
902int
903cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
904	int *name;
905	u_int namelen;
906	void *oldp;
907	size_t *oldlenp;
908	void *newp;
909	size_t newlen;
910	struct proc *p;
911{
912	int error;
913
914	/* all sysctl names at this level are terminal */
915	if (namelen != 1)
916		return (ENOTDIR);               /* overloaded */
917
918	switch (name[0]) {
919	case CPU_CONSDEV:
920		return (sysctl_rdstruct(oldp, oldlenp, newp, &cn_tty->t_dev,
921		   sizeof cn_tty->t_dev));
922	case CPU_ADJKERNTZ:
923		error = sysctl_int(oldp, oldlenp, newp, newlen, &adjkerntz);
924		if (!error && newp)
925			resettodr();
926		return error;
927	case CPU_DISRTCSET:
928		return (sysctl_int(oldp, oldlenp, newp,	newlen,	&disable_rtc_set));
929	default:
930		return (EOPNOTSUPP);
931	}
932	/* NOTREACHED */
933}
934
935/*
936 * Initialize 386 and configure to run kernel
937 */
938
939/*
940 * Initialize segments & interrupt table
941 */
942
943int currentldt;
944int _default_ldt;
945union descriptor gdt[NGDT];		/* global descriptor table */
946struct gate_descriptor idt[NIDT];	/* interrupt descriptor table */
947union descriptor ldt[NLDT];		/* local descriptor table */
948
949struct	i386tss	tss, panic_tss;
950
951extern  struct user *proc0paddr;
952
953/* software prototypes -- in more palatable form */
954struct soft_segment_descriptor gdt_segs[] = {
955/* GNULL_SEL	0 Null Descriptor */
956{	0x0,			/* segment base address  */
957	0x0,			/* length */
958	0,			/* segment type */
959	0,			/* segment descriptor priority level */
960	0,			/* segment descriptor present */
961	0, 0,
962	0,			/* default 32 vs 16 bit size */
963	0  			/* limit granularity (byte/page units)*/ },
964/* GCODE_SEL	1 Code Descriptor for kernel */
965{	0x0,			/* segment base address  */
966	0xfffff,		/* length - all address space */
967	SDT_MEMERA,		/* segment type */
968	0,			/* segment descriptor priority level */
969	1,			/* segment descriptor present */
970	0, 0,
971	1,			/* default 32 vs 16 bit size */
972	1  			/* limit granularity (byte/page units)*/ },
973/* GDATA_SEL	2 Data Descriptor for kernel */
974{	0x0,			/* segment base address  */
975	0xfffff,		/* length - all address space */
976	SDT_MEMRWA,		/* segment type */
977	0,			/* segment descriptor priority level */
978	1,			/* segment descriptor present */
979	0, 0,
980	1,			/* default 32 vs 16 bit size */
981	1  			/* limit granularity (byte/page units)*/ },
982/* GLDT_SEL	3 LDT Descriptor */
983{	(int) ldt,		/* segment base address  */
984	sizeof(ldt)-1,		/* length - all address space */
985	SDT_SYSLDT,		/* segment type */
986	0,			/* segment descriptor priority level */
987	1,			/* segment descriptor present */
988	0, 0,
989	0,			/* unused - default 32 vs 16 bit size */
990	0  			/* limit granularity (byte/page units)*/ },
991/* GTGATE_SEL	4 Null Descriptor - Placeholder */
992{	0x0,			/* segment base address  */
993	0x0,			/* length - all address space */
994	0,			/* segment type */
995	0,			/* segment descriptor priority level */
996	0,			/* segment descriptor present */
997	0, 0,
998	0,			/* default 32 vs 16 bit size */
999	0  			/* limit granularity (byte/page units)*/ },
1000/* GPANIC_SEL	5 Panic Tss Descriptor */
1001{	(int) &panic_tss,	/* segment base address  */
1002	sizeof(tss)-1,		/* length - all address space */
1003	SDT_SYS386TSS,		/* segment type */
1004	0,			/* segment descriptor priority level */
1005	1,			/* segment descriptor present */
1006	0, 0,
1007	0,			/* unused - default 32 vs 16 bit size */
1008	0  			/* limit granularity (byte/page units)*/ },
1009/* GPROC0_SEL	6 Proc 0 Tss Descriptor */
1010{	(int) kstack,		/* segment base address  */
1011	sizeof(tss)-1,		/* length - all address space */
1012	SDT_SYS386TSS,		/* segment type */
1013	0,			/* segment descriptor priority level */
1014	1,			/* segment descriptor present */
1015	0, 0,
1016	0,			/* unused - default 32 vs 16 bit size */
1017	0  			/* limit granularity (byte/page units)*/ },
1018/* GUSERLDT_SEL	7 User LDT Descriptor per process */
1019{	(int) ldt,		/* segment base address  */
1020	(512 * sizeof(union descriptor)-1),		/* length */
1021	SDT_SYSLDT,		/* segment type */
1022	0,			/* segment descriptor priority level */
1023	1,			/* segment descriptor present */
1024	0, 0,
1025	0,			/* unused - default 32 vs 16 bit size */
1026	0  			/* limit granularity (byte/page units)*/ },
1027/* GAPMCODE32_SEL 8 APM BIOS 32-bit interface (32bit Code) */
1028{	0,			/* segment base address (overwritten by APM)  */
1029	0xfffff,		/* length */
1030	SDT_MEMERA,		/* segment type */
1031	0,			/* segment descriptor priority level */
1032	1,			/* segment descriptor present */
1033	0, 0,
1034	1,			/* default 32 vs 16 bit size */
1035	1  			/* limit granularity (byte/page units)*/ },
1036/* GAPMCODE16_SEL 9 APM BIOS 32-bit interface (16bit Code) */
1037{	0,			/* segment base address (overwritten by APM)  */
1038	0xfffff,		/* length */
1039	SDT_MEMERA,		/* segment type */
1040	0,			/* segment descriptor priority level */
1041	1,			/* segment descriptor present */
1042	0, 0,
1043	0,			/* default 32 vs 16 bit size */
1044	1  			/* limit granularity (byte/page units)*/ },
1045/* GAPMDATA_SEL	10 APM BIOS 32-bit interface (Data) */
1046{	0,			/* segment base address (overwritten by APM) */
1047	0xfffff,		/* length */
1048	SDT_MEMRWA,		/* segment type */
1049	0,			/* segment descriptor priority level */
1050	1,			/* segment descriptor present */
1051	0, 0,
1052	1,			/* default 32 vs 16 bit size */
1053	1  			/* limit granularity (byte/page units)*/ },
1054};
1055
1056struct soft_segment_descriptor ldt_segs[] = {
1057	/* Null Descriptor - overwritten by call gate */
1058{	0x0,			/* segment base address  */
1059	0x0,			/* length - all address space */
1060	0,			/* segment type */
1061	0,			/* segment descriptor priority level */
1062	0,			/* segment descriptor present */
1063	0, 0,
1064	0,			/* default 32 vs 16 bit size */
1065	0  			/* limit granularity (byte/page units)*/ },
1066	/* Null Descriptor - overwritten by call gate */
1067{	0x0,			/* segment base address  */
1068	0x0,			/* length - all address space */
1069	0,			/* segment type */
1070	0,			/* segment descriptor priority level */
1071	0,			/* segment descriptor present */
1072	0, 0,
1073	0,			/* default 32 vs 16 bit size */
1074	0  			/* limit granularity (byte/page units)*/ },
1075	/* Null Descriptor - overwritten by call gate */
1076{	0x0,			/* segment base address  */
1077	0x0,			/* length - all address space */
1078	0,			/* segment type */
1079	0,			/* segment descriptor priority level */
1080	0,			/* segment descriptor present */
1081	0, 0,
1082	0,			/* default 32 vs 16 bit size */
1083	0  			/* limit granularity (byte/page units)*/ },
1084	/* Code Descriptor for user */
1085{	0x0,			/* segment base address  */
1086	0xfffff,		/* length - all address space */
1087	SDT_MEMERA,		/* segment type */
1088	SEL_UPL,		/* segment descriptor priority level */
1089	1,			/* segment descriptor present */
1090	0, 0,
1091	1,			/* default 32 vs 16 bit size */
1092	1  			/* limit granularity (byte/page units)*/ },
1093	/* Data Descriptor for user */
1094{	0x0,			/* segment base address  */
1095	0xfffff,		/* length - all address space */
1096	SDT_MEMRWA,		/* segment type */
1097	SEL_UPL,		/* segment descriptor priority level */
1098	1,			/* segment descriptor present */
1099	0, 0,
1100	1,			/* default 32 vs 16 bit size */
1101	1  			/* limit granularity (byte/page units)*/ },
1102};
1103
1104void
1105setidt(idx, func, typ, dpl)
1106	int idx;
1107	inthand_t *func;
1108	int typ;
1109	int dpl;
1110{
1111	struct gate_descriptor *ip = idt + idx;
1112
1113	ip->gd_looffset = (int)func;
1114	ip->gd_selector = 8;
1115	ip->gd_stkcpy = 0;
1116	ip->gd_xx = 0;
1117	ip->gd_type = typ;
1118	ip->gd_dpl = dpl;
1119	ip->gd_p = 1;
1120	ip->gd_hioffset = ((int)func)>>16 ;
1121}
1122
1123#define	IDTVEC(name)	__CONCAT(X,name)
1124
1125extern inthand_t
1126	IDTVEC(div), IDTVEC(dbg), IDTVEC(nmi), IDTVEC(bpt), IDTVEC(ofl),
1127	IDTVEC(bnd), IDTVEC(ill), IDTVEC(dna), IDTVEC(dble), IDTVEC(fpusegm),
1128	IDTVEC(tss), IDTVEC(missing), IDTVEC(stk), IDTVEC(prot),
1129	IDTVEC(page), IDTVEC(rsvd), IDTVEC(fpu), IDTVEC(rsvd0),
1130	IDTVEC(rsvd1), IDTVEC(rsvd2), IDTVEC(rsvd3), IDTVEC(rsvd4),
1131	IDTVEC(rsvd5), IDTVEC(rsvd6), IDTVEC(rsvd7), IDTVEC(rsvd8),
1132	IDTVEC(rsvd9), IDTVEC(rsvd10), IDTVEC(rsvd11), IDTVEC(rsvd12),
1133	IDTVEC(rsvd13), IDTVEC(rsvd14), IDTVEC(syscall);
1134
1135void
1136sdtossd(sd, ssd)
1137	struct segment_descriptor *sd;
1138	struct soft_segment_descriptor *ssd;
1139{
1140	ssd->ssd_base  = (sd->sd_hibase << 24) | sd->sd_lobase;
1141	ssd->ssd_limit = (sd->sd_hilimit << 16) | sd->sd_lolimit;
1142	ssd->ssd_type  = sd->sd_type;
1143	ssd->ssd_dpl   = sd->sd_dpl;
1144	ssd->ssd_p     = sd->sd_p;
1145	ssd->ssd_def32 = sd->sd_def32;
1146	ssd->ssd_gran  = sd->sd_gran;
1147}
1148
1149void
1150init386(first)
1151	int first;
1152{
1153	extern char etext[];
1154	int x;
1155	unsigned biosbasemem, biosextmem;
1156	struct gate_descriptor *gdp;
1157	int gsel_tss;
1158	extern int sigcode,szsigcode;
1159	/* table descriptors - used to load tables by microp */
1160	struct region_descriptor r_gdt, r_idt;
1161	int	pagesinbase, pagesinext;
1162	int	target_page;
1163	extern struct pte *CMAP1;
1164	extern caddr_t CADDR1;
1165
1166	proc0.p_addr = proc0paddr;
1167
1168	/*
1169	 * Initialize the console before we print anything out.
1170	 */
1171
1172	cninit ();
1173
1174	/*
1175	 * make gdt memory segments, the code segment goes up to end of the
1176	 * page with etext in it, the data segment goes to the end of
1177	 * the address space
1178	 */
1179	/*
1180	 * XXX text protection is temporarily (?) disabled.  The limit was
1181	 * i386_btop(i386_round_page(etext)) - 1.
1182	 */
1183	gdt_segs[GCODE_SEL].ssd_limit = i386_btop(0) - 1;
1184	gdt_segs[GDATA_SEL].ssd_limit = i386_btop(0) - 1;
1185	for (x = 0; x < NGDT; x++)
1186		ssdtosd(&gdt_segs[x], &gdt[x].sd);
1187
1188	/* make ldt memory segments */
1189	/*
1190	 * The data segment limit must not cover the user area because we
1191	 * don't want the user area to be writable in copyout() etc. (page
1192	 * level protection is lost in kernel mode on 386's).  Also, we
1193	 * don't want the user area to be writable directly (page level
1194	 * protection of the user area is not available on 486's with
1195	 * CR0_WP set, because there is no user-read/kernel-write mode).
1196	 *
1197	 * XXX - VM_MAXUSER_ADDRESS is an end address, not a max.  And it
1198	 * should be spelled ...MAX_USER...
1199	 */
1200#define VM_END_USER_RW_ADDRESS	VM_MAXUSER_ADDRESS
1201	/*
1202	 * The code segment limit has to cover the user area until we move
1203	 * the signal trampoline out of the user area.  This is safe because
1204	 * the code segment cannot be written to directly.
1205	 */
1206#define VM_END_USER_R_ADDRESS	(VM_END_USER_RW_ADDRESS + UPAGES * NBPG)
1207	ldt_segs[LUCODE_SEL].ssd_limit = i386_btop(VM_END_USER_R_ADDRESS) - 1;
1208	ldt_segs[LUDATA_SEL].ssd_limit = i386_btop(VM_END_USER_RW_ADDRESS) - 1;
1209	/* Note. eventually want private ldts per process */
1210	for (x = 0; x < NLDT; x++)
1211		ssdtosd(&ldt_segs[x], &ldt[x].sd);
1212
1213	/* exceptions */
1214	setidt(0, &IDTVEC(div),  SDT_SYS386TGT, SEL_KPL);
1215	setidt(1, &IDTVEC(dbg),  SDT_SYS386TGT, SEL_KPL);
1216	setidt(2, &IDTVEC(nmi),  SDT_SYS386TGT, SEL_KPL);
1217 	setidt(3, &IDTVEC(bpt),  SDT_SYS386TGT, SEL_UPL);
1218	setidt(4, &IDTVEC(ofl),  SDT_SYS386TGT, SEL_UPL);
1219	setidt(5, &IDTVEC(bnd),  SDT_SYS386TGT, SEL_KPL);
1220	setidt(6, &IDTVEC(ill),  SDT_SYS386TGT, SEL_KPL);
1221	setidt(7, &IDTVEC(dna),  SDT_SYS386TGT, SEL_KPL);
1222	setidt(8, &IDTVEC(dble),  SDT_SYS386TGT, SEL_KPL);
1223	setidt(9, &IDTVEC(fpusegm),  SDT_SYS386TGT, SEL_KPL);
1224	setidt(10, &IDTVEC(tss),  SDT_SYS386TGT, SEL_KPL);
1225	setidt(11, &IDTVEC(missing),  SDT_SYS386TGT, SEL_KPL);
1226	setidt(12, &IDTVEC(stk),  SDT_SYS386TGT, SEL_KPL);
1227	setidt(13, &IDTVEC(prot),  SDT_SYS386TGT, SEL_KPL);
1228	setidt(14, &IDTVEC(page),  SDT_SYS386TGT, SEL_KPL);
1229	setidt(15, &IDTVEC(rsvd),  SDT_SYS386TGT, SEL_KPL);
1230	setidt(16, &IDTVEC(fpu),  SDT_SYS386TGT, SEL_KPL);
1231	setidt(17, &IDTVEC(rsvd0),  SDT_SYS386TGT, SEL_KPL);
1232	setidt(18, &IDTVEC(rsvd1),  SDT_SYS386TGT, SEL_KPL);
1233	setidt(19, &IDTVEC(rsvd2),  SDT_SYS386TGT, SEL_KPL);
1234	setidt(20, &IDTVEC(rsvd3),  SDT_SYS386TGT, SEL_KPL);
1235	setidt(21, &IDTVEC(rsvd4),  SDT_SYS386TGT, SEL_KPL);
1236	setidt(22, &IDTVEC(rsvd5),  SDT_SYS386TGT, SEL_KPL);
1237	setidt(23, &IDTVEC(rsvd6),  SDT_SYS386TGT, SEL_KPL);
1238	setidt(24, &IDTVEC(rsvd7),  SDT_SYS386TGT, SEL_KPL);
1239	setidt(25, &IDTVEC(rsvd8),  SDT_SYS386TGT, SEL_KPL);
1240	setidt(26, &IDTVEC(rsvd9),  SDT_SYS386TGT, SEL_KPL);
1241	setidt(27, &IDTVEC(rsvd10),  SDT_SYS386TGT, SEL_KPL);
1242	setidt(28, &IDTVEC(rsvd11),  SDT_SYS386TGT, SEL_KPL);
1243	setidt(29, &IDTVEC(rsvd12),  SDT_SYS386TGT, SEL_KPL);
1244	setidt(30, &IDTVEC(rsvd13),  SDT_SYS386TGT, SEL_KPL);
1245	setidt(31, &IDTVEC(rsvd14),  SDT_SYS386TGT, SEL_KPL);
1246
1247#include	"isa.h"
1248#if	NISA >0
1249	isa_defaultirq();
1250#endif
1251
1252	r_gdt.rd_limit = sizeof(gdt) - 1;
1253	r_gdt.rd_base =  (int) gdt;
1254	lgdt(&r_gdt);
1255
1256	r_idt.rd_limit = sizeof(idt) - 1;
1257	r_idt.rd_base = (int) idt;
1258	lidt(&r_idt);
1259
1260	_default_ldt = GSEL(GLDT_SEL, SEL_KPL);
1261	lldt(_default_ldt);
1262	currentldt = _default_ldt;
1263
1264#ifdef DDB
1265	kdb_init();
1266	if (boothowto & RB_KDB)
1267		Debugger("Boot flags requested debugger");
1268#endif
1269
1270	/* Use BIOS values stored in RTC CMOS RAM, since probing
1271	 * breaks certain 386 AT relics.
1272	 */
1273	biosbasemem = rtcin(RTC_BASELO)+ (rtcin(RTC_BASEHI)<<8);
1274	biosextmem = rtcin(RTC_EXTLO)+ (rtcin(RTC_EXTHI)<<8);
1275
1276	/*
1277	 * If BIOS tells us that it has more than 640k in the basemem,
1278	 *	don't believe it - set it to 640k.
1279	 */
1280	if (biosbasemem > 640)
1281		biosbasemem = 640;
1282
1283	/*
1284	 * Some 386 machines might give us a bogus number for extended
1285	 *	mem. If this happens, stop now.
1286	 */
1287#ifndef LARGEMEM
1288	if (biosextmem > 65536) {
1289		panic("extended memory beyond limit of 64MB");
1290		/* NOTREACHED */
1291	}
1292#endif
1293
1294	pagesinbase = biosbasemem * 1024 / NBPG;
1295	pagesinext = biosextmem * 1024 / NBPG;
1296
1297	/*
1298	 * Special hack for chipsets that still remap the 384k hole when
1299	 *	there's 16MB of memory - this really confuses people that
1300	 *	are trying to use bus mastering ISA controllers with the
1301	 *	"16MB limit"; they only have 16MB, but the remapping puts
1302	 *	them beyond the limit.
1303	 * XXX - this should be removed when bounce buffers are
1304	 *	implemented.
1305	 */
1306	/*
1307	 * If extended memory is between 15-16MB (16-17MB phys address range),
1308	 *	chop it to 15MB.
1309	 */
1310	if ((pagesinext > 3840) && (pagesinext < 4096))
1311		pagesinext = 3840;
1312
1313	/*
1314	 * Maxmem isn't the "maximum memory", it's one larger than the
1315	 * highest page of of the physical address space. It should be
1316	 * called something like "Maxphyspage".
1317	 */
1318	Maxmem = pagesinext + 0x100000/PAGE_SIZE;
1319
1320#ifdef MAXMEM
1321	Maxmem = MAXMEM/4;
1322#endif
1323	/*
1324	 * Calculate number of physical pages, but account for Maxmem
1325	 *	adjustment above.
1326	 */
1327	physmem = pagesinbase + Maxmem - 0x100000/PAGE_SIZE;
1328
1329	/* call pmap initialization to make new kernel address space */
1330	pmap_bootstrap (first, 0);
1331
1332	/*
1333	 * Do simple memory test over range of extended memory that BIOS
1334	 *	indicates exists. Adjust Maxmem to the highest page of
1335	 *	good memory.
1336	 */
1337	printf("Testing memory (%dMB)...", ptoa(Maxmem)/1024/1024);
1338
1339	for (target_page = Maxmem - 2; target_page >= atop(first); target_page--) {
1340
1341		/*
1342		 * map page into kernel: valid, read/write, non-cacheable
1343		 */
1344		*(int *)CMAP1 = PG_V | PG_KW | PG_N | ptoa(target_page);
1345		pmap_update();
1346
1347		/*
1348		 * Test for alternating 1's and 0's
1349		 */
1350		filli(0xaaaaaaaa, CADDR1, PAGE_SIZE/sizeof(int));
1351		if (test_page((int *)CADDR1, 0xaaaaaaaa)) {
1352			Maxmem = target_page;
1353			badpages++;
1354			continue;
1355		}
1356		/*
1357		 * Test for alternating 0's and 1's
1358		 */
1359		filli(0x55555555, CADDR1, PAGE_SIZE/sizeof(int));
1360		if (test_page((int *)CADDR1, 0x55555555)) {
1361			Maxmem = target_page;
1362			badpages++;
1363			continue;
1364		}
1365		/*
1366		 * Test for all 1's
1367		 */
1368		filli(0xffffffff, CADDR1, PAGE_SIZE/sizeof(int));
1369		if (test_page((int *)CADDR1, 0xffffffff)) {
1370			Maxmem = target_page;
1371			badpages++;
1372			continue;
1373		}
1374		/*
1375		 * Test zeroing of page
1376		 */
1377		bzero(CADDR1, PAGE_SIZE);
1378		if (test_page((int *)CADDR1, 0)) {
1379			/*
1380			 * test of page failed
1381			 */
1382			Maxmem = target_page;
1383			badpages++;
1384			continue;
1385		}
1386	}
1387	printf("done.\n");
1388
1389	*(int *)CMAP1 = 0;
1390	pmap_update();
1391
1392	avail_end = (Maxmem << PAGE_SHIFT)
1393		    - i386_round_page(sizeof(struct msgbuf));
1394
1395	/*
1396	 * Initialize pointers to the two chunks of memory; for use
1397	 *	later in vm_page_startup.
1398	 */
1399	/* avail_start is initialized in pmap_bootstrap */
1400	x = 0;
1401	if (pagesinbase > 1) {
1402		phys_avail[x++] = NBPG;		/* skip first page of memory */
1403		phys_avail[x++] = pagesinbase * NBPG;	/* memory up to the ISA hole */
1404	}
1405	phys_avail[x++] = avail_start;	/* memory up to the end */
1406	phys_avail[x++] = avail_end;
1407	phys_avail[x++] = 0;		/* no more chunks */
1408	phys_avail[x++] = 0;
1409
1410	/* now running on new page tables, configured,and u/iom is accessible */
1411
1412	/* make a initial tss so microp can get interrupt stack on syscall! */
1413	proc0.p_addr->u_pcb.pcb_tss.tss_esp0 = (int) kstack + UPAGES*NBPG;
1414	proc0.p_addr->u_pcb.pcb_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL) ;
1415	gsel_tss = GSEL(GPROC0_SEL, SEL_KPL);
1416
1417	((struct i386tss *)gdt_segs[GPROC0_SEL].ssd_base)->tss_ioopt =
1418		(sizeof(tss))<<16;
1419
1420	ltr(gsel_tss);
1421
1422	/* make a call gate to reenter kernel with */
1423	gdp = &ldt[LSYS5CALLS_SEL].gd;
1424
1425	x = (int) &IDTVEC(syscall);
1426	gdp->gd_looffset = x++;
1427	gdp->gd_selector = GSEL(GCODE_SEL,SEL_KPL);
1428	gdp->gd_stkcpy = 1;
1429	gdp->gd_type = SDT_SYS386CGT;
1430	gdp->gd_dpl = SEL_UPL;
1431	gdp->gd_p = 1;
1432	gdp->gd_hioffset = ((int) &IDTVEC(syscall)) >>16;
1433
1434	/* transfer to user mode */
1435
1436	_ucodesel = LSEL(LUCODE_SEL, SEL_UPL);
1437	_udatasel = LSEL(LUDATA_SEL, SEL_UPL);
1438
1439	/* setup proc 0's pcb */
1440	bcopy(&sigcode, proc0.p_addr->u_pcb.pcb_sigc, szsigcode);
1441	proc0.p_addr->u_pcb.pcb_flags = 0;
1442	proc0.p_addr->u_pcb.pcb_ptd = IdlePTD;
1443}
1444
1445int
1446test_page(address, pattern)
1447	int *address;
1448	int pattern;
1449{
1450	int *x;
1451
1452	for (x = address; x < (int *)((char *)address + PAGE_SIZE); x++) {
1453		if (*x != pattern)
1454			return (1);
1455	}
1456	return(0);
1457}
1458
1459/*
1460 * The registers are in the frame; the frame is in the user area of
1461 * the process in question; when the process is active, the registers
1462 * are in "the kernel stack"; when it's not, they're still there, but
1463 * things get flipped around.  So, since p->p_md.md_regs is the whole address
1464 * of the register set, take its offset from the kernel stack, and
1465 * index into the user block.  Don't you just *love* virtual memory?
1466 * (I'm starting to think seymour is right...)
1467 */
1468
1469int
1470ptrace_set_pc (struct proc *p, unsigned int addr) {
1471	void *regs = (char*)p->p_addr +
1472		((char*) p->p_md.md_regs - (char*) kstack);
1473
1474	((struct trapframe *)regs)->tf_eip = addr;
1475	return 0;
1476}
1477
1478int
1479ptrace_single_step (struct proc *p) {
1480	void *regs = (char*)p->p_addr +
1481		((char*) p->p_md.md_regs - (char*) kstack);
1482
1483	((struct trapframe *)regs)->tf_eflags |= PSL_T;
1484	return 0;
1485}
1486
1487/*
1488 * Copy the registers to user-space.
1489 */
1490
1491int
1492ptrace_getregs (struct proc *p, unsigned int *addr) {
1493	int error;
1494	struct reg regs = {0};
1495
1496	error = fill_regs (p, &regs);
1497	if (error)
1498		return error;
1499
1500	return copyout (&regs, addr, sizeof (regs));
1501}
1502
1503int
1504ptrace_setregs (struct proc *p, unsigned int *addr) {
1505	int error;
1506	struct reg regs = {0};
1507
1508	error = copyin (addr, &regs, sizeof(regs));
1509	if (error)
1510		return error;
1511
1512	return set_regs (p, &regs);
1513}
1514
1515int
1516fill_regs(struct proc *p, struct reg *regs) {
1517	struct trapframe *tp;
1518	void *ptr = (char*)p->p_addr +
1519		((char*) p->p_md.md_regs - (char*) kstack);
1520
1521	tp = ptr;
1522	regs->r_es = tp->tf_es;
1523	regs->r_ds = tp->tf_ds;
1524	regs->r_edi = tp->tf_edi;
1525	regs->r_esi = tp->tf_esi;
1526	regs->r_ebp = tp->tf_ebp;
1527	regs->r_ebx = tp->tf_ebx;
1528	regs->r_edx = tp->tf_edx;
1529	regs->r_ecx = tp->tf_ecx;
1530	regs->r_eax = tp->tf_eax;
1531	regs->r_eip = tp->tf_eip;
1532	regs->r_cs = tp->tf_cs;
1533	regs->r_eflags = tp->tf_eflags;
1534	regs->r_esp = tp->tf_esp;
1535	regs->r_ss = tp->tf_ss;
1536	return 0;
1537}
1538
1539int
1540set_regs (struct proc *p, struct reg *regs) {
1541	struct trapframe *tp;
1542	void *ptr = (char*)p->p_addr +
1543		((char*) p->p_md.md_regs - (char*) kstack);
1544
1545	tp = ptr;
1546	tp->tf_es = regs->r_es;
1547	tp->tf_ds = regs->r_ds;
1548	tp->tf_edi = regs->r_edi;
1549	tp->tf_esi = regs->r_esi;
1550	tp->tf_ebp = regs->r_ebp;
1551	tp->tf_ebx = regs->r_ebx;
1552	tp->tf_edx = regs->r_edx;
1553	tp->tf_ecx = regs->r_ecx;
1554	tp->tf_eax = regs->r_eax;
1555	tp->tf_eip = regs->r_eip;
1556	tp->tf_cs = regs->r_cs;
1557	tp->tf_eflags = regs->r_eflags;
1558	tp->tf_esp = regs->r_esp;
1559	tp->tf_ss = regs->r_ss;
1560	return 0;
1561}
1562
1563#ifndef DDB
1564void
1565Debugger(const char *msg)
1566{
1567	printf("Debugger(\"%s\") called.\n", msg);
1568}
1569#endif /* no DDB */
1570
1571#include <sys/disklabel.h>
1572#define b_cylin	b_resid
1573/*
1574 * Determine the size of the transfer, and make sure it is
1575 * within the boundaries of the partition. Adjust transfer
1576 * if needed, and signal errors or early completion.
1577 */
1578int
1579bounds_check_with_label(struct buf *bp, struct disklabel *lp, int wlabel)
1580{
1581        struct partition *p = lp->d_partitions + dkpart(bp->b_dev);
1582        int labelsect = lp->d_partitions[0].p_offset;
1583        int maxsz = p->p_size,
1584                sz = (bp->b_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT;
1585
1586        /* overwriting disk label ? */
1587        /* XXX should also protect bootstrap in first 8K */
1588        if (bp->b_blkno + p->p_offset <= LABELSECTOR + labelsect &&
1589#if LABELSECTOR != 0
1590            bp->b_blkno + p->p_offset + sz > LABELSECTOR + labelsect &&
1591#endif
1592            (bp->b_flags & B_READ) == 0 && wlabel == 0) {
1593                bp->b_error = EROFS;
1594                goto bad;
1595        }
1596
1597#if     defined(DOSBBSECTOR) && defined(notyet)
1598        /* overwriting master boot record? */
1599        if (bp->b_blkno + p->p_offset <= DOSBBSECTOR &&
1600            (bp->b_flags & B_READ) == 0 && wlabel == 0) {
1601                bp->b_error = EROFS;
1602                goto bad;
1603        }
1604#endif
1605
1606        /* beyond partition? */
1607        if (bp->b_blkno < 0 || bp->b_blkno + sz > maxsz) {
1608                /* if exactly at end of disk, return an EOF */
1609                if (bp->b_blkno == maxsz) {
1610                        bp->b_resid = bp->b_bcount;
1611                        return(0);
1612                }
1613                /* or truncate if part of it fits */
1614                sz = maxsz - bp->b_blkno;
1615                if (sz <= 0) {
1616                        bp->b_error = EINVAL;
1617                        goto bad;
1618                }
1619                bp->b_bcount = sz << DEV_BSHIFT;
1620        }
1621
1622        /* calculate cylinder for disksort to order transfers with */
1623        bp->b_pblkno = bp->b_blkno + p->p_offset;
1624        bp->b_cylin = bp->b_pblkno / lp->d_secpercyl;
1625        return(1);
1626
1627bad:
1628        bp->b_flags |= B_ERROR;
1629        return(-1);
1630}
1631
1632int
1633disk_externalize(int drive, void *userp, size_t *maxlen)
1634{
1635	if(*maxlen < sizeof drive) {
1636		return ENOMEM;
1637	}
1638
1639	*maxlen -= sizeof drive;
1640	return copyout(&drive, userp, sizeof drive);
1641}
1642
1643