]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/pc98/pc98/machdep.c
This commit was generated by cvs2svn to compensate for changes in r53910,
[FreeBSD/FreeBSD.git] / sys / pc98 / pc98 / machdep.c
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  * $FreeBSD$
39  */
40
41 #include "apm.h"
42 #include "ether.h"
43 #include "npx.h"
44 #include "opt_atalk.h"
45 #include "opt_compat.h"
46 #include "opt_cpu.h"
47 #include "opt_ddb.h"
48 #include "opt_inet.h"
49 #include "opt_ipx.h"
50 #include "opt_maxmem.h"
51 #include "opt_msgbuf.h"
52 #include "opt_perfmon.h"
53 #include "opt_smp.h"
54 #include "opt_sysvipc.h"
55 #include "opt_user_ldt.h"
56 #include "opt_userconfig.h"
57
58 #include <sys/param.h>
59 #include <sys/systm.h>
60 #include <sys/sysproto.h>
61 #include <sys/signalvar.h>
62 #include <sys/kernel.h>
63 #include <sys/linker.h>
64 #include <sys/proc.h>
65 #include <sys/buf.h>
66 #include <sys/reboot.h>
67 #include <sys/callout.h>
68 #include <sys/malloc.h>
69 #include <sys/mbuf.h>
70 #include <sys/msgbuf.h>
71 #include <sys/sysent.h>
72 #include <sys/sysctl.h>
73 #include <sys/vmmeter.h>
74 #include <sys/bus.h>
75
76 #ifdef SYSVSHM
77 #include <sys/shm.h>
78 #endif
79
80 #ifdef SYSVMSG
81 #include <sys/msg.h>
82 #endif
83
84 #ifdef SYSVSEM
85 #include <sys/sem.h>
86 #endif
87
88 #include <vm/vm.h>
89 #include <vm/vm_param.h>
90 #include <sys/lock.h>
91 #include <vm/vm_kern.h>
92 #include <vm/vm_object.h>
93 #include <vm/vm_page.h>
94 #include <vm/vm_map.h>
95 #include <vm/vm_pager.h>
96 #include <vm/vm_extern.h>
97
98 #include <sys/user.h>
99 #include <sys/exec.h>
100 #include <sys/cons.h>
101
102 #include <ddb/ddb.h>
103
104 #include <net/netisr.h>
105
106 #include <machine/cpu.h>
107 #include <machine/reg.h>
108 #include <machine/clock.h>
109 #include <machine/specialreg.h>
110 #include <machine/bootinfo.h>
111 #include <machine/ipl.h>
112 #include <machine/md_var.h>
113 #include <machine/pcb_ext.h>            /* pcb.h included via sys/user.h */
114 #ifdef SMP
115 #include <machine/smp.h>
116 #include <machine/globaldata.h>
117 #endif
118 #ifdef PERFMON
119 #include <machine/perfmon.h>
120 #endif
121
122 #ifdef OLD_BUS_ARCH
123 #include <i386/isa/isa_device.h>
124 #endif
125 #include <i386/isa/intr_machdep.h>
126 #ifdef PC98
127 #include <pc98/pc98/pc98_machdep.h>
128 #include <pc98/pc98/pc98.h>
129 #else
130 #include <isa/rtc.h>
131 #endif
132 #include <machine/vm86.h>
133 #include <machine/random.h>
134 #include <sys/ptrace.h>
135 #include <machine/sigframe.h>
136
137 extern void init386 __P((int first));
138 extern void dblfault_handler __P((void));
139
140 extern void printcpuinfo(void); /* XXX header file */
141 extern void earlysetcpuclass(void);     /* same header file */
142 extern void finishidentcpu(void);
143 extern void panicifcpuunsupported(void);
144 extern void initializecpu(void);
145
146 static void cpu_startup __P((void *));
147 SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL)
148
149 static MALLOC_DEFINE(M_MBUF, "mbuf", "mbuf");
150
151 #ifdef PC98
152 int     need_pre_dma_flush;     /* If 1, use wbinvd befor DMA transfer. */
153 int     need_post_dma_flush;    /* If 1, use invd after DMA transfer. */
154 #endif
155
156 int     _udatasel, _ucodesel;
157 u_int   atdevbase;
158
159 #if defined(SWTCH_OPTIM_STATS)
160 extern int swtch_optim_stats;
161 SYSCTL_INT(_debug, OID_AUTO, swtch_optim_stats,
162         CTLFLAG_RD, &swtch_optim_stats, 0, "");
163 SYSCTL_INT(_debug, OID_AUTO, tlb_flush_count,
164         CTLFLAG_RD, &tlb_flush_count, 0, "");
165 #endif
166
167 #ifdef PC98
168 static int      ispc98 = 1;
169 #else
170 static int      ispc98 = 0;
171 #endif
172 SYSCTL_INT(_machdep, OID_AUTO, ispc98, CTLFLAG_RD, &ispc98, 0, "");
173
174 int physmem = 0;
175 int cold = 1;
176
177 static int
178 sysctl_hw_physmem SYSCTL_HANDLER_ARGS
179 {
180         int error = sysctl_handle_int(oidp, 0, ctob(physmem), req);
181         return (error);
182 }
183
184 SYSCTL_PROC(_hw, HW_PHYSMEM, physmem, CTLTYPE_INT|CTLFLAG_RD,
185         0, 0, sysctl_hw_physmem, "I", "");
186
187 static int
188 sysctl_hw_usermem SYSCTL_HANDLER_ARGS
189 {
190         int error = sysctl_handle_int(oidp, 0,
191                 ctob(physmem - cnt.v_wire_count), req);
192         return (error);
193 }
194
195 SYSCTL_PROC(_hw, HW_USERMEM, usermem, CTLTYPE_INT|CTLFLAG_RD,
196         0, 0, sysctl_hw_usermem, "I", "");
197
198 static int
199 sysctl_hw_availpages SYSCTL_HANDLER_ARGS
200 {
201         int error = sysctl_handle_int(oidp, 0,
202                 i386_btop(avail_end - avail_start), req);
203         return (error);
204 }
205
206 SYSCTL_PROC(_hw, OID_AUTO, availpages, CTLTYPE_INT|CTLFLAG_RD,
207         0, 0, sysctl_hw_availpages, "I", "");
208
209 static int
210 sysctl_machdep_msgbuf SYSCTL_HANDLER_ARGS
211 {
212         int error;
213
214         /* Unwind the buffer, so that it's linear (possibly starting with
215          * some initial nulls).
216          */
217         error=sysctl_handle_opaque(oidp,msgbufp->msg_ptr+msgbufp->msg_bufr,
218                 msgbufp->msg_size-msgbufp->msg_bufr,req);
219         if(error) return(error);
220         if(msgbufp->msg_bufr>0) {
221                 error=sysctl_handle_opaque(oidp,msgbufp->msg_ptr,
222                         msgbufp->msg_bufr,req);
223         }
224         return(error);
225 }
226
227 SYSCTL_PROC(_machdep, OID_AUTO, msgbuf, CTLTYPE_STRING|CTLFLAG_RD,
228         0, 0, sysctl_machdep_msgbuf, "A","Contents of kernel message buffer");
229
230 static int msgbuf_clear;
231
232 static int
233 sysctl_machdep_msgbuf_clear SYSCTL_HANDLER_ARGS
234 {
235         int error;
236         error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2,
237                 req);
238         if (!error && req->newptr) {
239                 /* Clear the buffer and reset write pointer */
240                 bzero(msgbufp->msg_ptr,msgbufp->msg_size);
241                 msgbufp->msg_bufr=msgbufp->msg_bufx=0;
242                 msgbuf_clear=0;
243         }
244         return (error);
245 }
246
247 SYSCTL_PROC(_machdep, OID_AUTO, msgbuf_clear, CTLTYPE_INT|CTLFLAG_RW,
248         &msgbuf_clear, 0, sysctl_machdep_msgbuf_clear, "I",
249         "Clear kernel message buffer");
250
251 int bootverbose = 0, Maxmem = 0;
252 #ifdef PC98
253 int Maxmem_under16M = 0;
254 #endif
255 long dumplo;
256
257 vm_offset_t phys_avail[10];
258
259 /* must be 2 less so 0 0 can signal end of chunks */
260 #define PHYS_AVAIL_ARRAY_END ((sizeof(phys_avail) / sizeof(vm_offset_t)) - 2)
261
262 static vm_offset_t buffer_sva, buffer_eva;
263 vm_offset_t clean_sva, clean_eva;
264 static vm_offset_t pager_sva, pager_eva;
265
266 #define offsetof(type, member)  ((size_t)(&((type *)0)->member))
267
268 static void
269 cpu_startup(dummy)
270         void *dummy;
271 {
272         register unsigned i;
273         register caddr_t v;
274         vm_offset_t maxaddr;
275         vm_size_t size = 0;
276         int firstaddr;
277         vm_offset_t minaddr;
278
279         if (boothowto & RB_VERBOSE)
280                 bootverbose++;
281
282         /*
283          * Good {morning,afternoon,evening,night}.
284          */
285         printf(version);
286         earlysetcpuclass();
287         startrtclock();
288         printcpuinfo();
289         panicifcpuunsupported();
290 #ifdef PERFMON
291         perfmon_init();
292 #endif
293         printf("real memory  = %u (%uK bytes)\n", ptoa(Maxmem), ptoa(Maxmem) / 1024);
294         /*
295          * Display any holes after the first chunk of extended memory.
296          */
297         if (bootverbose) {
298                 int indx;
299
300                 printf("Physical memory chunk(s):\n");
301                 for (indx = 0; phys_avail[indx + 1] != 0; indx += 2) {
302                         int size1 = phys_avail[indx + 1] - phys_avail[indx];
303
304                         printf("0x%08x - 0x%08x, %u bytes (%u pages)\n",
305                             phys_avail[indx], phys_avail[indx + 1] - 1, size1,
306                             size1 / PAGE_SIZE);
307                 }
308         }
309
310         /*
311          * Calculate callout wheel size
312          */
313         for (callwheelsize = 1, callwheelbits = 0;
314              callwheelsize < ncallout;
315              callwheelsize <<= 1, ++callwheelbits)
316                 ;
317         callwheelmask = callwheelsize - 1;
318
319         /*
320          * Allocate space for system data structures.
321          * The first available kernel virtual address is in "v".
322          * As pages of kernel virtual memory are allocated, "v" is incremented.
323          * As pages of memory are allocated and cleared,
324          * "firstaddr" is incremented.
325          * An index into the kernel page table corresponding to the
326          * virtual memory address maintained in "v" is kept in "mapaddr".
327          */
328
329         /*
330          * Make two passes.  The first pass calculates how much memory is
331          * needed and allocates it.  The second pass assigns virtual
332          * addresses to the various data structures.
333          */
334         firstaddr = 0;
335 again:
336         v = (caddr_t)firstaddr;
337
338 #define valloc(name, type, num) \
339             (name) = (type *)v; v = (caddr_t)((name)+(num))
340 #define valloclim(name, type, num, lim) \
341             (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num)))
342
343         valloc(callout, struct callout, ncallout);
344         valloc(callwheel, struct callout_tailq, callwheelsize);
345 #ifdef SYSVSHM
346         valloc(shmsegs, struct shmid_ds, shminfo.shmmni);
347 #endif
348 #ifdef SYSVSEM
349         valloc(sema, struct semid_ds, seminfo.semmni);
350         valloc(sem, struct sem, seminfo.semmns);
351         /* This is pretty disgusting! */
352         valloc(semu, int, (seminfo.semmnu * seminfo.semusz) / sizeof(int));
353 #endif
354 #ifdef SYSVMSG
355         valloc(msgpool, char, msginfo.msgmax);
356         valloc(msgmaps, struct msgmap, msginfo.msgseg);
357         valloc(msghdrs, struct msg, msginfo.msgtql);
358         valloc(msqids, struct msqid_ds, msginfo.msgmni);
359 #endif
360
361         if (nbuf == 0) {
362                 nbuf = 50;
363                 if (physmem > 1024)
364                         nbuf += min((physmem - 1024) / 8, 2048);
365                 if (physmem > 16384)
366                         nbuf += (physmem - 16384) / 20;
367         }
368         nswbuf = max(min(nbuf/4, 256), 16);
369
370         valloc(swbuf, struct buf, nswbuf);
371         valloc(buf, struct buf, nbuf);
372         v = bufhashinit(v);
373
374         /*
375          * End of first pass, size has been calculated so allocate memory
376          */
377         if (firstaddr == 0) {
378                 size = (vm_size_t)(v - firstaddr);
379                 firstaddr = (int)kmem_alloc(kernel_map, round_page(size));
380                 if (firstaddr == 0)
381                         panic("startup: no room for tables");
382                 goto again;
383         }
384
385         /*
386          * End of second pass, addresses have been assigned
387          */
388         if ((vm_size_t)(v - firstaddr) != size)
389                 panic("startup: table size inconsistency");
390
391         clean_map = kmem_suballoc(kernel_map, &clean_sva, &clean_eva,
392                         (nbuf*BKVASIZE) + (nswbuf*MAXPHYS) + pager_map_size);
393         buffer_map = kmem_suballoc(clean_map, &buffer_sva, &buffer_eva,
394                                 (nbuf*BKVASIZE));
395         pager_map = kmem_suballoc(clean_map, &pager_sva, &pager_eva,
396                                 (nswbuf*MAXPHYS) + pager_map_size);
397         pager_map->system_map = 1;
398         exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
399                                 (16*(ARG_MAX+(PAGE_SIZE*3))));
400
401         /*
402          * Finally, allocate mbuf pool.  Since mclrefcnt is an off-size
403          * we use the more space efficient malloc in place of kmem_alloc.
404          */
405         {
406                 vm_offset_t mb_map_size;
407
408                 mb_map_size = nmbufs * MSIZE + nmbclusters * MCLBYTES;
409                 mb_map_size = roundup2(mb_map_size, max(MCLBYTES, PAGE_SIZE));
410                 mclrefcnt = malloc(mb_map_size / MCLBYTES, M_MBUF, M_NOWAIT);
411                 bzero(mclrefcnt, mb_map_size / MCLBYTES);
412                 mb_map = kmem_suballoc(kmem_map, (vm_offset_t *)&mbutl, &maxaddr,
413                         mb_map_size);
414                 mb_map->system_map = 1;
415         }
416
417         /*
418          * Initialize callouts
419          */
420         SLIST_INIT(&callfree);
421         for (i = 0; i < ncallout; i++) {
422                 callout_init(&callout[i]);
423                 callout[i].c_flags = CALLOUT_LOCAL_ALLOC;
424                 SLIST_INSERT_HEAD(&callfree, &callout[i], c_links.sle);
425         }
426
427         for (i = 0; i < callwheelsize; i++) {
428                 TAILQ_INIT(&callwheel[i]);
429         }
430
431 #if defined(USERCONFIG)
432         userconfig();
433         cninit();               /* the preferred console may have changed */
434 #endif
435
436         printf("avail memory = %u (%uK bytes)\n", ptoa(cnt.v_free_count),
437             ptoa(cnt.v_free_count) / 1024);
438
439         /*
440          * Set up buffers, so they can be used to read disk labels.
441          */
442         bufinit();
443         vm_pager_bufferinit();
444
445 #ifdef SMP
446         /*
447          * OK, enough kmem_alloc/malloc state should be up, lets get on with it!
448          */
449         mp_start();                     /* fire up the APs and APICs */
450         mp_announce();
451 #endif  /* SMP */
452 }
453
454 int
455 register_netisr(num, handler)
456         int num;
457         netisr_t *handler;
458 {
459         
460         if (num < 0 || num >= (sizeof(netisrs)/sizeof(*netisrs)) ) {
461                 printf("register_netisr: bad isr number: %d\n", num);
462                 return (EINVAL);
463         }
464         netisrs[num] = handler;
465         return (0);
466 }
467
468 void
469 netisr_sysinit(data)
470         void *data;
471 {
472         const struct netisrtab *nit;
473
474         nit = (const struct netisrtab *)data;
475         register_netisr(nit->nit_num, nit->nit_isr);
476 }
477
478 /*
479  * Send an interrupt to process.
480  *
481  * Stack is set up to allow sigcode stored
482  * at top to call routine, followed by kcall
483  * to sigreturn routine below.  After sigreturn
484  * resets the signal mask, the stack, and the
485  * frame pointer, it returns to the user
486  * specified pc, psl.
487  */
488 static void
489 osendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
490 {
491         register struct proc *p = curproc;
492         register struct trapframe *regs;
493         register struct osigframe *fp;
494         struct osigframe sf;
495         struct sigacts *psp = p->p_sigacts;
496         int oonstack;
497
498         regs = p->p_md.md_regs;
499         oonstack = (p->p_sigstk.ss_flags & SS_ONSTACK) ? 1 : 0;
500
501         /* Allocate and validate space for the signal handler context. */
502         if ((p->p_flag & P_ALTSTACK) && !oonstack &&
503             SIGISMEMBER(psp->ps_sigonstack, sig)) {
504                 fp = (struct osigframe *)(p->p_sigstk.ss_sp +
505                     p->p_sigstk.ss_size - sizeof(struct osigframe));
506                 p->p_sigstk.ss_flags |= SS_ONSTACK;
507         }
508         else
509                 fp = (struct osigframe *)regs->tf_esp - 1;
510
511         /*
512          * grow() will return FALSE if the fp will not fit inside the stack
513          *      and the stack can not be grown. useracc will return FALSE
514          *      if access is denied.
515          */
516         if (grow_stack(p, (int)fp) == FALSE ||
517             !useracc((caddr_t)fp, sizeof(struct osigframe), VM_PROT_WRITE)) {
518                 /*
519                  * Process has trashed its stack; give it an illegal
520                  * instruction to halt it in its tracks.
521                  */
522                 SIGACTION(p, SIGILL) = SIG_DFL;
523                 SIGDELSET(p->p_sigignore, SIGILL);
524                 SIGDELSET(p->p_sigcatch, SIGILL);
525                 SIGDELSET(p->p_sigmask, SIGILL);
526                 psignal(p, SIGILL);
527                 return;
528         }
529
530         /* Translate the signal if appropriate */
531         if (p->p_sysent->sv_sigtbl) {
532                 if (sig <= p->p_sysent->sv_sigsize)
533                         sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)];
534         }
535
536         /* Build the argument list for the signal handler. */
537         sf.sf_signum = sig;
538         sf.sf_scp = (register_t)&fp->sf_siginfo.si_sc;
539         if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) {
540                 /* Signal handler installed with SA_SIGINFO. */
541                 sf.sf_arg2 = (register_t)&fp->sf_siginfo;
542                 sf.sf_siginfo.si_signo = sig;
543                 sf.sf_siginfo.si_code = code;
544                 sf.sf_ahu.sf_action = (__osiginfohandler_t *)catcher;
545         }
546         else {
547                 /* Old FreeBSD-style arguments. */
548                 sf.sf_arg2 = code;
549                 sf.sf_addr = (register_t *)regs->tf_err;
550                 sf.sf_ahu.sf_handler = catcher;
551         }
552
553         /* save scratch registers */
554         sf.sf_siginfo.si_sc.sc_eax = regs->tf_eax;
555         sf.sf_siginfo.si_sc.sc_ebx = regs->tf_ebx;
556         sf.sf_siginfo.si_sc.sc_ecx = regs->tf_ecx;
557         sf.sf_siginfo.si_sc.sc_edx = regs->tf_edx;
558         sf.sf_siginfo.si_sc.sc_esi = regs->tf_esi;
559         sf.sf_siginfo.si_sc.sc_edi = regs->tf_edi;
560         sf.sf_siginfo.si_sc.sc_cs = regs->tf_cs;
561         sf.sf_siginfo.si_sc.sc_ds = regs->tf_ds;
562         sf.sf_siginfo.si_sc.sc_ss = regs->tf_ss;
563         sf.sf_siginfo.si_sc.sc_es = regs->tf_es;
564         sf.sf_siginfo.si_sc.sc_fs = regs->tf_fs;
565         sf.sf_siginfo.si_sc.sc_gs = rgs();
566         sf.sf_siginfo.si_sc.sc_isp = regs->tf_isp;
567
568         /* Build the signal context to be used by sigreturn. */
569         sf.sf_siginfo.si_sc.sc_onstack = oonstack;
570         SIG2OSIG(*mask, sf.sf_siginfo.si_sc.sc_mask);
571         sf.sf_siginfo.si_sc.sc_sp = regs->tf_esp;
572         sf.sf_siginfo.si_sc.sc_fp = regs->tf_ebp;
573         sf.sf_siginfo.si_sc.sc_pc = regs->tf_eip;
574         sf.sf_siginfo.si_sc.sc_ps = regs->tf_eflags;
575         sf.sf_siginfo.si_sc.sc_trapno = regs->tf_trapno;
576         sf.sf_siginfo.si_sc.sc_err = regs->tf_err;
577
578         /*
579          * If we're a vm86 process, we want to save the segment registers.
580          * We also change eflags to be our emulated eflags, not the actual
581          * eflags.
582          */
583         if (regs->tf_eflags & PSL_VM) {
584                 struct trapframe_vm86 *tf = (struct trapframe_vm86 *)regs;
585                 struct vm86_kernel *vm86 = &p->p_addr->u_pcb.pcb_ext->ext_vm86;
586
587                 sf.sf_siginfo.si_sc.sc_gs = tf->tf_vm86_gs;
588                 sf.sf_siginfo.si_sc.sc_fs = tf->tf_vm86_fs;
589                 sf.sf_siginfo.si_sc.sc_es = tf->tf_vm86_es;
590                 sf.sf_siginfo.si_sc.sc_ds = tf->tf_vm86_ds;
591
592                 if (vm86->vm86_has_vme == 0)
593                         sf.sf_siginfo.si_sc.sc_ps =
594                             (tf->tf_eflags & ~(PSL_VIF | PSL_VIP))
595                             | (vm86->vm86_eflags & (PSL_VIF | PSL_VIP));
596                 /* see sendsig for comment */
597                 tf->tf_eflags &= ~(PSL_VM|PSL_NT|PSL_T|PSL_VIF|PSL_VIP);
598         }
599
600         /* Copy the sigframe out to the user's stack. */
601         if (copyout(&sf, fp, sizeof(struct osigframe)) != 0) {
602                 /*
603                  * Something is wrong with the stack pointer.
604                  * ...Kill the process.
605                  */
606                 sigexit(p, SIGILL);
607         }
608
609         regs->tf_esp = (int)fp;
610         regs->tf_eip = PS_STRINGS - oszsigcode;
611         regs->tf_cs = _ucodesel;
612         regs->tf_ds = _udatasel;
613         regs->tf_es = _udatasel;
614         regs->tf_fs = _udatasel;
615         load_gs(_udatasel);
616         regs->tf_ss = _udatasel;
617 }
618
619 void
620 sendsig(catcher, sig, mask, code)
621         sig_t catcher;
622         int sig;
623         sigset_t *mask;
624         u_long code;
625 {
626         struct proc *p = curproc;
627         struct trapframe *regs;
628         struct sigacts *psp = p->p_sigacts;
629         struct sigframe sf, *sfp;
630         int oonstack;
631
632         if (SIGISMEMBER(psp->ps_osigset, sig)) {
633                 osendsig(catcher, sig, mask, code);
634                 return;
635         }
636
637         regs = p->p_md.md_regs;
638         oonstack = (p->p_sigstk.ss_flags & SS_ONSTACK) ? 1 : 0;
639
640         /* save user context */
641         bzero(&sf, sizeof(struct sigframe));
642         sf.sf_uc.uc_sigmask = *mask;
643         sf.sf_uc.uc_stack = p->p_sigstk;
644         sf.sf_uc.uc_mcontext.mc_onstack = oonstack;
645         sf.sf_uc.uc_mcontext.mc_gs = rgs();
646         bcopy(regs, &sf.sf_uc.uc_mcontext.mc_fs, sizeof(struct trapframe));
647
648         /* Allocate and validate space for the signal handler context. */
649         if ((p->p_flag & P_ALTSTACK) != 0 && !oonstack &&
650             SIGISMEMBER(psp->ps_sigonstack, sig)) {
651                 sfp = (struct sigframe *)(p->p_sigstk.ss_sp +
652                     p->p_sigstk.ss_size - sizeof(struct sigframe));
653                 p->p_sigstk.ss_flags |= SS_ONSTACK;
654         }
655         else
656                 sfp = (struct sigframe *)regs->tf_esp - 1;
657
658         /*
659          * grow() will return FALSE if the sfp will not fit inside the stack
660          * and the stack can not be grown. useracc will return FALSE if
661          * access is denied.
662          */
663         if (grow_stack(p, (int)sfp) == FALSE ||
664             !useracc((caddr_t)sfp, sizeof(struct sigframe), VM_PROT_WRITE)) {
665                 /*
666                  * Process has trashed its stack; give it an illegal
667                  * instruction to halt it in its tracks.
668                  */
669 #ifdef DEBUG
670                 printf("process %d has trashed its stack\n", p->p_pid);
671 #endif
672                 SIGACTION(p, SIGILL) = SIG_DFL;
673                 SIGDELSET(p->p_sigignore, SIGILL);
674                 SIGDELSET(p->p_sigcatch, SIGILL);
675                 SIGDELSET(p->p_sigmask, SIGILL);
676                 psignal(p, SIGILL);
677                 return;
678         }
679
680         /* Translate the signal is appropriate */
681         if (p->p_sysent->sv_sigtbl) {
682                 if (sig <= p->p_sysent->sv_sigsize)
683                         sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)];
684         }
685
686         /* Build the argument list for the signal handler. */
687         sf.sf_signum = sig;
688         sf.sf_ucontext = (register_t)&sfp->sf_uc;
689         if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) {
690                 /* Signal handler installed with SA_SIGINFO. */
691                 sf.sf_siginfo = (register_t)&sfp->sf_si;
692                 sf.sf_ahu.sf_action = (__siginfohandler_t *)catcher;
693
694                 /* fill siginfo structure */
695                 sf.sf_si.si_signo = sig;
696                 sf.sf_si.si_code = code;
697                 sf.sf_si.si_addr = (void*)regs->tf_err;
698         }
699         else {
700                 /* Old FreeBSD-style arguments. */
701                 sf.sf_siginfo = code;
702                 sf.sf_addr = (register_t *)regs->tf_err;
703                 sf.sf_ahu.sf_handler = catcher;
704         }
705
706         /*
707          * If we're a vm86 process, we want to save the segment registers.
708          * We also change eflags to be our emulated eflags, not the actual
709          * eflags.
710          */
711         if (regs->tf_eflags & PSL_VM) {
712                 struct trapframe_vm86 *tf = (struct trapframe_vm86 *)regs;
713                 struct vm86_kernel *vm86 = &p->p_addr->u_pcb.pcb_ext->ext_vm86;
714
715                 sf.sf_uc.uc_mcontext.mc_gs = tf->tf_vm86_gs;
716                 sf.sf_uc.uc_mcontext.mc_fs = tf->tf_vm86_fs;
717                 sf.sf_uc.uc_mcontext.mc_es = tf->tf_vm86_es;
718                 sf.sf_uc.uc_mcontext.mc_ds = tf->tf_vm86_ds;
719
720                 if (vm86->vm86_has_vme == 0)
721                         sf.sf_uc.uc_mcontext.mc_eflags =
722                             (tf->tf_eflags & ~(PSL_VIF | PSL_VIP)) |
723                             (vm86->vm86_eflags & (PSL_VIF | PSL_VIP));
724
725                 /*
726                  * We should never have PSL_T set when returning from vm86
727                  * mode.  It may be set here if we deliver a signal before
728                  * getting to vm86 mode, so turn it off.
729                  *
730                  * Clear PSL_NT to inhibit T_TSSFLT faults on return from
731                  * syscalls made by the signal handler.  This just avoids
732                  * wasting time for our lazy fixup of such faults.  PSL_NT
733                  * does nothing in vm86 mode, but vm86 programs can set it
734                  * almost legitimately in probes for old cpu types.
735                  */
736                 tf->tf_eflags &= ~(PSL_VM|PSL_NT|PSL_T|PSL_VIF|PSL_VIP);
737         }
738
739         /*
740          * Copy the sigframe out to the user's stack.
741          */
742         if (copyout(&sf, sfp, sizeof(struct sigframe)) != 0) {
743                 /*
744                  * Something is wrong with the stack pointer.
745                  * ...Kill the process.
746                  */
747                 sigexit(p, SIGILL);
748         }
749
750         regs->tf_esp = (int)sfp;
751         regs->tf_eip = PS_STRINGS - *(p->p_sysent->sv_szsigcode);
752         regs->tf_cs = _ucodesel;
753         regs->tf_ds = _udatasel;
754         regs->tf_es = _udatasel;
755         regs->tf_fs = _udatasel;
756         load_gs(_udatasel);
757         regs->tf_ss = _udatasel;
758 }
759
760 /*
761  * System call to cleanup state after a signal
762  * has been taken.  Reset signal mask and
763  * stack state from context left by sendsig (above).
764  * Return to previous pc and psl as specified by
765  * context left by sendsig. Check carefully to
766  * make sure that the user has not modified the
767  * state to gain improper privileges.
768  */
769 #define EFL_SECURE(ef, oef)     ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0)
770 #define CS_SECURE(cs)           (ISPL(cs) == SEL_UPL)
771
772 int
773 osigreturn(p, uap)
774         struct proc *p;
775         struct osigreturn_args /* {
776                 struct osigcontext *sigcntxp;
777         } */ *uap;
778 {
779         register struct osigcontext *scp;
780         register struct trapframe *regs = p->p_md.md_regs;
781         int eflags;
782
783         scp = uap->sigcntxp;
784
785         if (!useracc((caddr_t)scp, sizeof (struct osigcontext), VM_PROT_READ))
786                 return(EFAULT);
787
788         eflags = scp->sc_ps;
789         if (eflags & PSL_VM) {
790                 struct trapframe_vm86 *tf = (struct trapframe_vm86 *)regs;
791                 struct vm86_kernel *vm86;
792
793                 /*
794                  * if pcb_ext == 0 or vm86_inited == 0, the user hasn't
795                  * set up the vm86 area, and we can't enter vm86 mode.
796                  */
797                 if (p->p_addr->u_pcb.pcb_ext == 0)
798                         return (EINVAL);
799                 vm86 = &p->p_addr->u_pcb.pcb_ext->ext_vm86;
800                 if (vm86->vm86_inited == 0)
801                         return (EINVAL);
802
803                 /* go back to user mode if both flags are set */
804                 if ((eflags & PSL_VIP) && (eflags & PSL_VIF))
805                         trapsignal(p, SIGBUS, 0);
806
807                 if (vm86->vm86_has_vme) {
808                         eflags = (tf->tf_eflags & ~VME_USERCHANGE) |
809                             (eflags & VME_USERCHANGE) | PSL_VM;
810                 } else {
811                         vm86->vm86_eflags = eflags;     /* save VIF, VIP */
812                         eflags = (tf->tf_eflags & ~VM_USERCHANGE) |                                         (eflags & VM_USERCHANGE) | PSL_VM;
813                 }
814                 tf->tf_vm86_ds = scp->sc_ds;
815                 tf->tf_vm86_es = scp->sc_es;
816                 tf->tf_vm86_fs = scp->sc_fs;
817                 tf->tf_vm86_gs = scp->sc_gs;
818                 tf->tf_ds = _udatasel;
819                 tf->tf_es = _udatasel;
820                 tf->tf_fs = _udatasel;
821         } else {
822                 /*
823                  * Don't allow users to change privileged or reserved flags.
824                  */
825                 /*
826                  * XXX do allow users to change the privileged flag PSL_RF.
827                  * The cpu sets PSL_RF in tf_eflags for faults.  Debuggers
828                  * should sometimes set it there too.  tf_eflags is kept in
829                  * the signal context during signal handling and there is no
830                  * other place to remember it, so the PSL_RF bit may be
831                  * corrupted by the signal handler without us knowing.
832                  * Corruption of the PSL_RF bit at worst causes one more or
833                  * one less debugger trap, so allowing it is fairly harmless.
834                  */
835                 if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_eflags & ~PSL_RF)) {
836                         return(EINVAL);
837                 }
838
839                 /*
840                  * Don't allow users to load a valid privileged %cs.  Let the
841                  * hardware check for invalid selectors, excess privilege in
842                  * other selectors, invalid %eip's and invalid %esp's.
843                  */
844                 if (!CS_SECURE(scp->sc_cs)) {
845                         trapsignal(p, SIGBUS, T_PROTFLT);
846                         return(EINVAL);
847                 }
848                 regs->tf_ds = scp->sc_ds;
849                 regs->tf_es = scp->sc_es;
850                 regs->tf_fs = scp->sc_fs;
851         }
852
853         /* restore scratch registers */
854         regs->tf_eax = scp->sc_eax;
855         regs->tf_ebx = scp->sc_ebx;
856         regs->tf_ecx = scp->sc_ecx;
857         regs->tf_edx = scp->sc_edx;
858         regs->tf_esi = scp->sc_esi;
859         regs->tf_edi = scp->sc_edi;
860         regs->tf_cs = scp->sc_cs;
861         regs->tf_ss = scp->sc_ss;
862         regs->tf_isp = scp->sc_isp;
863
864         if (scp->sc_onstack & 01)
865                 p->p_sigstk.ss_flags |= SS_ONSTACK;
866         else
867                 p->p_sigstk.ss_flags &= ~SS_ONSTACK;
868
869         SIGSETOLD(p->p_sigmask, scp->sc_mask);
870         SIG_CANTMASK(p->p_sigmask);
871         regs->tf_ebp = scp->sc_fp;
872         regs->tf_esp = scp->sc_sp;
873         regs->tf_eip = scp->sc_pc;
874         regs->tf_eflags = eflags;
875         return(EJUSTRETURN);
876 }
877
878 int
879 sigreturn(p, uap)
880         struct proc *p;
881         struct sigreturn_args /* {
882                 ucontext_t *sigcntxp;
883         } */ *uap;
884 {
885         struct trapframe *regs;
886         ucontext_t *ucp;
887         int cs, eflags;
888
889         ucp = uap->sigcntxp;
890
891         if (!useracc((caddr_t)ucp, sizeof(struct osigcontext), VM_PROT_READ))
892                 return (EFAULT);
893         if (((struct osigcontext *)ucp)->sc_trapno == 0x01d516)
894                 return (osigreturn(p, (struct osigreturn_args *)uap));
895
896         /*
897          * Since ucp is not an osigcontext but a ucontext_t, we have to
898          * check again if all of it is accessible.  A ucontext_t is
899          * much larger, so instead of just checking for the pointer
900          * being valid for the size of an osigcontext, now check for
901          * it being valid for a whole, new-style ucontext_t.
902          */
903         if (!useracc((caddr_t)ucp, sizeof(ucontext_t), VM_PROT_READ))
904                 return (EFAULT);
905
906         regs = p->p_md.md_regs;
907         eflags = ucp->uc_mcontext.mc_eflags;
908
909         if (eflags & PSL_VM) {
910                 struct trapframe_vm86 *tf = (struct trapframe_vm86 *)regs;
911                 struct vm86_kernel *vm86;
912
913                 /*
914                  * if pcb_ext == 0 or vm86_inited == 0, the user hasn't
915                  * set up the vm86 area, and we can't enter vm86 mode.
916                  */
917                 if (p->p_addr->u_pcb.pcb_ext == 0)
918                         return (EINVAL);
919                 vm86 = &p->p_addr->u_pcb.pcb_ext->ext_vm86;
920                 if (vm86->vm86_inited == 0)
921                         return (EINVAL);
922
923                 /* go back to user mode if both flags are set */
924                 if ((eflags & PSL_VIP) && (eflags & PSL_VIF))
925                         trapsignal(p, SIGBUS, 0);
926
927                 if (vm86->vm86_has_vme) {
928                         eflags = (tf->tf_eflags & ~VME_USERCHANGE) |
929                             (eflags & VME_USERCHANGE) | PSL_VM;
930                 } else {
931                         vm86->vm86_eflags = eflags;     /* save VIF, VIP */
932                         eflags = (tf->tf_eflags & ~VM_USERCHANGE) |                                         (eflags & VM_USERCHANGE) | PSL_VM;
933                 }
934                 bcopy(&ucp->uc_mcontext.mc_fs, tf, sizeof(struct trapframe));
935                 tf->tf_eflags = eflags;
936                 tf->tf_vm86_ds = tf->tf_ds;
937                 tf->tf_vm86_es = tf->tf_es;
938                 tf->tf_vm86_fs = tf->tf_fs;
939                 tf->tf_vm86_gs = ucp->uc_mcontext.mc_gs;
940                 tf->tf_ds = _udatasel;
941                 tf->tf_es = _udatasel;
942                 tf->tf_fs = _udatasel;
943         } else {
944                 /*
945                  * Don't allow users to change privileged or reserved flags.
946                  */
947                 /*
948                  * XXX do allow users to change the privileged flag PSL_RF.
949                  * The cpu sets PSL_RF in tf_eflags for faults.  Debuggers
950                  * should sometimes set it there too.  tf_eflags is kept in
951                  * the signal context during signal handling and there is no
952                  * other place to remember it, so the PSL_RF bit may be
953                  * corrupted by the signal handler without us knowing.
954                  * Corruption of the PSL_RF bit at worst causes one more or
955                  * one less debugger trap, so allowing it is fairly harmless.
956                  */
957                 if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_eflags & ~PSL_RF)) {
958                         printf("sigreturn: eflags = 0x%x\n", eflags);
959                         return(EINVAL);
960                 }
961
962                 /*
963                  * Don't allow users to load a valid privileged %cs.  Let the
964                  * hardware check for invalid selectors, excess privilege in
965                  * other selectors, invalid %eip's and invalid %esp's.
966                  */
967                 cs = ucp->uc_mcontext.mc_cs;
968                 if (!CS_SECURE(cs)) {
969                         printf("sigreturn: cs = 0x%x\n", cs);
970                         trapsignal(p, SIGBUS, T_PROTFLT);
971                         return(EINVAL);
972                 }
973                 bcopy(&ucp->uc_mcontext.mc_fs, regs, sizeof(struct trapframe));
974         }
975
976         if (ucp->uc_mcontext.mc_onstack & 1)
977                 p->p_sigstk.ss_flags |= SS_ONSTACK;
978         else
979                 p->p_sigstk.ss_flags &= ~SS_ONSTACK;
980
981         p->p_sigmask = ucp->uc_sigmask;
982         SIG_CANTMASK(p->p_sigmask);
983         return(EJUSTRETURN);
984 }
985
986 /*
987  * Machine dependent boot() routine
988  *
989  * I haven't seen anything to put here yet
990  * Possibly some stuff might be grafted back here from boot()
991  */
992 void
993 cpu_boot(int howto)
994 {
995 }
996
997 /*
998  * Shutdown the CPU as much as possible
999  */
1000 void
1001 cpu_halt(void)
1002 {
1003         for (;;)
1004                 __asm__ ("hlt");
1005 }
1006
1007 /*
1008  * Clear registers on exec
1009  */
1010 void
1011 setregs(p, entry, stack, ps_strings)
1012         struct proc *p;
1013         u_long entry;
1014         u_long stack;
1015         u_long ps_strings;
1016 {
1017         struct trapframe *regs = p->p_md.md_regs;
1018         struct pcb *pcb = &p->p_addr->u_pcb;
1019
1020 #ifdef USER_LDT
1021         /* was i386_user_cleanup() in NetBSD */
1022         if (pcb->pcb_ldt) {
1023                 if (pcb == curpcb) {
1024                         lldt(_default_ldt);
1025                         currentldt = _default_ldt;
1026                 }
1027                 kmem_free(kernel_map, (vm_offset_t)pcb->pcb_ldt,
1028                         pcb->pcb_ldt_len * sizeof(union descriptor));
1029                 pcb->pcb_ldt_len = (int)pcb->pcb_ldt = 0;
1030         }
1031 #endif
1032   
1033         bzero((char *)regs, sizeof(struct trapframe));
1034         regs->tf_eip = entry;
1035         regs->tf_esp = stack;
1036         regs->tf_eflags = PSL_USER | (regs->tf_eflags & PSL_T);
1037         regs->tf_ss = _udatasel;
1038         regs->tf_ds = _udatasel;
1039         regs->tf_es = _udatasel;
1040         regs->tf_fs = _udatasel;
1041         regs->tf_cs = _ucodesel;
1042
1043         /* PS_STRINGS value for BSD/OS binaries.  It is 0 for non-BSD/OS. */
1044         regs->tf_ebx = ps_strings;
1045
1046         /* reset %gs as well */
1047         if (pcb == curpcb)
1048                 load_gs(_udatasel);
1049         else
1050                 pcb->pcb_gs = _udatasel;
1051
1052         /*
1053          * Initialize the math emulator (if any) for the current process.
1054          * Actually, just clear the bit that says that the emulator has
1055          * been initialized.  Initialization is delayed until the process
1056          * traps to the emulator (if it is done at all) mainly because
1057          * emulators don't provide an entry point for initialization.
1058          */
1059         p->p_addr->u_pcb.pcb_flags &= ~FP_SOFTFP;
1060
1061         /*
1062          * Arrange to trap the next npx or `fwait' instruction (see npx.c
1063          * for why fwait must be trapped at least if there is an npx or an
1064          * emulator).  This is mainly to handle the case where npx0 is not
1065          * configured, since the npx routines normally set up the trap
1066          * otherwise.  It should be done only at boot time, but doing it
1067          * here allows modifying `npx_exists' for testing the emulator on
1068          * systems with an npx.
1069          */
1070         load_cr0(rcr0() | CR0_MP | CR0_TS);
1071
1072 #if NNPX > 0
1073         /* Initialize the npx (if any) for the current process. */
1074         npxinit(__INITIAL_NPXCW__);
1075 #endif
1076
1077       /*
1078        * XXX - Linux emulator
1079        * Make sure sure edx is 0x0 on entry. Linux binaries depend
1080        * on it.
1081        */
1082       p->p_retval[1] = 0;
1083 }
1084
1085 static int
1086 sysctl_machdep_adjkerntz SYSCTL_HANDLER_ARGS
1087 {
1088         int error;
1089         error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2,
1090                 req);
1091         if (!error && req->newptr)
1092                 resettodr();
1093         return (error);
1094 }
1095
1096 SYSCTL_PROC(_machdep, CPU_ADJKERNTZ, adjkerntz, CTLTYPE_INT|CTLFLAG_RW,
1097         &adjkerntz, 0, sysctl_machdep_adjkerntz, "I", "");
1098
1099 SYSCTL_INT(_machdep, CPU_DISRTCSET, disable_rtc_set,
1100         CTLFLAG_RW, &disable_rtc_set, 0, "");
1101
1102 SYSCTL_STRUCT(_machdep, CPU_BOOTINFO, bootinfo, 
1103         CTLFLAG_RD, &bootinfo, bootinfo, "");
1104
1105 SYSCTL_INT(_machdep, CPU_WALLCLOCK, wall_cmos_clock,
1106         CTLFLAG_RW, &wall_cmos_clock, 0, "");
1107
1108 /*
1109  * Initialize 386 and configure to run kernel
1110  */
1111
1112 /*
1113  * Initialize segments & interrupt table
1114  */
1115
1116 int _default_ldt;
1117 #ifdef SMP
1118 union descriptor gdt[NGDT * NCPU];      /* global descriptor table */
1119 #else
1120 union descriptor gdt[NGDT];             /* global descriptor table */
1121 #endif
1122 static struct gate_descriptor idt0[NIDT];
1123 struct gate_descriptor *idt = &idt0[0]; /* interrupt descriptor table */
1124 union descriptor ldt[NLDT];             /* local descriptor table */
1125 #ifdef SMP
1126 /* table descriptors - used to load tables by microp */
1127 struct region_descriptor r_gdt, r_idt;
1128 #endif
1129
1130 #ifndef SMP
1131 extern struct segment_descriptor common_tssd, *tss_gdt;
1132 #endif
1133 int private_tss;                        /* flag indicating private tss */
1134
1135 #if defined(I586_CPU) && !defined(NO_F00F_HACK)
1136 extern int has_f00f_bug;
1137 #endif
1138
1139 static struct i386tss dblfault_tss;
1140 static char dblfault_stack[PAGE_SIZE];
1141
1142 extern  struct user *proc0paddr;
1143
1144
1145 /* software prototypes -- in more palatable form */
1146 struct soft_segment_descriptor gdt_segs[] = {
1147 /* GNULL_SEL    0 Null Descriptor */
1148 {       0x0,                    /* segment base address  */
1149         0x0,                    /* length */
1150         0,                      /* segment type */
1151         0,                      /* segment descriptor priority level */
1152         0,                      /* segment descriptor present */
1153         0, 0,
1154         0,                      /* default 32 vs 16 bit size */
1155         0                       /* limit granularity (byte/page units)*/ },
1156 /* GCODE_SEL    1 Code Descriptor for kernel */
1157 {       0x0,                    /* segment base address  */
1158         0xfffff,                /* length - all address space */
1159         SDT_MEMERA,             /* segment type */
1160         0,                      /* segment descriptor priority level */
1161         1,                      /* segment descriptor present */
1162         0, 0,
1163         1,                      /* default 32 vs 16 bit size */
1164         1                       /* limit granularity (byte/page units)*/ },
1165 /* GDATA_SEL    2 Data Descriptor for kernel */
1166 {       0x0,                    /* segment base address  */
1167         0xfffff,                /* length - all address space */
1168         SDT_MEMRWA,             /* segment type */
1169         0,                      /* segment descriptor priority level */
1170         1,                      /* segment descriptor present */
1171         0, 0,
1172         1,                      /* default 32 vs 16 bit size */
1173         1                       /* limit granularity (byte/page units)*/ },
1174 /* GPRIV_SEL    3 SMP Per-Processor Private Data Descriptor */
1175 {       0x0,                    /* segment base address  */
1176         0xfffff,                /* length - all address space */
1177         SDT_MEMRWA,             /* segment type */
1178         0,                      /* segment descriptor priority level */
1179         1,                      /* segment descriptor present */
1180         0, 0,
1181         1,                      /* default 32 vs 16 bit size */
1182         1                       /* limit granularity (byte/page units)*/ },
1183 /* GPROC0_SEL   4 Proc 0 Tss Descriptor */
1184 {
1185         0x0,                    /* segment base address */
1186         sizeof(struct i386tss)-1,/* length - all address space */
1187         SDT_SYS386TSS,          /* segment type */
1188         0,                      /* segment descriptor priority level */
1189         1,                      /* segment descriptor present */
1190         0, 0,
1191         0,                      /* unused - default 32 vs 16 bit size */
1192         0                       /* limit granularity (byte/page units)*/ },
1193 /* GLDT_SEL     5 LDT Descriptor */
1194 {       (int) ldt,              /* segment base address  */
1195         sizeof(ldt)-1,          /* length - all address space */
1196         SDT_SYSLDT,             /* segment type */
1197         SEL_UPL,                /* segment descriptor priority level */
1198         1,                      /* segment descriptor present */
1199         0, 0,
1200         0,                      /* unused - default 32 vs 16 bit size */
1201         0                       /* limit granularity (byte/page units)*/ },
1202 /* GUSERLDT_SEL 6 User LDT Descriptor per process */
1203 {       (int) ldt,              /* segment base address  */
1204         (512 * sizeof(union descriptor)-1),             /* length */
1205         SDT_SYSLDT,             /* segment type */
1206         0,                      /* segment descriptor priority level */
1207         1,                      /* segment descriptor present */
1208         0, 0,
1209         0,                      /* unused - default 32 vs 16 bit size */
1210         0                       /* limit granularity (byte/page units)*/ },
1211 /* GTGATE_SEL   7 Null Descriptor - Placeholder */
1212 {       0x0,                    /* segment base address  */
1213         0x0,                    /* length - all address space */
1214         0,                      /* segment type */
1215         0,                      /* segment descriptor priority level */
1216         0,                      /* segment descriptor present */
1217         0, 0,
1218         0,                      /* default 32 vs 16 bit size */
1219         0                       /* limit granularity (byte/page units)*/ },
1220 /* GBIOSLOWMEM_SEL 8 BIOS access to realmode segment 0x40, must be #8 in GDT */
1221 {       0x400,                  /* segment base address */
1222         0xfffff,                /* length */
1223         SDT_MEMRWA,             /* segment type */
1224         0,                      /* segment descriptor priority level */
1225         1,                      /* segment descriptor present */
1226         0, 0,
1227         1,                      /* default 32 vs 16 bit size */
1228         1                       /* limit granularity (byte/page units)*/ },
1229 /* GPANIC_SEL   9 Panic Tss Descriptor */
1230 {       (int) &dblfault_tss,    /* segment base address  */
1231         sizeof(struct i386tss)-1,/* length - all address space */
1232         SDT_SYS386TSS,          /* segment type */
1233         0,                      /* segment descriptor priority level */
1234         1,                      /* segment descriptor present */
1235         0, 0,
1236         0,                      /* unused - default 32 vs 16 bit size */
1237         0                       /* limit granularity (byte/page units)*/ },
1238 /* GBIOSCODE32_SEL 10 BIOS 32-bit interface (32bit Code) */
1239 {       0,                      /* segment base address (overwritten)  */
1240         0xfffff,                /* length */
1241         SDT_MEMERA,             /* segment type */
1242         0,                      /* segment descriptor priority level */
1243         1,                      /* segment descriptor present */
1244         0, 0,
1245         0,                      /* default 32 vs 16 bit size */
1246         1                       /* limit granularity (byte/page units)*/ },
1247 /* GBIOSCODE16_SEL 11 BIOS 32-bit interface (16bit Code) */
1248 {       0,                      /* segment base address (overwritten)  */
1249         0xfffff,                /* length */
1250         SDT_MEMERA,             /* segment type */
1251         0,                      /* segment descriptor priority level */
1252         1,                      /* segment descriptor present */
1253         0, 0,
1254         0,                      /* default 32 vs 16 bit size */
1255         1                       /* limit granularity (byte/page units)*/ },
1256 /* GBIOSDATA_SEL 12 BIOS 32-bit interface (Data) */
1257 {       0,                      /* segment base address (overwritten) */
1258         0xfffff,                /* length */
1259         SDT_MEMRWA,             /* segment type */
1260         0,                      /* segment descriptor priority level */
1261         1,                      /* segment descriptor present */
1262         0, 0,
1263         1,                      /* default 32 vs 16 bit size */
1264         1                       /* limit granularity (byte/page units)*/ },
1265 /* GBIOSUTIL_SEL 13 BIOS 16-bit interface (Utility) */
1266 {       0,                      /* segment base address (overwritten) */
1267         0xfffff,                /* length */
1268         SDT_MEMRWA,             /* segment type */
1269         0,                      /* segment descriptor priority level */
1270         1,                      /* segment descriptor present */
1271         0, 0,
1272         0,                      /* default 32 vs 16 bit size */
1273         1                       /* limit granularity (byte/page units)*/ },
1274 /* GBIOSARGS_SEL 14 BIOS 16-bit interface (Arguments) */
1275 {       0,                      /* segment base address (overwritten) */
1276         0xfffff,                /* length */
1277         SDT_MEMRWA,             /* segment type */
1278         0,                      /* segment descriptor priority level */
1279         1,                      /* segment descriptor present */
1280         0, 0,
1281         0,                      /* default 32 vs 16 bit size */
1282         1                       /* limit granularity (byte/page units)*/ },
1283 };
1284
1285 static struct soft_segment_descriptor ldt_segs[] = {
1286         /* Null Descriptor - overwritten by call gate */
1287 {       0x0,                    /* segment base address  */
1288         0x0,                    /* length - all address space */
1289         0,                      /* segment type */
1290         0,                      /* segment descriptor priority level */
1291         0,                      /* segment descriptor present */
1292         0, 0,
1293         0,                      /* default 32 vs 16 bit size */
1294         0                       /* limit granularity (byte/page units)*/ },
1295         /* Null Descriptor - overwritten by call gate */
1296 {       0x0,                    /* segment base address  */
1297         0x0,                    /* length - all address space */
1298         0,                      /* segment type */
1299         0,                      /* segment descriptor priority level */
1300         0,                      /* segment descriptor present */
1301         0, 0,
1302         0,                      /* default 32 vs 16 bit size */
1303         0                       /* limit granularity (byte/page units)*/ },
1304         /* Null Descriptor - overwritten by call gate */
1305 {       0x0,                    /* segment base address  */
1306         0x0,                    /* length - all address space */
1307         0,                      /* segment type */
1308         0,                      /* segment descriptor priority level */
1309         0,                      /* segment descriptor present */
1310         0, 0,
1311         0,                      /* default 32 vs 16 bit size */
1312         0                       /* limit granularity (byte/page units)*/ },
1313         /* Code Descriptor for user */
1314 {       0x0,                    /* segment base address  */
1315         0xfffff,                /* length - all address space */
1316         SDT_MEMERA,             /* segment type */
1317         SEL_UPL,                /* segment descriptor priority level */
1318         1,                      /* segment descriptor present */
1319         0, 0,
1320         1,                      /* default 32 vs 16 bit size */
1321         1                       /* limit granularity (byte/page units)*/ },
1322         /* Null Descriptor - overwritten by call gate */
1323 {       0x0,                    /* segment base address  */
1324         0x0,                    /* length - all address space */
1325         0,                      /* segment type */
1326         0,                      /* segment descriptor priority level */
1327         0,                      /* segment descriptor present */
1328         0, 0,
1329         0,                      /* default 32 vs 16 bit size */
1330         0                       /* limit granularity (byte/page units)*/ },
1331         /* Data Descriptor for user */
1332 {       0x0,                    /* segment base address  */
1333         0xfffff,                /* length - all address space */
1334         SDT_MEMRWA,             /* segment type */
1335         SEL_UPL,                /* segment descriptor priority level */
1336         1,                      /* segment descriptor present */
1337         0, 0,
1338         1,                      /* default 32 vs 16 bit size */
1339         1                       /* limit granularity (byte/page units)*/ },
1340 };
1341
1342 void
1343 setidt(idx, func, typ, dpl, selec)
1344         int idx;
1345         inthand_t *func;
1346         int typ;
1347         int dpl;
1348         int selec;
1349 {
1350         struct gate_descriptor *ip;
1351
1352         ip = idt + idx;
1353         ip->gd_looffset = (int)func;
1354         ip->gd_selector = selec;
1355         ip->gd_stkcpy = 0;
1356         ip->gd_xx = 0;
1357         ip->gd_type = typ;
1358         ip->gd_dpl = dpl;
1359         ip->gd_p = 1;
1360         ip->gd_hioffset = ((int)func)>>16 ;
1361 }
1362
1363 #define IDTVEC(name)    __CONCAT(X,name)
1364
1365 extern inthand_t
1366         IDTVEC(div), IDTVEC(dbg), IDTVEC(nmi), IDTVEC(bpt), IDTVEC(ofl),
1367         IDTVEC(bnd), IDTVEC(ill), IDTVEC(dna), IDTVEC(fpusegm),
1368         IDTVEC(tss), IDTVEC(missing), IDTVEC(stk), IDTVEC(prot),
1369         IDTVEC(page), IDTVEC(mchk), IDTVEC(rsvd), IDTVEC(fpu), IDTVEC(align),
1370         IDTVEC(syscall), IDTVEC(int0x80_syscall);
1371
1372 void
1373 sdtossd(sd, ssd)
1374         struct segment_descriptor *sd;
1375         struct soft_segment_descriptor *ssd;
1376 {
1377         ssd->ssd_base  = (sd->sd_hibase << 24) | sd->sd_lobase;
1378         ssd->ssd_limit = (sd->sd_hilimit << 16) | sd->sd_lolimit;
1379         ssd->ssd_type  = sd->sd_type;
1380         ssd->ssd_dpl   = sd->sd_dpl;
1381         ssd->ssd_p     = sd->sd_p;
1382         ssd->ssd_def32 = sd->sd_def32;
1383         ssd->ssd_gran  = sd->sd_gran;
1384 }
1385
1386 #define PHYSMAP_SIZE    (2 * 8)
1387
1388 /*
1389  * Populate the (physmap) array with base/bound pairs describing the
1390  * available physical memory in the system, then test this memory and
1391  * build the phys_avail array describing the actually-available memory.
1392  *
1393  * If we cannot accurately determine the physical memory map, then use
1394  * value from the 0xE801 call, and failing that, the RTC.
1395  *
1396  * Total memory size may be set by the kernel environment variable
1397  * hw.physmem or the compile-time define MAXMEM.
1398  */
1399 static void
1400 getmemsize_pc98(int first)
1401 {
1402         u_int   biosbasemem, biosextmem;
1403         u_int   pagesinbase, pagesinext;
1404         int     pa_indx;
1405         int     speculative_mprobe;
1406 #if     NNPX > 0
1407         int     msize;
1408 #endif
1409         vm_offset_t     target_page;
1410
1411         pc98_getmemsize();
1412         biosbasemem = 640;                      /* 640KB */
1413         biosextmem = (Maxmem * PAGE_SIZE - 0x100000)/1024;   /* extent memory */
1414
1415 #ifdef SMP
1416         /* make hole for AP bootstrap code */
1417         pagesinbase = mp_bootaddress(biosbasemem) / PAGE_SIZE;
1418 #else
1419         pagesinbase = biosbasemem * 1024 / PAGE_SIZE;
1420 #endif
1421
1422         pagesinext = biosextmem * 1024 / PAGE_SIZE;
1423
1424         /*
1425          * Maxmem isn't the "maximum memory", it's one larger than the
1426          * highest page of the physical address space.  It should be
1427          * called something like "Maxphyspage".
1428          */
1429         Maxmem = pagesinext + 0x100000/PAGE_SIZE;
1430         /*
1431          * Indicate that we wish to do a speculative search for memory beyond
1432          * the end of the reported size if the indicated amount is 64MB (0x4000
1433          * pages) - which is the largest amount that the BIOS/bootblocks can
1434          * currently report. If a specific amount of memory is indicated via
1435          * the MAXMEM option or the npx0 "msize", then don't do the speculative
1436          * memory probe.
1437          */
1438         if (Maxmem >= 0x4000)
1439                 speculative_mprobe = TRUE;
1440         else
1441                 speculative_mprobe = FALSE;
1442
1443 #ifdef MAXMEM
1444         Maxmem = MAXMEM/4;
1445         speculative_mprobe = FALSE;
1446 #endif
1447
1448 #if NNPX > 0
1449         if (resource_int_value("npx", 0, "msize", &msize) == 0) {
1450                 if (msize != 0) {
1451                         Maxmem = msize / 4;
1452                         speculative_mprobe = FALSE;
1453                 }
1454         }
1455 #endif
1456
1457 #ifdef SMP
1458         /* look for the MP hardware - needed for apic addresses */
1459         mp_probe();
1460 #endif
1461
1462         /* call pmap initialization to make new kernel address space */
1463         pmap_bootstrap (first, 0);
1464
1465         /*
1466          * Size up each available chunk of physical memory.
1467          */
1468
1469         /*
1470          * We currently don't bother testing base memory.
1471          * XXX  ...but we probably should.
1472          */
1473         pa_indx = 0;
1474         if (pagesinbase > 1) {
1475                 phys_avail[pa_indx++] = PAGE_SIZE;      /* skip first page of memory */
1476                 phys_avail[pa_indx] = ptoa(pagesinbase);/* memory up to the ISA hole */
1477                 physmem = pagesinbase - 1;
1478         } else {
1479                 /* point at first chunk end */
1480                 pa_indx++;
1481         }
1482
1483         for (target_page = avail_start; target_page < ptoa(Maxmem); target_page += PAGE_SIZE) {
1484                 int tmp, page_bad;
1485
1486                 page_bad = FALSE;
1487                 /* skip system area */
1488                 if (target_page>=ptoa(Maxmem_under16M) &&
1489                                 target_page < ptoa(4096))
1490                         page_bad = TRUE;
1491                 /*
1492                  * map page into kernel: valid, read/write, non-cacheable
1493                  */
1494                 if (pc98_machine_type & M_EPSON_PC98) {
1495                         switch (epson_machine_id) {
1496                         case 0x34:                              /* PC-486HX */
1497                         case 0x35:                              /* PC-486HG */
1498                         case 0x3B:                              /* PC-486HA */
1499                                 *(int *)CMAP1 = PG_V | PG_RW | target_page;
1500                                 break;
1501                         default:
1502 #ifdef WB_CACHE
1503                                 *(int *)CMAP1 = PG_V | PG_RW | target_page;
1504 #else
1505                                 *(int *)CMAP1 = PG_V | PG_RW | PG_N | target_page;
1506 #endif
1507                                 break;
1508                         }
1509                 } else {
1510                 *(int *)CMAP1 = PG_V | PG_RW | PG_N | target_page;
1511                 }
1512                 invltlb();
1513
1514                 tmp = *(int *)CADDR1;
1515                 /*
1516                  * Test for alternating 1's and 0's
1517                  */
1518                 *(volatile int *)CADDR1 = 0xaaaaaaaa;
1519                 if (*(volatile int *)CADDR1 != 0xaaaaaaaa) {
1520                         page_bad = TRUE;
1521                 }
1522                 /*
1523                  * Test for alternating 0's and 1's
1524                  */
1525                 *(volatile int *)CADDR1 = 0x55555555;
1526                 if (*(volatile int *)CADDR1 != 0x55555555) {
1527                         page_bad = TRUE;
1528                 }
1529                 /*
1530                  * Test for all 1's
1531                  */
1532                 *(volatile int *)CADDR1 = 0xffffffff;
1533                 if (*(volatile int *)CADDR1 != 0xffffffff) {
1534                         page_bad = TRUE;
1535                 }
1536                 /*
1537                  * Test for all 0's
1538                  */
1539                 *(volatile int *)CADDR1 = 0x0;
1540                 if (*(volatile int *)CADDR1 != 0x0) {
1541                         /*
1542                          * test of page failed
1543                          */
1544                         page_bad = TRUE;
1545                 }
1546                 /*
1547                  * Restore original value.
1548                  */
1549                 *(int *)CADDR1 = tmp;
1550
1551                 /*
1552                  * Adjust array of valid/good pages.
1553                  */
1554                 if (page_bad == FALSE) {
1555                         /*
1556                          * If this good page is a continuation of the
1557                          * previous set of good pages, then just increase
1558                          * the end pointer. Otherwise start a new chunk.
1559                          * Note that "end" points one higher than end,
1560                          * making the range >= start and < end.
1561                          * If we're also doing a speculative memory
1562                          * test and we at or past the end, bump up Maxmem
1563                          * so that we keep going. The first bad page
1564                          * will terminate the loop.
1565                          */
1566                         if (phys_avail[pa_indx] == target_page) {
1567                                 phys_avail[pa_indx] += PAGE_SIZE;
1568                                 if (speculative_mprobe == TRUE &&
1569                                     phys_avail[pa_indx] >= (64*1024*1024))
1570                                         Maxmem++;
1571                         } else {
1572                                 pa_indx++;
1573                                 if (pa_indx == PHYS_AVAIL_ARRAY_END) {
1574                                         printf("Too many holes in the physical address space, giving up\n");
1575                                         pa_indx--;
1576                                         break;
1577                                 }
1578                                 phys_avail[pa_indx++] = target_page;    /* start */
1579                                 phys_avail[pa_indx] = target_page + PAGE_SIZE;  /* end */
1580                         }
1581                         physmem++;
1582                 }
1583         }
1584
1585         *(int *)CMAP1 = 0;
1586         invltlb();
1587
1588         /*
1589          * XXX
1590          * The last chunk must contain at least one page plus the message
1591          * buffer to avoid complicating other code (message buffer address
1592          * calculation, etc.).
1593          */
1594         while (phys_avail[pa_indx - 1] + PAGE_SIZE +
1595             round_page(MSGBUF_SIZE) >= phys_avail[pa_indx]) {
1596                 physmem -= atop(phys_avail[pa_indx] - phys_avail[pa_indx - 1]);
1597                 phys_avail[pa_indx--] = 0;
1598                 phys_avail[pa_indx--] = 0;
1599         }
1600
1601         Maxmem = atop(phys_avail[pa_indx]);
1602
1603         /* Trim off space for the message buffer. */
1604         phys_avail[pa_indx] -= round_page(MSGBUF_SIZE);
1605
1606         avail_end = phys_avail[pa_indx];
1607 }
1608
1609 #ifndef PC98
1610 static void
1611 getmemsize(int first)
1612 {
1613         int i, physmap_idx, pa_indx;
1614         u_int basemem, extmem;
1615         struct vm86frame vmf;
1616         struct vm86context vmc;
1617         vm_offset_t pa, physmap[PHYSMAP_SIZE];
1618         pt_entry_t pte;
1619         const char *cp;
1620         struct {
1621                 u_int64_t base;
1622                 u_int64_t length;
1623                 u_int32_t type;
1624         } *smap;
1625
1626         bzero(&vmf, sizeof(struct vm86frame));
1627         bzero(physmap, sizeof(physmap));
1628
1629         /*
1630          * Perform "base memory" related probes & setup
1631          */
1632         vm86_intcall(0x12, &vmf);
1633         basemem = vmf.vmf_ax;
1634         if (basemem > 640) {
1635                 printf("Preposterous BIOS basemem of %uK, truncating to 640K\n",
1636                         basemem);
1637                 basemem = 640;
1638         }
1639
1640         /*
1641          * XXX if biosbasemem is now < 640, there is a `hole'
1642          * between the end of base memory and the start of
1643          * ISA memory.  The hole may be empty or it may
1644          * contain BIOS code or data.  Map it read/write so
1645          * that the BIOS can write to it.  (Memory from 0 to
1646          * the physical end of the kernel is mapped read-only
1647          * to begin with and then parts of it are remapped.
1648          * The parts that aren't remapped form holes that
1649          * remain read-only and are unused by the kernel.
1650          * The base memory area is below the physical end of
1651          * the kernel and right now forms a read-only hole.
1652          * The part of it from PAGE_SIZE to
1653          * (trunc_page(biosbasemem * 1024) - 1) will be
1654          * remapped and used by the kernel later.)
1655          *
1656          * This code is similar to the code used in
1657          * pmap_mapdev, but since no memory needs to be
1658          * allocated we simply change the mapping.
1659          */
1660         for (pa = trunc_page(basemem * 1024);
1661              pa < ISA_HOLE_START; pa += PAGE_SIZE) {
1662                 pte = (pt_entry_t)vtopte(pa + KERNBASE);
1663                 *pte = pa | PG_RW | PG_V;
1664         }
1665
1666         /*
1667          * if basemem != 640, map pages r/w into vm86 page table so 
1668          * that the bios can scribble on it.
1669          */
1670         pte = (pt_entry_t)vm86paddr;
1671         for (i = basemem / 4; i < 160; i++)
1672                 pte[i] = (i << PAGE_SHIFT) | PG_V | PG_RW | PG_U;
1673
1674         /*
1675          * map page 1 R/W into the kernel page table so we can use it
1676          * as a buffer.  The kernel will unmap this page later.
1677          */
1678         pte = (pt_entry_t)vtopte(KERNBASE + (1 << PAGE_SHIFT));
1679         *pte = (1 << PAGE_SHIFT) | PG_RW | PG_V;
1680
1681         extmem = (Maxmem * PAGE_SIZE - 0x100000)/1024;   /* extent memory */
1682         /*
1683          * get memory map with INT 15:E820
1684          */
1685 #define SMAPSIZ         sizeof(*smap)
1686 #define SMAP_SIG        0x534D4150                      /* 'SMAP' */
1687
1688         vmc.npages = 0;
1689         smap = (void *)vm86_addpage(&vmc, 1, KERNBASE + (1 << PAGE_SHIFT));
1690         vm86_getptr(&vmc, (vm_offset_t)smap, &vmf.vmf_es, &vmf.vmf_di);
1691
1692         physmap_idx = 0;
1693         vmf.vmf_ebx = 0;
1694         do {
1695                 vmf.vmf_eax = 0xE820;
1696                 vmf.vmf_edx = SMAP_SIG;
1697                 vmf.vmf_ecx = SMAPSIZ;
1698                 i = vm86_datacall(0x15, &vmf, &vmc);
1699                 if (i || vmf.vmf_eax != SMAP_SIG)
1700                         break;
1701                 if (boothowto & RB_VERBOSE)
1702                         printf("SMAP type=%02x base=%08x %08x len=%08x %08x\n",
1703                                 smap->type,
1704                                 *(u_int32_t *)((char *)&smap->base + 4),
1705                                 (u_int32_t)smap->base,
1706                                 *(u_int32_t *)((char *)&smap->length + 4),
1707                                 (u_int32_t)smap->length);
1708
1709                 if (smap->type != 0x01)
1710                         goto next_run;
1711
1712                 if (smap->length == 0)
1713                         goto next_run;
1714
1715                 if (smap->base >= 0xffffffff) {
1716                         printf("%uK of memory above 4GB ignored\n",
1717                             (u_int)(smap->length / 1024));
1718                         goto next_run;
1719                 }
1720
1721                 for (i = 0; i <= physmap_idx; i += 2) {
1722                         if (smap->base < physmap[i + 1]) {
1723                                 if (boothowto & RB_VERBOSE)
1724                                         printf(
1725         "Overlapping or non-montonic memory region, ignoring second region\n");
1726                                 goto next_run;
1727                         }
1728                 }
1729
1730                 if (smap->base == physmap[physmap_idx + 1]) {
1731                         physmap[physmap_idx + 1] += smap->length;
1732                         goto next_run;
1733                 }
1734
1735                 physmap_idx += 2;
1736                 if (physmap_idx == PHYSMAP_SIZE) {
1737                         printf(
1738                 "Too many segments in the physical address map, giving up\n");
1739                         break;
1740                 }
1741                 physmap[physmap_idx] = smap->base;
1742                 physmap[physmap_idx + 1] = smap->base + smap->length;
1743 next_run:
1744         } while (vmf.vmf_ebx != 0);
1745
1746         if (physmap[1] != 0)
1747                 goto physmap_done;
1748
1749         /*
1750          * If we failed above, try memory map with INT 15:E801
1751          */
1752         vmf.vmf_ax = 0xE801;
1753         if (vm86_intcall(0x15, &vmf) == 0) {
1754                 extmem = vmf.vmf_cx + vmf.vmf_dx * 64;
1755         } else {
1756 #if 0
1757                 vmf.vmf_ah = 0x88;
1758                 vm86_intcall(0x15, &vmf);
1759                 extmem = vmf.vmf_ax;
1760 #else
1761                 /*
1762                  * Prefer the RTC value for extended memory.
1763                  */
1764                 extmem = rtcin(RTC_EXTLO) + (rtcin(RTC_EXTHI) << 8);
1765 #endif
1766         }
1767
1768         /*
1769          * Special hack for chipsets that still remap the 384k hole when
1770          * there's 16MB of memory - this really confuses people that
1771          * are trying to use bus mastering ISA controllers with the
1772          * "16MB limit"; they only have 16MB, but the remapping puts
1773          * them beyond the limit.
1774          *
1775          * If extended memory is between 15-16MB (16-17MB phys address range),
1776          *      chop it to 15MB.
1777          */
1778         if ((extmem > 15 * 1024) && (extmem < 16 * 1024))
1779                 extmem = 15 * 1024;
1780
1781         physmap[0] = 0;
1782         physmap[1] = basemem * 1024;
1783         physmap_idx = 2;
1784         physmap[physmap_idx] = 0x100000;
1785         physmap[physmap_idx + 1] = physmap[physmap_idx] + extmem * 1024;
1786
1787 physmap_done:
1788         /*
1789          * Now, physmap contains a map of physical memory.
1790          */
1791
1792 #ifdef SMP
1793         /* make hole for AP bootstrap code */
1794         physmap[1] = mp_bootaddress(physmap[1] / 1024);
1795
1796         /* look for the MP hardware - needed for apic addresses */
1797         mp_probe();
1798 #endif
1799
1800         /*
1801          * Maxmem isn't the "maximum memory", it's one larger than the
1802          * highest page of the physical address space.  It should be
1803          * called something like "Maxphyspage".  We may adjust this 
1804          * based on ``hw.physmem'' and the results of the memory test.
1805          */
1806         Maxmem = atop(physmap[physmap_idx + 1]);
1807
1808 #ifdef MAXMEM
1809         Maxmem = MAXMEM / 4;
1810 #endif
1811
1812         /*
1813          * hw.maxmem is a size in bytes; we also allow k, m, and g suffixes
1814          * for the appropriate modifiers.  This overrides MAXMEM.
1815          */
1816         if ((cp = getenv("hw.physmem")) != NULL) {
1817                 u_int64_t AllowMem, sanity;
1818                 char *ep;
1819
1820                 sanity = AllowMem = strtouq(cp, &ep, 0);
1821                 if ((ep != cp) && (*ep != 0)) {
1822                         switch(*ep) {
1823                         case 'g':
1824                         case 'G':
1825                                 AllowMem <<= 10;
1826                         case 'm':
1827                         case 'M':
1828                                 AllowMem <<= 10;
1829                         case 'k':
1830                         case 'K':
1831                                 AllowMem <<= 10;
1832                                 break;
1833                         default:
1834                                 AllowMem = sanity = 0;
1835                         }
1836                         if (AllowMem < sanity)
1837                                 AllowMem = 0;
1838                 }
1839                 if (AllowMem == 0)
1840                         printf("Ignoring invalid memory size of '%s'\n", cp);
1841                 else
1842                         Maxmem = atop(AllowMem);
1843         }
1844
1845         if (atop(physmap[physmap_idx + 1]) != Maxmem &&
1846             (boothowto & RB_VERBOSE))
1847                 printf("Physical memory use set to %uK\n", Maxmem * 4);
1848
1849         /*
1850          * If Maxmem has been increased beyond what the system has detected,
1851          * extend the last memory segment to the new limit.
1852          */ 
1853         if (atop(physmap[physmap_idx + 1]) < Maxmem)
1854                 physmap[physmap_idx + 1] = ptoa(Maxmem);
1855
1856         /* call pmap initialization to make new kernel address space */
1857         pmap_bootstrap(first, 0);
1858
1859         /*
1860          * Size up each available chunk of physical memory.
1861          */
1862         physmap[0] = PAGE_SIZE;         /* mask off page 0 */
1863         pa_indx = 0;
1864         phys_avail[pa_indx++] = physmap[0];
1865         phys_avail[pa_indx] = physmap[0];
1866 #if 0
1867         pte = (pt_entry_t)vtopte(KERNBASE);
1868 #else
1869         pte = (pt_entry_t)CMAP1;
1870 #endif
1871
1872         /*
1873          * physmap is in bytes, so when converting to page boundaries,
1874          * round up the start address and round down the end address.
1875          */
1876         for (i = 0; i <= physmap_idx; i += 2) {
1877                 vm_offset_t end;
1878
1879                 end = ptoa(Maxmem);
1880                 if (physmap[i + 1] < end)
1881                         end = trunc_page(physmap[i + 1]);
1882                 for (pa = round_page(physmap[i]); pa < end; pa += PAGE_SIZE) {
1883                         int tmp, page_bad;
1884 #if 0
1885                         int *ptr = 0;
1886 #else
1887                         int *ptr = (int *)CADDR1;
1888 #endif
1889
1890                         /*
1891                          * block out kernel memory as not available.
1892                          */
1893                         if (pa >= 0x100000 && pa < first)
1894                                 continue;
1895         
1896                         page_bad = FALSE;
1897
1898                         /*
1899                          * map page into kernel: valid, read/write,non-cacheable
1900                          */
1901                         *pte = pa | PG_V | PG_RW | PG_N;
1902                         invltlb();
1903
1904                         tmp = *(int *)ptr;
1905                         /*
1906                          * Test for alternating 1's and 0's
1907                          */
1908                         *(volatile int *)ptr = 0xaaaaaaaa;
1909                         if (*(volatile int *)ptr != 0xaaaaaaaa) {
1910                                 page_bad = TRUE;
1911                         }
1912                         /*
1913                          * Test for alternating 0's and 1's
1914                          */
1915                         *(volatile int *)ptr = 0x55555555;
1916                         if (*(volatile int *)ptr != 0x55555555) {
1917                         page_bad = TRUE;
1918                         }
1919                         /*
1920                          * Test for all 1's
1921                          */
1922                         *(volatile int *)ptr = 0xffffffff;
1923                         if (*(volatile int *)ptr != 0xffffffff) {
1924                                 page_bad = TRUE;
1925                         }
1926                         /*
1927                          * Test for all 0's
1928                          */
1929                         *(volatile int *)ptr = 0x0;
1930                         if (*(volatile int *)ptr != 0x0) {
1931                                 page_bad = TRUE;
1932                         }
1933                         /*
1934                          * Restore original value.
1935                          */
1936                         *(int *)ptr = tmp;
1937
1938                         /*
1939                          * Adjust array of valid/good pages.
1940                          */
1941                         if (page_bad == TRUE) {
1942                                 continue;
1943                         }
1944                         /*
1945                          * If this good page is a continuation of the
1946                          * previous set of good pages, then just increase
1947                          * the end pointer. Otherwise start a new chunk.
1948                          * Note that "end" points one higher than end,
1949                          * making the range >= start and < end.
1950                          * If we're also doing a speculative memory
1951                          * test and we at or past the end, bump up Maxmem
1952                          * so that we keep going. The first bad page
1953                          * will terminate the loop.
1954                          */
1955                         if (phys_avail[pa_indx] == pa) {
1956                                 phys_avail[pa_indx] += PAGE_SIZE;
1957                         } else {
1958                                 pa_indx++;
1959                                 if (pa_indx == PHYS_AVAIL_ARRAY_END) {
1960                                         printf("Too many holes in the physical address space, giving up\n");
1961                                         pa_indx--;
1962                                         break;
1963                                 }
1964                                 phys_avail[pa_indx++] = pa;     /* start */
1965                                 phys_avail[pa_indx] = pa + PAGE_SIZE;   /* end */
1966                         }
1967                         physmem++;
1968                 }
1969         }
1970         *pte = 0;
1971         invltlb();
1972
1973         /*
1974          * XXX
1975          * The last chunk must contain at least one page plus the message
1976          * buffer to avoid complicating other code (message buffer address
1977          * calculation, etc.).
1978          */
1979         while (phys_avail[pa_indx - 1] + PAGE_SIZE +
1980             round_page(MSGBUF_SIZE) >= phys_avail[pa_indx]) {
1981                 physmem -= atop(phys_avail[pa_indx] - phys_avail[pa_indx - 1]);
1982                 phys_avail[pa_indx--] = 0;
1983                 phys_avail[pa_indx--] = 0;
1984         }
1985
1986         Maxmem = atop(phys_avail[pa_indx]);
1987
1988         /* Trim off space for the message buffer. */
1989         phys_avail[pa_indx] -= round_page(MSGBUF_SIZE);
1990
1991         avail_end = phys_avail[pa_indx];
1992 }
1993 #endif
1994
1995 void
1996 init386(first)
1997         int first;
1998 {
1999         int x;
2000         struct gate_descriptor *gdp;
2001         int gsel_tss;
2002 #ifndef SMP
2003         /* table descriptors - used to load tables by microp */
2004         struct region_descriptor r_gdt, r_idt;
2005 #endif
2006         int off;
2007
2008         /*
2009          * Prevent lowering of the ipl if we call tsleep() early.
2010          */
2011         safepri = cpl;
2012
2013         proc0.p_addr = proc0paddr;
2014
2015         atdevbase = ISA_HOLE_START + KERNBASE;
2016
2017 #ifdef PC98
2018         /*
2019          * Initialize DMAC
2020          */
2021         pc98_init_dmac();
2022 #endif
2023
2024         if (bootinfo.bi_modulep) {
2025                 preload_metadata = (caddr_t)bootinfo.bi_modulep + KERNBASE;
2026                 preload_bootstrap_relocate(KERNBASE);
2027         }
2028         if (bootinfo.bi_envp)
2029                 kern_envp = (caddr_t)bootinfo.bi_envp + KERNBASE;
2030
2031         /*
2032          * make gdt memory segments, the code segment goes up to end of the
2033          * page with etext in it, the data segment goes to the end of
2034          * the address space
2035          */
2036         /*
2037          * XXX text protection is temporarily (?) disabled.  The limit was
2038          * i386_btop(round_page(etext)) - 1.
2039          */
2040         gdt_segs[GCODE_SEL].ssd_limit = i386_btop(0) - 1;
2041         gdt_segs[GDATA_SEL].ssd_limit = i386_btop(0) - 1;
2042 #ifdef SMP
2043         gdt_segs[GPRIV_SEL].ssd_limit =
2044                 i386_btop(sizeof(struct privatespace)) - 1;
2045         gdt_segs[GPRIV_SEL].ssd_base = (int) &SMP_prvspace[0];
2046         gdt_segs[GPROC0_SEL].ssd_base =
2047                 (int) &SMP_prvspace[0].globaldata.gd_common_tss;
2048         SMP_prvspace[0].globaldata.gd_prvspace = &SMP_prvspace[0];
2049 #else
2050         gdt_segs[GPRIV_SEL].ssd_limit = i386_btop(0) - 1;
2051         gdt_segs[GPROC0_SEL].ssd_base = (int) &common_tss;
2052 #endif
2053
2054         for (x = 0; x < NGDT; x++) {
2055 #ifdef BDE_DEBUGGER
2056                 /* avoid overwriting db entries with APM ones */
2057                 if (x >= GAPMCODE32_SEL && x <= GAPMDATA_SEL)
2058                         continue;
2059 #endif
2060                 ssdtosd(&gdt_segs[x], &gdt[x].sd);
2061         }
2062
2063         r_gdt.rd_limit = NGDT * sizeof(gdt[0]) - 1;
2064         r_gdt.rd_base =  (int) gdt;
2065         lgdt(&r_gdt);
2066
2067         /* make ldt memory segments */
2068         /*
2069          * The data segment limit must not cover the user area because we
2070          * don't want the user area to be writable in copyout() etc. (page
2071          * level protection is lost in kernel mode on 386's).  Also, we
2072          * don't want the user area to be writable directly (page level
2073          * protection of the user area is not available on 486's with
2074          * CR0_WP set, because there is no user-read/kernel-write mode).
2075          *
2076          * XXX - VM_MAXUSER_ADDRESS is an end address, not a max.  And it
2077          * should be spelled ...MAX_USER...
2078          */
2079 #define VM_END_USER_RW_ADDRESS  VM_MAXUSER_ADDRESS
2080         /*
2081          * The code segment limit has to cover the user area until we move
2082          * the signal trampoline out of the user area.  This is safe because
2083          * the code segment cannot be written to directly.
2084          */
2085 #define VM_END_USER_R_ADDRESS   (VM_END_USER_RW_ADDRESS + UPAGES * PAGE_SIZE)
2086         ldt_segs[LUCODE_SEL].ssd_limit = i386_btop(VM_END_USER_R_ADDRESS) - 1;
2087         ldt_segs[LUDATA_SEL].ssd_limit = i386_btop(VM_END_USER_RW_ADDRESS) - 1;
2088         for (x = 0; x < sizeof ldt_segs / sizeof ldt_segs[0]; x++)
2089                 ssdtosd(&ldt_segs[x], &ldt[x].sd);
2090
2091         _default_ldt = GSEL(GLDT_SEL, SEL_KPL);
2092         lldt(_default_ldt);
2093 #ifdef USER_LDT
2094         currentldt = _default_ldt;
2095 #endif
2096
2097         /* exceptions */
2098         for (x = 0; x < NIDT; x++)
2099                 setidt(x, &IDTVEC(rsvd), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
2100         setidt(0, &IDTVEC(div),  SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
2101         setidt(1, &IDTVEC(dbg),  SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
2102         setidt(2, &IDTVEC(nmi),  SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
2103         setidt(3, &IDTVEC(bpt),  SDT_SYS386TGT, SEL_UPL, GSEL(GCODE_SEL, SEL_KPL));
2104         setidt(4, &IDTVEC(ofl),  SDT_SYS386TGT, SEL_UPL, GSEL(GCODE_SEL, SEL_KPL));
2105         setidt(5, &IDTVEC(bnd),  SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
2106         setidt(6, &IDTVEC(ill),  SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
2107         setidt(7, &IDTVEC(dna),  SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
2108         setidt(8, 0,  SDT_SYSTASKGT, SEL_KPL, GSEL(GPANIC_SEL, SEL_KPL));
2109         setidt(9, &IDTVEC(fpusegm),  SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
2110         setidt(10, &IDTVEC(tss),  SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
2111         setidt(11, &IDTVEC(missing),  SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
2112         setidt(12, &IDTVEC(stk),  SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
2113         setidt(13, &IDTVEC(prot),  SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
2114         setidt(14, &IDTVEC(page),  SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
2115         setidt(15, &IDTVEC(rsvd),  SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
2116         setidt(16, &IDTVEC(fpu),  SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
2117         setidt(17, &IDTVEC(align), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
2118         setidt(18, &IDTVEC(mchk),  SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
2119         setidt(0x80, &IDTVEC(int0x80_syscall),
2120                         SDT_SYS386TGT, SEL_UPL, GSEL(GCODE_SEL, SEL_KPL));
2121
2122         r_idt.rd_limit = sizeof(idt0) - 1;
2123         r_idt.rd_base = (int) idt;
2124         lidt(&r_idt);
2125
2126         /*
2127          * Initialize the console before we print anything out.
2128          */
2129         cninit();
2130
2131 #include        "isa.h"
2132 #if     NISA >0
2133         isa_defaultirq();
2134 #endif
2135         rand_initialize();
2136
2137 #ifdef DDB
2138         kdb_init();
2139         if (boothowto & RB_KDB)
2140                 Debugger("Boot flags requested debugger");
2141 #endif
2142
2143         finishidentcpu();       /* Final stage of CPU initialization */
2144         setidt(6, &IDTVEC(ill),  SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
2145         setidt(13, &IDTVEC(prot),  SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
2146         initializecpu();        /* Initialize CPU registers */
2147
2148         /* make an initial tss so cpu can get interrupt stack on syscall! */
2149         common_tss.tss_esp0 = (int) proc0.p_addr + UPAGES*PAGE_SIZE - 16;
2150         common_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL) ;
2151         gsel_tss = GSEL(GPROC0_SEL, SEL_KPL);
2152         private_tss = 0;
2153         tss_gdt = &gdt[GPROC0_SEL].sd;
2154         common_tssd = *tss_gdt;
2155         common_tss.tss_ioopt = (sizeof common_tss) << 16;
2156         ltr(gsel_tss);
2157
2158         dblfault_tss.tss_esp = dblfault_tss.tss_esp0 = dblfault_tss.tss_esp1 =
2159             dblfault_tss.tss_esp2 = (int) &dblfault_stack[sizeof(dblfault_stack)];
2160         dblfault_tss.tss_ss = dblfault_tss.tss_ss0 = dblfault_tss.tss_ss1 =
2161             dblfault_tss.tss_ss2 = GSEL(GDATA_SEL, SEL_KPL);
2162         dblfault_tss.tss_cr3 = (int)IdlePTD;
2163         dblfault_tss.tss_eip = (int) dblfault_handler;
2164         dblfault_tss.tss_eflags = PSL_KERNEL;
2165         dblfault_tss.tss_ds = dblfault_tss.tss_es =
2166             dblfault_tss.tss_gs = GSEL(GDATA_SEL, SEL_KPL);
2167         dblfault_tss.tss_fs = GSEL(GPRIV_SEL, SEL_KPL);
2168         dblfault_tss.tss_cs = GSEL(GCODE_SEL, SEL_KPL);
2169         dblfault_tss.tss_ldt = GSEL(GLDT_SEL, SEL_KPL);
2170
2171         vm86_initialize();
2172 #ifdef PC98
2173         getmemsize_pc98(first);
2174 #else
2175         getmemsize(first);
2176 #endif
2177         /* now running on new page tables, configured,and u/iom is accessible */
2178
2179         /* Map the message buffer. */
2180         for (off = 0; off < round_page(MSGBUF_SIZE); off += PAGE_SIZE)
2181                 pmap_kenter((vm_offset_t)msgbufp + off, avail_end + off);
2182
2183         msgbufinit(msgbufp, MSGBUF_SIZE);
2184
2185         /* make a call gate to reenter kernel with */
2186         gdp = &ldt[LSYS5CALLS_SEL].gd;
2187
2188         x = (int) &IDTVEC(syscall);
2189         gdp->gd_looffset = x++;
2190         gdp->gd_selector = GSEL(GCODE_SEL,SEL_KPL);
2191         gdp->gd_stkcpy = 1;
2192         gdp->gd_type = SDT_SYS386CGT;
2193         gdp->gd_dpl = SEL_UPL;
2194         gdp->gd_p = 1;
2195         gdp->gd_hioffset = ((int) &IDTVEC(syscall)) >>16;
2196
2197         /* XXX does this work? */
2198         ldt[LBSDICALLS_SEL] = ldt[LSYS5CALLS_SEL];
2199         ldt[LSOL26CALLS_SEL] = ldt[LSYS5CALLS_SEL];
2200
2201         /* transfer to user mode */
2202
2203         _ucodesel = LSEL(LUCODE_SEL, SEL_UPL);
2204         _udatasel = LSEL(LUDATA_SEL, SEL_UPL);
2205
2206         /* setup proc 0's pcb */
2207         proc0.p_addr->u_pcb.pcb_flags = 0;
2208         proc0.p_addr->u_pcb.pcb_cr3 = (int)IdlePTD;
2209 #ifdef SMP
2210         proc0.p_addr->u_pcb.pcb_mpnest = 1;
2211 #endif
2212         proc0.p_addr->u_pcb.pcb_ext = 0;
2213 }
2214
2215 #if defined(I586_CPU) && !defined(NO_F00F_HACK)
2216 static void f00f_hack(void *unused);
2217 SYSINIT(f00f_hack, SI_SUB_INTRINSIC, SI_ORDER_FIRST, f00f_hack, NULL);
2218
2219 static void
2220 f00f_hack(void *unused) {
2221         struct gate_descriptor *new_idt;
2222 #ifndef SMP
2223         struct region_descriptor r_idt;
2224 #endif
2225         vm_offset_t tmp;
2226
2227         if (!has_f00f_bug)
2228                 return;
2229
2230         printf("Intel Pentium detected, installing workaround for F00F bug\n");
2231
2232         r_idt.rd_limit = sizeof(idt0) - 1;
2233
2234         tmp = kmem_alloc(kernel_map, PAGE_SIZE * 2);
2235         if (tmp == 0)
2236                 panic("kmem_alloc returned 0");
2237         if (((unsigned int)tmp & (PAGE_SIZE-1)) != 0)
2238                 panic("kmem_alloc returned non-page-aligned memory");
2239         /* Put the first seven entries in the lower page */
2240         new_idt = (struct gate_descriptor*)(tmp + PAGE_SIZE - (7*8));
2241         bcopy(idt, new_idt, sizeof(idt0));
2242         r_idt.rd_base = (int)new_idt;
2243         lidt(&r_idt);
2244         idt = new_idt;
2245         if (vm_map_protect(kernel_map, tmp, tmp + PAGE_SIZE,
2246                            VM_PROT_READ, FALSE) != KERN_SUCCESS)
2247                 panic("vm_map_protect failed");
2248         return;
2249 }
2250 #endif /* defined(I586_CPU) && !NO_F00F_HACK */
2251
2252 int
2253 ptrace_set_pc(p, addr)
2254         struct proc *p;
2255         unsigned long addr;
2256 {
2257         p->p_md.md_regs->tf_eip = addr;
2258         return (0);
2259 }
2260
2261 int
2262 ptrace_single_step(p)
2263         struct proc *p;
2264 {
2265         p->p_md.md_regs->tf_eflags |= PSL_T;
2266         return (0);
2267 }
2268
2269 int ptrace_read_u_check(p, addr, len)
2270         struct proc *p;
2271         vm_offset_t addr;
2272         size_t len;
2273 {
2274         vm_offset_t gap;
2275
2276         if ((vm_offset_t) (addr + len) < addr)
2277                 return EPERM;
2278         if ((vm_offset_t) (addr + len) <= sizeof(struct user))
2279                 return 0;
2280
2281         gap = (char *) p->p_md.md_regs - (char *) p->p_addr;
2282         
2283         if ((vm_offset_t) addr < gap)
2284                 return EPERM;
2285         if ((vm_offset_t) (addr + len) <= 
2286             (vm_offset_t) (gap + sizeof(struct trapframe)))
2287                 return 0;
2288         return EPERM;
2289 }
2290
2291 int ptrace_write_u(p, off, data)
2292         struct proc *p;
2293         vm_offset_t off;
2294         long data;
2295 {
2296         struct trapframe frame_copy;
2297         vm_offset_t min;
2298         struct trapframe *tp;
2299
2300         /*
2301          * Privileged kernel state is scattered all over the user area.
2302          * Only allow write access to parts of regs and to fpregs.
2303          */
2304         min = (char *)p->p_md.md_regs - (char *)p->p_addr;
2305         if (off >= min && off <= min + sizeof(struct trapframe) - sizeof(int)) {
2306                 tp = p->p_md.md_regs;
2307                 frame_copy = *tp;
2308                 *(int *)((char *)&frame_copy + (off - min)) = data;
2309                 if (!EFL_SECURE(frame_copy.tf_eflags, tp->tf_eflags) ||
2310                     !CS_SECURE(frame_copy.tf_cs))
2311                         return (EINVAL);
2312                 *(int*)((char *)p->p_addr + off) = data;
2313                 return (0);
2314         }
2315         min = offsetof(struct user, u_pcb) + offsetof(struct pcb, pcb_savefpu);
2316         if (off >= min && off <= min + sizeof(struct save87) - sizeof(int)) {
2317                 *(int*)((char *)p->p_addr + off) = data;
2318                 return (0);
2319         }
2320         return (EFAULT);
2321 }
2322
2323 int
2324 fill_regs(p, regs)
2325         struct proc *p;
2326         struct reg *regs;
2327 {
2328         struct pcb *pcb;
2329         struct trapframe *tp;
2330
2331         tp = p->p_md.md_regs;
2332         regs->r_fs = tp->tf_fs;
2333         regs->r_es = tp->tf_es;
2334         regs->r_ds = tp->tf_ds;
2335         regs->r_edi = tp->tf_edi;
2336         regs->r_esi = tp->tf_esi;
2337         regs->r_ebp = tp->tf_ebp;
2338         regs->r_ebx = tp->tf_ebx;
2339         regs->r_edx = tp->tf_edx;
2340         regs->r_ecx = tp->tf_ecx;
2341         regs->r_eax = tp->tf_eax;
2342         regs->r_eip = tp->tf_eip;
2343         regs->r_cs = tp->tf_cs;
2344         regs->r_eflags = tp->tf_eflags;
2345         regs->r_esp = tp->tf_esp;
2346         regs->r_ss = tp->tf_ss;
2347         pcb = &p->p_addr->u_pcb;
2348         regs->r_gs = pcb->pcb_gs;
2349         return (0);
2350 }
2351
2352 int
2353 set_regs(p, regs)
2354         struct proc *p;
2355         struct reg *regs;
2356 {
2357         struct pcb *pcb;
2358         struct trapframe *tp;
2359
2360         tp = p->p_md.md_regs;
2361         if (!EFL_SECURE(regs->r_eflags, tp->tf_eflags) ||
2362             !CS_SECURE(regs->r_cs))
2363                 return (EINVAL);
2364         tp->tf_fs = regs->r_fs;
2365         tp->tf_es = regs->r_es;
2366         tp->tf_ds = regs->r_ds;
2367         tp->tf_edi = regs->r_edi;
2368         tp->tf_esi = regs->r_esi;
2369         tp->tf_ebp = regs->r_ebp;
2370         tp->tf_ebx = regs->r_ebx;
2371         tp->tf_edx = regs->r_edx;
2372         tp->tf_ecx = regs->r_ecx;
2373         tp->tf_eax = regs->r_eax;
2374         tp->tf_eip = regs->r_eip;
2375         tp->tf_cs = regs->r_cs;
2376         tp->tf_eflags = regs->r_eflags;
2377         tp->tf_esp = regs->r_esp;
2378         tp->tf_ss = regs->r_ss;
2379         pcb = &p->p_addr->u_pcb;
2380         pcb->pcb_gs = regs->r_gs;
2381         return (0);
2382 }
2383
2384 int
2385 fill_fpregs(p, fpregs)
2386         struct proc *p;
2387         struct fpreg *fpregs;
2388 {
2389         bcopy(&p->p_addr->u_pcb.pcb_savefpu, fpregs, sizeof *fpregs);
2390         return (0);
2391 }
2392
2393 int
2394 set_fpregs(p, fpregs)
2395         struct proc *p;
2396         struct fpreg *fpregs;
2397 {
2398         bcopy(fpregs, &p->p_addr->u_pcb.pcb_savefpu, sizeof *fpregs);
2399         return (0);
2400 }
2401
2402 int
2403 fill_dbregs(p, dbregs)
2404         struct proc *p;
2405         struct dbreg *dbregs;
2406 {
2407         struct pcb *pcb;
2408
2409         pcb = &p->p_addr->u_pcb;
2410         dbregs->dr0 = pcb->pcb_dr0;
2411         dbregs->dr1 = pcb->pcb_dr1;
2412         dbregs->dr2 = pcb->pcb_dr2;
2413         dbregs->dr3 = pcb->pcb_dr3;
2414         dbregs->dr4 = 0;
2415         dbregs->dr5 = 0;
2416         dbregs->dr6 = pcb->pcb_dr6;
2417         dbregs->dr7 = pcb->pcb_dr7;
2418         return (0);
2419 }
2420
2421 int
2422 set_dbregs(p, dbregs)
2423         struct proc *p;
2424         struct dbreg *dbregs;
2425 {
2426         struct pcb *pcb;
2427
2428         pcb = &p->p_addr->u_pcb;
2429
2430         /*
2431          * Don't let a process set a breakpoint that is not within the
2432          * process's address space.  If a process could do this, it
2433          * could halt the system by setting a breakpoint in the kernel
2434          * (if ddb was enabled).  Thus, we need to check to make sure
2435          * that no breakpoints are being enabled for addresses outside
2436          * process's address space, unless, perhaps, we were called by
2437          * uid 0.
2438          *
2439          * XXX - what about when the watched area of the user's
2440          * address space is written into from within the kernel
2441          * ... wouldn't that still cause a breakpoint to be generated
2442          * from within kernel mode?
2443          */
2444
2445         if (p->p_ucred->cr_uid != 0) {
2446                 if (dbregs->dr7 & 0x3) {
2447                         /* dr0 is enabled */
2448                         if (dbregs->dr0 >= VM_MAXUSER_ADDRESS)
2449                                 return (EINVAL);
2450                 }
2451
2452                 if (dbregs->dr7 & (0x3<<2)) {
2453                         /* dr1 is enabled */
2454                         if (dbregs->dr1 >= VM_MAXUSER_ADDRESS)
2455                                 return (EINVAL);
2456                 }
2457
2458                 if (dbregs->dr7 & (0x3<<4)) {
2459                         /* dr2 is enabled */
2460                         if (dbregs->dr2 >= VM_MAXUSER_ADDRESS)
2461                                 return (EINVAL);
2462                 }
2463
2464                 if (dbregs->dr7 & (0x3<<6)) {
2465                         /* dr3 is enabled */
2466                         if (dbregs->dr3 >= VM_MAXUSER_ADDRESS)
2467                                 return (EINVAL);
2468                 }
2469         }
2470
2471         pcb->pcb_dr0 = dbregs->dr0;
2472         pcb->pcb_dr1 = dbregs->dr1;
2473         pcb->pcb_dr2 = dbregs->dr2;
2474         pcb->pcb_dr3 = dbregs->dr3;
2475         pcb->pcb_dr6 = dbregs->dr6;
2476         pcb->pcb_dr7 = dbregs->dr7;
2477
2478         pcb->pcb_flags |= PCB_DBREGS;
2479
2480         return (0);
2481 }
2482
2483 #ifndef DDB
2484 void
2485 Debugger(const char *msg)
2486 {
2487         printf("Debugger(\"%s\") called.\n", msg);
2488 }
2489 #endif /* no DDB */
2490
2491 #include <sys/disklabel.h>
2492
2493 /*
2494  * Determine the size of the transfer, and make sure it is
2495  * within the boundaries of the partition. Adjust transfer
2496  * if needed, and signal errors or early completion.
2497  */
2498 int
2499 bounds_check_with_label(struct buf *bp, struct disklabel *lp, int wlabel)
2500 {
2501         struct partition *p = lp->d_partitions + dkpart(bp->b_dev);
2502         int labelsect = lp->d_partitions[0].p_offset;
2503         int maxsz = p->p_size,
2504                 sz = (bp->b_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT;
2505
2506         /* overwriting disk label ? */
2507         /* XXX should also protect bootstrap in first 8K */
2508         if (bp->b_blkno + p->p_offset <= LABELSECTOR + labelsect &&
2509 #if LABELSECTOR != 0
2510             bp->b_blkno + p->p_offset + sz > LABELSECTOR + labelsect &&
2511 #endif
2512             (bp->b_flags & B_READ) == 0 && wlabel == 0) {
2513                 bp->b_error = EROFS;
2514                 goto bad;
2515         }
2516
2517 #if     defined(DOSBBSECTOR) && defined(notyet)
2518         /* overwriting master boot record? */
2519         if (bp->b_blkno + p->p_offset <= DOSBBSECTOR &&
2520             (bp->b_flags & B_READ) == 0 && wlabel == 0) {
2521                 bp->b_error = EROFS;
2522                 goto bad;
2523         }
2524 #endif
2525
2526         /* beyond partition? */
2527         if (bp->b_blkno < 0 || bp->b_blkno + sz > maxsz) {
2528                 /* if exactly at end of disk, return an EOF */
2529                 if (bp->b_blkno == maxsz) {
2530                         bp->b_resid = bp->b_bcount;
2531                         return(0);
2532                 }
2533                 /* or truncate if part of it fits */
2534                 sz = maxsz - bp->b_blkno;
2535                 if (sz <= 0) {
2536                         bp->b_error = EINVAL;
2537                         goto bad;
2538                 }
2539                 bp->b_bcount = sz << DEV_BSHIFT;
2540         }
2541
2542         bp->b_pblkno = bp->b_blkno + p->p_offset;
2543         return(1);
2544
2545 bad:
2546         bp->b_flags |= B_ERROR;
2547         return(-1);
2548 }
2549
2550 #ifdef DDB
2551
2552 /*
2553  * Provide inb() and outb() as functions.  They are normally only
2554  * available as macros calling inlined functions, thus cannot be
2555  * called inside DDB.
2556  *
2557  * The actual code is stolen from <machine/cpufunc.h>, and de-inlined.
2558  */
2559
2560 #undef inb
2561 #undef outb
2562
2563 /* silence compiler warnings */
2564 u_char inb(u_int);
2565 void outb(u_int, u_char);
2566
2567 u_char
2568 inb(u_int port)
2569 {
2570         u_char  data;
2571         /*
2572          * We use %%dx and not %1 here because i/o is done at %dx and not at
2573          * %edx, while gcc generates inferior code (movw instead of movl)
2574          * if we tell it to load (u_short) port.
2575          */
2576         __asm __volatile("inb %%dx,%0" : "=a" (data) : "d" (port));
2577         return (data);
2578 }
2579
2580 void
2581 outb(u_int port, u_char data)
2582 {
2583         u_char  al;
2584         /*
2585          * Use an unnecessary assignment to help gcc's register allocator.
2586          * This make a large difference for gcc-1.40 and a tiny difference
2587          * for gcc-2.6.0.  For gcc-1.40, al had to be ``asm("ax")'' for
2588          * best results.  gcc-2.6.0 can't handle this.
2589          */
2590         al = data;
2591         __asm __volatile("outb %0,%%dx" : : "a" (al), "d" (port));
2592 }
2593
2594 #endif /* DDB */