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

📄 simos_interface.c

📁 一个用在mips体系结构中的操作系统
💻 C
字号:
/* * 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.  * *//***************************************************************** * simos_interface.c * * This is the interface from simos into the detailed cpu simulator. * Simos puts all of the state into a structure that can be directly * loaded into the cpus data structures. When this level of simulation * has completed, the new state will be restored and control will be * passed back to simos. Mipsy will run until it has executed the * number of instructions passed to MipsyEnter() or until MipsyExit() * is invoked. * * $Author: bosch $ * $Date: 1998/02/10 00:31:59 $ *****************************************************************/ #include <stdio.h>#include <string.h>#include <stdlib.h>#include "mipsy.h"#include "cpu.h"#include "fpu.h"#include "machine_params.h"#include "simutil.h"#include "cpu_stats.h"#ifdef MIPSY_MXS# include "ms.h"#endif#include "cpu_state.h"#include "sim_error.h"#include "cp0.h"#include "eventcallback.h"#include "cpu_interface.h"#include "simmisc.h" #include "simmagic.h"#include "annotations.h"#include "hw_events.h"#include "registry.h"#include "memref.h"/* Global Functions */extern void HandleDebugSignal(int cpuid, int sigusr); /* Defined in debug.c */extern void CPUVectorInit(void);extern void MipsyDumpAllStats(void);extern CPUState *SBase;/* Local Functions */static void ReadConfiguration(void);static void SetupMipsy(int cpuNum);static void SendIntr(int cpunum, IEC, SimTime delay);static void IntrBitsChanged(int cpunum);static void DeliverSIPS(int r, int chan, SimTime delay);static void FaultInject(int cpuNum, faultTypeEnum);static void MakeProcExit(int cpuNum);static int  MipsyResetCPU(int cpuNum);static CPUType mipsyExitTo = BASE;/***************************************************************** * MipsyEnter * * This is the main interface into setting up MIPSY to run. It * should be called from simos to set up registers, tlb, cache, * memory, etc. The second parameter is the number of instructions * to simulate. * If count is set to zero, MipsyRun will not be called, but the * final stats will be printed and we will return to base mode. *****************************************************************/voidMipsyEnter(int swtch){   int cpu;   static int initialized = 0;   PE = SBase;   CPUVectorInit();   if (!initialized) {             initialized = 1;      MipsyInit();      HWEventsLateInit();   }   ReadConfiguration();   for (cpu = 0; cpu < TOTAL_CPUS; cpu++) {      SetupMipsy(cpu);      ASSERT(PE[cpu].myNum == cpu);   }   InstallTimers();	/* tell simmagic to start timers */   InstallPoller();	/* add poll callback to eventqueue */   for (cpu = 0; cpu < TOTAL_CPUS; cpu++) {      MipsyCheckForInterrupts(&PE[cpu]);   }   /*     * Jump into Mipsy     */    MipsyRun(swtch);      /* Right now we dump everything when switching out of mipsy */   MipsyDumpAllStats();   CPUPrint("***************  %lld  final annotations ****************\n",            (uint64) MipsyReadTime(0));   AnnExec(AnnFind("simos","periodic"));   if (mipsyExitTo == BASE) {      AnnExec(AnnFind("simos","exit"));      CPUWarning("User requested abort at cycle count %lld\n",                 (uint64)MipsyReadTime(0));      exit(0);   }#ifdef MIPSY_MXS   for (cpu = 0; cpu < TOTAL_CPUS; cpu++) {      CopyFromMXS(&PE[cpu]);   }#endif   SimulatorSwitch(MIPSY,mipsyExitTo);}/***************************************************************** * SetupMipsy *  * These are mipsy specific variables that need to be set whenever * switching to this Uber-simulator. *****************************************************************/static voidSetupMipsy(int cpuNum){   register CPUState *P = &PE[cpuNum];      MIPSY_SET_TIME(cpuNum, P->cycleCount);   if (P->cpuStatus != cpu_running) {      P->cpuStatus = cpu_stalled;      CPUPrint("MIPSY: Processor %d is NOT RUNNING\n", P->myNum);   } else {      P->cpuStatus = cpu_running;      CPUPrint("MIPSY: Processor %d is running\n", P->myNum);   }   P->myNum = cpuNum;   P->takeInterrupt = FALSE;   STATS_SET(cpuNum, numInstructions, 0);   STATS_SET(cpuNum, nextInstrSample, MS_SAMPLE_INSTR_INTERVAL);   STATS_SET(cpuNum, iReads, 0);   STATS_SET(cpuNum, dReads, 0);   STATS_SET(cpuNum, dWrites, 0);   STATS_SET(cpuNum, stallTime, 0);   /* Assuming you never enter mipsy in a delay slot */   P->nPC = P->PC + INST_SIZE;      MipsyInitTLBHashTable(P);      #ifdef MIPSY_MXS   CopyToMXS(P);#endif}/***************************************************************** * SimosMipsySetExitSimulator *  * This overrides the default exit simulator passed into  * SimosCPUEnter *****************************************************************/voidMipsySetExitSimulator(CPUType newCpu){   mipsyExitTo = newCpu;   simosCPUType = newCpu;}/***************************************************************** * ReadConfiguration * There are several mipsy variables set in the uid configuration  * file interpreted by simos. Set these to mipsy variables. *****************************************************************/static voidReadConfiguration(void){   simosCPUType = MIPSY;   CPUVec.Send_Interrupt  = SendIntr;   CPUVec.Deliver_SIPS    = DeliverSIPS;   CPUVec.IntrBitsChanged = IntrBitsChanged;   /* Fault injection model. */   CPUVec.FaultInject = FaultInject;   CPUVec.FirewallChange  = 0;   CPUVec.ResetCPU        = MipsyResetCPU;   CPUVec.MigRepStart     = MigRepStart;   CPUVec.MigRepEnd       = MigRepEnd;;   /* parallel event queues */   CPUVec.singleEventQueue  = TRUE;   CPUVec.ProcMakeProcExit  = MakeProcExit;   CPUVec.ExitSimulator     = MipsyExit;} /***************************************************************** * CPU Fault handling *****************************************************************/static voidFaultInject(int cpuNum, faultTypeEnum faultType){   extern Result smashinst(int cpunum, VA addr, int rnd, char* errbuf);   /* smashinst only here to avoid linking problems... actually called    * directly from faults.c in common/tcl    */   switch (faultType) {   case SIMFAULT_HALT:      /* We simulate a fault by halting the specified cpu */      PE[cpuNum].cpuStatus = cpu_halted;      break;   case SIMFAULT_DISABLECPU:      ASSERT (cpuNum>=0 && cpuNum < SIM_MAXCPUS);      PE[cpuNum].cpuStatus = cpu_idle;      break;   default:      CPUWarning("Unknown fault (%d) ignored\n", faultType);      smashinst(0, 0, 0, 0);      break;   }}/***************************************************************** * Interrupt posting code.  *****************************************************************/#define MAXIBLOCKS 64static struct IntrBlock {    EventCallbackHdr cbhdr;    int              cpunum;      /* CPU to interrupt. */    IEC              intrtoset;} iblocks[MAXIBLOCKS];static int irotor = 0;static voidSendIntrCallback(int cpuNum, EventCallbackHdr *E, void* arg){   struct IntrBlock *iblock = (struct IntrBlock *)arg;  RaiseIBit(cpuNum, iblock->intrtoset);  MipsyCheckForInterrupts(&PE[cpuNum]);  return;}static voidSendIntr(int cpuNum, IEC intrtoset, SimTime delay){   int i;   if (delay == 0) {      RaiseIBit(cpuNum, intrtoset);      MipsyCheckForInterrupts(&PE[cpuNum]);      return;   }   i = irotor;   do {      if (iblocks[i].cbhdr.active == FALSE) {         iblocks[i].cpunum = cpuNum;         iblocks[i].intrtoset = intrtoset;         EventDoCallback(cpuNum, SendIntrCallback, &iblocks[i].cbhdr,                          &iblocks[i], delay);         if (i == MAXIBLOCKS-1)              irotor = 0;         else            irotor = i+1;         return;      }      if (i == MAXIBLOCKS-1)          i = 0;      else         i += 1;   } while (i != irotor);   CPUError("Too many simultaneous interrupts");}static void IntrBitsChanged(int cpuNum){   MipsyCheckForInterrupts(&PE[cpuNum]);}/***************************************************************** * put a cpu back into the initial state where we watch * outOfSlaveLoop to indicate when to restart *****************************************************************/static int MipsyResetCPU(int cpuNum)   /* what about flush the cache so loadimage won't lead to inconsistencies? */{   PE[cpuNum].stalledInst = FALSE;   return 0;   /* nothing more to do: simmisc.c:ResetCPUs changes cpuStatus to cpu_not_booted,                * LaunchSlave changes it back to Running.                */}/* GET THIS OUT OF HERE */#include "sips.h"/*****************************************************************//* SIPS delivery code (actually only calls back into simmagic.c). */#define MAXSBLOCKS 128static struct SIPSBlock {    EventCallbackHdr cbhdr;    int r;             /* recipient CPU. */    int chan;          /* recipient's channel. */} sblocks[MAXSBLOCKS];static int srotor = 0;static void DeliverSIPSCallback(int cpuNum, EventCallbackHdr *E, void* arg){   struct SIPSBlock *sipsBlock = (struct SIPSBlock *)arg;   sim_sips_deliver(sipsBlock->r, sipsBlock->chan);   MipsyCheckForInterrupts(&PE[cpuNum]);   return;}static voidDeliverSIPS(int cpuNum, int chan, SimTime delay){   int i;   if (delay == 0) {      /* deliver NOW */      sim_sips_deliver(cpuNum, chan);      MipsyCheckForInterrupts(&PE[cpuNum]);      return;   }   i = srotor;   do {      if (sblocks[i].cbhdr.active == FALSE) {         sblocks[i].r            = cpuNum;         sblocks[i].chan         = chan;         EventDoCallback(cpuNum, DeliverSIPSCallback, &sblocks[i].cbhdr,                          &sblocks[i], delay);         if (i == MAXSBLOCKS-1)              srotor = 0;         else            srotor = i+1;         return;      }      if (i == MAXSBLOCKS-1)          i = 0;      else         i += 1;   } while (i != srotor);   CPUError("Too many simultaneous SIPS");}/****************************************************************** * Write a call to the system call exit on the user's stack.  Then  * jump to it *****************************************************************/static void MakeProcExit(int cpuNum){   CPUState *P = &PE[cpuNum];   PA pAddr;   VA vSP;   uint smash[4];   /* Ensure that we are not writting over a page boundary by using */   /* the beginning of the page*/     vSP = FORM_ADDR(PAGE_NUMBER(P->R[REG_SP]), 0);   if (TranslateVirtualNoSideeffect(P, vSP, &pAddr) != SUCCESS) {      CPUWarning("Can't translate address in MipsyMakeProcExit\n");      return;   }   CPUWarning("PROCexit: CPU %d smashing address %#x\n", P->myNum, vSP);   smash[0] = CIi( addiu_op, A0, G0, 0 ); /* li a0, 0 */    smash[1] = CIi( addiu_op, V0, G0, 1001 ); /* li v0, 1001 */    smash[2] = CIs( syscall_op, 0, 0, 0); /* syscall */   MemRefDebugWriteData(cpuNum, vSP, pAddr, (char *)smash, 12);   /* This trick won't work in base mode both because of this opcode */   /* because we are not flushing the data cache*/   P->nPC = vSP;   P->branchTarget = vSP + INST_SIZE;}       #ifdef MIPSY_MXS	/*	 *  Routines that copy state from Mipsy down to MXS, or from	 *  MXS back up to Mipsy.	 *	 *	These routines must only be called when MXS is in a	 *	consistent state.  The state of the processor is taken	 *	from the thread that holds the status at the graduation	 *	point.	 *	 *	When initializing MXS, the graduation thread and the	 *	thread belonging to branch node 0 start out in the	 *	same state.	 */void CopyToMXS (CPUState *P)	{	struct	s_cpu_state	*st;	int	i;	THREAD	*th;	st = P->st;	th = &st->grad;        if (P->PC+4 == P->nPC) {           th->thread_st = TH_ACTIVE;          th->pc = P->PC;        } else {          th->thread_st |= TH_BRANCH|TH_ACTIVE;          th->pc = P->PC;          th->branch_pc = P->nPC;        }#ifdef BREAKPOINT	th->debugpc = th->pc;#endif	ms_iwin_init (st);	for (i=0; i < NUM_GP_REGS; i++)           st->regs[th->regnames[i]] = P->R[i];	for (i=0; i < NUM_FP_REGS; i++)           st->regs[th->regnames[FPREG+i]] = IntReg(i^0x1);	st->regs[th->regnames[HIREG]] = P->HI;	st->regs[th->regnames[LOREG]] = P->LO;	st->regs[th->regnames[FPCTL]] = P->FCR[0];	st->regs[th->regnames[FPCTL+1]] = P->FCR[31] & (~CONDBIT);	st->regs[th->regnames[CNDREG]] = P->FCR[31] & CONDBIT;	}void CopyFromMXS (CPUState *P)	{	struct	s_cpu_state	*st;	int	i;	THREAD	*th;	st = P->st;	th = &st->grad;        if (th->thread_st & TH_BRANCH) {           /* We are in delay slot */          P->PC = th->pc;          P->nPC = th->branch_pc;        } else {          P->PC = th->pc;          P->nPC = P->PC + 4;        }	for (i=0; i < NUM_GP_REGS; i++)           P->R[i] = st->regs[th->regnames[i]];	for (i=0; i < NUM_FP_REGS; i++)           IntReg(i^0x1) = st->regs[th->regnames[FPREG+i]];	P->HI = st->regs[th->regnames[HIREG]];	P->LO = st->regs[th->regnames[LOREG]];	P->FCR[0] = st->regs[th->regnames[FPCTL]];	P->FCR[31] =		((~CONDBIT) & st->regs[th->regnames[FPCTL+1]]) |		(CONDBIT & st->regs[th->regnames[CNDREG]]);	}#endif

⌨️ 快捷键说明

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