📄 flash_interface.c
字号:
static void FlashliteInitRemap(void);static voidInitSimosMemoryMap(void){ char *addrMapType; int i, memPerProc = 0; memsysVec.MemsysSetRemap = FlashliteSetRemap; memsysVec.MemsysControlRemap = FlashliteControlRemap; memsysVec.MemsysGetNodeAddress = FlashliteGetNodeAddress; FlashliteInitRemap(); ParamLookup(&addrMapType, "MEMSYS.FLASH.FlashAddrMap", PARAM_STRING); if (addrMapType == NULL) addrMapType = "ZeroOnly"; simosPageToNode = (signed char *) calloc(1,MEM_SIZE(0)/FLASH_PAGE_SIZE); ParamLookup(&memPerProc, "MEMSYS.FLASH.TotalMemPerProc", PARAM_INT); bytesPerNode_shift = GetLog2(MEM_SIZE(0)/NUM_CPUS(0)); ASSERT(MEM_SIZE(0) == ((1<<bytesPerNode_shift) * NUM_CPUS(0))); nodeOffsetMask = (1<<bytesPerNode_shift) - 1;/* Hive currently uses only a single remap page, but using 2 pages just to be safe. There's an assert in remap code anyway... */ directMapLimit = 2*FLASH_PAGE_SIZE; if (!strcmp(addrMapType, "FirstTouch")) { addrMap = FIRST_TOUCH; ASSERT(MEM_SIZE(0) <= memPerProc); for(i = 0; i < MEM_SIZE(0)/FLASH_PAGE_SIZE; i++) simosPageToNode[i] = -1; CPUPrint("FlashAddrMap is FirstTouch\n"); } else if (!strcmp(addrMapType, "RoundRobin")) { int pagesPerMem = 0, stripewidth = 0; addrMap = ROUND_ROBIN; ASSERT(MEM_SIZE(0) <= memPerProc); ParamLookup(&pagesPerMem, "MEMSYS.FLASH.RoundRobinStripe", PARAM_INT); ParamLookup(&stripewidth, "MEMSYS.FLASH.NumFlashNodes", PARAM_INT); if (stripewidth < 0) stripewidth = NUM_CPUS(0); for(i = 0; i < MEM_SIZE(0)/FLASH_PAGE_SIZE; i++) simosPageToNode[i] = (i/pagesPerMem) % stripewidth; CPUPrint("FlashAddrMap is RoundRobin with stripe unit of %d\n", pagesPerMem); } else if (!strcmp(addrMapType, "HiveRoundRobin")) { int pageNum, cell, cpu, ncpusPerCell, pagesPerCPU; addrMap = HIVE_ROUND_ROBIN; /* compact roundrobin memory layout: pages are laid out across all cpus in cell using roundrobin allocation, and the offset is same as for Hive. */ ncpusPerCell = NUM_CPUS(0)/NUM_CELLS(0); pagesPerCPU = MEM_SIZE(0)/NUM_CPUS(0)/FLASH_PAGE_SIZE; ASSERT(MEM_SIZE(0)/NUM_CPUS(0) <= memPerProc); CPUPrint("FlashAddrMap is HiveRoundRobin with ncells: %d\nncpusPerCell: %d\npagesPerCPU: 0x%x\nbytesPerNode_shift: %d nodeOffsetMask: 0x%x directMapLimit: 0x%x\n", NUM_CELLS(0), ncpusPerCell, pagesPerCPU, bytesPerNode_shift, nodeOffsetMask, directMapLimit); for (cell = 0; cell < NUM_CELLS(0); cell++) { for (cpu = 0; cpu < ncpusPerCell; cpu++) { int CPU = cell*ncpusPerCell + cpu; for (pageNum = pagesPerCPU*CPU; pageNum < pagesPerCPU*(CPU+1); pageNum++) { simosPageToNode[pageNum] = cell*ncpusPerCell + ((pageNum + cpu) % ncpusPerCell); } } } } else if (!strcmp(addrMapType, "Hive")) { int pageNum, numPages; addrMap = HIVE; ASSERT(MEM_SIZE(0)/NUM_CPUS(0) <= memPerProc); numPages = MEM_SIZE(0)/FLASH_PAGE_SIZE; for (pageNum = 0; pageNum < numPages; pageNum++) { PA paddr = pageNum*FLASH_PAGE_SIZE; int n; for (n = NUM_CPUS(0)-1; n >= 0; n--) { if (paddr >= remapVec->NodeAddr[n]) { simosPageToNode[pageNum] = n; break; } } } CPUPrint("FlashAddrMap is using the Hive mappings\n"); } else { CPUPrint("FlashAddrMap is node zero only\n"); }#ifdef FIREWALL_HACK FlashliteDownloadFirewall();#endif}/***************************************************************** * remap region support - XXX Once we get PPCs working this * should use the remap support inside of flashlite. Until then * we fake it here. *****************************************************************/static voidFlashliteInitRemap(void){ int i; /* We initialize backmapMask to all ones except for the * bits that might be set in the node id field */ nodeaddrMask = ~0; for (i=0; i<NUM_CPUS(0); i++) { if (!remapVec->NodeAddrInitialized) { remapVec->NodeAddr[i] = MEMADDR_TO_PHYS(0, SIM_MEM_ADDR(0) + i * (MEM_SIZE(0) / NUM_CPUS(0))); } nodeaddrMask &= ~remapVec->NodeAddr[i]; } remapVec->NodeAddrInitialized = 1;}static voidFlashliteSetRemap(int cpunum, PA mask){ remapVec->RemapMask[cpunum] = mask;}static voidFlashliteControlRemap(int cpunum, int isEnabled){ remapVec->RemapEnable[cpunum] = isEnabled; /* make sure directMapLimit is bigger than remap range */ if (isEnabled) ASSERT(directMapLimit & remapVec->RemapMask[cpunum]);}static unsigned int FlashliteGetNodeAddress(int cpunum){ return remapVec->NodeAddr[cpunum];}static voidInitMagicPromalias(void){ int cpu; char* pFram; /* points into Flashlite's FRAM memory */ char* pFprom; /* points into Flashlite's FPROM memory */ char* fprom; /* points to Simos's copy of the FPROM */ fprom = sim_misc.fprom[0]; if (fprom == NULL) return; /* none there */ for (cpu= 0; cpu<NUM_CPUS(0); cpu++) { pFprom = FlashWritePromAlias(cpu, SWS_ZONE_FPROMALIAS, fprom, FPROM_SIZE); /* For now, don't use SIMRAMALIAS_SIZE ... it's big! */ pFram = FlashWriteRamAlias(cpu, SWS_ZONE_FRAMALIAS, sim_misc.fram[cpu], FRAM_SIZE); free(sim_misc.fram[cpu]); sim_misc.fram[cpu] = pFram; sim_misc.fprom[cpu] = pFprom; } free(fprom); /* NOTE: at this point, the sim_misc fprom and fram pointers * point directly into Flashlite memory. This allows a * cohabitation between Flite and fast FRAM/FPROM access * emulation through simmagic. */}/* * The following function is called by the memory fault command * (cpus/shared/faults.c) to set ECC for a number of lines, starting at a * specified address. The address MUST be KSEG0. */int insertECC(unsigned int addr, int lines){ LL faddr; int node; int cachelinesz = SCACHE_LINE_SIZE; if (!IS_KSEG0(addr) || lines <= 0 || !IS_KSEG0(addr+(unsigned)lines)) return 1; faddr = FlashAddrFromAddr(0, MEMADDR_TO_PHYS(0, addr)); node = SimosAddrToMemnum(MEMADDR_TO_PHYS(0, addr)); for ( ; lines > 0; lines--) { SetECC(node, faddr, ~0); addr += cachelinesz; } return 0;}#ifdef HWBCOPY/****************************************************************** * Hwbcopy annotations -- place pages on a specific node *****************************************************************/static int HwbPlaceCmd(Tcl_Interp *interp, int argc, char *argv[]);static tclcmd hwbcopyCmds[] = { "place", 4, HwbPlaceCmd, " place address node", NULL, 0, NULL, NULL};void HwbcopyAnnInit(Tcl_Interp *interp) { Tcl_CreateCommand(interp, "hwbcopy", DispatchCmd, (ClientData) hwbcopyCmds, (Tcl_CmdDeleteProc*)NULL); Tcl_SetVar2(interp, "HWBCOPY", "hwbDMA", "No", TCL_GLOBAL_ONLY); Tcl_LinkVar(interp, "HWBCOPY(hwbDMA)", (char *) &hwbDMA, TCL_LINK_BOOLEAN); Tcl_SetVar2(interp, "HWBCOPY", "hwprefetch", "No", TCL_GLOBAL_ONLY); Tcl_LinkVar(interp, "HWBCOPY(hwprefetch)", (char *) &hwprefetch, TCL_LINK_BOOLEAN); Tcl_SetVar2(interp, "HWBCOPY", "hwprefRange", "0", TCL_GLOBAL_ONLY); Tcl_LinkVar(interp, "HWBCOPY(hwprefRange)", (char *) &hwprefRange, TCL_LINK_INT); Tcl_SetVar2(interp, "HWBCOPY", "hwprefDepth", "0", TCL_GLOBAL_ONLY); Tcl_LinkVar(interp, "HWBCOPY(hwprefDepth)", (char *) &hwprefDepth, TCL_LINK_INT); Tcl_SetVar2(interp, "HWBCOPY", "hwbDMAChannels", "1", TCL_GLOBAL_ONLY); Tcl_LinkVar(interp, "HWBCOPY(hwbDMAChannels)", (char *) &hwbDMAChannels, TCL_LINK_INT); Tcl_SetVar2(interp, "HWBCOPY", "hwbDMADelay", "0", TCL_GLOBAL_ONLY); Tcl_LinkVar(interp, "HWBCOPY(hwbDMADelay)", (char *) &hwbDMADelay, TCL_LINK_INT);}static int HwbPlaceCmd(Tcl_Interp *interp, int argc, char *argv[]){ int node; int pAddr; int page; char *addrMapType; ParamLookup(&addrMapType, "MEMSYS.FLASH.FlashAddrMap", PARAM_STRING); if ((memsysVec.type == FLASHLITE) && (!strcmp(addrMapType, "FirstTouch"))) { if (argc < 4) { Tcl_AppendResult(interp, "not enough arguments to hwbcopy place", NULL); return TCL_ERROR; } Tcl_GetInt(interp, argv[3], &node); Tcl_GetInt(interp, argv[2], &pAddr); page = pAddr / FLASH_PAGE_SIZE; if (simosPageToNode[page] == -1) { simosPageToNode[page] = node; /* CPUWarning("Page 0x%x being placed on node %d\n",pAddr,node);*/ } else if (node != simosPageToNode[page]) { CPUWarning("Tried to place page 0x%x on node %d, already on node %d\n",pAddr,node,simosPageToNode[page]); } } return TCL_OK;}#endif /* HWBCOPY */#endif#ifndef SOLOvoid FlashliteUndirtify(int leaveShared){ /* first drain memory system, then undirtify */ FlashDrainMemSys(); FlashUndirtify(leaveShared);}void SyncMemory(void){ datafindHeader *dfH; int pAddr; int nDirty = 0, nCrit = 0; FlashFreezeMemSys(); for (pAddr = 0; pAddr < MEM_SIZE(0); pAddr += SCACHE_LINE_SIZE) { dfH = FlashGetAppData(FlashAddrFromAddr(0, pAddr)); ASSERT(dfH->numCopies > 0); if (dfH->dirty) {#ifdef SOLO LL *memAddr = (LL *)pAddr;#else LL *memAddr = (LL *)PHYS_TO_MEMADDR(0, pAddr);#endif ASSERT(dfH->numCopies == 1); if (dfH->critWordOffset[0]) { ConvertCritWordFirstToNormal((LL*)(dfH->dataCopies[0]), memAddr, dfH->critWordOffset[0]); nCrit++; } else { bcopy(dfH->dataCopies[0], memAddr, SCACHE_LINE_SIZE); } nDirty++; /* just for stats */ } else { /* clean: so there must be a copy in memory, and I don't need to do anything */ ASSERT((dfH->dataLocation[dfH->numCopies-1] & DATAFIND_LOCATION_TYPE_MASK) == DATAFIND_LOCATION_MEMORY); } } FlashUnfreezeMemSys(); CPUWarning("%d critical-word ordered lines, %d dirty lines, %d total lines\n", nCrit, nDirty, MEM_SIZE(0)/SCACHE_LINE_SIZE);}#endif/* Routines for reading from / writing to the FPROM and FRAM. Check for the [vAddr, vAddr+nbytes) to see if it's in FPROM/FRAM range. If so, copy the data into buf and return 1 to indicate data was found in FPROM/FRAM. */intGetFPROMAndFRAM(int cpunum, VA vAddr, uint nbytes, char *buf){#ifndef SOLO if (vAddr >= FRAM_BASE && vAddr+nbytes < FRAM_BASE + FRAM_SIZE) { unsigned raddr = vAddr - FRAM_BASE + SWS_ZONE_FRAMALIAS; FlashReadRamAlias(cpunum, buf, (unsigned long long)raddr, nbytes); return 1; } if (vAddr >= FPROM_BASE && vAddr+nbytes < FPROM_BASE + FPROM_SIZE) { unsigned raddr = vAddr - FPROM_BASE + SWS_ZONE_FPROMALIAS; FlashReadPromAlias(cpunum, buf, (unsigned long long) raddr, nbytes); return 1; }#endif return 0;}intPutFPROMAndFRAM(int cpunum, VA vAddr, uint nbytes, char *buf){#ifndef SOLO if (vAddr >= FRAM_BASE && vAddr+nbytes < FRAM_BASE + FRAM_SIZE) { unsigned raddr = vAddr - FRAM_BASE + SWS_ZONE_FRAMALIAS; FlashWriteRamAlias(cpunum, (unsigned long long)raddr, buf, nbytes); return 1; } if (vAddr >= FPROM_BASE && vAddr+nbytes < FPROM_BASE + FPROM_SIZE) { unsigned raddr = vAddr - FPROM_BASE + SWS_ZONE_FPROMALIAS; FlashWritePromAlias(cpunum, (unsigned long long) raddr, buf, nbytes); return 1; }#endif return 0;}voidFlashliteDrain(void){#ifndef SOLO uint cpu, i, numBadNodes, *badNodes; FlashDrainMemSys(); /* download nodemap */ numBadNodes = FlashGetBadNodesList(0, &badNodes); for (i = 0; i < numBadNodes; i++) { int badNode = badNodes[i]; /* NOTE: this is not exactly what flashlite does for non-Hive addr maps due to roundrobin effect */ uint memPerCPU = MEM_SIZE(0)/NUM_CPUS(0); uint startAddr = memPerCPU * badNode; uint endAddr = memPerCPU * (badNode+1); uint addr; for (addr = startAddr; addr < endAddr; addr += SCACHE_LINE_SIZE) { SimMagic_MakeIncoherent(addr); } CPUVec.ResetCPU(badNode); ResetCPUs(badNode, badNode); } /* incoherent lines on working nodes */ for (cpu = 0; cpu < NUM_CPUS(0); cpu++) { uint *badLines; uint numBadLines; FLASHAddress faddr; /* skip bad nodes */ for (i = 0; i < numBadNodes; i++) { if (cpu == badNodes[i]) break; } if (i != numBadNodes) continue; faddr.ll = 0; faddr.fa.node = cpu; numBadLines = FlashGetIncoherentLinesList(cpu, &badLines); for (i = 0; i < numBadLines; i++) { faddr.fa.offset = badLines[i]; SimMagic_MakeIncoherent(FlashAddrToSimosAddr(faddr.ll)); } free(badLines); if (numBadLines) CPUWarning("WARNING: incoherent lines found.\n"); } free(badNodes); /* download firewall */ if (SIMFIREWALL_ON) { FLASHAddress faddr; LL prot; uint p; for (p = 0; p < MEM_SIZE(0); p += FLASH_PAGE_SIZE) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -