summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPatrick Williams <iawillia@us.ibm.com>2013-05-20 14:34:56 -0500
committerA. Patrick Williams III <iawillia@us.ibm.com>2013-06-10 10:04:07 -0500
commit857112a56dc57b18b1feacf948b87875dc4aea45 (patch)
treef0ee915b3e37f9134a9268ea0c2a7e32c56a17ee /src
parente3d115c541291493888f533b215e28b890776e50 (diff)
downloadtalos-hostboot-857112a56dc57b18b1feacf948b87875dc4aea45.tar.gz
talos-hostboot-857112a56dc57b18b1feacf948b87875dc4aea45.zip
New mm_block_map syscall.
RTC: 71081 Change-Id: Ic5531fbba92cfc7aad7d303f043d6a350483d63d Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/4607 Tested-by: Jenkins Server Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src')
-rwxr-xr-xsrc/build/debug/Hostboot/_DebugFrameworkVMM.pm2
-rw-r--r--src/include/kernel/devicesegment.H15
-rw-r--r--src/include/kernel/segmentmgr.H49
-rw-r--r--src/include/kernel/vmmmgr.H7
-rw-r--r--src/include/sys/mm.h17
-rw-r--r--src/include/sys/mmio.h2
-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
-rw-r--r--src/lib/syscall_mm.C15
-rw-r--r--src/lib/syscall_mmio.C6
12 files changed, 137 insertions, 85 deletions
diff --git a/src/build/debug/Hostboot/_DebugFrameworkVMM.pm b/src/build/debug/Hostboot/_DebugFrameworkVMM.pm
index caa48d534..6286db864 100755
--- a/src/build/debug/Hostboot/_DebugFrameworkVMM.pm
+++ b/src/build/debug/Hostboot/_DebugFrameworkVMM.pm
@@ -897,6 +897,8 @@ sub printDeviceSegments
my $segmentSize =::read64($mmiostructptr + $curmmiodevice*16
+ MMIO_STRUCT_SEGSIZE_OFFSET, 8);
+ # Segment size is a 63 bit quantity.
+ $segmentSize = $segmentSize & 0x7FFFFFFFFFFFFFFF;
if ($segmentPhyAddr != 0)
{
diff --git a/src/include/kernel/devicesegment.H b/src/include/kernel/devicesegment.H
index c010ffba8..411d4a37c 100644
--- a/src/include/kernel/devicesegment.H
+++ b/src/include/kernel/devicesegment.H
@@ -5,7 +5,7 @@
/* */
/* IBM CONFIDENTIAL */
/* */
-/* COPYRIGHT International Business Machines Corp. 2011,2012 */
+/* COPYRIGHT International Business Machines Corp. 2011,2013 */
/* */
/* p1 */
/* */
@@ -69,9 +69,10 @@ class DeviceSegment : public Segment
* @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* devMap(void* ra, uint64_t i_devDataSize);
+ void* devMap(void* ra, uint64_t i_devDataSize, bool i_nonCI);
/**
* @brief Unmap a device from the device segment.
@@ -86,7 +87,7 @@ class DeviceSegment : public Segment
* @return the physical address bound to the virtual address, or
* -EFAULT if i_vaddr not found. @see errno.h
*/
- uint64_t findPhysicalAddress(uint64_t i_vaddr) const;
+ uint64_t findPhysicalAddress(uint64_t i_vaddr) const;
private:
/**
@@ -94,9 +95,9 @@ class DeviceSegment : public Segment
*/
struct devSegData
{
- uint64_t addr; /* Real address assigned to device */
- uint64_t size; /* A particular device's segment block size */
- devSegData(): addr(0),size(THIRTYTWO_GB){};
+ uint64_t addr; //< Real address assigned to device
+ uint64_t no_ci:1; //< Device should be mapped non-CI.
+ uint64_t size:63; //< A particular device's segment block size
};
/**
@@ -105,7 +106,7 @@ class DeviceSegment : public Segment
enum
{
MMIO_MAP_DEVICES = 32
- }; //TODO - Only necessary if a device uses a SCOM region other than 32GB
+ };
devSegData iv_mmioMap[MMIO_MAP_DEVICES];
diff --git a/src/include/kernel/segmentmgr.H b/src/include/kernel/segmentmgr.H
index ecefbc0dd..cfc17597e 100644
--- a/src/include/kernel/segmentmgr.H
+++ b/src/include/kernel/segmentmgr.H
@@ -1,25 +1,25 @@
-// IBM_PROLOG_BEGIN_TAG
-// This is an automatically generated prolog.
-//
-// $Source: src/include/kernel/segmentmgr.H $
-//
-// 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/include/kernel/segmentmgr.H $ */
+/* */
+/* 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 */
/** @file segmentmgr.H
* Provides definition of the SegmentManager class.
*/
@@ -137,9 +137,10 @@ class SegmentManager
* @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
*/
- static void* devMap(void* ra, uint64_t i_devDataSize);
+ static void* devMap(void* ra, uint64_t i_devDataSize, bool i_nonCI);
/**
* @brief Unmap a device from the device segment
@@ -165,7 +166,7 @@ class SegmentManager
/** See castOutPages */
void _castOutPages(uint64_t i_type);
/** See devMap */
- void* _devMap(void* ra, uint64_t i_devDataSize);
+ void* _devMap(void* ra, uint64_t i_devDataSize, bool i_nonCI);
/** See devUnmap */
int _devUnmap(void* ea);
diff --git a/src/include/kernel/vmmmgr.H b/src/include/kernel/vmmmgr.H
index 87ae0caf6..b740d03e1 100644
--- a/src/include/kernel/vmmmgr.H
+++ b/src/include/kernel/vmmmgr.H
@@ -5,7 +5,7 @@
/* */
/* IBM CONFIDENTIAL */
/* */
-/* COPYRIGHT International Business Machines Corp. 2010,2012 */
+/* COPYRIGHT International Business Machines Corp. 2010,2013 */
/* */
/* p1 */
/* */
@@ -103,9 +103,10 @@ class VmmManager
* @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
*/
- static void* devMap(void* ra, uint64_t i_devDataSize);
+ static void* devMap(void* ra, uint64_t i_devDataSize, bool i_nonCI);
/**
* @brief Unmap a device from the device segment
@@ -246,7 +247,7 @@ class VmmManager
int _mmExtend( void );
/** See devMap */
- void* _devMap(void* ra, uint64_t i_devDataSize);
+ void* _devMap(void* ra, uint64_t i_devDataSize, bool i_nonCI);
/** See devUnmap */
int _devUnmap(void* ea);
diff --git a/src/include/sys/mm.h b/src/include/sys/mm.h
index d71d5a1b3..959c2fa57 100644
--- a/src/include/sys/mm.h
+++ b/src/include/sys/mm.h
@@ -122,6 +122,23 @@ int mm_extend(MM_EXTEND_SIZE i_size = MM_EXTEND_REAL_MEMORY);
*/
int mm_linear_map(void *i_paddr, uint64_t i_size);
+/** @fn mm_block_map()
+ * @brief Allocate an arbitrary physical address into the VMM.
+ * @param[in] i_paddr - Physical address of the memory to map.
+ * @param[in] i_size - Size of memory to map (in bytes).
+ *
+ * @return Virtual address or NULL.
+ */
+void* mm_block_map(void* i_paddr, uint64_t i_size);
+
+/** @fn mm_block_unmap()
+ * @brief Unallocate a block previously allocated with mm_block_map.
+ * @param[in] i_vaddr - Virtual address of the mapped block.
+ *
+ * @return int - 0 for successful unmap, non-zero otherwise.
+ */
+int mm_block_unmap(void* i_vaddr);
+
/** @fs mm_icache_invalidate()
* @brief Invalidate the ICACHE for the given memory
*
diff --git a/src/include/sys/mmio.h b/src/include/sys/mmio.h
index 273965a88..9fd609cf9 100644
--- a/src/include/sys/mmio.h
+++ b/src/include/sys/mmio.h
@@ -48,7 +48,7 @@ enum SEG_DATA_SIZES
* @param i_devDataSize[in] - Size of device segment block
* @return void* - Pointer to beginning virtual address, NULL otherwise
*/
-void* mmio_dev_map(void *ra, SEG_DATA_SIZES i_devDataSize);
+void* mmio_dev_map(void *ra, uint64_t i_devDataSize);
/**
* @brief System call to unmap a device from the device segment(2TB)
* @param ea[in] - Void pointer to effective address
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;
diff --git a/src/lib/syscall_mm.C b/src/lib/syscall_mm.C
index 98a4aa0a6..b39c23894 100644
--- a/src/lib/syscall_mm.C
+++ b/src/lib/syscall_mm.C
@@ -128,5 +128,20 @@ void mm_tolerate_ue(uint64_t i_state)
// that all preceeding instructions have completed, so there
// are no visible effects of instruction reordering with respect
// to this state change.
+}
+/**
+ * System call to map an arbitrary physical address into the VMM.
+ */
+void* mm_block_map(void* i_paddr, uint64_t i_size)
+{
+ return _syscall3(DEV_MAP, i_paddr, (void*)i_size, (void*)1);
+}
+
+/**
+ * System call to unmap a previous mm_block_map.
+ */
+int mm_block_unmap(void* i_vaddr)
+{
+ return (int64_t) _syscall1(DEV_UNMAP, i_vaddr);
}
diff --git a/src/lib/syscall_mmio.C b/src/lib/syscall_mmio.C
index e1e71121e..7d593c27e 100644
--- a/src/lib/syscall_mmio.C
+++ b/src/lib/syscall_mmio.C
@@ -5,7 +5,7 @@
/* */
/* IBM CONFIDENTIAL */
/* */
-/* COPYRIGHT International Business Machines Corp. 2010,2012 */
+/* COPYRIGHT International Business Machines Corp. 2010,2013 */
/* */
/* p1 */
/* */
@@ -29,9 +29,9 @@
using namespace Systemcalls;
-void* mmio_dev_map(void *ra, SEG_DATA_SIZES i_devDataSize)
+void* mmio_dev_map(void *ra, uint64_t i_devDataSize)
{
- return _syscall2(DEV_MAP, ra, (void*)i_devDataSize);
+ return _syscall3(DEV_MAP, ra, (void*)i_devDataSize, (void*)0);
}
int mmio_dev_unmap(void *ea)
OpenPOWER on IntegriCloud