📄 machdep.c
字号:
* Be careful to save and restore the original contents for msgbuf. */ physmem = btoc(v - KERNBASE); cp = (char *)MACH_PHYS_TO_UNCACHED(physmem << PGSHIFT); while (cp < (char *)MACH_MAX_MEM_ADDR) { if (badaddr(cp, 4)) break; i = *(int *)cp; *(int *)cp = 0xa5a5a5a5; /* * Data will persist on the bus if we read it right away. * Have to be tricky here. */ ((int *)cp)[4] = 0x5a5a5a5a; MachEmptyWriteBuffer(); if (*(int *)cp != 0xa5a5a5a5) break; *(int *)cp = i; cp += NBPG; physmem++; } maxmem = physmem;#if NLE > 0 /* * Grab 128K at the top of physical memory for the lance chip * on machines where it does dma through the I/O ASIC. * It must be physically contiguous and aligned on a 128K boundary. */ if (pmax_boardtype == DS_3MIN || pmax_boardtype == DS_MAXINE || pmax_boardtype == DS_3MAXPLUS) { maxmem -= btoc(128 * 1024); le_iomem = (maxmem << PGSHIFT); }#endif /* NLE */#if NASC > 0 /* * Ditto for the scsi chip. There is probably a way to make asc.c * do dma without these buffers, but it would require major * re-engineering of the asc driver. * They must be 8K in size and page aligned. */ if (pmax_boardtype == DS_3MIN || pmax_boardtype == DS_MAXINE || pmax_boardtype == DS_3MAXPLUS) { maxmem -= btoc(ASC_NCMD * 8192); asc_iomem = (maxmem << PGSHIFT); }#endif /* NASC */ /* * Initialize error message buffer (at end of core). */ maxmem -= btoc(sizeof (struct msgbuf)); msgbufp = (struct msgbuf *)(MACH_PHYS_TO_CACHED(maxmem << PGSHIFT)); msgbufmapped = 1; /* * Allocate space for system data structures. * The first available kernel virtual address is in "v". * As pages of kernel virtual memory are allocated, "v" is incremented. * * These data structures are allocated here instead of cpu_startup() * because physical memory is directly addressable. We don't have * to map these into virtual address space. */ start = v;#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))) valloc(cfree, struct cblock, nclist); valloc(callout, struct callout, ncallout); valloc(swapmap, struct map, nswapmap = maxproc * 2);#ifdef SYSVSHM valloc(shmsegs, struct shmid_ds, shminfo.shmmni);#endif /* * Determine how many buffers to allocate. * We allocate more buffer space than the BSD standard of * using 10% of memory for the first 2 Meg, 5% of remaining. * We just allocate a flat 10%. Insure a minimum of 16 buffers. * We allocate 1/2 as many swap buffer headers as file i/o buffers. */ if (bufpages == 0) bufpages = physmem / 10 / CLSIZE; if (nbuf == 0) { nbuf = bufpages; if (nbuf < 16) nbuf = 16; } if (nswbuf == 0) { nswbuf = (nbuf / 2) &~ 1; /* force even */ if (nswbuf > 256) nswbuf = 256; /* sanity */ } valloc(swbuf, struct buf, nswbuf); valloc(buf, struct buf, nbuf); /* * Clear allocated memory. */ bzero(start, v - start); /* * Initialize the virtual memory system. */ pmap_bootstrap((vm_offset_t)v);}/* * Console initialization: called early on from main, * before vm init or startup. Do enough configuration * to choose and initialize a console. */consinit(){ register int kbd, crt; register char *oscon; /* * First get the "osconsole" environment variable. */ oscon = (*callv->getenv)("osconsole"); crt = kbd = -1; if (oscon && *oscon >= '0' && *oscon <= '9') { kbd = *oscon - '0'; cn_tab.cn_screen = 0; while (*++oscon) { if (*oscon == ',') cn_tab.cn_screen = 1; else if (cn_tab.cn_screen && *oscon >= '0' && *oscon <= '9') { crt = kbd; kbd = *oscon - '0'; break; } } } if (pmax_boardtype == DS_PMAX && kbd == 1) cn_tab.cn_screen = 1; /* * The boot program uses PMAX ROM entrypoints so the ROM sets * osconsole to '1' like the PMAX. */ if (pmax_boardtype == DS_3MAX && crt == -1 && kbd == 1) { cn_tab.cn_screen = 1; crt = 0; kbd = 7; } /* * First try the keyboard/crt cases then fall through to the * remote serial lines. */ if (cn_tab.cn_screen) { switch (pmax_boardtype) { case DS_PMAX:#if NDC > 0 && NPM > 0 if (pminit()) { cn_tab.cn_dev = makedev(DCDEV, DCKBD_PORT); cn_tab.cn_getc = KBDGetc; cn_tab.cn_kbdgetc = dcGetc; cn_tab.cn_putc = fbPutc; cn_tab.cn_disabled = 0; return; }#endif /* NDC and NPM */ goto remcons; case DS_MAXINE:#if NDTOP > 0 if (kbd == 3) { cn_tab.cn_dev = makedev(DTOPDEV, 0); cn_tab.cn_getc = dtopKBDGetc; cn_tab.cn_putc = fbPutc; } else#endif /* NDTOP */ goto remcons;#if NXCFB > 0 if (crt == 3 && xcfbinit()) { cn_tab.cn_disabled = 0; return; }#endif /* XCFB */ break; case DS_3MAX:#if NDC > 0 if (kbd == 7) { cn_tab.cn_dev = makedev(DCDEV, DCKBD_PORT); cn_tab.cn_getc = KBDGetc; cn_tab.cn_kbdgetc = dcGetc; cn_tab.cn_putc = fbPutc; } else#endif /* NDC */ goto remcons; break; case DS_3MIN: case DS_3MAXPLUS:#if NSCC > 0 if (kbd == 3) { cn_tab.cn_dev = makedev(SCCDEV, SCCKBD_PORT); cn_tab.cn_getc = KBDGetc; cn_tab.cn_kbdgetc = sccGetc; cn_tab.cn_putc = fbPutc; } else#endif /* NSCC */ goto remcons; break; default: goto remcons; }; /* * Check for a suitable turbochannel frame buffer. */ if (tc_slot_info[crt].driver_name) {#if NMFB > 0 if (strcmp(tc_slot_info[crt].driver_name, "mfb") == 0 && mfbinit(tc_slot_info[crt].k1seg_address)) { cn_tab.cn_disabled = 0; return; }#endif /* NMFB */#if NCFB > 0 if (strcmp(tc_slot_info[crt].driver_name, "cfb") == 0 && cfbinit(tc_slot_info[crt].k1seg_address)) { cn_tab.cn_disabled = 0; return; }#endif /* NCFB */ printf("crt: %s not supported as console device\n", tc_slot_info[crt].driver_name); } else printf("No crt console device in slot %d\n", crt); }remcons: /* * Configure a serial port as a remote console. */ cn_tab.cn_screen = 0; switch (pmax_boardtype) { case DS_PMAX:#if NDC > 0 if (kbd == 4) cn_tab.cn_dev = makedev(DCDEV, DCCOMM_PORT); else cn_tab.cn_dev = makedev(DCDEV, DCPRINTER_PORT); cn_tab.cn_getc = dcGetc; cn_tab.cn_putc = dcPutc;#endif /* NDC */ break; case DS_3MAX:#if NDC > 0 cn_tab.cn_dev = makedev(DCDEV, DCPRINTER_PORT); cn_tab.cn_getc = dcGetc; cn_tab.cn_putc = dcPutc;#endif /* NDC */ break; case DS_3MIN: case DS_3MAXPLUS:#if NSCC > 0 cn_tab.cn_dev = makedev(SCCDEV, SCCCOMM3_PORT); cn_tab.cn_getc = sccGetc; cn_tab.cn_putc = sccPutc;#endif /* NSCC */ break; case DS_MAXINE:#if NSCC > 0 cn_tab.cn_dev = makedev(SCCDEV, SCCCOMM2_PORT); cn_tab.cn_getc = sccGetc; cn_tab.cn_putc = sccPutc;#endif /* NSCC */ break; }; if (cn_tab.cn_dev == NODEV) printf("Can't configure console!\n");}/* * cpu_startup: allocate memory for variable-sized tables, * initialize cpu, and do autoconfiguration. */cpu_startup(){ register unsigned i; register caddr_t v; int base, residual; vm_offset_t minaddr, maxaddr; vm_size_t size;#ifdef DEBUG extern int pmapdebug; int opmapdebug = pmapdebug; pmapdebug = 0;#endif /* * Good {morning,afternoon,evening,night}. */ printf(version); printf("real mem = %d\n", ctob(physmem)); /* * Allocate virtual address space for file I/O buffers. * Note they are different than the array of headers, 'buf', * and usually occupy more virtual memory than physical. */ size = MAXBSIZE * nbuf; buffer_map = kmem_suballoc(kernel_map, (vm_offset_t *)&buffers, &maxaddr, size, TRUE); minaddr = (vm_offset_t)buffers; if (vm_map_find(buffer_map, vm_object_allocate(size), (vm_offset_t)0, &minaddr, size, FALSE) != KERN_SUCCESS) panic("startup: cannot allocate buffers"); base = bufpages / nbuf; residual = bufpages % nbuf; for (i = 0; i < nbuf; i++) { vm_size_t curbufsize; vm_offset_t curbuf; /* * First <residual> buffers get (base+1) physical pages * allocated for them. The rest get (base) physical pages. * * The rest of each buffer occupies virtual space, * but has no physical memory allocated for it. */ curbuf = (vm_offset_t)buffers + i * MAXBSIZE; curbufsize = CLBYTES * (i < residual ? base+1 : base); vm_map_pageable(buffer_map, curbuf, curbuf+curbufsize, FALSE); vm_map_simplify(buffer_map, curbuf); } /* * Allocate a submap for exec arguments. This map effectively * limits the number of processes exec'ing at any time. */ exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr, 16 * NCARGS, TRUE); /* * Allocate a submap for physio */ phys_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr, VM_PHYS_SIZE, TRUE); /* * Finally, allocate mbuf pool. Since mclrefcnt is an off-size * we use the more space efficient malloc in place of kmem_alloc. */ mclrefcnt = (char *)malloc(NMBCLUSTERS+CLBYTES/MCLBYTES, M_MBUF, M_NOWAIT); bzero(mclrefcnt, NMBCLUSTERS+CLBYTES/MCLBYTES); mb_map = kmem_suballoc(kernel_map, (vm_offset_t *)&mbutl, &maxaddr, VM_MBUF_SIZE, FALSE); /* * Initialize callouts */ callfree = callout; for (i = 1; i < ncallout; i++) callout[i-1].c_next = &callout[i]; callout[i-1].c_next = NULL;#ifdef DEBUG pmapdebug = opmapdebug;#endif printf("avail mem = %d\n", ptoa(cnt.v_free_count)); printf("using %d buffers containing %d bytes of memory\n", nbuf, bufpages * CLBYTES); /* * Set up CPU-specific registers, cache, etc. */ initcpu(); /* * Set up buffers, so they can be used to read disk labels. */ bufinit(); /* * Configure the system. */ configure();}/* * machine dependent system variables. */cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) int *name; u_int namelen; void *oldp; size_t *oldlenp; void *newp; size_t newlen; struct proc *p;{ /* all sysctl names at this level are terminal */ if (namelen != 1) return (ENOTDIR); /* overloaded */ switch (name[0]) { case CPU_CONSDEV: return (sysctl_rdstruct(oldp, oldlenp, newp, &cn_tab.cn_dev, sizeof cn_tab.cn_dev)); default: return (EOPNOTSUPP); } /* NOTREACHED */}/* * Set registers on exec. * Clear all registers except sp, pc. */setregs(p, entry, retval) register struct proc *p; u_long entry; int retval[2];{ int sp = p->p_md.md_regs[SP]; extern struct proc *machFPCurProcPtr; bzero((caddr_t)p->p_md.md_regs, (FSR + 1) * sizeof(int)); p->p_md.md_regs[SP] = sp; p->p_md.md_regs[PC] = entry & ~3; p->p_md.md_regs[PS] = PSL_USERSET; p->p_md.md_flags & ~MDP_FPUSED; if (machFPCurProcPtr == p) machFPCurProcPtr = (struct proc *)0;}/* * WARNING: code in locore.s assumes the layout shown for sf_signum * thru sf_handler so... don't screw with them! */struct sigframe { int sf_signum; /* signo for handler */ int sf_code; /* additional info for handler */ struct sigcontext *sf_scp; /* context ptr for handler */ sig_t sf_handler; /* handler addr for u_sigc */ struct sigcontext sf_sc; /* actual context */};#ifdef DEBUGint sigdebug = 0;int sigpid = 0;#define SDB_FOLLOW 0x01#define SDB_KSTACK 0x02#define SDB_FPSTATE 0x04#endif/* * Send an interrupt to process. */voidsendsig(catcher, sig, mask, code) sig_t catcher; int sig, mask; unsigned code;{ register struct proc *p = curproc; register struct sigframe *fp; register int *regs; register struct sigacts *psp = p->p_sigacts; int oonstack, fsize; struct sigcontext ksc; extern char sigcode[], esigcode[]; regs = p->p_md.md_regs; oonstack = psp->ps_sigstk.ss_flags & SA_ONSTACK; /* * Allocate and validate space for the signal handler * context. Note that if the stack is in data space, the * call to grow() is a nop, and the copyout() * will fail if the process has not already allocated * the space with a `brk'. */ fsize = sizeof(struct sigframe); if ((psp->ps_flags & SAS_ALTSTACK) && (psp->ps_sigstk.ss_flags & SA_ONSTACK) == 0 && (psp->ps_sigonstack & sigmask(sig))) { fp = (struct sigframe *)(psp->ps_sigstk.ss_base + psp->ps_sigstk.ss_size - fsize); psp->ps_sigstk.ss_flags |= SA_ONSTACK; } else fp = (struct sigframe *)(regs[SP] - fsize); if ((unsigned)fp <= USRSTACK - ctob(p->p_vmspace->vm_ssize)) (void)grow(p, (unsigned)fp);#ifdef DEBUG if ((sigdebug & SDB_FOLLOW) || (sigdebug & SDB_KSTACK) && p->p_pid == sigpid) printf("sendsig(%d): sig %d ssp %x usp %x scp %x\n", p->p_pid, sig, &oonstack, fp, &fp->sf_sc);#endif /* * Build the signal context to be used by sigreturn. */ ksc.sc_onstack = oonstack; ksc.sc_mask = mask; ksc.sc_pc = regs[PC]; ksc.sc_regs[ZERO] = 0xACEDBADE; /* magic number */ bcopy((caddr_t)®s[1], (caddr_t)&ksc.sc_regs[1], sizeof(ksc.sc_regs) - sizeof(int)); ksc.sc_fpused = p->p_md.md_flags & MDP_FPUSED; if (ksc.sc_fpused) { extern struct proc *machFPCurProcPtr; /* if FPU has current state, save it first */ if (p == machFPCurProcPtr) MachSaveCurFPState(p); bcopy((caddr_t)&p->p_md.md_regs[F0], (caddr_t)ksc.sc_fpregs, sizeof(ksc.sc_fpregs)); } if (copyout((caddr_t)&ksc, (caddr_t)&fp->sf_sc, sizeof(ksc))) { /* * Process has trashed its stack; give it an illegal * instruction to halt it in its tracks. */ SIGACTION(p, SIGILL) = SIG_DFL; sig = sigmask(SIGILL); p->p_sigignore &= ~sig; p->p_sigcatch &= ~sig;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -