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

📄 simos_interface.c

📁 一个用在mips体系结构中的操作系统
💻 C
📖 第 1 页 / 共 2 页
字号:
         break;      }   }   SIM_DEBUG(('d', "\n"));}/***************************************************************** * remap region support * *****************************************************************/static voidEmbraRemapInit(void){   int i;   if (!remapVec->NodeAddrInitialized) {      for (i=0; i<TOTAL_CPUS; i++) {            int m = M_FROM_CPU(i);#ifdef TORNADO         remapVec->NodeAddr[i] = (i*NUM_MEMORIES(m)/NUM_CPUS(m)) *            (MEM_SIZE(m) / NUM_CPUS(m));         CPUWarning("embra: nodeaddr for %d is %lx\n",		      i, (unsigned long)(remapVec->NodeAddr[i]));#elif defined(SIM_ORIGIN)         remapVec->NodeAddr[i] =             MEMADDR_TO_PHYS(m, SIM_MEM_ADDR(m) +                             (MCPU_FROM_CPU(i)/2) * 2 * (MEM_SIZE(m) / NUM_CPUS(m)));#else         remapVec->NodeAddr[i] =             MEMADDR_TO_PHYS(m, SIM_MEM_ADDR(m) +                             MCPU_FROM_CPU(i) * (MEM_SIZE(m) / NUM_CPUS(m)));#endif      }      remapVec->NodeAddrInitialized = 1;   }}static voidem_setremap(int cpunum, PA mask){   unsigned int cnum = (unsigned int) cpunum;   if (cnum < SIM_MAXCPUS) {      remapVec->RemapMask[cnum] = mask;      /* changing the mask might increase or decrease the remap zone.       * The simplest way to reflect this change in the mmu is to       * flush the mmu and renew it.       */      qc_renew(cnum);   } else {      CPUWarning("cpunum out of range in em_setremap");   }}static voidem_controlremap(int cpunum, int isEnabled){   unsigned int cnum = (unsigned int) cpunum;   if (cnum < SIM_MAXCPUS) {      remapVec->RemapEnable[cnum] = isEnabled;      /* the simplest way to update the mmu is to flush and renew it. */      qc_renew(cnum);   } else {      CPUWarning("cpunum out of range in em_controlremap");   }}static PAem_getnodeaddr(int cpunum){   return remapVec->NodeAddr[cpunum];}uint NearestLog2(int n){   uint pwr = 0x80000000;   while( !(pwr & n) ) {      pwr >>= 1;   }   return pwr;}/***************************************************************** * EmbraCPUVectorInit * * Assign the proper function pointers to the shared CPUVector *****************************************************************/void EmbraCPUVectorInit(void){   CPUVec.Handle_Debug_Signal  = Embra_Handle_Debug_Signal;   CPUVec.InstallMemAnnotation = EmbraInstallMemAnnotation;   CPUVec.GetRegister    = Embra_GetRegister;   CPUVec.PutRegister    = Embra_PutRegister;   CPUVec.GetMemory      = Embra_GetMemory;   CPUVec.PutMemory      = Embra_PutMemory;   CPUVec.TranslateVirtualNoSE = Embra_TranslateVirtualNoSE;   CPUVec.CycleCount     = EmbraCpuCycleCount;   CPUVec.InstrCount     = EmbraCpuInstrCount;   CPUVec.Send_Interrupt = Embra_Send_Interrupt;   CPUVec.Deliver_SIPS   = Embra_Deliver_SIPS;   CPUVec.FaultInject    = Embra_FaultInject;   CPUVec.ResetCPU       = Embra_ResetCPU;   CPUVec.CurrentCpuNum  = EmbraCurrentCpuNum;   CPUVec.CurrentPC      = EmbraCurrentPC;   memsysVec.type                 = NO_MEMSYS;   memsysVec.MemsysCmd            = 0;   memsysVec.MemsysSetRemap       = em_setremap;   memsysVec.MemsysGetNodeAddress = em_getnodeaddr;   memsysVec.MemsysControlRemap   = em_controlremap;   CPUVec.DMAInval = EmbraDMAInval;   if( embra.sequential ) {      CPUVec.singleEventQueue = 1;   } else {      CPUVec.singleEventQueue = 0;   }   CPUVec.SelectorChange    = Dump_QC_Counters;   CPUVec.DoCheckpoint      = EmbraCheckpoint;   CPUVec.ProcMakeProcExit  = EmbraMakeProcExit;   CPUVec.ExitSimulator     = EmbraExit;   CPUVec.IntrBitsChanged   = EmIntrBitsChanged;   CPUVec.FirewallChange    = EmFirewallChange;   CPUVec.MigRepStart       = MigRepStart;   CPUVec.MigRepEnd         = MigRepEnd;   CPUVec.useMemRef         = FALSE;}/***************************************************************** * Procexit Support *****************************************************************//****************************************************************** * Write a call to the system call exit on the user's stack.  Then  * jump to it *****************************************************************//* Macros to cons up instructions ( ConsInstruction<instruction_type>) */#define CIi(opCode, rt, rs, immed) ((int)\((opCode) << 26 | (rs) << 21 | (rt) << 16 | ((immed) & 0xffff ) ) )#define CIs(funct, rd, rs, rt) ((int)\(spec_op << 26 | (rs) << 21 | (rt) << 16 | (rd) << 11 | funct) )int EmbraMakeProcessExit(int cpuNum){   EmbraState *P = &EMP[cpuNum];   uint *pPtr;   VA vSP;   if (CURRENT_MODE(P) != USER_MODE ){      CPUWarning("%d %llu Tyring to make pid exit\n",                 cpuNum, EmbraCpuCycleCount(cpuNum));      return 0;   }     /* Insure 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 );   pPtr = (uint*) non_excepting_tv( cpuNum, vSP );   if( !pPtr ) {      CPUWarning("Failure to translate stack address in MakeProcExit\n");      return 0;   }   CPUWarning("PROCexit: CPU %d smashing address %#x\n", P->myNum, vSP);   *pPtr++ = CIi( addiu_op, A0, G0, 0 ); /* li a0, 0 */   *pPtr++ = CIi( addiu_op, V0, G0, 1001 ); /* li v0, 1001 */   /* This trick won't work in base mode both because of this opcode */   /* because we are not flushing the data cache*/   *pPtr++ = CIs( syscall_op, 0, 0, 0); /* syscall */   P->PC = vSP;   return 1;}/***************************************************************** * fault support * */static EventCallbackHdr DeadCpuCycleMaintenance[SIM_MAXCPUS];static int              lowest_live_cpu = 0;static uint             deadcpus        = 0;#define DEADCPUCYCLEINTERVAL   10000intEmbraCurrentCpuNum(void) {   int cpuNum =  curEmp - &EMP[0];   ASSERT( cpuNum == curEmp->myNum);   ASSERT( cpuNum >= 0 && cpuNum < TOTAL_CPUS);   return cpuNum;}VAEmbraCurrentPC(int cpuNum) {   return EMP[cpuNum].PC;}static voidEmbra_FaultInject(int cpuno, faultTypeEnum faultType){   switch (faultType) {    case SIMFAULT_HALT:       /* do something lower-level (not the right thing, eventually) */       ProcRemove( cpuno );       /* the problem with ProcRemove is that the cycle counter of        * the failed cpu stops incrementing, so events driven off of        * that (notably the timer interrupt) cause an infinite loop        * when the time on that cpu gets sufficiently far behind the        * time on the rest of the system.  We need to set up a periodic        * callback on some other cpu that increments the cycle count        * on the failed cpu.        *        * We use the lowest_live_cpu to do this.  If it is the lowest        * live cpu itself that has failed, need to move any previous        * cycle maintenance callbacks to the new lowest live cpu.        */       if (cpuno == lowest_live_cpu) {          int i;          lowest_live_cpu = -1;          for (i=0; i<TOTAL_CPUS; i++) {             if (i == cpuno) continue;             if (deadcpus & (1<<i)) continue;             lowest_live_cpu = i;             break;          }          ASSERT(lowest_live_cpu != -1);  /* should be at least 1 live one*/          for (i=0; i<TOTAL_CPUS; i++) {             if (deadcpus & (1<<i)) {                SimTime delta =  DeadCpuCycleMaintenance[i].when                                  - EmbraCpuCycleCount(cpuno);                EventCallbackRemove(&DeadCpuCycleMaintenance[i]);                EventDoCallback(lowest_live_cpu, DeadCpuCycleInc,                                 &DeadCpuCycleMaintenance[i],                                 (void*) i, delta);             }          }       }       deadcpus |= (1 << cpuno);       EventDoCallback(lowest_live_cpu, DeadCpuCycleInc,                        &DeadCpuCycleMaintenance[cpuno], (void*) cpuno,                       DEADCPUCYCLEINTERVAL);       break;   default:       CPUWarning("Unknown fault (%d) ignored\n", faultType);       break;   }}static void DeadCpuCycleInc(int cpuNum, EventCallbackHdr *E, void* arg){   int deadcpu = (int) arg;   EMP[deadcpu].cycleCount += DEADCPUCYCLEINTERVAL;   EventDoCallback(lowest_live_cpu, DeadCpuCycleInc,                    &DeadCpuCycleMaintenance[deadcpu], (void*) deadcpu,                   DEADCPUCYCLEINTERVAL);   }int Embra_ResetCPU(int cpuNum){   /* TBD: clear cached state about interrupts, etc */   /* by calling putregister for the pc and RA, we trigger normal side-    * effect detection which prevents us from returning to bad code    * in the TC    */   Embra_PutRegister(cpuNum, PC_REGNUM, (uint)continue_run_without_chaining);   Embra_PutRegister(cpuNum, 31,        (uint)continue_run_without_chaining);   EMP[cpuNum].jumpPC  = (uint)continue_run_without_chaining;   return 0;}

⌨️ 快捷键说明

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