machdep.c revision 4
1345153Sdim/*- 2345153Sdim * Copyright (c) 1982, 1987, 1990 The Regents of the University of California. 3345153Sdim * Copyright (c) 1992 Terrence R. Lambert. 4345153Sdim * All rights reserved. 5345153Sdim * 6345153Sdim * This code is derived from software contributed to Berkeley by 7345153Sdim * William Jolitz. 8345153Sdim * 9345153Sdim * Redistribution and use in source and binary forms, with or without 10345153Sdim * modification, are permitted provided that the following conditions 11345153Sdim * are met: 12345153Sdim * 1. Redistributions of source code must retain the above copyright 13345153Sdim * notice, this list of conditions and the following disclaimer. 14345153Sdim * 2. Redistributions in binary form must reproduce the above copyright 15345153Sdim * notice, this list of conditions and the following disclaimer in the 16345153Sdim * documentation and/or other materials provided with the distribution. 17345153Sdim * 3. All advertising materials mentioning features or use of this software 18345153Sdim * must display the following acknowledgement: 19345153Sdim * This product includes software developed by the University of 20345153Sdim * California, Berkeley and its contributors. 21345153Sdim * 4. Neither the name of the University nor the names of its contributors 22345153Sdim * may be used to endorse or promote products derived from this software 23345153Sdim * without specific prior written permission. 24345153Sdim * 25345153Sdim * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26345153Sdim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27345153Sdim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28345153Sdim * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29345153Sdim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30345153Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31345153Sdim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32345153Sdim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33345153Sdim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34345153Sdim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35345153Sdim * SUCH DAMAGE. 36345153Sdim * 37345153Sdim * @(#)machdep.c 7.4 (Berkeley) 6/3/91 38345153Sdim * 39345153Sdim * PATCHES MAGIC LEVEL PATCH THAT GOT US HERE 40345153Sdim * -------------------- ----- ---------------------- 41345153Sdim * CURRENT PATCH LEVEL: 5 00158 42345153Sdim * -------------------- ----- ---------------------- 43345153Sdim * 44345153Sdim * 15 Aug 92 William Jolitz Large memory bug 45345153Sdim * 15 Aug 92 Terry Lambert Fixed CMOS RAM size bug 46345153Sdim * 25 Mar 93 Sean Eric Fagan Added #ifdef HZ around microtime for 47345153Sdim * the new microtime.s routine 48345153Sdim * 08 Apr 93 Andrew Herbert Fixes for kmem_alloc panics 49345153Sdim * 20 Apr 93 Bruce Evans New npx-0.5 code 50345153Sdim * 25 Apr 93 Bruce Evans New intr-0.1 code 51345153Sdim */ 52345153Sdimstatic char rcsid[] = "$Header: /usr/src/sys.386bsd/i386/i386/RCS/machdep.c,v 1.2 92/01/21 14:22:09 william Exp Locker: root $"; 53345153Sdim 54345153Sdim 55345153Sdim#include <stddef.h> 56345153Sdim#include "param.h" 57345153Sdim#include "systm.h" 58345153Sdim#include "signalvar.h" 59345153Sdim#include "kernel.h" 60345153Sdim#include "proc.h" 61345153Sdim#include "user.h" 62345153Sdim#include "buf.h" 63345153Sdim#include "reboot.h" 64345153Sdim#include "conf.h" 65345153Sdim#include "file.h" 66345153Sdim#include "callout.h" 67345153Sdim#include "malloc.h" 68345153Sdim#include "mbuf.h" 69345153Sdim#include "msgbuf.h" 70345153Sdim#include "net/netisr.h" 71345153Sdim 72345153Sdim#include "vm/vm.h" 73345153Sdim#include "vm/vm_kern.h" 74345153Sdim#include "vm/vm_page.h" 75345153Sdim 76345153Sdimextern vm_offset_t avail_end; 77345153Sdim 78345153Sdim#include "machine/cpu.h" 79345153Sdim#include "machine/reg.h" 80345153Sdim#include "machine/psl.h" 81345153Sdim#include "machine/specialreg.h" 82345153Sdim#include "i386/isa/rtc.h" 83345153Sdim 84345153Sdim 85345153Sdim#define EXPECT_BASEMEM 640 /* The expected base memory*/ 86345153Sdim#define INFORM_WAIT 1 /* Set to pause berfore crash in weird cases*/ 87345153Sdim 88345153Sdim/* 89345153Sdim * Declare these as initialized data so we can patch them. 90345153Sdim */ 91345153Sdimint nswbuf = 0; 92345153Sdim#ifdef NBUF 93345153Sdimint nbuf = NBUF; 94345153Sdim#else 95345153Sdimint nbuf = 0; 96345153Sdim#endif 97345153Sdim#ifdef BUFPAGES 98345153Sdimint bufpages = BUFPAGES; 99345153Sdim#else 100345153Sdimint bufpages = 0; 101345153Sdim#endif 102345153Sdimint msgbufmapped; /* set when safe to use msgbuf */ 103345153Sdimextern int freebufspace; 104345153Sdim 105345153Sdim/* 106345153Sdim * Machine-dependent startup code 107345153Sdim */ 108345153Sdimint boothowto = 0, Maxmem = 0; 109345153Sdimlong dumplo; 110345153Sdimint physmem, maxmem; 111345153Sdimextern int bootdev; 112345153Sdim#ifdef SMALL 113345153Sdimextern int forcemaxmem; 114345153Sdim#endif 115345153Sdimint biosmem; 116345153Sdim 117345153Sdimextern cyloffset; 118345153Sdim 119345153Sdimcpu_startup() 120345153Sdim{ 121345153Sdim register int unixsize; 122345153Sdim register unsigned i; 123345153Sdim register struct pte *pte; 124345153Sdim int mapaddr, j; 125345153Sdim register caddr_t v; 126345153Sdim int maxbufs, base, residual; 127345153Sdim extern long Usrptsize; 128345153Sdim vm_offset_t minaddr, maxaddr; 129345153Sdim vm_size_t size; 130345153Sdim int firstaddr; 131345153Sdim 132345153Sdim /* 133345153Sdim * Initialize error message buffer (at end of core). 134345153Sdim */ 135345153Sdim 136345153Sdim /* avail_end was pre-decremented in pmap_bootstrap to compensate */ 137345153Sdim for (i = 0; i < btoc(sizeof (struct msgbuf)); i++) 138345153Sdim pmap_enter(pmap_kernel(), msgbufp, avail_end + i * NBPG, 139345153Sdim VM_PROT_ALL, TRUE); 140345153Sdim msgbufmapped = 1; 141345153Sdim 142345153Sdim#ifdef KDB 143345153Sdim kdb_init(); /* startup kernel debugger */ 144345153Sdim#endif 145345153Sdim /* 146345153Sdim * Good {morning,afternoon,evening,night}. 147345153Sdim */ 148345153Sdim /*printf(version); 149345153Sdim printf("real mem = %d\n", ctob(physmem));*/ 150345153Sdim 151345153Sdim /* 152345153Sdim * Allocate space for system data structures. 153345153Sdim * The first available kernel virtual address is in "v". 154345153Sdim * As pages of kernel virtual memory are allocated, "v" is incremented. 155345153Sdim * As pages of memory are allocated and cleared, 156345153Sdim * "firstaddr" is incremented. 157345153Sdim * An index into the kernel page table corresponding to the 158345153Sdim * virtual memory address maintained in "v" is kept in "mapaddr". 159345153Sdim */ 160345153Sdim 161345153Sdim /* 162345153Sdim * Make two passes. The first pass calculates how much memory is 163345153Sdim * needed and allocates it. The second pass assigns virtual 164345153Sdim * addresses to the various data structures. 165345153Sdim */ 166345153Sdim firstaddr = 0; 167345153Sdimagain: 168345153Sdim v = (caddr_t)firstaddr; 169345153Sdim 170345153Sdim#define valloc(name, type, num) \ 171345153Sdim (name) = (type *)v; v = (caddr_t)((name)+(num)) 172345153Sdim#define valloclim(name, type, num, lim) \ 173345153Sdim (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num))) 174345153Sdim valloc(callout, struct callout, ncallout); 175345153Sdim#ifdef SYSVSHM 176345153Sdim valloc(shmsegs, struct shmid_ds, shminfo.shmmni); 177345153Sdim#endif 178345153Sdim /* 179345153Sdim * Determine how many buffers to allocate. 180345153Sdim * Use 10% of memory for the first 2 Meg, 5% of the remaining 181345153Sdim * memory. Insure a minimum of 16 buffers. 182345153Sdim * We allocate 1/2 as many swap buffer headers as file i/o buffers. 183345153Sdim */ 184345153Sdim if (bufpages == 0) 185345153Sdim if (physmem < (2 * 1024 * 1024)) 186345153Sdim bufpages = physmem / 10 / CLSIZE; 187345153Sdim else 188345153Sdim bufpages = ((2 * 1024 * 1024 + physmem) / 20) / CLSIZE; 189345153Sdim /* 190345153Sdim * 15 Aug 92 William Jolitz bufpages fix for too large 191345153Sdim */ 192345153Sdim bufpages = min( NKMEMCLUSTERS*2/5, bufpages); 193345153Sdim 194345153Sdim if (nbuf == 0) { 195345153Sdim nbuf = bufpages / 2; 196345153Sdim if (nbuf < 16) 197345153Sdim nbuf = 16; 198345153Sdim } 199345153Sdim freebufspace = bufpages * NBPG; 200345153Sdim if (nswbuf == 0) { 201345153Sdim nswbuf = (nbuf / 2) &~ 1; /* force even */ 202345153Sdim if (nswbuf > 256) 203345153Sdim nswbuf = 256; /* sanity */ 204345153Sdim } 205345153Sdim valloc(swbuf, struct buf, nswbuf); 206345153Sdim valloc(buf, struct buf, nbuf); 207345153Sdim 208345153Sdim /* 209345153Sdim * End of first pass, size has been calculated so allocate memory 210345153Sdim */ 211345153Sdim if (firstaddr == 0) { 212345153Sdim size = (vm_size_t)(v - firstaddr); 213345153Sdim firstaddr = (int)kmem_alloc(kernel_map, round_page(size)); 214345153Sdim if (firstaddr == 0) 215345153Sdim panic("startup: no room for tables"); 216345153Sdim goto again; 217345153Sdim } 218345153Sdim /* 219345153Sdim * End of second pass, addresses have been assigned 220345153Sdim */ 221345153Sdim if ((vm_size_t)(v - firstaddr) != size) 222345153Sdim panic("startup: table size inconsistency"); 223345153Sdim /* 224345153Sdim * Allocate a submap for buffer space allocations. 225345153Sdim */ 226345153Sdim buffer_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr, 227345153Sdim bufpages*NBPG, TRUE); 228345153Sdim /* 229345153Sdim * Allocate a submap for physio 230345153Sdim */ 231345153Sdim phys_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr, 232345153Sdim VM_PHYS_SIZE, TRUE); 233345153Sdim 234345153Sdim /* 235345153Sdim * Finally, allocate mbuf pool. Since mclrefcnt is an off-size 236345153Sdim * we use the more space efficient malloc in place of kmem_alloc. 237345153Sdim */ 238345153Sdim mclrefcnt = (char *)malloc(NMBCLUSTERS+CLBYTES/MCLBYTES, 239345153Sdim M_MBUF, M_NOWAIT); 240345153Sdim bzero(mclrefcnt, NMBCLUSTERS+CLBYTES/MCLBYTES); 241345153Sdim mb_map = kmem_suballoc(kernel_map, (vm_offset_t)&mbutl, &maxaddr, 242345153Sdim VM_MBUF_SIZE, FALSE); 243345153Sdim /* 244345153Sdim * Initialize callouts 245345153Sdim */ 246345153Sdim callfree = callout; 247345153Sdim for (i = 1; i < ncallout; i++) 248345153Sdim callout[i-1].c_next = &callout[i]; 249345153Sdim 250345153Sdim /*printf("avail mem = %d\n", ptoa(vm_page_free_count));*/ 251345153Sdim 252345153Sdim /* 253345153Sdim * Set up CPU-specific registers, cache, etc. 254345153Sdim */ 255345153Sdim initcpu(); 256345153Sdim 257345153Sdim /* 258345153Sdim * Set up buffers, so they can be used to read disk labels. 259345153Sdim */ 260345153Sdim bufinit(); 261345153Sdim 262345153Sdim /* 263345153Sdim * Configure the system. 264345153Sdim */ 265345153Sdim configure(); 266345153Sdim} 267345153Sdim 268345153Sdim#ifdef PGINPROF 269345153Sdim/* 270345153Sdim * Return the difference (in microseconds) 271345153Sdim * between the current time and a previous 272345153Sdim * time as represented by the arguments. 273345153Sdim * If there is a pending clock interrupt 274345153Sdim * which has not been serviced due to high 275345153Sdim * ipl, return error code. 276345153Sdim */ 277345153Sdim/*ARGSUSED*/ 278345153Sdimvmtime(otime, olbolt, oicr) 279345153Sdim register int otime, olbolt, oicr; 280345153Sdim{ 281345153Sdim 282345153Sdim return (((time.tv_sec-otime)*60 + lbolt-olbolt)*16667); 283345153Sdim} 284345153Sdim#endif 285345153Sdim 286345153Sdimstruct sigframe { 287345153Sdim int sf_signum; 288345153Sdim int sf_code; 289345153Sdim struct sigcontext *sf_scp; 290345153Sdim sig_t sf_handler; 291345153Sdim int sf_eax; 292345153Sdim int sf_edx; 293345153Sdim int sf_ecx; 294345153Sdim struct sigcontext sf_sc; 295345153Sdim} ; 296345153Sdim 297345153Sdimextern int kstack[]; 298345153Sdim 299345153Sdim/* 300345153Sdim * Send an interrupt to process. 301345153Sdim * 302345153Sdim * Stack is set up to allow sigcode stored 303345153Sdim * in u. to call routine, followed by kcall 304345153Sdim * to sigreturn routine below. After sigreturn 305345153Sdim * resets the signal mask, the stack, and the 306345153Sdim * frame pointer, it returns to the user 307345153Sdim * specified pc, psl. 308345153Sdim */ 309345153Sdimvoid 310345153Sdimsendsig(catcher, sig, mask, code) 311345153Sdim sig_t catcher; 312345153Sdim int sig, mask; 313345153Sdim unsigned code; 314345153Sdim{ 315345153Sdim register struct proc *p = curproc; 316345153Sdim register int *regs; 317345153Sdim register struct sigframe *fp; 318345153Sdim struct sigacts *ps = p->p_sigacts; 319345153Sdim int oonstack, frmtrap; 320345153Sdim 321345153Sdim regs = p->p_regs; 322345153Sdim oonstack = ps->ps_onstack; 323345153Sdim frmtrap = curpcb->pcb_flags & FM_TRAP; 324345153Sdim /* 325345153Sdim * Allocate and validate space for the signal handler 326345153Sdim * context. Note that if the stack is in P0 space, the 327345153Sdim * call to grow() is a nop, and the useracc() check 328345153Sdim * will fail if the process has not already allocated 329345153Sdim * the space with a `brk'. 330345153Sdim */ 331345153Sdim if (!ps->ps_onstack && (ps->ps_sigonstack & sigmask(sig))) { 332345153Sdim fp = (struct sigframe *)(ps->ps_sigsp 333345153Sdim - sizeof(struct sigframe)); 334345153Sdim ps->ps_onstack = 1; 335345153Sdim } else { 336345153Sdim if (frmtrap) 337345153Sdim fp = (struct sigframe *)(regs[tESP] 338345153Sdim - sizeof(struct sigframe)); 339345153Sdim else 340345153Sdim fp = (struct sigframe *)(regs[sESP] 341345153Sdim - sizeof(struct sigframe)); 342345153Sdim } 343345153Sdim 344345153Sdim if ((unsigned)fp <= (unsigned)p->p_vmspace->vm_maxsaddr + MAXSSIZ - ctob(p->p_vmspace->vm_ssize)) 345345153Sdim (void)grow(p, (unsigned)fp); 346345153Sdim 347345153Sdim if (useracc((caddr_t)fp, sizeof (struct sigframe), B_WRITE) == 0) { 348345153Sdim /* 349345153Sdim * Process has trashed its stack; give it an illegal 350345153Sdim * instruction to halt it in its tracks. 351345153Sdim */ 352345153Sdim SIGACTION(p, SIGILL) = SIG_DFL; 353345153Sdim sig = sigmask(SIGILL); 354345153Sdim p->p_sigignore &= ~sig; 355345153Sdim p->p_sigcatch &= ~sig; 356345153Sdim p->p_sigmask &= ~sig; 357345153Sdim psignal(p, SIGILL); 358345153Sdim return; 359345153Sdim } 360345153Sdim 361345153Sdim /* 362345153Sdim * Build the argument list for the signal handler. 363345153Sdim */ 364345153Sdim fp->sf_signum = sig; 365345153Sdim fp->sf_code = code; 366345153Sdim fp->sf_scp = &fp->sf_sc; 367345153Sdim fp->sf_handler = catcher; 368345153Sdim 369345153Sdim /* save scratch registers */ 370345153Sdim if(frmtrap) { 371345153Sdim fp->sf_eax = regs[tEAX]; 372345153Sdim fp->sf_edx = regs[tEDX]; 373345153Sdim fp->sf_ecx = regs[tECX]; 374345153Sdim } else { 375345153Sdim fp->sf_eax = regs[sEAX]; 376345153Sdim fp->sf_edx = regs[sEDX]; 377345153Sdim fp->sf_ecx = regs[sECX]; 378345153Sdim } 379345153Sdim /* 380345153Sdim * Build the signal context to be used by sigreturn. 381345153Sdim */ 382345153Sdim fp->sf_sc.sc_onstack = oonstack; 383345153Sdim fp->sf_sc.sc_mask = mask; 384345153Sdim if(frmtrap) { 385345153Sdim fp->sf_sc.sc_sp = regs[tESP]; 386345153Sdim fp->sf_sc.sc_fp = regs[tEBP]; 387345153Sdim fp->sf_sc.sc_pc = regs[tEIP]; 388345153Sdim fp->sf_sc.sc_ps = regs[tEFLAGS]; 389345153Sdim regs[tESP] = (int)fp; 390345153Sdim regs[tEIP] = (int)((struct pcb *)kstack)->pcb_sigc; 391345153Sdim } else { 392345153Sdim fp->sf_sc.sc_sp = regs[sESP]; 393345153Sdim fp->sf_sc.sc_fp = regs[sEBP]; 394345153Sdim fp->sf_sc.sc_pc = regs[sEIP]; 395345153Sdim fp->sf_sc.sc_ps = regs[sEFLAGS]; 396345153Sdim regs[sESP] = (int)fp; 397345153Sdim regs[sEIP] = (int)((struct pcb *)kstack)->pcb_sigc; 398345153Sdim } 399345153Sdim} 400345153Sdim 401345153Sdim/* 402345153Sdim * System call to cleanup state after a signal 403345153Sdim * has been taken. Reset signal mask and 404345153Sdim * stack state from context left by sendsig (above). 405345153Sdim * Return to previous pc and psl as specified by 406345153Sdim * context left by sendsig. Check carefully to 407345153Sdim * make sure that the user has not modified the 408345153Sdim * psl to gain improper priviledges or to cause 409345153Sdim * a machine fault. 410345153Sdim */ 411345153Sdimsigreturn(p, uap, retval) 412345153Sdim struct proc *p; 413345153Sdim struct args { 414345153Sdim struct sigcontext *sigcntxp; 415345153Sdim } *uap; 416345153Sdim int *retval; 417345153Sdim{ 418345153Sdim register struct sigcontext *scp; 419345153Sdim register struct sigframe *fp; 420345153Sdim register int *regs = p->p_regs; 421345153Sdim 422345153Sdim 423345153Sdim /* 424345153Sdim * (XXX old comment) regs[sESP] points to the return address. 425345153Sdim * The user scp pointer is above that. 426345153Sdim * The return address is faked in the signal trampoline code 427345153Sdim * for consistency. 428345153Sdim */ 429345153Sdim scp = uap->sigcntxp; 430345153Sdim fp = (struct sigframe *) 431345153Sdim ((caddr_t)scp - offsetof(struct sigframe, sf_sc)); 432345153Sdim 433345153Sdim if (useracc((caddr_t)fp, sizeof (*fp), 0) == 0) 434345153Sdim return(EINVAL); 435345153Sdim 436345153Sdim /* restore scratch registers */ 437345153Sdim regs[sEAX] = fp->sf_eax ; 438345153Sdim regs[sEDX] = fp->sf_edx ; 439345153Sdim regs[sECX] = fp->sf_ecx ; 440345153Sdim 441345153Sdim if (useracc((caddr_t)scp, sizeof (*scp), 0) == 0) 442345153Sdim return(EINVAL); 443345153Sdim#ifdef notyet 444345153Sdim if ((scp->sc_ps & PSL_MBZ) != 0 || (scp->sc_ps & PSL_MBO) != PSL_MBO) { 445345153Sdim return(EINVAL); 446345153Sdim } 447345153Sdim#endif 448345153Sdim p->p_sigacts->ps_onstack = scp->sc_onstack & 01; 449345153Sdim p->p_sigmask = scp->sc_mask &~ 450345153Sdim (sigmask(SIGKILL)|sigmask(SIGCONT)|sigmask(SIGSTOP)); 451345153Sdim regs[sEBP] = scp->sc_fp; 452345153Sdim regs[sESP] = scp->sc_sp; 453345153Sdim regs[sEIP] = scp->sc_pc; 454345153Sdim regs[sEFLAGS] = scp->sc_ps; 455345153Sdim return(EJUSTRETURN); 456345153Sdim} 457345153Sdim 458345153Sdimint waittime = -1; 459345153Sdimstruct pcb dumppcb; 460345153Sdim 461345153Sdimboot(arghowto) 462345153Sdim int arghowto; 463345153Sdim{ 464345153Sdim register long dummy; /* r12 is reserved */ 465345153Sdim register int howto; /* r11 == how to boot */ 466345153Sdim register int devtype; /* r10 == major of root dev */ 467345153Sdim extern char *panicstr; 468345153Sdim extern int cold; 469345153Sdim int nomsg = 1; 470345153Sdim 471345153Sdim if(cold) { 472345153Sdim printf("hit reset please"); 473345153Sdim for(;;); 474345153Sdim } 475345153Sdim howto = arghowto; 476345153Sdim if ((howto&RB_NOSYNC) == 0 && waittime < 0 && bfreelist[0].b_forw) { 477345153Sdim register struct buf *bp; 478345153Sdim int iter, nbusy; 479345153Sdim 480345153Sdim waittime = 0; 481345153Sdim (void) splnet(); 482345153Sdim /* 483345153Sdim * Release inodes held by texts before update. 484345153Sdim */ 485345153Sdim if (panicstr == 0) 486345153Sdim vnode_pager_umount(NULL); 487345153Sdim sync((struct sigcontext *)0); 488345153Sdim 489345153Sdim for (iter = 0; iter < 20; iter++) { 490345153Sdim nbusy = 0; 491345153Sdim for (bp = &buf[nbuf]; --bp >= buf; ) 492345153Sdim if ((bp->b_flags & (B_BUSY|B_INVAL)) == B_BUSY) 493345153Sdim nbusy++; 494345153Sdim if (nbusy == 0) 495345153Sdim break; 496345153Sdim if (nomsg) { 497345153Sdim printf("updating disks before rebooting... "); 498345153Sdim nomsg = 0; 499345153Sdim } 500345153Sdim /* printf("%d ", nbusy); */ 501345153Sdim DELAY(40000 * iter); 502345153Sdim } 503345153Sdim if (nbusy) 504345153Sdim printf(" failed!\n"); 505345153Sdim else if (nomsg == 0) 506345153Sdim printf("succeded.\n"); 507345153Sdim DELAY(10000); /* wait for printf to finish */ 508345153Sdim } 509345153Sdim splhigh(); 510345153Sdim devtype = major(rootdev); 511345153Sdim if (howto&RB_HALT) { 512345153Sdim pg("\nThe operating system has halted. Please press any key to reboot.\n\n"); 513345153Sdim } else { 514345153Sdim if (howto & RB_DUMP) { 515345153Sdim savectx(&dumppcb, 0); 516345153Sdim dumppcb.pcb_ptd = rcr3(); 517345153Sdim dumpsys(); 518345153Sdim /*NOTREACHED*/ 519345153Sdim } 520345153Sdim } 521345153Sdim#ifdef lint 522345153Sdim dummy = 0; dummy = dummy; 523345153Sdim printf("howto %d, devtype %d\n", arghowto, devtype); 524345153Sdim#endif 525345153Sdim cpu_reset(); 526345153Sdim for(;;) ; 527345153Sdim /*NOTREACHED*/ 528345153Sdim} 529345153Sdim 530345153Sdimint dumpmag = 0x8fca0101; /* magic number for savecore */ 531345153Sdimint dumpsize = 0; /* also for savecore */ 532345153Sdim/* 533345153Sdim * Doadump comes here after turning off memory management and 534345153Sdim * getting on the dump stack, either when called above, or by 535345153Sdim * the auto-restart code. 536345153Sdim */ 537345153Sdimdumpsys() 538345153Sdim{ 539345153Sdim 540345153Sdim if (dumpdev == NODEV) 541345153Sdim return; 542345153Sdim if ((minor(dumpdev)&07) != 1) 543345153Sdim return; 544345153Sdim printf("\nThe operating system is saving a copy of RAM memory to device %x, offset %d\n\ 545345153Sdim(hit any key to abort): [ amount left to save (MB) ] ", dumpdev, dumplo); 546345153Sdim dumpsize = physmem; 547345153Sdim switch ((*bdevsw[major(dumpdev)].d_dump)(dumpdev)) { 548345153Sdim 549345153Sdim case ENXIO: 550345153Sdim printf("-- device bad\n"); 551345153Sdim break; 552345153Sdim 553345153Sdim case EFAULT: 554345153Sdim printf("-- device not ready\n"); 555345153Sdim break; 556345153Sdim 557345153Sdim case EINVAL: 558345153Sdim printf("-- area improper\n"); 559345153Sdim break; 560345153Sdim 561345153Sdim case EIO: 562345153Sdim printf("-- i/o error\n"); 563345153Sdim break; 564345153Sdim 565345153Sdim case EINTR: 566345153Sdim printf("-- aborted from console\n"); 567345153Sdim break; 568345153Sdim 569345153Sdim default: 570345153Sdim printf(" succeeded\n"); 571345153Sdim break; 572345153Sdim } 573345153Sdim printf("system rebooting.\n\n"); 574345153Sdim DELAY(10000); 575345153Sdim} 576345153Sdim 577345153Sdim#ifdef HZ 578345153Sdim/* 579345153Sdim * If HZ is defined we use this code, otherwise the code in 580345153Sdim * /sys/i386/i386/microtime.s is used. The othercode only works 581345153Sdim * for HZ=100. 582345153Sdim */ 583345153Sdimmicrotime(tvp) 584345153Sdim register struct timeval *tvp; 585345153Sdim{ 586345153Sdim int s = splhigh(); 587345153Sdim 588345153Sdim *tvp = time; 589345153Sdim tvp->tv_usec += tick; 590345153Sdim while (tvp->tv_usec > 1000000) { 591345153Sdim tvp->tv_sec++; 592345153Sdim tvp->tv_usec -= 1000000; 593345153Sdim } 594345153Sdim splx(s); 595345153Sdim} 596345153Sdim#endif /* HZ */ 597345153Sdim 598345153Sdimphysstrat(bp, strat, prio) 599345153Sdim struct buf *bp; 600345153Sdim int (*strat)(), prio; 601345153Sdim{ 602345153Sdim register int s; 603345153Sdim caddr_t baddr; 604345153Sdim 605345153Sdim /* 606345153Sdim * vmapbuf clobbers b_addr so we must remember it so that it 607345153Sdim * can be restored after vunmapbuf. This is truely rude, we 608345153Sdim * should really be storing this in a field in the buf struct 609345153Sdim * but none are available and I didn't want to add one at 610345153Sdim * this time. Note that b_addr for dirty page pushes is 611345153Sdim * restored in vunmapbuf. (ugh!) 612345153Sdim */ 613345153Sdim baddr = bp->b_un.b_addr; 614345153Sdim vmapbuf(bp); 615345153Sdim (*strat)(bp); 616345153Sdim /* pageout daemon doesn't wait for pushed pages */ 617345153Sdim if (bp->b_flags & B_DIRTY) 618345153Sdim return; 619345153Sdim s = splbio(); 620345153Sdim while ((bp->b_flags & B_DONE) == 0) 621345153Sdim sleep((caddr_t)bp, prio); 622345153Sdim splx(s); 623345153Sdim vunmapbuf(bp); 624345153Sdim bp->b_un.b_addr = baddr; 625345153Sdim} 626345153Sdim 627345153Sdiminitcpu() 628345153Sdim{ 629345153Sdim} 630345153Sdim 631345153Sdim/* 632345153Sdim * Clear registers on exec 633345153Sdim */ 634345153Sdimsetregs(p, entry) 635345153Sdim struct proc *p; 636345153Sdim u_long entry; 637345153Sdim{ 638345153Sdim 639345153Sdim p->p_regs[sEBP] = 0; /* bottom of the fp chain */ 640345153Sdim p->p_regs[sEIP] = entry; 641345153Sdim 642345153Sdim p->p_addr->u_pcb.pcb_flags = 0; /* no fp at all */ 643345153Sdim load_cr0(rcr0() | CR0_TS); /* start emulating */ 644345153Sdim#ifdef NPX 645345153Sdim npxinit(__INITIAL_NPXCW__); 646345153Sdim#endif 647345153Sdim} 648345153Sdim 649345153Sdim/* 650345153Sdim * Initialize 386 and configure to run kernel 651345153Sdim */ 652345153Sdim 653345153Sdim/* 654345153Sdim * Initialize segments & interrupt table 655345153Sdim */ 656345153Sdim 657345153Sdim 658345153Sdim#define GNULL_SEL 0 /* Null Descriptor */ 659345153Sdim#define GCODE_SEL 1 /* Kernel Code Descriptor */ 660345153Sdim#define GDATA_SEL 2 /* Kernel Data Descriptor */ 661345153Sdim#define GLDT_SEL 3 /* LDT - eventually one per process */ 662345153Sdim#define GTGATE_SEL 4 /* Process task switch gate */ 663345153Sdim#define GPANIC_SEL 5 /* Task state to consider panic from */ 664345153Sdim#define GPROC0_SEL 6 /* Task state process slot zero and up */ 665345153Sdim#define NGDT GPROC0_SEL+1 666345153Sdim 667345153Sdimunion descriptor gdt[GPROC0_SEL+1]; 668345153Sdim 669345153Sdim/* interrupt descriptor table */ 670345153Sdimstruct gate_descriptor idt[NIDT]; 671345153Sdim 672345153Sdim/* local descriptor table */ 673345153Sdimunion descriptor ldt[5]; 674345153Sdim#define LSYS5CALLS_SEL 0 /* forced by intel BCS */ 675345153Sdim#define LSYS5SIGR_SEL 1 676345153Sdim 677345153Sdim#define L43BSDCALLS_SEL 2 /* notyet */ 678345153Sdim#define LUCODE_SEL 3 679345153Sdim#define LUDATA_SEL 4 680345153Sdim/* seperate stack, es,fs,gs sels ? */ 681345153Sdim/* #define LPOSIXCALLS_SEL 5 /* notyet */ 682345153Sdim 683345153Sdimstruct i386tss tss, panic_tss; 684345153Sdim 685345153Sdimextern struct user *proc0paddr; 686345153Sdim 687345153Sdim/* software prototypes -- in more palitable form */ 688345153Sdimstruct soft_segment_descriptor gdt_segs[] = { 689345153Sdim /* Null Descriptor */ 690345153Sdim{ 0x0, /* segment base address */ 691345153Sdim 0x0, /* length - all address space */ 692345153Sdim 0, /* segment type */ 693345153Sdim 0, /* segment descriptor priority level */ 694345153Sdim 0, /* segment descriptor present */ 695345153Sdim 0,0, 696345153Sdim 0, /* default 32 vs 16 bit size */ 697345153Sdim 0 /* limit granularity (byte/page units)*/ }, 698345153Sdim /* Code Descriptor for kernel */ 699345153Sdim{ 0x0, /* segment base address */ 700345153Sdim 0xfffff, /* length - all address space */ 701345153Sdim SDT_MEMERA, /* segment type */ 702345153Sdim 0, /* segment descriptor priority level */ 703345153Sdim 1, /* segment descriptor present */ 704345153Sdim 0,0, 705345153Sdim 1, /* default 32 vs 16 bit size */ 706345153Sdim 1 /* limit granularity (byte/page units)*/ }, 707345153Sdim /* Data Descriptor for kernel */ 708345153Sdim{ 0x0, /* segment base address */ 709345153Sdim 0xfffff, /* length - all address space */ 710345153Sdim SDT_MEMRWA, /* segment type */ 711345153Sdim 0, /* segment descriptor priority level */ 712345153Sdim 1, /* segment descriptor present */ 713345153Sdim 0,0, 714345153Sdim 1, /* default 32 vs 16 bit size */ 715345153Sdim 1 /* limit granularity (byte/page units)*/ }, 716345153Sdim /* LDT Descriptor */ 717345153Sdim{ (int) ldt, /* segment base address */ 718345153Sdim sizeof(ldt)-1, /* length - all address space */ 719345153Sdim SDT_SYSLDT, /* segment type */ 720345153Sdim 0, /* segment descriptor priority level */ 721345153Sdim 1, /* segment descriptor present */ 722345153Sdim 0,0, 723345153Sdim 0, /* unused - default 32 vs 16 bit size */ 724345153Sdim 0 /* limit granularity (byte/page units)*/ }, 725345153Sdim /* Null Descriptor - Placeholder */ 726345153Sdim{ 0x0, /* segment base address */ 727345153Sdim 0x0, /* length - all address space */ 728345153Sdim 0, /* segment type */ 729345153Sdim 0, /* segment descriptor priority level */ 730345153Sdim 0, /* segment descriptor present */ 731345153Sdim 0,0, 732345153Sdim 0, /* default 32 vs 16 bit size */ 733345153Sdim 0 /* limit granularity (byte/page units)*/ }, 734345153Sdim /* Panic Tss Descriptor */ 735345153Sdim{ (int) &panic_tss, /* segment base address */ 736345153Sdim sizeof(tss)-1, /* length - all address space */ 737345153Sdim SDT_SYS386TSS, /* segment type */ 738345153Sdim 0, /* segment descriptor priority level */ 739345153Sdim 1, /* segment descriptor present */ 740345153Sdim 0,0, 741345153Sdim 0, /* unused - default 32 vs 16 bit size */ 742345153Sdim 0 /* limit granularity (byte/page units)*/ }, 743345153Sdim /* Proc 0 Tss Descriptor */ 744345153Sdim{ (int) kstack, /* segment base address */ 745345153Sdim sizeof(tss)-1, /* length - all address space */ 746345153Sdim SDT_SYS386TSS, /* segment type */ 747345153Sdim 0, /* segment descriptor priority level */ 748345153Sdim 1, /* segment descriptor present */ 749345153Sdim 0,0, 750345153Sdim 0, /* unused - default 32 vs 16 bit size */ 751345153Sdim 0 /* limit granularity (byte/page units)*/ }}; 752345153Sdim 753345153Sdimstruct soft_segment_descriptor ldt_segs[] = { 754345153Sdim /* Null Descriptor - overwritten by call gate */ 755345153Sdim{ 0x0, /* segment base address */ 756345153Sdim 0x0, /* length - all address space */ 757345153Sdim 0, /* segment type */ 758345153Sdim 0, /* segment descriptor priority level */ 759345153Sdim 0, /* segment descriptor present */ 760345153Sdim 0,0, 761345153Sdim 0, /* default 32 vs 16 bit size */ 762345153Sdim 0 /* limit granularity (byte/page units)*/ }, 763345153Sdim /* Null Descriptor - overwritten by call gate */ 764345153Sdim{ 0x0, /* segment base address */ 765345153Sdim 0x0, /* length - all address space */ 766345153Sdim 0, /* segment type */ 767345153Sdim 0, /* segment descriptor priority level */ 768345153Sdim 0, /* segment descriptor present */ 769345153Sdim 0,0, 770345153Sdim 0, /* default 32 vs 16 bit size */ 771345153Sdim 0 /* limit granularity (byte/page units)*/ }, 772345153Sdim /* Null Descriptor - overwritten by call gate */ 773345153Sdim{ 0x0, /* segment base address */ 774345153Sdim 0x0, /* length - all address space */ 775345153Sdim 0, /* segment type */ 776345153Sdim 0, /* segment descriptor priority level */ 777345153Sdim 0, /* segment descriptor present */ 778345153Sdim 0,0, 779345153Sdim 0, /* default 32 vs 16 bit size */ 780345153Sdim 0 /* limit granularity (byte/page units)*/ }, 781345153Sdim /* Code Descriptor for user */ 782345153Sdim{ 0x0, /* segment base address */ 783345153Sdim 0xfffff, /* length - all address space */ 784345153Sdim SDT_MEMERA, /* segment type */ 785345153Sdim SEL_UPL, /* segment descriptor priority level */ 786345153Sdim 1, /* segment descriptor present */ 787345153Sdim 0,0, 788345153Sdim 1, /* default 32 vs 16 bit size */ 789345153Sdim 1 /* limit granularity (byte/page units)*/ }, 790345153Sdim /* Data Descriptor for user */ 791345153Sdim{ 0x0, /* segment base address */ 792345153Sdim 0xfffff, /* length - all address space */ 793345153Sdim SDT_MEMRWA, /* segment type */ 794345153Sdim SEL_UPL, /* segment descriptor priority level */ 795345153Sdim 1, /* segment descriptor present */ 796345153Sdim 0,0, 797345153Sdim 1, /* default 32 vs 16 bit size */ 798345153Sdim 1 /* limit granularity (byte/page units)*/ } }; 799345153Sdim 800345153Sdimsetidt(idx, func, typ, dpl) char *func; { 801345153Sdim struct gate_descriptor *ip = idt + idx; 802345153Sdim 803345153Sdim ip->gd_looffset = (int)func; 804345153Sdim ip->gd_selector = 8; 805345153Sdim ip->gd_stkcpy = 0; 806345153Sdim ip->gd_xx = 0; 807345153Sdim ip->gd_type = typ; 808345153Sdim ip->gd_dpl = dpl; 809345153Sdim ip->gd_p = 1; 810345153Sdim ip->gd_hioffset = ((int)func)>>16 ; 811345153Sdim} 812345153Sdim 813345153Sdim#define IDTVEC(name) __CONCAT(X, name) 814345153Sdimextern IDTVEC(div), IDTVEC(dbg), IDTVEC(nmi), IDTVEC(bpt), IDTVEC(ofl), 815345153Sdim IDTVEC(bnd), IDTVEC(ill), IDTVEC(dna), IDTVEC(dble), IDTVEC(fpusegm), 816345153Sdim IDTVEC(tss), IDTVEC(missing), IDTVEC(stk), IDTVEC(prot), 817345153Sdim IDTVEC(page), IDTVEC(rsvd), IDTVEC(fpu), IDTVEC(rsvd0), 818345153Sdim IDTVEC(rsvd1), IDTVEC(rsvd2), IDTVEC(rsvd3), IDTVEC(rsvd4), 819345153Sdim IDTVEC(rsvd5), IDTVEC(rsvd6), IDTVEC(rsvd7), IDTVEC(rsvd8), 820345153Sdim IDTVEC(rsvd9), IDTVEC(rsvd10), IDTVEC(rsvd11), IDTVEC(rsvd12), 821345153Sdim IDTVEC(rsvd13), IDTVEC(rsvd14), IDTVEC(rsvd14), IDTVEC(syscall); 822345153Sdim 823345153Sdimint lcr0(), lcr3(), rcr0(), rcr2(); 824345153Sdimint _udatasel, _ucodesel, _gsel_tss; 825345153Sdim 826345153Sdiminit386(first) 827345153Sdim{ 828345153Sdim extern ssdtosd(), lgdt(), lidt(), lldt(), etext; 829345153Sdim int x, *pi; 830345153Sdim unsigned biosbasemem, biosextmem; 831345153Sdim struct gate_descriptor *gdp; 832345153Sdim extern int sigcode,szsigcode; 833345153Sdim /* table descriptors - used to load tables by microp */ 834345153Sdim struct region_descriptor r_gdt, r_idt; 835345153Sdim int pagesinbase, pagesinext; 836345153Sdim 837345153Sdim 838345153Sdim proc0.p_addr = proc0paddr; 839345153Sdim 840345153Sdim /* 841345153Sdim * Initialize the console before we print anything out. 842345153Sdim */ 843345153Sdim 844345153Sdim cninit (KERNBASE+0xa0000); 845345153Sdim 846345153Sdim /* make gdt memory segments */ 847345153Sdim gdt_segs[GCODE_SEL].ssd_limit = btoc((int) &etext + NBPG); 848345153Sdim for (x=0; x < NGDT; x++) ssdtosd(gdt_segs+x, gdt+x); 849345153Sdim /* make ldt memory segments */ 850345153Sdim ldt_segs[LUCODE_SEL].ssd_limit = btoc(UPT_MIN_ADDRESS); 851345153Sdim ldt_segs[LUDATA_SEL].ssd_limit = btoc(UPT_MIN_ADDRESS); 852345153Sdim /* Note. eventually want private ldts per process */ 853345153Sdim for (x=0; x < 5; x++) ssdtosd(ldt_segs+x, ldt+x); 854345153Sdim 855345153Sdim /* exceptions */ 856345153Sdim setidt(0, &IDTVEC(div), SDT_SYS386TGT, SEL_KPL); 857345153Sdim setidt(1, &IDTVEC(dbg), SDT_SYS386TGT, SEL_KPL); 858345153Sdim setidt(2, &IDTVEC(nmi), SDT_SYS386TGT, SEL_KPL); 859345153Sdim setidt(3, &IDTVEC(bpt), SDT_SYS386TGT, SEL_UPL); 860345153Sdim setidt(4, &IDTVEC(ofl), SDT_SYS386TGT, SEL_KPL); 861345153Sdim setidt(5, &IDTVEC(bnd), SDT_SYS386TGT, SEL_KPL); 862345153Sdim setidt(6, &IDTVEC(ill), SDT_SYS386TGT, SEL_KPL); 863345153Sdim setidt(7, &IDTVEC(dna), SDT_SYS386TGT, SEL_KPL); 864345153Sdim setidt(8, &IDTVEC(dble), SDT_SYS386TGT, SEL_KPL); 865345153Sdim setidt(9, &IDTVEC(fpusegm), SDT_SYS386TGT, SEL_KPL); 866345153Sdim setidt(10, &IDTVEC(tss), SDT_SYS386TGT, SEL_KPL); 867345153Sdim setidt(11, &IDTVEC(missing), SDT_SYS386TGT, SEL_KPL); 868345153Sdim setidt(12, &IDTVEC(stk), SDT_SYS386TGT, SEL_KPL); 869345153Sdim setidt(13, &IDTVEC(prot), SDT_SYS386TGT, SEL_KPL); 870345153Sdim setidt(14, &IDTVEC(page), SDT_SYS386TGT, SEL_KPL); 871345153Sdim setidt(15, &IDTVEC(rsvd), SDT_SYS386TGT, SEL_KPL); 872345153Sdim setidt(16, &IDTVEC(fpu), SDT_SYS386TGT, SEL_KPL); 873345153Sdim setidt(17, &IDTVEC(rsvd0), SDT_SYS386TGT, SEL_KPL); 874345153Sdim setidt(18, &IDTVEC(rsvd1), SDT_SYS386TGT, SEL_KPL); 875345153Sdim setidt(19, &IDTVEC(rsvd2), SDT_SYS386TGT, SEL_KPL); 876345153Sdim setidt(20, &IDTVEC(rsvd3), SDT_SYS386TGT, SEL_KPL); 877345153Sdim setidt(21, &IDTVEC(rsvd4), SDT_SYS386TGT, SEL_KPL); 878345153Sdim setidt(22, &IDTVEC(rsvd5), SDT_SYS386TGT, SEL_KPL); 879345153Sdim setidt(23, &IDTVEC(rsvd6), SDT_SYS386TGT, SEL_KPL); 880345153Sdim setidt(24, &IDTVEC(rsvd7), SDT_SYS386TGT, SEL_KPL); 881345153Sdim setidt(25, &IDTVEC(rsvd8), SDT_SYS386TGT, SEL_KPL); 882345153Sdim setidt(26, &IDTVEC(rsvd9), SDT_SYS386TGT, SEL_KPL); 883345153Sdim setidt(27, &IDTVEC(rsvd10), SDT_SYS386TGT, SEL_KPL); 884345153Sdim setidt(28, &IDTVEC(rsvd11), SDT_SYS386TGT, SEL_KPL); 885345153Sdim setidt(29, &IDTVEC(rsvd12), SDT_SYS386TGT, SEL_KPL); 886345153Sdim setidt(30, &IDTVEC(rsvd13), SDT_SYS386TGT, SEL_KPL); 887345153Sdim setidt(31, &IDTVEC(rsvd14), SDT_SYS386TGT, SEL_KPL); 888345153Sdim 889345153Sdim#include "isa.h" 890345153Sdim#if NISA >0 891345153Sdim isa_defaultirq(); 892345153Sdim#endif 893345153Sdim 894345153Sdim r_gdt.rd_limit = sizeof(gdt)-1; 895345153Sdim r_gdt.rd_base = (int) gdt; 896345153Sdim lgdt(&r_gdt); 897345153Sdim r_idt.rd_limit = sizeof(idt)-1; 898345153Sdim r_idt.rd_base = (int) idt; 899345153Sdim lidt(&r_idt); 900345153Sdim lldt(GSEL(GLDT_SEL, SEL_KPL)); 901345153Sdim 902345153Sdim#include "ddb.h" 903345153Sdim#if NDDB > 0 904345153Sdim kdb_init(); 905345153Sdim if (boothowto & RB_KDB) 906345153Sdim Debugger(); 907345153Sdim#endif 908345153Sdim 909345153Sdim /* Use BIOS values stored in RTC CMOS RAM, since probing 910345153Sdim * breaks certain 386 AT relics. 911345153Sdim */ 912345153Sdim biosbasemem = rtcin(RTC_BASELO)+ (rtcin(RTC_BASEHI)<<8); 913345153Sdim biosextmem = rtcin(RTC_EXTLO)+ (rtcin(RTC_EXTHI)<<8); 914345153Sdim/*printf("bios base %d ext %d ", biosbasemem, biosextmem);*/ 915345153Sdim 916345153Sdim /* 917345153Sdim * 15 Aug 92 Terry Lambert The real fix for the CMOS bug 918345153Sdim */ 919345153Sdim if( biosbasemem != EXPECT_BASEMEM) { 920345153Sdim printf( "Warning: Base memory %dK, assuming %dK\n", biosbasemem, EXPECT_BASEMEM); 921345153Sdim biosbasemem = EXPECT_BASEMEM; /* assume base*/ 922345153Sdim } 923345153Sdim 924345153Sdim if( biosextmem > 65536) { 925345153Sdim printf( "Warning: Extended memory %dK(>64M), assuming 0K\n", biosextmem); 926345153Sdim biosextmem = 0; /* assume none*/ 927345153Sdim } 928345153Sdim 929345153Sdim /* 930345153Sdim * Go into normal calculation; Note that we try to run in 640K, and 931345153Sdim * that invalid CMOS values of non 0xffff are no longer a cause of 932345153Sdim * ptdi problems. I have found a gutted kernel can run in 640K. 933345153Sdim */ 934345153Sdim pagesinbase = 640/4 - first/NBPG; 935345153Sdim pagesinext = biosextmem/4; 936345153Sdim /* use greater of either base or extended memory. do this 937345153Sdim * until I reinstitue discontiguous allocation of vm_page 938345153Sdim * array. 939345153Sdim */ 940345153Sdim if (pagesinbase > pagesinext) 941345153Sdim Maxmem = 640/4; 942345153Sdim else { 943345153Sdim Maxmem = pagesinext + 0x100000/NBPG; 944345153Sdim first = 0x100000; /* skip hole */ 945345153Sdim } 946345153Sdim 947345153Sdim /* This used to explode, since Maxmem used to be 0 for bas CMOS*/ 948345153Sdim maxmem = Maxmem - 1; /* highest page of usable memory */ 949345153Sdim physmem = maxmem; /* number of pages of physmem addr space */ 950345153Sdim/*printf("using first 0x%x to 0x%x\n ", first, maxmem*NBPG);*/ 951345153Sdim if (maxmem < 2048/4) { 952345153Sdim printf("Too little RAM memory. Warning, running in degraded mode.\n"); 953345153Sdim#ifdef INFORM_WAIT 954345153Sdim /* 955345153Sdim * People with less than 2 Meg have to hit return; this way 956345153Sdim * we see the messages and can tell them why they blow up later. 957345153Sdim * If they get working well enough to recompile, they can unset 958345153Sdim * the flag; otherwise, it's a toy and they have to lump it. 959345153Sdim */ 960345153Sdim getchar(); /* kernel getchar in /sys/i386/isa/pccons.c*/ 961345153Sdim#endif /* !INFORM_WAIT*/ 962345153Sdim } 963345153Sdim /* 964345153Sdim * End of CMOS bux fix 965345153Sdim */ 966345153Sdim 967345153Sdim /* call pmap initialization to make new kernel address space */ 968345153Sdim pmap_bootstrap (first, 0); 969345153Sdim /* now running on new page tables, configured,and u/iom is accessible */ 970345153Sdim 971345153Sdim /* make a initial tss so microp can get interrupt stack on syscall! */ 972345153Sdim proc0.p_addr->u_pcb.pcb_tss.tss_esp0 = (int) kstack + UPAGES*NBPG; 973345153Sdim proc0.p_addr->u_pcb.pcb_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL) ; 974345153Sdim _gsel_tss = GSEL(GPROC0_SEL, SEL_KPL); 975345153Sdim ltr(_gsel_tss); 976345153Sdim 977345153Sdim /* make a call gate to reenter kernel with */ 978345153Sdim gdp = &ldt[LSYS5CALLS_SEL].gd; 979345153Sdim 980345153Sdim x = (int) &IDTVEC(syscall); 981345153Sdim gdp->gd_looffset = x++; 982345153Sdim gdp->gd_selector = GSEL(GCODE_SEL,SEL_KPL); 983345153Sdim gdp->gd_stkcpy = 0; 984345153Sdim gdp->gd_type = SDT_SYS386CGT; 985345153Sdim gdp->gd_dpl = SEL_UPL; 986345153Sdim gdp->gd_p = 1; 987345153Sdim gdp->gd_hioffset = ((int) &IDTVEC(syscall)) >>16; 988345153Sdim 989345153Sdim /* transfer to user mode */ 990345153Sdim 991345153Sdim _ucodesel = LSEL(LUCODE_SEL, SEL_UPL); 992345153Sdim _udatasel = LSEL(LUDATA_SEL, SEL_UPL); 993345153Sdim 994345153Sdim /* setup proc 0's pcb */ 995345153Sdim bcopy(&sigcode, proc0.p_addr->u_pcb.pcb_sigc, szsigcode); 996345153Sdim proc0.p_addr->u_pcb.pcb_flags = 0; 997345153Sdim proc0.p_addr->u_pcb.pcb_ptd = IdlePTD; 998345153Sdim} 999345153Sdim 1000345153Sdimextern struct pte *CMAP1, *CMAP2; 1001345153Sdimextern caddr_t CADDR1, CADDR2; 1002345153Sdim/* 1003 * zero out physical memory 1004 * specified in relocation units (NBPG bytes) 1005 */ 1006clearseg(n) { 1007 1008 *(int *)CMAP2 = PG_V | PG_KW | ctob(n); 1009 load_cr3(rcr3()); 1010 bzero(CADDR2,NBPG); 1011 *(int *) CADDR2 = 0; 1012} 1013 1014/* 1015 * copy a page of physical memory 1016 * specified in relocation units (NBPG bytes) 1017 */ 1018copyseg(frm, n) { 1019 1020 *(int *)CMAP2 = PG_V | PG_KW | ctob(n); 1021 load_cr3(rcr3()); 1022 bcopy((void *)frm, (void *)CADDR2, NBPG); 1023} 1024 1025/* 1026 * copy a page of physical memory 1027 * specified in relocation units (NBPG bytes) 1028 */ 1029physcopyseg(frm, to) { 1030 1031 *(int *)CMAP1 = PG_V | PG_KW | ctob(frm); 1032 *(int *)CMAP2 = PG_V | PG_KW | ctob(to); 1033 load_cr3(rcr3()); 1034 bcopy(CADDR1, CADDR2, NBPG); 1035} 1036 1037/*aston() { 1038 schednetisr(NETISR_AST); 1039}*/ 1040 1041setsoftclock() { 1042 schednetisr(NETISR_SCLK); 1043} 1044 1045/* 1046 * insert an element into a queue 1047 */ 1048#undef insque 1049_insque(element, head) 1050 register struct prochd *element, *head; 1051{ 1052 element->ph_link = head->ph_link; 1053 head->ph_link = (struct proc *)element; 1054 element->ph_rlink = (struct proc *)head; 1055 ((struct prochd *)(element->ph_link))->ph_rlink=(struct proc *)element; 1056} 1057 1058/* 1059 * remove an element from a queue 1060 */ 1061#undef remque 1062_remque(element) 1063 register struct prochd *element; 1064{ 1065 ((struct prochd *)(element->ph_link))->ph_rlink = element->ph_rlink; 1066 ((struct prochd *)(element->ph_rlink))->ph_link = element->ph_link; 1067 element->ph_rlink = (struct proc *)0; 1068} 1069 1070vmunaccess() {} 1071 1072/* 1073 * Below written in C to allow access to debugging code 1074 */ 1075copyinstr(fromaddr, toaddr, maxlength, lencopied) u_int *lencopied, maxlength; 1076 void *toaddr, *fromaddr; { 1077 int c,tally; 1078 1079 tally = 0; 1080 while (maxlength--) { 1081 c = fubyte(fromaddr++); 1082 if (c == -1) { 1083 if(lencopied) *lencopied = tally; 1084 return(EFAULT); 1085 } 1086 tally++; 1087 *(char *)toaddr++ = (char) c; 1088 if (c == 0){ 1089 if(lencopied) *lencopied = (u_int)tally; 1090 return(0); 1091 } 1092 } 1093 if(lencopied) *lencopied = (u_int)tally; 1094 return(ENAMETOOLONG); 1095} 1096 1097copyoutstr(fromaddr, toaddr, maxlength, lencopied) u_int *lencopied, maxlength; 1098 void *fromaddr, *toaddr; { 1099 int c; 1100 int tally; 1101 1102 tally = 0; 1103 while (maxlength--) { 1104 c = subyte(toaddr++, *(char *)fromaddr); 1105 if (c == -1) return(EFAULT); 1106 tally++; 1107 if (*(char *)fromaddr++ == 0){ 1108 if(lencopied) *lencopied = tally; 1109 return(0); 1110 } 1111 } 1112 if(lencopied) *lencopied = tally; 1113 return(ENAMETOOLONG); 1114} 1115 1116copystr(fromaddr, toaddr, maxlength, lencopied) u_int *lencopied, maxlength; 1117 void *fromaddr, *toaddr; { 1118 u_int tally; 1119 1120 tally = 0; 1121 while (maxlength--) { 1122 *(u_char *)toaddr = *(u_char *)fromaddr++; 1123 tally++; 1124 if (*(u_char *)toaddr++ == 0) { 1125 if(lencopied) *lencopied = tally; 1126 return(0); 1127 } 1128 } 1129 if(lencopied) *lencopied = tally; 1130 return(ENAMETOOLONG); 1131} 1132