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

📄 simmagic.c

📁 一个用在mips体系结构中的操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:
  ASSERT(VA_ZONE(VA) == MAGIC_ZONE_FIREWALL);  /* actually, we should return a bus error for accesses which fall   * outside the valid range. For now, we have an assertion since this   * makes things easier to debug.   */  ASSERT(pg < (MEM_SIZE(M_FROM_CPU(cpuNum))               / NUM_CPUS(M_FROM_CPU(cpuNum))));  if (type == BDOOR_LOAD_DOUBLE) {    /* anyone can read the firewall status */    *datap = (MagicRegister)sim_firewall_page_prot(node, pg);  } else if (type == BDOOR_STORE_DOUBLE) {    /* only nodes in the same cell and cells which have firewall write     * access to this page can write the firewall.     */    return sim_firewall_set_page_prot(cpuNum, node, pg, (uint64)*datap);  } else return 1; /* can only handle dword accesses */  return 0;}/* * Routine called when the MIG_REP zone is accessed  * for reading or setting cache-miss or write counters. */static intMIG_REP_access(int cpuNum, uint VA, int type, void* buff){  MagicRegister* datap = (MagicRegister*)buff;  int            node  = FIRST_CPU(M_FROM_CPU(cpuNum)) + VA_NODE(VA);  unsigned long  pg    = VA_OFFS(VA);  ASSERT(!USE_MAGIC());  ASSERT(VA_ZONE(VA) == MAGIC_ZONE_MIG_REP);  if (IS_NUMA()) {     unsigned long typeMask = (1<<(__MAGIC_ZONE_OFFS-1));     unsigned long countType = pg & typeMask;     unsigned long countAddr = (pg & (~typeMask))/sizeof(uint64);     if (type == BDOOR_LOAD_DOUBLE) {        *datap = (MagicRegister) MigRepGetInfo(pg, node, countType, countAddr);     } else if (type == BDOOR_STORE_DOUBLE) {        MigRepSetInfo(pg, node, *datap, countType, countAddr);     } else {        return 1; /* can only handle dword accesses */     }  } else {     /*      * For now we just return 0 for reads and do nothing for writes      */     if (type == BDOOR_LOAD_DOUBLE) {        *datap = (MagicRegister) 0;     } else if (type == BDOOR_STORE_DOUBLE) {     } else {        return 1; /* can only handle dword accesses */     }  }  return 0;}static intPPR_access(int cpuNum, uint VA, int type, void* buff){  /* PPR access to specified node */  int n = FIRST_CPU(M_FROM_CPU(cpuNum)) + VA_NODE(VA);  ASSERT(!USE_MAGIC());  ASSERT(VA_ZONE(VA) == MAGIC_ZONE_PPR);  return PPR_handler(cpuNum, n, VA_REG(VA), type, buff);}static intPPC_access(int cpuNum, uint VA, int type, void* buff){    /* PPC access to specified node */  int n = FIRST_CPU(M_FROM_CPU(cpuNum)) + VA_NODE(VA);  ASSERT(!USE_MAGIC());  ASSERT(VA_ZONE(VA) == MAGIC_ZONE_PPC);  return PPC_handler(cpuNum, n,		     VA_GRP(VA), VA_OPC(VA), VA_SEQ(VA), type, buff);}static intBDOOR_disk_access(int cpuNum, uint VA, int type, void* buff){  int node = VA_NODE(VA); /* relative to current machine */  int offs = VA_OFFS(VA) - __MAGIC_BDOOR_DISKS_OFFS;  int nd   = offs / sizeof(DevDiskRegisters); /* unit # */  int doff = offs % sizeof(DevDiskRegisters); /* offset in unit regs */  ASSERT(VA_ZONE(VA) == MAGIC_ZONE_BDOOR_DEV);  /* XXX   * Uncomment the following assert when not using more disk   * controllers than nodes any longer. Currently, I think this   * is only used for DISCO. DT.   * XXX   */  /* ASSERT(0 <= node && node < NUM_CPUS(M_FROM_CPU(cpuNum))); */  /* Note for multiple machines:   * must translate this access to an absolute node number.   */  return disk_handler(node + FIRST_CPU(M_FROM_CPU(cpuNum)),		      nd, doff, type, buff);}static intBDOOR_console_access(int cpuNum, uint VA, int type, void* buff){  int n    = VA_NODE(VA);  int offs = VA_OFFS(VA) - __MAGIC_BDOOR_CNSLE_OFFS;  ASSERT(VA_ZONE(VA) == MAGIC_ZONE_BDOOR_DEV);  ASSERT(!inCellMode || (n % CPUS_PER_CELL(0) == 0));   ASSERT(0 <= offs && offs < sizeof(DevConsoleRegisters));  return console_handler(cpuNum, n, offs, type, buff);}static intBDOOR_ether_access(int cpuNum, uint VA, int type, void* buff){  int n    = VA_NODE(VA);  int offs = VA_OFFS(VA) - __MAGIC_BDOOR_ETHER_OFFS;  ASSERT(VA_ZONE(VA) == MAGIC_ZONE_BDOOR_DEV);  ASSERT(!inCellMode || (n % CPUS_PER_CELL(0) == 0));   ASSERT(0 <= offs && offs < sizeof(DevEtherRegisters));  return ether_handler(cpuNum, n, offs, type, buff);}static intBDOOR_clock_access(int cpuNum, uint VA, int type, void* buff){  int n    = VA_NODE(VA);  int offs = VA_OFFS(VA) - __MAGIC_BDOOR_CLOCK_OFFS;  ASSERT(VA_ZONE(VA) == MAGIC_ZONE_BDOOR_DEV);  ASSERT(!inCellMode || (n % CPUS_PER_CELL(0) == 0));   ASSERT(0 <= offs && offs < sizeof(DevClockRegisters));  return clock_handler(cpuNum, n, offs, type, buff);}#ifdef TORNADOstatic intBDOOR_gizmo_access(int cpuNum, uint VA, int type, void* buff){  int n    = VA_NODE(VA);  int offs = VA_OFFS(VA) - __MAGIC_BDOOR_GIZMO_OFFS;  ASSERT(VA_ZONE(VA) == MAGIC_ZONE_BDOOR_DEV);  ASSERT(0 <= offs && offs < sizeof(DevGizmoRegisters));  return gizmo_handler(cpuNum, n, offs, type, buff);}#endif /* TORNADO */static intOSPC_access(int cpuNum, uint VA, int type, void* buff){  int offs = VA & (MAGIC_OSPC_SIZE-1);  int err;  byte ospc_buff[MAGIC_OSPC_SIZE];  ASSERT(!USE_MAGIC());  ASSERT(VA >= __MAGIC_OSPC_BASE && VA < __MAGIC_OSPC_END);  if (type != BDOOR_LOAD_BYTE &&      type != BDOOR_LOAD_HALF &&      type != BDOOR_LOAD_WORD &&      type != BDOOR_LOAD_DOUBLE) {    ASSERT(0); /* for debugging */    return 1;  }  err = sim_magic_OSPC_access(cpuNum, VA, ospc_buff);  ASSERT(err >= 0);  switch (type) {  case BDOOR_LOAD_BYTE:    *(unsigned char*)buff = ((unsigned char*)ospc_buff)[offs];#if (DEBUG_MAGIC == 1)    LogEntry("OSPC_access", cpuNum, "VA 0x%08x BYTE data 0x%02x\n",	     VA, *(unsigned char*)buff);#endif    break;  case BDOOR_LOAD_HALF:    *(unsigned short*)buff =      ((unsigned short*)ospc_buff)[offs/sizeof(unsigned short)];#if (DEBUG_MAGIC == 1)    LogEntry("OSPC_access", cpuNum, "VA 0x%08x HALF data 0x%04x\n",	     VA, *(unsigned short*)buff);#endif    break;  case BDOOR_LOAD_WORD:    ASSERT(offs % sizeof(uint) == 0);    *(uint*)buff   = ((uint*)ospc_buff)[offs/sizeof(uint)];#if (DEBUG_MAGIC == 1)    LogEntry("OSPC_access", cpuNum, "VA 0x%08x WORD data 0x%08x\n",	     VA, *(uint*)buff);#endif    break;  case BDOOR_LOAD_DOUBLE:    ASSERT(offs % sizeof(uint64) == 0);    *(uint64*)buff = ((uint64*)ospc_buff)[offs/sizeof(uint64)];#if (DEBUG_MAGIC == 1)    LogEntry("OSPC_access", cpuNum, "VA 0x%08x DWORD data 0x%016lx\n",	     VA, *(uint64*)buff);#endif    break;  }  return 0;}/* CAVEAT: we currently DON'T model the latency of getting an OSPC * cacheline when not running under Flashlite. This is not tragic, * but should be fixed at some point. */Result sim_magic_MemsysCmd(int cpunum, int cmd, unsigned int paddr,                    int transId,  unsigned int replacedPaddr,                     int writeback, byte *data){  int command = cmd & MEMSYS_CMDMASK;  int flavor  = cmd & (~MEMSYS_CMDMASK);  byte *wb_buff = data;  Result res;  /* Is this an OSPC access we should handle? */  if ( 0 &&       !USE_MAGIC()                                                  &&       (command == MEMSYS_GET || command == MEMSYS_REPLACEMENT_HINT) &&       (flavor == 0)                                                 &&       (paddr >= (__MAGIC_OSPC_BASE - K0BASE) &&	paddr <  (__MAGIC_OSPC_BASE - K0BASE + 2*MAGIC_OSPC_SIZE)) ) {CPUWarning("OSPC access...\n");    /* OSPC access -- handle hic et nunc */    if (cmd == MEMSYS_GET) {      /* Note: paddr is critical-word-first, which is irrelevant for now */      unsigned int offs = (paddr & ~(MAGIC_OSPC_SIZE-1)) -	                  (__MAGIC_OSPC_BASE - K0BASE);      byte ospc_buff[MAGIC_OSPC_SIZE];      static byte wb_save[MAGIC_OSPC_SIZE];      MagicRegister errval, okval;      int err;      /* read the data -- for now, this is only SIPS data */      switch (offs) {      case MAGIC_OSPC_LO_OFFS:	errval = MAGIC_OSPC_LO_NONE;	okval  = MAGIC_OSPC_LO_SIPSREQ;	err = sim_sips_get(cpunum, 1, ospc_buff);	break;      case MAGIC_OSPC_HI_OFFS:	okval  = MAGIC_OSPC_HI_SIPSREPLY;	errval = MAGIC_OSPC_HI_NONE;	err = sim_sips_get(cpunum, 0, ospc_buff);	break;      default: ASSERT(0);      }      /* SIPS status */      *((MagicRegister*)ospc_buff) = err ? errval : okval;      /* Note: at this point, the GET is done, as far as we're concerned.       * However, we still might have to do a WB, which might stall.       * This is sort of perverse, since we're actually doing the operations       * in the reverse order than on the real machine (i.e. we're satisfying       * the GET first...       * In order to avoid clobbering the unique copy of the wb data, we'll       * save it to a private buffer.       */      ASSERT(MAGIC_OSPC_SIZE >= SCACHE_LINE_SIZE);      bcopy(wb_buff, wb_save, sizeof(wb_save));      wb_buff = wb_save;      /* Now tell the processor the GET has completed. If the WB stalls,       * then we'll call MipsyStall to stall the processor (!).       * THIS IS A HACK!!!       */      CacheCmdDone(cpunum, transId, MEMSYS_SHARED, MEMSYS_STATUS_SUCCESS,		   MEMSYS_RESULT_MEMORY, ospc_buff);    }    /* else: replacement hint is ignored */    if (writeback) {      ASSERT((paddr & ~(MAGIC_OSPC_SIZE-1)) !=	     (replacedPaddr & ~(MAGIC_OSPC_SIZE-1)));      /* Need to perform the writeback, too! */      res = memsysVec.MemsysCmd(cpunum, MEMSYS_GET, 0LL, -1,                                replacedPaddr, writeback, data);      if (res == STALL) {	/* oops, write buffer filled up. We'll have to stall the	 * CPU again. This is a total hack.	 */	CPUWarning("Stalling during OSPC....\n");      }      return res;    } else {      return SUCCESS;    }  } else    /* Main memory access -- pass on unaffected */    return memsysVec.MemsysCmd(cpunum, cmd, paddr, transId,                               replacedPaddr, writeback, data);}/* * Device polling. Some simulated devices which take asynchronous * input from the "real world" need to have a poll function called * periodically to check for input. */static EventCallbackHdr pollHdr;	/* poll devices callback */static void PollDevices(int cpuNum, EventCallbackHdr *hdr, void *arg){#if (DEBUG_MAGIC == 1)  LogEntry("PollDevices", 0, "\n");#endif  /* 1. Poll all consoles */  sim_console_poll();  /* 2. Poll all ethernet interfaces */#ifndef linux  SimetherPoll();#endif#ifdef TORNADO  /* 3. Poll gizmo interface */  gizmo_poll();#endif /* TORNADO */  /* register callback for next poll round */  EventDoCallback(0, PollDevices, &pollHdr, NULL, MAGIC_POLL_INTERVAL);}void InstallPoller(void){  static int installed = 0;  if (!installed) {    installed = 1;    EventDoCallback(0, PollDevices, &pollHdr, NULL, MAGIC_POLL_INTERVAL);  }}/* *** * *** MAGIC & devices initialization. * *** * *** Initialize all devices, device polling, MAGIC emulation, etc. * *** */static voidInitDevices(int restoreFromChkpt){  /*   * CPUVector   */    CPUVec.UncachedPIO = SimMagic_DoPIO;  /* disks */  {    int m, n, uc = NUM_UNITS_PER_CONTROLLER(0);    for (m = 0; m < NUM_MACHINES; m++)      for (n = 0; n < TOTAL_CPUS; n++) {	ASSERT(NUM_UNITS_PER_CONTROLLER(m) * NUM_DISK_CONTROLLERS(m,n) <=	       DEV_DISK_MAX_UNIT);	ASSERT(uc == NUM_UNITS_PER_CONTROLLER(m));      }  }  sim_disk_init(DISK_NODES,		NUM_UNITS_PER_CONTROLLER(0),		disk_interrupt, restoreFromChkpt);  /* ethernet interfaces */  SimetherInit(restoreFromChkpt, ether_interrupt);  /* consoles */  sim_console_init(TOTAL_CONSOLES, console_interrupt);  /* NOTE: at this point, we'd also like to initialize polling (for those   * devices that need it). Unfortunately, this depends on the CPUVec   * being more completely initialized than it is now (before any CPU   * simulator has started). So we'll let the CPU simulators call   * InstallPoller().   */  /* 3. Misc. initialization */  sim_sips_init(TOTAL_CPUS, sips_interrupt);  /* 4. Checkpointing stuff */  Simcpt_Register("magic", SimMagic_CheckpointCB, ALL_CPUS);  if (restoreFromChkpt) Simcpt_Restore("magic");}static voidBuildDeviceToMachine(void){   int machNo, count;   /*    * Build the arrays that map from device number back to machine number    */      deviceToMachine.console = (int*)malloc(TOTAL_CONSOLES*sizeof(int));   deviceToMachine.ether = (int*)malloc(TOTAL_ETHER_CONTROLLERS*sizeof(int));   deviceToMachine.clock = (int*)malloc(TOTAL_CLOCKS*sizeof(int));   ASSERT(deviceToMachine.console);   ASSERT(deviceToMachine.ether);   ASSERT(deviceToMachine.clock);   for (machNo = 0; machNo < NUM_MACHINES; machNo++) {      for (count = FIRST_CONSOLE(machNo);           count <= LAST_CONSOLE(machNo); count++) {         deviceToMachine.console[count] = machNo;      }      for (count = FIRST_ETHER_CONTROLLER(machNo);           count <= LAST_ETHER_CONTROLLER(machNo); count++)

⌨️ 快捷键说明

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