From ed35e3da7c2606f6fe0930725892deae85df33b7 Mon Sep 17 00:00:00 2001 From: Ilya Smirnov Date: Mon, 12 Nov 2018 08:51:33 -0600 Subject: 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 Tested-by: Jenkins Server Tested-by: Jenkins OP Build CI Tested-by: FSP CI Jenkins Tested-by: Jenkins OP HW Reviewed-by: Michael Baiocchi Reviewed-by: Daniel M. Crowell --- src/include/usr/secureboot/smf.H | 57 +++- src/usr/secureboot/smf/smf.C | 151 ++++++----- src/usr/secureboot/smf/test/makefile | 1 + src/usr/secureboot/smf/test/testmemutils.H | 108 ++++---- src/usr/secureboot/smf/test/testsmf.H | 413 +++++++++++++++++++++++++++++ src/usr/secureboot/smf/test/testsmfutils.H | 74 +++--- 6 files changed, 637 insertions(+), 167 deletions(-) create mode 100644 src/usr/secureboot/smf/test/testsmf.H 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& 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(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(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& 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::vectorl_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(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( @@ -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()); - l_totMemOnSystem += getTotalProcMemSize(l_proc); + TARGETING::get_huid(l_proc.proc), + l_proc.proc->getAttr()); + 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::vectorl_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(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(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(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(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 +#include +#include +#include +#include +#include +#include +#include +#include + +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(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(); + + } 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(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()) + { + // 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(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"); } }; -- cgit v1.2.1