summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMatthew Barth <msbarth@us.ibm.com>2011-08-12 10:54:52 -0500
committerMATTHEW S. BARTH <msbarth@us.ibm.com>2011-08-15 16:14:21 -0500
commit5b4ea4d127be9898ae1aada5df6b06e67ec47086 (patch)
tree2df7dd4825b8208492a536174f6f6bb4dc86d997 /src
parentfa0113e4599fcca0c2d4c938c88d445d288a952a (diff)
downloadtalos-hostboot-5b4ea4d127be9898ae1aada5df6b06e67ec47086.tar.gz
talos-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.H9
-rw-r--r--src/include/kernel/block.H30
-rw-r--r--src/kernel/basesegment.C25
-rw-r--r--src/kernel/block.C43
-rw-r--r--src/usr/testcore/kernel/slbtest.H13
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:
OpenPOWER on IntegriCloud