summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/include/kernel/devicesegment.H35
-rw-r--r--src/include/kernel/segmentmgr.H36
-rw-r--r--src/include/kernel/vmmmgr.H9
-rw-r--r--src/include/usr/vmmconst.h8
-rw-r--r--src/kernel/devicesegment.C50
-rw-r--r--src/kernel/segmentmgr.C48
-rw-r--r--src/kernel/vmmmgr.C42
-rw-r--r--src/usr/intr/intrrp.C24
-rw-r--r--src/usr/testcore/kernel/segmenttest.H29
9 files changed, 183 insertions, 98 deletions
diff --git a/src/include/kernel/devicesegment.H b/src/include/kernel/devicesegment.H
index c60619705..dcaf78af8 100644
--- a/src/include/kernel/devicesegment.H
+++ b/src/include/kernel/devicesegment.H
@@ -35,9 +35,14 @@ class DeviceSegment : public Segment
{
public:
/**
- * @brief Constructor (Device segment at 2TB)
+ * @brief Constructor (Device segment at 2TB + N)
+ *
+ * @param[in] segId - Segment ID to map this device segment at.
+ *
+ * Associates itself with the SegmentManager.
*/
- DeviceSegment() : Segment(VMM_VADDR_DEVICE_SEGMENT) {};
+ explicit DeviceSegment(size_t segId) : Segment(segId * TERABYTE)
+ { init(segId); };
/**
* @brief Destructor
@@ -45,9 +50,9 @@ class DeviceSegment : public Segment
~DeviceSegment() {};
/**
- * @brief Add the device segment
+ * @brief Add the device segment to the SegmentManager.
*/
- static void init();
+ void init(size_t segId);
/**
* @brief Handle a page fault for a device address access
@@ -60,19 +65,19 @@ class DeviceSegment : public Segment
/**
- * @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
*/
- static void* devMap(void* ra, uint64_t i_devDataSize);
+ void* devMap(void* ra, uint64_t i_devDataSize);
/**
- * @brief Unmap a device from the device segment(2TB)
+ * @brief Unmap a device from the device segment.
* @param ea[in] - Void pointer to effective address
* @return int - 0 for successful unmap, non-zero otherwise
*/
- static int devUnmap(void* ea);
+ int devUnmap(void* ea);
private:
/**
@@ -100,20 +105,6 @@ class DeviceSegment : public Segment
*/
void _init();
- /**
- * @brief Map a device into the device segment(2TB)
- * @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* _devMap(void* ra, uint64_t i_devDataSize);
-
- /**
- * @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 _devUnmap(void* ea);
};
#endif
diff --git a/src/include/kernel/segmentmgr.H b/src/include/kernel/segmentmgr.H
index d2e4be2df..85ecf3269 100644
--- a/src/include/kernel/segmentmgr.H
+++ b/src/include/kernel/segmentmgr.H
@@ -51,17 +51,18 @@ class SegmentManager
BASE_SEGMENT_ID = 0,
/** Task Stack Segment (1-2TB). */
STACK_SEGMENT_ID = 1,
- /** MMIO Space Segment (2-3TB). */
- MMIO_SEGMENT_ID = 2,
+ /** MMIO Space Segments (2-11TB). */
+ MMIO_FIRST_SEGMENT_ID = 2,
+ MMIO_LAST_SEGMENT_ID = MMIO_FIRST_SEGMENT_ID + 8,
- MAX_SEGMENTS = 4
+ MAX_SEGMENTS = 16
};
enum
{
CI_ACCESS = 0xFFFFFFFF
// Set to all F's to identify this type
- };
+ };
/**
* Constructor. Initializes instance variables.
@@ -130,12 +131,30 @@ class SegmentManager
*/
static void castOutPages(uint64_t i_type);
+ /**
+ * @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
+ */
+ static void* devMap(void* ra, uint64_t i_devDataSize);
+
+ /**
+ * @brief Unmap a device from the device segment
+ * @param ea[in] - Void pointer to effective address
+ * @return int - 0 for successful unmap, non-zero otherwise
+ */
+ static int devUnmap(void* ea);
+
+
private:
/** See handlePageFault. */
bool _handlePageFault(task_t* i_task, uint64_t i_addr);
/** See addSegment. */
void _addSegment(Segment* i_segment, size_t i_segId);
+ /** See getSegment. */
+ Segment* _getSegment(size_t i_segId);
/** See initSLB. */
void _initSLB();
/** See updateRefCount. */
@@ -143,14 +162,19 @@ class SegmentManager
PageTableManager::UsageStats_t i_stats );
/** See castOutPages */
void _castOutPages(uint64_t i_type);
+ /** See devMap */
+ void* _devMap(void* ra, uint64_t i_devDataSize);
+ /** See devUnmap */
+ int _devUnmap(void* ea);
+
/** See findPhysicalAddress */
uint64_t _findPhysicalAddress(uint64_t i_vaddr) const;
ALWAYS_INLINE
- size_t getSegmentIdFromAddress(uint64_t i_addr) const
+ static size_t getSegmentIdFromAddress(uint64_t i_addr)
{
- return i_addr >> SLBE_s;
+ return i_addr >> SLBE_s;
}
/** Array of segment objects to associated segment IDs. */
diff --git a/src/include/kernel/vmmmgr.H b/src/include/kernel/vmmmgr.H
index 3782bb762..46f283e18 100644
--- a/src/include/kernel/vmmmgr.H
+++ b/src/include/kernel/vmmmgr.H
@@ -86,7 +86,7 @@ class VmmManager
static bool pteMiss(task_t* t, uint64_t effAddr);
/**
- * @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
@@ -94,7 +94,7 @@ class VmmManager
static void* devMap(void* ra, uint64_t i_devDataSize);
/**
- * @brief Unmap a device from the device segment(2TB)
+ * @brief Unmap a device from the device segment
* @param ea[in] - Void pointer to effective address
* @return int - 0 for successful unmap, non-zero otherwise
*/
@@ -198,6 +198,11 @@ class VmmManager
int _mmRemovePages(VmmManager::PAGE_REMOVAL_OPS i_op,void* i_vaddr,
uint64_t i_size,task_t* i_task);
+ /** See devMap */
+ void* _devMap(void* ra, uint64_t i_devDataSize);
+ /** See devUnmap */
+ int _devUnmap(void* ea);
+
public:
friend class Block;
friend class StackSegment;
diff --git a/src/include/usr/vmmconst.h b/src/include/usr/vmmconst.h
index f490f1301..5036b8146 100644
--- a/src/include/usr/vmmconst.h
+++ b/src/include/usr/vmmconst.h
@@ -37,8 +37,10 @@
/** Stack Segment is at 1 TB */
#define VMM_VADDR_STACK_SEGMENT (1 * TERABYTE)
-/** Device Segment is at 2 TB */
-#define VMM_VADDR_DEVICE_SEGMENT (2 * TERABYTE)
+/** Device Segments are at 2 TB - 10 TB */
+#define VMM_VADDR_DEVICE_SEGMENT_FIRST (2 * TERABYTE)
+#define VMM_VADDR_DEVICE_SEGMENT_LAST (VMM_VADDR_DEVICE_SEGMENT_FIRST + \
+ (8 * TERABYTE))
/**
@@ -54,7 +56,7 @@
/** Attribute Resource Provider */
// Note: Not simplified to make it easier to extract with the PNOR targeting
-// image generator script
+// image generator script
#define VMM_VADDR_ATTR_RP (3ul * 1024ul * 1024ul * 1024ul)
/** Virtual memory block priorities */
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;
+}
+
diff --git a/src/usr/intr/intrrp.C b/src/usr/intr/intrrp.C
index d328c75ae..5099c437c 100644
--- a/src/usr/intr/intrrp.C
+++ b/src/usr/intr/intrrp.C
@@ -54,7 +54,7 @@ void IntrRp::init( void * i_taskArgs )
{
errlHndl_t err = NULL;
err = Singleton<IntrRp>::instance()._init();
- INITSERVICE::TaskArgs* args =
+ INITSERVICE::TaskArgs* args =
static_cast<INITSERVICE::TaskArgs*>(i_taskArgs);
if(err)
{
@@ -68,7 +68,7 @@ void IntrRp::init( void * i_taskArgs )
// BaseAddress:
// BA[18:43] = ICPBAR (P8 says [14:43] (30 bits))
// BA[47:49] = COREid (0-7)
-// BA[50:51] = cpu thread (0-3)
+// BA[50:51] = cpu thread (0-3)
//
// BA+0 = XIRR (poll - Read/Write has no side effects))
// BA+4 = XIRR (Read locks HW, Write -> EOI to HW))
@@ -108,7 +108,7 @@ errlHndl_t IntrRp::_init()
//targetService.masterProcChipTargetHandle( procTarget );
//
// TODO What if this does not jive with with the PIR?
-
+
// TODO Does this need to be read here?
//err = deviceRead(procTarget,
// &realAddr,
@@ -116,7 +116,7 @@ errlHndl_t IntrRp::_init()
// DEVICE_SCOM_ADDRESS(ICPBAR_SCOM_ADDR));
//if(err) return err;
- if(realAddr == 0)
+ if(realAddr == 0)
{
realAddr = (static_cast<uint64_t>(ICPBAR_VAL)) << 34;
}
@@ -132,7 +132,7 @@ errlHndl_t IntrRp::_init()
// The realAddr is the base address for the whole system.
- // Therefore the realAddr must be based on the processor with
+ // Therefore the realAddr must be based on the processor with
// lowest BAR value in the system. (usually n0p0)
// TODO Adjust the realAddr if the BAR came from a processor other
// than cpuid 0
@@ -151,7 +151,7 @@ errlHndl_t IntrRp::_init()
// Set up the interrupt provider registers
// NOTE: Simics only supports 4 threads, and two cores per proc chip.
- //
+ //
// NOTE: P7 register address format only supports 4 threads per core.
// This will change for P8
//
@@ -178,7 +178,7 @@ errlHndl_t IntrRp::_init()
// Get the kernel msg queue for ext intr
// Create a task to handle the messages
- iv_msgQ = msg_q_create();
+ iv_msgQ = msg_q_create();
msg_q_register(iv_msgQ, INTR_MSGQ);
task_create(IntrRp::msg_handler, NULL);
@@ -384,7 +384,7 @@ errlHndl_t IntrRp::registerInterrupt(msg_q_t i_msgQ, ext_intr_t i_type)
0
);
}
-
+
}
return err;
}
@@ -427,11 +427,11 @@ void IntrRp::initInterruptPresenter(const PIR_t i_pir) const
// where it started, it gets rejected by hardware.
//
// According to BOOK IV, The links regs are setup by firmware.
- //
+ //
// Should be possible to link all interrupt forwarding directly to
// the master core and either make them direct (lspec = 0) or by setting
// the LOOPTRIP bit to stop the forwarding at the masterProc.
- //
+ //
LinkReg_t linkReg;
linkReg.word = 0;
linkReg.loopTrip = 1; // needed?
@@ -450,7 +450,7 @@ errlHndl_t IntrRp::checkAddress(uint64_t i_addr)
{
errlHndl_t err = NULL;
- if(i_addr < VMM_VADDR_DEVICE_SEGMENT)
+ if(i_addr < VMM_VADDR_DEVICE_SEGMENT_FIRST)
{
/*@ errorlog tag
* @errortype ERRL_SEV_INFORMATIONAL
@@ -480,7 +480,7 @@ errlHndl_t IntrRp::checkAddress(uint64_t i_addr)
errlHndl_t INTR::registerMsgQ(msg_q_t i_msgQ, ext_intr_t i_type)
{
errlHndl_t err = NULL;
- // Can't add while handling an interrupt, so
+ // Can't add while handling an interrupt, so
// send msg instead of direct call
msg_q_t intr_msgQ = msg_q_resolve(INTR_MSGQ);
if(intr_msgQ)
diff --git a/src/usr/testcore/kernel/segmenttest.H b/src/usr/testcore/kernel/segmenttest.H
index effa34e2e..e5b9ff64a 100644
--- a/src/usr/testcore/kernel/segmenttest.H
+++ b/src/usr/testcore/kernel/segmenttest.H
@@ -34,6 +34,8 @@
#include <sys/mmio.h>
#include <usr/vmmconst.h>
+#include <list>
+
class segmenttest: public CxxTest::TestSuite
{
public:
@@ -82,6 +84,33 @@ class segmenttest: public CxxTest::TestSuite
}
}
+ // Verify we can allocate a block from the second device segment.
+ void testManyDeviceBlocks()
+ {
+ std::list<void*> blocks;
+
+ void* block = NULL;
+ while (reinterpret_cast<uint64_t>(block)
+ < (VMM_VADDR_DEVICE_SEGMENT_FIRST + TERABYTE))
+ {
+ block = mmio_dev_map(reinterpret_cast<void*>(10 * TERABYTE),
+ THIRTYTWO_GB);
+
+ if (block == NULL)
+ {
+ TS_FAIL("Unable to allocate device block.");
+ break;
+ }
+ blocks.push_back(block);
+ }
+
+ while(!blocks.empty())
+ {
+ mmio_dev_unmap(blocks.front());
+ blocks.pop_front();
+ }
+ }
+
};
#endif
OpenPOWER on IntegriCloud