summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Barth <msbarth@us.ibm.com>2011-10-20 15:49:12 -0500
committerA. Patrick Williams III <iawillia@us.ibm.com>2011-10-25 15:12:23 -0500
commit0ad20184aec21ef0560a9eee7e7c26a36ace07e1 (patch)
treebb402e0c2342a791074fde9939701a1bbf9dedef
parent5ab488739184f2b2649193e3f9da695ee334d04f (diff)
downloadtalos-hostboot-0ad20184aec21ef0560a9eee7e7c26a36ace07e1.tar.gz
talos-hostboot-0ad20184aec21ef0560a9eee7e7c26a36ace07e1.zip
Update kernel 'EVICT' pages path to cast out pages when low on memory.
Change-Id: I79b9cfad5d80267c6709b094d7f852d89e08534b Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/452 Tested-by: Jenkins Server Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
-rw-r--r--src/include/kernel/block.H10
-rw-r--r--src/include/kernel/pagemgr.H61
-rw-r--r--src/kernel/basesegment.C5
-rw-r--r--src/kernel/block.C72
-rw-r--r--src/kernel/pagemgr.C5
-rw-r--r--src/kernel/syscall.C2
-rw-r--r--src/usr/testcore/kernel/vmmbasetest.H66
7 files changed, 111 insertions, 110 deletions
diff --git a/src/include/kernel/block.H b/src/include/kernel/block.H
index 01187617f..60aeadaf0 100644
--- a/src/include/kernel/block.H
+++ b/src/include/kernel/block.H
@@ -143,16 +143,8 @@ class Block
/**
* @brief Cast out older phyiscal memory pages
* @param[in] i_type - Castout contraint @see VmmManager::castOutPages()
- * @return number of pages cast out
*/
- size_t castOutPages(uint64_t i_type);
-
- /**
- * @brief Evict a memory page
- * @param[in] i_pte shadow page table entry
- * @return true of page was evicted
- */
- bool evictPage(ShadowPTE* i_pte);
+ void castOutPages(uint64_t i_type);
/**
* @brief Removes a range of pages within a block of virtual memory
diff --git a/src/include/kernel/pagemgr.H b/src/include/kernel/pagemgr.H
index 3ed2c1b34..41fb1e493 100644
--- a/src/include/kernel/pagemgr.H
+++ b/src/include/kernel/pagemgr.H
@@ -39,6 +39,7 @@
class PageManager
{
public:
+
static void init();
static void* allocatePage(size_t n = 1);
@@ -57,53 +58,63 @@ class PageManager
*/
static void coalesce( void );
- enum
- {
- MEMLEN = VmmManager::HTABORG,
+ /**
+ * Retrieve the number of available pages
+ * @returns Number of free pages
+ */
+ static uint64_t availPages();
- BUCKETS = 16,
- };
+ enum
+ {
+ MEMLEN = VmmManager::HTABORG,
+ BUCKETS = 16,
+ };
protected:
- PageManager();
- ~PageManager() {};
+
+ PageManager();
+ ~PageManager() {};
private:
- void* _allocatePage(size_t);
- void _freePage(void*, size_t);
+
+ void* _allocatePage(size_t);
+ void _freePage(void*, size_t);
void _coalesce( void ); //!< see coalesce()
/** see queryAvail() */
- ALWAYS_INLINE
- uint64_t _queryAvail() const
+ ALWAYS_INLINE uint64_t _queryAvail() const
{
return (100*iv_pagesAvail)/iv_pagesTotal;
}
- ALWAYS_INLINE
- uint64_t firstPageAddr( void )
+ ALWAYS_INLINE uint64_t firstPageAddr( void )
{
return ALIGN_PAGE(VFS_LAST_ADDRESS);
}
-
- /** Statistics on number of free pages (for debug) */
+ /** see availPages() */
+ ALWAYS_INLINE uint64_t _availPages() const
+ {
+ return iv_pagesAvail;
+ }
+
+ /** Statistics on number of free pages (for debug) */
uint64_t iv_pagesAvail;
- /** Total number of pages */
+ /** Total number of pages */
uint64_t iv_pagesTotal;
- struct page_t
- {
- page_t* next; //!< Next block of pages
+ static size_t cv_coalesce_count; //!< running coalesced counter
+
+ struct page_t
+ {
+ page_t* next; //!< Next block of pages
page_t* prev; //!< Prev block of pages
page_t* key; //!< Key for pqueue
- };
- Util::Lockfree::Stack<page_t> first_page[BUCKETS];
+ };
+ Util::Lockfree::Stack<page_t> first_page[BUCKETS];
- page_t* pop_bucket(size_t);
- void push_bucket(page_t*, size_t);
-
- static size_t cv_coalesce_count; //!< running coalesced counter
+ page_t* pop_bucket(size_t);
+ void push_bucket(page_t*, size_t);
};
#endif
diff --git a/src/kernel/basesegment.C b/src/kernel/basesegment.C
index dee18600a..3e45b72ef 100644
--- a/src/kernel/basesegment.C
+++ b/src/kernel/basesegment.C
@@ -201,10 +201,7 @@ int BaseSegment::_mmSetPermission(void* i_va, uint64_t i_size, uint64_t i_access
void BaseSegment::castOutPages(uint64_t i_type)
{
- size_t cast_out = 0;
- cast_out = iv_block->castOutPages(i_type);
- // Could try again with a more agressive constraint if cast_out == 0 ????
- if(cast_out) printkd("Cast out %ld pages,Type=%ld\n",cast_out,i_type);
+ iv_block->castOutPages(i_type);
}
/**
* STATIC
diff --git a/src/kernel/block.C b/src/kernel/block.C
index 5b1520b1b..bdec164de 100644
--- a/src/kernel/block.C
+++ b/src/kernel/block.C
@@ -117,15 +117,6 @@ bool Block::handlePageFault(task_t* i_task, uint64_t i_addr)
}
else
{
- // Test code @TODO remove - SET up ro pages to test cast out pages
- //if(pte->getPage() == 0)
- //{
- // void* l_page = PageManager::allocatePage();
- // memset(l_page,'U',PAGESIZE);
- // pte->setPageAddr(reinterpret_cast<uint64_t>(l_page));
- // pte->setPresent(true);
- // pte->setWritable(false);
- //}
return false; //TODO - Swap kernel base block pages for user pages
}
}
@@ -319,50 +310,25 @@ void Block::updateRefCount( uint64_t i_vaddr,
}
// track the changed/dirty bit
- spte->setDirty( i_stats.C );
-
-}
-
-
-bool Block::evictPage(ShadowPTE* i_pte)
-{
- ShadowPTE* pte = i_pte;
- bool do_cast_out = false;
-
- if(!pte->isWritable()) // ro, executable
- {
- do_cast_out = true;
- }
- else // is writable...
+ if (i_stats.C)
{
- // if pte->isWriteTracked() flush then cast out
+ spte->setDirty( i_stats.C );
}
-
- if(do_cast_out)
- {
- PageTableManager::delEntry(pte->getPageAddr());
- PageManager::freePage(reinterpret_cast<void*>(pte->getPageAddr()));
- pte->setPresent(false);
- pte->setPageAddr(NULL);
- }
-
- return do_cast_out;
}
-size_t Block::castOutPages(uint64_t i_type)
+void Block::castOutPages(uint64_t i_type)
{
- size_t cast_out = 0;
+ void* l_vaddr = NULL;
// drill down
if(iv_nextBlock)
{
- cast_out += iv_nextBlock->castOutPages(i_type);
+ iv_nextBlock->castOutPages(i_type);
}
// TODO We will eventually need to skip other blocks as well, such as
// when the memory space grows.
if(iv_baseAddr != 0) // Skip base area
{
- bool is_cast_out = false;
size_t rw_constraint = 5;
size_t ro_constraint = 3;
@@ -386,9 +352,12 @@ size_t Block::castOutPages(uint64_t i_type)
if(pte->isWritable())
{
- if((pte->getLRU() > rw_constraint) && pte->isWriteTracked())
+ if(pte->getLRU() > rw_constraint && pte->isWriteTracked())
{
- is_cast_out = evictPage(pte);
+ //'EVICT' single page
+ l_vaddr = reinterpret_cast<void*>(page);
+ this->removePages(VmmManager::EVICT,l_vaddr,
+ PAGESIZE,NULL);
//printk("+");
}
}
@@ -396,22 +365,15 @@ size_t Block::castOutPages(uint64_t i_type)
{
if(pte->getLRU() > ro_constraint)
{
- is_cast_out = evictPage(pte);
+ //'EVICT' single page
+ l_vaddr = reinterpret_cast<void*>(page);
+ this->removePages(VmmManager::EVICT,l_vaddr,
+ PAGESIZE,NULL);
}
}
-
- if(is_cast_out)
- {
- //printk("-");
- ++cast_out;
- is_cast_out = false;
- }
}
}
- //printk("\n");
}
-
- return cast_out;
}
int Block::mmSetPermission(uint64_t i_va, uint64_t i_size,uint64_t i_access_type)
@@ -566,10 +528,7 @@ int Block::removePages(VmmManager::PAGE_REMOVAL_OPS i_op, void* i_vaddr,
else if (pte->isDirty() && !pte->isWriteTracked() &&
i_op == VmmManager::EVICT)
{
- //Leave as 'printk' to note page was skipped
- printk("Block::removePages >> Unable to EVICT ");
- printk("dirty page thats not write tracked: ");
- printk("va: 0x%.16lX, pa: 0x%.16lX \n",l_vaddr, pageAddr);
+ //Skip page
}
else if (i_op != VmmManager::FLUSH)
{
@@ -584,6 +543,7 @@ int Block::removePages(VmmManager::PAGE_REMOVAL_OPS i_op, void* i_vaddr,
void Block::releasePTE(ShadowPTE* i_pte)
{
+ i_pte->setDirty(false);
i_pte->setPresent(false);
i_pte->setPageAddr(NULL);
}
diff --git a/src/kernel/pagemgr.C b/src/kernel/pagemgr.C
index 82e743ef1..ca5dca055 100644
--- a/src/kernel/pagemgr.C
+++ b/src/kernel/pagemgr.C
@@ -51,6 +51,11 @@ uint64_t PageManager::queryAvail()
return Singleton<PageManager>::instance()._queryAvail();
}
+uint64_t PageManager::availPages()
+{
+ return Singleton<PageManager>::instance()._availPages();
+}
+
PageManager::PageManager() : iv_pagesAvail(0), iv_pagesTotal(0)
{
// Determine first page of un-allocated memory
diff --git a/src/kernel/syscall.C b/src/kernel/syscall.C
index 87cfba6bd..ca32657cf 100644
--- a/src/kernel/syscall.C
+++ b/src/kernel/syscall.C
@@ -61,7 +61,7 @@ void kernel_execute_decrementer()
#endif
KernelMisc::shutdown();
}
-
+ CpuManager::executePeriodics(c);
s->setNextRunnable();
}
diff --git a/src/usr/testcore/kernel/vmmbasetest.H b/src/usr/testcore/kernel/vmmbasetest.H
index 3e1e2fdcd..cd2f20ff1 100644
--- a/src/usr/testcore/kernel/vmmbasetest.H
+++ b/src/usr/testcore/kernel/vmmbasetest.H
@@ -29,13 +29,16 @@
#include <cxxtest/TestSuite.H>
#include <sys/task.h>
#include <kernel/console.H>
+#include <kernel/pagemgr.H>
#include <arch/ppc.H>
#include <sys/mm.h>
+#include <usr/vmmconst.h>
class VmmBaseTest : public CxxTest::TestSuite
{
public:
static volatile int rc;
+ static msg_q_t iv_mq;
void testNullAccess()
{
@@ -90,21 +93,35 @@ class VmmBaseTest : public CxxTest::TestSuite
void testCastOutPages()
{
- //uint64_t vmemaddr = (1ul * 1024 * 1024 * 1024)/2;
- //uint64_t vmsize = 4ul * 1024 * 500;
- //printk("Test case: cast out pages\n");
- //printk("Set up virtual block at %p\n",(void*)vmemaddr);
- //size_t rc = mm_alloc_block(NULL, // need a msgq?
- // (void*)vmemaddr,
- // vmsize);
- //if(rc) printk("RC=%ld\n",rc);
- // touch something on every page
- //for(uint64_t i = vmemaddr; i < (vmemaddr + vmsize); i += PAGESIZE)
- //{
- // if(*((char *)i) != 'U') printk("Yiks %p is %c\n",(void*)i,*((char *)i));
- //}
-
- // see printk buffer for cast out pages
+ uint64_t l_testAddr = VMM_VADDR_RMVPAGE_TEST;
+ uint64_t l_testSize = VMM_SIZE_RMVPAGE_TEST;
+ uint64_t vaddr = l_testAddr+l_testSize;
+ uint64_t vsize = PageManager::availPages()*PAGESIZE;
+ rc = mm_alloc_block(iv_mq,reinterpret_cast<void*>(vaddr),vsize);
+ if (rc != 0)
+ {
+ TS_FAIL("Unable to allocate block.\n");
+ }
+ //TODO - Mix READ_ONLY and WRITE_TRACKED pages to cast out test
+ rc = mm_set_permission(reinterpret_cast<void*>(vaddr),vsize,
+ (uint64_t)(READ_ONLY));
+ if (rc != 0)
+ {
+ TS_FAIL("Failed to set block permissions to READ_ONLY.\n");
+ }
+ task_create(msgDaemon, NULL);
+ //Touch each page until less than 10% free pages remain
+ //printk("Page Percent Avail: 0x%lX\n",PageManager::queryAvail());
+ for(uint64_t i = vaddr; i < (vaddr + vsize); i += PAGESIZE)
+ {
+ if (PageManager::queryAvail() < 10)
+ {
+ printkd("Less than 10 percent pages remain\n");
+ break;
+ }
+ (*(volatile uint64_t *)i); sync();
+ }
+ nanosleep(1,0);
}
private:
@@ -133,7 +150,26 @@ class VmmBaseTest : public CxxTest::TestSuite
task_end();
}
+ static void msgDaemon(void* unused)
+ {
+ msg_t* message = NULL;
+ uint64_t ea = 0;
+ while (1)
+ {
+ message = msg_wait(iv_mq);
+ if (message)
+ {
+ ea = message->data[0];
+ /*printkd("Effective Addr: 0x%lX, %s\n",ea,
+ message->type==MSG_MM_RP_READ?"READ":"WRITE");*/
+ message->data[1] = 0;
+ rc = msg_respond(iv_mq, message);
+ }
+ }
+ }
+
};
volatile int VmmBaseTest::rc = 0;
+msg_q_t VmmBaseTest::iv_mq = msg_q_create();
#endif
OpenPOWER on IntegriCloud