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

📄 simos_interface.c

📁 一个用在mips体系结构中的操作系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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:30:58 $ *****************************************************************/#include <stdio.h>#include <bstring.h>#include <string.h>#include <sys/types.h>#include <unistd.h>#include <sys/types.h>#include <sys/prctl.h>#include <sys/time.h>#include <limits.h>#include <sys/mman.h>#include "simtypes.h"#include "simutil.h"#include "simmisc.h"#include "firewall.h"#include "simmagic.h"#include "cpu_interface.h"#include "gdb_interface.h"#include "simstats.h"#include "embra.h"#include "driver.h"#include "cp0.h"#include "cache.h"#include "clock.h"#include "qc.h"#include "mem_control.h"#include "main_run.h"#include "stats.h"#include "debug.h"#include "directory.h"#include "translator.h"#include "registry.h"#include "embra_interface.h"#include "hw_events.h"#include "tc.h"#include "params.h"#include "embra.h"#include "../../memsystems/memsys.h"/* Local Functions */static void Embra_FaultInject(int cpuNum, faultTypeEnum faultType);static void DeadCpuCycleInc(int cpuNum, EventCallbackHdr *E, void* arg);static void EmbraRemapInit(void);int Embra_ResetCPU(int cpuNum);int EmbraCurrentCpuNum(void);VA  EmbraCurrentPC(int cpuNum);extern CPUState *SBase;extern SimTime embraLastCount[SIM_MAXCPUS];void EmbraTclInit(Tcl_Interp *interp){   ParamRegister("PARAM(CPU.Embra.MPinUP)", (char *)&embra.MPinUP, PARAM_BOOLEAN);   ParamRegister("PARAM(CPU.EmbraPage.UseETLB)", (char *)&embra.useETLB, PARAM_BOOLEAN);   ParamRegister("PARAM(CPU.EmbraCache.UseVQC)", (char *)&embra.useVQC, PARAM_BOOLEAN);   ParamRegister("PARAM(CPU.Embra.DisableStat)", (char *)&embra.stats, PARAM_BOOLEAN);   ParamRegister("PARAM(CPU.Embra.InlineQC)", (char *) &embra.inlineQC, PARAM_BOOLEAN);   ParamRegister("PARAM(CPU.Embra.TimeQuantum)", (char *)&embra.timeQuantum, PARAM_INT);   ParamRegister("PARAM(CPU.Embra.PeriodAnnInterval)",               (char *)&embra.periodicAnnInterval, PARAM_INT);   ParamRegister("PARAM(CPU.Embra.StatInterval)",               (char *)&embra.statInterval, PARAM_INT);   ParamRegister("PARAM(CPU.Embra.MiscCheckInterval)",               (char *)&embra.miscCheckInterval, PARAM_INT);   ParamRegister("PARAM(CPU.Embra.SeparateMMUs)",                 (char *)&embra.separateMMUs,PARAM_BOOLEAN);}/***************************************************************** * EmbraEnter * * This is the main interface into setting up Embra 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. *****************************************************************/voidEmbraEnter(int swtch){   int i;      EMP = SBase;      /* If we are uniprocessor, don't do MPinUP */   if (TOTAL_CPUS == 1) {      embra.MPinUP = 0;      embra.sequential = 1;      embra.parallel   = 0;   } else if (embra.MPinUP) {      embra.sequential = 1;      embra.parallel   = 0;   } else {      ASSERT(0);      embra.sequential = 0;      embra.parallel   = 1;   }   embra.emode = sim_misc.myCPUType;   ASSERT( embra.emode ==EMBRA_PAGE || embra.emode==EMBRA_CACHE);   if (embra.emode==EMBRA_CACHE) {      if (SCACHE_ASSOC!=1) {         CPUError("EMBRA_CACHE requires a direct-mapped cache. set  PARAM(CACHE.2Level.L2Assoc) 1 \n");      }   }#ifdef EMBRA_USE_QC64   embra.inlineQC = FALSE; /* Doesn't work with 64bit mode */#endif   /* Load these on each entry */   EmbraCPUVectorInit();   EmbraDebugInit();   /* enable reinstating callbacks */   InstallTimers();	/* tell simmagic to start timers */   InstallPoller();	/* add poll callback to eventqueue */   EmbraRemapInit();	/* initialize remap array */      simosCPUType = embra.emode;    Embra_Init(0, swtch);   Clear_Translation_State( TCFLUSH_ALL);   if (!swtch) {     /* this is not a switch from another simulator */     for (i=0;i<TOTAL_CPUS;i++) {       curEmp = &EMP[i];       embraLastCount[i] = 0ll;       AnnExec(AnnFind("simos", "enter"));     }   }   /* if switching from MIPSY, check for not_booted/faulted cpus */   if (swtch) {      for (i = 0; i < TOTAL_CPUS; i++) {         if (SBase[i].cpuStatus == cpu_not_booted) {            Embra_ResetCPU(i);         }      }   }   EmbraTimeDiff();   HWEventsLateInit();   Embra_Run(0, 1);   /* Will we return from here? */   ASSERT(0);   }/***************************************************************** * EmbraExit * *****************************************************************/voidEmbraExit(CPUType new_cpu){   extern struct timeval run_start; /* driver.c */   extern struct timeval run_end; /* driver.c */   if (new_cpu != NO_CPU) {      CPUWarning("Exit embra into %s\n", simName[new_cpu]);   }   sim_misc.enterThisCPU = new_cpu;   if (embra.sequential) {      int cpu;            int annType = EmbraAnnType();      EmbraClosePeriodicCallbacks();      /*       * XXX this is key. If we have a post-pc annotation,       * XXX we better advance the pc.       */      if (annType==ANNFM_PC_TYPE) {	CPUWarning("Embra: switching on PC annotation. Advancing PC \n");	EMP[CPUVec.CurrentCpuNum()].PC += INST_SIZE;      }      /* Switching in delay slot doesn't work. */      ASSERT ((new_cpu == NO_CPU) || !IN_BD(EMP[CPUVec.CurrentCpuNum()].PC));      /*       * sync the clocks or mipsy will get confused.        */      EmbraFixCycleCounts();      EventProcess(-1,EMP[0].cycleCount);   } else {       ASSERT (0);   }   Em_Tlb_Clear(0);   AnnExec(AnnFind("simos","periodic"));   if ((new_cpu == NO_CPU) || (new_cpu == BASE)) {      AnnExec(AnnFind("simos", "exit"));   }   Print_Recent_Stats(0);   gettimeofday( &run_end );   CPUPrint("EmbraRunTime %u sec for %10lld cycles\n",             run_end.tv_sec - run_start.tv_sec ,            (uint64)EmbraCpuCycleCount(0));      SimulatorSwitch(embra.emode, new_cpu);}/***************************************************************** * This is called from simhd DMA engine  *****************************************************************/voidEmbraDMAInval(int machine, PA* k0list){  int cpu;  SIM_DEBUG(('d', "DMA Clear "));   while( *k0list ) {      switch( embra.emode ) {      case EMBRA_CACHE: {         /* Invalidate caches */         PA pa;         for( pa = K0_TO_PHYS(*k0list); pa < K0_TO_PHYS(*k0list) + DEFAULT_PAGESZ;                                        pa += SCACHE_LINE_SIZE ) {            if( embra.sequential ) {               /* Invalidate from everybodies cache */                              unsigned dir_entry;               if (NUM_CPUS(machine)>1) {                   dir_entry = directory[machine][ADDR2SLINE(pa)];               } else {                   dir_entry = 1<<FIRST_CPU(machine);               }               Cache_Clobber( machine, TOTAL_CPUS, pa, dir_entry, MEM_D_EXCLUSIVE );            } else {               Dir_Entry new_dir_entry =                   Directory_Lock(CURR_CPU, pa, 0/*VA*/, MEM_D_EXCLUSIVE);               /* Invalidate from everybodies cache */               Cache_Clobber( machine, TOTAL_CPUS, pa, (~((Dir_Entry)0)) >> (32 - TOTAL_CPUS),                              MEM_D_EXCLUSIVE );               Directory_Free(CURR_CPU, pa, new_dir_entry);            }         }         /* Note that this is being called via the backdoor, so on the */         /* stack is mem_translate.  Since that routine returns via */         /* ReenterTC..., it is acceptable to call icache_co... without */         /* checkint the return code and doing a ReenterTC... */	 for (cpu = 0; cpu < TOTAL_CPUS; cpu++)            EmbraTCCoherenceCheck(cpu, 0,(PA)*k0list, (PA)*k0list+DEFAULT_PAGESZ);         k0list++;         break;      }      case EMBRA_PAGE:         SIM_DEBUG(('d', "0x%08x ", *k0list));         /* Note that this is being called via the backdoor, so on the */         /* stack is mem_translate.  Since that routine returns via */         /* ReenterTC..., it is acceptable to call icache_co... without */         /* checkint the return code and doing a ReenterTC... */	 /*xxx This MUST be called in embra page mode to invalidate any	  * stale translations which might still linger in the TC (the real	  * Icache will also be flushed).	  *xxx Also note that ALL CPU caches must be invalidated!	  */	 for (cpu = 0; cpu < TOTAL_CPUS; cpu++)	   EmbraTCCoherenceCheck(cpu, 0,(PA)*k0list, (PA)*k0list+DEFAULT_PAGESZ);         k0list++;

⌨️ 快捷键说明

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