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