summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIlya Smirnov <ismirno@us.ibm.com>2018-11-12 08:51:33 -0600
committerDaniel M. Crowell <dcrowell@us.ibm.com>2019-03-01 15:20:41 -0600
commited35e3da7c2606f6fe0930725892deae85df33b7 (patch)
treecb63a99beed07dcac836b2ce574ca07a27ce58bf
parent8ee01af225a0ac2a6de48624dfd56a3095fb9920 (diff)
downloadtalos-hostboot-ed35e3da7c2606f6fe0930725892deae85df33b7.tar.gz
talos-hostboot-ed35e3da7c2606f6fe0930725892deae85df33b7.zip
Unit Tests For SMF Secure Mem Distribution
This change introduces the unit tests (and helper functions) to test the SMF memory distribution algorithm. Change-Id: I0084f869d582e96354f06ec76c3de416c9838701 RTC: 192411 Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/68679 Reviewed-by: Nicholas E. Bofferding <bofferdn@us.ibm.com> Tested-by: Jenkins Server <pfd-jenkins+hostboot@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: Michael Baiocchi <mbaiocch@us.ibm.com> Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
-rw-r--r--src/include/usr/secureboot/smf.H57
-rw-r--r--src/usr/secureboot/smf/smf.C151
-rw-r--r--src/usr/secureboot/smf/test/makefile1
-rw-r--r--src/usr/secureboot/smf/test/testmemutils.H108
-rw-r--r--src/usr/secureboot/smf/test/testsmf.H413
-rw-r--r--src/usr/secureboot/smf/test/testsmfutils.H74
6 files changed, 637 insertions, 167 deletions
diff --git a/src/include/usr/secureboot/smf.H b/src/include/usr/secureboot/smf.H
index c77688585..990bce09b 100644
--- a/src/include/usr/secureboot/smf.H
+++ b/src/include/usr/secureboot/smf.H
@@ -39,26 +39,59 @@ namespace SMF
{
/**
- * @brief A function that destributes the requested amount of secure
+ * @brief A function that distributes the requested amount of secure
* memory between the functional procs with memory on the system.
* The memory is distributed in power-of-two chunks of 256MB
* until either all memory is distributed or there are no procs
- * remaining with memory available. The function returns predictive
- * or informational errors in the following cases: there is no
- * available memory behind the procs on the system (predictive error),
- * the exact amount of secure mem allocated did not match the requested
- * amount (informational error). If 0 is passed in to the function, no
- * attempt at distribution occurs and the SMF mode is turned off.
+ * remaining with memory available. If the requested amount is not
+ * a power-of-two factor of 256MB, the amount of memory will be rounded
+ * up accordingly. The function returns predictive or informational
+ * errors in the following cases: there is no available memory behind the
+ * procs on the system (predictive error), the exact amount of secure mem
+ * allocated did not match the requested amount (informational error). If
+ * 0 is passed in to the function, no attempt at distribution occurs and
+ * the SMF mode is turned off.
*
* @param[in] i_requestedSmfMemAmtInBytes the amount of secure memory to be
- * distributed (in bytes)
- * among the procs on the system
+ * distributed (in bytes) among the procs on the system
*
* @return nullptr: the memory was successfully distributed as requested
- * non-nullptr: a distribution error occurred (this error is never
- * unrecoverable)
+ * non-nullptr: a distribution error occurred (the error type will
+ * never be unrecoverable)
*/
-errlHndl_t distributeSmfMem(uint64_t i_requestedSmfMemAmtInBytes);
+errlHndl_t distributeSmfMem(const uint64_t i_requestedSmfMemAmtInBytes);
+
+/**
+ * @brief Function to distribute the requested amount of SMF memory between
+ * passed in procs with available memory. If 0 is passed in to the
+ * function, no attempt at distribution occurs and the SMF mode is turned
+ * off. Amount that are not power-of-two factors of 256MB are rounded up
+ * accordingly.
+ *
+ * @param[in] i_requestedSmfMemAmtInBytes the requested amount of secure memory
+ * to distribute between the procs (in bytes)
+ *
+ * @param[in] i_procToMemVec the vector of available procs on the system and
+ * the amount of memory attached to each
+ *
+ * @return nullptr: distribution was successful
+ * non-nullptr: an error occurred during distribution (the error type
+ * will never be unrecoverable)
+ */
+errlHndl_t distributeSmfMem(const uint64_t i_requestedSmfMemAmtInBytes,
+ std::vector<struct ProcToMemAssoc>& i_procToMemVec);
+
+/**
+ * @brief Helper function to return the total amount of memory available behind
+ * the given proc
+ *
+ * @param[in] i_proc the proc target to calculate the total memory for
+ *
+ * @pre the target must not be nullptr or the funtion will assert
+ *
+ * @return the total amount of memory, in bytes, available behind the input proc
+ */
+uint64_t getTotalProcMemSize(const TARGETING::Target* const i_proc);
} // namespace SMF
} // namespace SECUREBOOT
diff --git a/src/usr/secureboot/smf/smf.C b/src/usr/secureboot/smf/smf.C
index a743163d6..62aad557e 100644
--- a/src/usr/secureboot/smf/smf.C
+++ b/src/usr/secureboot/smf/smf.C
@@ -71,19 +71,12 @@ struct ProcToMemAssoc
}
};
-/**
- * @brief helper function to return the total amount of memory available behind
- * the given proc
- *
- * @param[in] i_proc the proc target to calculate the total memory for
- *
- * @return the total amount of memory, in bytes, available behind the input proc
- */
uint64_t getTotalProcMemSize(const TARGETING::Target* const i_proc)
{
TARGETING::ATTR_PROC_MEM_SIZES_type l_procMemSizes = {};
uint64_t l_totProcMem = 0;
+ assert(i_proc, "nullptr was passed to getTotalProcMemSize");
assert(i_proc->tryGetAttr<TARGETING::ATTR_PROC_MEM_SIZES>(l_procMemSizes),
"Could not get ATTR_PROC_MEM_SIZES from a proc target!");
@@ -109,63 +102,28 @@ void setSmfEnabled(bool i_enabled)
l_sys->setAttr<TARGETING::ATTR_SMF_ENABLED>(i_enabled);
}
-/**
- * @brief function to distribute the requested amount of memory between procs
- * with available memory on the system
- *
- * @param[in] i_requestedSmfMemAmtInBytes the requested amount of secure memory
- * to distribute between the procs (in bytes)
- *
- * @return nullptr: distribution was successful
- * non-nullptr: an error occurred during distribution (the error will
- * never be unrecoverable)
- */
-errlHndl_t distributeSmfMem(uint64_t i_requestedSmfMemAmtInBytes)
+errlHndl_t distributeSmfMem(const uint64_t i_requestedSmfMemAmtInBytes,
+ std::vector<struct ProcToMemAssoc>& i_procToMemVec)
{
errlHndl_t l_errl = nullptr;
- do {
+ do{
+ // The agreed-upon logic for handling 0 SMF memory request is to turn SMF
+ // mode off and not to attempt to distribute any memory
if(i_requestedSmfMemAmtInBytes == 0)
{
TRACFCOMP(SMF_TRACE::g_trac_smf, "distributeSmfMem: Requested 0 memory amount; SMF mode will be turned off.");
setSmfEnabled(false);
- break;
- }
-
- std::vector<struct ProcToMemAssoc>l_procToMemVec;
-
- // Get all the functional procs amongs which we will distribute the
- // requested SMF memory
- TARGETING::TargetHandleList l_procList;
- TARGETING::getAllChips(l_procList, TARGETING::TYPE_PROC, true);
-
- assert(l_procList.size(), "distributeSmfMem: no procs were found on the system");
-
- // Populate the vector of processor memory associations
- for(const auto l_proc : l_procList)
- {
- struct ProcToMemAssoc l_pToM(l_proc,
- 0,
- getTotalProcMemSize(l_proc),
- true);
- // The proc with lowest address 0 needs to have 8GB subtracted from
- // the available mem. This is done to make sure that hostboot can
- // run on that proc.
- if(ISTEP::get_bottom_mem_addr(l_proc) == 0)
+ for(auto& l_proc : i_procToMemVec)
{
- if(l_pToM.availableMem >= MIN_MEM_RESERVED_FOR_HB)
- {
- l_pToM.availableMem -= MIN_MEM_RESERVED_FOR_HB;
- }
- else
- {
- l_pToM.availableMem = 0;
- }
- TRACDCOMP(SMF_TRACE::g_trac_smf, "distributeSmfMem: memory behind proc 0x%x has been reduced by 0x%x", TARGETING::get_huid(l_proc), MIN_MEM_RESERVED_FOR_HB);
+ l_proc.proc->setAttr<TARGETING::ATTR_PROC_SMF_BAR_SIZE>(0);
}
- l_procToMemVec.push_back(l_pToM);
+
+ // No need to proceed with trying to allocate the memory if the
+ // requested amt is 0, so break out here.
+ break;
}
TRACFCOMP(SMF_TRACE::g_trac_smf, "distributeSmfMem: distributing 0x%.16llx requested memory.", i_requestedSmfMemAmtInBytes);
@@ -181,7 +139,7 @@ errlHndl_t distributeSmfMem(uint64_t i_requestedSmfMemAmtInBytes)
// requested memory or ran out of procs to allocate the mem on.
while(true)
{
- for(auto& l_member : l_procToMemVec)
+ for(auto& l_member : i_procToMemVec)
{
// This will be recalculated every loop.
l_allocatedSoFar = 0;
@@ -221,7 +179,7 @@ errlHndl_t distributeSmfMem(uint64_t i_requestedSmfMemAmtInBytes)
// We need to check this on each allocation (after each proc)
// because we may have to stop mid way through the proc loop
// when we've allocated all requested mem.
- for(const auto& l_proc : l_procToMemVec)
+ for(const auto& l_proc : i_procToMemVec)
{
l_allocatedSoFar += l_proc.memToAllocate;
}
@@ -248,7 +206,7 @@ errlHndl_t distributeSmfMem(uint64_t i_requestedSmfMemAmtInBytes)
// Find out if we still have procs remaining. If not, then the
// user has requested too much memory to be allocated.
uint8_t l_procsStillRemaining = 0;
- for(const auto& l_usableProc : l_procToMemVec)
+ for(const auto& l_usableProc : i_procToMemVec)
{
l_procsStillRemaining |= l_usableProc.useProc;
}
@@ -256,7 +214,7 @@ errlHndl_t distributeSmfMem(uint64_t i_requestedSmfMemAmtInBytes)
// Commit the allocated memory to each proc
if(!l_procsStillRemaining || l_remainingAmtToAllocate <= 0)
{
- for(auto l_Proc : l_procToMemVec)
+ for(auto l_Proc : i_procToMemVec)
{
l_Proc.proc->
setAttr<TARGETING::ATTR_PROC_SMF_BAR_SIZE>(
@@ -268,12 +226,12 @@ errlHndl_t distributeSmfMem(uint64_t i_requestedSmfMemAmtInBytes)
} // while true
uint64_t l_totMemOnSystem = 0; // For error handling below
- for(const auto l_proc : l_procList)
+ for(const auto& l_proc : i_procToMemVec)
{
TRACFCOMP(SMF_TRACE::g_trac_smf, "distributeSmfMem: proc 0x%x SMF_BAR_SIZE = 0x%.16llx",
- TARGETING::get_huid(l_proc),
- l_proc->getAttr<TARGETING::ATTR_PROC_SMF_BAR_SIZE>());
- l_totMemOnSystem += getTotalProcMemSize(l_proc);
+ TARGETING::get_huid(l_proc.proc),
+ l_proc.proc->getAttr<TARGETING::ATTR_PROC_SMF_BAR_SIZE>());
+ l_totMemOnSystem += getTotalProcMemSize(l_proc.proc);
}
// Error conditions
@@ -334,6 +292,75 @@ errlHndl_t distributeSmfMem(uint64_t i_requestedSmfMemAmtInBytes)
break;
}
+ }while(0);
+
+ return l_errl;
+}
+
+errlHndl_t distributeSmfMem(const uint64_t i_requestedSmfMemAmtInBytes)
+{
+ errlHndl_t l_errl = nullptr;
+
+ do {
+
+ std::vector<struct ProcToMemAssoc>l_procToMemVec;
+
+ // Get all the functional procs amongs which we will distribute the
+ // requested SMF memory
+ TARGETING::TargetHandleList l_procList;
+ TARGETING::getAllChips(l_procList, TARGETING::TYPE_PROC, true);
+
+ assert(l_procList.size(), "distributeSmfMem: no procs were found on the system");
+
+ // The agreed-upon logic for handling 0 SMF memory request is to turn SMF
+ // mode off and not to attempt to distribute any memory
+ if(i_requestedSmfMemAmtInBytes == 0)
+ {
+ TRACFCOMP(SMF_TRACE::g_trac_smf, "distributeSmfMem: Requested 0 memory amount; SMF mode will be turned off.");
+ setSmfEnabled(false);
+
+ for(auto& l_proc : l_procList)
+ {
+ l_proc->setAttr<TARGETING::ATTR_PROC_SMF_BAR_SIZE>(0);
+ }
+
+ // No need to proceed with trying to allocate the memory if the
+ // requested amt is 0, so break out here.
+ break;
+ }
+
+ // Populate the vector of processor memory associations
+ for(const auto l_proc : l_procList)
+ {
+ struct ProcToMemAssoc l_pToM(l_proc,
+ 0,
+ getTotalProcMemSize(l_proc),
+ true);
+
+ // The proc with lowest address 0 needs to have 8GB subtracted from
+ // the available mem. This is done to make sure that hostboot can
+ // run on that proc.
+ if(ISTEP::get_bottom_mem_addr(l_proc) == 0)
+ {
+ if(l_pToM.availableMem >= MIN_MEM_RESERVED_FOR_HB)
+ {
+ l_pToM.availableMem -= MIN_MEM_RESERVED_FOR_HB;
+ }
+ else
+ {
+ l_pToM.availableMem = 0;
+ }
+ TRACDCOMP(SMF_TRACE::g_trac_smf, "distributeSmfMem: memory behind proc 0x%x has been reduced by 0x%x", TARGETING::get_huid(l_proc), MIN_MEM_RESERVED_FOR_HB);
+ }
+ l_procToMemVec.push_back(l_pToM);
+ }
+
+ l_errl = distributeSmfMem(i_requestedSmfMemAmtInBytes, l_procToMemVec);
+ if(l_errl)
+ {
+ break;
+ }
+
} while(0);
return l_errl;
diff --git a/src/usr/secureboot/smf/test/makefile b/src/usr/secureboot/smf/test/makefile
index e8226b017..ce94ce1cd 100644
--- a/src/usr/secureboot/smf/test/makefile
+++ b/src/usr/secureboot/smf/test/makefile
@@ -28,6 +28,7 @@ MODULE = testsmf
TESTS = testsmfutils.H
TESTS += testmemutils.H
+TESTS += testsmf.H
include ${ROOTPATH}/config.mk
diff --git a/src/usr/secureboot/smf/test/testmemutils.H b/src/usr/secureboot/smf/test/testmemutils.H
index 912267791..702df1b57 100644
--- a/src/usr/secureboot/smf/test/testmemutils.H
+++ b/src/usr/secureboot/smf/test/testmemutils.H
@@ -38,8 +38,41 @@
class MemUtilsTestSuite : public CxxTest::TestSuite
{
+private:
+ bool cv_isSmfLoaded;
+
public:
+ MemUtilsTestSuite() : cv_isSmfLoaded(false)
+ {
+ errlHndl_t l_errl = nullptr;
+ l_errl = VFS::module_load("libsmf.so");
+ if(l_errl)
+ {
+ TS_FAIL("MemUtilsTestSuite(): could not load libsmf.so");
+ errlCommit(l_errl, CXXTEST_COMP_ID);
+ cv_isSmfLoaded = false;
+ }
+ else
+ {
+ cv_isSmfLoaded = true;
+ }
+ }
+
+ ~MemUtilsTestSuite()
+ {
+ if(cv_isSmfLoaded)
+ {
+ errlHndl_t l_errl = nullptr;
+ l_errl = VFS::module_unload("libsmf.so");
+ if(l_errl)
+ {
+ TS_FAIL("~MemUtilsTestSuite(): could not unload libsmf.so");
+ errlCommit(l_errl, CXXTEST_COMP_ID);
+ }
+ }
+ }
+
/**
* @brief Test get_top_mem_addr and get_bottom_mem_addr helper functions;
* test both calls with and without a proc argument.
@@ -47,10 +80,14 @@ public:
void testGetTopBotMemAddr() const
{
TS_INFO(ENTER_MRK "testGetTopBotMemAddr");
- bool l_libsmf_loaded = false;
errlHndl_t l_errl = nullptr;
do {
+ if(!cv_isSmfLoaded)
+ {
+ break;
+ }
+
const uint64_t TEST_TOP_MEM_SIZE = 0xdeadbeefbeefdead;
TARGETING::ATTR_PROC_MEM_SIZES_type l_mProcMemSizes = {
TEST_TOP_MEM_SIZE, 0, 0, 0, 0, 0, 0, 0};
@@ -61,15 +98,6 @@ public:
TARGETING::Target* l_masterProc = nullptr;
- l_errl = VFS::module_load("libsmf.so");
- if(l_errl)
- {
- TS_FAIL("Could not load libsmf.so");
- errlCommit(l_errl, CXXTEST_COMP_ID);
- break;
- }
- l_libsmf_loaded = true;
-
l_errl = TARGETING::targetService()
.queryMasterProcChipTargetHandle(l_masterProc);
if(l_errl)
@@ -146,16 +174,6 @@ public:
l_masterProc->setAttr<TARGETING::ATTR_PROC_MEM_BASES>(l_origMemBases);
} while(0);
- if(l_libsmf_loaded)
- {
- l_errl = VFS::module_unload("libsmf.so");
- if(l_errl)
- {
- TS_FAIL("Could not unload libsmf.so");
- errlCommit(l_errl, CXXTEST_COMP_ID);
- }
- }
-
TS_INFO(EXIT_MRK "testGetTopBotMemAddr");
}
@@ -166,24 +184,19 @@ public:
void testGetTopSmfMemAddr() const
{
TS_INFO(ENTER_MRK "testGetTopSmfMemAddr");
- bool l_libsmf_loaded = false;
errlHndl_t l_errl = nullptr;
do {
+ if(!cv_isSmfLoaded)
+ {
+ break;
+ }
+
const uint64_t TEST_SMF_MEM_SIZE = 0xbeefdeaddeadbeef;
const uint64_t TEST_SMF_BAR = 0;
TARGETING::Target* l_masterProc = nullptr;
- l_errl = VFS::module_load("libsmf.so");
- if(l_errl)
- {
- TS_FAIL("Could not load libsmf.so");
- errlCommit(l_errl, CXXTEST_COMP_ID);
- break;
- }
- l_libsmf_loaded = true;
-
l_errl = TARGETING::targetService()
.queryMasterProcChipTargetHandle(l_masterProc);
if(l_errl)
@@ -221,16 +234,6 @@ public:
setAttr<TARGETING::ATTR_PROC_SMF_BAR_SIZE>(l_origSmfMemSize);
} while(0);
- if(l_libsmf_loaded)
- {
- l_errl = VFS::module_unload("libsmf.so");
- if(l_errl)
- {
- TS_FAIL("Could not unload libsmf.so");
- errlCommit(l_errl, CXXTEST_COMP_ID);
- }
- }
-
TS_INFO(EXIT_MRK "testGetTopSmfMemAddr");
}
@@ -241,25 +244,20 @@ public:
void testGetTopHomerMemAddr() const
{
TS_INFO(ENTER_MRK"testGetTopHomerMemAddr");
- bool l_libsmf_loaded = false;
errlHndl_t l_errl = nullptr;
do {
+ if(!cv_isSmfLoaded)
+ {
+ break;
+ }
+
const uint64_t TEST_SMF_BAR = 0;
const uint64_t TEST_SMF_BAR_SIZE = 0xdeadbeefdeadbeef;
TARGETING::Target* l_sys = nullptr;
TARGETING::Target* l_masterProc = nullptr;
- l_errl = VFS::module_load("libsmf.so");
- if(l_errl)
- {
- TS_FAIL("Could not load libsmf.so");
- errlCommit(l_errl, CXXTEST_COMP_ID);
- break;
- }
- l_libsmf_loaded = true;
-
l_errl = TARGETING::targetService()
.queryMasterProcChipTargetHandle(l_masterProc);
if(l_errl)
@@ -306,16 +304,6 @@ public:
l_sys->setAttr<TARGETING::ATTR_SMF_ENABLED>(false);
} while(0);
- if(l_libsmf_loaded)
- {
- l_errl = VFS::module_unload("libsmf.so");
- if(l_errl)
- {
- TS_FAIL("Could not unload libsmf.so");
- errlCommit(l_errl, CXXTEST_COMP_ID);
- }
- }
-
TS_INFO(EXIT_MRK"testGetTopHomerMemAddr");
}
diff --git a/src/usr/secureboot/smf/test/testsmf.H b/src/usr/secureboot/smf/test/testsmf.H
new file mode 100644
index 000000000..81a50a6e0
--- /dev/null
+++ b/src/usr/secureboot/smf/test/testsmf.H
@@ -0,0 +1,413 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/secureboot/smf/test/testsmf.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2018 */
+/* [+] 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 __TEST_SMF_H
+#define __TEST_SMF_H
+
+#include <cxxtest/TestSuite.H>
+#include <errl/errlmanager.H>
+#include <targeting/common/target.H>
+#include <targeting/common/targetservice.H>
+#include <hbotcompid.H>
+#include <secureboot/smf.H>
+#include <secureboot/secure_reasoncodes.H>
+#include <errl/hberrltypes.H>
+#include <vfs/vfs.H>
+
+const uint64_t DISTRIBUTE_EXACT_SMF_AMT = 1 * GIGABYTE;
+const uint64_t DISTRIBUTE_NON_EXACT_SMF_AMT = 800 * MEGABYTE;
+
+class SmfMemDistributionSuite : public CxxTest::TestSuite
+{
+private:
+ bool cv_isSmfLoaded;
+ /**
+ * @brief Helper function to set master proc's ATTR_PROC_SMF_BAR_SIZE
+ * to the desired size passed in as an argument.
+ * @param[in] i_desiredMemSize the desired size of ATTR_PROC_SMF_BAR_SIZE
+ * @return nullptr on success; non-nullptr on error
+ */
+ errlHndl_t setSmfMemSize(const uint64_t i_desiredMemSize) const
+ {
+ errlHndl_t l_errl = nullptr;
+
+ do{
+
+ TARGETING::Target* l_masterProc = nullptr;
+ l_errl = TARGETING::targetService()
+ .queryMasterProcChipTargetHandle(l_masterProc);
+ if(l_errl)
+ {
+ break;
+ }
+
+ l_masterProc->
+ setAttr<TARGETING::ATTR_PROC_SMF_BAR_SIZE>(i_desiredMemSize);
+
+ }while(0);
+ return l_errl;
+ }
+
+ /**
+ * @brief Helper function to fetch the ATTR_PROC_SMF_BAR_SIZE attr from
+ * the master proc.
+ * @param[out] o_size the size of ATTR_PROC_SMF_BAR_SIZE on master proc
+ * @return nullptr on success; non-nullptr on error
+ */
+ errlHndl_t getSmfMemSize(uint64_t& o_size) const
+ {
+ errlHndl_t l_errl = nullptr;
+
+ do {
+
+ TARGETING::Target* l_masterProc = nullptr;
+ l_errl = TARGETING::targetService()
+ .queryMasterProcChipTargetHandle(l_masterProc);
+ if(l_errl)
+ {
+ break;
+ }
+
+ o_size = l_masterProc->
+ getAttr<TARGETING::ATTR_PROC_SMF_BAR_SIZE>();
+
+ } while(0);
+ return l_errl;
+ }
+
+ // Exception: An input of 1 will result in output of 1
+ uint64_t getHighestPwrTwoLessThan(const uint64_t i_val) const
+ {
+ uint64_t l_result = 1;
+
+ if(i_val)
+ {
+ for(; (l_result << 1) < i_val; l_result <<= 1);
+ }
+ else
+ {
+ l_result = 0;
+ }
+
+ return l_result;
+ }
+
+public:
+ SmfMemDistributionSuite() : cv_isSmfLoaded(false)
+ {
+ errlHndl_t l_errl = nullptr;
+ l_errl = VFS::module_load("libsmf.so");
+ if(l_errl)
+ {
+ TS_FAIL("SmfMemDistributionSuite(): could not load libsmf.so");
+ errlCommit(l_errl, CXXTEST_COMP_ID);
+ cv_isSmfLoaded = false;
+ }
+ else
+ {
+ cv_isSmfLoaded = true;
+ }
+ }
+
+ ~SmfMemDistributionSuite()
+ {
+ if(cv_isSmfLoaded)
+ {
+ errlHndl_t l_errl = nullptr;
+ l_errl = VFS::module_unload("libsmf.so");
+ if(l_errl)
+ {
+ TS_FAIL("~SmfMemDistributionSuite(): could not unload libsmf.so");
+ errlCommit(l_errl, CXXTEST_COMP_ID);
+ }
+ }
+ }
+
+ void testDistributeZeroMem() const
+ {
+ TS_INFO(ENTER_MRK"testDistributeZeroMem");
+ errlHndl_t l_errl = nullptr;
+ do {
+ if(!cv_isSmfLoaded)
+ {
+ break;
+ }
+
+ // Set up SMF on the system target for this test.
+ // We expect SMF to be turned off when the function runs.
+ TARGETING::Target* l_sys = nullptr;
+
+ TARGETING::targetService().getTopLevelTarget(l_sys);
+ assert(l_sys != nullptr, "The top level target is nullptr!");
+ l_sys->setAttr<TARGETING::ATTR_SMF_ENABLED>(true);
+
+ // Set SMF mem size to be something other than 0
+ l_errl = setSmfMemSize(0x1);
+ if(l_errl)
+ {
+ TS_FAIL("testDistributeZeroMem: could not setSmfMemSize");
+ errlCommit(l_errl, CXXTEST_COMP_ID);
+ break;
+ }
+
+ l_errl = SECUREBOOT::SMF::distributeSmfMem(0);
+ if(l_errl)
+ {
+ TS_FAIL("testDistributeZeroMem: distributeSmfMem returned an errl. Errl plid = 0x%x", l_errl->plid());
+ errlCommit(l_errl, CXXTEST_COMP_ID);
+ }
+
+ if(l_sys->getAttr<TARGETING::ATTR_SMF_ENABLED>())
+ {
+ // SMF should have been turned OFF with 0 mem request
+ TS_FAIL("testDistributeZeroMem: SMF should have been disabled on 0 SMF mem request");
+ }
+
+ uint64_t l_resultingSmfSize = 0;
+ l_errl = getSmfMemSize(l_resultingSmfSize);
+ if(l_errl)
+ {
+ TS_FAIL("testDistributeZeroMem: could not getSmfMemSize");
+ errlCommit(l_errl, CXXTEST_COMP_ID);
+ break;
+ }
+
+ if(l_resultingSmfSize != 0)
+ {
+ TS_FAIL("testDistributeZeroMem: Request to distribute zero SMF memory resulted in non-zero SMF_BAR_SIZE under master proc");
+ }
+ } while(0);
+
+ TS_INFO(EXIT_MRK"testDistributeZeroMem");
+ }
+
+ void testDistributeSmallMemAmt() const
+ {
+ TS_INFO(INFO_MRK"testDistributeSmallMemAmt");
+ errlHndl_t l_errl = nullptr;
+
+ do {
+ if(!cv_isSmfLoaded)
+ {
+ break;
+ }
+
+ l_errl = SECUREBOOT::SMF::distributeSmfMem(0x1);
+ if(!l_errl)
+ {
+ TS_FAIL("testDistributeSmallMemAmt: distributeSmfMem should have returned an error log.");
+ }
+ else
+ {
+ if(l_errl->reasonCode() != SECUREBOOT::RC_ALLOCATED_NE_REQUESTED)
+ {
+ TS_FAIL("testDistributeSmallMemAmt: Incorrect RC returned. Expected 0x%x, actual 0x%x", SECUREBOOT::RC_ALLOCATED_NE_REQUESTED, l_errl->reasonCode());
+
+ if(l_errl->sev() != ERRORLOG::ERRL_SEV_INFORMATIONAL)
+ {
+ TS_FAIL("testDistributeSmallMemAmt: Incorrect error log severity. Expected 0x%x, actual 0x%x", ERRORLOG::ERRL_SEV_INFORMATIONAL, l_errl->sev());
+ }
+ errlCommit(l_errl, CXXTEST_COMP_ID);
+ }
+ delete l_errl;
+ l_errl = nullptr;
+ }
+
+ uint64_t l_smfBarSize = 0;
+ l_errl = getSmfMemSize(l_smfBarSize);
+ if(l_errl)
+ {
+ TS_FAIL("testDistributeSmallMemAmt: could not getSmfMemSize");
+ errlCommit(l_errl, CXXTEST_COMP_ID);
+ break;
+ }
+
+ if(l_smfBarSize != SECUREBOOT::SMF::MIN_SMF_MEMORY_AMT)
+ {
+ TS_FAIL("testDistributeSmallMemAmt: Unexpected amount of memory allocated. Expected: 0x%x, actual: 0x%x", SECUREBOOT::SMF::MIN_SMF_MEMORY_AMT, l_smfBarSize);
+ }
+ } while(0);
+
+ TS_INFO(EXIT_MRK"testDistributeSmallMemAmt");
+ }
+
+ void testDistributeLargeMemAmt() const
+ {
+ TS_INFO(ENTER_MRK"testDistributeLargeMemAmt");
+ errlHndl_t l_errl = nullptr;
+
+ do {
+ if(!cv_isSmfLoaded)
+ {
+ break;
+ }
+
+ // Try to distribute very large amt of mem
+ l_errl = SECUREBOOT::SMF::distributeSmfMem(1000000*GIGABYTE);
+ if(!l_errl)
+ {
+ TS_FAIL("testDistributeLargeMemAmt: distributeSmfMem should have returned an error log.");
+ }
+ else
+ {
+ if(l_errl->reasonCode() != SECUREBOOT::RC_ALLOCATED_NE_REQUESTED)
+ {
+ TS_FAIL("testDistributeLargeMemAmt: Incorrect RC returned. Expected 0x%x, actual 0x%x", SECUREBOOT::RC_ALLOCATED_NE_REQUESTED, l_errl->reasonCode());
+
+ if(l_errl->sev() != ERRORLOG::ERRL_SEV_INFORMATIONAL)
+ {
+ TS_FAIL("testDistributeLargeMemAmt: Incorrect error log severity. Expected 0x%x, actual 0x%x", ERRORLOG::ERRL_SEV_INFORMATIONAL, l_errl->sev());
+ }
+
+ errlCommit(l_errl, CXXTEST_COMP_ID);
+ }
+ delete l_errl;
+ l_errl = nullptr;
+ }
+
+ uint64_t l_smfBarSize = 0;
+ l_errl = getSmfMemSize(l_smfBarSize);
+ if(l_errl)
+ {
+ TS_FAIL("testDistributeLargeMemAmt: could not getSmfMemSize");
+ errlCommit(l_errl, CXXTEST_COMP_ID);
+ break;
+ }
+
+ TARGETING::Target* l_masterProc = nullptr;
+ l_errl = TARGETING::targetService()
+ .queryMasterProcChipTargetHandle(l_masterProc);
+ if(l_errl)
+ {
+ TS_FAIL("testDistributeLargeMemAmt: could not get master proc!");
+ errlCommit(l_errl, CXXTEST_COMP_ID);
+ break;
+ }
+
+ uint64_t l_expectedMemAmt = getHighestPwrTwoLessThan(
+ SECUREBOOT::SMF::getTotalProcMemSize(l_masterProc) -
+ SECUREBOOT::SMF::MIN_MEM_RESERVED_FOR_HB);
+
+ if(l_smfBarSize != l_expectedMemAmt)
+ {
+ TS_FAIL("testDistributeLargeMemAmt: Unexpected amount of memory allocated. Expected: 0x%x, actual: 0x%x", l_expectedMemAmt, l_smfBarSize);
+ }
+ } while(0);
+
+ TS_INFO(EXIT_MRK"testDistributeLargeMemAmt");
+ }
+
+ void testDistributeExactAmt() const
+ {
+ TS_INFO(ENTER_MRK"testDistributeExactAmt");
+ errlHndl_t l_errl = nullptr;
+
+ do {
+ if(!cv_isSmfLoaded)
+ {
+ break;
+ }
+
+ // This amount should be distributed exactly
+ l_errl = SECUREBOOT::SMF::distributeSmfMem(DISTRIBUTE_EXACT_SMF_AMT);
+ if(l_errl)
+ {
+ TS_FAIL("testDistributeExactAmt: Unexpected error log returned from distributeSmfMem. Plid = 0x%x", l_errl->plid());
+ errlCommit(l_errl, CXXTEST_COMP_ID);
+ }
+
+ uint64_t l_smfBarSize = 0;
+ l_errl = getSmfMemSize(l_smfBarSize);
+ if(l_errl)
+ {
+ TS_FAIL("testDistributeExactAmt: could not getSmfMemSize");
+ errlCommit(l_errl, CXXTEST_COMP_ID);
+ break;
+ }
+
+ if(l_smfBarSize != DISTRIBUTE_EXACT_SMF_AMT)
+ {
+ TS_FAIL("testDistributeExactAmt: Unexpected amount of memory allocated. Expected: 0x%x, actual 0x%x", DISTRIBUTE_EXACT_SMF_AMT, l_smfBarSize);
+ }
+ } while(0);
+
+ TS_INFO(EXIT_MRK"testDistributeExactAmt");
+ }
+
+ void testDistributeNotExactAmt()
+ {
+ TS_INFO(ENTER_MRK"testDistributeNotExactAmt");
+ errlHndl_t l_errl = nullptr;
+
+ do {
+ if(!cv_isSmfLoaded)
+ {
+ break;
+ }
+
+ // Distribute the amount that cannot be fit exactly.
+ // 800MB will be adjusted up to 1GB because of the power-of-two
+ // hardware constraints.
+ l_errl =
+ SECUREBOOT::SMF::distributeSmfMem(DISTRIBUTE_NON_EXACT_SMF_AMT);
+ if(!l_errl)
+ {
+ TS_FAIL("testDistributeNotExactAmt: distributeSmfMem should have returned an error log.");
+ }
+ else
+ {
+ if(l_errl->reasonCode() != SECUREBOOT::RC_ALLOCATED_NE_REQUESTED)
+ {
+ TS_FAIL("testDistributeNotExactAmt: Incorrect RC returned. Expected 0x%x, actual 0x%x", SECUREBOOT::RC_ALLOCATED_NE_REQUESTED, l_errl->reasonCode());
+
+ if(l_errl->sev() != ERRORLOG::ERRL_SEV_INFORMATIONAL)
+ {
+ TS_FAIL("testDistributeNotExactAmt: Incorrect error log severity. Expected 0x%x, actual 0x%x", ERRORLOG::ERRL_SEV_INFORMATIONAL, l_errl->sev());
+ }
+ errlCommit(l_errl, CXXTEST_COMP_ID);
+ }
+ delete l_errl;
+ l_errl = nullptr;
+ }
+
+ uint64_t l_smfBarSize = 0;
+ l_errl = getSmfMemSize(l_smfBarSize);
+ if(l_errl)
+ {
+ TS_FAIL("testDistributeNotExactAmt: could not getSmfMemSize");
+ errlCommit(l_errl, CXXTEST_COMP_ID);
+ break;
+ }
+
+ if(l_smfBarSize != DISTRIBUTE_EXACT_SMF_AMT)
+ {
+ TS_FAIL("testDistributeNotExactAmt: Unexpected amount of memory allocated. Expected: 0x%x, actual 0x%x", DISTRIBUTE_EXACT_SMF_AMT, l_smfBarSize);
+ }
+ } while(0);
+
+ TS_INFO(EXIT_MRK"testDistributeNotExactAmt");
+ }
+};
+
+#endif
diff --git a/src/usr/secureboot/smf/test/testsmfutils.H b/src/usr/secureboot/smf/test/testsmfutils.H
index 0e61c9785..d8ad2fb8a 100644
--- a/src/usr/secureboot/smf/test/testsmfutils.H
+++ b/src/usr/secureboot/smf/test/testsmfutils.H
@@ -39,8 +39,41 @@
class SmfUtilsTestSuite : public CxxTest::TestSuite
{
+private:
+ bool cv_isSmfLoaded;
+
public:
+ SmfUtilsTestSuite() : cv_isSmfLoaded(false)
+ {
+ errlHndl_t l_errl = nullptr;
+ l_errl = VFS::module_load("libsmf.so");
+ if(l_errl)
+ {
+ TS_FAIL("SmfUtilsTestSuite(): could not load libsmf.so");
+ errlCommit(l_errl, CXXTEST_COMP_ID);
+ cv_isSmfLoaded = false;
+ }
+ else
+ {
+ cv_isSmfLoaded = true;
+ }
+ }
+
+ ~SmfUtilsTestSuite()
+ {
+ if(cv_isSmfLoaded)
+ {
+ errlHndl_t l_errl = nullptr;
+ l_errl = VFS::module_unload("libsmf.so");
+ if(l_errl)
+ {
+ TS_FAIL("~SmfUtilsTestSuite(): could not unload libsmf.so");
+ errlCommit(l_errl, CXXTEST_COMP_ID);
+ }
+ }
+ }
+
/**
* @brief Test isSmfEnabled helper function
*/
@@ -49,19 +82,16 @@ public:
TS_INFO(ENTER_MRK "testIsSmfEnabled");
do {
+ if(!cv_isSmfLoaded)
+ {
+ break;
+ }
+
TARGETING::Target* l_sys = nullptr;
TARGETING::targetService().getTopLevelTarget(l_sys);
assert(l_sys, "The top level target is nullptr!");
l_sys->setAttr<TARGETING::ATTR_SMF_ENABLED>(true);
- errlHndl_t l_errl = VFS::module_load("libsmf.so");
- if(l_errl)
- {
- TS_FAIL("Could not load libsmf.so");
- errlCommit(l_errl, CXXTEST_COMP_ID);
- break;
- }
-
bool l_smfEnabled = SECUREBOOT::SMF::isSmfEnabled();
if(l_smfEnabled != true)
{
@@ -75,13 +105,6 @@ public:
TS_FAIL("testIsSmfEnabled: expected SMF to be disabled, but it's enabled");
}
- l_errl = VFS::module_unload("libsmf.so");
- if(l_errl)
- {
- TS_FAIL("Could not unload libsmf.so");
- errlCommit(l_errl, CXXTEST_COMP_ID);
- break;
- }
} while (0);
TS_INFO(EXIT_MRK "testIsSmfEnabled");
@@ -93,20 +116,15 @@ public:
void testCheckRiskLevelForSmf() const
{
TS_INFO(ENTER_MRK "testCheckRiskLevelForSmf");
- bool l_libsmf_loaded = false;
errlHndl_t l_errl = nullptr;
do {
- TARGETING::Target* l_masterProc = nullptr;
-
- l_errl = VFS::module_load("libsmf.so");
- if(l_errl)
+ if(!cv_isSmfLoaded)
{
- TS_FAIL("Could not load libsmf.so");
- errlCommit(l_errl, CXXTEST_COMP_ID);
break;
}
- l_libsmf_loaded = true;
+
+ TARGETING::Target* l_masterProc = nullptr;
l_errl = TARGETING::targetService()
.queryMasterProcChipTargetHandle(l_masterProc);
@@ -159,16 +177,6 @@ public:
}
} while(0);
- if(l_libsmf_loaded)
- {
- l_errl = VFS::module_unload("libsmf.so");
- if(l_errl)
- {
- TS_FAIL("Could not unload libsmf.so");
- errlCommit(l_errl, CXXTEST_COMP_ID);
- }
- }
-
TS_INFO(EXIT_MRK "testCheckRiskLevelForSmf");
}
};
OpenPOWER on IntegriCloud