📄 machdep.c
字号:
/* * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * This software was developed by the Computer Systems Engineering group * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and * contributed to Berkeley. * * 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, Lawrence Berkeley Laboratory. * * 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.6 (Berkeley) 1/14/94 * * from: $Header: machdep.c,v 1.44 93/10/31 05:28:36 torek Exp $ */#include <sys/param.h>#include <sys/proc.h>#include <sys/user.h>#include <sys/map.h>#include <sys/buf.h>#include <sys/device.h>#include <sys/reboot.h>#include <sys/systm.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/mount.h>#include <sys/msgbuf.h>#ifdef SYSVSHM#include <sys/shm.h>#endif#include <sys/exec.h>#include <sys/sysctl.h>#include <machine/autoconf.h>#include <machine/frame.h>#include <machine/cpu.h>#include <vm/vm_kern.h>#include <vm/vm_page.h>#include <sparc/sparc/asm.h>#include <sparc/sparc/cache.h>#include <sparc/sparc/vaddrs.h>vm_map_t buffer_map;extern vm_offset_t avail_end;/* * 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 physmem;extern struct msgbuf msgbuf;struct msgbuf *msgbufp = &msgbuf;int msgbufmapped = 1; /* message buffer is always mapped *//* * safepri is a safe priority for sleep to set for a spin-wait * during autoconfiguration or after a panic. */int safepri = 0;caddr_t allocsys();/* * Machine-dependent startup code */cpu_startup(){ register unsigned i; register caddr_t v; register int sz; int base, residual;#ifdef DEBUG extern int pmapdebug; int opmapdebug = pmapdebug;#endif vm_offset_t minaddr, maxaddr; vm_size_t size;#ifdef DEBUG pmapdebug = 0;#endif /* * Good {morning,afternoon,evening,night}. */ printf(version); /*identifycpu();*/ physmem = btoc(avail_end); printf("real mem = %d\n", avail_end); /* * Find out how much space we need, allocate it, * and then give everything true virtual addresses. */ sz = (int)allocsys((caddr_t)0); if ((v = (caddr_t)kmem_alloc(kernel_map, round_page(sz))) == 0) panic("startup: no room for tables"); if (allocsys(v) - v != sz) panic("startup: table size inconsistency"); /* * Now allocate buffers proper. They are different than the above * in that they 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 map for physio. Others use a submap of the kernel * map, but we want one completely separate, even though it uses * the same pmap. */ phys_map = vm_map_create(kernel_pmap, DVMA_BASE, DVMA_END, 1); if (phys_map == NULL) panic("unable to create DVMA map"); /* * 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 buffers, so they can be used to read disk labels. */ bufinit(); /* * Configure the system, then turn on the cache. Should be able * to do this earlier, but then esp.c fails on SS1+ boxes (??). */ configure(); cache_enable();}/* * Allocate space for system data structures. We are given * a starting virtual address and we return a final virtual * address; along the way we set each data structure pointer. * * You call allocsys() with 0 to find out how much space we want, * allocate that much and fill it with zeroes, and then call * allocsys() again with the correct base virtual address. */caddr_tallocsys(v) register caddr_t v;{#define valloc(name, type, num) \ v = (caddr_t)(((name) = (type *)v) + (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 (enough to * hold 5% of total physical memory, but at least 16). * Allocate 1/2 as many swap buffer headers as file i/o buffers. */ if (bufpages == 0) bufpages = (physmem / 20) / 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); return (v);}/* * Set up registers on exec. * * XXX this entire mess must be fixed *//* ARGSUSED */setregs(p, entry, retval) register struct proc *p; u_long entry; int retval[2];{ register struct trapframe *tf = p->p_md.md_tf; register struct fpstate *fs; register int psr, sp; /* * The syscall will ``return'' to npc or %g7 or %g2; set them all. * Set the rest of the registers to 0 except for %o6 (stack pointer, * built in exec()) and psr (retain CWP and PSR_S bits). */ psr = tf->tf_psr & (PSR_S | PSR_CWP); sp = tf->tf_out[6]; if ((fs = p->p_md.md_fpstate) != NULL) { /* * We hold an FPU state. If we own *the* FPU chip state * we must get rid of it, and the only way to do that is * to save it. In any case, get rid of our FPU state. */ if (p == fpproc) { savefpstate(fs); fpproc = NULL; } free((void *)fs, M_SUBPROC); p->p_md.md_fpstate = NULL; } bzero((caddr_t)tf, sizeof *tf); tf->tf_psr = psr; tf->tf_global[2] = tf->tf_global[7] = tf->tf_npc = entry & ~3; tf->tf_out[6] = sp; retval[1] = 0;}#ifdef DEBUGint sigdebug = 0;int sigpid = 0;#define SDB_FOLLOW 0x01#define SDB_KSTACK 0x02#define SDB_FPSTATE 0x04#endifstruct sigframe { int sf_signo; /* signal number */ int sf_code; /* code */#ifdef COMPAT_SUNOS struct sigcontext *sf_scp; /* points to user addr of sigcontext */#else int sf_xxx; /* placeholder */#endif int sf_addr; /* SunOS compat, always 0 for now */ struct sigcontext sf_sc; /* actual sigcontext */};/* * 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 are this level are terminal */ if (namelen != 1) return (ENOTDIR); /* overloaded */ switch (name[0]) { default: return (EOPNOTSUPP); } /* NOTREACHED */}/* * 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 sigacts *psp = p->p_sigacts; register struct sigframe *fp; register struct trapframe *tf; register int addr, oonstack, oldsp, newsp; struct sigframe sf; extern char sigcode[], esigcode[];#define szsigcode (esigcode - sigcode) tf = p->p_md.md_tf; oldsp = tf->tf_out[6]; oonstack = psp->ps_sigstk.ss_flags & SA_ONSTACK; /* * Compute new user stack addresses, subtract off * one signal frame, and align. */ if ((psp->ps_flags & SAS_ALTSTACK) && !oonstack && (psp->ps_sigonstack & sigmask(sig))) { fp = (struct sigframe *)(psp->ps_sigstk.ss_base + psp->ps_sigstk.ss_size); psp->ps_sigstk.ss_flags |= SA_ONSTACK; } else fp = (struct sigframe *)oldsp; fp = (struct sigframe *)((int)(fp - 1) & ~7);#ifdef DEBUG if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) printf("sendsig: %s[%d] sig %d newusp %x scp %x\n", p->p_comm, p->p_pid, sig, fp, &fp->sf_sc);#endif /* * Now set up the signal frame. We build it in kernel space * and then copy it out. We probably ought to just build it * directly in user space.... */ sf.sf_signo = sig; sf.sf_code = code;#ifdef COMPAT_SUNOS sf.sf_scp = &fp->sf_sc;#endif sf.sf_addr = 0; /* XXX */ /* * Build the signal context to be used by sigreturn. */ sf.sf_sc.sc_onstack = oonstack; sf.sf_sc.sc_mask = mask; sf.sf_sc.sc_sp = oldsp; sf.sf_sc.sc_pc = tf->tf_pc; sf.sf_sc.sc_npc = tf->tf_npc; sf.sf_sc.sc_psr = tf->tf_psr; sf.sf_sc.sc_g1 = tf->tf_global[1]; sf.sf_sc.sc_o0 = tf->tf_out[0]; /* * Put the stack in a consistent state before we whack away * at it. Note that write_user_windows may just dump the * registers into the pcb; we need them in the process's memory. * We also need to make sure that when we start the signal handler, * its %i6 (%fp), which is loaded from the newly allocated stack area, * joins seamlessly with the frame it was in when the signal occurred, * so that the debugger and _longjmp code can back up through it. */ newsp = (int)fp - sizeof(struct rwindow); write_user_windows();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -