diff options
author | Dan Crowell <dcrowell@us.ibm.com> | 2011-07-06 10:16:21 -0500 |
---|---|---|
committer | Daniel M. Crowell <dcrowell@us.ibm.com> | 2011-07-14 14:53:35 -0500 |
commit | 2583b46750d1e1c062763eff204baa1460e7ae90 (patch) | |
tree | 3fc331001e03e014bba295eda594fe86d248d477 /src/usr | |
parent | accc0f438eca45dcd1058a195d192d51a6f1c4aa (diff) | |
download | talos-hostboot-2583b46750d1e1c062763eff204baa1460e7ae90.tar.gz talos-hostboot-2583b46750d1e1c062763eff204baa1460e7ae90.zip |
Initial checkin of PageTableManager - RTC:3195
Add new delRange method to delete based on page numbers, part of RTC:3195
Plus code review comments from previous commit - http://gfw160.austin.ibm.com:8080/gerrit/188
Change-Id: Ie45365162cf1367c5c0dcc3afc2907a6ddfa53d3
Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/188
Tested-by: Jenkins Server
Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Reviewed-by: MATTHEW S. BARTH <msbarth@us.ibm.com>
Diffstat (limited to 'src/usr')
-rw-r--r-- | src/usr/testcore/kernel/ptmgrtest.H | 392 |
1 files changed, 392 insertions, 0 deletions
diff --git a/src/usr/testcore/kernel/ptmgrtest.H b/src/usr/testcore/kernel/ptmgrtest.H new file mode 100644 index 000000000..6ae1e2b4d --- /dev/null +++ b/src/usr/testcore/kernel/ptmgrtest.H @@ -0,0 +1,392 @@ +#ifndef __PTMGRTEST_H +#define __PTMGRTEST_H +/** + * @file ptmgr.H + * + * @brief Test cases for the Page Table Manager +*/ +#include <cxxtest/TestSuite.H> +#include <arch/ppc.H> +#include <sys/time.h> +#include <kernel/ptmgr.H> + +//#define PASS_TRACE(args...) TS_TRACE(args) +#define PASS_TRACE(args...) + +typedef struct pte_test_t { + uint64_t va; + uint64_t hash; + uint64_t page; + bool loaded; + bool delrangeva; +} pte_test_t; + + +const pte_test_t TEST_DATA[] = { + { 0x0000000000000100, 0x0000000000000000, 100, true, false }, // Page 0 + { 0x000000000053C008, 0x000000000000053C, 101, true, false }, // Something on the heap + { 0x0000000035004000, 0x0000000000035004, 102, true, false }, // <1TB + { 0x0000000040000000, 0x0000000000040000, 103, true, false }, // 1TB + { 0x0000000066666660, 0x0000000000066666, 104, true, false }, // 1TB < x < 2TB + { 0x0000000080000000, 0x0000000000080000, 105, true, false }, // 2TB + { 0x0000000080002000, 0x0000000000080002, 106, true, true }, // 2TB + 2 4K pages + { 0x0000000088888880, 0x0000000000088888, 107, true, false }, // 2TB < x < 3TB + { 0x00000000C0005000, 0x00000000000C0005, 108, true, false }, // >3TB + { 0x0000000040001FF8, 0x0000000000040001, 109, true, false }, // just before a page boundary + + //2 addresses in the same page + { 0x0000000090000040, 0x0000000000090000, 110, true, false }, + { 0x0000000090000100, 0x0000000000090000, 110, true, false }, + + //Out of range address (too big) ?? + { 0x0040000000000000, 0x0000000000004000, 111, true, false }, + + //Several addresses with the same PTEG, enough to overflow a PTEG + { 0x0000000080803000, 0x0000000000080803, 112, false, true }, // 2TB+8MB+12K + { 0x0000000081003000, 0x0000000000081003, 113, true, true }, // 2TB+16MB+12K + { 0x0000000082003000, 0x0000000000082003, 114, true, true }, // 2TB+32MB+12K + { 0x0000000084003000, 0x0000000000084003, 115, true, true }, // 2TB+64MB+12K + { 0x0000000084803000, 0x0000000000084803, 116, true, true }, // 2TB+72MB+12K + { 0x0000000085003000, 0x0000000000085003, 117, true, true }, // 2TB+80MB+12K + { 0x0000000085803000, 0x0000000000085803, 118, true, false }, // 2TB+88MB+12K + { 0x0000000086003000, 0x0000000000086003, 119, true, false }, // 2TB+96MB+12K + { 0x0000000086803000, 0x0000000000086803, 120, true, false }, // 2TB+124MB+12K +}; + + +class ptmgrtest : public CxxTest::TestSuite +{ + private: + enum { + VA_RANGE_START = 0x0000000080001000, + VA_RANGE_FINISH = 0x0000000085800000, + + PN_RANGE_START = 107, + PN_RANGE_FINISH = 115, + }; + + public: + + /** + * 1) Generate hash values for a range of addresses + * 2) Verify hash against hardcoded expected results + */ + void test_hash40( void ) + { + TS_TRACE( ">> test_hash40 <<" ); + printk( ">> test_hash40 <<\n" ); + uint64_t fails, total = 0; + + // Initialize the Page Table + PageTableManager* ptmgr = new PageTableManager(true); + + // test the hashes + uint64_t hash = 0; + for( uint64_t x = 0; x < (sizeof(TEST_DATA)/sizeof(TEST_DATA[0])); x++ ) + { + hash = ptmgr->computeHash( TEST_DATA[x].va ); + if( TEST_DATA[x].hash != hash ) + { + TS_FAIL( "ptmgrtest::test_hash40> ERROR : Hash mismatch" ); + printk( "VA=0x%.16lX, Exp: %.16lX, Act: %.16lX\n", TEST_DATA[x].va, TEST_DATA[x].hash, hash ); + fails++; + } + else + { + PASS_TRACE( "ptmgrtest::test_hash40> PASS : 0x%.16lX", TEST_DATA[x].va ); + } + total++; + } + + delete ptmgr; + + TS_TRACE( "ptmgrtest::test_hash40> fails=%d/%d", fails, total ); + printk( "ptmgrtest::test_hash40> fails=%ld/%ld\n", fails, total ); + } + + /** + * 1) Initialize a local Page Table + * 2) Add some PTEs + * 3) Verify the PTE we just added is in the Page Table + * 4) Verify expected PTEs are still in the Page Table + */ + void test_addEntry( void ) + { + TS_TRACE( ">> test_addEntry <<" ); + printk( ">> test_addEntry <<\n" ); + uint64_t fails = 0; + uint64_t total = 0; + uint64_t status = 0; + uint64_t pn = 0; + + // 1) Initialize the Page Table + PageTableManager* ptmgr = new PageTableManager(true); + + for( uint64_t x = 0; x < (sizeof(TEST_DATA)/sizeof(TEST_DATA[0])); x++ ) + { + // 2) Add some PTEs + ptmgr->_addEntry( TEST_DATA[x].va, TEST_DATA[x].page, VmmManager::NORMAL_ACCESS ); + + // 3) Verify the PTE we just added is in the Page Table + status = ptmgr->_getStatus( TEST_DATA[x].va, pn ); + if( !(status & PageTableManager::PTE_PRESENT) ) + { + TS_FAIL( "ptmgrtest::test_addEntry> ERROR1 : entry not found" ); + TS_TRACE( "Addr=%.16lX, Status=%.16lX", TEST_DATA[x].va, status ); + fails++; + } + else if( (status & PageTableManager::PTE_VALID) && (pn == TEST_DATA[x].page) ) + { + PASS_TRACE( "ptmgrtest::test_addEntry> PASS1 : 0x%.16lX", TEST_DATA[x].va ); + } + else + { + TS_FAIL( "ptmgrtest::test_addEntry> ERROR2 : unknown error" ); + TS_TRACE( "Addr=%.16lX, Status=%.16lX", TEST_DATA[x].va, status ); + fails++; + } + total++; + } + + // 4) Verify expected PTEs are still in the Page Table + //PRINT_PT; + + status = PageTableManager::PTE_UNKNOWN; + for( uint64_t x = 0; x < (sizeof(TEST_DATA)/sizeof(TEST_DATA[0])); x++ ) + { + status = ptmgr->_getStatus( TEST_DATA[x].va, pn ); + + if( !(status & PageTableManager::PTE_PRESENT) && TEST_DATA[x].loaded ) + { + TS_FAIL( "ptmgrtest::test_addEntry> ERROR3 : entry not found" ); + TS_TRACE( "Addr=%.16lX, Status=%.16lX, Exp Page=%ld", TEST_DATA[x].va, status, TEST_DATA[x].page ); + fails++; + } + else if( (status & PageTableManager::PTE_VALID) + && !TEST_DATA[x].loaded ) + { + TS_FAIL( "ptmgrtest::test_addEntry> ERROR4 : PTE should be unloaded" ); + TS_TRACE( "Addr=%.16lX, Status=%.16lX", TEST_DATA[x].va, status ); + TS_TRACE( "Exp Page = %ld, Act Page = %ld", TEST_DATA[x].page, pn ); + fails++; + } + else if( (status & PageTableManager::PTE_VALID) + && (pn == TEST_DATA[x].page) + && TEST_DATA[x].loaded ) + { + PASS_TRACE( "ptmgrtest::test_addEntry> PASS2 : 0x%.16lX", TEST_DATA[x].va ); + } + else if( !(status & PageTableManager::PTE_VALID) + && !TEST_DATA[x].loaded ) + { + PASS_TRACE( "ptmgrtest::test_addEntry> PASS3 : 0x%.16lX", TEST_DATA[x].va ); + } + else + { + TS_FAIL( "ptmgrtest::test_addEntry> ERROR5 : unknown error" ); + TS_TRACE( "Addr=%.16lX, Status=%.16lX", TEST_DATA[x].va, status ); + TS_TRACE( "Exp Page = %ld, Act Page = %ld", TEST_DATA[x].page, pn ); + fails++; + } + total++; + } + + // delete our local table + delete ptmgr; + + TS_TRACE( "ptmgrtest::test_addEntry> fails=%d/%d", fails, total ); + printk( "ptmgrtest::test_addEntry> fails=%ld/%ld\n", fails, total ); + } + + /** + * 1) Initialize the Page Table + * 2) Populate the Page Table + * 3) Remove PTEs one at a time and verify they have been removed + */ + void test_delEntry( void ) + { + TS_TRACE( ">> test_delEntry <<" ); + printk( ">> test_delEntry <<\n" ); + uint64_t fails = 0; + uint64_t total = 0; + uint64_t ignored = 0; + + // 1) Initialize the Page Table + PageTableManager* ptmgr = new PageTableManager(true); + + // 2) Populate the Page Table + fillTable(ptmgr); + //ptmgr->_printPT(); + + // 3) Remove PTEs one at a time and verify they have been removed + for( uint64_t x = 0; x < (sizeof(TEST_DATA)/sizeof(TEST_DATA[0])); x++ ) + { + ptmgr->_delEntry( TEST_DATA[x].va ); + + uint64_t status = ptmgr->_getStatus( TEST_DATA[x].va, ignored ); + if( status & PageTableManager::PTE_VALID ) + { + TS_FAIL( "ptmgrtest::test_delEntry> ERROR : entry still present!" ); + printk( "VA = %.16lX\n", TEST_DATA[x].va ); + PageTableManager::printPTE( TEST_DATA[x].va, true ); + fails++; + } + else + { + PASS_TRACE( "ptmgrtest::test_delEntry> PASS : 0x%.16lX", TEST_DATA[x].va ); + } + total++; + } + + // should print out an empty table + //ptmgr->_printPT(); + + delete ptmgr; + + TS_TRACE( "ptmgrtest::test_delEntry> fails=%d/%d", fails, total ); + printk( "ptmgrtest::test_delEntry> fails=%ld/%ld\n", fails, total ); + } + + /** + * 1) Initialize the Page Table + * 2) Populate the Page Table + * 3) Remove a range of PTEs + * 4) Verify they have been removed + */ + void test_delRangeVA( void ) + { + TS_TRACE( ">> test_delRangeVA <<" ); + printk( ">> test_delRangeVA <<\n" ); + uint64_t fails = 0; + uint64_t total = 0; + uint64_t ignored = 0; + + // 1) Initialize the Page Table + PageTableManager* ptmgr = new PageTableManager(true); + + // 2) Populate the Page Table + fillTable(ptmgr); + //ptmgr->_printPT(); + + // 3) Remove a range of PTEs + ptmgr->_delRangeVA( VA_RANGE_START, VA_RANGE_FINISH ); + + // 4) Verify they have been removed + for( uint64_t x = 0; x < (sizeof(TEST_DATA)/sizeof(TEST_DATA[0])); x++ ) + { + if( TEST_DATA[x].loaded ) + { + uint64_t status = ptmgr->_getStatus( TEST_DATA[x].va, ignored ); + if( (status & PageTableManager::PTE_VALID) && TEST_DATA[x].delrangeva ) + { + TS_FAIL( "ptmgrtest::test_delRangeVA> ERROR1 : entry still present" ); + printk( "addr = %.16lX\n", TEST_DATA[x].va ); + PageTableManager::printPTE( TEST_DATA[x].va, false ); + fails++; + } + else if( !(status & PageTableManager::PTE_VALID) && !TEST_DATA[x].delrangeva ) + { + TS_FAIL( "ptmgrtest::test_delRangeVA> ERROR2 : deleted a wrong entry" ); + printk( "addr = %.16lX\n", TEST_DATA[x].va ); + PageTableManager::printPTE( TEST_DATA[x].va, false ); + fails++; + } + else + { + PASS_TRACE( "%s> PASS : 0x%.16lX\n", __FUNCTION__, TEST_DATA[x].va ); + } + total++; + } + } + + //ptmgr->_printPT(); + + delete ptmgr; + + TS_TRACE( "ptmgrtest::test_delRangeVA> fails=%d/%d", fails, total ); + printk( "ptmgrtest::test_delRangeVA> fails=%ld/%ld\n", fails, total ); + } + + /** + * 1) Initialize the Page Table + * 2) Populate the Page Table + * 3) Remove a range of PTEs + * 4) Verify they have been removed + */ + void test_delRangePN( void ) + { + TS_TRACE( ">> test_delRangePN <<" ); + printk( ">> test_delRangePN <<\n" ); + uint64_t fails = 0; + uint64_t total = 0; + uint64_t pagenum = 0; + + // 1) Initialize the Page Table + PageTableManager* ptmgr = new PageTableManager(true); + + // 2) Populate the Page Table + fillTable(ptmgr); + //ptmgr->_printPT(); + + // 3) Remove a range of PTEs + ptmgr->_delRangePN( PN_RANGE_START, PN_RANGE_FINISH ); + + // 4) Verify they have been removed + for( uint64_t x = 0; x < (sizeof(TEST_DATA)/sizeof(TEST_DATA[0])); x++ ) + { + if( TEST_DATA[x].loaded ) + { + uint64_t status = ptmgr->_getStatus( TEST_DATA[x].va, pagenum ); + if( (status & PageTableManager::PTE_VALID) + && (pagenum >= PN_RANGE_START) + && (pagenum <= PN_RANGE_FINISH) ) + { + TS_FAIL( "ptmgrtest::test_delRangePN> ERROR1 : entry still present" ); + printk( "addr = %.16lX, page=%ld\n", TEST_DATA[x].va, pagenum ); + PageTableManager::printPTE( TEST_DATA[x].va, false ); + fails++; + } + else if( !(status & PageTableManager::PTE_VALID) + && (pagenum < PN_RANGE_START) + && (pagenum > PN_RANGE_FINISH) ) + { + TS_FAIL( "ptmgrtest::test_delRangePN> ERROR2 : deleted a wrong entry" ); + printk( "addr = %.16lX, page=%ld\n", TEST_DATA[x].va, pagenum ); + PageTableManager::printPTE( TEST_DATA[x].va, false ); + fails++; + } + else + { + PASS_TRACE( "%s> PASS : 0x%.16lX\n", __FUNCTION__, TEST_DATA[x].va ); + } + total++; + } + } + + //ptmgr->_printPT(); + + delete ptmgr; + + TS_TRACE( "ptmgrtest::test_delRangePN> fails=%d/%d", fails, total ); + printk( "ptmgrtest::test_delRangePN> fails=%ld/%ld\n", fails, total ); + } + + //@todo - Test LRU + + private: + /** + * @brief Populate the table with entries + */ + void fillTable( PageTableManager* ptmgr ) + { + for( uint64_t x = 0; x < (sizeof(TEST_DATA)/sizeof(TEST_DATA[0])); x++ ) + { + // 2) Add some PTEs + ptmgr->_addEntry( TEST_DATA[x].va, TEST_DATA[x].page, VmmManager::NORMAL_ACCESS ); + } + } + +}; + + +#endif |