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

📄 simmagic.c

📁 一个用在mips体系结构中的操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:
     RDONLY;     if (IS_NUMA() ) {        /*          * Gets any pending pages whose cache-miss counters         * crossed the threshold set. This is in response to         * the hotpage interrupt. Returns the local page number         * or zero when there are no more. The latter also resets         * the interrupt.         */        *datap = (MagicRegister) MigRepGetHotPage(cpu);     } else {        /* Currently we just return 0 */        *datap = (MagicRegister) 0;     }    break;      default:    /* Slow case: uncached access to OSPC mirror area? */    switch (r & ~(MAGIC_OSPC_SIZE-1)) {    case (MAGIC_PPR_OSPC + (MAGIC_OSPC_LO_OFFS >> __MAGIC_REG_OFFS)):    case (MAGIC_PPR_OSPC + (MAGIC_OSPC_HI_OFFS >> __MAGIC_REG_OFFS)):      {	int  offs = r & ((MAGIC_OSPC_SIZE-1) >> __MAGIC_REG_OFFS);	byte ospc_buff[MAGIC_OSPC_SIZE];	int  result;	result =	  sim_magic_OSPC_access(cpu, 				__MAGIC_OSPC_BASE +			          ((r - MAGIC_PPR_OSPC) << __MAGIC_REG_OFFS),				ospc_buff);	ASSERT(result == 0);	*datap = ((uint64*)ospc_buff)[offs];      }      break;    case (MAGIC_PPR_OSPC + (MAGIC_OSPC_VEC_REQ_OFFS >> __MAGIC_REG_OFFS)):    case (MAGIC_PPR_OSPC + (MAGIC_OSPC_VEC_REP_OFFS >> __MAGIC_REG_OFFS)):      /* not emulated by simmagic */      ASSERT(0);      break;    default:      /* Illegal PPR access */      ASSERT(0); /* should actually buserror. Do later */      break;    }  }#if (DEBUG_MAGIC == 1)  LogEntry("PPR_handler", cpu, "data 0x%llx\n", (uint64)*datap);#endif  return 0;#undef RDONLY#undef WRONLY#undef RDWR}/**************************************************************************** * * PPC emulation * ****************************************************************************/#define PPC_GROUPS          2       /* only kernel and msg so far */#define PPC_MAX             0x10    /* max. PPC's per group */#define PPC_SIZE            16      /* 16 dwords */typedef struct PPCStat {  MagicRegister  data[PPC_SIZE]; /* PPC data */  unsigned int   inited;         /* which words have been inited? */} PPCStat;#define PPC_IS_INITED(bf, n) ((bf & (1 << n)) != 0)#define PPC_WORD_INITED(bf, n) bf |= (1 << n)#define PPC_ALL_INITED(bf, n) (((bf) & ((1 << n) - 1)) == ((1 << n) - 1))#define PPC_CLEAR_INITED(bf) bf = 0static PPCStat ppcs[SIM_MAXCPUS][PPC_GROUPS][PPC_MAX];/* PPC access handler. * Returns: *  - 0: access handled successfully *  - 1: cannot handle, bus-error access */static intPPC_handler(int   cpu,   /* CPU doing the access */	    int   n,     /* destination node */	    int   g,     /* PPC group */	    int   p,     /* PPC number */	    int   offs,  /* byte offset */	    int   type,  /* access type */	    void *buff)  /* data buffer */{#define ARGS(n)       if (!PPC_ALL_INITED(ps->inited, n)) goto retry#define BAD_PPC(_why) (MAGIC_PPC_NOT_SUCCESSFUL_BIT | (_why))  MagicRegister* datap = (MagicRegister*)buff;  PPCStat*       ps    = &ppcs[n][g][p];  ASSERT(0 <= cpu && cpu < TOTAL_CPUS);  ASSERT(0 <= n && n < TOTAL_CPUS);  /* Note: we should never get here if we use Flite! */  /* except for the few PPCs that are not yet implemented in flite */  if (USE_MAGIC()) {     ASSERT((p == MAGIC_PPC_OP_CELLNODECONFIG) ||            (p == MAGIC_PPC_OP_NODEADDRCONFIG) ||            (p == MAGIC_PPC_OP_STARTSLAVENODE));  }#if (DEBUG_MAGIC == 1)  LogEntry("PPC_handler", cpu, "n=%d g=%d p=0x%x offs=0x%x t=%d\n",	   n, g, p, offs, type);#endif  /* we only handle dword accesses and buserror all others */  if (type != BDOOR_LOAD_DOUBLE && type != BDOOR_STORE_DOUBLE) return 1;  /* henceforth, we only deal with word offsets */  offs = offs / sizeof(MagicRegister);  if (type == BDOOR_STORE_DOUBLE) {#if (DEBUG_MAGIC == 1)    LogEntry("PPC_handler", cpu, "data = 0x%llx\n", (uint64)*datap);#endif    /* Store PPC argument */    ps->data[offs] = *datap;    PPC_WORD_INITED(ps->inited, offs);    return 0;  }  /* we can only handle reads to the first dword of a PPC. We buserr   * all other reads.   */  if (offs != 0) return 1;  switch (g) {  case MAGIC_PPC_GROUP_KERNEL: /* KERNEL group */    switch (p) {    case MAGIC_PPC_OP_SIPSLO:    case MAGIC_PPC_OP_SIPSHI:                                   ARGS(PPC_SIZE);      switch (sim_sips_send(cpu,			    (p == MAGIC_PPC_OP_SIPSLO),			    (void*)ps->data, 0)) {      case SIPS_OK:         *datap = (MagicRegister)0;                 break;      case SIPS_RETRYLOCAL: *datap = BAD_PPC(MAGIC_PPC_BUSY);          break;      case SIPS_RETRYREMOTE:*datap = BAD_PPC(MAGIC_PPC_REMOTEBUSY);    break;      case SIPS_BADDEST:    *datap = BAD_PPC(MAGIC_PPC_ARGOUTOFRANGE); break;      case SIPS_REMOTEDEAD: *datap = BAD_PPC(MAGIC_PPC_REMOTEDEAD);    break;      default:              ASSERT(0); break;      }      break;    case MAGIC_PPC_OP_MEMCPY:                                   ARGS(4);      ASSERT(0); /* not yet implemented */      break;    case MAGIC_PPC_OP_IBITWRITE:                                ARGS(2);      {	if ((int)ps->data[0] > DEV_IEC_MAX) {	  CPUWarning("sws_ppc_op_ibitwrite: iec out of range\n");	  goto out_of_range;	}	if ((int)ps->data[1] != 0x00 &&	    (int)ps->data[1] != 0x01 &&	    (int)ps->data[1] != 0x02 &&	    (int)ps->data[1] != 0x04 &&	    (int)ps->data[1] != 0x08 &&	    (int)ps->data[1] != 0x10) {	  CPUWarning("sws_ppc_op_ibitwrite: bad ibit\n");#ifdef IRIX6_4          /* Temp patch to keep the current 6.4 kernel working. */          *datap = (MagicRegister)0; /* success */          break;#else 	  goto out_of_range;#endif	}	mm[n].iBitTable[(int)ps->data[0]] = (int) ps->data[1];	recompute_intr_bits(n);      }      *datap = (MagicRegister)0; /* success */      break;    case MAGIC_PPC_OP_IBITREAD:                                 ARGS(1);      {	if ((int)ps->data[0] > DEV_IEC_MAX) {	  CPUWarning("sws_ppc_op_ibitread: iec out of range\n");	  goto out_of_range;	}	*datap = mm[n].iBitTable[(int)ps->data[0]];      }      break;    case MAGIC_PPC_OP_DONATE:                                   ARGS(3);      ASSERT(0); /* not yet implemented */      break;    case MAGIC_PPC_OP_RESETPOOL:                                ARGS(1);      ASSERT(0); /* not yet implemented */      break;    case MAGIC_PPC_OP_LOADSTATE:                                ARGS(1);      CPUPrint("LOADSTATE not implemented\n");      *datap = 0;      break;    case MAGIC_PPC_OP_STORESTATE:                               ARGS(2);      ASSERT(0); /* not yet implemented */      break;    case MAGIC_PPC_OP_MEMRESET:                                 ARGS(2);      ASSERT(0); /* not yet implemented */      break;    case MAGIC_PPC_OP_VECTORPKT:                                ARGS(7);      ASSERT(0); /* not yet implemented */      break;    case MAGIC_PPC_OP_BZERO:                                    ARGS(3);      ASSERT(0); /* not yet implemented */      break;    case MAGIC_PPC_OP_CELLNODECONFIG:                           ARGS(1);      {	MagicRegister cell = ps->data[0];	if (cell >= NUM_CELLS(0)) goto out_of_range;	*datap = node_config((int)cell, cpu);      }      break;    case MAGIC_PPC_OP_NODEADDRCONFIG:                           ARGS(1);      {	MagicRegister node = FIRST_CPU(M_FROM_CPU(cpu))+ps->data[0]; 	if (node >= TOTAL_CPUS) goto out_of_range;	*datap = addr_config((int)node);      }      break;#if !defined(IRIX6_4)    case MAGIC_PPC_OP_STARTSLAVENODE:                           ARGS(3);      {	int slave = FIRST_CPU(M_FROM_CPU(cpu))+ps->data[0];	if (slave >= TOTAL_CPUS) goto out_of_range;        if (inCellMode) {            if (((cpu / CPUS_PER_CELL(0))*CPUS_PER_CELL(0)) != cpu ||                slave < cpu ||                slave >= cpu+CPUS_PER_CELL(0)) goto out_of_range;        }	if (LaunchSlave(slave, (VA)(ps->data[1]), (Reg)(ps->data[2]),                         0, 0, 0))	  goto out_of_range;      }      *datap = 0;      break;#else    case MAGIC_PPC_OP_STARTSLAVENODE:                           ARGS(4);      {	int slave = FIRST_CPU(M_FROM_CPU(cpu))+ps->data[0];	if (slave >= TOTAL_CPUS) goto out_of_range;        if (inCellMode) {            if (((cpu / CPUS_PER_CELL(0))*CPUS_PER_CELL(0)) != cpu ||                slave < cpu ||                slave >= cpu+CPUS_PER_CELL(0)) goto out_of_range;        }	if (LaunchSlave(slave, (VA)(ps->data[1]), (Reg)(ps->data[2]),                         (Reg)(ps->data[3]), 0, 0))	  goto out_of_range;      }      *datap = 0;      break;#endif    default: goto bad_opc;    }    break;      case MAGIC_PPC_GROUP_MSG: /* MSG group */    switch (p) {    case MAGIC_PPC_OP_MEMCPY_V:                                 ARGS(4);      ASSERT(0); /* not yet implemented */      break;    case MAGIC_PPC_OP_SIPS_V:                                   ARGS(16);      ASSERT(0); /* not yet implemented */      break;    case MAGIC_PPC_OP_BZERO_V:                                  ARGS(3);      ASSERT(0); /* not yet implemented */      break;    default: goto bad_opc;    }    break;      default: goto bad_grp;  }      PPC_CLEAR_INITED(ps->inited);#if (DEBUG_MAGIC == 1)  LogEntry("PPC_handler", cpu, "result=0x%016llx\n", (uint64)*datap);#endif  return 0;      /* Error returns: */out_of_range:  CPUWarning("MAGIC value out of range\n");  *datap = MAGIC_PPC_NOT_SUCCESSFUL_BIT|MAGIC_PPC_ARGOUTOFRANGE;  return 0;retry:  *datap = MAGIC_PPC_NOT_SUCCESSFUL_BIT|MAGIC_PPC_RETRY_CODE; return 0;bad_opc:  *datap = MAGIC_PPC_NOT_SUCCESSFUL_BIT|MAGIC_PPC_BADOPCODE; return 0;bad_grp:  *datap = MAGIC_PPC_NOT_SUCCESSFUL_BIT|MAGIC_PPC_BADGROUP; return 0;#undef ARGS#undef BAD_PPC}/**************************************************************************** * * Device registers and interrupt emulation * ****************************************************************************//* * DISK device. * The shadow array is indexed by: *   - absolute node number (i.e. NOT machine-relative one) *   - controller number *   - disk unit number */static DevDiskRegisters**** disk_shadow;#define DISK_SHADOW(_NODE,_CTRL,_UNIT) (*disk_shadow[_NODE][_CTRL][_UNIT])static voiddisk_initialize(void){  disk_shadow = (DevDiskRegisters****)    ZMALLOC(DISK_NODES*sizeof(DevDiskRegisters***), "disk_shadow");}static voiddisk_touch(int node, int ctrl, int unit){  char name[32];  int  nc = NUM_DISK_CONTROLLERS(M_FROM_CPU(node), MCPU_FROM_CPU(node));  int  uc = DEV_DISK_MAX_UNIT / nc;  ASSERT(0 <= node && node < DISK_NODES &&	 0 <= ctrl && ctrl < nc         &&	 0 <= unit && unit < uc);  if (!disk_shadow[node]) {    sprintf(name, "disk_shadow[%d]", node);    disk_shadow[node] = (DevDiskRegisters***)      ZMALLOC(nc*sizeof(DevDiskRegisters**), name);  }  if (!disk_shadow[node][ctrl]) {    sprintf(name, "disk_shadow[%d][%d]", node, ctrl);    disk_shadow[node][ctrl] = (DevDiskRegisters**)      ZMALLOC(uc*sizeof(DevDiskRegisters*), name);  }  if (!disk_shadow[node][ctrl][unit]) {    sprintf(name, "disk_shadow[%d][%d][%d]", node, ctrl, unit);    disk_shadow[node][ctrl][unit] = (DevDiskRegisters*)      ZMALLOC(sizeof(DevDiskRegisters), name);    sim_disk_touch(node, ctrl, unit);  }}static voiddisk_status_update(int node, int ctrl, int unit){  int done, bytes_tr, errno_val;  DevDiskRegisters* regs = &DISK_SHADOW(node,ctrl,unit);  sim_disk_status(node, ctrl, unit,		  &done, &bytes_tr, &errno_val);  regs->intr_pending     = (DevRegister)done;  regs->bytesTransferred = (DevRegister)bytes_tr;  regs->errnoVal         = (DevRegister)errno_val;  regs->doneIO           = (DevRegister)done;}/* * Note: when running multiple machines, the following routine * is called with an absolute node number (i.e. not a machine- * relative one). */static intdisk_handler(int node, int nd, int doff, int type, void* buff){   int          nc    = NUM_DISK_CONTROLLERS(M_FROM_CPU(node),                                             MCPU_FROM_CPU(node));   int          uc    = DEV_DISK_MAX_UNIT / nc;   int          ctrl  = nd / uc; /* controller */   int          unit  = nd % uc; /* unit attached to controller */   DevRegister* datap = (DevRegister*)buff;   ASSERT(0 <= node && node < DISK_NODES &&          0 <= ctrl && ctrl < nc         &&          0 <= unit && unit < uc);#if (DEBUG_MAGIC == 1)   LogEntry("disk_handler", CPUVec.CurrentCpuNum(),            "node=%d ctrl=%d unit=%d doff=0x%x t=%d data=0x%08x\n",            node, ctrl, unit, doff, type, *datap);#endif   disk_touch(node, ctrl, unit);    /* we only handle dword accesses and buserror all others */   ASSERT (BDOOR_SIZE(type) == sizeof(DevRegister));     if (doff == offsetof(DevDiskRegisters, intr_pending)) {          if (BDOOR_IS_LOAD(type)) {         /* note: bogus mapping (n,nd) -> SimOS disk #. To be improved */         disk_status_update(node, ctrl, unit);         *datap = DISK_SHADOW(node,ctrl,unit).intr_pending;      } else {         /* note: bogus mapping (n,nd) -> SimOS disk #. To be improved */         sim_disk_iodone(node, ctrl, unit);         disk_status_update(node, ctrl, unit);      }       } else if (doff == offsetof(DevDiskRegisters, errnoVal)) {          if (BDOOR_IS_STORE(type)) goto illegal;      disk_status_update(node, ctrl, unit);      *datap = DISK_SHADOW(node,ctrl,unit).errnoVal;   } else if (doff == offsetof(DevDiskRegisters, bytesTransferred)) {          if (BDOOR_IS_STORE(type)) goto illegal;      disk_status_update(node, ctrl, unit);      *datap = DISK_SHADOW(node,ctrl,unit).bytesTransferred;       } else if (doff == offsetof(DevDiskRegisters, interruptNode)) {          /* interruptNode is always the first cpu of the     * cell in the current implementation.

⌨️ 快捷键说明

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