X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Kernel%2Farch%2Fx86_64%2Fmm_phys.c;h=c2c215b3b99603d96146a1044d4451cedfbc2919;hb=e31829ecc2b8ae2338745f4ed393748704a81531;hp=fcc8547369eef65f643c2b2795cbc6a7f15326ed;hpb=952891ddb96a341c0e24ecb7dec6361c7bbeaece;p=tpg%2Facess2.git diff --git a/Kernel/arch/x86_64/mm_phys.c b/Kernel/arch/x86_64/mm_phys.c index fcc85473..c2c215b3 100644 --- a/Kernel/arch/x86_64/mm_phys.c +++ b/Kernel/arch/x86_64/mm_phys.c @@ -8,6 +8,8 @@ #include #include +#define TRACE_REF 0 + enum eMMPhys_Ranges { MM_PHYS_16BIT, // Does anything need this? @@ -30,12 +32,21 @@ void MM_InitPhys_Multiboot(tMBoot_Info *MBoot); //void MM_DerefPhys(tPAddr PAddr); int MM_int_GetRangeID( tPAddr Addr ); +// === MACROS === +#define PAGE_ALLOC_TEST(__page) (gaMainBitmap[(__page)>>6] & (1ULL << ((__page)&63))) +#define PAGE_ALLOC_SET(__page) do{gaMainBitmap[(__page)>>6] |= (1ULL << ((__page)&63));}while(0) +#define PAGE_ALLOC_CLEAR(__page) do{gaMainBitmap[(__page)>>6] &= ~(1ULL << ((__page)&63));}while(0) +//#define PAGE_MULTIREF_TEST(__page) (gaMultiBitmap[(__page)>>6] & (1ULL << ((__page)&63))) +//#define PAGE_MULTIREF_SET(__page) do{gaMultiBitmap[(__page)>>6] |= 1ULL << ((__page)&63);}while(0) +//#define PAGE_MULTIREF_CLEAR(__page) do{gaMultiBitmap[(__page)>>6] &= ~(1ULL << ((__page)&63));}while(0) + // === GLOBALS === tMutex glPhysicalPages; Uint64 *gaSuperBitmap = (void*)MM_PAGE_SUPBMP; // 1 bit = 64 Pages, 16 MiB per Word Uint64 *gaMainBitmap = (void*)MM_PAGE_BITMAP; // 1 bit = 1 Page, 256 KiB per Word Uint64 *gaMultiBitmap = (void*)MM_PAGE_DBLBMP; // Each bit means that the page is being used multiple times Uint32 *gaiPageReferences = (void*)MM_PAGE_COUNTS; // Reference Counts +void **gapPageNodes = (void*)MM_PAGE_NODES; // Reference Counts tPAddr giFirstFreePage; // First possibly free page Uint64 giPhysRangeFree[NUM_MM_PHYS_RANGES]; // Number of free pages in each range Uint64 giPhysRangeFirst[NUM_MM_PHYS_RANGES]; // First free page in each range @@ -172,7 +183,7 @@ void MM_InitPhys_Multiboot(tMBoot_Info *MBoot) paddr = ent->Base; } - Log(" MM_InitPhys_Multiboot: paddr=0x%x, avail=%i", paddr, avail); + Log("MM_InitPhys_Multiboot: paddr=0x%x, avail=0x%x pg", paddr, avail); // Map while( todo && avail --) @@ -424,12 +435,16 @@ tPAddr MM_AllocPhysRange(int Pages, int MaxBits) for( i = 0; i < Pages; i++, addr++ ) { gaMainBitmap[addr >> 6] |= 1LL << (addr & 63); + if( MM_GetPhysAddr( (tVAddr)&gaiPageReferences[addr] ) ) + gaiPageReferences[addr] = 1; +// Log("page %P refcount = %i", MM_GetRefCount(addr<<12)); rangeID = MM_int_GetRangeID(addr << 12); giPhysRangeFree[ rangeID ] --; LOG("%x == %x", addr, giPhysRangeFirst[ rangeID ]); if(addr == giPhysRangeFirst[ rangeID ]) giPhysRangeFirst[ rangeID ] += 1; } + addr -= Pages; ret = addr; // Save the return address // Update super bitmap @@ -443,6 +458,9 @@ tPAddr MM_AllocPhysRange(int Pages, int MaxBits) } Mutex_Release(&glPhysicalPages); + #if TRACE_REF + Log("MM_AllocPhysRange: ret = %P (Ref %i)", ret << 12, MM_GetRefCount(ret<<12)); + #endif LEAVE('x', ret << 12); return ret << 12; } @@ -460,7 +478,7 @@ tPAddr MM_AllocPhys(void) if( gaiStaticAllocPages[i] ) { tPAddr ret = gaiStaticAllocPages[i]; gaiStaticAllocPages[i] = 0; - Log("MM_AllocPhys: Return %x, static alloc %i", ret, i); + Log("MM_AllocPhys: Return %P, static alloc %i", ret, i); return ret; } } @@ -475,27 +493,43 @@ void MM_RefPhys(tPAddr PAddr) { Uint64 page = PAddr >> 12; - if( PAddr >> 12 > giMaxPhysPage ) return ; + if( page > giMaxPhysPage ) return ; - if( gaMainBitmap[ page >> 6 ] & (1LL << (page&63)) ) + if( PAGE_ALLOC_TEST(page) ) { - // Reference again - gaMultiBitmap[ page >> 6 ] |= 1LL << (page&63); - if( !MM_GetPhysAddr( ((tVAddr)&gaiPageReferences[ page ]) & ~0xFFF ) ) { - if( !MM_Allocate( ((tVAddr)&gaiPageReferences[ page ]) & ~0xFFF ) ) { + tVAddr ref_base = ((tVAddr)&gaiPageReferences[ page ]) & ~0xFFF; + // Allocate reference page + if( !MM_GetPhysAddr(ref_base) ) + { + const int pages_per_refpage = PAGE_SIZE/sizeof(gaiPageReferences[0]); + int i; + int page_base = page / pages_per_refpage * pages_per_refpage; + if( !MM_Allocate( ref_base ) ) { Log_Error("Arch", "Out of memory when allocating reference count page"); return ; } + // Fill block + Log("Allocated references for %P-%P", page_base << 12, (page_base+pages_per_refpage)<<12); + for( i = 0; i < pages_per_refpage; i ++ ) { + int pg = page_base + i; + gaiPageReferences[pg] = !!PAGE_ALLOC_TEST(pg); + } } - gaiPageReferences[ page ] ++; + gaiPageReferences[page] ++; } else { // Allocate - gaMainBitmap[page >> 6] |= 1LL << (page&63); - if( gaMainBitmap[page >> 6 ] + 1 == 0 ) + PAGE_ALLOC_SET(page); + if( gaMainBitmap[page >> 6] + 1 == 0 ) gaSuperBitmap[page>> 12] |= 1LL << ((page >> 6) & 63); + if( MM_GetPhysAddr( (tVAddr)&gaiPageReferences[page] ) ) + gaiPageReferences[page] = 1; } + + #if TRACE_REF + Log("MM_RefPhys: %P referenced (%i)", page << 12, MM_GetRefCount(page << 12)); + #endif } /** @@ -507,18 +541,17 @@ void MM_DerefPhys(tPAddr PAddr) if( PAddr >> 12 > giMaxPhysPage ) return ; - if( gaMultiBitmap[ page >> 6 ] & (1LL << (page&63)) ) { + if( MM_GetPhysAddr( (tVAddr) &gaiPageReferences[page] ) ) + { gaiPageReferences[ page ] --; - if( gaiPageReferences[ page ] == 1 ) - gaMultiBitmap[ page >> 6 ] &= ~(1LL << (page&63)); if( gaiPageReferences[ page ] == 0 ) - gaMainBitmap[ page >> 6 ] &= ~(1LL << (page&63)); + PAGE_ALLOC_CLEAR(page); } else - gaMainBitmap[ page >> 6 ] &= ~(1LL << (page&63)); + PAGE_ALLOC_CLEAR(page); // Update the free counts if the page was freed - if( !(gaMainBitmap[ page >> 6 ] & (1LL << (page&63))) ) + if( !PAGE_ALLOC_TEST(page) ) { int rangeID; rangeID = MM_int_GetRangeID( PAddr ); @@ -533,6 +566,27 @@ void MM_DerefPhys(tPAddr PAddr) if(gaMainBitmap[ page >> 6 ] + 1 != 0 ) { gaSuperBitmap[page >> 12] &= ~(1LL << ((page >> 6) & 63)); } + + #if TRACE_REF + Log("Page %P dereferenced (%i)", page << 12, MM_GetRefCount(page << 12)); + #endif +} + +int MM_GetRefCount( tPAddr PAddr ) +{ + PAddr >>= 12; + + if( PAddr > giMaxPhysPage ) return 0; + + if( MM_GetPhysAddr( (tVAddr)&gaiPageReferences[PAddr] ) ) { + return gaiPageReferences[PAddr]; + } + + if( PAGE_ALLOC_TEST(PAddr) ) + { + return 1; + } + return 0; } /** @@ -553,3 +607,35 @@ int MM_int_GetRangeID( tPAddr Addr ) else return MM_PHYS_16BIT; } + +int MM_SetPageNode(tPAddr PAddr, void *Node) +{ + tPAddr page = PAddr >> 12; + tVAddr node_page = ((tVAddr)&gapPageNodes[page]) & ~(PAGE_SIZE-1); + +// if( !MM_GetRefCount(PAddr) ) return 1; + + if( !MM_GetPhysAddr(node_page) ) { + if( !MM_Allocate(node_page) ) + return -1; + memset( (void*)node_page, 0, PAGE_SIZE ); + } + + gapPageNodes[page] = Node; + return 0; +} + +int MM_GetPageNode(tPAddr PAddr, void **Node) +{ +// if( !MM_GetRefCount(PAddr) ) return 1; + PAddr >>= 12; + + if( !MM_GetPhysAddr( (tVAddr)&gapPageNodes[PAddr] ) ) { + *Node = NULL; + return 0; + } + + *Node = gapPageNodes[PAddr]; + return 0; +} +