diff options
author | Patrick Williams <iawillia@us.ibm.com> | 2013-05-20 14:34:56 -0500 |
---|---|---|
committer | A. Patrick Williams III <iawillia@us.ibm.com> | 2013-06-10 10:04:07 -0500 |
commit | 857112a56dc57b18b1feacf948b87875dc4aea45 (patch) | |
tree | f0ee915b3e37f9134a9268ea0c2a7e32c56a17ee /src | |
parent | e3d115c541291493888f533b215e28b890776e50 (diff) | |
download | talos-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-x | src/build/debug/Hostboot/_DebugFrameworkVMM.pm | 2 | ||||
-rw-r--r-- | src/include/kernel/devicesegment.H | 15 | ||||
-rw-r--r-- | src/include/kernel/segmentmgr.H | 49 | ||||
-rw-r--r-- | src/include/kernel/vmmmgr.H | 7 | ||||
-rw-r--r-- | src/include/sys/mm.h | 17 | ||||
-rw-r--r-- | src/include/sys/mmio.h | 2 | ||||
-rw-r--r-- | src/kernel/devicesegment.C | 31 | ||||
-rw-r--r-- | src/kernel/segmentmgr.C | 53 | ||||
-rw-r--r-- | src/kernel/syscall.C | 14 | ||||
-rw-r--r-- | src/kernel/vmmmgr.C | 11 | ||||
-rw-r--r-- | src/lib/syscall_mm.C | 15 | ||||
-rw-r--r-- | src/lib/syscall_mmio.C | 6 |
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) |