📄 machdep.c
字号:
*/ if (cpu == VAX_60) fccons_init();#endif MVAX || VAX3600 || VAX420 || VAX60 /* * Allocate space for system data structures. * The first available real memory address is in "firstaddr". * As pages of memory are allocated, "firstaddr" is incremented. * The first available kernel virtual address is in "v". * As pages of kernel virtual memory are allocated, "v" is incremented. * An index into the kernel page table corresponding to the * virtual memory address maintained in "v" is kept in "mapaddr". */ mapaddr = firstaddr; v = (caddr_t) (0x80000000 | (firstaddr * NBPG));#define valloc(name, type, num) \ (name) = (type *)(v); (v) = (caddr_t)((name)+(num))#define valloclim(name, type, num, lim) \ (name) = (type *)(v); (v) = (caddr_t)((lim) = ((name)+(num))) valloclim (gnode, struct gnode , ngnode, gnodeNGNODE); valloclim (file, struct file , nfile, fileNFILE); valloclim (proc, struct proc , nproc, procNPROC); valloclim (text, struct text , ntext, textNTEXT); valloc (cfree, struct cblock , nclist); valloc (callout, struct callout, ncallout); valloc (chrout, struct chrout, nchrout); valloc (swapmap, struct map, nswapmap = nproc * 2); valloc (kernelmap, struct map , nproc+32); valloc (nch, struct nch, nchsize); valloc (flox, struct filock, flckinfo.recs ); valloc (flinotab, struct flino, flckinfo.fils ); valloc (kmemmap, struct map, (ekmempt - kmempt) - km_wmapsize); valloc (kmemwmap, struct map, km_wmapsize); valloc (kmemusage, struct kmemusage, (ekmempt - kmempt) / CLSIZE); /* allocate space for gateway screen freelist */ valloc(screen_storage, char, screen_space_needed());#ifdef QUOTA valloclim (quota, struct quota , nquota, quotaNQUOTA); valloclim (dquot, struct dquot , ndquot, dquotNDQUOT);#endif QUOTA /* * Determine how many buffers to allocate, unless this has * already been patched into the kernel. * * Use bufcache% (a config'able option) of memory. * If bufpgs > (physmem - min mem reserved for system) * then set bufpgs to (physmem - min mem reserved for system). * Ensure that bufpages is at least 10% of memory. * * We allocate 1/2 as many swap buffer headers (nswbuf) * as file i/o buffers (nbuf), but never more than 256. */ if (bufpages == 0) { /* * requestpages, maxbufpages, tenpercent are measured * in NBPG byte units. * * requestpages is what was requested in the config file. * maxbufpages is the upper limit of what is allowed. * tenpercent is the lower limit of what is allowed. * * As silly as this sounds, the upper limit can be lower * than the lower limit (even negative on minimum * configuration machines), so make sure that the upper * limit is >= tenpercent * * Since we only have MINMEM_PGS to guide us, and * since this number is only meaningful for kernels * with relatively small system table sizes, scale * up the estimate of the demands that these tables * make on memory as a function of maxusers when * computing the upper limit. * Allow for the buffer headers as well. * */ requestpages = (physmem * ((float)bufcache/100)); maxbufpages = physmem - MINMEM_PGS - (maxusers/32) * 1024 /* .5 MB per 32 users */ - (sysptsize * sizeof(struct pte)) / NBPG - 1; /* * kperbuf is set to 4 for * uniprocessors, and 8 (no moving of physical * memory under a virtual address) for multi-processors. * Sanity test kperbuf on multiprocessors to * guarantee that buffer memory is not moved around. */ if (!kperbuf) /* hasn't been manually patched */ kperbuf = ((smp) ? 8 : 4); if (smp && kperbuf != 8) panic("buffer header allocation failure"); maxbufs = maxbufpages / CLSIZE / kperbuf; maxbufpages -= (maxbufs * sizeof(struct buf)) / NBPG; tenpercent = physmem / 10; if (maxbufpages < tenpercent) maxbufpages = tenpercent;if (bufdebug) {printf("startup: physmem %d bufcache %d requestpages %d\n", physmem, bufcache, requestpages);printf("startup: kperbuf %d maxbufs %d maxbufpages %d tenpercent %d\n", kperbuf, maxbufs, maxbufpages, tenpercent);} if (requestpages > maxbufpages) {if (bufdebug) {printf("startup: bufcache request of %d bytes reduced to %d bytes\n", requestpages*NBPG, maxbufpages*NBPG);} requestpages = maxbufpages; } /* bufpages is measured in page cluster units */ bufpages = requestpages / CLSIZE; } if (nbuf == 0) { /* nbuf is # of kperbuf-K objects that can fit in bufpages */ nbuf = bufpages / kperbuf; } if (nswbuf == 0) { nswbuf = (nbuf / 2) &~ 1; /* force even */ if (nswbuf > 256) nswbuf = 256; /* sanity */ }if (bufdebug) {printf("startup: bufpages %d nbuf %d nswbuf %d\n", bufpages, nbuf, nswbuf);printf("startup: valloc swbuf v = 0x%x nswbuf %d\n", v, nswbuf);} valloc(swbuf, struct buf, nswbuf); /* * Now the amount of virtual memory remaining for buffers * can be calculated, estimating needs for the cmap. */ ncmap = (maxmem*NBPG - ((int)v &~ 0x80000000)) / (CLBYTES + sizeof(struct cmap)) + 2;if (bufdebug) {printf("startup: maxmem %d NBPG %d v 0x%x CLBYTES %d sizeof(cmap) %d\n", maxmem, NBPG, v, CLBYTES, sizeof(struct cmap));printf("startup: ncmap %d = (%d / %d) + 2\n", ncmap, (maxmem*NBPG - ((int)v &~ 0x80000000)), (CLBYTES + sizeof(struct cmap)) );} maxbufs = ((sysptsize * NBPG) - ((int)(v + ncmap * sizeof(struct cmap)) - 0x80000000)) / (MAXBSIZE + sizeof(struct buf));if (bufdebug) {printf("startup: sysptsize %d ncmap %d sizeof(cmap) %d\n", sysptsize, ncmap, sizeof(struct cmap));printf("startup: ((0x%x + 0x%x) - 0x80000000) / 0x%x\n", v, ncmap*sizeof(struct cmap), sizeof(struct buf));printf("startup: maxbufs %d\n", maxbufs);} /* * If the system page table is too small for the available * physical memory (not enough room for nbufs after the core map) * then the size of physical memory (physmem) is artifically * reduced to MINMEM_PGS (the minimun amount supported). * This should allow booting generic kernels on systems with * large physical memory. */ if (maxbufs < 16) { /* * Let's not print this anymore. It scares the user and they * complain about it alot. They will be told in a less * frightful way later, where 'real mem' is displayed. */if (bufdebug) {printf("startup: system page table too small, reducing physmem to %d meg\n",MINMEM_MB);} if (++tries > 1) panic ("sys pt too small"); physmem=MINMEM_PGS; /* # of 512 byte pages = MINMEM_MB */ maxusers=(maxusers > 8) ? 8 : maxusers; nbuf=bufpages=nswbuf=0; goto tryagain; } reducenbufs = 0; if (nbuf > maxbufs) {if (bufdebug) {printf("startup: sysptsize limits number of buffers to %d\n", maxbufs);} nbuf = maxbufs; reducenbufs = 1; } if (bufpages > nbuf * (MAXBSIZE / CLBYTES)) { bufpages = nbuf * (MAXBSIZE / CLBYTES);if (bufdebug) {printf("startup: bufpages > than needed, reduced to %d\n", bufpages);} }if (bufdebug) {printf("startup: valloc buf, nbuf %d(%d) bufpages %d v 0x%x\n", nbuf, sizeof(struct buf), bufpages, v);} valloc(buf, struct buf, nbuf); /* * Allocate space for core map. * Allow space for all of phsical memory minus the amount * dedicated to the system. The amount of physical memory * dedicated to the system is the total virtual memory of * the system thus far, plus core map, buffer pages, * and buffer headers not yet allocated. * Add 2: 1 because the 0th entry is unused, 1 for rounding. */ ncmap = (maxmem*NBPG - ((int)(v + bufpages*CLBYTES) &~ 0x80000000)) / (CLBYTES + sizeof(struct cmap)) + 2;if (bufdebug) {printf("startup: maxmem %d bufpages %d v 0x%x\n", maxmem, bufpages, v);printf("startup: ncmap %d = (%d / %d) + 2\n", ncmap, (maxmem*NBPG - ((int)(v + bufpages*CLBYTES) &~ 0x80000000)), (CLBYTES + sizeof(struct cmap)) );} if (ncmap <= 0) { if (++tries > 1) panic ("no memory (A)"); printf("not enough memory after allocating buffer cache!\n"); if (bufcache > 10) { bufcache = max(bufcache / 2, 10); printf("bufcache reduced to %d percent\n", bufcache); } else { maxusers = max(maxusers / 2, 2); printf("maxusers reduced to %d\n", maxusers); } printf("consider re-sizing kernel configuration parameters\n"); nbuf=bufpages=nswbuf=0; goto tryagain; } valloclim(cmap, struct cmap, ncmap, ecmap); /* * Clear space allocated thus far, and make r/w entries * for the space in the kernel map. */ unixsize = btoc((int)v &~ 0x80000000); while (firstaddr < unixsize) { *(int *)(&Sysmap[firstaddr]) = PG_V | PG_KW | firstaddr; bzero(0x80000000 | (ctob(firstaddr)),NBPG); firstaddr++; } /* Save PFN of last kernel page to dump for crashdump code */ lastkpage = firstaddr; /* * Now allocate buffers proper. They are different than the above * in that they usually occupy more virtual memory than physical. * Set endofmem to the last used kernel virtual address. */ v = (caddr_t) ((int)(v + PGOFSET) &~ PGOFSET);if (bufdebug) {printf("startup: valloc buffers, nbuf %d MAXBSIZE %d v 0x%x\n", nbuf, MAXBSIZE, v);} valloc(buffers, char, MAXBSIZE * nbuf); endofmem = v;if (bufdebug) {printf("startup: endofmem = 0x%x\n", endofmem);} base = bufpages / nbuf; /* clusters of memory per buffer header */ residual = bufpages % nbuf;if (bufdebug) {printf("startup: base (K/buf) = %d, residual = %d\n", base, residual);} mapaddr = firstaddr; for (i = 0; i < residual; i++) { for (j = 0; j < (base + 1) * CLSIZE; j++) { *(int *)(&Sysmap[mapaddr+j]) = PG_V | PG_KW | firstaddr; bzero(0x80000000 | (ctob(mapaddr)),NBPG); firstaddr++; } mapaddr += MAXBSIZE / NBPG; } for (i = residual; i < nbuf; i++) { for (j = 0; j < base * CLSIZE; j++) { *(int *)(&Sysmap[mapaddr+j]) = PG_V | PG_KW | firstaddr; bzero(0x80000000 | (ctob(mapaddr)),NBPG); firstaddr++; } mapaddr += MAXBSIZE / NBPG; }if (bufdebug) {printf("startup: end(kernel real mem) %d, end(kernel virtual mem) %d\n", firstaddr*NBPG, ((int)endofmem & ~ 0x80000000));printf("startup: sys virt pgs %d, sys real pgs %d\n", ((int)(v + 1) & ~0x80000000) / NBPG, firstaddr*NBPG);printf("startup: # of sys ptes %d, # of sys ptes used %d\n", sysptsize, mapaddr);} if (firstaddr >= physmem - MINMEM_FREE) panic ("no memory (B)"); mtpr (TBIA, 0); /* * Initialize callouts */ callfree = callout; for (i = 1; i < ncallout; i++) callout[i - 1].c_next = &callout[i]; /* * Initialize interrupt queue */ chrfree = chrcur = &chrout[0]; for (i = 1; i < nchrout; i++) chrout[i - 1].c_next = &chrout[i]; chrout[nchrout - 1].c_next = &chrout[0]; /* circular llist */ /* * Initialize gateway screen freelist */ screen_init_freelist(screen_storage); /* * Initialize memory allocator and swap * and user page table maps. * * THE USER PAGE TABLE MAP IS CALLED ``kernelmap'' * WHICH IS A VERY UNDESCRIPTIVE AND INCONSISTENT NAME. */ meminit (firstaddr, maxmem); maxmem = freemem; kmeminit(); rminit (kernelmap, (long)usrptsize, (long) 1, "usrpt", nproc+32); /* * Log startup printfs */ appendflg = 1; /* tell error logger we're starting up */ printf (version); printf ("real mem = %d\n", ctob (Physmem)); if (tries && Physmem != physmem) { /* we've reconfigured because of a small SPT */ printf("Memory configuration adjusted to run with small system page table\n"); printf ("real mem = %d\n", ctob (physmem)); } printf ("avail mem = %d\n", ctob (maxmem)); if (reducenbufs) { /* # of buffer headers was limited by sysptsize */ printf("Buffer configuration adjusted to run with small system page table\n"); } printf ("using %d buffers containing %d bytes of memory\n", nbuf, bufpages * CLBYTES); /* allocate 1 pte for each proc structure to be used to double map the PCB in the u_area */ nxv = (char *)get_sys_ptes(nproc, &pte); /* put virtual address for double map in the proc structure */ for(i=0;i<nproc; i++) { proc[i].p_pcb =(struct pcb *)((int) nxv + (i*512)); } /* * Clear restart inhibit flags. */ switch(cpu) {#ifdef VAX9000 case VAX_9000: ka9000_clear_coldstart(); ka9000_clear_warmstart(); break;#endif VAX9000#ifdef VAX8800 case VAX_8800: case VAX_8820: cons_putc (N_COMM|N_CLR_COLD); cons_putc (N_COMM|N_CLR_WARM); break;#endif VAX8800 default: cons_putc (TXDB_CWSI); cons_putc (TXDB_CCSI); break; }}/* * Enable Cache * * The actual routines are entered through cpusw, and are located * in the appropiate cpu dependent routine kaXXX.c */cachenbl(){ if ((*cpup->cachenbl)() < 0 ) panic("No cachenbl routine configured\n");}#ifdef PGINPROF/* * Return the difference (in microseconds) * between the current time and a previous * time as represented by the arguments. * If there is a pending clock interrupt * which has not been serviced due to high * ipl, return error code. */vmtime (otime, olbolt, oicr)register int otime, olbolt, oicr;{ if (mfpr (ICCS) & ICCS_INT) return (-1); else return (((time.tv_sec - otime) * 60 + lbolt - olbolt) * 16667 + mfpr (ICR) - oicr);}#endif/* * Send an interrupt to process. * * Stack is set up to allow sigcode stored * in u. to call routine, followed by chmk * to sigcleanup routine below. After sigcleanup * resets the signal mask and the stack, it * returns to user who then unwinds with the * rei at the bottom of sigcode. */sendsig (p, sig, mask)int (*p) (), sig, mask;{ register struct sigcontext *scp; /* know to be r11 */ register int *regs; register struct sigframe {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -