summaryrefslogtreecommitdiffstats
path: root/src/usr/sbeio
diff options
context:
space:
mode:
authorMike Baiocchi <mbaiocch@us.ibm.com>2017-07-06 21:17:47 -0500
committerDaniel M. Crowell <dcrowell@us.ibm.com>2017-07-19 13:49:22 -0400
commitc0f528fbaf2532d8cfaf51165fe4f7055a11f24a (patch)
tree7643434d680a6bb7a3b44ffa81e038dae1861e3c /src/usr/sbeio
parentbf8d6d1dfc603df78a07f9e413d54dc33be857e6 (diff)
downloadtalos-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/makefile1
-rw-r--r--src/usr/sbeio/sbe_memRegionMgr.C622
-rw-r--r--src/usr/sbeio/sbe_memRegionMgr.H141
-rw-r--r--src/usr/sbeio/test/sbe_memregiontest.H179
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
OpenPOWER on IntegriCloud