diff options
author | Matthew Barth <msbarth@us.ibm.com> | 2011-08-12 10:54:52 -0500 |
---|---|---|
committer | MATTHEW S. BARTH <msbarth@us.ibm.com> | 2011-08-15 16:14:21 -0500 |
commit | 5b4ea4d127be9898ae1aada5df6b06e67ec47086 (patch) | |
tree | 2df7dd4825b8208492a536174f6f6bb4dc86d997 /src | |
parent | fa0113e4599fcca0c2d4c938c88d445d288a952a (diff) | |
download | blackbird-hostboot-5b4ea4d127be9898ae1aada5df6b06e67ec47086.tar.gz blackbird-hostboot-5b4ea4d127be9898ae1aada5df6b06e67ec47086.zip |
Support msgq and paging data for blocks in base segment
Change-Id: I4f1775b6a843140be97f3c328155aa1654086723
Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/254
Tested-by: Jenkins Server
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/include/kernel/basesegment.H | 9 | ||||
-rw-r--r-- | src/include/kernel/block.H | 30 | ||||
-rw-r--r-- | src/kernel/basesegment.C | 25 | ||||
-rw-r--r-- | src/kernel/block.C | 43 | ||||
-rw-r--r-- | src/usr/testcore/kernel/slbtest.H | 13 |
5 files changed, 105 insertions, 15 deletions
diff --git a/src/include/kernel/basesegment.H b/src/include/kernel/basesegment.H index 8086c08b5..210a4100f 100644 --- a/src/include/kernel/basesegment.H +++ b/src/include/kernel/basesegment.H @@ -61,6 +61,15 @@ class BaseSegment : public Segment /** Block-chain associated with this Segment. */ Block* iv_block; + + /** + * @brief Allocates a block of virtual memory of the given size + * @param i_mq[in] - Message queue to be associated with the block + * @param i_va[in] - Base virtual address of the block to be allocated + * @param i_size[in] - Requested virtual memory size of the block + * @return int - 0 for successful block allocation, non-zero otherwise + */ + int _mmAllocBlock(MessageQueue* i_mq,void* i_va,uint64_t i_size); }; #endif diff --git a/src/include/kernel/block.H b/src/include/kernel/block.H index 1de1c1280..45b506a80 100644 --- a/src/include/kernel/block.H +++ b/src/include/kernel/block.H @@ -7,9 +7,11 @@ #include <stdint.h> #include <kernel/task.H> #include <kernel/vmmmgr.H> +#include <kernel/msghandler.H> class ShadowPTE; class Segment; +class MessageQueue; /** @class Block * @brief Provides management of the memory pages associated with a block of @@ -36,13 +38,17 @@ class Block * * @param[in] i_baseAddr - Base virtual Address of the block. * @param[in] i_size - Size of the block (in bytes). + * @param[in] i_msgQueue - Message queue passed along to the handler + * Default: NULL * * Will allocate enough shadow PTEs to track pages in the block. */ - Block(uint64_t i_baseAddr, uint64_t i_size) : + Block(uint64_t i_baseAddr, uint64_t i_size, + MessageQueue* i_msgQueue = NULL) : iv_baseAddr(i_baseAddr), iv_size(i_size), - iv_parent(NULL), iv_nextBlock(NULL), iv_ptes(NULL) - { init(); }; + iv_parent(NULL), iv_nextBlock(NULL), iv_ptes(NULL), + iv_msgHdlr(NULL) + { init(i_msgQueue); }; /** * @brief Destructor. @@ -118,6 +124,18 @@ class Block void setPhysicalPage(uint64_t i_vAddr, uint64_t i_pAddr, VmmManager::ACCESS_TYPES i_access); + /** + * @brief Adds up the total size of all blocks within the segment + * + * @param[in/out] io_totalSize - total size allocated within segment + */ + void totalBlocksAlloc(uint64_t &io_totalSize) + { + io_totalSize=io_totalSize+this->iv_size; + if (iv_nextBlock == NULL) return; + else iv_nextBlock->totalBlocksAlloc(io_totalSize); + } + private: /** Base address of the block */ const uint64_t iv_baseAddr; @@ -131,10 +149,14 @@ class Block /** Pointer to the Shadow PTE entries. */ ShadowPTE* iv_ptes; + /** Pointer to the message handler */ + MessageHandler* iv_msgHdlr; /** * @brief Finish initialization of block. * + * @param[in] i_msgQ - The message queue associated with this block + * * Construct ShadowPTE entries. * * This is defined as a separate function to reduce the code @@ -142,7 +164,7 @@ class Block * "not-in-charge" version of each constructor, so put as much * common code into an init function. */ - void init(); + void init(MessageQueue* i_msgQ); /** * @brief Find the Shadow PTE for a virtual address. diff --git a/src/kernel/basesegment.C b/src/kernel/basesegment.C index d9f5a12e8..35e6375a2 100644 --- a/src/kernel/basesegment.C +++ b/src/kernel/basesegment.C @@ -6,6 +6,8 @@ #include <kernel/block.H> #include <kernel/vmmmgr.H> #include <kernel/cpuid.H> +//#include <kernel/console.H> +#define SLBE_s 40 BaseSegment::~BaseSegment() { @@ -72,9 +74,32 @@ bool BaseSegment::handlePageFault(task_t* i_task, uint64_t i_addr) } /** + * STATIC * Allocates a block of virtual memory of the given size */ int BaseSegment::mmAllocBlock(MessageQueue* i_mq,void* i_va,uint64_t i_size) { + return Singleton<BaseSegment>::instance()._mmAllocBlock(i_mq,i_va,i_size); +} + +/** + * Allocates a block of virtual memory of the given size + */ +int BaseSegment::_mmAllocBlock(MessageQueue* i_mq,void* i_va,uint64_t i_size) +{ + uint64_t l_vaddr = reinterpret_cast<uint64_t>(i_va); + uint64_t l_blockSizeTotal = 0;//iv_block->iv_size; + iv_block->totalBlocksAlloc(l_blockSizeTotal); + //Verify input address and size falls within this segment's address range + if ((l_vaddr < this->getBaseAddress() || + l_vaddr >= (this->getBaseAddress() + (1ull << SLBE_s))) && + (l_blockSizeTotal+i_size <= (1ull << SLBE_s))) + { + return -1; + } + //TODO - Align i_size to page size + Block* l_block = new Block(l_vaddr, i_size, i_mq); + l_block->setParent(this); + iv_block->appendBlock(l_block); return 0; } diff --git a/src/kernel/block.C b/src/kernel/block.C index 25157dac5..d5cc685d8 100644 --- a/src/kernel/block.C +++ b/src/kernel/block.C @@ -1,11 +1,14 @@ #include <limits.h> #include <assert.h> +#include <sys/msg.h> + #include <kernel/block.H> #include <kernel/spte.H> #include <kernel/vmmmgr.H> #include <kernel/ptmgr.H> - +#include <kernel/pagemgr.H> +//#include <kernel/console.H> Block::~Block() { // Release shadow PTE array. @@ -18,10 +21,16 @@ Block::~Block() } } -void Block::init() +void Block::init(MessageQueue* i_msgQ) { // Create a shadow PTE for each page. iv_ptes = new ShadowPTE[iv_size / PAGESIZE]; + this->iv_msgHdlr = NULL; + if (i_msgQ != NULL) + { + //Create message handler attribute for this block with this msgq + this->iv_msgHdlr = new MessageHandler(VmmManager::getLock(),i_msgQ); + } } ShadowPTE* Block::getPTE(uint64_t i_addr) const @@ -42,13 +51,29 @@ bool Block::handlePageFault(task_t* i_task, uint64_t i_addr) if (!pte->isPresent()) { - // TODO. Needs swapping support. - return false; - } - - if (pte->getPage() == 0) - { - return false; + if (this->iv_msgHdlr != NULL) + { + void* l_page = reinterpret_cast<void*>(pte->getPageAddr()); + //If the page data is zero, create the page + if (pte->getPage() == 0) + { + l_page = PageManager::allocatePage(); + //Add to ShadowPTE + pte->setPageAddr(reinterpret_cast<uint64_t>(l_page)); + //TODO - Update to correct permissions requested + pte->setExecutable(true); + pte->setWritable(false); + } + //Send message to handler to read page + this->iv_msgHdlr->sendMessage(MSG_MM_RP_READ, + reinterpret_cast<void*>(i_addr),l_page,i_task); + //Done(waiting for response) + return true; + } + else + { + return false; //TODO - Swap kernel base block pages for user pages + } } // Add page table entry. diff --git a/src/usr/testcore/kernel/slbtest.H b/src/usr/testcore/kernel/slbtest.H index 0572ca068..d5920a14f 100644 --- a/src/usr/testcore/kernel/slbtest.H +++ b/src/usr/testcore/kernel/slbtest.H @@ -69,13 +69,22 @@ class slbtest: public CxxTest::TestSuite int rc = -1; msg_q_t mq = msg_q_create(); //Create empty message queue uint64_t va = 0xC800000000; //800GB - uint64_t size = 0x40000000; //1GB - printk("Allocate 1GB block with empty msgq @ vaddr = 800GB within base segment\n"); + uint64_t size = 0x100000; //1MB + printk("Allocate 1MB block with empty msgq @ vaddr = 800GB within base segment\n"); rc = mm_alloc_block(mq,reinterpret_cast<void*>(va),size); if (rc != 0) { TS_FAIL("Failed to create BaseSegment block\n"); } + msg_q_t mq2 = msg_q_create(); //Create empty message queue + uint64_t va2 = 0xE100000000; //900GB + uint64_t size2 = 0x100000; //1MB + printk("Allocate 1MB block with empty msgq @ vaddr = 900GB within base segment\n"); + rc = mm_alloc_block(mq2,reinterpret_cast<void*>(va2),size2); + if (rc != 0) + { + TS_FAIL("Failed to create BaseSegment block\n"); + } } private: |