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

📄 simmagic.c

📁 一个用在mips体系结构中的操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:
/**************************************************************************** * * SIPS support * ****************************************************************************/struct { /* SIPS state for each MAGIC */  MagicRegister stall;   /* shadow of STALLOSPC PPR */  int           stalled; /* did an access stall on this OSPC? */  int           st_lo;   /* stalled on OSPC_LO? */  VA            st_va;   /* stalled VA (could actually be computed) */} sst[SIM_MAXCPUS];static voidsips_interrupt(int n, int lo, int on){  /* suppress the interrupt if a cache miss is already stalled   * on this OSPC.   */  if (on && sst[n].stalled && sst[n].st_lo == lo) {    /* unstall access that stalled on this OSPC */    CacheCmdUnstall(n, sst[n].st_va);#if (DEBUG_MAGIC == 1)    LogEntry("sips_interrupt", n, "lo=%d on=%d SUPPRESSED\n", lo, on);#endif    return;  }  /* XXX DT not true in general!     ASSERT(!sst[n].stalled);     */#if (DEBUG_MAGIC == 1)  LogEntry("sips_interrupt", n, "lo=%d on=%d\n", lo, on);#endif  if (on) RaiseIBit(n, lo ? DEV_IEC_OSPC_LO : DEV_IEC_OSPC_HI);  else    ClearIBit(n, lo ? DEV_IEC_OSPC_LO : DEV_IEC_OSPC_HI);}/* NOTE ON OSPC ACCESSES: * * In the real machine, OSPC accesses are done through a distinct * (cacheable noncoherent) address space. Lacking enough address bits in * the 32bit SimOS version, we have squeezed in the OSPC area in the * second page of KSEG0. The various simulators use different mechanisms for * accessing this area: * *  - MIPSY contains a hack in CacheCmdDone. This routine is called *    by the memory system when an access completes; in turn, it calls *    into sima_magic_OSPC_access below, which may either complete *    the access right away (if the data is available), or delay the *    access (and call the given continuation later) if we stall on *    this OSPC read. * *  - EMBRA cannot go through the same mechanism, since having all *    Embra memory accesses go through a function would defeat the *    efficiency goals of Embra. Hence, Embra special-cases the page *    in KSEG0 that maps to OSPC's and treats access to this page like *    backdoor accesses, which will go through OSPC_access (registered *    in the backdoor). */intsim_magic_OSPC_access(int cpuNum, uint VA, byte *data){  int            err;  int            stall = 0;  MagicRegister  errval, okval;  MagicRegister* dr = (MagicRegister*)data;  if (USE_MAGIC()) return 0; /* Flashlite */  /* read the data -- for now, this is only SIPS data */  if (VA >= (__MAGIC_OSPC_BASE + MAGIC_OSPC_LO_OFFS) &&      VA <  (__MAGIC_OSPC_BASE + MAGIC_OSPC_LO_OFFS + MAGIC_OSPC_SIZE)) {    errval = MAGIC_OSPC_LO_NONE;    okval  = MAGIC_OSPC_LO_SIPSREQ;    err = sim_sips_get(cpuNum, 1, data);    if (sst[cpuNum].stall == (MagicRegister)DEV_IEC_OSPC_LO && err != 0) {      stall = 1;    }  } else    if (VA >= (__MAGIC_OSPC_BASE + MAGIC_OSPC_HI_OFFS) &&	VA <  (__MAGIC_OSPC_BASE + MAGIC_OSPC_HI_OFFS + MAGIC_OSPC_SIZE)) {      okval  = MAGIC_OSPC_HI_SIPSREPLY;      errval = MAGIC_OSPC_HI_NONE;      err = sim_sips_get(cpuNum, 0, data);      if (sst[cpuNum].stall == (MagicRegister)DEV_IEC_OSPC_HI && err != 0) {	stall = 1;      }  } else {    /* access to some other location -- ignore */    return 0;  }  /* SIPS status */  *dr = ( ((*dr) & ~MAGIC_OSPC_OPCODE_MASK) |	  (((MagicRegister)(err ? errval : okval)) << MAGIC_OSPC_OPCODE_OFFS) );#if (DEBUG_MAGIC == 1)  LogEntry("OSPC_access", cpuNum, "delay=%d\n",	   stall ? (CPU_CLOCK * MAGIC_OSPC_TIMEOUT_US) : 0);#endif  return stall ? (CPU_CLOCK * MAGIC_OSPC_TIMEOUT_US) : 0;}voidsim_magic_OSPC_stalled(int cpuNum, VA va, int stalled){#if (DEBUG_MAGIC == 1)  LogEntry("sim_magic_OSPC_stalled", cpuNum, "va=0x%llx st=%d\n",	   (uint64)va, stalled);#endif  if (stalled) {    /* access has stalled */    ASSERT(!sst[cpuNum].stalled);    sst[cpuNum].stalled = 1;    sst[cpuNum].st_va   = va;    sst[cpuNum].st_lo   = (va >= (__MAGIC_OSPC_BASE + MAGIC_OSPC_LO_OFFS)    &&			   va <  (__MAGIC_OSPC_BASE + MAGIC_OSPC_LO_OFFS + 				  MAGIC_OSPC_SIZE));  } else {    /* stalled access has timed out. Unstall */    ASSERT(sst[cpuNum].stalled);    ASSERT(sst[cpuNum].st_va == va);    ASSERT(sst[cpuNum].st_lo == (va >= (__MAGIC_OSPC_BASE+MAGIC_OSPC_LO_OFFS)&&				 va <  (__MAGIC_OSPC_BASE+MAGIC_OSPC_LO_OFFS+ 					MAGIC_OSPC_SIZE)));    sst[cpuNum].stalled = 0;    sst[cpuNum].stall   = (MagicRegister)0;  }}/**************************************************************************** * * PPR emulation * ****************************************************************************/#define MAX_PPR    0x40     /* max. number of PPR's */#define PPR_NODE(va) (((va)>>__MAGIC_NODE_OFFS) & \		      ((1 << __MAGIC_NODE_BITS) - 1))#define PPR_REG(va)  (((va)>>__MAGIC_REG_OFFS) & \		      ((1 << __MAGIC_REG_BITS) - 1))static MagicRegisternode_config(int cell, int realCPU){  unsigned int npc, first, cpu;  if (inCellMode) {     ASSERT((NUM_CPUS(0)/NUM_CELLS(0))*NUM_CELLS(0) == NUM_CPUS(0));     cpu = realCPU;     npc = NUM_CPUS(0)/NUM_CELLS(0);     first = cell * npc;  } else {     ASSERT((cell == 0) && (NUM_CELLS(0) == 1));     cpu = MCPU_FROM_CPU(realCPU);     npc = NUM_CPUS(M_FROM_CPU(realCPU));     first = 0;  }  ASSERT(((((MagicRegister)cpu) << MAGIC_NODECONFIG_THISNODE_OFFS)	 & ~MAGIC_NODECONFIG_THISNODE_MASK) == 0LL);  ASSERT(((((MagicRegister)first) << MAGIC_NODECONFIG_FIRSTNODE_OFFS)	 & ~MAGIC_NODECONFIG_FIRSTNODE_MASK) == 0LL);  ASSERT(((((MagicRegister)npc) << MAGIC_NODECONFIG_NODESINCELL_OFFS)	 & ~MAGIC_NODECONFIG_NODESINCELL_MASK) == 0LL);  ASSERT(((((MagicRegister)cell) << MAGIC_NODECONFIG_THISCELL_OFFS)	 & ~MAGIC_NODECONFIG_THISCELL_MASK) == 0LL);  ASSERT(((((MagicRegister)NUM_CELLS(0)) << MAGIC_NODECONFIG_NCELLS_OFFS)	 & ~MAGIC_NODECONFIG_NCELLS_MASK) == 0LL);  return (((MagicRegister)cpu) << MAGIC_NODECONFIG_THISNODE_OFFS)      |         (((MagicRegister)first) << MAGIC_NODECONFIG_FIRSTNODE_OFFS)   |         (((MagicRegister)npc) << MAGIC_NODECONFIG_NODESINCELL_OFFS)   |         (((MagicRegister)cell) << MAGIC_NODECONFIG_THISCELL_OFFS)     |         (((MagicRegister)NUM_CELLS(0)) << MAGIC_NODECONFIG_NCELLS_OFFS);}static MagicRegisteraddr_config(int n){  unsigned int machNo = M_FROM_CPU(n);  unsigned int pages = MEM_SIZE(machNo) / SIM_PAGE_SIZE / NUM_CPUS(machNo);  unsigned int nnb   = __MAGIC_NODE_BITS; /* node_number_bits */  unsigned int masb  = 0; /* MAGIC address space bits */  ASSERT((MEM_SIZE(machNo)/NUM_CPUS(machNo))*NUM_CPUS(machNo)         == MEM_SIZE(machNo));  ASSERT(((((MagicRegister)pages) << MAGIC_ADDRCONFIG_PAGES_OFFS)	 & ~MAGIC_ADDRCONFIG_PAGES_MASK) == 0LL);  ASSERT(((((MagicRegister)nnb) << MAGIC_ADDRCONFIG_NNBITS_OFFS)	 & ~MAGIC_ADDRCONFIG_NNBITS_MASK) == 0LL);  ASSERT(((((MagicRegister)masb) << MAGIC_ADDRCONFIG_MASBITS_OFFS)	 & ~MAGIC_ADDRCONFIG_MASBITS_MASK) == 0LL);  return (((MagicRegister)pages) << MAGIC_ADDRCONFIG_PAGES_OFFS)      |         (((MagicRegister)nnb) << MAGIC_ADDRCONFIG_NNBITS_OFFS)       |         (((MagicRegister)masb) << MAGIC_ADDRCONFIG_MASBITS_OFFS);}/* PPR access handler -- handles all accesses to PPR's. * Returns: *  - 0: ok access *  - 1: this type of access not supported (only dword implemented *       for now) *  - -1: bus-error this access. */static intPPR_handler(int   cpu,   /* CPU doing the access */	    int   n,     /* destination node */	    int   r,     /* register number */	    int   type,  /* access type */	    void *buff)  /* data buffer */{    /* NOTE: for 32 bit Topsy's pleasure, we support word access -- PZ. */#define RDONLY if (type == BDOOR_STORE_DOUBLE || type == BDOOR_STORE_WORD) return -1#define WRONLY if (type == BDOOR_LOAD_DOUBLE || type == BDOOR_LOAD_WORD) return -1#define RDWR#ifdef __alpha  MagicRegister* datap = (MagicRegister*) buff;#else  int* datap = (int*)buff; /* hack (PZ) */#endif  int            isrd  = (type == BDOOR_LOAD_DOUBLE || type == BDOOR_LOAD_WORD);  ASSERT(0 <= cpu && cpu < TOTAL_CPUS);  ASSERT(0 <= n && n < TOTAL_CPUS);  /* Note: we should never get here if we use Flite! */  ASSERT(!USE_MAGIC());#if (DEBUG_MAGIC == 1)  LogEntry("PPR_handler", cpu, "n=%d r=0x%x t=%d\n", n, r, type);#endif  /* silly support for word accesses (PZ) */  if (type = BDOOR_STORE_WORD)      *datap &= 0xffffffff; /* mask off high bits */  /* we only handle dword accesses and buserror all others */  if (type != BDOOR_LOAD_DOUBLE && type != BDOOR_STORE_DOUBLE &&      type != BDOOR_LOAD_WORD && type != BDOOR_STORE_WORD) return 1;  switch (r) {      case MAGIC_PPR_IECHIGH:                                            RDONLY;    *datap = mm[n].IEChigh;    break;  case MAGIC_PPR_ACKINTERNAL:                                        WRONLY;    return AckInternalInt(n, (IEC)*datap);  case MAGIC_PPR_IECPENDING:                                         RDWR;    if (isrd) {      *datap = mm[n].iPendingReg;    } else {      /* clear selected interrupt bits */      mm[n].iTransReg &= ~(*datap);      mm[n].iPendingReg &= ~(*datap); /* topsy hack -- PZ */      recompute_intr_bits(n);    }    break;  case MAGIC_PPR_SIPSLOACK:                                          RDONLY;    return AckInternalInt(n, (IEC)DEV_IEC_OSPC_LO);  case MAGIC_PPR_SIPSHIACK:                                          RDONLY;    return AckInternalInt(n, (IEC)DEV_IEC_OSPC_HI);  case MAGIC_PPR_IECENABLE:                                          RDWR;    if (isrd) {      *datap = mm[n].iEnableMask;    } else {      mm[n].iEnableMask = *datap;      recompute_intr_bits(n);    }    break;  case MAGIC_PPR_SENDIPI:                                            WRONLY;  {     int iec;     switch (*datap) {     case 0:	iec = DEV_IEC_IPI;	break;     case 1:	iec = DEV_IEC_IPI1;	break;     case 2:	iec = DEV_IEC_IPI2;	break;     default:	CPUError("only ipi 0, 1, and 2 supported\n");     }     CPUVec.Send_Interrupt(n, iec, IPI_LATENCY);  }  break;  case MAGIC_PPR_OPSPACE:                                            RDWR;    ASSERT(0); /* not yet implemented */    break;  case MAGIC_PPR_ASID:                                               RDWR;    ASSERT(0); /* not yet implemented */    break;  case MAGIC_PPR_TLBINVAL:                                           WRONLY;    ASSERT(0); /* not yet implemented */    break;  case MAGIC_PPR_TLBINUSE:                                           RDONLY;    ASSERT(0); /* not yet implemented */    break;  case MAGIC_PPR_MSGTAG:                                             RDWR;    ASSERT(0); /* not yet implemented */    break;  case MAGIC_PPR_STALLOSPC:                                          RDWR;    if (isrd) *datap = sst[n].stall;    else      sst[n].stall = *datap;    break;  case MAGIC_PPR_CYCLECOUNT:                                         RDONLY;    /* XXX is this correct? */    *datap = (MagicRegister) CPUVec.CycleCount(n);    break;      case MAGIC_PPR_PROTVERSION:                                        RDONLY;    /* This always returns 2 for now */    *datap = (MagicRegister)2;    break;  case MAGIC_PPR_HWVERSION:                                          RDONLY;    ASSERT(0); /* not yet implemented */    break;  case MAGIC_PPR_REMAPMASK:                                          RDWR;    ASSERT( !isrd ); /* w not yet implemented */    memsysVec.MemsysSetRemap(n, (PA)*datap);    memsysVec.MemsysControlRemap(n, 1); /* remapenable */    break;  case MAGIC_PPR_PROTCONTROL:                                        RDWR;    ASSERT(0); /* not yet implemented */    break;  case MAGIC_PPR_RTC:                                                RDONLY;     {        SimTime currentCycle = CPUVec.CycleCount(n) + startingCycle[n];        *datap = (MagicRegister) CyclesToNanoSecs(currentCycle)/1000;        break;     }  case MAGIC_PPR_INTERVAL:                                           RDWR;    if (isrd)      *datap = mm[n].timerInterval;    else {      mm[n].timerInterval = *datap;      /* XXX fix this */      InstallTimer(n, *datap, *datap);    }    break;  case MAGIC_PPR_SLOTMAP:                                            RDWR;    if (isrd)      *datap =	( (MagicRegister)mm[n].ioSlotMap[0] << MAGIC_SLOTMAP_SLOT0_OFFS ) |	( (MagicRegister)mm[n].ioSlotMap[1] << MAGIC_SLOTMAP_SLOT1_OFFS ) |	( (MagicRegister)mm[n].ioSlotMap[2] << MAGIC_SLOTMAP_SLOT2_OFFS ) |	( (MagicRegister)mm[n].ioSlotMap[3] << MAGIC_SLOTMAP_SLOT3_OFFS );    else {      int slot;      for (slot=0; slot<4; slot++)          while (mm[n].ioSlots[slot] > 0) ClearSlot(n, slot);      mm[n].ioSlotMap[0] = (*datap & MAGIC_SLOTMAP_SLOT0_MASK) >>	                                           MAGIC_SLOTMAP_SLOT0_OFFS;      mm[n].ioSlotMap[1] = (*datap & MAGIC_SLOTMAP_SLOT1_MASK) >>	                                           MAGIC_SLOTMAP_SLOT1_OFFS;      mm[n].ioSlotMap[2] = (*datap & MAGIC_SLOTMAP_SLOT2_MASK) >>	                                           MAGIC_SLOTMAP_SLOT2_OFFS;      mm[n].ioSlotMap[3] = (*datap & MAGIC_SLOTMAP_SLOT3_MASK) >>	                                           MAGIC_SLOTMAP_SLOT3_OFFS;    }    break;  case MAGIC_PPR_FWSHIFT:                                            RDWR;    /* obsolete, should be removed */    ASSERT(0);    break;  case MAGIC_PPR_RECOVERYSYNC:                                       RDONLY;    ASSERT(0); /* not yet implemented */    break;  case MAGIC_PPR_REPORT_DIAG_RESULT:                                 RDONLY;    ASSERT(0); /* not yet implemented */    break;  case MAGIC_PPR_NODECONFIG:                                         RDONLY;    {      int cell;      if (inCellMode)          cell = cpu / CPUS_PER_CELL(0); /* this is my node number */      else          cell = 0;      *datap = node_config(cell, cpu);    }    break;  case MAGIC_PPR_ADDRCONFIG:                                         RDONLY;    *datap = addr_config(cpu);    break;  case MAGIC_PPR_MIG_REP:

⌨️ 快捷键说明

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