📄 page.c
字号:
/* ***************************************************************************//* * *//* * page.c - does some memory allocation, plus paging for "virtual memory" *//* * *//* ***************************************************************************//* This code was liberated from flashlite, hence the copyright: *//* ************************************************************************* *//* * * *//* * Copyright (C) 1993-1998 Stanford University * *//* * * *//* * These coded instructions, statements, and computer programs contain * *//* * unpublished proprietary information of Stanford University, and * *//* * are protected by Federal copyright law. They may not be disclosed * *//* * to third parties or copied or duplicated in any form, in whole or * *//* * in part, without the prior written consent of Stanford University. * *//* * * *//* ************************************************************************* *//*#define COMA*/#include <stdio.h>#include <stdlib.h>#include <string.h>#include "solo.h"#include "simtypes.h"#include "sim_error.h"#include "solo_page.h"#include "cp0.h"#include "tcl_init.h"#include "params.h"#ifdef USE_FLASHLITE# include "machine.h"# ifdef FLASHPOINT# include "mipsy_interface.h"# include "flash_interface.h"# endif#endif#include "pcache.h" /* So we know the MHT size */#include "scache.h" /* So we know the MHT size */#include "bstring.h"#define MINIMUM_VA_VALUE 100#define ONE_MEGABYTE 0x100000/* padding so that comaHACKADDR * is on a FLASH cacheline of its * own. We need to avoid a situation * where it is on the same cache line * as soloActiveProcs...bad things * happen if it is!!! */static struct garbage { int PAD[128]; int comaHACKADDR; int PAD1[128];} junk;#ifdef COMAvoid SysPlaceRangeCOMAHack(unsigned procNum, FLASHAddress addrToDelete);#elsevoid SysPlaceRangeCOMAHack(unsigned procNum, FLASHAddress addrToDelete) {}#endifint soloPACompressNodeShift;uint soloPACompressOffsetMask;uint soloLockBase;uint soloBarrierBase;uint soloTotalMemory;static int nextclus = 0; /* next processor to assign pages to */static unsigned *cachepage; /* array of next cacheable space page numbers */static int totalProcs; /* Number of processors on system */static int totalMemPerProc; /* Memory per node */static int applicationMemoryStart; /* ??? */static enum { ROUND_ROBIN, FIRST_TOUCHED} allocationPolicy;/* Global FlashLite declarations *//* local function prototypes */static void InitPageTrans(void);static void InitMemAllocation(void);static int NumBits(unsigned number);static bool RemoveMapping(VA v_addr);#ifdef FLASHPOINT// I need to call this from solo_anl.c when using flashpointbool GetPhysicalAddr(VA v_addr, SoloPA *p_addr, uint *flavor);SoloPA AllocatePage(int module, VA va);void NewMapping(VA v_addr, SoloPA p_addr, uint flavor);#elsestatic bool GetPhysicalAddr(VA v_addr, SoloPA *p_addr, uint *flavor);static SoloPA AllocatePage(int module, VA va);static void NewMapping(VA v_addr, SoloPA p_addr, uint flavor);#endifstatic void TrySysPlaceRange(int cpuNum, EventCallbackHdr *hdr, void *v);static EventCallbackHdr sys_place_range_callback;static int sys_place_range_tries;static VA sys_place_range_start;static VA sys_place_range_stop;static int sys_place_range_node;int sys_place_range_StallCPUS = 0;static unsigned *nextPageFrame;static char *protocol;#define SYS_PLACE_RANGE_QUIESCENT_TIME 100000#define SYS_PLACE_RANGE_MAX_TRIES 15void SoloInitPageTranslation(void){ InitMemAllocation(); InitPageTrans(); ParamLookup(&protocol, "MEMSYS.FLASH.Protocol", PARAM_STRING);}voidSolosys_place_range(VA start, VA stop, int node){ SoloPA pa; VA va; int oldNode; uint flavor; int i;#ifdef DEBUG_PAGE_VERBOSE CPUPrint( "sys_place_range %d: Allocating range %x to %x\n", node, start, stop);#endif pa = 0LL; va = start & SOLO_PAGE_NUMBER_MASK; do { if (!GetPhysicalAddr(va, &pa, &flavor)) { ASSERT(node < totalProcs); pa = AllocatePage(node, va); NewMapping( va, pa, TLB_CACHED); } else { oldNode = SOLO_PA_NODE(pa); if (oldNode != node) {#ifdef DEBUG_PAGE_VERBOSE CPUWarning("sys_place_range %u: Moving page %x (%llx) from %d to %d\n", node, va, pa, oldNode, node);#endif sys_place_range_StallCPUS = 1; /* Tell all the CPU's not to do anything */ sys_place_range_tries = 0; sys_place_range_start = va; sys_place_range_stop = stop; sys_place_range_node = node; sys_place_range_callback.active = 0; EventDoCallback(soloCPUNum, TrySysPlaceRange, &sys_place_range_callback, 0, SYS_PLACE_RANGE_QUIESCENT_TIME); break; /* TrySysPlaceRange will loop for me */ } } va += SOLO_PAGE_SIZE; } while (va < stop);} static voidTrySysPlaceRange(int cpuNum, EventCallbackHdr *hdr, void *v){ SoloPA pa, currentPA; PA realPA; FLASHAddress transit; VA va, currentVA; int cpu, i, j, result, wasDirty; int oldNode; uint flavor; int node = sys_place_range_node;#define LINE_BUFFER_SIZE 1024 char data[LINE_BUFFER_SIZE];#ifdef DEBUG_PAGE_VERBOSE CPUPrint( "TrySysPlaceRange %d: Moving VA range %8.8x to %8.8x\n", node, sys_place_range_start, sys_place_range_stop);#endif ASSERT(LINE_BUFFER_SIZE >= SCACHE_LINE_SIZE); /* Check MHT's to see if anything is outstanding */ for (i=0; i<soloActiveProcs; i++) { for (j = 0; j < MHT_SIZE; j++) { if (CACHE[i].MHT[j].inuse) { CPUPrint("sys_place_range %u: wakeup %d found MHT %d, entry %d in use\n", cpuNum, sys_place_range_tries, i, j); sys_place_range_tries++; if (sys_place_range_tries >= SYS_PLACE_RANGE_MAX_TRIES) { CPUError("sys_place_range %u: too many tries with MHT full\n",cpuNum); } EventDoCallback(cpuNum, TrySysPlaceRange, &sys_place_range_callback, 0, SYS_PLACE_RANGE_QUIESCENT_TIME); return; } } } /* Ok, MHT's seem clean, so let's clean up the caches. Now when I find mappings already established, I go ahead and move them. Grab on to your socks.*/ ASSERT(node < totalProcs); va = sys_place_range_start; do { if (!GetPhysicalAddr(va, &pa, &flavor)) { pa = AllocatePage(node, va); NewMapping( va, pa, TLB_CACHED); } else { oldNode = SOLO_PA_NODE(pa); if (oldNode != node) { for (cpu=0; cpu<soloActiveProcs; cpu++) { for (currentPA = pa, currentVA = va; currentPA < pa + SOLO_PAGE_SIZE; currentPA += SCACHE_LINE_SIZE, currentVA += SCACHE_LINE_SIZE) { realPA = SoloCompressAddr(currentPA); if (CacheExtract(cpu, realPA, SCACHE_LINE_SIZE, &wasDirty, (char *)data)) { if (wasDirty) { bcopy(data, (char *)currentVA, SCACHE_LINE_SIZE); if (!strcmp(protocol,"COMA")) { transit.ll = currentPA; SysPlaceRangeCOMAHack(cpu, transit); } } } } } /* Do the actual remapping operation */ CPUPrint("sys_place_range %u: Moving page %x (%llx) to %d\n", cpuNum, va, pa, node); if (!RemoveMapping(va)) { CPUError("RemoveMapping failed though mapping exists!\n"); } pa = AllocatePage(node, va); NewMapping(va, pa, TLB_CACHED); CPUPrint("sys_place_range %u: VA %x now at PA %llx\n", cpuNum, va, pa); } } va += SOLO_PAGE_SIZE; } while (va < sys_place_range_stop); sys_place_range_StallCPUS = 0;} /* ****************************************************************************//* * V_to_P maps virtual to physical addresses **//* * - global cacheble space assigned round-robin **//* * - private cacheable space assigned to home cluster **//* ****************************************************************************/SoloPASoloV_to_P(int proc, VA va, int clus, bool isFrame, uint *tlbFlavor){ SoloPA pa; bool retVal; uint flavor;#ifdef DEBUG_PAGE_VERBOSE CPUPrint( "V_to_P %u: Translating %x", proc, va);#endif#ifdef T5_MODEL pa = (LL) va;#ifdef DEBUG_PAGE_VERBOSE CPUPrint( "\nV_to_P %u: Returning PA==VA\n", proc);#endif return pa;#else pa = 0LL; if (va < MINIMUM_VA_VALUE) { CPUError("\nV_to_P %d: Got virtual address 0x%x\n", proc,va); } /* Check for references to other spaces */ if (va & VIRTUAL_MSG_MASK) { /* This is MSG space */#ifdef USE_FLASHLITE retVal = GetPhysicalAddr((va & 0x7fffffff), &pa, &flavor); ASSERT(retVal); ASSERT(flavor == TLB_CACHED); pa |= (MSG << SOLO_PA_SPACE_SHIFT); *tlbFlavor = TLB_UNCACHED; flavor = TLB_UNCACHED; /* this is so the (*tlbFlavor) below */ /* doesn't squash the uncached setting. */#ifdef DEBUG_PAGE_VERBOSE CPUPrint("\nMSG_SPACE Returning translation %16.16llx\n", pa);#endif#else CPUError("\nBad access to VA 0x%x\n",va);#endif } else if (!GetPhysicalAddr(va, &pa, &flavor)) { int node; if (isFrame == FALSE) { /* global */ if (allocationPolicy == ROUND_ROBIN) { nextclus = ((va & SOLO_PAGE_NUMBER_MASK) >> SOLO_PAGE_SHIFT) & (totalProcs - 1); node = nextclus; } else { /* first touched */ node = clus; } } else { /* private */ node = proc; } ASSERT(node < totalProcs); pa = AllocatePage(node, va); NewMapping(va, pa, TLB_CACHED); flavor = TLB_CACHED; } (*tlbFlavor) = flavor;#ifdef DEBUG_PAGE_VERBOSE CPUPrint( "Resulting translation --> %16.16llx\n", pa);#endif return pa;#endif /* T5_MODEL */}boolSoloPageHasBeenMapped(VA vaddr){ SoloPA paddr; uint flavor; return (GetPhysicalAddr(vaddr, &paddr, &flavor));}voidSoloEstablishMapping(SoloPA pa, VA va, int space, uint tlbFlavor){ SoloPA addr; uint flavor; /* Make sure we don't have a normal mapping of this virtual address */ /* to some other physical address */ if (GetPhysicalAddr(va, &addr, &flavor)) {#ifdef DEBUG_PAGE_VERBOSE CPUPrint( "EstablishMapping: flushing old mapping!\n");#endif if (!RemoveMapping(va)) { CPUError("RemoveMapping failed though old mapping exists!\n"); } } addr = SOLO_FORM_PA(SOLO_PA_NODE(pa),space,SOLO_PA_OFFSET(pa)); /* Be sure space is set in mapping */ NewMapping(va, addr, tlbFlavor);}intSoloGetHome(unsigned vaddr){ SoloPA paddr; uint flavor; if (GetPhysicalAddr(vaddr, &paddr, &flavor) == FALSE) { return -1; } else { return SOLO_PA_NODE(paddr); }}/* *************************************************************************** *//* * AllocatePage allocates the next page of cacheable space * *//* *************************************************************************** */SoloPAAllocatePage(int module, VA va){ VA pageFrame; unsigned numFrames; PA offset; /* Used for COMA only */ LL current, upperBound, lowerBound; unsigned reservedMemoryPerNode = 0; if (!strcmp(protocol,"COMA")) { ParamLookup(&reservedMemoryPerNode, "MEMSYS.FLASH.ReservedMemoryPerNode", PARAM_INT); } ASSERT(module < totalProcs); numFrames = ONE_MEGABYTE >> SOLO_PAGE_SHIFT; /* pageFrame = (va & (ONE_MEGABYTE - 1)) >> SOLO_PAGE_SHIFT;*/ if (nextPageFrame[module] >= soloLockBase) { nextPageFrame[module] = 0; } pageFrame = nextPageFrame[module]; nextPageFrame[module] = (nextPageFrame[module] + 1) % (ONE_MEGABYTE >> SOLO_PAGE_SHIFT); ASSERT(cachepage[(module * numFrames) + pageFrame] != (totalMemPerProc/ONE_MEGABYTE)); cachepage[(module * numFrames) + pageFrame]++;#define LOG_ONE_MB 20 if (!strcmp(protocol,"COMA")) { if (reservedMemoryPerNode > 0) { lowerBound = (LL)((module*reservedMemoryPerNode)%totalMemPerProc);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -