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