⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 simmagic.c

📁 一个用在mips体系结构中的操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Copyright (C) 1996-1998 by the Board of Trustees *    of Leland Stanford Junior University. *  * This file is part of the SimOS distribution.  * See LICENSE file for terms of the license.  * */ /***************************************************************** * simmagic.c * * Interface between the OS view of the machine and the SimOS * device simulators. * * Created by: John Chapin, 05/95 * Revision history: *   06/95  (Dan Teodosiu) added interrupt subsystem support. *   06/95  (John Chapin)  added register access, interrupt event codes *   06/95  (John Chapin)  moved flash defines out, added universal I/O ops *   11/95  (John Chapin)  added PPC version 2 support *   07/96  (Dan Teodosiu) complete OS/SimOS overhaul *   02/97  (Ben Werther)  generalized number of devices per machine * ****************************************************************/#include "sim.h"#include <stdio.h>#include <sys/types.h>#include <sys/mman.h>#include <sys/file.h>#include <sys/signal.h>#ifndef __alpha#ifndef i386#include <sys/unistd.h>#include <sys/ioccom.h>#include <sys/filio.h>#include <netinet/in.h>#endif#endif#include <sys/time.h>#include <sys/uio.h>#include <unistd.h>#include <string.h>#ifdef sgi#include <netinet/if_ether.h>#endif#include <errno.h>#include <netdb.h>#include <stdlib.h>#include "syslimits.h"#include "simtypes.h"#include "checkpoint.h"#include "machine_params.h"#include "cpu_interface.h"#include "cpu_state.h"#include "sim_error.h"#include "addr_layout.h"#include "registry.h"#include "dma.h"#include "../../devices/disk/simos_interface.h"#include "remote_access.h"#include "simutil.h"#include "../../memsystems/flashlite/flash_interface.h"#include "../../memsystems/memsys.h"#include "simmagic.h"#include "hd.h"#include "console.h"#include "ethernet.h"#include "sips.h"#include "firewall.h"#include "startup.h"#include "machine_defs.h"#ifdef SUPPORT_LINUX#include "linux_init.h"#endif#ifdef TORNADO#include "simgizmo.h"#endif/* Cache counting stuff. The routines are in numa.c */#define IS_NUMA() (memsysVec.type == NUMA)uint64 MigRepGetHotPage(int memnum);uint64 MigRepGetInfo(unsigned long addr, int memnum,                                  unsigned long countType, unsigned long countAddr);void MigRepSetInfo(unsigned long addr, int memnum, uint64 val,                   unsigned long countType, unsigned long countAddr);/* Control debugging info printout: 0=off, 1=on */#define DEBUG_MAGIC 0#define offsetof(t,m) ((int)&((t*)0)->m)int FPromUseFL;long initialBootTime; static CptCallback SimMagic_CheckpointCB;typedef struct MagicStatus {  MagicRegister iPendingReg;   /* 64b interrupt pending reg */  MagicRegister iTransReg;     /* 64b int pending reg (transition-sensitive) */  MagicRegister iEnableMask;   /* 64b interrupt enable mask */  unsigned char iBitTable[64]; /* IEC -> CPU intrBits map				* Note: read/written in 64-bit 				* chunks so must be aligned				*/  MagicRegister IEChigh;       /* current interrupt level (board) */  IEC           ioSlotMap[SIM_MAXSLOTS]; /* slot -> IEC map */  IEC           ioSlots[SIM_MAXSLOTS];   /* pending count for each slot */    int           timerInterval; /* 0 => no timer interrupt on this CPU				* > 0 => interrupt with specified				* periodicity [us].				*/  MagicRegister workerMask;    /* mask bits for cell boundary */  MagicRegister workerMatch;   /* match bits for cell id */} MagicStatus;MagicStatus mm[SIM_MAXCPUS]; /* MAGIC status for all nodes */DeviceToMachineStruct deviceToMachine; /* Device to machine mappings *//* * Save someone a bunch of debugging time if they use some of SGI compilers * that doesn't sign-extend correctly when optimization is turned on. */#define CHECK_FOR_COMPILER_BUG CheckForCompilerBug(0x80000000,(VA)0xffffffff80000000LL)static voidCheckForCompilerBug(uint addr, VA val){   VA   vAddr = (VA)(Reg32_s)addr; /* Sign extend if needed */   if (vAddr != val) CPUError("Your compiler is broken\n");}#define CHECK_FOR_COMPILER_BUG2 \  CheckForCompilerBug2(0x80000000,(Reg)0xffffffff80000000LL)static voidCheckForCompilerBug2(Reg addr, Reg val){   Reg new = (Reg)(Reg32_s)addr; /* Sign extend if needed */   if (new != val) CPUWarning("CAREFUL: Your compiler is broken\n");}/**************************************************************************** * * Interrupt subsystem * ****************************************************************************//* recompute intrBits for the specified CPU. */voidrecompute_intr_bits(register int cpu){  MagicRegister pend;  MagicRegister trans;  int           iechigh;  int i;  MagicRegister mask;  ASSERT(!USE_MAGIC());    /* compute IEChigh = ffsb(pend) */  pend = mm[cpu].iPendingReg & mm[cpu].iEnableMask;  if (pend == 0) {      iechigh = 0;  } else {    for (iechigh = -1; pend >= (1<<8); pend >>= 8) iechigh += 8;    for ( ; pend != 0; pend >>= 1)                 iechigh++;  }  mm[cpu].IEChigh = iechigh;  /* compute cause bits */  trans = mm[cpu].iTransReg & mm[cpu].iEnableMask;  CPUVec.intrBits[cpu] = 0;  for(i=0, mask = 1; i < 64; i++, mask <<= 1) {     if (trans & mask) {	 CPUVec.intrBits[cpu] |= (mm[cpu].iBitTable[i]<<2);     }  }#ifdef TORNADO  /* XXX this may be broken now -- check! */  if ( mm[cpu].iPendingReg == 0x1 ) {    CPUVec.intrBits[cpu] |= (CAUSE_IP4 >> CAUSE_IPSHIFT);  } else if ( mm[cpu].iPendingReg ) {    CPUVec.intrBits[cpu] |= (CAUSE_IP8 >> CAUSE_IPSHIFT);  } else {    CPUVec.intrBits[cpu] &= ~(CAUSE_IPMASK >> CAUSE_IPSHIFT);  }#endif  CPUVec.IntrBitsChanged(cpu);}voidRaiseIBit(int cpu, IEC code){  MagicRegister ibit = ((MagicRegister)1) << code;  ASSERT(!USE_MAGIC());  if (!(mm[cpu].iPendingReg & ibit)) {    /* 0->1 transition */#if (DEBUG_MAGIC == 1)    LogEntry("RaiseIBit", cpu, "code=0x%x 0->1 transition\n", code);#endif    mm[cpu].iPendingReg |= ibit;    mm[cpu].iTransReg   |= ibit;    recompute_intr_bits(cpu);  } else {    /* no transition */#if (DEBUG_MAGIC == 1)    LogEntry("RaiseIBit", cpu, "code=0x%x no transition\n", code);#endif  }}voidClearIBit(int cpu, IEC code){  MagicRegister ibit = ((MagicRegister)1) << code;  ASSERT(!USE_MAGIC());  if ((mm[cpu].iPendingReg & ibit)) {    /* 1->0 transition */#if (DEBUG_MAGIC == 1)    LogEntry("ClearIBit", cpu, "code=0x%x 1->0 transition\n", code);#endif    mm[cpu].iPendingReg &= ~ibit;    mm[cpu].iTransReg   &= ~ibit;    recompute_intr_bits(cpu);  } else {    /* no transition */#if (DEBUG_MAGIC == 1)    LogEntry("ClearIBit", cpu, "code=0x%x no transition\n", code);#endif  }}static voidRaiseSlot(int cpu, int slot){  ASSERT(0 <= cpu && cpu < TOTAL_CPUS);  ASSERT(0 <= slot && slot < SIM_MAXSLOTS);#if (DEBUG_MAGIC == 1)  LogEntry("RaiseSlot",cpu,"slot=%d  prevVal=0x%x\n",	   slot, mm[cpu].ioSlots[slot]);#endif  if (mm[cpu].ioSlots[slot]++ == 0) {    /* Slot transitions 0->1, must raise interrupt bit */    if (USE_MAGIC()) {      FlashliteRaiseSlot(cpu, slot);    } else {      RaiseIBit(cpu, mm[cpu].ioSlotMap[slot]);    }  }}voidClearSlot(int cpu, int slot){  register int slotval;    ASSERT(0 <= cpu && cpu < TOTAL_CPUS);  ASSERT(0 <= slot && slot < SIM_MAXSLOTS);#if (DEBUG_MAGIC == 1)  LogEntry("ClearSlot",cpu,"slot=%d  prevVal=0x%x\n",	   slot, mm[cpu].ioSlots[slot]);#endif  slotval = --mm[cpu].ioSlots[slot];  if (slotval < 0) {     /* this can occur if: console TX_INTR is      * pending when a cell is rebooted.  This gets cleared once      * during cell initialization and again on the next GetIntrStatus      * since flags in the simulated console device are still set.      */      Sim_Warning("ClearSlot(%d, %d): slot value dropped below 0\n",                   cpu, slot);      mm[cpu].ioSlots[slot] = 0;  } else if (slotval == 0) {    /* Slot transitions 1->0, must clear interrupt bit. */    if (USE_MAGIC()) {      FlashliteClearSlot(cpu, slot);    } else {       ClearIBit(cpu, mm[cpu].ioSlotMap[slot]);    }  }}/* NOTE: can ack only an internal interrupt cause */intAckInternalInt(int n, IEC iec){  switch (iec) {  case DEV_IEC_OSPC_LO:  case DEV_IEC_OSPC_HI:    /* ack SIPS (if any) */    sim_sips_ack(n, (iec == DEV_IEC_OSPC_LO));    return 0;  case DEV_IEC_CLOCK:  case DEV_IEC_IPI:  case DEV_IEC_IPI1:  case DEV_IEC_IPI2:    /* just clear int */    ClearIBit(n, iec);    return 0;  default: return -1;  }}/***************************************************************** * Migration-Replication support *****************************************************************/void MigRepStart(int cpu){   RaiseIBit(cpu, DEV_IEC_MIG_REP);}void MigRepEnd(int cpu){   ClearIBit(cpu, DEV_IEC_MIG_REP);}/**************************************************************************** * * Clock interrupt support * ****************************************************************************//* eventcallback hdr for clock timer */static EventCallbackHdr timerHdr[SIM_MAXCPUS];/* clock interrupt counter for stats */static uint             clockIntrs;/* maintain last time timer was invoked so that   we can checkpoint the correct timeleft. */static SimTime          lastTimeout[SIM_MAXCPUS];/* timer callback: raise interrupt and enqueue yourself for next tick */static voidTimerCallback(int cpuNum, EventCallbackHdr *hdr, void *arg){  ASSERT(!USE_MAGIC());  /* if (CPUVec.drainEvents) { */  if (0) {      /* eventqueue is being cleared, so figure out the timeleft so      * next CPU model can restart the clock correctly */     CPUVec.clockStarted[cpuNum] = 0;          SBase[cpuNum].clockTimeLeft = SBase[cpuNum].clockInterval -         (CPUVec.CycleCount(cpuNum) - lastTimeout[cpuNum])/CPU_CLOCK;     if (SBase[cpuNum].clockTimeLeft > SBase[cpuNum].clockInterval)        SBase[cpuNum].clockTimeLeft = SBase[cpuNum].clockInterval;     return;  }    lastTimeout[cpuNum] = CPUVec.CycleCount(cpuNum);  clockIntrs++;  RaiseIBit(cpuNum, DEV_IEC_CLOCK);  CPUVec.IntrBitsChanged(cpuNum);      EventDoCallback(cpuNum, TimerCallback, hdr, NULL,		  CPUVec.clockInterval[cpuNum] * CPU_CLOCK);}/* sets up the callback data and the first callback */voidInstallTimer(int cpuNum, unsigned int interval, unsigned int timeLeft){  ASSERT(!USE_MAGIC());  CPUVec.clockInterval[cpuNum] = interval;    if (CPUVec.clockStarted[cpuNum]) EventCallbackRemove(&timerHdr[cpuNum]);  CPUVec.clockStarted[cpuNum] = 1;  EventDoCallback(cpuNum, TimerCallback, &timerHdr[cpuNum], NULL, 		  timeLeft * CPU_CLOCK);  SBase[cpuNum].clockInterval = CPUVec.clockInterval[cpuNum];  SBase[cpuNum].clockStarted = CPUVec.clockStarted[cpuNum];}/* called when restoring from a checkpoint */voidInstallTimers(void){  int i;  for(i = 0; i < TOTAL_CPUS; i++) {     if (SBase[i].clockStarted) {        if (USE_MAGIC()) {           FlashliteInstallTimer(i, SBase[i].clockInterval, SBase[i].clockTimeLeft);        } else {           InstallTimer(i, SBase[i].clockInterval, SBase[i].clockTimeLeft);        }     }  }}/* called when checkpointing, so that timeLeft field can be updated. */voidTimerUpdateTimeLeft(void){  int cpuNum;  for(cpuNum = 0; cpuNum < TOTAL_CPUS; cpuNum++)    if (SBase[cpuNum].clockStarted) {      SBase[cpuNum].clockTimeLeft = SBase[cpuNum].clockInterval - 	     (CPUVec.CycleCount(cpuNum) - lastTimeout[cpuNum])/CPU_CLOCK;      if (SBase[cpuNum].clockTimeLeft > SBase[cpuNum].clockInterval)	SBase[cpuNum].clockTimeLeft = SBase[cpuNum].clockInterval;    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -