diff options
author | Mike Baiocchi <mbaiocch@us.ibm.com> | 2017-07-06 21:17:47 -0500 |
---|---|---|
committer | Daniel M. Crowell <dcrowell@us.ibm.com> | 2017-07-19 13:49:22 -0400 |
commit | c0f528fbaf2532d8cfaf51165fe4f7055a11f24a (patch) | |
tree | 7643434d680a6bb7a3b44ffa81e038dae1861e3c /src/usr/sbeio | |
parent | bf8d6d1dfc603df78a07f9e413d54dc33be857e6 (diff) | |
download | talos-hostboot-c0f528fbaf2532d8cfaf51165fe4f7055a11f24a.tar.gz talos-hostboot-c0f528fbaf2532d8cfaf51165fe4f7055a11f24a.zip |
Secureboot: Base Support of Opening/Closing Memory Regions via SBE
This commit provides the base support of Opening and Closing Unsecure
Memory Regions via PSU commands to the SBE. It introduces external
interfaces, a Memory Region Manager class, and a testcase that
covers the expected use of the interfaces. However, it does not
enable the actual PSU commands to the SBE since their support
is not yet available.
Change-Id: I086011fcbd485abf2db574a82d43cfdea120ffc8
RTC:145686
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/42834
Reviewed-by: Nicholas E. Bofferding <bofferdn@us.ibm.com>
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Reviewed-by: Stephen M. Cprek <smcprek@us.ibm.com>
Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com>
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com>
Reviewed-by: Marshall J. Wilks <mjwilks@us.ibm.com>
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/usr/sbeio')
-rw-r--r-- | src/usr/sbeio/makefile | 1 | ||||
-rw-r--r-- | src/usr/sbeio/sbe_memRegionMgr.C | 622 | ||||
-rw-r--r-- | src/usr/sbeio/sbe_memRegionMgr.H | 141 | ||||
-rw-r--r-- | src/usr/sbeio/test/sbe_memregiontest.H | 179 |
4 files changed, 943 insertions, 0 deletions
diff --git a/src/usr/sbeio/makefile b/src/usr/sbeio/makefile index 91aac40bd..fb74a3ea3 100644 --- a/src/usr/sbeio/makefile +++ b/src/usr/sbeio/makefile @@ -43,6 +43,7 @@ OBJS += sbe_scomAccess.o OBJS += sbe_scomAccessdd.o OBJS += sbe_ffdc_parser.o OBJS += sbe_setFFDCAddr.o +OBJS += sbe_memRegionMgr.o SUBDIRS += test.d SUBDIRS += runtime.d diff --git a/src/usr/sbeio/sbe_memRegionMgr.C b/src/usr/sbeio/sbe_memRegionMgr.C new file mode 100644 index 000000000..9cd4dbc34 --- /dev/null +++ b/src/usr/sbeio/sbe_memRegionMgr.C @@ -0,0 +1,622 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/sbeio/sbe_memRegionMgr.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +/** +* @file sbe_memRegionMgr.C +* @brief Opens and Closes Unsecure Memory Regions via the SBE +*/ + +#include <config.h> +#include <trace/interface.H> +#include <errl/errlmanager.H> +#include <sbeio/sbeioif.H> +#include <sbeio/sbe_psudd.H> +#include <sbeio/sbeioreasoncodes.H> +#include <targeting/common/targetservice.H> +#include <vmmconst.h> +#include <sys/misc.h> + +#include "sbe_memRegionMgr.H" + +extern trace_desc_t* g_trac_sbeio; + +#define SBE_TRACD(printf_string,args...) \ +TRACDCOMP(g_trac_sbeio,"memRegion: " printf_string,##args) + +#define SBE_TRACF(printf_string,args...) \ +TRACFCOMP(g_trac_sbeio,"memRegion: " printf_string,##args) + +namespace SBEIO +{ + +// External Function to Open an Unsecure Memory Region +// - see sbeioif.H for details +errlHndl_t openUnsecureMemRegion(const uint64_t i_start_addr, + const uint32_t i_size, + const bool i_isWritable) +{ + return Singleton<MemRegionMgr>::instance() + .openUnsecureMemRegion(i_start_addr, + i_size, + i_isWritable); +}; + + +// External Function to Close an Unsecure Memory Region +// - see sbeioif.H for details +errlHndl_t closeUnsecureMemRegion(const uint64_t i_start_addr) +{ + return Singleton<MemRegionMgr>::instance() + .closeUnsecureMemRegion(i_start_addr); +}; + + +// External Function to Close All Unsecure Memory Regions +// - see sbeioif.H for details +errlHndl_t closeAllUnsecureMemRegions() +{ + return Singleton<MemRegionMgr>::instance() + .closeAllUnsecureMemRegions(); +}; + + +/*****************************************************************************/ +/* + * MemRegionMgr : Constructor : Setup Instance Variables + */ +MemRegionMgr::MemRegionMgr() +{ + SBE_TRACD(ENTER_MRK"MemRegionMgr Constructor"); + + // SBE opens Memory Region for HB DUMP before starting hostboot + // so just add it directly to iv_memRegions + regionData hb_dump_region; + hb_dump_region.start_addr = cpu_spr_value(CPU_SPR_HRMOR); + hb_dump_region.size = VMM_MEMORY_SIZE; + hb_dump_region.flags = SbePsu::SBE_MEM_REGION_OPEN_READ_ONLY; + iv_memRegions.push_back(hb_dump_region); + + SBE_TRACF("MemRegionMgr Constructor: Initial region(s):"); + printIvMemRegions(); + + SBE_TRACD(EXIT_MRK"MemRegionMgr Constructor"); +}; + +/* + * MemRegionMgr : Destructor : Clear Instance Variables + */ +MemRegionMgr::~MemRegionMgr() +{ + // Clear Vector of Unsecure Memory Regions + iv_memRegions.clear(); +}; + +/** + * MemRegionMgr::openUnsecureMemRegion + * - see sbe_unsecureMemRegionMgr.H for details + */ +errlHndl_t MemRegionMgr::openUnsecureMemRegion( + const uint64_t i_start_addr, + const uint32_t i_size, + const bool i_isWritable) +{ + + errlHndl_t errl = nullptr; + regionData l_region; + bool itr_region_closed = false; + const uint8_t input_flags = i_isWritable ? + SbePsu::SBE_MEM_REGION_OPEN_READ_WRITE : + SbePsu::SBE_MEM_REGION_OPEN_READ_ONLY; + + SBE_TRACF(ENTER_MRK"openUnsecureMemRegion: i_start_addr=0x%.16llX, " + "i_size=0x%.8X, i_isWritable=%d (flags=0x%.2X)", + i_start_addr, i_size, i_isWritable, input_flags); + + do + { + // Handle 'Open' Request + // -- Look for identical region + // ---- if so, fail + // -- Look for possible overlap with existing regions + // ---- If overlap, close existing regions and re-open + // all regions as necessary + // ---- If no overlap, open requested region + + // @TODO RTC 174970 - Add checks to not exceed 8 memory regions + + auto itr = iv_memRegions.begin(); + while (itr != iv_memRegions.end()) + { + // reset for each loop + itr_region_closed = false; + + // Look for Overlap: start_addr starts at or is inside + // existing region + if ((i_start_addr >= itr->start_addr) && + (i_start_addr < (itr->start_addr + itr->size))) + { + SBE_TRACF(INFO_MRK"openUnsecureMemRegion: Overlap Found: " + "Req Region Starts inside existing region. " + "Exist start=0x%.16lX, size=0x%.8X, flags=0x%.2X" + "Req start=0x%.16lX, size=0x%.8X, flags=0x%.2X", + itr->start_addr, itr->size, itr->flags, + i_start_addr, i_size, input_flags); + + // Close Existing Region + l_region.start_addr = itr->start_addr; + l_region.size = itr->size; + l_region.flags = SbePsu::SBE_MEM_REGION_CLOSE; + + errl = doUnsecureMemRegionOp(l_region); + + if (errl) + { + SBE_TRACF(ERR_MRK "openUnsecureMemRegion: Close Op " + "Failed: err rc=0x%.4X plid=0x%.8X", + ERRL_GETRC_SAFE(errl), ERRL_GETPLID_SAFE(errl)); + + // Return error to caller ASAP + break; + } + else + { + // This region will be removed from the cache list later + itr_region_closed = true; + } + + // Re-Open Non-overlapping initial part of Existing Region + l_region.start_addr = itr->start_addr; + l_region.size = i_start_addr - itr->start_addr; + l_region.flags = itr->flags; + + errl = doUnsecureMemRegionOp(l_region); + + if (errl) + { + SBE_TRACF(ERR_MRK "openUnsecureMemRegion: Re-Open Op " + "Failed: err rc=0x%.4X plid=0x%.8X", + ERRL_GETRC_SAFE(errl), ERRL_GETPLID_SAFE(errl)); + + // Return error to caller ASAP + break; + } + else + { + // Add the region to the cache list + iv_memRegions.push_front(l_region); + } + } + + // Look for Overlap: end of region inside existing region + if (((i_start_addr + i_size) > itr->start_addr) && + ((i_start_addr + i_size) < (itr->start_addr + itr->size))) + { + SBE_TRACF(INFO_MRK"openUnsecureMemRegion: Overlap Found: " + "Req Region Ends inside existing region. " + "Exist start=0x%.16lX, size=0x%.8X, flags=0x%.2X" + "Req start=0x%.16lX, size=0x%.8X, flags=0x%.2X", + itr->start_addr, itr->size, itr->flags, + i_start_addr, i_size, input_flags); + + // Close Existing Region - if not already closed + if (itr_region_closed == false) + { + l_region.start_addr = itr->start_addr; + l_region.size = itr->size; + l_region.flags = SbePsu::SBE_MEM_REGION_CLOSE; + + errl = doUnsecureMemRegionOp(l_region); + + if (errl) + { + SBE_TRACF(ERR_MRK "openUnsecureMemRegion: Close Op " + "Failed: err rc=0x%.4X plid=0x%.8X", + ERRL_GETRC_SAFE(errl), + ERRL_GETPLID_SAFE(errl)); + + // Return error to caller ASAP + break; + } + else + { + // This region will be removed from the cache list later + itr_region_closed = true; + } + } + + // Re-open, non-overlapping back end part of + // Existing Region + l_region.start_addr = i_start_addr + i_size; + l_region.size = (itr->start_addr + itr->size) - + (i_start_addr + i_size); + l_region.flags = itr->flags; + + errl = doUnsecureMemRegionOp(l_region); + + if (errl) + { + SBE_TRACF(ERR_MRK "openUnsecureMemRegion: Re-Open Op " + "Failed: err rc=0x%.4X plid=0x%.8X", + ERRL_GETRC_SAFE(errl), + ERRL_GETPLID_SAFE(errl)); + + // Return error to caller ASAP + break; + } + else + { + // Add the region to the cache list + iv_memRegions.push_front(l_region); + } + } + + // Look for Overlap: existing region enclosed by requested region + else if ((i_start_addr <= itr->start_addr) && + ((i_start_addr + i_size) >= + (itr->start_addr + itr->size))) + { + SBE_TRACF(INFO_MRK"openUnsecureMemRegion: Overlap Found: " + "Req Region encloses existing region. " + "Exist start=0x%.16lX, size=0x%.8X, flags=0x%.2X" + "Req start=0x%.16lX, size=0x%.8X, flags=0x%.2X", + itr->start_addr, itr->size, itr->flags, + i_start_addr, i_size, input_flags); + + // Close Existing Region + if (itr_region_closed==false) + { + l_region.start_addr = itr->start_addr; + l_region.size = itr->size; + l_region.flags = SbePsu::SBE_MEM_REGION_CLOSE; + + errl = doUnsecureMemRegionOp(l_region); + + if (errl) + { + SBE_TRACF(ERR_MRK "openUnsecureMemRegion: Close Op " + "(enclosed) Failed: err rc=0x%.4X plid=0x%.8X", + ERRL_GETRC_SAFE(errl), ERRL_GETPLID_SAFE(errl)); + + // Return error to caller ASAP + break; + } + else + { + // This region will be removed from the cache list later + itr_region_closed = true; + } + } + } + + // Increment Iterator + if (itr_region_closed == true) + { + itr = iv_memRegions.erase(itr); + } + else + { + ++itr; + } + } + + // If previous error, don't open a new region + if (errl) + { + break; + } + + + // Open Requested Region + l_region.start_addr = i_start_addr; + l_region.size = i_size; + l_region.flags = input_flags; + + errl = doUnsecureMemRegionOp(l_region); + if (errl) + { + SBE_TRACF(ERR_MRK "openUnsecureMemRegion: Open Call Failed: " + "err rc=0x%.4X plid=0x%.8X", + ERRL_GETRC_SAFE(errl), ERRL_GETPLID_SAFE(errl)); + + // Return error to caller ASAP + break; + } + else + { + // Add region to cache on success + iv_memRegions.push_front(l_region); + } + + } + while (0); + + // TODO RTC 174970 remove when base support is working + printIvMemRegions(); + + SBE_TRACF(EXIT_MRK "openUnsecureMemRegion: i_start_addr=0x%.16llX: " + "err_rc=0x%.4X", + i_start_addr, + ERRL_GETRC_SAFE(errl)); + + return errl; +} + +/** + * MemRegionMgr::closeUnsecureMemRegion + * - see sbe_unsecureMemRegionMgr.H for details + */ +errlHndl_t MemRegionMgr::closeUnsecureMemRegion(const uint64_t i_start_addr) +{ + errlHndl_t errl = nullptr; + + bool region_found = false; + regionData l_region; + + SBE_TRACF(ENTER_MRK"closeUnsecureMemRegion: i_start_addr=0x%.16llX", + i_start_addr); + + do + { + auto itr = iv_memRegions.begin(); + while (itr != iv_memRegions.end()) + { + if (itr->start_addr == i_start_addr) + { + region_found = true; + + // Close Requested Region + l_region.start_addr = itr->start_addr; + l_region.size = itr->size; + l_region.flags = SbePsu::SBE_MEM_REGION_CLOSE; + errl = doUnsecureMemRegionOp(l_region); + if (errl) + { + SBE_TRACF(ERR_MRK "closeUnsecureMemRegion: Close Op Failed:" + " err rc=0x%.4X plid=0x%.8X", + ERRL_GETRC_SAFE(errl), ERRL_GETPLID_SAFE(errl)); + } + else + { + itr = iv_memRegions.erase(itr); + } + + // Quit walking through regions + break; + } + + // Keep looking + ++itr; + } + + // If previous error, don't even check for "region not found" error + if (errl) + { + break; + } + + if (region_found == false) + { + SBE_TRACF(ERR_MRK"closeUnsecureMemRegion: Requested Region " + "Does Not Exist! start_addr=0x%.16llX", + i_start_addr); + + /*@ + * @errortype + * @moduleid SBEIO_MEM_REGION + * @reasoncode SBEIO_MEM_REGION_DOES_NOT_EXIST + * @userdata1 Starting Address of Unsecure Memory Region + * @userdata2 Number of Unsecure Memory Regions + * @devdesc Unsecure Memory Region Does Not Exist + * @custdesc A problem occurred during the IPL + */ + errl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + SBEIO_MEM_REGION, + SBEIO_MEM_REGION_DOES_NOT_EXIST, + i_start_addr, + iv_memRegions.size(), + true /*Add HB SW Callout*/ ); + break; + } + + } + while (0); + + SBE_TRACF(EXIT_MRK "closeUnsecureMemRegion: i_start_addr0x%.16llX: " + "err_rc=0x%4X", + i_start_addr, + ERRL_GETRC_SAFE(errl)); + + return errl; +} + +/** + * MemRegionMgr::closeUnsecureMemRegions + * - see sbe_unsecureMemRegionMgr.H for details + */ +errlHndl_t MemRegionMgr::closeAllUnsecureMemRegions() +{ + errlHndl_t errl = nullptr; + errlHndl_t errl_orig = nullptr; + + regionData l_region; + + SBE_TRACF(ENTER_MRK"closeAllUnsecureMemRegions: closing %d region(s)", + iv_memRegions.size()); + + printIvMemRegions(); + + do + { + // Close every memory region saved in vector + auto itr = iv_memRegions.begin(); + while (itr != iv_memRegions.end()) + { + // Close Requested Region + l_region.start_addr = itr->start_addr; + l_region.size = itr->size; + l_region.flags = SbePsu::SBE_MEM_REGION_CLOSE; + + errl = doUnsecureMemRegionOp(l_region); + + if ( ( errl != nullptr) && + ( errl_orig != nullptr ) ) + { + SBE_TRACF(ERR_MRK "closeAllUnsecureMemRegions: Another Fail: " + "Committing new err rc=0x%.4X plid=0x%.8X with plid " + "of original err rc=0x%.4X plid=0x%.8X", + ERRL_GETRC_SAFE(errl), + ERRL_GETPLID_SAFE(errl), + ERRL_GETRC_SAFE(errl_orig), + ERRL_GETPLID_SAFE(errl_orig)); + + // commit new error with orignal err PLID + errl->plid(errl_orig->plid()); + + errlCommit(errl, SBEIO_COMP_ID); + + // Skip region since it failed to close + ++itr; + } + else if ( errl != nullptr) + { + SBE_TRACF(ERR_MRK "closeAllUnsecureMemRegions: Close Fail: " + "err rc=0x%.4X plid=0x%.8X", + ERRL_GETRC_SAFE(errl), + ERRL_GETPLID_SAFE(errl)); + + // Save error and continue + errl_orig = errl; + errl = nullptr; + + // Skip region since it failed to close + ++itr; + } + else + { + itr = iv_memRegions.erase(itr); + } + } + } + while (0); + + printIvMemRegions(); + + SBE_TRACF(EXIT_MRK "closeAllUnsecureMemRegions: regions left = %d, " + "err_rc=0x%.4X", + iv_memRegions.size(), + ERRL_GETRC_SAFE(errl_orig)); + + return errl_orig; +} + +/** + * MemRegionMgr::doUnsecureMemRegionOp + * - see sbe_unsecureMemRegionMgr.H for details + */ +errlHndl_t MemRegionMgr::doUnsecureMemRegionOp(const regionData & i_region) +{ + errlHndl_t errl = nullptr; + + // @TODO RTC 174970 - make TRACD when SBE support is tested + SBE_TRACF(ENTER_MRK"doUnsecureMemRegionOp: start_addr=0x%.16llX, " + "size=0x%.8X, controlFlags=0x%.2X", + i_region.start_addr, i_region.size, i_region.flags); + + do + { + // Find master proc for target of PSU command + TARGETING::TargetService& tS = TARGETING::targetService(); + TARGETING::Target * l_master = nullptr; + + errl = tS.queryMasterProcChipTargetHandle(l_master); + if (errl) + { + SBE_TRACF(ERR_MRK "doUnsecureMemRegionOp: Failed to get Master " + "Proc: err rc=0x%.4X plid=0x%.8X", + ERRL_GETRC_SAFE(errl), ERRL_GETPLID_SAFE(errl)); + + break; + } + SbePsu::psuCommand l_psuCommand( + i_region.flags | + SbePsu::SBE_MEM_REGION_RESPONSE_REQUIRED, //control flags + SbePsu::SBE_PSU_CLASS_SECURITY_CONTROL, //command class + SbePsu::SBE_PSU_SET_UNSECURE_MEMORY_REGION_CMD); //command + + SbePsu::psuResponse l_psuResponse; + + // set up PSU command message + l_psuCommand.cd6_memRegion_Size = i_region.size; + l_psuCommand.cd6_memRegion_Start_Addr = i_region.start_addr; + +// @TODO RTC 174970 - Activate code block when SBE support is tested +#if 0 + errl = SBEIO::SbePsu::getTheInstance().performPsuChipOp(l_master, + &l_psuCommand, + &l_psuResponse, + SbePsu::MAX_PSU_SHORT_TIMEOUT_NS, + SbePsu::SBE_MEMORY_REGION_REQ_USED_REGS, + SbePsu::SBE_MEMORY_REGION_RSP_USED_REGS); +#endif + if (errl) + { + SBE_TRACF(ERR_MRK "doUnsecureMemRegionOp: PSU Cmd Failed: " + "err rc=0x%.4X plid=0x%.4X (mbxReg0=0x%.16llX)", + ERRL_GETRC_SAFE(errl), ERRL_GETPLID_SAFE(errl), + l_psuCommand.mbxReg0); + break; + } + + } + while (0); + + // @TODO RTC 174970 - make TRACD when SBE support is tested + SBE_TRACF(EXIT_MRK "doUnsecureMemRegionOp: start_addr=0x%.16llX, " + "size=0x%.8X, controlFlags=0x%.2X: err_rc=0x%.4X", + i_region.start_addr, i_region.size, i_region.flags, + ERRL_GETRC_SAFE(errl)); + return errl; +} + +/** + * MemRegionMgr::printIvMemRegions + * - see sbe_unsecureMemRegionMgr.H for details + */ +void MemRegionMgr::printIvMemRegions(void) const +{ + SBE_TRACF("MemRegionMgr::printIvMemRegions: number of entries=%d", + iv_memRegions.size()); + + for ( const auto& itr : iv_memRegions ) + { + SBE_TRACF("printIvMemRegions: start_addr=0x%.16llX, " + "size=0x%.8X, flags=0x%.2X (%s)", + itr.start_addr, itr.size, itr.flags, + itr.flags == SbePsu::SBE_MEM_REGION_OPEN_READ_ONLY ? + "Read-Only" : "Read-Write"); + } +} + +} // end namespace SBEIO diff --git a/src/usr/sbeio/sbe_memRegionMgr.H b/src/usr/sbeio/sbe_memRegionMgr.H new file mode 100644 index 000000000..b2b10cf70 --- /dev/null +++ b/src/usr/sbeio/sbe_memRegionMgr.H @@ -0,0 +1,141 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/sbeio/sbe_memRegionMgr.H $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +#ifndef __SBE_MEMREGIONMGR_H +#define __SBE_MEMREGIONMGR_H + +#include <stdint.h> +#include <errl/errlentry.H> +#include <vector> +#include <sbeio/sbeioif.H> + +namespace SBEIO +{ + +/* + * @brief Struct containing specifics of a Unsecure Memory Region + */ +struct regionData +{ + uint64_t start_addr; // Start address of region + uint32_t size; // Size of region in bytes + + // Control Flags for PSU command - + // see SbePsu::psuSetUnsecureMemoryRegionControlFlags + uint8_t flags; + + regionData() : start_addr(0), size(0), flags(0) {} +}; + +/** @class MemRegionMgr + * @brief Responsible for managing the SBE Unsecure Memory Regions + * + */ +class MemRegionMgr +{ + + private: + + /** Cache of Unsecure Memory Regions that are currently open */ + std::list< regionData > iv_memRegions; + + /* For Debug purposes: Pring Out Vector of iv_memRegions */ + void printIvMemRegions() const; + + /** + * @brief Local Function To Open/Close Unsecure Memory Regions + * + * @param[in] i_region Structure containing information about the region + * + * @return errlHndl_t Error log handle on failure. + * + */ + errlHndl_t doUnsecureMemRegionOp(const regionData & i_region); + + public: + /** + * @brief Constructor. Initializes instance variables. + */ + MemRegionMgr(); + + /** + * Destructor. + */ + ~MemRegionMgr(); + + /** + * Delete Copy Constructor + */ + MemRegionMgr(const MemRegionMgr&) = delete; + + /** + * Delete Copy Assignment + */ + MemRegionMgr& operator= (const MemRegionMgr&) = delete; + + /** + * Delete Move Constructor + */ + MemRegionMgr (MemRegionMgr&&) = delete; + + /** + * Delete Move Assignment + */ + MemRegionMgr& operator = (MemRegionMgr&&) = delete; + + /** + * @brief Open Unsecure Memory Region via the SBE + * + * @note: See openUnsecureMemRegion() function in sbeioif.H for details + * + */ + errlHndl_t openUnsecureMemRegion( + const uint64_t i_start_addr, + const uint32_t i_size, + const bool i_isWritable); + + /** + * @brief Close Unsecure Memory Region + * + * @note: See closeUnsecureMemRegion() function in sbeioif.H for details + * + */ + errlHndl_t closeUnsecureMemRegion(const uint64_t i_start_addr); + + + /** + * @brief Close All Unsecure Memory Regions + * + * @note: See closeAllUnsecureMemRegions() function in sbeioif.H for details + * + */ + errlHndl_t closeAllUnsecureMemRegions(); + +}; // class MemRegionMgr + + +}; // end namespace SBEIO + +#endif + diff --git a/src/usr/sbeio/test/sbe_memregiontest.H b/src/usr/sbeio/test/sbe_memregiontest.H new file mode 100644 index 000000000..2c2c87121 --- /dev/null +++ b/src/usr/sbeio/test/sbe_memregiontest.H @@ -0,0 +1,179 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/sbeio/test/sbe_memregiontest.H $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +#ifndef __SBE_MEMREGION_H +#define __SBE_MEMREGION_H + +/** + * @file sbe_ffdctest.H + * + * @brief Test cases for Opening/Closing SBE/HB Memory Regions +*/ + +#include <cxxtest/TestSuite.H> +#include <errl/errlentry.H> +#include <errl/errlmanager.H> +#include <sbeio/sbeioif.H> + +#define SBE_TRACF_MRT(printf_string,args...) \ + TRACFCOMP(g_trac_sbeio,"memRegionTest: " printf_string,##args) + +extern trace_desc_t* g_trac_sbeio; + +class SbeMemRegionTest : public CxxTest::TestSuite +{ + public: + + /** + * @brief Open and Close Overlapping Unsecure Memory Regions + */ + void testSBEMemRegion1(void) + { + TS_TRACE(ENTER_MRK"memRegionTest1: Opening and Closing Unsecure Memory Regions"); + + errlHndl_t errl = nullptr; + + // Reserve and Open Random Overlapping Memory Regions to force + // MemRegionMgr to update regions around each other + + // Malloc memory buffer to play with + // @TODO RTC 174970 - reserve a buffer of Physical Memory and use + // Physical addresses so that SBEIO commands will be successful + uint32_t mem_buf_size = 256; + void * mem_buf = malloc(mem_buf_size); + uint64_t mem_buf_start_addr = + reinterpret_cast<uint64_t>(mem_buf); + + do + { + + // Test 1: Open Read-Write region for front half of memory buffer + errl = SBEIO::openUnsecureMemRegion(mem_buf_start_addr, + mem_buf_size/2, + true); //true=Read-Write + if (errl) + { + TS_FAIL("memRegionTest1: T1: SBEIO::openUnsecureMemRegion() Failed: rc=0x%X, plid=0x%X", + ERRL_GETRC_SAFE(errl), ERRL_GETPLID_SAFE(errl)); + break; + } + else + { + SBE_TRACF_MRT("memRegionTest1: T1: SBEIO::openUnsecureMemRegion() SUCCESSFUL"); + } + + // Test 2: Open Overlapping Read-Only region for middle chunk of + // memory buffer + errl = SBEIO::openUnsecureMemRegion(mem_buf_start_addr+mem_buf_size/4, + mem_buf_size/2, + false); //false=Read-Only + if (errl) + { + TS_FAIL("memRegionTest1: T2: SBEIO::openUnsecureMemRegion() Failed: rc=0x%X, plid=0x%X", + ERRL_GETRC_SAFE(errl), ERRL_GETPLID_SAFE(errl)); + break; + } + else + { + SBE_TRACF_MRT("memRegionTest1: T2: SBEIO::openUnsecureMemRegion() SUCCESSFUL"); + } + + // Test 3: Open Overlapping Read-Write region completely enclosed by + // existing region + errl = SBEIO::openUnsecureMemRegion(mem_buf_start_addr+mem_buf_size/2, + mem_buf_size/8, + true); //true=Read-Write + if (errl) + { + TS_FAIL("memRegionTest1: T3: SBEIO::openUnsecureMemRegion() Failed: rc=0x%X, plid=0x%X", + ERRL_GETRC_SAFE(errl), ERRL_GETPLID_SAFE(errl)); + break; + } + else + { + SBE_TRACF_MRT("memRegionTest1: T3: SBEIO::openUnsecureMemRegion() SUCCESSFUL"); + } + + // Test 4: Open Overlapping Read-Write region that completely encloses + // existing regions + errl = SBEIO::openUnsecureMemRegion(mem_buf_start_addr+mem_buf_size/8, + (mem_buf_size/4) * 3, + true); //true=Read-Write + if (errl) + { + TS_FAIL("memRegionTest1: T4: SBEIO::openUnsecureMemRegion() Failed: rc=0x%X, plid=0x%X", + ERRL_GETRC_SAFE(errl), ERRL_GETPLID_SAFE(errl)); + break; + } + else + { + SBE_TRACF_MRT("memRegionTest1: T4: SBEIO::openUnsecureMemRegion() SUCCESSFUL"); + } + + // Test 5: Open Non-Overlapping Read-Only Region at the end + // existing regions + errl = SBEIO::openUnsecureMemRegion(mem_buf_start_addr+(mem_buf_size/8)*7, + mem_buf_size/8, + false); //false=Read-Only + if (errl) + { + TS_FAIL("memRegionTest1: T5: SBEIO::openUnsecureMemRegion() Failed: rc=0x%X, plid=0x%X", + ERRL_GETRC_SAFE(errl), ERRL_GETPLID_SAFE(errl)); + break; + } + else + { + SBE_TRACF_MRT("memRegionTest1: T5: SBEIO::openUnsecureMemRegion() SUCCESSFUL"); + } + + // @TODO RTC 174970 Add testcases for open/close fail scenarios + + // Test 99: Close all Memory Regions + errl = SBEIO::closeAllUnsecureMemRegions(); + if (errl) + { + TS_FAIL("memRegionTest1: T99: SBEIO::closeAllUnsecureMemRegions Failed: rc=0x%X, plid=0x%X", + ERRL_GETRC_SAFE(errl), ERRL_GETPLID_SAFE(errl)); + } + else + { + SBE_TRACF_MRT("memRegionTest1: T99: Closing All Memory Regions SUCCESSFUL"); + } + + }while(0); + + free (mem_buf); + mem_buf = nullptr; + + if (errl) + { + errlCommit(errl, SBEIO_COMP_ID); + } + + TS_TRACE(EXIT_MRK"memRegionTest1"); + } + +}; + +#endif |