📄 machdep.c
字号:
/* * Copyright (c) 1988 University of Utah. * Copyright (c) 1982, 1986, 1990, 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. * * 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. * * from: Utah $Hdr: machdep.c 1.74 92/12/20$ * * @(#)machdep.c 8.10 (Berkeley) 4/20/94 */#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/ioctl.h>#include <sys/tty.h>#include <sys/mount.h>#include <sys/user.h>#include <sys/exec.h>#include <sys/sysctl.h>#ifdef SYSVSHM#include <sys/shm.h>#endif#ifdef HPUXCOMPAT#include <hp/hpux/hpux.h>#endif#include <machine/cpu.h>#include <machine/reg.h>#include <machine/psl.h>#include <hp/dev/cons.h>#include <hp300/hp300/isr.h>#include <hp300/hp300/pte.h>#include <net/netisr.h>#define MAXMEM 64*1024*CLSIZE /* XXX - from cmap.h */#include <vm/vm_kern.h>/* the following is used externally (sysctl_hw) */char machine[] = "hp300"; /* cpu "architecture" */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 msgbufmapped; /* set when safe to use msgbuf */int maxmem; /* max memory per process */int physmem = MAXMEM; /* 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;extern u_int lowram;extern short exframesize[];/* * Console initialization: called early on from main, * before vm init or startup. Do enough configuration * to choose and initialize a console. */consinit(){ /* * Set cpuspeed immediately since cninit() called routines * might use delay. Note that we only set it if a custom value * has not already been specified. */ if (cpuspeed == 0) { switch (machineid) { case HP_320: case HP_330: case HP_340: cpuspeed = MHZ_16; break; case HP_350: case HP_360: case HP_380: cpuspeed = MHZ_25; break; case HP_370: case HP_433: cpuspeed = MHZ_33; break; case HP_375: cpuspeed = MHZ_50; break; default: /* assume the fastest */ cpuspeed = MHZ_50; break; } if (mmutype == MMU_68040) cpuspeed *= 2; /* XXX */ } /* * Find what hardware is attached to this machine. */ find_devs(); /* * Initialize the console before we print anything out. */ cninit();}/* * cpu_startup: allocate memory for variable-sized tables, * initialize cpu, and do autoconfiguration. */cpu_startup(){ register unsigned i; register caddr_t v, firstaddr; int base, residual; vm_offset_t minaddr, maxaddr; vm_size_t size;#ifdef BUFFERS_UNMANAGED vm_offset_t bufmemp; caddr_t buffermem; int ix;#endif#ifdef DEBUG extern int pmapdebug; int opmapdebug = pmapdebug; pmapdebug = 0;#endif /* * Initialize error message buffer (at end of core). * avail_end was pre-decremented in pmap_bootstrap to compensate. */ for (i = 0; i < btoc(sizeof (struct msgbuf)); i++) pmap_enter(kernel_pmap, (vm_offset_t)msgbufp, avail_end + i * NBPG, VM_PROT_ALL, TRUE); msgbufmapped = 1; /* * Good {morning,afternoon,evening,night}. */ printf(version); identifycpu(); printf("real mem = %d\n", ctob(physmem)); /* * Allocate space for system data structures. * The first available real memory address is in "firstaddr". * The first available kernel virtual address is in "v". * As pages of kernel virtual memory are allocated, "v" is incremented. * As pages of memory are allocated and cleared, * "firstaddr" is incremented. * An index into the kernel page table corresponding to the * virtual memory address maintained in "v" is kept in "mapaddr". */ /* * Make two passes. The first pass calculates how much memory is * needed and allocates it. The second pass assigns virtual * addresses to the various data structures. */ firstaddr = 0;again: v = (caddr_t)firstaddr;#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. * Since HPs tend to be long on memory and short on disk speed, * we allocate more buffer space than the BSD standard of * use 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); /* * End of first pass, size has been calculated so allocate memory */ if (firstaddr == 0) { size = (vm_size_t)(v - firstaddr); firstaddr = (caddr_t) kmem_alloc(kernel_map, round_page(size)); if (firstaddr == 0) panic("startup: no room for tables");#ifdef BUFFERS_UNMANAGED buffermem = (caddr_t) kmem_alloc(kernel_map, bufpages*CLBYTES); if (buffermem == 0) panic("startup: no room for buffers");#endif goto again; } /* * End of second pass, addresses have been assigned */ if ((vm_size_t)(v - firstaddr) != size) 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;#ifdef BUFFERS_UNMANAGED bufmemp = (vm_offset_t) buffermem;#endif 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);#ifdef BUFFERS_UNMANAGED /* * Move the physical pages over from buffermem. */ for (ix = 0; ix < curbufsize/CLBYTES; ix++) { vm_offset_t pa; pa = pmap_extract(kernel_pmap, bufmemp); if (pa == 0) panic("startup: unmapped buffer"); pmap_remove(kernel_pmap, bufmemp, bufmemp+CLBYTES); pmap_enter(kernel_pmap, (vm_offset_t)(curbuf + ix * CLBYTES), pa, VM_PROT_READ|VM_PROT_WRITE, TRUE); bufmemp += CLBYTES; }#else vm_map_pageable(buffer_map, curbuf, curbuf+curbufsize, FALSE); vm_map_simplify(buffer_map, curbuf);#endif }#ifdef BUFFERS_UNMANAGED#if 0 /* * We would like to free the (now empty) original address range * but too many bad things will happen if we try. */ kmem_free(kernel_map, (vm_offset_t)buffermem, bufpages*CLBYTES);#endif#endif /* * 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. * XXX Should clear registers except sp, pc, * but would break init; should be fixed soon. */setregs(p, entry, retval) register struct proc *p; u_long entry; int retval[2];{ struct frame *frame = (struct frame *)p->p_md.md_regs; frame->f_pc = entry & ~1;#ifdef FPCOPROC /* restore a null state frame */ p->p_addr->u_pcb.pcb_fpregs.fpf_null = 0; m68881_restore(&p->p_addr->u_pcb.pcb_fpregs);#endif#ifdef HPUXCOMPAT if (p->p_md.md_flags & MDP_HPUX) { frame->f_regs[A0] = 0; /* not 68010 (bit 31), no FPA (30) */ retval[0] = 0; /* no float card */#ifdef FPCOPROC retval[1] = 1; /* yes 68881 */#else retval[1] = 0; /* no 68881 */#endif } /* * XXX This doesn't have much to do with setting registers but * I didn't want to muck up kern_exec.c with this code, so I * stuck it here. * * Ensure we perform the right action on traps type 1 and 2: * If our parent is an HPUX process and we are being traced, turn * on HPUX style interpretation. Else if we were using the HPUX * style interpretation, revert to the BSD interpretation. * * Note that we do this by changing the trap instruction in the * global "sigcode" array which then gets copied out to the user's * sigcode in the stack. Since we are changing it in the global * array we must always reset it, even for non-HPUX processes. * * Note also that implementing it in this way creates a potential * race where we could have tweaked it for process A which then * blocks in the copyout to the stack and process B comes along * and untweaks it causing A to wind up with the wrong setting * when the copyout continues. However, since we have already * copied something out to this user stack page (thereby faulting * it in), this scenerio is extremely unlikely. */ { extern short sigcodetrap[]; if ((p->p_pptr->p_md.md_flags & MDP_HPUX) && (p->p_flag & P_TRACED)) { p->p_md.md_flags |= MDP_HPUXTRACE; *sigcodetrap = 0x4E42; } else { p->p_md.md_flags &= ~MDP_HPUXTRACE; *sigcodetrap = 0x4E41; } }#endif}/* * Info for CTL_HW */char cpu_model[120];extern char version[];identifycpu(){ char *t, *mc; int len; switch (machineid) { case HP_320: t = "320 (16.67MHz"; break; case HP_330: t = "318/319/330 (16.67MHz"; break; case HP_340: t = "340 (16.67MHz"; break; case HP_350: t = "350 (25MHz"; break; case HP_360: t = "360 (25MHz"; break; case HP_370: t = "370 (33.33MHz"; break; case HP_375: t = "345/375 (50MHz"; break; case HP_380: t = "380/425 (25MHz"; break; case HP_433: t = "433 (33MHz"; break; default: printf("\nunknown machine type %d\n", machineid); panic("startup"); } mc = (mmutype == MMU_68040 ? "40" : (mmutype == MMU_68030 ? "30" : "20")); sprintf(cpu_model, "HP9000/%s MC680%s CPU", t, mc); switch (mmutype) { case MMU_68040: case MMU_68030: strcat(cpu_model, "+MMU"); break; case MMU_68851: strcat(cpu_model, ", MC68851 MMU"); break; case MMU_HP: strcat(cpu_model, ", HP MMU"); break; default: printf("%s\nunknown MMU type %d\n", cpu_model, mmutype); panic("startup"); } len = strlen(cpu_model); if (mmutype == MMU_68040) len += sprintf(cpu_model + len, "+FPU, 4k on-chip physical I/D caches"); else if (mmutype == MMU_68030) len += sprintf(cpu_model + len, ", %sMHz MC68882 FPU", machineid == HP_340 ? "16.67" : (machineid == HP_360 ? "25" : (machineid == HP_370 ? "33.33" : "50"))); else len += sprintf(cpu_model + len, ", %sMHz MC68881 FPU", machineid == HP_350 ? "20" : "16.67"); switch (ectype) { case EC_VIRT: sprintf(cpu_model + len, ", %dK virtual-address cache", machineid == HP_320 ? 16 : 32); break; case EC_PHYS: sprintf(cpu_model + len, ", %dK physical-address cache", machineid == HP_370 ? 64 : 32); break; } strcat(cpu_model, ")"); printf("%s\n", cpu_model); /* * Now that we have told the user what they have, * let them know if that machine type isn't configured. */ switch (machineid) { case -1: /* keep compilers happy */#if !defined(HP320) && !defined(HP350) case HP_320: case HP_350:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -