BSD 4_3_Net_2 release
[unix-history] / usr / src / sys / i386 / i386 / machdep.c
... / ...
CommitLineData
1/*-
2 * Copyright (c) 1982, 1987, 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * William Jolitz.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * @(#)machdep.c 7.4 (Berkeley) 6/3/91
37 */
38
39
40#include "param.h"
41#include "systm.h"
42#include "signalvar.h"
43#include "kernel.h"
44#include "map.h"
45#include "proc.h"
46#include "user.h"
47#include "buf.h"
48#include "reboot.h"
49#include "conf.h"
50#include "file.h"
51#include "clist.h"
52#include "callout.h"
53#include "malloc.h"
54#include "mbuf.h"
55#include "msgbuf.h"
56#include "net/netisr.h"
57
58#include "vm/vm.h"
59#include "vm/vm_kern.h"
60#include "vm/vm_page.h"
61
62vm_map_t buffer_map;
63extern vm_offset_t avail_end;
64
65#include "machine/cpu.h"
66#include "machine/reg.h"
67#include "machine/psl.h"
68#include "machine/specialreg.h"
69#include "i386/isa/rtc.h"
70
71/*
72 * Declare these as initialized data so we can patch them.
73 */
74int nswbuf = 0;
75#ifdef NBUF
76int nbuf = NBUF;
77#else
78int nbuf = 0;
79#endif
80#ifdef BUFPAGES
81int bufpages = BUFPAGES;
82#else
83int bufpages = 0;
84#endif
85int msgbufmapped; /* set when safe to use msgbuf */
86
87/*
88 * Machine-dependent startup code
89 */
90int boothowto = 0, Maxmem = 0;
91long dumplo;
92int physmem, maxmem;
93extern int bootdev;
94#ifdef SMALL
95extern int forcemaxmem;
96#endif
97int biosmem;
98
99extern cyloffset;
100
101cpu_startup(firstaddr)
102 int firstaddr;
103{
104 register int unixsize;
105 register unsigned i;
106 register struct pte *pte;
107 int mapaddr, j;
108 register caddr_t v;
109 int maxbufs, base, residual;
110 extern long Usrptsize;
111 vm_offset_t minaddr, maxaddr;
112 vm_size_t size;
113
114 /*
115 * Initialize error message buffer (at end of core).
116 */
117
118 /* avail_end was pre-decremented in pmap_bootstrap to compensate */
119 for (i = 0; i < btoc(sizeof (struct msgbuf)); i++)
120 pmap_enter(pmap_kernel(), msgbufp, avail_end + i * NBPG,
121 VM_PROT_ALL, TRUE);
122 msgbufmapped = 1;
123
124#ifdef KDB
125 kdb_init(); /* startup kernel debugger */
126#endif
127 /*
128 * Good {morning,afternoon,evening,night}.
129 */
130 printf(version);
131 printf("real mem = %d\n", ctob(physmem));
132
133 /*
134 * Allocate space for system data structures.
135 * The first available real memory address is in "firstaddr".
136 * The first available kernel virtual address is in "v".
137 * As pages of kernel virtual memory are allocated, "v" is incremented.
138 * As pages of memory are allocated and cleared,
139 * "firstaddr" is incremented.
140 * An index into the kernel page table corresponding to the
141 * virtual memory address maintained in "v" is kept in "mapaddr".
142 */
143
144 /*
145 * Make two passes. The first pass calculates how much memory is
146 * needed and allocates it. The second pass assigns virtual
147 * addresses to the various data structures.
148 */
149 firstaddr = 0;
150again:
151 v = (caddr_t)firstaddr;
152
153#define valloc(name, type, num) \
154 (name) = (type *)v; v = (caddr_t)((name)+(num))
155#define valloclim(name, type, num, lim) \
156 (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num)))
157 valloc(cfree, struct cblock, nclist);
158 valloc(callout, struct callout, ncallout);
159 valloc(swapmap, struct map, nswapmap = maxproc * 2);
160#ifdef SYSVSHM
161 valloc(shmsegs, struct shmid_ds, shminfo.shmmni);
162#endif
163 /*
164 * Determine how many buffers to allocate.
165 * Use 10% of memory for the first 2 Meg, 5% of the remaining
166 * memory. Insure a minimum of 16 buffers.
167 * We allocate 1/2 as many swap buffer headers as file i/o buffers.
168 */
169 if (bufpages == 0)
170 if (physmem < (2 * 1024 * 1024))
171 bufpages = physmem / 10 / CLSIZE;
172 else
173 bufpages = ((2 * 1024 * 1024 + physmem) / 20) / CLSIZE;
174 if (nbuf == 0) {
175 nbuf = bufpages / 2;
176 if (nbuf < 16)
177 nbuf = 16;
178 }
179 if (nswbuf == 0) {
180 nswbuf = (nbuf / 2) &~ 1; /* force even */
181 if (nswbuf > 256)
182 nswbuf = 256; /* sanity */
183 }
184 valloc(swbuf, struct buf, nswbuf);
185 valloc(buf, struct buf, nbuf);
186
187 /*
188 * End of first pass, size has been calculated so allocate memory
189 */
190 if (firstaddr == 0) {
191 size = (vm_size_t)(v - firstaddr);
192 firstaddr = (int)kmem_alloc(kernel_map, round_page(size));
193 if (firstaddr == 0)
194 panic("startup: no room for tables");
195 goto again;
196 }
197 /*
198 * End of second pass, addresses have been assigned
199 */
200 if ((vm_size_t)(v - firstaddr) != size)
201 panic("startup: table size inconsistency");
202 /*
203 * Now allocate buffers proper. They are different than the above
204 * in that they usually occupy more virtual memory than physical.
205 */
206 size = MAXBSIZE * nbuf;
207 buffer_map = kmem_suballoc(kernel_map, (vm_offset_t)&buffers,
208 &maxaddr, size, FALSE);
209 minaddr = (vm_offset_t)buffers;
210 if (vm_map_find(buffer_map, vm_object_allocate(size), (vm_offset_t)0,
211 &minaddr, size, FALSE) != KERN_SUCCESS)
212 panic("startup: cannot allocate buffers");
213 base = bufpages / nbuf;
214 residual = bufpages % nbuf;
215 for (i = 0; i < nbuf; i++) {
216 vm_size_t curbufsize;
217 vm_offset_t curbuf;
218
219 /*
220 * First <residual> buffers get (base+1) physical pages
221 * allocated for them. The rest get (base) physical pages.
222 *
223 * The rest of each buffer occupies virtual space,
224 * but has no physical memory allocated for it.
225 */
226 curbuf = (vm_offset_t)buffers + i * MAXBSIZE;
227 curbufsize = CLBYTES * (i < residual ? base+1 : base);
228 vm_map_pageable(buffer_map, curbuf, curbuf+curbufsize, FALSE);
229 vm_map_simplify(buffer_map, curbuf);
230 }
231 /*
232 * Allocate a submap for exec arguments. This map effectively
233 * limits the number of processes exec'ing at any time.
234 */
235 exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
236 16*NCARGS, TRUE);
237 /*
238 * Allocate a submap for physio
239 */
240 phys_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
241 VM_PHYS_SIZE, TRUE);
242
243 /*
244 * Finally, allocate mbuf pool. Since mclrefcnt is an off-size
245 * we use the more space efficient malloc in place of kmem_alloc.
246 */
247 mclrefcnt = (char *)malloc(NMBCLUSTERS+CLBYTES/MCLBYTES,
248 M_MBUF, M_NOWAIT);
249 bzero(mclrefcnt, NMBCLUSTERS+CLBYTES/MCLBYTES);
250 mb_map = kmem_suballoc(kernel_map, (vm_offset_t)&mbutl, &maxaddr,
251 VM_MBUF_SIZE, FALSE);
252 /*
253 * Initialize callouts
254 */
255 callfree = callout;
256 for (i = 1; i < ncallout; i++)
257 callout[i-1].c_next = &callout[i];
258
259 printf("avail mem = %d\n", ptoa(vm_page_free_count));
260 printf("using %d buffers containing %d bytes of memory\n",
261 nbuf, bufpages * CLBYTES);
262
263 /*
264 * Set up CPU-specific registers, cache, etc.
265 */
266 initcpu();
267
268 /*
269 * Set up buffers, so they can be used to read disk labels.
270 */
271 bufinit();
272
273 /*
274 * Configure the system.
275 */
276 configure();
277}
278
279#ifdef PGINPROF
280/*
281 * Return the difference (in microseconds)
282 * between the current time and a previous
283 * time as represented by the arguments.
284 * If there is a pending clock interrupt
285 * which has not been serviced due to high
286 * ipl, return error code.
287 */
288/*ARGSUSED*/
289vmtime(otime, olbolt, oicr)
290 register int otime, olbolt, oicr;
291{
292
293 return (((time.tv_sec-otime)*60 + lbolt-olbolt)*16667);
294}
295#endif
296
297struct sigframe {
298 int sf_signum;
299 int sf_code;
300 struct sigcontext *sf_scp;
301 sig_t sf_handler;
302 int sf_eax;
303 int sf_edx;
304 int sf_ecx;
305 struct sigcontext sf_sc;
306} ;
307
308extern int kstack[];
309
310/*
311 * Send an interrupt to process.
312 *
313 * Stack is set up to allow sigcode stored
314 * in u. to call routine, followed by kcall
315 * to sigreturn routine below. After sigreturn
316 * resets the signal mask, the stack, and the
317 * frame pointer, it returns to the user
318 * specified pc, psl.
319 */
320void
321sendsig(catcher, sig, mask, code)
322 sig_t catcher;
323 int sig, mask;
324 unsigned code;
325{
326 register struct proc *p = curproc;
327 register int *regs;
328 register struct sigframe *fp;
329 struct sigacts *ps = p->p_sigacts;
330 int oonstack, frmtrap;
331
332 regs = p->p_regs;
333 oonstack = ps->ps_onstack;
334 frmtrap = curpcb->pcb_flags & FM_TRAP;
335 /*
336 * Allocate and validate space for the signal handler
337 * context. Note that if the stack is in P0 space, the
338 * call to grow() is a nop, and the useracc() check
339 * will fail if the process has not already allocated
340 * the space with a `brk'.
341 */
342 if (!ps->ps_onstack && (ps->ps_sigonstack & sigmask(sig))) {
343 fp = (struct sigframe *)(ps->ps_sigsp
344 - sizeof(struct sigframe));
345 ps->ps_onstack = 1;
346 } else {
347 if (frmtrap)
348 fp = (struct sigframe *)(regs[tESP]
349 - sizeof(struct sigframe));
350 else
351 fp = (struct sigframe *)(regs[sESP]
352 - sizeof(struct sigframe));
353 }
354
355 if ((unsigned)fp <= USRSTACK - ctob(p->p_vmspace->vm_ssize))
356 (void)grow((unsigned)fp);
357
358 if (useracc((caddr_t)fp, sizeof (struct sigframe), B_WRITE) == 0) {
359 /*
360 * Process has trashed its stack; give it an illegal
361 * instruction to halt it in its tracks.
362 */
363 SIGACTION(p, SIGILL) = SIG_DFL;
364 sig = sigmask(SIGILL);
365 p->p_sigignore &= ~sig;
366 p->p_sigcatch &= ~sig;
367 p->p_sigmask &= ~sig;
368 psignal(p, SIGILL);
369 return;
370 }
371
372 /*
373 * Build the argument list for the signal handler.
374 */
375 fp->sf_signum = sig;
376 fp->sf_code = code;
377 fp->sf_scp = &fp->sf_sc;
378 fp->sf_handler = catcher;
379
380 /* save scratch registers */
381 if(frmtrap) {
382 fp->sf_eax = regs[tEAX];
383 fp->sf_edx = regs[tEDX];
384 fp->sf_ecx = regs[tECX];
385 } else {
386 fp->sf_eax = regs[sEAX];
387 fp->sf_edx = regs[sEDX];
388 fp->sf_ecx = regs[sECX];
389 }
390 /*
391 * Build the signal context to be used by sigreturn.
392 */
393 fp->sf_sc.sc_onstack = oonstack;
394 fp->sf_sc.sc_mask = mask;
395 if(frmtrap) {
396 fp->sf_sc.sc_sp = regs[tESP];
397 fp->sf_sc.sc_fp = regs[tEBP];
398 fp->sf_sc.sc_pc = regs[tEIP];
399 fp->sf_sc.sc_ps = regs[tEFLAGS];
400 regs[tESP] = (int)fp;
401 regs[tEIP] = (int)((struct pcb *)kstack)->pcb_sigc;
402 } else {
403 fp->sf_sc.sc_sp = regs[sESP];
404 fp->sf_sc.sc_fp = regs[sEBP];
405 fp->sf_sc.sc_pc = regs[sEIP];
406 fp->sf_sc.sc_ps = regs[sEFLAGS];
407 regs[sESP] = (int)fp;
408 regs[sEIP] = (int)((struct pcb *)kstack)->pcb_sigc;
409 }
410}
411
412/*
413 * System call to cleanup state after a signal
414 * has been taken. Reset signal mask and
415 * stack state from context left by sendsig (above).
416 * Return to previous pc and psl as specified by
417 * context left by sendsig. Check carefully to
418 * make sure that the user has not modified the
419 * psl to gain improper priviledges or to cause
420 * a machine fault.
421 */
422sigreturn(p, uap, retval)
423 struct proc *p;
424 struct args {
425 struct sigcontext *sigcntxp;
426 } *uap;
427 int *retval;
428{
429 register struct sigcontext *scp;
430 register struct sigframe *fp;
431 register int *regs = p->p_regs;
432
433
434 fp = (struct sigframe *) regs[sESP] ;
435
436 if (useracc((caddr_t)fp, sizeof (*fp), 0) == 0)
437 return(EINVAL);
438
439 /* restore scratch registers */
440 regs[sEAX] = fp->sf_eax ;
441 regs[sEDX] = fp->sf_edx ;
442 regs[sECX] = fp->sf_ecx ;
443
444 scp = fp->sf_scp;
445 if (useracc((caddr_t)scp, sizeof (*scp), 0) == 0)
446 return(EINVAL);
447#ifdef notyet
448 if ((scp->sc_ps & PSL_MBZ) != 0 || (scp->sc_ps & PSL_MBO) != PSL_MBO) {
449 return(EINVAL);
450 }
451#endif
452 p->p_sigacts->ps_onstack = scp->sc_onstack & 01;
453 p->p_sigmask = scp->sc_mask &~
454 (sigmask(SIGKILL)|sigmask(SIGCONT)|sigmask(SIGSTOP));
455 regs[sEBP] = scp->sc_fp;
456 regs[sESP] = scp->sc_sp;
457 regs[sEIP] = scp->sc_pc;
458 regs[sEFLAGS] = scp->sc_ps;
459 return(EJUSTRETURN);
460}
461
462int waittime = -1;
463
464boot(arghowto)
465 int arghowto;
466{
467 register long dummy; /* r12 is reserved */
468 register int howto; /* r11 == how to boot */
469 register int devtype; /* r10 == major of root dev */
470 extern char *panicstr;
471
472 howto = arghowto;
473 if ((howto&RB_NOSYNC) == 0 && waittime < 0 && bfreelist[0].b_forw) {
474 register struct buf *bp;
475 int iter, nbusy;
476
477 waittime = 0;
478 (void) splnet();
479 printf("syncing disks... ");
480 /*
481 * Release inodes held by texts before update.
482 */
483 if (panicstr == 0)
484 vnode_pager_umount(NULL);
485 sync((struct sigcontext *)0);
486
487 for (iter = 0; iter < 20; iter++) {
488 nbusy = 0;
489 for (bp = &buf[nbuf]; --bp >= buf; )
490 if ((bp->b_flags & (B_BUSY|B_INVAL)) == B_BUSY)
491 nbusy++;
492 if (nbusy == 0)
493 break;
494 printf("%d ", nbusy);
495 DELAY(40000 * iter);
496 }
497 if (nbusy)
498 printf("giving up\n");
499 else
500 printf("done\n");
501 DELAY(10000); /* wait for printf to finish */
502 }
503 splhigh();
504 devtype = major(rootdev);
505 if (howto&RB_HALT) {
506 printf("halting (in tight loop); hit reset\n\n");
507 splx(0xfffd); /* all but keyboard XXX */
508 for (;;) ;
509 } else {
510 if (howto & RB_DUMP) {
511 dumpsys();
512 /*NOTREACHED*/
513 }
514 }
515#ifdef lint
516 dummy = 0; dummy = dummy;
517 printf("howto %d, devtype %d\n", arghowto, devtype);
518#endif
519 reset_cpu();
520 for(;;) ;
521 /*NOTREACHED*/
522}
523
524int dumpmag = 0x8fca0101; /* magic number for savecore */
525int dumpsize = 0; /* also for savecore */
526/*
527 * Doadump comes here after turning off memory management and
528 * getting on the dump stack, either when called above, or by
529 * the auto-restart code.
530 */
531dumpsys()
532{
533
534 if (dumpdev == NODEV)
535 return;
536 if ((minor(dumpdev)&07) != 1)
537 return;
538 dumpsize = physmem;
539 printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo);
540 printf("dump ");
541 switch ((*bdevsw[major(dumpdev)].d_dump)(dumpdev)) {
542
543 case ENXIO:
544 printf("device bad\n");
545 break;
546
547 case EFAULT:
548 printf("device not ready\n");
549 break;
550
551 case EINVAL:
552 printf("area improper\n");
553 break;
554
555 case EIO:
556 printf("i/o error\n");
557 break;
558
559 default:
560 printf("succeeded\n");
561 break;
562 }
563 printf("\n\n");
564 DELAY(1000);
565}
566
567microtime(tvp)
568 register struct timeval *tvp;
569{
570 int s = splhigh();
571
572 *tvp = time;
573 tvp->tv_usec += tick;
574 while (tvp->tv_usec > 1000000) {
575 tvp->tv_sec++;
576 tvp->tv_usec -= 1000000;
577 }
578 splx(s);
579}
580
581physstrat(bp, strat, prio)
582 struct buf *bp;
583 int (*strat)(), prio;
584{
585 register int s;
586 caddr_t baddr;
587
588 /*
589 * vmapbuf clobbers b_addr so we must remember it so that it
590 * can be restored after vunmapbuf. This is truely rude, we
591 * should really be storing this in a field in the buf struct
592 * but none are available and I didn't want to add one at
593 * this time. Note that b_addr for dirty page pushes is
594 * restored in vunmapbuf. (ugh!)
595 */
596 baddr = bp->b_un.b_addr;
597 vmapbuf(bp);
598 (*strat)(bp);
599 /* pageout daemon doesn't wait for pushed pages */
600 if (bp->b_flags & B_DIRTY)
601 return;
602 s = splbio();
603 while ((bp->b_flags & B_DONE) == 0)
604 sleep((caddr_t)bp, prio);
605 splx(s);
606 vunmapbuf(bp);
607 bp->b_un.b_addr = baddr;
608}
609
610initcpu()
611{
612}
613
614/*
615 * Clear registers on exec
616 */
617setregs(p, entry)
618 struct proc *p;
619 u_long entry;
620{
621
622 p->p_regs[sEBP] = 0; /* bottom of the fp chain */
623 p->p_regs[sEIP] = entry;
624
625 p->p_addr->u_pcb.pcb_flags = 0; /* no fp at all */
626 load_cr0(rcr0() | CR0_EM); /* start emulating */
627#ifdef NPX
628 npxinit(0x262);
629#endif
630}
631
632/*
633 * Initialize 386 and configure to run kernel
634 */
635
636/*
637 * Initialize segments & interrupt table
638 */
639
640
641#define GNULL_SEL 0 /* Null Descriptor */
642#define GCODE_SEL 1 /* Kernel Code Descriptor */
643#define GDATA_SEL 2 /* Kernel Data Descriptor */
644#define GLDT_SEL 3 /* LDT - eventually one per process */
645#define GTGATE_SEL 4 /* Process task switch gate */
646#define GPANIC_SEL 5 /* Task state to consider panic from */
647#define GPROC0_SEL 6 /* Task state process slot zero and up */
648#define NGDT GPROC0_SEL+1
649
650union descriptor gdt[GPROC0_SEL+1];
651
652/* interrupt descriptor table */
653struct gate_descriptor idt[32+16];
654
655/* local descriptor table */
656union descriptor ldt[5];
657#define LSYS5CALLS_SEL 0 /* forced by intel BCS */
658#define LSYS5SIGR_SEL 1
659
660#define L43BSDCALLS_SEL 2 /* notyet */
661#define LUCODE_SEL 3
662#define LUDATA_SEL 4
663/* seperate stack, es,fs,gs sels ? */
664/* #define LPOSIXCALLS_SEL 5 /* notyet */
665
666struct i386tss tss, panic_tss;
667
668extern struct user *proc0paddr;
669
670/* software prototypes -- in more palitable form */
671struct soft_segment_descriptor gdt_segs[] = {
672 /* Null Descriptor */
673{ 0x0, /* segment base address */
674 0x0, /* length - all address space */
675 0, /* segment type */
676 0, /* segment descriptor priority level */
677 0, /* segment descriptor present */
678 0,0,
679 0, /* default 32 vs 16 bit size */
680 0 /* limit granularity (byte/page units)*/ },
681 /* Code Descriptor for kernel */
682{ 0x0, /* segment base address */
683 0xfffff, /* length - all address space */
684 SDT_MEMERA, /* segment type */
685 0, /* segment descriptor priority level */
686 1, /* segment descriptor present */
687 0,0,
688 1, /* default 32 vs 16 bit size */
689 1 /* limit granularity (byte/page units)*/ },
690 /* Data Descriptor for kernel */
691{ 0x0, /* segment base address */
692 0xfffff, /* length - all address space */
693 SDT_MEMRWA, /* segment type */
694 0, /* segment descriptor priority level */
695 1, /* segment descriptor present */
696 0,0,
697 1, /* default 32 vs 16 bit size */
698 1 /* limit granularity (byte/page units)*/ },
699 /* LDT Descriptor */
700{ (int) ldt, /* segment base address */
701 sizeof(ldt)-1, /* length - all address space */
702 SDT_SYSLDT, /* segment type */
703 0, /* segment descriptor priority level */
704 1, /* segment descriptor present */
705 0,0,
706 0, /* unused - default 32 vs 16 bit size */
707 0 /* limit granularity (byte/page units)*/ },
708 /* Null Descriptor - Placeholder */
709{ 0x0, /* segment base address */
710 0x0, /* length - all address space */
711 0, /* segment type */
712 0, /* segment descriptor priority level */
713 0, /* segment descriptor present */
714 0,0,
715 0, /* default 32 vs 16 bit size */
716 0 /* limit granularity (byte/page units)*/ },
717 /* Panic Tss Descriptor */
718{ (int) &panic_tss, /* segment base address */
719 sizeof(tss)-1, /* length - all address space */
720 SDT_SYS386TSS, /* segment type */
721 0, /* segment descriptor priority level */
722 1, /* segment descriptor present */
723 0,0,
724 0, /* unused - default 32 vs 16 bit size */
725 0 /* limit granularity (byte/page units)*/ },
726 /* Proc 0 Tss Descriptor */
727{ (int) kstack, /* segment base address */
728 sizeof(tss)-1, /* length - all address space */
729 SDT_SYS386TSS, /* segment type */
730 0, /* segment descriptor priority level */
731 1, /* segment descriptor present */
732 0,0,
733 0, /* unused - default 32 vs 16 bit size */
734 0 /* limit granularity (byte/page units)*/ }};
735
736struct soft_segment_descriptor ldt_segs[] = {
737 /* Null Descriptor - overwritten by call gate */
738{ 0x0, /* segment base address */
739 0x0, /* length - all address space */
740 0, /* segment type */
741 0, /* segment descriptor priority level */
742 0, /* segment descriptor present */
743 0,0,
744 0, /* default 32 vs 16 bit size */
745 0 /* limit granularity (byte/page units)*/ },
746 /* Null Descriptor - overwritten by call gate */
747{ 0x0, /* segment base address */
748 0x0, /* length - all address space */
749 0, /* segment type */
750 0, /* segment descriptor priority level */
751 0, /* segment descriptor present */
752 0,0,
753 0, /* default 32 vs 16 bit size */
754 0 /* limit granularity (byte/page units)*/ },
755 /* Null Descriptor - overwritten by call gate */
756{ 0x0, /* segment base address */
757 0x0, /* length - all address space */
758 0, /* segment type */
759 0, /* segment descriptor priority level */
760 0, /* segment descriptor present */
761 0,0,
762 0, /* default 32 vs 16 bit size */
763 0 /* limit granularity (byte/page units)*/ },
764 /* Code Descriptor for user */
765{ 0x0, /* segment base address */
766 0xfffff, /* length - all address space */
767 SDT_MEMERA, /* segment type */
768 SEL_UPL, /* segment descriptor priority level */
769 1, /* segment descriptor present */
770 0,0,
771 1, /* default 32 vs 16 bit size */
772 1 /* limit granularity (byte/page units)*/ },
773 /* Data Descriptor for user */
774{ 0x0, /* segment base address */
775 0xfffff, /* length - all address space */
776 SDT_MEMRWA, /* segment type */
777 SEL_UPL, /* segment descriptor priority level */
778 1, /* segment descriptor present */
779 0,0,
780 1, /* default 32 vs 16 bit size */
781 1 /* limit granularity (byte/page units)*/ } };
782
783/* table descriptors - used to load tables by microp */
784struct region_descriptor r_gdt = {
785 sizeof(gdt)-1,(char *)gdt
786};
787
788struct region_descriptor r_idt = {
789 sizeof(idt)-1,(char *)idt
790};
791
792setidt(idx, func, typ, dpl) char *func; {
793 struct gate_descriptor *ip = idt + idx;
794
795 ip->gd_looffset = (int)func;
796 ip->gd_selector = 8;
797 ip->gd_stkcpy = 0;
798 ip->gd_xx = 0;
799 ip->gd_type = typ;
800 ip->gd_dpl = dpl;
801 ip->gd_p = 1;
802 ip->gd_hioffset = ((int)func)>>16 ;
803}
804
805#define IDTVEC(name) __CONCAT(X, name)
806extern IDTVEC(div), IDTVEC(dbg), IDTVEC(nmi), IDTVEC(bpt), IDTVEC(ofl),
807 IDTVEC(bnd), IDTVEC(ill), IDTVEC(dna), IDTVEC(dble), IDTVEC(fpusegm),
808 IDTVEC(tss), IDTVEC(missing), IDTVEC(stk), IDTVEC(prot),
809 IDTVEC(page), IDTVEC(rsvd), IDTVEC(fpu), IDTVEC(rsvd0),
810 IDTVEC(rsvd1), IDTVEC(rsvd2), IDTVEC(rsvd3), IDTVEC(rsvd4),
811 IDTVEC(rsvd5), IDTVEC(rsvd6), IDTVEC(rsvd7), IDTVEC(rsvd8),
812 IDTVEC(rsvd9), IDTVEC(rsvd10), IDTVEC(rsvd11), IDTVEC(rsvd12),
813 IDTVEC(rsvd13), IDTVEC(rsvd14), IDTVEC(rsvd14), IDTVEC(syscall);
814
815int lcr0(), lcr3(), rcr0(), rcr2();
816int _udatasel, _ucodesel, _gsel_tss;
817
818init386(first) { extern ssdtosd(), lgdt(), lidt(), lldt(), etext;
819 int x, *pi;
820 unsigned biosbasemem, biosextmem;
821 struct gate_descriptor *gdp;
822 extern int sigcode,szsigcode;
823
824 proc0.p_addr = proc0paddr;
825
826 /*
827 * Initialize the console before we print anything out.
828 */
829
830 cninit (KERNBASE+0xa0000);
831
832 /* make gdt memory segments */
833 gdt_segs[GCODE_SEL].ssd_limit = btoc((int) &etext + NBPG);
834 for (x=0; x < NGDT; x++) ssdtosd(gdt_segs+x, gdt+x);
835 /* make ldt memory segments */
836 ldt_segs[LUCODE_SEL].ssd_limit = btoc(UPT_MIN_ADDRESS);
837 ldt_segs[LUDATA_SEL].ssd_limit = btoc(UPT_MIN_ADDRESS);
838 /* Note. eventually want private ldts per process */
839 for (x=0; x < 5; x++) ssdtosd(ldt_segs+x, ldt+x);
840
841 /* exceptions */
842 setidt(0, &IDTVEC(div), SDT_SYS386TGT, SEL_KPL);
843 setidt(1, &IDTVEC(dbg), SDT_SYS386TGT, SEL_KPL);
844 setidt(2, &IDTVEC(nmi), SDT_SYS386TGT, SEL_KPL);
845 setidt(3, &IDTVEC(bpt), SDT_SYS386TGT, SEL_UPL);
846 setidt(4, &IDTVEC(ofl), SDT_SYS386TGT, SEL_KPL);
847 setidt(5, &IDTVEC(bnd), SDT_SYS386TGT, SEL_KPL);
848 setidt(6, &IDTVEC(ill), SDT_SYS386TGT, SEL_KPL);
849 setidt(7, &IDTVEC(dna), SDT_SYS386TGT, SEL_KPL);
850 setidt(8, &IDTVEC(dble), SDT_SYS386TGT, SEL_KPL);
851 setidt(9, &IDTVEC(fpusegm), SDT_SYS386TGT, SEL_KPL);
852 setidt(10, &IDTVEC(tss), SDT_SYS386TGT, SEL_KPL);
853 setidt(11, &IDTVEC(missing), SDT_SYS386TGT, SEL_KPL);
854 setidt(12, &IDTVEC(stk), SDT_SYS386TGT, SEL_KPL);
855 setidt(13, &IDTVEC(prot), SDT_SYS386TGT, SEL_KPL);
856 setidt(14, &IDTVEC(page), SDT_SYS386TGT, SEL_KPL);
857 setidt(15, &IDTVEC(rsvd), SDT_SYS386TGT, SEL_KPL);
858 setidt(16, &IDTVEC(fpu), SDT_SYS386TGT, SEL_KPL);
859 setidt(17, &IDTVEC(rsvd0), SDT_SYS386TGT, SEL_KPL);
860 setidt(18, &IDTVEC(rsvd1), SDT_SYS386TGT, SEL_KPL);
861 setidt(19, &IDTVEC(rsvd2), SDT_SYS386TGT, SEL_KPL);
862 setidt(20, &IDTVEC(rsvd3), SDT_SYS386TGT, SEL_KPL);
863 setidt(21, &IDTVEC(rsvd4), SDT_SYS386TGT, SEL_KPL);
864 setidt(22, &IDTVEC(rsvd5), SDT_SYS386TGT, SEL_KPL);
865 setidt(23, &IDTVEC(rsvd6), SDT_SYS386TGT, SEL_KPL);
866 setidt(24, &IDTVEC(rsvd7), SDT_SYS386TGT, SEL_KPL);
867 setidt(25, &IDTVEC(rsvd8), SDT_SYS386TGT, SEL_KPL);
868 setidt(26, &IDTVEC(rsvd9), SDT_SYS386TGT, SEL_KPL);
869 setidt(27, &IDTVEC(rsvd10), SDT_SYS386TGT, SEL_KPL);
870 setidt(28, &IDTVEC(rsvd11), SDT_SYS386TGT, SEL_KPL);
871 setidt(29, &IDTVEC(rsvd12), SDT_SYS386TGT, SEL_KPL);
872 setidt(30, &IDTVEC(rsvd13), SDT_SYS386TGT, SEL_KPL);
873 setidt(31, &IDTVEC(rsvd14), SDT_SYS386TGT, SEL_KPL);
874
875#include "isa.h"
876#if NISA >0
877 isa_defaultirq();
878#endif
879
880 lgdt(gdt, sizeof(gdt)-1);
881 lidt(idt, sizeof(idt)-1);
882 lldt(GSEL(GLDT_SEL, SEL_KPL));
883
884#ifdef notyet
885 /* determine amount of memory present so we can scale kernel PT */
886 for (i= RAM_BEGIN; i < IOM_BEGIN; i += NBPG)
887 if (probemem(i) == 0) break;
888 if (i == IOM_BEGIN) {
889 if (maxphysmem == 0) maxphysmem = RAM_END;
890 for (i= IOM_END; i < maxphysmem; i += NBPG)
891 if (probemem(i) == 0) break;
892 }
893 maxmem = i / NBPG;
894#else
895Maxmem = 8192 *1024 /NBPG;
896 maxmem = Maxmem;
897#endif
898
899 /* reconcile against BIOS's recorded values in RTC
900 * we trust neither of them, as both can lie!
901 */
902 biosbasemem = rtcin(RTC_BASELO)+ (rtcin(RTC_BASEHI)<<8);
903 biosextmem = rtcin(RTC_EXTLO)+ (rtcin(RTC_EXTHI)<<8);
904 if (biosbasemem == 0xffff || biosextmem == 0xffff) {
905 if (maxmem > 0xffc)
906 maxmem = 640/4;
907 } else if (biosextmem > 0 && biosbasemem == 640) {
908 int totbios = (biosbasemem + 0x60000 + biosextmem)/4;
909 if (totbios < maxmem) maxmem = totbios;
910 } else maxmem = 640/4;
911 maxmem = maxmem-1;
912 physmem = maxmem - (0x100 -0xa0);
913
914 /* call pmap initialization to make new kernel address space */
915 pmap_bootstrap (first, 0);
916 /* now running on new page tables, configured,and u/iom is accessible */
917
918 /* make a initial tss so microp can get interrupt stack on syscall! */
919 proc0.p_addr->u_pcb.pcb_tss.tss_esp0 = (int) kstack + UPAGES*NBPG;
920 proc0.p_addr->u_pcb.pcb_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL) ;
921 _gsel_tss = GSEL(GPROC0_SEL, SEL_KPL);
922 ltr(_gsel_tss);
923
924 /* make a call gate to reenter kernel with */
925 gdp = &ldt[LSYS5CALLS_SEL].gd;
926
927 x = (int) &IDTVEC(syscall);
928 gdp->gd_looffset = x++;
929 gdp->gd_selector = GSEL(GCODE_SEL,SEL_KPL);
930 gdp->gd_stkcpy = 0;
931 gdp->gd_type = SDT_SYS386CGT;
932 gdp->gd_dpl = SEL_UPL;
933 gdp->gd_p = 1;
934 gdp->gd_hioffset = ((int) &IDTVEC(syscall)) >>16;
935
936 /* transfer to user mode */
937
938 _ucodesel = LSEL(LUCODE_SEL, SEL_UPL);
939 _udatasel = LSEL(LUDATA_SEL, SEL_UPL);
940
941 /* setup proc 0's pcb */
942 bcopy(&sigcode, proc0.p_addr->u_pcb.pcb_sigc, szsigcode);
943 proc0.p_addr->u_pcb.pcb_flags = 0;
944 proc0.p_addr->u_pcb.pcb_ptd = IdlePTD;
945}
946
947extern struct pte *CMAP1, *CMAP2;
948extern caddr_t CADDR1, CADDR2;
949/*
950 * zero out physical memory
951 * specified in relocation units (NBPG bytes)
952 */
953clearseg(n) {
954
955 *(int *)CMAP2 = PG_V | PG_KW | ctob(n);
956 load_cr3(rcr3());
957 bzero(CADDR2,NBPG);
958 *(int *) CADDR2 = 0;
959}
960
961/*
962 * copy a page of physical memory
963 * specified in relocation units (NBPG bytes)
964 */
965copyseg(frm, n) {
966
967 *(int *)CMAP2 = PG_V | PG_KW | ctob(n);
968 load_cr3(rcr3());
969 bcopy((void *)frm, (void *)CADDR2, NBPG);
970}
971
972/*
973 * copy a page of physical memory
974 * specified in relocation units (NBPG bytes)
975 */
976physcopyseg(frm, to) {
977
978 *(int *)CMAP1 = PG_V | PG_KW | ctob(frm);
979 *(int *)CMAP2 = PG_V | PG_KW | ctob(to);
980 load_cr3(rcr3());
981 bcopy(CADDR1, CADDR2, NBPG);
982}
983
984/*aston() {
985 schednetisr(NETISR_AST);
986}*/
987
988setsoftclock() {
989 schednetisr(NETISR_SCLK);
990}
991
992/*
993 * insert an element into a queue
994 */
995#undef insque
996_insque(element, head)
997 register struct prochd *element, *head;
998{
999 element->ph_link = head->ph_link;
1000 head->ph_link = (struct proc *)element;
1001 element->ph_rlink = (struct proc *)head;
1002 ((struct prochd *)(element->ph_link))->ph_rlink=(struct proc *)element;
1003}
1004
1005/*
1006 * remove an element from a queue
1007 */
1008#undef remque
1009_remque(element)
1010 register struct prochd *element;
1011{
1012 ((struct prochd *)(element->ph_link))->ph_rlink = element->ph_rlink;
1013 ((struct prochd *)(element->ph_rlink))->ph_link = element->ph_link;
1014 element->ph_rlink = (struct proc *)0;
1015}
1016
1017vmunaccess() {}
1018
1019/*
1020 * Below written in C to allow access to debugging code
1021 */
1022copyinstr(fromaddr, toaddr, maxlength, lencopied) u_int *lencopied, maxlength;
1023 void *toaddr, *fromaddr; {
1024 u_int c,tally;
1025
1026 tally = 0;
1027 while (maxlength--) {
1028 c = fubyte(fromaddr++);
1029 if (c == -1) {
1030 if(lencopied) *lencopied = tally;
1031 return(EFAULT);
1032 }
1033 tally++;
1034 *(char *)toaddr++ = (char) c;
1035 if (c == 0){
1036 if(lencopied) *lencopied = tally;
1037 return(0);
1038 }
1039 }
1040 if(lencopied) *lencopied = tally;
1041 return(ENAMETOOLONG);
1042}
1043
1044copyoutstr(fromaddr, toaddr, maxlength, lencopied) u_int *lencopied, maxlength;
1045 void *fromaddr, *toaddr; {
1046 int c;
1047 int tally;
1048
1049 tally = 0;
1050 while (maxlength--) {
1051 c = subyte(toaddr++, *(char *)fromaddr);
1052 if (c == -1) return(EFAULT);
1053 tally++;
1054 if (*(char *)fromaddr++ == 0){
1055 if(lencopied) *lencopied = tally;
1056 return(0);
1057 }
1058 }
1059 if(lencopied) *lencopied = tally;
1060 return(ENAMETOOLONG);
1061}
1062
1063copystr(fromaddr, toaddr, maxlength, lencopied) u_int *lencopied, maxlength;
1064 void *fromaddr, *toaddr; {
1065 u_int tally;
1066
1067 tally = 0;
1068 while (maxlength--) {
1069 *(u_char *)toaddr = *(u_char *)fromaddr++;
1070 tally++;
1071 if (*(u_char *)toaddr++ == 0) {
1072 if(lencopied) *lencopied = tally;
1073 return(0);
1074 }
1075 }
1076 if(lencopied) *lencopied = tally;
1077 return(ENAMETOOLONG);
1078}