diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/include/kernel/basesegment.H | 12 | ||||
-rw-r--r-- | src/include/kernel/block.H | 16 | ||||
-rw-r--r-- | src/include/kernel/ptmgr.H | 64 | ||||
-rw-r--r-- | src/include/kernel/segment.H | 14 | ||||
-rw-r--r-- | src/include/kernel/segmentmgr.H | 13 | ||||
-rw-r--r-- | src/include/kernel/spte.H | 29 | ||||
-rw-r--r-- | src/include/util/align.H | 6 | ||||
-rw-r--r-- | src/kernel/basesegment.C | 6 | ||||
-rw-r--r-- | src/kernel/block.C | 43 | ||||
-rw-r--r-- | src/kernel/ptmgr.C | 175 | ||||
-rw-r--r-- | src/kernel/segmentmgr.C | 21 | ||||
-rw-r--r-- | src/usr/testcore/kernel/ptmgrtest.H | 32 |
12 files changed, 377 insertions, 54 deletions
diff --git a/src/include/kernel/basesegment.H b/src/include/kernel/basesegment.H index a661ae5ce..72869d535 100644 --- a/src/include/kernel/basesegment.H +++ b/src/include/kernel/basesegment.H @@ -63,7 +63,17 @@ class BaseSegment : public Segment * * Calls block chain to deal with page fault. */ - bool handlePageFault(task_t* i_task, uint64_t i_addr); + virtual bool handlePageFault(task_t* i_task, uint64_t i_addr); + + /** + * @brief Implementation of the pure-virtual function from Segment. + * Update LRU statistics on the block that owns the address * + * + * @param[in] i_vaddr - Virtual Address of page + * @param[in] i_stats - Usage statistics + */ + virtual void updateRefCount( uint64_t i_vaddr, + PageTableManager::UsageStats_t i_stats ); /** * @brief Allocates a block of virtual memory of the given size diff --git a/src/include/kernel/block.H b/src/include/kernel/block.H index 94daf0b3a..2421f97f9 100644 --- a/src/include/kernel/block.H +++ b/src/include/kernel/block.H @@ -30,6 +30,8 @@ #include <kernel/task.H> #include <kernel/vmmmgr.H> #include <kernel/blockmsghdlr.H> +#include <kernel/msghandler.H> +#include <kernel/ptmgr.H> class ShadowPTE; class Segment; @@ -140,6 +142,20 @@ class Block */ uint64_t findPhysicalAddress(uint64_t i_vaddr) const; + /** + * @brief Responsible for updating usage counts within the block [chain]. + * + * @param[in] i_vaddr - Abbreviated Virtual Address of page + * (bottom 23 bits are zero) + * @param[in] i_stats - Usage statistics + * + * If the address is not within this block or a matching page cannot be + * found, the block will attempt to make calls down the block-chain + * if it exists. + */ + void updateRefCount( uint64_t i_vaddr, + PageTableManager::UsageStats_t i_stats ); + friend class Segment; friend class BaseSegment; friend class StackSegment; diff --git a/src/include/kernel/ptmgr.H b/src/include/kernel/ptmgr.H index bab4ba3b4..c7505bc1f 100644 --- a/src/include/kernel/ptmgr.H +++ b/src/include/kernel/ptmgr.H @@ -41,14 +41,14 @@ class PageTableManager */ enum { - PTE_UNKNOWN = 0x0000000000000000, /**< Entry wasn't found */ - PTE_PRESENT = 0x0000000000000001, /**< Entry is present in table */ - PTE_VALID = 0x0000000000000002, /**< Entry is valid */ - PTE_READ_ONLY = 0x0000000000000004, /**< Read-Only */ - PTE_EXECUTE = 0x0000000000000008, /**< Execute permission */ - PTE_CACHE_INHIBITED = 0x0000000000000010, /**< Cache-Inhibited Access */ - PTE_MODIFIED = 0x0000000000000020, /**< Page has been modified */ - PTE_ACCESSED = 0x0000000000000040, /**< Page has been accessed */ + PTE_UNKNOWN = 0x0000000000000000, /**< Entry wasn't found */ + PTE_PRESENT = 0x0000000000000001, /**< Entry is present in table */ + PTE_VALID = 0x0000000000000002, /**< Entry is valid */ + PTE_READ_ONLY = 0x0000000000000004, /**< Read-Only */ + PTE_EXECUTE = 0x0000000000000008, /**< Execute permission */ + PTE_CACHE_INHIBITED = 0x0000000000000010, /**< Cache-Inhibited Access */ + PTE_MODIFIED = 0x0000000000000020, /**< Page has been modified */ + PTE_ACCESSED = 0x0000000000000040, /**< Page has been accessed */ }; /** @@ -56,11 +56,30 @@ class PageTableManager */ enum { - PT_SIZE = (1 << 18), /**< Size of Page Table in bytes */ - PTE_SIZE = 2*sizeof(uint64_t), /**< Size of a single Page Table Entry in bytes */ - PTEG_SIZE = 8, /**< Number of PTEs in a single PTE Group */ - PTEG_COUNT = (PT_SIZE / PTE_SIZE) / PTEG_SIZE, /**< Number of PTEGs in the Page Table */ - INVALID_PN = 0xFFFFFFFFFFFFFFFF, /**< Invalid value for a Page Number return */ + PT_SIZE = (1 << 18), /**< Size of Page Table in bytes */ + PTE_SIZE = /**< Size of 1 Page Table Entry in bytes */ + 2*sizeof(uint64_t), + PTEG_SIZE = 8, /**< Number of PTEs in a single PTE Group */ + PTEG_COUNT = /**< Number of PTEGs in the Page Table */ + (PT_SIZE / PTE_SIZE) / PTEG_SIZE, + INVALID_PN = /**< Error value for a Page Number return */ + 0xFFFFFFFFFFFFFFFF, + }; + + /** + * LRU Statistics + */ + struct UsageStats_t { + union { + struct { + uint64_t C:1; /**< Page has been modified */ + uint64_t R:1; /**< Page has been referenced */ + uint64_t LRU:2; /**< Current value of LRU */ + uint64_t rsv:60; /**< Reserved space */ + }; + uint64_t fullword; /**< Full Dword0 */ + }; + UsageStats_t():fullword(0){}; }; /** @@ -175,7 +194,8 @@ class PageTableManager struct { /**< Dword0 Attributes */ uint64_t B:2; /**< 0:1 Segment Size */ uint64_t AVA:55; /**< 2:56 Abbreviated Virtual Address = VA w/o bottom 23 bits */ - uint64_t SW:2; /**< 57:58 =SW[0:1] - Reserved */ + uint64_t SW:1; /**< 57 =SW[] - Reserved */ + uint64_t R2:1; /**< 58 =SW[1] - Shadow R bit */ uint64_t LRU:2; /**< 59:60 =SW[2:3] - Used for LRU algorithm */ uint64_t L:1; /**< 61 Virtual page size */ uint64_t H:1; /**< 62 Hash function identifier */ @@ -413,13 +433,27 @@ class PageTableManager VmmManager::ACCESS_TYPES getAccessType( const PageTableEntry* i_pte ); /** + * @brief Calculate the original Virtual Address from a PTE + * + * @param[in] i_pte PTE to examine, must be pointer to real entry in table + * + * @return uint64_t page-aligned virtual address + */ + uint64_t getVirtAddrFromPTE( const PageTableEntry* i_pte ); + + /** * @brief Fill in default values for the PTE * * @param[out] o_pte PTE to modify */ static void setupDefaultPTE( PageTableEntry* o_pte ); - + /** + * @brief Push C/R/LRU bits to the VMM + * + * @param[in] i_pte PTE to examine, must be pointer to real entry in table + */ + void pushUsageStats( PageTableEntry* i_pte ); // Allow testcase to see inside friend class ptmgrtest; diff --git a/src/include/kernel/segment.H b/src/include/kernel/segment.H index 05c5c0fdc..d7a4a7547 100644 --- a/src/include/kernel/segment.H +++ b/src/include/kernel/segment.H @@ -28,6 +28,7 @@ #include <kernel/task.H> #include <errno.h> +#include <kernel/ptmgr.H> /** @class Segment * @brief Virtual segment class to handle virtual memory management within @@ -75,6 +76,19 @@ class Segment */ virtual uint64_t findPhysicalAddress(uint64_t i_vaddr) const { return -EFAULT; }; + /** + * @brief Update LRU statistics on the block that owns the address + * + * @param[in] i_vaddr - Virtual Address of page + * @param[in] i_stats - Usage statistics + */ + virtual void updateRefCount( uint64_t i_vaddr, + PageTableManager::UsageStats_t i_stats ) + { + //default to a NOOP + return; + }; + protected: /** The base address of the segment. */ const uint64_t iv_baseAddress; diff --git a/src/include/kernel/segmentmgr.H b/src/include/kernel/segmentmgr.H index 0d8caec33..563497047 100644 --- a/src/include/kernel/segmentmgr.H +++ b/src/include/kernel/segmentmgr.H @@ -29,6 +29,7 @@ #include <kernel/task.H> #include <builtins.h> +#include <kernel/ptmgr.H> // Forward declaration. class Segment; @@ -107,6 +108,15 @@ class SegmentManager */ static uint64_t findPhysicalAddress(uint64_t i_vaddr); + /** + * @brief Update LRU statistics on the block that owns the page + * + * @param[in] i_vaddr - Virtual Address of page + * @param[in] i_stats - Usage statistics + */ + static void updateRefCount( uint64_t i_vaddr, + PageTableManager::UsageStats_t i_stats ); + private: /** See handlePageFault. */ @@ -115,6 +125,9 @@ class SegmentManager void _addSegment(Segment* i_segment, size_t i_segId); /** See initSLB. */ void _initSLB(); + /** See updateRefCount. */ + void _updateRefCount( uint64_t i_vaddr, + PageTableManager::UsageStats_t i_stats ); /** See findPhysicalAddress */ uint64_t _findPhysicalAddress(uint64_t i_vaddr) const; diff --git a/src/include/kernel/spte.H b/src/include/kernel/spte.H index 1a284d6e7..abd81dff3 100644 --- a/src/include/kernel/spte.H +++ b/src/include/kernel/spte.H @@ -66,8 +66,11 @@ class ShadowPTE /** Allocate from a zero'd page. */ uint32_t allocate_from_zero:1; + /** LRU value - lower means it was accessed more recently. */ + uint32_t last_access:3; + /** Reserved for future use. */ - uint32_t reserved:6; + uint32_t reserved:3; } PACKED; }; @@ -106,10 +109,34 @@ class ShadowPTE bool isDirty() const { return dirty; }; /** Set dirty bit. */ void setDirty(bool i_dirty) { dirty = i_dirty; }; + /** Get allocate-from-zero bit. */ bool isAllocateFromZero() const { return allocate_from_zero; }; /** Set allocate-from-zero bit. */ void setAllocateFromZero(bool i_zero) { allocate_from_zero = i_zero; }; + + /** Get last_acces bits. */ + uint8_t getLRU() const { return last_access; }; + /** Increment the LRU bits. */ + void incLRU() { + if( last_access < 0b111 ) + { + last_access++; + } + }; + /** Decrement the LRU bits. */ + void decLRU() { + if( last_access > 0 ) + { + last_access--; + } + }; + /** Zero out the LRU bits. */ + void zeroLRU() { + last_access = 0; + }; + + }; #endif diff --git a/src/include/util/align.H b/src/include/util/align.H index 3ac7eee97..7ff67ba38 100644 --- a/src/include/util/align.H +++ b/src/include/util/align.H @@ -25,7 +25,13 @@ #include <limits.h> +// Return a number >= input that is aligned on a 4-byte boundary #define ALIGN_4(u) ((u + 0x3ull) & ~0x3ull) + +// Return a number >= input that is aligned on a page boundary #define ALIGN_PAGE(u) ((u + (PAGESIZE-1)) & ~(PAGESIZE-1)) +// Return a number <= input that is aligned on a page boundary +#define ALIGN_PAGE_DOWN(u) ((u) - (u)%PAGESIZE) + #endif diff --git a/src/kernel/basesegment.C b/src/kernel/basesegment.C index 2dc99d458..72ace03c8 100644 --- a/src/kernel/basesegment.C +++ b/src/kernel/basesegment.C @@ -136,3 +136,9 @@ uint64_t BaseSegment::findPhysicalAddress(uint64_t i_vaddr) const return (iv_block ? iv_block->findPhysicalAddress(i_vaddr) : -EFAULT); } +void BaseSegment::updateRefCount( uint64_t i_vaddr, + PageTableManager::UsageStats_t i_stats ) +{ + // Just call over to block chain + iv_block->updateRefCount(i_vaddr, i_stats); +} diff --git a/src/kernel/block.C b/src/kernel/block.C index 1402bd60a..59a7892f2 100644 --- a/src/kernel/block.C +++ b/src/kernel/block.C @@ -32,7 +32,7 @@ #include <kernel/vmmmgr.H> #include <kernel/ptmgr.H> #include <kernel/pagemgr.H> -//#include <kernel/console.H> +#include <kernel/console.H> Block::~Block() { @@ -235,6 +235,7 @@ void Block::setPageAllocateFromZero(uint64_t i_vAddr) else { // No block owns this address. Code bug. + printk("setPageAllocateFromZero> i_vaddr=0x%.lX\n", i_vAddr ); kassert(iv_nextBlock); } return; @@ -247,10 +248,10 @@ void Block::setPageAllocateFromZero(uint64_t i_vAddr) void Block::releaseAllPages() { - // Release all pages from page table. + // Release all pages from page table. PageTableManager::delRangeVA(iv_baseAddr, iv_baseAddr + iv_size); - // Free all pages back to page manager. + // Free all pages back to page manager. for(uint64_t page = iv_baseAddr; page < (iv_baseAddr + iv_size); page += PAGESIZE) @@ -264,3 +265,39 @@ void Block::releaseAllPages() } } } + +void Block::updateRefCount( uint64_t i_vaddr, + PageTableManager::UsageStats_t i_stats ) +{ + // Check containment, call down chain if address isn't in this block. + if (!isContained(i_vaddr)) + { + if (iv_nextBlock) + { + iv_nextBlock->updateRefCount(i_vaddr, i_stats); + } + else + { + // No block owns this address. Code bug. + printk("updateRefCount> i_vaddr=0x%.lX\n", i_vaddr ); + kassert(iv_nextBlock); + } + return; + } + + ShadowPTE* spte = getPTE(i_vaddr); + + // Adjust the LRU statistics + if( i_stats.R ) + { + spte->zeroLRU(); + } + else + { + spte->incLRU(); + } + + // track the changed/dirty bit + spte->setDirty( i_stats.C ); + +} diff --git a/src/kernel/ptmgr.C b/src/kernel/ptmgr.C index f1e72bbca..0feffb7e6 100644 --- a/src/kernel/ptmgr.C +++ b/src/kernel/ptmgr.C @@ -24,8 +24,10 @@ #include <kernel/vmmmgr.H> #include <util/singleton.H> #include <kernel/console.H> +#include <kernel/segmentmgr.H> #include <arch/ppc.H> #include <assert.h> +#include <util/align.H> //#define Dprintk(...) printkd(args...) #define Dprintk(args...) @@ -308,14 +310,17 @@ void PageTableManager::_addEntry( uint64_t i_vAddr, //Note: no need to lock here because that is handled by higher function + // page-align this address + uint64_t l_vaddr = ALIGN_PAGE_DOWN(i_vAddr); + PageTableEntry pte_data; setupDefaultPTE( &pte_data ); // find the matching PTEG first so we only do it once - uint64_t pteg_addr = findPTEG( i_vAddr ); + uint64_t pteg_addr = findPTEG( l_vaddr ); //look for a matching entry in the table already - PageTableEntry* pte_slot = findPTE( i_vAddr, pteg_addr ); + PageTableEntry* pte_slot = findPTE( l_vaddr, pteg_addr ); if( pte_slot == NULL ) { // look for an empty/invalid entry that we can use @@ -324,14 +329,26 @@ void PageTableManager::_addEntry( uint64_t i_vAddr, { // look for a valid entry we can steal pte_slot = findOldPTE( pteg_addr ); + + // delete the entry that we're going to steal first + delEntry( pte_slot ); } + + // since the entry isn't in the table right now we should + // start fresh with the usage bits + pte_data.C = 0b0; //Clear Changed bit + pte_data.R = 0b0; //Clear Referenced bit + pte_data.LRU = 0b00; //Clear LRU bits } else { - if( (pte_slot->V == 1) && (i_page != pte_slot->PN) ) + if( pte_slot->V == 1 ) { - Eprintk( "**ERROR** PageTableManager::_addEntry> Duplicate PTE with different page number\n" ); - kassert(false); + if( i_page != pte_slot->PN ) + { + Eprintk( "**ERROR** PageTableManager::_addEntry> Duplicate PTE with different page number\n" ); + kassert(false); + } } } @@ -378,7 +395,11 @@ void PageTableManager::_delEntry( uint64_t i_vAddr ) */ void PageTableManager::delEntry( PageTableEntry* i_pte ) { + // clear the entry from the table writePTE( i_pte, i_pte, false ); + + // need to notify VMM when we remove a PTE + pushUsageStats( i_pte ); } /** @@ -412,7 +433,7 @@ void PageTableManager::_delRangePN( uint64_t i_pnStart, { if( (pte->V == 1) && (pte->PN >= i_pnStart) && (pte->PN <= i_pnFinish) ) { - writePTE( pte, pte, false ); + delEntry( pte ); } pte++; @@ -604,12 +625,18 @@ void PageTableManager::writePTE( PageTableEntry* i_pte, PageTableEntry* i_dest, bool i_valid ) { - // are we stealing a PTE - bool pte_stolen = false; + // Are we stealing a valid PTE? if( (i_dest->V == 1) && i_valid ) { - pte_stolen = true; - printPTE( "Stealing", i_dest ); + // If the AVAs match then we're just modifying permissions or something + if( i_pte->AVA != i_dest->AVA ) + { + // this should never happen because we should always go + // through the delEntry() path instead + printPTE( "Stealing", i_dest ); + Eprintk( "**ERROR** PageTableManager::writePTE> Trying to steal a PTE\n" ); + kassert(false); + } } if(ivTABLE) @@ -703,7 +730,7 @@ void PageTableManager::printPTE( const char* i_label, } else { - printkd( "[%4ld:%4ld]> @%p : %.16lX %.16lX : AVA=%16lX, PN=%ld\n", pte_num/PTEG_SIZE, pte_num%PTEG_SIZE, i_pte, i_pte->dword0, i_pte->dword1, i_pte->AVA, i_pte->PN ); + printkd( "[%4ld:%4ld]> @%p : %.16lX %.16lX : VA=%16lX, PN=%ld\n", pte_num/PTEG_SIZE, pte_num%PTEG_SIZE, i_pte, i_pte->dword0, i_pte->dword1, getVirtAddrFromPTE(i_pte), i_pte->PN ); } } @@ -822,9 +849,9 @@ VmmManager::ACCESS_TYPES PageTableManager::getAccessType( const PageTableEntry* */ void PageTableManager::setupDefaultPTE( PageTableEntry* o_pte ) { - o_pte->B = 0b01; //Segment Size (01=1TB) - o_pte->L = 0b0; //Virtual page size (1=>4KB) - o_pte->H = 0b0; //Hash function identifier (0=primary hash) + o_pte->B = 0b01; //Segment Size (01=1TB) + o_pte->L = 0b0; //Virtual page size (1=>4KB) + o_pte->H = 0b0; //Hash function identifier (0=primary hash) } /** @@ -876,7 +903,7 @@ PageTableManager::PageTableEntry* PageTableManager::findOldPTE( uint64_t i_ptegA pte++; } - PageTableManager::printPTE( "Dropping PTE", old_pte ); + //PageTableManager::printPTE( "Dropping PTE", old_pte ); return old_pte; } @@ -908,21 +935,34 @@ void PageTableManager::updateLRU( const PageTableEntry* i_newPTE ) new_pte = *pte_cur; old_pte = *pte_cur; + // if the entry is valid and has been used since last update + // then reset the LRU to 0 and clear the R bit if( (new_pte.V == 1) && (new_pte.R == 1) ) { - new_pte.LRU = 1; + new_pte.LRU = 0; new_pte.R = 0; + new_pte.R2 = 1; // remember that the R bit was set } else { + // page hasn't been used, increment the LRU if( new_pte.LRU < 0b11 ) { new_pte.LRU++; } } - } while( !__sync_bool_compare_and_swap( &(pte_cur->dword0), - old_pte.dword0, - new_pte.dword0 ) ); + + + // if the value currently in the table (pte_cur) is still + // equal to the value we saved off earlier (old_pte) then + // we will write our new data (new_pte) into the table + // else we will try again + } while( !__sync_bool_compare_and_swap( &(pte_cur->dword1), + old_pte.dword1, + new_pte.dword1 ) ); + + // LRU and R2 are on dword0 + pte_cur->dword0 = new_pte.dword0; // tlbie, eieio, tlbsync, ptesync invalidateTLB(pte_cur); @@ -965,3 +1005,100 @@ void PageTableManager::invalidateTLB( PageTableEntry* i_pte ) Tprintk( "<< PageTableManager::invalidateTLB( )\n" ); } +/** + * @brief Calculate the original Virtual Address from a PTE + */ +uint64_t PageTableManager::getVirtAddrFromPTE( const PageTableEntry* i_pte ) +{ + uint64_t pte_addr = (uint64_t)i_pte; + + /* + 0....5....1....5....2....5....3....5....4....5....50...5....6....5....7....5.. full VA (78 bits) + 000000000000000vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv000000000000 top 15 and bottom 12 bits are zero + 000000000000000---------aaaaaaaaaaaaaa---------------------------------------- X=VA[24:37] + 000000000000000bbbbbbbbbbbbBBBBBBBBBBB---------------------------------------- Y=VA[0:37] + 000000000000000-----------------------cccccccccccccccccCCCCCCCCCCC------------ Z=VA[38:65] + 000000000000000dddddddddddddddddddddddddddddddddddddddd----------------------- AVA = VA[0:54] + + 0000000000000000000000000000BBBBBBBBBBB = Y' = VA[27:37] = AVA[27:37] + 0000000000000000000000000000CCCCCCCCCCC = Z' = VA[55:65] + + X^Y^Z % 2048 = ptegnum + 0^Y^Z % 2048 = ptegnum (all of X is above the % line) + Y' ^ Z' = ptegnum + Z' = Y' ^ ptegnum + */ + + // first get the PTEG number (=hash result) based on the PTE pointer + uint64_t pteg_num = (pte_addr - getAddress())/PTEG_SIZE_BYTES; + + // next pull the Y' value out of the AVA + uint64_t Yp = EXTRACT_RJ_LEN( i_pte->AVA, 55, 27, 37 ); + + // next invert the XOR operation from the hash function + uint64_t Zp = Yp ^ pteg_num; + + // finally put everything together to make a complete virtual address + uint64_t va = (Zp << 12) | (i_pte->AVA << 23); + + return va; +} + +/** + * @brief Push C/R/LRU bits to the VMM + * + * @param[in] i_pte PTE to examine, must be pointer to real entry in table + */ +void PageTableManager::pushUsageStats( PageTableEntry* i_pte ) +{ + // skip this in unit-test mode because addresses aren't really backed + if( ivTABLE ) + { + return; + } + + UsageStats_t stats; + + PageTableEntry new_pte = *i_pte; + PageTableEntry old_pte = *i_pte; + + // use this funny loop to avoid races where another thread + // is causing the C bit to be updated at the same time + do { + new_pte = *i_pte; + old_pte = *i_pte; + + // always update the R,R2,C bits, even for invalid entries + // it is up to the caller to be sensible about when this + // function is called + + // read and clear the referenced bit + stats.R = new_pte.R || new_pte.R2; + new_pte.R = 0; + new_pte.R2 = 0; //R2 is on dword0 + + // read and clear the changed bit + stats.C = new_pte.C; + new_pte.C = 0; + + // just read the LRU and send it up + stats.LRU = new_pte.LRU; + + // if the value currently in the table (i_pte) is still + // equal to the value we saved off earlier (old_pte) then + // we will write our new data (new_pte) into the table + // else we will try again + } while( !__sync_bool_compare_and_swap( &(i_pte->dword1), + old_pte.dword1, + new_pte.dword1 ) ); + + // R2 is on dword0 + i_pte->dword0 = new_pte.dword0; + + // tlbie, eieio, tlbsync, ptesync + invalidateTLB(i_pte); + + // now we need to send what we learned to the rest of the VMM + uint64_t va = getVirtAddrFromPTE(i_pte); + SegmentManager::updateRefCount( va, stats ); +} diff --git a/src/kernel/segmentmgr.C b/src/kernel/segmentmgr.C index 3f43db965..c52b4de04 100644 --- a/src/kernel/segmentmgr.C +++ b/src/kernel/segmentmgr.C @@ -49,6 +49,12 @@ uint64_t SegmentManager::findPhysicalAddress(uint64_t i_vaddr) return Singleton<SegmentManager>::instance()._findPhysicalAddress(i_vaddr); } +void SegmentManager::updateRefCount( uint64_t i_vaddr, + PageTableManager::UsageStats_t i_stats ) +{ + Singleton<SegmentManager>::instance()._updateRefCount(i_vaddr,i_stats); +} + bool SegmentManager::_handlePageFault(task_t* i_task, uint64_t i_addr) { size_t segId = getSegmentIdFromAddress(i_addr); @@ -112,3 +118,18 @@ uint64_t SegmentManager::_findPhysicalAddress(uint64_t i_vaddr) const return paddr; } +void SegmentManager::_updateRefCount( uint64_t i_vaddr, + PageTableManager::UsageStats_t i_stats ) +{ + // This constant should come from page manager. Segment size. + const size_t SLBE_s = 40; + + // Get segment ID from effective address. + size_t segId = i_vaddr >> SLBE_s; + + // Call contained segment object to update the reference count + if ((segId < MAX_SEGMENTS) && (NULL != iv_segments[segId])) + { + iv_segments[segId]->updateRefCount( i_vaddr, i_stats ); + } +} diff --git a/src/usr/testcore/kernel/ptmgrtest.H b/src/usr/testcore/kernel/ptmgrtest.H index 9d1793710..c32573a43 100644 --- a/src/usr/testcore/kernel/ptmgrtest.H +++ b/src/usr/testcore/kernel/ptmgrtest.H @@ -95,8 +95,7 @@ class ptmgrtest : public CxxTest::TestSuite */ void test_hash40( void ) { - TS_TRACE( ">> test_hash40 <<" ); - printkd( ">> test_hash40 <<\n" ); + TS_TRACE( ">> ptmgrtest::test_hash40 <<" ); uint64_t fails, total = 0; // Initialize the Page Table @@ -123,7 +122,6 @@ class ptmgrtest : public CxxTest::TestSuite delete ptmgr; TS_TRACE( "ptmgrtest::test_hash40> fails=%d/%d", fails, total ); - printkd( "ptmgrtest::test_hash40> fails=%ld/%ld\n", fails, total ); } /** @@ -134,8 +132,7 @@ class ptmgrtest : public CxxTest::TestSuite */ void test_addEntry( void ) { - TS_TRACE( ">> test_addEntry <<" ); - printkd( ">> test_addEntry <<\n" ); + TS_TRACE( ">> ptmgrtest::test_addEntry <<" ); uint64_t fails = 0; uint64_t total = 0; uint64_t status = 0; @@ -160,6 +157,16 @@ class ptmgrtest : public CxxTest::TestSuite else if( (status & PageTableManager::PTE_VALID) && (pn == TEST_DATA[x].page) ) { PASS_TRACE( "ptmgrtest::test_addEntry> PASS1 : 0x%.16lX", TEST_DATA[x].va ); + + PageTableManager::PageTableEntry* pte = ptmgr->findPTE(TEST_DATA[x].va); + uint64_t va = ptmgr->getVirtAddrFromPTE(pte); + if( va != (TEST_DATA[x].va - TEST_DATA[x].va%4096) ) + { + printk( "ptmgrtest::test_addEntry> ERROR6 : VA doesn't match expected" ); + printk( "Exp=%.16lX, Act=%.16lX", TEST_DATA[x].va, va ); + fails++; + } + total++; } else { @@ -217,7 +224,6 @@ class ptmgrtest : public CxxTest::TestSuite delete ptmgr; TS_TRACE( "ptmgrtest::test_addEntry> fails=%d/%d", fails, total ); - printkd( "ptmgrtest::test_addEntry> fails=%ld/%ld\n", fails, total ); } /** @@ -227,8 +233,7 @@ class ptmgrtest : public CxxTest::TestSuite */ void test_delEntry( void ) { - TS_TRACE( ">> test_delEntry <<" ); - printkd( ">> test_delEntry <<\n" ); + TS_TRACE( ">> ptmgrtest::test_delEntry <<" ); uint64_t fails = 0; uint64_t total = 0; uint64_t ignored = 0; @@ -266,7 +271,6 @@ class ptmgrtest : public CxxTest::TestSuite delete ptmgr; TS_TRACE( "ptmgrtest::test_delEntry> fails=%d/%d", fails, total ); - printkd( "ptmgrtest::test_delEntry> fails=%ld/%ld\n", fails, total ); } /** @@ -277,8 +281,7 @@ class ptmgrtest : public CxxTest::TestSuite */ void test_delRangeVA( void ) { - TS_TRACE( ">> test_delRangeVA <<" ); - printkd( ">> test_delRangeVA <<\n" ); + TS_TRACE( ">> ptmgrtest::test_delRangeVA <<" ); uint64_t fails = 0; uint64_t total = 0; uint64_t ignored = 0; @@ -326,7 +329,6 @@ class ptmgrtest : public CxxTest::TestSuite delete ptmgr; TS_TRACE( "ptmgrtest::test_delRangeVA> fails=%d/%d", fails, total ); - printkd( "ptmgrtest::test_delRangeVA> fails=%ld/%ld\n", fails, total ); } /** @@ -337,8 +339,7 @@ class ptmgrtest : public CxxTest::TestSuite */ void test_delRangePN( void ) { - TS_TRACE( ">> test_delRangePN <<" ); - printkd( ">> test_delRangePN <<\n" ); + TS_TRACE( ">> ptmgrtest::test_delRangePN <<" ); uint64_t fails = 0; uint64_t total = 0; uint64_t pagenum = 0; @@ -390,11 +391,12 @@ class ptmgrtest : public CxxTest::TestSuite delete ptmgr; TS_TRACE( "ptmgrtest::test_delRangePN> fails=%d/%d", fails, total ); - printkd( "ptmgrtest::test_delRangePN> fails=%ld/%ld\n", fails, total ); } //@todo - Test LRU + //@todo - Test propagation of C/R bits to blocks + private: /** * @brief Populate the table with entries |