summaryrefslogtreecommitdiffstats
path: root/src/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel')
-rw-r--r--src/kernel/devicesegment.C31
-rw-r--r--src/kernel/segmentmgr.C53
-rw-r--r--src/kernel/syscall.C14
-rw-r--r--src/kernel/vmmmgr.C11
4 files changed, 62 insertions, 47 deletions
diff --git a/src/kernel/devicesegment.C b/src/kernel/devicesegment.C
index 4236417e8..747d4a3ea 100644
--- a/src/kernel/devicesegment.C
+++ b/src/kernel/devicesegment.C
@@ -5,7 +5,7 @@
/* */
/* IBM CONFIDENTIAL */
/* */
-/* COPYRIGHT International Business Machines Corp. 2011,2012 */
+/* COPYRIGHT International Business Machines Corp. 2011,2013 */
/* */
/* p1 */
/* */
@@ -65,15 +65,17 @@ bool DeviceSegment::handlePageFault(task_t* i_task, uint64_t i_addr,
uint64_t device_offset = segment_ea -
(idx * (1ull << SLBE_s) / MMIO_MAP_DEVICES);
- if (0 == iv_mmioMap[idx].addr ||
- device_offset >= (uint64_t)iv_mmioMap[idx].size)
+ if (device_offset >= (uint64_t)iv_mmioMap[idx].size)
{
return false;
}
PageTableManager::addEntry((i_addr / PAGESIZE) * PAGESIZE,
(iv_mmioMap[idx].addr + device_offset) / PAGESIZE,
- SegmentManager::CI_ACCESS);
+ (iv_mmioMap[idx].no_ci ?
+ (BYPASS_HRMOR | WRITABLE) :
+ SegmentManager::CI_ACCESS)
+ );
return true;
}
@@ -82,21 +84,22 @@ bool DeviceSegment::handlePageFault(task_t* i_task, uint64_t i_addr,
* @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
+ * @param i_nonCI[in] - Device should be mapped cacheable instead of CI
* @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, bool i_nonCI)
{
void *segBlock = NULL;
if (i_devDataSize <= THIRTYTWO_GB)
{
- //TODO - Use segment block size if/when new device size needed
for (size_t i = 0; i < MMIO_MAP_DEVICES; i++)
{
- if (0 == iv_mmioMap[i].addr)
+ if ((0 == iv_mmioMap[i].addr) && (0 == iv_mmioMap[i].size))
{
+ iv_mmioMap[i].no_ci = i_nonCI;
iv_mmioMap[i].size = i_devDataSize;
iv_mmioMap[i].addr = reinterpret_cast<uint64_t>(ra);
- //TODO - Use segment block size if/when new device size needed
+
segBlock = reinterpret_cast<void*>(i *
((1ull << SLBE_s) / MMIO_MAP_DEVICES) +
this->getBaseAddress());
@@ -124,15 +127,16 @@ int DeviceSegment::devUnmap(void *ea)
return rc;
}
segment_ea = segment_ea - this->getBaseAddress();
- //TODO - Calculate idx by segment block size if/when new device size needed
+
size_t idx = segment_ea / ((1ull << SLBE_s) / MMIO_MAP_DEVICES);
- if (0 != iv_mmioMap[idx].addr)
+ if ((0 != iv_mmioMap[idx].addr) || (0 != iv_mmioMap[idx].size))
{
//Remove all of the defined block's size (<= 32GB)
PageTableManager::delRangePN(iv_mmioMap[idx].addr / PAGESIZE,
(iv_mmioMap[idx].addr + iv_mmioMap[idx].size) / PAGESIZE,
false);
iv_mmioMap[idx].addr = 0;
+ iv_mmioMap[idx].size = 0;
rc = 0;
}
@@ -153,12 +157,13 @@ uint64_t DeviceSegment::findPhysicalAddress(uint64_t i_vaddr) const
return rc;
}
segment_ea = segment_ea - this->getBaseAddress();
- //TODO - Calculate idx by segment block size if/when new device size needed
+
size_t idx = segment_ea / ((1ull << SLBE_s) / MMIO_MAP_DEVICES);
- if (0 != iv_mmioMap[idx].addr)
+ if ((0 != iv_mmioMap[idx].addr) || (0 != iv_mmioMap[idx].size))
{
//memory offset within this device's window
- uint64_t offset = segment_ea - idx*((1ull << SLBE_s) / MMIO_MAP_DEVICES);
+ uint64_t offset = segment_ea -
+ idx*((1ull << SLBE_s) / MMIO_MAP_DEVICES);
return (iv_mmioMap[idx].addr + offset);
}
diff --git a/src/kernel/segmentmgr.C b/src/kernel/segmentmgr.C
index 998e7af5a..71379cf3e 100644
--- a/src/kernel/segmentmgr.C
+++ b/src/kernel/segmentmgr.C
@@ -1,25 +1,25 @@
-// IBM_PROLOG_BEGIN_TAG
-// This is an automatically generated prolog.
-//
-// $Source: src/kernel/segmentmgr.C $
-//
-// IBM CONFIDENTIAL
-//
-// COPYRIGHT International Business Machines Corp. 2011
-//
-// p1
-//
-// Object Code Only (OCO) source materials
-// Licensed Internal Code Source Materials
-// IBM HostBoot Licensed Internal Code
-//
-// The source code for this program is not published or other-
-// wise divested of its trade secrets, irrespective of what has
-// been deposited with the U.S. Copyright Office.
-//
-// Origin: 30
-//
-// IBM_PROLOG_END
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/kernel/segmentmgr.C $ */
+/* */
+/* IBM CONFIDENTIAL */
+/* */
+/* COPYRIGHT International Business Machines Corp. 2011,2013 */
+/* */
+/* p1 */
+/* */
+/* Object Code Only (OCO) source materials */
+/* Licensed Internal Code Source Materials */
+/* IBM HostBoot Licensed Internal Code */
+/* */
+/* The source code for this program is not published or otherwise */
+/* divested of its trade secrets, irrespective of what has been */
+/* deposited with the U.S. Copyright Office. */
+/* */
+/* Origin: 30 */
+/* */
+/* IBM_PROLOG_END_TAG */
#include <assert.h>
#include <errno.h>
#include <arch/ppc.H>
@@ -63,9 +63,10 @@ void SegmentManager::castOutPages(uint64_t i_type)
Singleton<SegmentManager>::instance()._castOutPages(i_type);
}
-void* SegmentManager::devMap(void* ra, uint64_t i_devDataSize)
+void* SegmentManager::devMap(void* ra, uint64_t i_devDataSize, bool i_nonCI)
{
- return Singleton<SegmentManager>::instance()._devMap(ra, i_devDataSize);
+ return Singleton<SegmentManager>::instance()._devMap(ra, i_devDataSize,
+ i_nonCI);
}
int SegmentManager::devUnmap(void* ea)
@@ -161,7 +162,7 @@ void SegmentManager::_castOutPages(uint64_t i_type)
}
}
-void* SegmentManager::_devMap(void* ra, uint64_t i_devDataSize)
+void* SegmentManager::_devMap(void* ra, uint64_t i_devDataSize, bool i_nonCI)
{
void* ea = NULL;
for (size_t i = MMIO_FIRST_SEGMENT_ID; i <= MMIO_LAST_SEGMENT_ID; i++)
@@ -169,7 +170,7 @@ void* SegmentManager::_devMap(void* ra, uint64_t i_devDataSize)
if (NULL == iv_segments[i]) continue;
ea = reinterpret_cast<DeviceSegment*>(iv_segments[i])->
- devMap(ra, i_devDataSize);
+ devMap(ra, i_devDataSize, i_nonCI);
if (ea != NULL) break;
}
diff --git a/src/kernel/syscall.C b/src/kernel/syscall.C
index 0a8e644a0..305e3c39a 100644
--- a/src/kernel/syscall.C
+++ b/src/kernel/syscall.C
@@ -532,10 +532,18 @@ namespace Systemcalls
void DevMap(task_t *t)
{
void *ra = (void*)TASK_GETARG0(t);
- uint64_t devDataSize = TASK_GETARG1(t);
+ uint64_t devDataSize = ALIGN_PAGE(TASK_GETARG1(t));
+ bool cacheable = (0 != TASK_GETARG2(t));
- kassert(TASK_SETRTN(t, (uint64_t)VmmManager::devMap(ra,devDataSize)) !=
- NULL);
+ if (devDataSize > THIRTYTWO_GB)
+ {
+ TASK_SETRTN(t, NULL);
+ }
+ else
+ {
+ TASK_SETRTN(t,
+ (uint64_t)VmmManager::devMap(ra,devDataSize,cacheable));
+ }
}
/**
diff --git a/src/kernel/vmmmgr.C b/src/kernel/vmmmgr.C
index d5152bf11..223f4f4c6 100644
--- a/src/kernel/vmmmgr.C
+++ b/src/kernel/vmmmgr.C
@@ -5,7 +5,7 @@
/* */
/* IBM CONFIDENTIAL */
/* */
-/* COPYRIGHT International Business Machines Corp. 2010,2012 */
+/* COPYRIGHT International Business Machines Corp. 2010,2013 */
/* */
/* p1 */
/* */
@@ -86,9 +86,10 @@ void VmmManager::flushPageTable( void )
Singleton<VmmManager>::instance()._flushPageTable();
}
-void* VmmManager::devMap(void* ra, uint64_t i_devDataSize)
+void* VmmManager::devMap(void* ra, uint64_t i_devDataSize, bool i_nonCI)
{
- return Singleton<VmmManager>::instance()._devMap(ra, i_devDataSize);
+ return Singleton<VmmManager>::instance()._devMap(ra, i_devDataSize,
+ i_nonCI);
}
int VmmManager::devUnmap(void* ea)
@@ -221,12 +222,12 @@ int VmmManager::_mmExtend(void)
return rc;
}
-void* VmmManager::_devMap(void* ra, uint64_t i_devDataSize)
+void* VmmManager::_devMap(void* ra, uint64_t i_devDataSize, bool i_nonCI)
{
void* ea = NULL;
lock.lock();
- ea = SegmentManager::devMap(ra, i_devDataSize);
+ ea = SegmentManager::devMap(ra, i_devDataSize, i_nonCI);
lock.unlock();
return ea;
OpenPOWER on IntegriCloud