📄 simmagic.c
字号:
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 + -