summaryrefslogtreecommitdiffstats
path: root/src/usr
diff options
context:
space:
mode:
authorDan Crowell <dcrowell@us.ibm.com>2011-07-06 10:16:21 -0500
committerDaniel M. Crowell <dcrowell@us.ibm.com>2011-07-14 14:53:35 -0500
commit2583b46750d1e1c062763eff204baa1460e7ae90 (patch)
tree3fc331001e03e014bba295eda594fe86d248d477 /src/usr
parentaccc0f438eca45dcd1058a195d192d51a6f1c4aa (diff)
downloadtalos-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.H392
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
OpenPOWER on IntegriCloud