📄 machdep.c
字号:
/* * Copyright (c) 1988 University of Utah. * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * the Systems Programming Group of the University of Utah Computer * Science Department, The Mach Operating System project at * Carnegie-Mellon University, Ralph Campbell, Sony Corp. and Kazumasa * Utashiro of Software Research Associates, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)machdep.c 8.3 (Berkeley) 1/12/94 *//* from: Utah $Hdr: machdep.c 1.63 91/04/24$ */#include <sys/param.h>#include <sys/systm.h>#include <sys/signalvar.h>#include <sys/kernel.h>#include <sys/map.h>#include <sys/proc.h>#include <sys/buf.h>#include <sys/reboot.h>#include <sys/conf.h>#include <sys/file.h>#include <sys/clist.h>#include <sys/callout.h>#include <sys/malloc.h>#include <sys/mbuf.h>#include <sys/msgbuf.h>#include <sys/user.h>#include <sys/exec.h>#include <sys/sysctl.h>#ifdef SYSVSHM#include <sys/shm.h>#endif#include <vm/vm_kern.h>#include <machine/cpu.h>#include <machine/reg.h>#include <machine/psl.h>#include <machine/pte.h>#include <machine/adrsmap.h>vm_map_t buffer_map;/* the following is used externally (sysctl_hw) */char machine[] = "SONY"; /* cpu "architecture" */char cpu_model[30];/* * Declare these as initialized data so we can patch them. */int nswbuf = 0;#ifdef NBUFint nbuf = NBUF;#elseint nbuf = 0;#endif#ifdef BUFPAGESint bufpages = BUFPAGES;#elseint bufpages = 0;#endifint msgbufmapped = 0; /* set when safe to use msgbuf */int maxmem; /* max memory per process */int physmem; /* max supported memory, changes to actual *//* * safepri is a safe priority for sleep to set for a spin-wait * during autoconfiguration or after a panic. */int safepri = PSL_LOWIPL;struct user *proc0paddr;struct proc nullproc; /* for use by switch_exit() *//* * Do all the stuff that locore normally does before calling main(). * Process arguments passed to us by the prom monitor. * Return the first page address following the system. */mach_init(x_boothowto, x_unkown, x_bootdev, x_maxmem) int x_boothowto; int x_unkown; int x_bootdev; int x_maxmem;{ register char *cp; register int i; register unsigned firstaddr; register caddr_t v; caddr_t start; extern u_long bootdev; extern char edata[], end[]; extern char MachUTLBMiss[], MachUTLBMissEnd[]; extern char MachException[], MachExceptionEnd[]; /* * Save parameters into kernel work area. */ *(int *)(MACH_CACHED_TO_UNCACHED(MACH_MAXMEMSIZE_ADDR)) = x_maxmem; *(int *)(MACH_CACHED_TO_UNCACHED(MACH_BOOTDEV_ADDR)) = x_bootdev; *(int *)(MACH_CACHED_TO_UNCACHED(MACH_BOOTSW_ADDR)) = x_boothowto; /* clear the BSS segment */ v = (caddr_t)pmax_round_page(end); bzero(edata, v - edata); boothowto = x_boothowto; bootdev = x_bootdev; maxmem = physmem = pmax_btop(x_maxmem); /* * Look at arguments passed to us and compute boothowto. */#ifdef GENERIC boothowto |= RB_SINGLE | RB_ASKNAME;#endif#ifdef KADB boothowto |= RB_KDB;#endif#ifdef MFS /* * Check to see if a mini-root was loaded into memory. It resides * at the start of the next page just after the end of BSS. */ if (boothowto & RB_MINIROOT) { boothowto |= RB_DFLTROOT; v += mfs_initminiroot(v); }#endif /* * Init mapping for u page(s) for proc[0], pm_tlbpid 1. */ start = v; curproc->p_addr = proc0paddr = (struct user *)v; curproc->p_md.md_regs = proc0paddr->u_pcb.pcb_regs; firstaddr = MACH_CACHED_TO_PHYS(v); for (i = 0; i < UPAGES; i++) { MachTLBWriteIndexed(i, (UADDR + (i << PGSHIFT)) | (1 << VMMACH_TLB_PID_SHIFT), curproc->p_md.md_upte[i] = firstaddr | PG_V | PG_M); firstaddr += NBPG; } v += UPAGES * NBPG; MachSetPID(1); /* * init nullproc for switch_exit(). * init mapping for u page(s), pm_tlbpid 0 * This could be used for an idle process. */ nullproc.p_addr = (struct user *)v; nullproc.p_md.md_regs = nullproc.p_addr->u_pcb.pcb_regs; bcopy("nullproc", nullproc.p_comm, sizeof("nullproc")); for (i = 0; i < UPAGES; i++) { nullproc.p_md.md_upte[i] = firstaddr | PG_V | PG_M; firstaddr += NBPG; } v += UPAGES * NBPG; /* clear pages for u areas */ bzero(start, v - start); /* * Copy down exception vector code. */ if (MachUTLBMissEnd - MachUTLBMiss > 0x80) panic("startup: UTLB code too large"); bcopy(MachUTLBMiss, (char *)MACH_UTLB_MISS_EXC_VEC, MachUTLBMissEnd - MachUTLBMiss); bcopy(MachException, (char *)MACH_GEN_EXC_VEC, MachExceptionEnd - MachException); /* * Clear out the I and D caches. */ MachConfigCache(); MachFlushCache(); /* * 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. * XXX need something better here. */#define SCC_CONSOLE 0#define SW_CONSOLE 0x07#define SW_NWB512 0x04#define SW_NWB225 0x01#define SW_FBPOP 0x02#define SW_FBPOP1 0x06#define SW_FBPOP2 0x03#define SW_AUTOSEL 0x07consinit(){ extern dev_t consdev; extern struct tty *constty, *cn_tty, *rs_tty; int dipsw = (int)*(volatile u_char *)DIP_SWITCH;#include "bm.h"#if NBM > 0#if defined(news3200) || defined(news3400) /* KU:XXX */ fbbm_probe(dipsw|2);#else fbbm_probe(dipsw);#endif vt100_open(); setup_fnt(); setup_fnt24();#else dipsw &= SW_CONSOLE;#endif switch (dipsw & SW_CONSOLE) { case 0: scc_open(SCC_CONSOLE); consdev = makedev(1, 0); constty = rs_tty; break; default:#if NBM > 0 consdev = makedev(22, 0); constty = cn_tty;#endif break; } return(0);}/* * 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();}/* * 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -