summaryrefslogtreecommitdiffstats
path: root/src/kernel
diff options
context:
space:
mode:
authorPatrick Williams <iawillia@us.ibm.com>2012-01-11 10:25:12 -0600
committerA. Patrick Williams III <iawillia@us.ibm.com>2012-01-18 09:52:45 -0600
commitb699fc329722088174afe6031351d3bddb559f6c (patch)
tree62e2ad43fb7becba393346fbb2aeca1ba140efdf /src/kernel
parent811a7e18fb3630f4af77c545f057aa147b18334c (diff)
downloadtalos-hostboot-b699fc329722088174afe6031351d3bddb559f6c.tar.gz
talos-hostboot-b699fc329722088174afe6031351d3bddb559f6c.zip
Support additional device segments and MMIO blocks
Change-Id: Icd2e9ed7de2c0227b25979622d0f37a77595570a Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/609 Tested-by: Jenkins Server Reviewed-by: MATTHEW S. BARTH <msbarth@us.ibm.com> Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com> Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src/kernel')
-rw-r--r--src/kernel/devicesegment.C50
-rw-r--r--src/kernel/segmentmgr.C48
-rw-r--r--src/kernel/vmmmgr.C42
3 files changed, 87 insertions, 53 deletions
diff --git a/src/kernel/devicesegment.C b/src/kernel/devicesegment.C
index 479183d4c..fae4b7032 100644
--- a/src/kernel/devicesegment.C
+++ b/src/kernel/devicesegment.C
@@ -22,6 +22,7 @@
// IBM_PROLOG_END
#include <util/singleton.H>
#include <limits.h>
+#include <assert.h>
#include <kernel/vmmmgr.H>
#include <kernel/ptmgr.H>
@@ -31,38 +32,14 @@
#include <kernel/console.H>
/**
- * STATIC
- * @brief Add the device segment
+ * @brief Add the device segment to the SegmentManager.
*/
-void DeviceSegment::init()
+void DeviceSegment::init(size_t segId)
{
- Singleton<DeviceSegment>::instance()._init();
-}
-
-/**
- * STATIC
- * @brief Map a device into the device segment(2TB)
- */
-void* DeviceSegment::devMap(void *ra, uint64_t i_devDataSize)
-{
- return Singleton<DeviceSegment>::instance()._devMap(ra,i_devDataSize);
-}
-
-/**
- * STATIC
- * @brief Unmap a device from the device segment(2TB)
- */
-int DeviceSegment::devUnmap(void *ea)
-{
- return Singleton<DeviceSegment>::instance()._devUnmap(ea);
-}
+ kassert((segId >= SegmentManager::MMIO_FIRST_SEGMENT_ID) &&
+ (segId <= SegmentManager::MMIO_LAST_SEGMENT_ID));
-/**
- * @brief Add the device segment
- */
-void DeviceSegment::_init()
-{
- SegmentManager::addSegment(this, SegmentManager::MMIO_SEGMENT_ID);
+ SegmentManager::addSegment(this, segId);
}
/**
@@ -101,12 +78,12 @@ bool DeviceSegment::handlePageFault(task_t* i_task, uint64_t i_addr)
/**
- * @brief Map a device into the device segment(2TB)
+ * @brief Map a device into the device segment.
* @param ra[in] - Void pointer to real address to be mapped in
* @param i_devDataSize[in] - Size of device segment block
* @return void* - Pointer to beginning virtual address, NULL otherwise
*/
-void *DeviceSegment::_devMap(void *ra, uint64_t i_devDataSize)
+void *DeviceSegment::devMap(void *ra, uint64_t i_devDataSize)
{
void *segBlock = NULL;
if (i_devDataSize <= THIRTYTWO_GB)
@@ -125,10 +102,6 @@ void *DeviceSegment::_devMap(void *ra, uint64_t i_devDataSize)
break;
}
}
- if (segBlock == NULL)
- {
- printk("Unable to map device, no empty segment blocks found\n");
- }
}
else
{
@@ -139,12 +112,7 @@ void *DeviceSegment::_devMap(void *ra, uint64_t i_devDataSize)
return segBlock;
}
-/**
- * @brief Unmap a device from the device segment(2TB)
- * @param ea[in] - Void pointer to effective address
- * @return int - 0 for successful unmap, non-zero otherwise
- */
-int DeviceSegment::_devUnmap(void *ea)
+int DeviceSegment::devUnmap(void *ea)
{
int rc = -EINVAL;
uint64_t segment_ea = reinterpret_cast<uint64_t>(ea);
diff --git a/src/kernel/segmentmgr.C b/src/kernel/segmentmgr.C
index 0b4370cfa..6659c634c 100644
--- a/src/kernel/segmentmgr.C
+++ b/src/kernel/segmentmgr.C
@@ -24,9 +24,11 @@
#include <errno.h>
#include <arch/ppc.H>
#include <util/singleton.H>
+#include <kernel/console.H>
#include <kernel/segmentmgr.H>
#include <kernel/segment.H>
+#include <kernel/devicesegment.H>
bool SegmentManager::handlePageFault(task_t* i_task, uint64_t i_addr)
{
@@ -60,6 +62,16 @@ void SegmentManager::castOutPages(uint64_t i_type)
Singleton<SegmentManager>::instance()._castOutPages(i_type);
}
+void* SegmentManager::devMap(void* ra, uint64_t i_devDataSize)
+{
+ return Singleton<SegmentManager>::instance()._devMap(ra, i_devDataSize);
+}
+
+int SegmentManager::devUnmap(void* ea)
+{
+ return Singleton<SegmentManager>::instance()._devUnmap(ea);
+}
+
bool SegmentManager::_handlePageFault(task_t* i_task, uint64_t i_addr)
{
size_t segId = getSegmentIdFromAddress(i_addr);
@@ -146,3 +158,39 @@ void SegmentManager::_castOutPages(uint64_t i_type)
}
}
}
+
+void* SegmentManager::_devMap(void* ra, uint64_t i_devDataSize)
+{
+ void* ea = NULL;
+ for (size_t i = MMIO_FIRST_SEGMENT_ID; i <= MMIO_LAST_SEGMENT_ID; i++)
+ {
+ if (NULL == iv_segments[i]) continue;
+
+ ea = reinterpret_cast<DeviceSegment*>(iv_segments[i])->
+ devMap(ra, i_devDataSize);
+
+ if (ea != NULL) break;
+ }
+
+ if (ea == NULL)
+ {
+ printk("SegmentManager: Ran out of device segment blocks.\n");
+ }
+
+ return ea;
+}
+
+int SegmentManager::_devUnmap(void* ea)
+{
+ size_t segId = getSegmentIdFromAddress(reinterpret_cast<uint64_t>(ea));
+ if ((segId < MMIO_FIRST_SEGMENT_ID) ||
+ (segId > MMIO_LAST_SEGMENT_ID) ||
+ (NULL == iv_segments[segId]))
+ {
+ return -EINVAL;
+ }
+
+ return reinterpret_cast<DeviceSegment*>(iv_segments[segId])->devUnmap(ea);
+}
+
+
diff --git a/src/kernel/vmmmgr.C b/src/kernel/vmmmgr.C
index b0fe28415..b1f13f1a3 100644
--- a/src/kernel/vmmmgr.C
+++ b/src/kernel/vmmmgr.C
@@ -45,7 +45,11 @@ void VmmManager::init()
BaseSegment::init();
StackSegment::init();
- DeviceSegment::init();
+ for (size_t i = SegmentManager::MMIO_FIRST_SEGMENT_ID;
+ i < SegmentManager::MMIO_LAST_SEGMENT_ID; ++i)
+ {
+ new DeviceSegment(i); // Self-registers with SegmentManager.
+ }
SegmentManager::initSLB();
v.initPTEs();
@@ -82,23 +86,14 @@ void VmmManager::flushPageTable( void )
Singleton<VmmManager>::instance()._flushPageTable();
}
-
-/**
- * STATIC
- * @brief A facade to map a device into the device segment(2TB)
- */
void* VmmManager::devMap(void* ra, uint64_t i_devDataSize)
{
- return DeviceSegment::devMap(ra, i_devDataSize);
+ return Singleton<VmmManager>::instance()._devMap(ra, i_devDataSize);
}
-/**
- * STATIC
- * @brief A facade to unmap a device from the device segment(2TB)
- */
int VmmManager::devUnmap(void* ea)
{
- return DeviceSegment::devUnmap(ea);
+ return Singleton<VmmManager>::instance()._devUnmap(ea);
}
void VmmManager::initPTEs()
@@ -211,3 +206,26 @@ void VmmManager::_flushPageTable( void )
lock.unlock();
}
+
+void* VmmManager::_devMap(void* ra, uint64_t i_devDataSize)
+{
+ void* ea = NULL;
+
+ lock.lock();
+ ea = SegmentManager::devMap(ra, i_devDataSize);
+ lock.unlock();
+
+ return ea;
+}
+
+int VmmManager::_devUnmap(void* ea)
+{
+ int rc = 0;
+
+ lock.lock();
+ rc = SegmentManager::devUnmap(ea);
+ lock.unlock();
+
+ return rc;
+}
+
OpenPOWER on IntegriCloud