machdep.c revision 911
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.22 1993/12/19 00:50:03 wollman Exp $
39 */
40
41#include "npx.h"
42#include "isa.h"
43
44#include <stddef.h>
45#include "param.h"
46#include "systm.h"
47#include "signalvar.h"
48#include "kernel.h"
49#include "map.h"
50#include "proc.h"
51#include "user.h"
52#include "exec.h"            /* for PS_STRINGS */
53#include "buf.h"
54#include "reboot.h"
55#include "conf.h"
56#include "file.h"
57#include "callout.h"
58#include "malloc.h"
59#include "mbuf.h"
60#include "msgbuf.h"
61#include "net/netisr.h"
62
63#ifdef SYSVSHM
64#include "sys/shm.h"
65#endif
66
67#include "vm/vm.h"
68#include "vm/vm_kern.h"
69#include "vm/vm_page.h"
70
71#include "sys/exec.h"
72#include "sys/vnode.h"
73
74#ifndef MACHINE_NONCONTIG
75extern vm_offset_t avail_end;
76#else
77extern vm_offset_t avail_start, avail_end;
78static vm_offset_t hole_start, hole_end;
79static vm_offset_t avail_next;
80static unsigned int avail_remaining;
81#endif /* MACHINE_NONCONTIG */
82
83#include "machine/cpu.h"
84#include "machine/reg.h"
85#include "machine/psl.h"
86#include "machine/specialreg.h"
87#include "machine/sysarch.h"
88#include "machine/cons.h"
89
90#include "i386/isa/isa.h"
91#include "i386/isa/rtc.h"
92
93static void identifycpu(void);
94static void initcpu(void);
95
96#define	EXPECT_BASEMEM	640	/* The expected base memory*/
97#define	INFORM_WAIT	1	/* Set to pause berfore crash in weird cases*/
98
99#ifndef PANIC_REBOOT_WAIT_TIME
100#define PANIC_REBOOT_WAIT_TIME 15 /* default to 15 seconds */
101#endif
102
103/*
104 * Declare these as initialized data so we can patch them.
105 */
106int	nswbuf = 0;
107#ifdef	NBUF
108int	nbuf = NBUF;
109#else
110int	nbuf = 0;
111#endif
112#ifdef	BUFPAGES
113int	bufpages = BUFPAGES;
114#else
115int	bufpages = 0;
116#endif
117extern int freebufspace;
118
119int _udatasel, _ucodesel;
120
121/*
122 * Machine-dependent startup code
123 */
124int boothowto = 0, Maxmem = 0;
125long dumplo;
126int physmem, maxmem;
127extern int bootdev;
128#ifdef SMALL
129extern int forcemaxmem;
130#endif
131int biosmem;
132
133extern cyloffset;
134
135int cpu_class;
136
137void dumpsys __P((void));
138
139void
140cpu_startup()
141{
142	register int unixsize;
143	register unsigned i;
144	register struct pte *pte;
145	int mapaddr, j;
146	register caddr_t v;
147	int maxbufs, base, residual;
148	extern long Usrptsize;
149	vm_offset_t minaddr, maxaddr;
150	vm_size_t size = 0;
151	int firstaddr;
152
153	/*
154	 * Initialize error message buffer (at end of core).
155	 */
156
157	/* avail_end was pre-decremented in pmap_bootstrap to compensate */
158	for (i = 0; i < btoc(sizeof (struct msgbuf)); i++)
159#ifndef MACHINE_NONCONTIG
160		pmap_enter(pmap_kernel(), (vm_offset_t)msgbufp,
161			   avail_end + i * NBPG,
162			   VM_PROT_ALL, TRUE);
163#else
164		pmap_enter(pmap_kernel(), (vm_offset_t)msgbufp + i * NBPG,
165			   avail_end + i * NBPG, VM_PROT_ALL, TRUE);
166#endif
167	msgbufmapped = 1;
168
169	/*
170	 * Good {morning,afternoon,evening,night}.
171	 */
172	printf(version);
173	identifycpu();
174	printf("real mem  = %d\n", ctob(physmem));
175
176	/*
177	 * Allocate space for system data structures.
178	 * The first available kernel virtual address is in "v".
179	 * As pages of kernel virtual memory are allocated, "v" is incremented.
180	 * As pages of memory are allocated and cleared,
181	 * "firstaddr" is incremented.
182	 * An index into the kernel page table corresponding to the
183	 * virtual memory address maintained in "v" is kept in "mapaddr".
184	 */
185
186	/*
187	 * Make two passes.  The first pass calculates how much memory is
188	 * needed and allocates it.  The second pass assigns virtual
189	 * addresses to the various data structures.
190	 */
191	firstaddr = 0;
192again:
193	v = (caddr_t)firstaddr;
194
195#define	valloc(name, type, num) \
196	    (name) = (type *)v; v = (caddr_t)((name)+(num))
197#define	valloclim(name, type, num, lim) \
198	    (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num)))
199/*	valloc(cfree, struct cblock, nclist);  no clists any more!!! - cgd */
200	valloc(callout, struct callout, ncallout);
201#ifdef NetBSD
202	valloc(swapmap, struct map, nswapmap = maxproc * 2);
203#endif
204#ifdef SYSVSHM
205	valloc(shmsegs, struct shmid_ds, shminfo.shmmni);
206#endif
207	/*
208	 * Determine how many buffers to allocate.
209	 * Use 20% of memory of memory beyond the first 2MB
210	 * Insure a minimum of 16 fs buffers.
211	 * We allocate 1/2 as many swap buffer headers as file i/o buffers.
212	 */
213	if (bufpages == 0)
214		bufpages = ((physmem << PGSHIFT) - 2048*1024) / NBPG / 5;
215	if (bufpages < 64)
216		bufpages = 64;
217
218	/*
219	 * We must still limit the maximum number of buffers to be no
220	 * more than 2/5's of the size of the kernal malloc region, this
221	 * will only take effect for machines with lots of memory
222	 */
223	bufpages = min(bufpages, (VM_KMEM_SIZE / NBPG) * 2 / 5);
224	if (nbuf == 0) {
225		nbuf = bufpages / 2;
226		if (nbuf < 32)
227			nbuf = 32;
228	}
229	freebufspace = bufpages * NBPG;
230	if (nswbuf == 0) {
231		nswbuf = (nbuf / 2) &~ 1;	/* force even */
232		if (nswbuf > 256)
233			nswbuf = 256;		/* sanity */
234	}
235	valloc(swbuf, struct buf, nswbuf);
236	valloc(buf, struct buf, nbuf);
237
238	/*
239	 * End of first pass, size has been calculated so allocate memory
240	 */
241	if (firstaddr == 0) {
242		size = (vm_size_t)(v - firstaddr);
243		firstaddr = (int)kmem_alloc(kernel_map, round_page(size));
244		if (firstaddr == 0)
245			panic("startup: no room for tables");
246		goto again;
247	}
248	/*
249	 * End of second pass, addresses have been assigned
250	 */
251	if ((vm_size_t)(v - firstaddr) != size)
252		panic("startup: table size inconsistency");
253
254	/*
255	 * Allocate a submap for buffer space allocations.
256	 * XXX we are NOT using buffer_map, but due to
257	 * the references to it we will just allocate 1 page of
258	 * vm (not real memory) to make things happy...
259	 */
260	buffer_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
261				/* bufpages * */NBPG, TRUE);
262	/*
263	 * Allocate a submap for exec arguments.  This map effectively
264	 * limits the number of processes exec'ing at any time.
265	 */
266/*	exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
267 *				16*NCARGS, TRUE);
268 *	NOT CURRENTLY USED -- cgd
269 */
270	/*
271	 * Allocate a submap for physio
272	 */
273	phys_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
274				 VM_PHYS_SIZE, TRUE);
275
276	/*
277	 * Finally, allocate mbuf pool.  Since mclrefcnt is an off-size
278	 * we use the more space efficient malloc in place of kmem_alloc.
279	 */
280	mclrefcnt = (char *)malloc(NMBCLUSTERS+CLBYTES/MCLBYTES,
281				   M_MBUF, M_NOWAIT);
282	bzero(mclrefcnt, NMBCLUSTERS+CLBYTES/MCLBYTES);
283	mb_map = kmem_suballoc(kernel_map, (vm_offset_t)&mbutl, &maxaddr,
284			       VM_MBUF_SIZE, FALSE);
285	/*
286	 * Initialize callouts
287	 */
288	callfree = callout;
289	for (i = 1; i < ncallout; i++)
290		callout[i-1].c_next = &callout[i];
291
292	printf("avail mem = %d\n", ptoa(vm_page_free_count));
293	printf("using %d buffers containing %d bytes of memory\n",
294		nbuf, bufpages * CLBYTES);
295
296	/*
297	 * Set up CPU-specific registers, cache, etc.
298	 */
299	initcpu();
300
301	/*
302	 * Set up buffers, so they can be used to read disk labels.
303	 */
304	bufinit();
305
306	/*
307	 * Configure the system.
308	 */
309	configure();
310}
311
312
313struct cpu_nameclass i386_cpus[] = {
314	{ "Intel 80286",	CPUCLASS_286 },		/* CPU_286   */
315	{ "i386SX",		CPUCLASS_386 },		/* CPU_386SX */
316	{ "i386DX",		CPUCLASS_386 },		/* CPU_386   */
317	{ "i486SX",		CPUCLASS_486 },		/* CPU_486SX */
318	{ "i486DX",		CPUCLASS_486 },		/* CPU_486   */
319	{ "i586",		CPUCLASS_586 },		/* CPU_586   */
320};
321
322static void
323identifycpu()	/* translated from hp300 -- cgd */
324{
325	printf("CPU: ");
326	if (cpu >= 0 && cpu < (sizeof i386_cpus/sizeof(struct cpu_nameclass))) {
327		printf("%s", i386_cpus[cpu].cpu_name);
328		cpu_class = i386_cpus[cpu].cpu_class;
329	} else {
330		printf("unknown cpu type %d\n", cpu);
331		panic("startup: bad cpu id");
332	}
333	printf(" (");
334	switch(cpu_class) {
335	case CPUCLASS_286:
336		printf("286");
337		break;
338	case CPUCLASS_386:
339		printf("386");
340		break;
341	case CPUCLASS_486:
342		printf("486");
343		break;
344	case CPUCLASS_586:
345		printf("586");
346		break;
347	default:
348		printf("unknown");	/* will panic below... */
349	}
350	printf("-class CPU)");
351	printf("\n");	/* cpu speed would be nice, but how? */
352
353	/*
354	 * Now that we have told the user what they have,
355	 * let them know if that machine type isn't configured.
356	 */
357	switch (cpu_class) {
358	case CPUCLASS_286:	/* a 286 should not make it this far, anyway */
359#if !defined(I386_CPU) && !defined(I486_CPU) && !defined(I586_CPU)
360#error This kernel is not configured for one of the supported CPUs
361#endif
362#if !defined(I386_CPU)
363	case CPUCLASS_386:
364#endif
365#if !defined(I486_CPU)
366	case CPUCLASS_486:
367#endif
368#if !defined(I586_CPU)
369	case CPUCLASS_586:
370#endif
371		panic("CPU class not configured");
372	default:
373		break;
374	}
375}
376
377#ifdef PGINPROF
378/*
379 * Return the difference (in microseconds)
380 * between the  current time and a previous
381 * time as represented  by the arguments.
382 * If there is a pending clock interrupt
383 * which has not been serviced due to high
384 * ipl, return error code.
385 */
386/*ARGSUSED*/
387vmtime(otime, olbolt, oicr)
388	register int otime, olbolt, oicr;
389{
390
391	return (((time.tv_sec-otime)*60 + lbolt-olbolt)*16667);
392}
393#endif
394
395extern int kstack[];
396
397/*
398 * Send an interrupt to process.
399 *
400 * Stack is set up to allow sigcode stored
401 * in u. to call routine, followed by kcall
402 * to sigreturn routine below.  After sigreturn
403 * resets the signal mask, the stack, and the
404 * frame pointer, it returns to the user
405 * specified pc, psl.
406 */
407void
408sendsig(catcher, sig, mask, code)
409	sig_t catcher;
410	int sig, mask;
411	unsigned code;
412{
413	register struct proc *p = curproc;
414	register int *regs;
415	register struct sigframe *fp;
416	struct sigacts *ps = p->p_sigacts;
417	int oonstack, frmtrap;
418
419	regs = p->p_regs;
420        oonstack = ps->ps_onstack;
421	frmtrap = curpcb->pcb_flags & FM_TRAP;
422	/*
423	 * Allocate and validate space for the signal handler
424	 * context. Note that if the stack is in P0 space, the
425	 * call to grow() is a nop, and the useracc() check
426	 * will fail if the process has not already allocated
427	 * the space with a `brk'.
428	 */
429        if (!ps->ps_onstack && (ps->ps_sigonstack & sigmask(sig))) {
430		fp = (struct sigframe *)(ps->ps_sigsp
431				- sizeof(struct sigframe));
432                ps->ps_onstack = 1;
433	} else {
434		if (frmtrap)
435			fp = (struct sigframe *)(regs[tESP]
436				- sizeof(struct sigframe));
437		else
438			fp = (struct sigframe *)(regs[sESP]
439				- sizeof(struct sigframe));
440	}
441
442	if (useracc((caddr_t)fp, sizeof (struct sigframe), B_WRITE) == 0) {
443		/*
444		 * Process has trashed its stack; give it an illegal
445		 * instruction to halt it in its tracks.
446		 */
447		SIGACTION(p, SIGILL) = SIG_DFL;
448		sig = sigmask(SIGILL);
449		p->p_sigignore &= ~sig;
450		p->p_sigcatch &= ~sig;
451		p->p_sigmask &= ~sig;
452		psignal(p, SIGILL);
453		return;
454	}
455
456	/*
457	 * Build the argument list for the signal handler.
458	 */
459	fp->sf_signum = sig;
460	fp->sf_code = code;
461	fp->sf_scp = &fp->sf_sc;
462	fp->sf_addr = (char *) regs[tERR];
463	fp->sf_handler = catcher;
464
465	/* save scratch registers */
466	if(frmtrap) {
467		fp->sf_eax = regs[tEAX];
468		fp->sf_edx = regs[tEDX];
469		fp->sf_ecx = regs[tECX];
470	} else {
471		fp->sf_eax = regs[sEAX];
472		fp->sf_edx = regs[sEDX];
473		fp->sf_ecx = regs[sECX];
474	}
475	/*
476	 * Build the signal context to be used by sigreturn.
477	 */
478	fp->sf_sc.sc_onstack = oonstack;
479	fp->sf_sc.sc_mask = mask;
480	if(frmtrap) {
481		fp->sf_sc.sc_sp = regs[tESP];
482		fp->sf_sc.sc_fp = regs[tEBP];
483		fp->sf_sc.sc_pc = regs[tEIP];
484		fp->sf_sc.sc_ps = regs[tEFLAGS];
485		regs[tESP] = (int)fp;
486		regs[tEIP] = (int)((struct pcb *)kstack)->pcb_sigc;
487	} else {
488		fp->sf_sc.sc_sp = regs[sESP];
489		fp->sf_sc.sc_fp = regs[sEBP];
490		fp->sf_sc.sc_pc = regs[sEIP];
491		fp->sf_sc.sc_ps = regs[sEFLAGS];
492		regs[sESP] = (int)fp;
493		regs[sEIP] = (int)((struct pcb *)kstack)->pcb_sigc;
494	}
495}
496
497/*
498 * System call to cleanup state after a signal
499 * has been taken.  Reset signal mask and
500 * stack state from context left by sendsig (above).
501 * Return to previous pc and psl as specified by
502 * context left by sendsig. Check carefully to
503 * make sure that the user has not modified the
504 * psl to gain improper priviledges or to cause
505 * a machine fault.
506 */
507struct sigreturn_args {
508	struct sigcontext *sigcntxp;
509};
510
511int
512sigreturn(p, uap, retval)
513	struct proc *p;
514	struct sigreturn_args *uap;
515	int *retval;
516{
517	register struct sigcontext *scp;
518	register struct sigframe *fp;
519	register int *regs = p->p_regs;
520
521	/*
522	 * (XXX old comment) regs[sESP] points to the return address.
523	 * The user scp pointer is above that.
524	 * The return address is faked in the signal trampoline code
525	 * for consistency.
526	 */
527	scp = uap->sigcntxp;
528	fp = (struct sigframe *)
529	     ((caddr_t)scp - offsetof(struct sigframe, sf_sc));
530
531	if (useracc((caddr_t)fp, sizeof (*fp), 0) == 0)
532		return(EINVAL);
533
534	/* restore scratch registers */
535	regs[sEAX] = fp->sf_eax ;
536	regs[sEDX] = fp->sf_edx ;
537	regs[sECX] = fp->sf_ecx ;
538
539	if (useracc((caddr_t)scp, sizeof (*scp), 0) == 0)
540		return(EINVAL);
541#ifdef notyet
542	if ((scp->sc_ps & PSL_MBZ) != 0 || (scp->sc_ps & PSL_MBO) != PSL_MBO) {
543		return(EINVAL);
544	}
545#endif
546        p->p_sigacts->ps_onstack = scp->sc_onstack & 01;
547	p->p_sigmask = scp->sc_mask &~
548	    (sigmask(SIGKILL)|sigmask(SIGCONT)|sigmask(SIGSTOP));
549	regs[sEBP] = scp->sc_fp;
550	regs[sESP] = scp->sc_sp;
551	regs[sEIP] = scp->sc_pc;
552	regs[sEFLAGS] = scp->sc_ps;
553	return(EJUSTRETURN);
554}
555
556/*
557 * a simple function to make the system panic (and dump a vmcore)
558 * in a predictable fashion
559 */
560void diediedie()
561{
562	panic("because you said to!");
563}
564
565int	waittime = -1;
566struct pcb dumppcb;
567
568void
569boot(arghowto)
570	int arghowto;
571{
572	register long dummy;		/* r12 is reserved */
573	register int howto;		/* r11 == how to boot */
574	register int devtype;		/* r10 == major of root dev */
575	extern int cold;
576	int nomsg = 1;
577
578	if(cold) {
579		printf("hit reset please");
580		for(;;);
581	}
582	howto = arghowto;
583	if ((howto&RB_NOSYNC) == 0 && waittime < 0 && bfreelist[0].b_forw) {
584		register struct buf *bp;
585		int iter, nbusy;
586
587		waittime = 0;
588		(void) splnet();
589		printf("syncing disks... ");
590		/*
591		 * Release inodes held by texts before update.
592		 */
593		if (panicstr == 0)
594			vnode_pager_umount(NULL);
595		sync((struct sigcontext *)0);
596		/*
597		 * Unmount filesystems
598		 */
599#if 0
600		if (panicstr == 0)
601			vfs_unmountall();
602#endif
603
604		for (iter = 0; iter < 20; iter++) {
605			nbusy = 0;
606			for (bp = &buf[nbuf]; --bp >= buf; )
607				if ((bp->b_flags & (B_BUSY|B_INVAL)) == B_BUSY)
608					nbusy++;
609			if (nbusy == 0)
610				break;
611			if (nomsg) {
612				printf("updating disks before rebooting... ");
613				nomsg = 0;
614			}
615			printf("%d ", nbusy);
616			DELAY(40000 * iter);
617		}
618		if (nbusy)
619			printf("giving up\n");
620		else
621			printf("done\n");
622		DELAY(10000);			/* wait for printf to finish */
623	}
624	splhigh();
625	devtype = major(rootdev);
626	if (howto&RB_HALT) {
627		printf("\n");
628		printf("The operating system has halted.\n");
629		printf("Please press any key to reboot.\n\n");
630		cngetc();
631	} else {
632		if (howto & RB_DUMP) {
633			savectx(&dumppcb, 0);
634			dumppcb.pcb_ptd = rcr3();
635			dumpsys();
636
637			if (PANIC_REBOOT_WAIT_TIME != 0) {
638				if (PANIC_REBOOT_WAIT_TIME != -1) {
639					int loop;
640					printf("Automatic reboot in %d seconds - press a key on the console to abort\n",
641						PANIC_REBOOT_WAIT_TIME);
642					for (loop = PANIC_REBOOT_WAIT_TIME; loop > 0; --loop) {
643						DELAY(1000 * 1000); /* one second */
644						if (sgetc(1)) /* Did user type a key? */
645							break;
646					}
647					if (!loop)
648						goto die;
649				}
650			} else { /* zero time specified - reboot NOW */
651				goto die;
652			}
653			printf("--> Press a key on the console to reboot <--\n");
654			cngetc();
655		}
656	}
657#ifdef lint
658	dummy = 0; dummy = dummy;
659	printf("howto %d, devtype %d\n", arghowto, devtype);
660#endif
661die:
662	printf("Rebooting...\n");
663	DELAY (100000);	/* wait 100ms for printf's to complete */
664	cpu_reset();
665	for(;;) ;
666	/*NOTREACHED*/
667}
668
669unsigned long	dumpmag = 0x8fca0101UL;	/* magic number for savecore */
670int		dumpsize = 0;		/* also for savecore */
671/*
672 * Doadump comes here after turning off memory management and
673 * getting on the dump stack, either when called above, or by
674 * the auto-restart code.
675 */
676void
677dumpsys()
678{
679
680	if (dumpdev == NODEV)
681		return;
682	if ((minor(dumpdev)&07) != 1)
683		return;
684	dumpsize = physmem;
685	printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo);
686	printf("dump ");
687	switch ((*bdevsw[major(dumpdev)].d_dump)(dumpdev)) {
688
689	case ENXIO:
690		printf("device bad\n");
691		break;
692
693	case EFAULT:
694		printf("device not ready\n");
695		break;
696
697	case EINVAL:
698		printf("area improper\n");
699		break;
700
701	case EIO:
702		printf("i/o error\n");
703		break;
704
705	case EINTR:
706		printf("aborted from console\n");
707		break;
708
709	default:
710		printf("succeeded\n");
711		break;
712	}
713}
714
715#ifdef HZ
716/*
717 * If HZ is defined we use this code, otherwise the code in
718 * /sys/i386/i386/microtime.s is used.  The othercode only works
719 * for HZ=100.
720 */
721microtime(tvp)
722	register struct timeval *tvp;
723{
724	int s = splhigh();
725
726	*tvp = time;
727	tvp->tv_usec += tick;
728	while (tvp->tv_usec > 1000000) {
729		tvp->tv_sec++;
730		tvp->tv_usec -= 1000000;
731	}
732	splx(s);
733}
734#endif /* HZ */
735
736void
737physstrat(bp, strat, prio)
738	struct buf *bp;
739	int (*strat)(), prio;
740{
741	register int s;
742	caddr_t baddr;
743
744	vmapbuf(bp);
745	(*strat)(bp);
746	/* pageout daemon doesn't wait for pushed pages */
747	if (bp->b_flags & B_DIRTY)
748		return;
749	s = splbio();
750	while ((bp->b_flags & B_DONE) == 0)
751	  tsleep((caddr_t)bp, prio, "physstr", 0);
752	splx(s);
753	vunmapbuf(bp);
754}
755
756static void
757initcpu()
758{
759}
760
761/*
762 * Clear registers on exec
763 */
764void
765setregs(p, entry)
766	struct proc *p;
767	u_long entry;
768{
769
770	p->p_regs[sEBP] = 0;	/* bottom of the fp chain */
771	p->p_regs[sEIP] = entry;
772
773	p->p_addr->u_pcb.pcb_flags = 0;	/* no fp at all */
774	load_cr0(rcr0() | CR0_TS);	/* start emulating */
775#if	NNPX > 0
776	npxinit(__INITIAL_NPXCW__);
777#endif	/* NNPX > 0 */
778}
779
780/*
781 * Initialize 386 and configure to run kernel
782 */
783
784/*
785 * Initialize segments & interrupt table
786 */
787#define DESCRIPTOR_SIZE	8
788
789#define	GNULL_SEL	0	/* Null Descriptor */
790#define	GCODE_SEL	1	/* Kernel Code Descriptor */
791#define	GDATA_SEL	2	/* Kernel Data Descriptor */
792#define	GLDT_SEL	3	/* LDT - eventually one per process */
793#define	GTGATE_SEL	4	/* Process task switch gate */
794#define	GPANIC_SEL	5	/* Task state to consider panic from */
795#define	GPROC0_SEL	6	/* Task state process slot zero and up */
796#define NGDT 	GPROC0_SEL+1
797
798unsigned char gdt[GPROC0_SEL+1][DESCRIPTOR_SIZE];
799
800/* interrupt descriptor table */
801struct gate_descriptor idt[NIDT];
802
803/* local descriptor table */
804unsigned char ldt[5][DESCRIPTOR_SIZE];
805#define	LSYS5CALLS_SEL	0	/* forced by intel BCS */
806#define	LSYS5SIGR_SEL	1
807
808#define	L43BSDCALLS_SEL	2	/* notyet */
809#define	LUCODE_SEL	3
810#define	LUDATA_SEL	4
811/* seperate stack, es,fs,gs sels ? */
812/* #define	LPOSIXCALLS_SEL	5*/	/* notyet */
813
814struct	i386tss	tss, panic_tss;
815
816extern  struct user *proc0paddr;
817
818/* software prototypes -- in more palatable form */
819struct soft_segment_descriptor gdt_segs[] = {
820	/* Null Descriptor */
821{	0x0,			/* segment base address  */
822	0x0,			/* length */
823	0,			/* segment type */
824	0,			/* segment descriptor priority level */
825	0,			/* segment descriptor present */
826	0, 0,
827	0,			/* default 32 vs 16 bit size */
828	0  			/* limit granularity (byte/page units)*/ },
829	/* Code Descriptor for kernel */
830{	0x0,			/* segment base address  */
831	0xfffff,		/* length - all address space */
832	SDT_MEMERA,		/* segment type */
833	0,			/* segment descriptor priority level */
834	1,			/* segment descriptor present */
835	0, 0,
836	1,			/* default 32 vs 16 bit size */
837	1  			/* limit granularity (byte/page units)*/ },
838	/* Data Descriptor for kernel */
839{	0x0,			/* segment base address  */
840	0xfffff,		/* length - all address space */
841	SDT_MEMRWA,		/* segment type */
842	0,			/* segment descriptor priority level */
843	1,			/* segment descriptor present */
844	0, 0,
845	1,			/* default 32 vs 16 bit size */
846	1  			/* limit granularity (byte/page units)*/ },
847	/* LDT Descriptor */
848{	(int) ldt,			/* segment base address  */
849	sizeof(ldt)-1,		/* length - all address space */
850	SDT_SYSLDT,		/* segment type */
851	0,			/* segment descriptor priority level */
852	1,			/* segment descriptor present */
853	0, 0,
854	0,			/* unused - default 32 vs 16 bit size */
855	0  			/* limit granularity (byte/page units)*/ },
856	/* Null Descriptor - Placeholder */
857{	0x0,			/* segment base address  */
858	0x0,			/* length - all address space */
859	0,			/* segment type */
860	0,			/* segment descriptor priority level */
861	0,			/* segment descriptor present */
862	0, 0,
863	0,			/* default 32 vs 16 bit size */
864	0  			/* limit granularity (byte/page units)*/ },
865	/* Panic Tss Descriptor */
866{	(int) &panic_tss,		/* segment base address  */
867	sizeof(tss)-1,		/* length - all address space */
868	SDT_SYS386TSS,		/* segment type */
869	0,			/* segment descriptor priority level */
870	1,			/* segment descriptor present */
871	0, 0,
872	0,			/* unused - default 32 vs 16 bit size */
873	0  			/* limit granularity (byte/page units)*/ },
874	/* Proc 0 Tss Descriptor */
875{	(int) kstack,			/* segment base address  */
876	sizeof(tss)-1,		/* length - all address space */
877	SDT_SYS386TSS,		/* segment type */
878	0,			/* segment descriptor priority level */
879	1,			/* segment descriptor present */
880	0, 0,
881	0,			/* unused - default 32 vs 16 bit size */
882	0  			/* limit granularity (byte/page units)*/ }};
883
884struct soft_segment_descriptor ldt_segs[] = {
885	/* Null Descriptor - overwritten by call gate */
886{	0x0,			/* segment base address  */
887	0x0,			/* length - all address space */
888	0,			/* segment type */
889	0,			/* segment descriptor priority level */
890	0,			/* segment descriptor present */
891	0, 0,
892	0,			/* default 32 vs 16 bit size */
893	0  			/* limit granularity (byte/page units)*/ },
894	/* Null Descriptor - overwritten by call gate */
895{	0x0,			/* segment base address  */
896	0x0,			/* length - all address space */
897	0,			/* segment type */
898	0,			/* segment descriptor priority level */
899	0,			/* segment descriptor present */
900	0, 0,
901	0,			/* default 32 vs 16 bit size */
902	0  			/* limit granularity (byte/page units)*/ },
903	/* Null Descriptor - overwritten by call gate */
904{	0x0,			/* segment base address  */
905	0x0,			/* length - all address space */
906	0,			/* segment type */
907	0,			/* segment descriptor priority level */
908	0,			/* segment descriptor present */
909	0, 0,
910	0,			/* default 32 vs 16 bit size */
911	0  			/* limit granularity (byte/page units)*/ },
912	/* Code Descriptor for user */
913{	0x0,			/* segment base address  */
914	0xfffff,		/* length - all address space */
915	SDT_MEMERA,		/* segment type */
916	SEL_UPL,		/* segment descriptor priority level */
917	1,			/* segment descriptor present */
918	0, 0,
919	1,			/* default 32 vs 16 bit size */
920	1  			/* limit granularity (byte/page units)*/ },
921	/* Data Descriptor for user */
922{	0x0,			/* segment base address  */
923	0xfffff,		/* length - all address space */
924	SDT_MEMRWA,		/* segment type */
925	SEL_UPL,		/* segment descriptor priority level */
926	1,			/* segment descriptor present */
927	0, 0,
928	1,			/* default 32 vs 16 bit size */
929	1  			/* limit granularity (byte/page units)*/ } };
930
931void
932setidt(idx, func, typ, dpl)
933	int idx;
934	void (*func)();
935	int typ;
936	int dpl;
937{
938	struct gate_descriptor *ip = idt + idx;
939
940	ip->gd_looffset = (int)func;
941	ip->gd_selector = 8;
942	ip->gd_stkcpy = 0;
943	ip->gd_xx = 0;
944	ip->gd_type = typ;
945	ip->gd_dpl = dpl;
946	ip->gd_p = 1;
947	ip->gd_hioffset = ((int)func)>>16 ;
948}
949
950#define	IDTVEC(name)	__CONCAT(X, name)
951typedef void idtvec_t();
952
953extern idtvec_t
954	IDTVEC(div), IDTVEC(dbg), IDTVEC(nmi), IDTVEC(bpt), IDTVEC(ofl),
955	IDTVEC(bnd), IDTVEC(ill), IDTVEC(dna), IDTVEC(dble), IDTVEC(fpusegm),
956	IDTVEC(tss), IDTVEC(missing), IDTVEC(stk), IDTVEC(prot),
957	IDTVEC(page), IDTVEC(rsvd), IDTVEC(fpu), IDTVEC(rsvd0),
958	IDTVEC(rsvd1), IDTVEC(rsvd2), IDTVEC(rsvd3), IDTVEC(rsvd4),
959	IDTVEC(rsvd5), IDTVEC(rsvd6), IDTVEC(rsvd7), IDTVEC(rsvd8),
960	IDTVEC(rsvd9), IDTVEC(rsvd10), IDTVEC(rsvd11), IDTVEC(rsvd12),
961	IDTVEC(rsvd13), IDTVEC(rsvd14), IDTVEC(rsvd14), IDTVEC(syscall);
962
963int _gsel_tss;
964
965void
966init386(first)
967	int first;
968{
969	extern ssdtosd(), lgdt(), lidt(), lldt(), etext;
970	int x, *pi;
971	unsigned biosbasemem, biosextmem;
972	struct gate_descriptor *gdp;
973	extern int sigcode,szsigcode;
974	/* table descriptors - used to load tables by microp */
975	unsigned short	r_gdt[3], r_idt[3];
976	int	pagesinbase, pagesinext;
977
978
979	proc0.p_addr = proc0paddr;
980
981	/*
982	 * Initialize the console before we print anything out.
983	 */
984
985	cninit ();
986
987	/*
988	 * make gdt memory segments, the code segment goes up to end of the
989	 * page with etext in it, the data segment goes to the end of
990	 * the address space
991	 */
992	gdt_segs[GCODE_SEL].ssd_limit = i386_btop(i386_round_page(&etext)) - 1;
993	gdt_segs[GDATA_SEL].ssd_limit = 0xffffffffUL;	/* XXX constant? */
994	for (x=0; x < NGDT; x++) ssdtosd(gdt_segs+x, gdt+x);
995	/* make ldt memory segments */
996	/*
997	 * The data segment limit must not cover the user area because we
998	 * don't want the user area to be writable in copyout() etc. (page
999	 * level protection is lost in kernel mode on 386's).  Also, we
1000	 * don't want the user area to be writable directly (page level
1001	 * protection of the user area is not available on 486's with
1002	 * CR0_WP set, because there is no user-read/kernel-write mode).
1003	 *
1004	 * XXX - VM_MAXUSER_ADDRESS is an end address, not a max.  And it
1005	 * should be spelled ...MAX_USER...
1006	 */
1007#define VM_END_USER_RW_ADDRESS	VM_MAXUSER_ADDRESS
1008	/*
1009	 * The code segment limit has to cover the user area until we move
1010	 * the signal trampoline out of the user area.  This is safe because
1011	 * the code segment cannot be written to directly.
1012	 */
1013#define VM_END_USER_R_ADDRESS	(VM_END_USER_RW_ADDRESS + UPAGES * NBPG)
1014	ldt_segs[LUCODE_SEL].ssd_limit = i386_btop(VM_END_USER_R_ADDRESS) - 1;
1015	ldt_segs[LUDATA_SEL].ssd_limit = i386_btop(VM_END_USER_RW_ADDRESS) - 1;
1016	/* Note. eventually want private ldts per process */
1017	for (x=0; x < 5; x++) ssdtosd(ldt_segs+x, ldt+x);
1018
1019	/* exceptions */
1020	setidt(0, &IDTVEC(div),  SDT_SYS386TGT, SEL_KPL);
1021	setidt(1, &IDTVEC(dbg),  SDT_SYS386TGT, SEL_KPL);
1022	setidt(2, &IDTVEC(nmi),  SDT_SYS386TGT, SEL_KPL);
1023 	setidt(3, &IDTVEC(bpt),  SDT_SYS386TGT, SEL_UPL);
1024	setidt(4, &IDTVEC(ofl),  SDT_SYS386TGT, SEL_KPL);
1025	setidt(5, &IDTVEC(bnd),  SDT_SYS386TGT, SEL_KPL);
1026	setidt(6, &IDTVEC(ill),  SDT_SYS386TGT, SEL_KPL);
1027	setidt(7, &IDTVEC(dna),  SDT_SYS386TGT, SEL_KPL);
1028	setidt(8, &IDTVEC(dble),  SDT_SYS386TGT, SEL_KPL);
1029	setidt(9, &IDTVEC(fpusegm),  SDT_SYS386TGT, SEL_KPL);
1030	setidt(10, &IDTVEC(tss),  SDT_SYS386TGT, SEL_KPL);
1031	setidt(11, &IDTVEC(missing),  SDT_SYS386TGT, SEL_KPL);
1032	setidt(12, &IDTVEC(stk),  SDT_SYS386TGT, SEL_KPL);
1033	setidt(13, &IDTVEC(prot),  SDT_SYS386TGT, SEL_KPL);
1034	setidt(14, &IDTVEC(page),  SDT_SYS386TGT, SEL_KPL);
1035	setidt(15, &IDTVEC(rsvd),  SDT_SYS386TGT, SEL_KPL);
1036	setidt(16, &IDTVEC(fpu),  SDT_SYS386TGT, SEL_KPL);
1037	setidt(17, &IDTVEC(rsvd0),  SDT_SYS386TGT, SEL_KPL);
1038	setidt(18, &IDTVEC(rsvd1),  SDT_SYS386TGT, SEL_KPL);
1039	setidt(19, &IDTVEC(rsvd2),  SDT_SYS386TGT, SEL_KPL);
1040	setidt(20, &IDTVEC(rsvd3),  SDT_SYS386TGT, SEL_KPL);
1041	setidt(21, &IDTVEC(rsvd4),  SDT_SYS386TGT, SEL_KPL);
1042	setidt(22, &IDTVEC(rsvd5),  SDT_SYS386TGT, SEL_KPL);
1043	setidt(23, &IDTVEC(rsvd6),  SDT_SYS386TGT, SEL_KPL);
1044	setidt(24, &IDTVEC(rsvd7),  SDT_SYS386TGT, SEL_KPL);
1045	setidt(25, &IDTVEC(rsvd8),  SDT_SYS386TGT, SEL_KPL);
1046	setidt(26, &IDTVEC(rsvd9),  SDT_SYS386TGT, SEL_KPL);
1047	setidt(27, &IDTVEC(rsvd10),  SDT_SYS386TGT, SEL_KPL);
1048	setidt(28, &IDTVEC(rsvd11),  SDT_SYS386TGT, SEL_KPL);
1049	setidt(29, &IDTVEC(rsvd12),  SDT_SYS386TGT, SEL_KPL);
1050	setidt(30, &IDTVEC(rsvd13),  SDT_SYS386TGT, SEL_KPL);
1051	setidt(31, &IDTVEC(rsvd14),  SDT_SYS386TGT, SEL_KPL);
1052
1053#include	"isa.h"
1054#if	NISA >0
1055	isa_defaultirq();
1056#endif
1057
1058	r_gdt[0] = (unsigned short) (sizeof(gdt) - 1);
1059	r_gdt[1] = (unsigned short) ((int) gdt & 0xffff);
1060	r_gdt[2] = (unsigned short) ((int) gdt >> 16);
1061	lgdt(&r_gdt);
1062	r_idt[0] = (unsigned short) (sizeof(idt) - 1);
1063	r_idt[1] = (unsigned short) ((int) idt & 0xfffff);
1064	r_idt[2] = (unsigned short) ((int) idt >> 16);
1065	lidt(&r_idt);
1066	lldt(GSEL(GLDT_SEL, SEL_KPL));
1067
1068#include "ddb.h"
1069#if NDDB > 0
1070	kdb_init();
1071	if (boothowto & RB_KDB)
1072		Debugger("Boot flags requested debugger");
1073#endif
1074
1075	/* Use BIOS values stored in RTC CMOS RAM, since probing
1076	 * breaks certain 386 AT relics.
1077	 */
1078	biosbasemem = rtcin(RTC_BASELO)+ (rtcin(RTC_BASEHI)<<8);
1079	biosextmem = rtcin(RTC_EXTLO)+ (rtcin(RTC_EXTHI)<<8);
1080/*printf("bios base %d ext %d ", biosbasemem, biosextmem);*/
1081
1082	/*
1083	 * 15 Aug 92	Terry Lambert		The real fix for the CMOS bug
1084	 */
1085	if( biosbasemem != EXPECT_BASEMEM) {
1086		printf( "Warning: Base memory %dK, assuming %dK\n", biosbasemem, EXPECT_BASEMEM);
1087		biosbasemem = EXPECT_BASEMEM;		/* assume base*/
1088	}
1089
1090	if( biosextmem > 65536) {
1091		printf( "Warning: Extended memory %dK(>64M), assuming 0K\n", biosextmem);
1092		biosextmem = 0;				/* assume none*/
1093	}
1094
1095	/*
1096	 * Go into normal calculation; Note that we try to run in 640K, and
1097	 * that invalid CMOS values of non 0xffff are no longer a cause of
1098	 * ptdi problems.  I have found a gutted kernel can run in 640K.
1099	 */
1100	pagesinbase = 640/4 - first/NBPG;
1101	pagesinext = biosextmem/4;
1102	/* use greater of either base or extended memory. do this
1103	 * until I reinstitue discontiguous allocation of vm_page
1104	 * array.
1105	 */
1106	if (pagesinbase > pagesinext)
1107		Maxmem = 640/4;
1108	else {
1109		Maxmem = pagesinext + 0x100000/NBPG;
1110		if (first < 0x100000)
1111			first = 0x100000; /* skip hole */
1112	}
1113
1114	/* This used to explode, since Maxmem used to be 0 for bas CMOS*/
1115	maxmem = Maxmem - 1;	/* highest page of usable memory */
1116	physmem = maxmem;	/* number of pages of physmem addr space */
1117/*printf("using first 0x%x to 0x%x\n ", first, maxmem*NBPG);*/
1118	if (maxmem < 2048/4) {
1119		printf("Too little RAM memory. Warning, running in degraded mode.\n");
1120#ifdef INFORM_WAIT
1121		/*
1122		 * People with less than 2 Meg have to hit return; this way
1123		 * we see the messages and can tell them why they blow up later.
1124		 * If they get working well enough to recompile, they can unset
1125		 * the flag; otherwise, it's a toy and they have to lump it.
1126		 */
1127		cngetc();
1128#endif	/* !INFORM_WAIT*/
1129	}
1130
1131	/* call pmap initialization to make new kernel address space */
1132#ifndef MACHINCE_NONCONTIG
1133	pmap_bootstrap (first, 0);
1134#else
1135	pmap_bootstrap ((vm_offset_t)atdevbase + IOM_SIZE);
1136
1137#endif /* MACHINE_NONCONTIG */
1138	/* now running on new page tables, configured,and u/iom is accessible */
1139
1140	/* make a initial tss so microp can get interrupt stack on syscall! */
1141	proc0.p_addr->u_pcb.pcb_tss.tss_esp0 = (int) kstack + UPAGES*NBPG;
1142	proc0.p_addr->u_pcb.pcb_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL) ;
1143	_gsel_tss = GSEL(GPROC0_SEL, SEL_KPL);
1144
1145	((struct i386tss *)gdt_segs[GPROC0_SEL].ssd_base)->tss_ioopt =
1146		(sizeof(tss))<<16;
1147
1148	ltr(_gsel_tss);
1149
1150	/* make a call gate to reenter kernel with */
1151	gdp = (struct gate_descriptor *) &ldt[LSYS5CALLS_SEL][0];
1152
1153	x = (int) &IDTVEC(syscall);
1154	gdp->gd_looffset = x++;
1155	gdp->gd_selector = GSEL(GCODE_SEL,SEL_KPL);
1156	gdp->gd_stkcpy = 0;
1157	gdp->gd_type = SDT_SYS386CGT;
1158	gdp->gd_dpl = SEL_UPL;
1159	gdp->gd_p = 1;
1160	gdp->gd_hioffset = ((int) &IDTVEC(syscall)) >>16;
1161
1162	/* transfer to user mode */
1163
1164	_ucodesel = LSEL(LUCODE_SEL, SEL_UPL);
1165	_udatasel = LSEL(LUDATA_SEL, SEL_UPL);
1166
1167	/* setup proc 0's pcb */
1168	bcopy(&sigcode, proc0.p_addr->u_pcb.pcb_sigc, szsigcode);
1169	proc0.p_addr->u_pcb.pcb_flags = 0;
1170	proc0.p_addr->u_pcb.pcb_ptd = IdlePTD;
1171}
1172
1173extern struct pte	*CMAP1, *CMAP2;
1174extern caddr_t		CADDR1, CADDR2;
1175/*
1176 * zero out physical memory
1177 * specified in relocation units (NBPG bytes)
1178 */
1179void
1180clearseg(n)
1181	int n;
1182{
1183
1184	*(int *)CMAP2 = PG_V | PG_KW | ctob(n);
1185	load_cr3(rcr3());
1186	bzero(CADDR2,NBPG);
1187#ifndef MACHINE_NONCONTIG
1188	*(int *) CADDR2 = 0;
1189#endif /* MACHINE_NONCONTIG */
1190}
1191
1192/*
1193 * copy a page of physical memory
1194 * specified in relocation units (NBPG bytes)
1195 */
1196void
1197copyseg(frm, n)
1198	int frm;
1199	int n;
1200{
1201
1202	*(int *)CMAP2 = PG_V | PG_KW | ctob(n);
1203	load_cr3(rcr3());
1204	bcopy((void *)frm, (void *)CADDR2, NBPG);
1205}
1206
1207/*
1208 * copy a page of physical memory
1209 * specified in relocation units (NBPG bytes)
1210 */
1211void
1212physcopyseg(frm, to)
1213	int frm;
1214	int to;
1215{
1216
1217	*(int *)CMAP1 = PG_V | PG_KW | ctob(frm);
1218	*(int *)CMAP2 = PG_V | PG_KW | ctob(to);
1219	load_cr3(rcr3());
1220	bcopy(CADDR1, CADDR2, NBPG);
1221}
1222
1223/*aston() {
1224	schednetisr(NETISR_AST);
1225}*/
1226
1227void
1228setsoftclock() {
1229	schednetisr(NETISR_SCLK);
1230}
1231
1232/*
1233 * insert an element into a queue
1234 */
1235#undef insque
1236void				/* XXX replace with inline FIXME! */
1237_insque(element, head)
1238	register struct prochd *element, *head;
1239{
1240	element->ph_link = head->ph_link;
1241	head->ph_link = (struct proc *)element;
1242	element->ph_rlink = (struct proc *)head;
1243	((struct prochd *)(element->ph_link))->ph_rlink=(struct proc *)element;
1244}
1245
1246/*
1247 * remove an element from a queue
1248 */
1249#undef remque
1250void				/* XXX replace with inline FIXME! */
1251_remque(element)
1252	register struct prochd *element;
1253{
1254	((struct prochd *)(element->ph_link))->ph_rlink = element->ph_rlink;
1255	((struct prochd *)(element->ph_rlink))->ph_link = element->ph_link;
1256	element->ph_rlink = (struct proc *)0;
1257}
1258
1259/*
1260 * The registers are in the frame; the frame is in the user area of
1261 * the process in question; when the process is active, the registers
1262 * are in "the kernel stack"; when it's not, they're still there, but
1263 * things get flipped around.  So, since p->p_regs is the whole address
1264 * of the register set, take its offset from the kernel stack, and
1265 * index into the user block.  Don't you just *love* virtual memory?
1266 * (I'm starting to think seymour is right...)
1267 */
1268
1269int
1270ptrace_set_pc (struct proc *p, unsigned int addr) {
1271	struct pcb *pcb;
1272	void *regs = (char*)p->p_addr +
1273		((char*) p->p_regs - (char*) kstack);
1274
1275	pcb = &p->p_addr->u_pcb;
1276	if (pcb->pcb_flags & FM_TRAP)
1277		((struct trapframe *)regs)->tf_eip = addr;
1278	else
1279		((struct syscframe *)regs)->sf_eip = addr;
1280	return 0;
1281}
1282
1283int
1284ptrace_single_step (struct proc *p) {
1285	struct pcb *pcb;
1286	void *regs = (char*)p->p_addr +
1287		((char*) p->p_regs - (char*) kstack);
1288
1289	pcb = &p->p_addr->u_pcb;
1290	if (pcb->pcb_flags & FM_TRAP)
1291		((struct trapframe *)regs)->tf_eflags |= PSL_T;
1292	else
1293		((struct syscframe *)regs)->sf_eflags |= PSL_T;
1294	return 0;
1295}
1296
1297/*
1298 * Copy the registers to user-space.  This is tedious because
1299 * we essentially duplicate code for trapframe and syscframe. *sigh*
1300 */
1301
1302int
1303ptrace_getregs (struct proc *p, unsigned int *addr) {
1304	int error;
1305	struct regs regs = {0};
1306
1307	if (error = fill_regs (p, &regs))
1308		return error;
1309
1310	return copyout (&regs, addr, sizeof (regs));
1311}
1312
1313int
1314ptrace_setregs (struct proc *p, unsigned int *addr) {
1315	int error;
1316	struct regs regs = {0};
1317
1318	if (error = copyin (addr, &regs, sizeof(regs)))
1319		return error;
1320
1321	return set_regs (p, &regs);
1322}
1323
1324int
1325fill_regs(struct proc *p, struct regs *regs) {
1326	int error;
1327	struct trapframe *tp;
1328	struct syscframe *sp;
1329	struct pcb *pcb;
1330	void *ptr = (char*)p->p_addr +
1331		((char*) p->p_regs - (char*) kstack);
1332
1333	pcb = &p->p_addr->u_pcb;
1334	if (pcb->pcb_flags & FM_TRAP) {
1335		tp = ptr;
1336		regs->r_es = tp->tf_es;
1337		regs->r_ds = tp->tf_ds;
1338		regs->r_edi = tp->tf_edi;
1339		regs->r_esi = tp->tf_esi;
1340		regs->r_ebp = tp->tf_ebp;
1341		regs->r_ebx = tp->tf_ebx;
1342		regs->r_edx = tp->tf_edx;
1343		regs->r_ecx = tp->tf_ecx;
1344		regs->r_eax = tp->tf_eax;
1345		regs->r_eip = tp->tf_eip;
1346		regs->r_cs = tp->tf_cs;
1347		regs->r_eflags = tp->tf_eflags;
1348		regs->r_esp = tp->tf_esp;
1349		regs->r_ss = tp->tf_ss;
1350	} else {
1351		sp = ptr;
1352		/*
1353		 * No sf_es or sf_ds... dunno why.
1354		 */
1355		/*
1356		 * regs.r_es = sp->sf_es;
1357		 * regs.r_ds = sp->sf_ds;
1358		 */
1359		regs->r_edi = sp->sf_edi;
1360		regs->r_esi = sp->sf_esi;
1361		regs->r_ebp = sp->sf_ebp;
1362		regs->r_ebx = sp->sf_ebx;
1363		regs->r_edx = sp->sf_edx;
1364		regs->r_ecx = sp->sf_ecx;
1365		regs->r_eax = sp->sf_eax;
1366		regs->r_eip = sp->sf_eip;
1367		regs->r_cs = sp->sf_cs;
1368		regs->r_eflags = sp->sf_eflags;
1369		regs->r_esp = sp->sf_esp;
1370		regs->r_ss = sp->sf_ss;
1371	}
1372	return 0;
1373}
1374
1375int
1376set_regs (struct proc *p, struct regs *regs) {
1377	int error;
1378	struct trapframe *tp;
1379	struct syscframe *sp;
1380	struct pcb *pcb;
1381	void *ptr = (char*)p->p_addr +
1382		((char*) p->p_regs - (char*) kstack);
1383
1384	pcb = &p->p_addr->u_pcb;
1385	if (pcb->pcb_flags & FM_TRAP) {
1386		tp = ptr;
1387		tp->tf_es = regs->r_es;
1388		tp->tf_ds = regs->r_ds;
1389		tp->tf_edi = regs->r_edi;
1390		tp->tf_esi = regs->r_esi;
1391		tp->tf_ebp = regs->r_ebp;
1392		tp->tf_ebx = regs->r_ebx;
1393		tp->tf_edx = regs->r_edx;
1394		tp->tf_ecx = regs->r_ecx;
1395		tp->tf_eax = regs->r_eax;
1396		tp->tf_eip = regs->r_eip;
1397		tp->tf_cs = regs->r_cs;
1398		tp->tf_eflags = regs->r_eflags;
1399		tp->tf_esp = regs->r_esp;
1400		tp->tf_ss = regs->r_ss;
1401	} else {
1402		sp = ptr;
1403		/*
1404		 * No sf_es or sf_ds members, dunno why...
1405		 */
1406		/*
1407		 * sp->sf_es = regs.r_es;
1408		 * sp->sf_ds = regs.r_ds;
1409		 */
1410		sp->sf_edi = regs->r_edi;
1411		sp->sf_esi = regs->r_esi;
1412		sp->sf_ebp = regs->r_ebp;
1413		sp->sf_ebx = regs->r_ebx;
1414		sp->sf_edx = regs->r_edx;
1415		sp->sf_ecx = regs->r_ecx;
1416		sp->sf_eax = regs->r_eax;
1417		sp->sf_eip = regs->r_eip;
1418		sp->sf_cs = regs->r_cs;
1419		sp->sf_eflags = regs->r_eflags;
1420		sp->sf_esp = regs->r_esp;
1421		sp->sf_ss = regs->r_ss;
1422	}
1423	return 0;
1424}
1425
1426#ifdef SLOW_OLD_COPYSTRS
1427vmunaccess() {}
1428
1429#if 0		/* assembler versions now in locore.s */
1430/*
1431 * Below written in C to allow access to debugging code
1432 */
1433copyinstr(fromaddr, toaddr, maxlength, lencopied) u_int *lencopied, maxlength;
1434	void *toaddr, *fromaddr; {
1435	int c,tally;
1436
1437	tally = 0;
1438	while (maxlength--) {
1439		c = fubyte(fromaddr++);
1440		if (c == -1) {
1441			if(lencopied) *lencopied = tally;
1442			return(EFAULT);
1443		}
1444		tally++;
1445		*(char *)toaddr++ = (char) c;
1446		if (c == 0){
1447			if(lencopied) *lencopied = (u_int)tally;
1448			return(0);
1449		}
1450	}
1451	if(lencopied) *lencopied = (u_int)tally;
1452	return(ENAMETOOLONG);
1453}
1454
1455copyoutstr(fromaddr, toaddr, maxlength, lencopied) u_int *lencopied, maxlength;
1456	void *fromaddr, *toaddr; {
1457	int c;
1458	int tally;
1459
1460	tally = 0;
1461	while (maxlength--) {
1462		c = subyte(toaddr++, *(char *)fromaddr);
1463		if (c == -1) return(EFAULT);
1464		tally++;
1465		if (*(char *)fromaddr++ == 0){
1466			if(lencopied) *lencopied = tally;
1467			return(0);
1468		}
1469	}
1470	if(lencopied) *lencopied = tally;
1471	return(ENAMETOOLONG);
1472}
1473
1474#endif /* SLOW_OLD_COPYSTRS */
1475
1476copystr(fromaddr, toaddr, maxlength, lencopied) u_int *lencopied, maxlength;
1477	void *fromaddr, *toaddr; {
1478	u_int tally;
1479
1480	tally = 0;
1481	while (maxlength--) {
1482		*(u_char *)toaddr = *(u_char *)fromaddr++;
1483		tally++;
1484		if (*(u_char *)toaddr++ == 0) {
1485			if(lencopied) *lencopied = tally;
1486			return(0);
1487		}
1488	}
1489	if(lencopied) *lencopied = tally;
1490	return(ENAMETOOLONG);
1491}
1492
1493#endif
1494
1495#include "ddb.h"
1496#if NDDB <= 0
1497void
1498Debugger(const char *msg)
1499{
1500	printf("Debugger(\"%s\") called.", msg);
1501}
1502#endif /* no DDB */
1503