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

📄 cpu.c

📁 一个用在mips体系结构中的操作系统
💻 C
📖 第 1 页 / 共 4 页
字号:
 * Called from the main execution loop each time an instruction  * is needed. The first argument is the PC value to read from.  * "backdoor" is a way of avoiding going through the cache * and memory system to directly access something in our real-life * address space (mipsy or simos). This procedure better be as fast as * possible!!! The Result returned is just a way of telling the * processor whether it has to stall or not (i.e. if there was an icache * miss.  *****************************************************************/static ResultReadInstruction(VA vAddr, Inst *inst)        {   Result ret;   PA pAddr;   int64 bdoorRetval = 0;    uint tlbFlavor = TLB_IFETCH|TLB_READING;   void *bdoorAddr = 0;   if (TranslateVirtual(P, vAddr, &pAddr, &tlbFlavor, &bdoorAddr) != SUCCESS)      return FAILURE;   if (!tlbFlavor) {      P->pcVPNcache = PAGE_NUMBER(vAddr);      P->pcPaddrcache = FORM_ADDR(PAGE_NUMBER(pAddr), 0);      if (SKIP_CACHES(P)) {         *inst =*(Inst *)HOST_DATA_ADDR(vAddr, pAddr, P->myNum);         return SUCCESS;      }      ret =  MemRefReadInst(P->myNum, vAddr, pAddr, inst);      if (ret != SUCCESS) {         if ((ret == STALL) || (ret == FAILURE)) {            P->stalledInst = 0;            P->cpuStatus = cpu_stalled;         } else if (ret == BUSERROR) {            RECORD_EXCEPTION(P, EXC_IBE, E_VEC, vAddr,                              P->CP0[C0_TLBHI], P->CP0[C0_CTXT], P->CP0[C0_XCTXT]);         } else {            CPUWarning("Unknown return value (%d) from ReadICache\n", ret);         }      }      /*       * The processor can have been idled as a consequence of an annotations       * For now, we can implement this by checking for the cpuStatus       */      if (P->cpuStatus == cpu_idle) {         P->stalledInst = 0;         ret = FAILURE;      }       return ret;   } else {#ifndef SOLO      /* this might be one of three things:       *    the boot prom (provided by flashlite)       *    the prom slave loop (SimOS magic)       *    a backdoor call       */      if (tlbFlavor & TLB_UNCACHED) {         /* executing instructions from the prom provided by flashlite          * or simmagic          */         return UncachedRead(vAddr, pAddr, inst, WORD_SZ);      }       /* A backdoor  call. Execute it on the real CPU. This */      /* assumes that all backdoor calls take less than 4 */      /* arguments. */      ret = MemRefSync(P->myNum);      if (ret != SUCCESS) {         /* Make sure all cached and uncached writes are flushed          * out of buffers before doing a backdoor call. This           * is needed for calls that start I/O.          */         return FAILURE;      }      SIM_DEBUG(('b', "MIPSY:CPU %d: Backdoor call at PC %#x PA %#x RA %#x\n",                  P->myNum, P->PC, pAddr, P->R[31]));      if (tlbFlavor == TLB_BDOOR_DATA) {         *inst = *(Inst *)bdoorAddr;      } else if (tlbFlavor == TLB_BDOOR_FUNC) {         Result returnFlag;                  returnFlag = ((Result (*)(int, uint, uint, unsigned char *))bdoorAddr)            (P->myNum, vAddr, BDOOR_LOAD_WORD, (unsigned char *)inst);         if (returnFlag == SUCCESS) {            return SUCCESS;         } else if (returnFlag == BUSERROR) {            RECORD_EXCEPTION(P, EXC_IBE, E_VEC, vAddr,                              P->CP0[C0_TLBHI], P->CP0[C0_CTXT], P->CP0[C0_XCTXT]);            return BUSERROR;         } else {            CPUError("Unknown result type: 0x%x\n", returnFlag);         }      } else {         ASSERT(tlbFlavor == TLB_BDOOR_FUNC_COMPAT);         bdoorRetval = ((int64 (*)(int,int,int,int))                        (bdoorAddr))(P->R[4],P->R[5],P->R[6],P->R[7]);         P->R[2] = bdoorRetval >> 32;         P->R[3] = bdoorRetval & 0xffffffff;         *inst = 0; /* NOP */         P->nPC = P->R[31];      }      return SUCCESS;#endif#ifdef SOLO      /* Solo Mipsy has back door calls that need to be handled */      /* We may need to know our cpu number at this time */      soloCPUNum = P->myNum;      bdoorRetval = ((int64 (*)(int,int,int,int))P->PC)         (P->R[4],P->R[5],P->R[6],P->R[7]);      P->R[2] = bdoorRetval >> 32;      P->R[3] = bdoorRetval & 0xffffffff;      P->nPC = P->R[31];      *inst = 0; /* NOP */      STATS_INC(P->myNum, numBdoorInsts, 1);      return SUCCESS;#endif   }}/**************************************************************** * MipsyReadMem *  * Common routine used by the CPU to read memory. *****************************************************************/ResultMipsyReadMem(VA vAddr, void *data, RefSize size, RefFlavor flavor){   Result ret;   PA pAddr;   uint tlbFlavor = TLB_READING;   void *bdoorAddr = 0;      ret = TranslateVirtual(P, vAddr, &pAddr, &tlbFlavor, &bdoorAddr);      if (ret == SUCCESS) {       if (!tlbFlavor) {         if (flavor & LL_FLAVOR) {             P->LLAddr =  pAddr & ~(SCACHE_LINE_SIZE-1);            if (UNCACHED_LL_SC) {               LLAddrs[P->myNum] = pAddr & ~(SCACHE_LINE_SIZE-1);            }         }          if (SKIP_CACHES(P)) {            switch (size) {            case BYTE_SZ:               *(byte *)data = *(byte *)HOST_DATA_ADDR(vAddr, pAddr, P->myNum);               break;            case HALF_SZ:               *(short *)data = BE2HO_2(*(short *)HOST_DATA_ADDR(vAddr, pAddr, P->myNum));               break;            case WORD_SZ:               *(uint *)data = BE2HO_4(*(uint *)HOST_DATA_ADDR(vAddr, pAddr, P->myNum));               break;            case DOUBLE_SZ:               *(int64 *)data =BE2HO_8(*(int64 *)HOST_DATA_ADDR(vAddr, pAddr, P->myNum));               break;            default:               CPUError("Bad size in MipsyReadMem\n");               ASSERT(0);            }            return SUCCESS;         }                  /* Go through the cache interface */         switch (size) {         case BYTE_SZ:            ret = MemRefReadData(P->myNum, vAddr, pAddr, data, BYTE_SZ, NO_FLAVOR);            break;         case HALF_SZ:            ret = MemRefReadData(P->myNum, vAddr, pAddr, data, HALF_SZ, NO_FLAVOR);            *(short *)data = BE2HO_2(*(short *)data);            break;         case WORD_SZ:            ret = MemRefReadData(P->myNum, vAddr, pAddr, data, WORD_SZ, flavor);            *(uint *)data = BE2HO_4(*(uint *)data);            break;         case DOUBLE_SZ:            ret = MemRefReadData(P->myNum, vAddr, pAddr, data, DOUBLE_SZ, flavor);            *(int64 *)data = BE2HO_8(*(int64 *)data);            break;         default:            CPUError("Bad size in MipsyReadMem\n");            ASSERT(0);         }         if (ret != SUCCESS) {             if ((ret == STALL) || (ret == FAILURE)) {               P->cpuStatus = cpu_stalled;            } else if (ret == BUSERROR) {               RECORD_EXCEPTION(P,EXC_DBE, E_VEC, vAddr,                                 P->CP0[C0_TLBHI], P->CP0[C0_CTXT], P->CP0[C0_XCTXT]);               return ret;            } else {               CPUWarning("Bad return value (%d) from MemRefReadData\n", ret);            }         } else {            /* We hit in the DCACHE */            CHECK_LD_ANN(vAddr, pAddr);            STATS_INC(P->myNum, dReads, 1);         }      } else {         if (tlbFlavor & TLB_UNCACHED) {            ret = UncachedRead(vAddr, pAddr, data, size);#ifdef HWBCOPY            if ((size == DOUBLE_SZ) && (tlbFlavor == TLB_MSG_SPACE)) ret = SUCCESS;#endif         } else if (tlbFlavor == TLB_BDOOR_DATA) {            STATS_INC(P->myNum, numBdoorInsts, 1);            switch (size) {            case BYTE_SZ:               *(byte *)data = *(byte *)bdoorAddr;               break;            case HALF_SZ:               *(short *)data = *(short *)bdoorAddr;               break;            case WORD_SZ:               *(uint *)data = *(uint *)pAddr;               break;            case DOUBLE_SZ:               *(uint64 *)data = *(uint64 *)bdoorAddr;               break;            default:               CPUError("Bad size in MipsyReadMem\n");               ASSERT(0);            }            return SUCCESS;         } else {            Result returnFlag;                        ASSERT(tlbFlavor == TLB_BDOOR_FUNC);            switch (size) {            case BYTE_SZ:               returnFlag = ((Result (*)(int, uint, uint, unsigned char *))bdoorAddr)                  (P->myNum, vAddr, BDOOR_LOAD_BYTE, data);               break;            case HALF_SZ:               returnFlag = ((Result (*)(int, uint, uint, short *))bdoorAddr)                  (P->myNum, vAddr, BDOOR_LOAD_HALF, data);               break;            case WORD_SZ:               returnFlag = ((Result (*)(int, uint, uint, int*))bdoorAddr)                  (P->myNum, vAddr, BDOOR_LOAD_WORD, data);               break;            case DOUBLE_SZ:               returnFlag = ((Result (*)(int, uint, uint, uint64 *))bdoorAddr)                  (P->myNum, vAddr, BDOOR_LOAD_DOUBLE, data);               break;            default:               CPUError("Bad size in MipsyReadMem\n");               ASSERT(0);            }                        if (returnFlag == SUCCESS) {               return SUCCESS;            } else if (returnFlag == BUSERROR) {               RECORD_EXCEPTION(P, EXC_DBE, E_VEC, vAddr,                                 P->CP0[C0_TLBHI], P->CP0[C0_CTXT], P->CP0[C0_XCTXT]);               return BUSERROR;            } else {               CPUError("Unknown result type: 0x%x\n", returnFlag);            }         }      }   }   return ret;}/* Used by solo */ResultSoloReadByte(int cpuNum, VA vAddr, char *data){   return MipsyReadMem(vAddr, (void *)data, BYTE_SZ, NO_FLAVOR);}/**************************************************************** * MipsyWriteMem *  * Common routine used by the CPU to write memory. *****************************************************************/ResultMipsyWriteMem(VA vAddr, void *data, RefSize size, RefFlavor flavor){   Result ret;   PA pAddr;   uint tlbFlavor = TLB_WRITING;   void *bdoorAddr = 0;   if (TranslateVirtual(P, vAddr, &pAddr, &tlbFlavor, &bdoorAddr) != SUCCESS) {      return FAILURE;   }   if (flavor == SC_FLAVOR) {      if (!P->LLbit)         return SCFAILURE;   }   if (!tlbFlavor) {      /* Special code to handle LL/SC when caches are inactive */      if (UNCACHED_LL_SC) {         if (numLLactive) {            int cpu;            PA matchAddr = pAddr & ~(SCACHE_LINE_SIZE-1);            if (P->LLbit) {               P->LLbit = 0;               LLAddrs[P->myNum] = (PA) -1;               numLLactive--;            }            for (cpu = 0; cpu < TOTAL_CPUS; cpu++) {               if (LLAddrs[cpu] == matchAddr) {                  PE[cpu].LLbit = 0;                  LLAddrs[cpu] = (PA) -1;                  numLLactive--;               }            }         }      }      if (SKIP_CACHES(P)) {         switch (size) {         case BYTE_SZ:            *(byte *)HOST_DATA_ADDR(vAddr, pAddr, P->myNum)   = *(byte *)data;            break;         case HALF_SZ:            *(short *)HOST_DATA_ADDR(vAddr, pAddr, P->myNum)  = HO2BE_2(*(short *)data);            break;         case WORD_SZ:            *(uint *)HOST_DATA_ADDR(vAddr, pAddr, P->myNum)   = HO2BE_4(*(uint *)data);            break;         case DOUBLE_SZ:            *(uint64 *)HOST_DATA_ADDR(vAddr, pAddr, P->myNum) = HO2BE_8(*(uint64 *)data);            break;         default:            ASSERT(0);         }         return SUCCESS;      }            /* Normal path through the cache interface. */      switch (size) {      case BYTE_SZ:         ret = MemRefWriteData(P->myNum, vAddr, pAddr,                                *(byte *)data, BYTE_SZ, NO_FLAVOR);         break;      case HALF_SZ:         ret =  MemRefWriteData(P->myNum, vAddr, pAddr,                                HO2BE_2(*(short *)data), HALF_SZ, NO_FLAVOR);         break;      case WORD_SZ:         ret = MemRefWriteData(P->myNum, vAddr, pAddr,                                HO2BE_4(*(uint *)data), WORD_SZ, flavor);          break;      case DOUBLE_SZ:         ret =  MemRefWriteData(P->myNum, vAddr, pAddr,                                 HO2BE_8(*(uint64 *)data), DOUBLE_SZ, flavor);         break;      default:         ASSERT(0);      }      if (ret != SUCCESS) {          if ((ret == STALL) || (ret == FAILURE)) {            P->cpuStatus = cpu_stalled;         } else if (ret == BUSERROR) {            RECORD_EXCEPTION(P, EXC_DBE, E_VEC, vAddr,                              P->CP0[C0_TLBHI], P->CP0[C0_CTXT], P->CP0[C0_XCTXT]) ;            return ret;         } else if (ret == SCFAILURE) {            /* This is OK, isn't it? */         } else {             CPUWarning("Bad return value (%d) from MemRefWriteData\n", ret);         }      } else {         CHECK_ST_ANN(vAddr, pAddr);         STATS_INC(P->myNum, dWrites, 1);      }      return ret;   }   if (tlbFlavor & TLB_UNCACHED) {      return UncachedWrite(vAddr, pAddr, data, size, (bool)tlbFlavor & TLB_ACCELERATED);#ifdef HWBCOPY   } else if (tlbFlavor & TLB_MSG_SPACE) {      return SUCCESS;#endif   } else if (tlbFlavor == TLB_BDOOR_DATA) { #ifndef SOLO      ASSERT(0);#endif         switch (size) {         case BYTE_SZ:            *(byte *)bdoorAddr = *(byte *)data;            break;         case HALF_SZ:            *(short *)bdoorAddr = *(short *)data;            break;         case WORD_SZ:            *(uint *)pAddr = *(uint *)data;            break;         case DOUBLE_SZ:#ifdef SOLO            *(uint64 *)pAddr = *(uint64 *)data;#else            *(uint64 *)bdoorAddr = *(uint64 *)data;#endif            break;         default:            ASSERT(0);         }      return SUCCESS;   } else {      Result returnFlag;

⌨️ 快捷键说明

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