summaryrefslogtreecommitdiffstats
path: root/src/usr/runtime
diff options
context:
space:
mode:
authorIlya Smirnov <ismirno@us.ibm.com>2018-01-26 12:10:24 -0600
committerDaniel M. Crowell <dcrowell@us.ibm.com>2018-02-14 15:01:31 -0500
commitd9c127dca8312f119b379c83b361216b910f6748 (patch)
tree8d37e7926981c115092a558daf36d8d02d405ae2 /src/usr/runtime
parentddfe08755562f0bd6b2ec445972f4b2c751a5f80 (diff)
downloadtalos-hostboot-d9c127dca8312f119b379c83b361216b910f6748.tar.gz
talos-hostboot-d9c127dca8312f119b379c83b361216b910f6748.zip
Error when hb tries to access reserved memory past limit
An issue has recently occurred when hb reserved memory past the allowed limit (256M-4K) and overwrote some of the PHYP memory, which caused bugs that were difficult to debug. This change is to check the memory address we are trying to reserve and throw an error if the address is at or above the allowed limit. We only execute this check if PHYP is running and only on components not belonging to PHYP (PHYP components may be placed outside of the limit). Change-Id: Ic62a7b724abc3b29b7872d0af47de8c68cde2ea8 RTC:186332 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/52850 Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Reviewed-by: Nicholas E. Bofferding <bofferdn@us.ibm.com> Tested-by: Jenkins OP Build CI <op-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> Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/usr/runtime')
-rw-r--r--src/usr/runtime/populate_hbruntime.C74
-rw-r--r--src/usr/runtime/preverifiedlidmgr.C10
-rw-r--r--src/usr/runtime/test/makefile3
-rw-r--r--src/usr/runtime/test/test_checkHbResMemLimit.H157
4 files changed, 235 insertions, 9 deletions
diff --git a/src/usr/runtime/populate_hbruntime.C b/src/usr/runtime/populate_hbruntime.C
index d8faf94dd..66806d87a 100644
--- a/src/usr/runtime/populate_hbruntime.C
+++ b/src/usr/runtime/populate_hbruntime.C
@@ -77,6 +77,7 @@
#include <runtime/common/runtime_utils.H>
#include <limits.h>
#include <errno.h>
+#include <vmmconst.h>
namespace RUNTIME
{
@@ -88,6 +89,15 @@ const uint16_t TPM_REQUIRED_BIT = 0x8000; //leftmost bit of uint16_t set to 1
const uint8_t BITS_PER_BYTE = 8;
+// The upper limit of the hostboot reserved memory. Only applies to PHYP.
+// The lower limit is Hostboot HRMOR + 64MB; 4KB is the PHYP component's
+// secure header.
+const uint64_t HB_RES_MEM_UPPER_LIMIT = 256*MEGABYTE - 4*KILOBYTE;
+
+// The lower limit of the hostboot reserved memory. Do not allow to reserve
+// any memory below this limit.
+const uint64_t HB_RES_MEM_LOWER_LIMIT = VMM_MEMORY_SIZE + VMM_HRMOR_OFFSET;
+
trace_desc_t *g_trac_runtime = nullptr;
TRAC_INIT(&g_trac_runtime, RUNTIME_COMP_NAME, KILOBYTE);
@@ -250,17 +260,69 @@ void traceHbRsvMemRange(hdatMsVpdRhbAddrRange_t* & i_rngPtr )
i_rngPtr->hdatRhbPermission);
}
+errlHndl_t checkHbResMemLimit(const uint64_t i_addr, const uint64_t i_size)
+{
+ errlHndl_t l_errl = nullptr;
+ // Only check if PHYP is running or if running in standalone.
+ if(TARGETING::is_phyp_load() || TARGETING::is_no_load())
+ {
+ if((i_addr < HB_RES_MEM_LOWER_LIMIT) or
+ ((i_addr + i_size - 1) > HB_RES_MEM_UPPER_LIMIT))
+ {
+ TRACFCOMP(g_trac_runtime, "checkHbResMemLimit> Attempt to write"
+ " to hostboot reserved memory outside of allowed hostboot address"
+ " range. Start addresss - 0x%08x end address - 0x%08x;"
+ " bottom limit - 0x%08x top limit - 0x%08x.",
+ i_addr, i_addr + i_size - 1,
+ HB_RES_MEM_LOWER_LIMIT, HB_RES_MEM_UPPER_LIMIT);
+
+ /*@
+ * @errortype
+ * @moduleid RUNTIME::MOD_CHECK_HB_RES_MEM_LIMIT
+ * @reasoncode RUNTIME::RC_HB_RES_MEM_EXCEEDED
+ * @userdata1 Starting address
+ * @userdata2 Size of the section
+ * @devdesc Hostboot attempted to reserve memory past allowed
+ * range. Bottom limit = Hostboot HRMOR + 64M, top
+ * limit = 256M - 4K.
+ * @custdesc Hostboot attempted to reserve memory outside of
+ * allowed range.
+ */
+ l_errl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ RUNTIME::MOD_CHECK_HB_RES_MEM_LIMIT,
+ RUNTIME::RC_HB_RES_MEM_EXCEEDED,
+ i_addr,
+ i_size,
+ true /*Add HB Software Callout*/);
+ l_errl->collectTrace(RUNTIME_COMP_NAME,KILOBYTE);
+ }
+ }
+ return l_errl;
+}
+
errlHndl_t setNextHbRsvMemEntry(const HDAT::hdatMsVpdRhbAddrRangeType i_type,
const uint16_t i_rangeId,
const uint64_t i_startAddr,
const uint64_t i_size,
const char* i_label,
- const HDAT::hdatRhbPermType i_permission)
+ const HDAT::hdatRhbPermType i_permission,
+ const bool i_checkMemoryLimit)
{
errlHndl_t l_elog = nullptr;
do {
+ // Check whether hostboot is trying to access memory outside of its allowed
+ // range.
+ if(i_checkMemoryLimit)
+ {
+ l_elog = checkHbResMemLimit(i_startAddr, i_size);
+ if(l_elog)
+ {
+ break;
+ }
+ }
+
// Get a pointer to the next available HDAT HB Rsv Mem entry
hdatMsVpdRhbAddrRange_t* l_rngPtr = nullptr;
l_elog = getNextRhbAddrRange(l_rngPtr);
@@ -813,10 +875,12 @@ errlHndl_t populate_HbRsvMem(uint64_t i_nodeId, bool i_master_node)
uint64_t l_hbAddr = cpu_spr_value(CPU_SPR_HRMOR)
- VMM_HRMOR_OFFSET;
l_elog = setNextHbRsvMemEntry(HDAT::RHB_TYPE_PRIMARY,
- i_nodeId,
- l_hbAddr,
- VMM_HB_RSV_MEM_SIZE,
- HBRT_RSVD_MEM__PRIMARY);
+ i_nodeId,
+ l_hbAddr,
+ VMM_HB_RSV_MEM_SIZE,
+ HBRT_RSVD_MEM__PRIMARY,
+ HDAT::RHB_READ_WRITE,
+ false);
if(l_elog != nullptr)
{
break;
diff --git a/src/usr/runtime/preverifiedlidmgr.C b/src/usr/runtime/preverifiedlidmgr.C
index e28e56af7..2362e1fc0 100644
--- a/src/usr/runtime/preverifiedlidmgr.C
+++ b/src/usr/runtime/preverifiedlidmgr.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2017 */
+/* Contributors Listed Below - COPYRIGHT 2017,2018 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -389,7 +389,11 @@ errlHndl_t PreVerifiedLidMgr::_loadFromMCL(const uint32_t i_lidId,
cv_pResvMemInfo->rangeId,
cv_pResvMemInfo->curAddr,
i_size,
- l_lidStr);
+ l_lidStr,
+ HDAT::RHB_READ_WRITE,
+ // Memory limit everything that
+ // is not a PHYP component
+ !(i_isPhypComp));
if(l_errl)
{
TRACFCOMP( g_trac_runtime, ERR_MRK"PreVerifiedLidMgr::_loadFromMCL - setNextHbRsvMemEntry Lid content failed");
@@ -573,4 +577,4 @@ errlHndl_t PreVerifiedLidMgr::loadImage(const uint64_t i_imgAddr,
TRACDCOMP( g_trac_runtime, EXIT_MRK"PreVerifiedLidMgr::loadImage");
return l_errl;
-} \ No newline at end of file
+}
diff --git a/src/usr/runtime/test/makefile b/src/usr/runtime/test/makefile
index 92715cf83..7eaaae928 100644
--- a/src/usr/runtime/test/makefile
+++ b/src/usr/runtime/test/makefile
@@ -5,7 +5,7 @@
#
# OpenPOWER HostBoot Project
#
-# Contributors Listed Below - COPYRIGHT 2012,2017
+# Contributors Listed Below - COPYRIGHT 2012,2018
# [+] International Business Machines Corp.
#
#
@@ -26,6 +26,7 @@ ROOTPATH = ../../../..
MODULE = testruntime
TESTS += testpreverifiedlidmgr.H
+TESTS += test_checkHbResMemLimit.H
#@TODO RTC 132750
#TESTS += hdatservicetest.H
#@TODO RTC:178802
diff --git a/src/usr/runtime/test/test_checkHbResMemLimit.H b/src/usr/runtime/test/test_checkHbResMemLimit.H
new file mode 100644
index 000000000..e2ab9ca41
--- /dev/null
+++ b/src/usr/runtime/test/test_checkHbResMemLimit.H
@@ -0,0 +1,157 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/runtime/test/test_checkHbResMemLimit.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_CHECKHBRESMEMLIMIT_H
+#define _TEST_CHECKHBRESMEMLIMIT_H
+
+#include <cxxtest/TestSuite.H>
+#include <runtime/populate_hbruntime.H>
+#include <errl/errlmanager.H>
+#include <hdat/hdat.H>
+#include <runtime/interface.h>
+#include <runtime/runtime_reasoncodes.H>
+#include <vmmconst.h>
+
+extern trace_desc_t* g_trac_runtime;
+
+class CheckHbResMemLimitTest : public CxxTest::TestSuite
+{
+public:
+
+ void testAddressWithinHbResMemRange()
+ {
+ TRACFCOMP(g_trac_runtime, "testAddressWithinHbResMemRange running");
+ errlHndl_t l_errl = nullptr;
+ l_errl = RUNTIME::checkHbResMemLimit(RUNTIME::HB_RES_MEM_LOWER_LIMIT, //i_addr
+ 1); //i_size
+ if(l_errl)
+ {
+ TS_FAIL("testAddressWithinHbResMemRange: checkHbResMemLimit"
+ " returned an unexpected error");
+ errlCommit(l_errl, CXXTEST_COMP_ID);
+ }
+ else
+ {
+ TRACDCOMP(g_trac_runtime, "testAddressWithinHbResMemRange:"
+ " no error returned (expected)");
+ }
+ TRACFCOMP(g_trac_runtime, "testAddressWithinHbResMemRange finished");
+ }
+
+ void testAddressAboveHbResMemRange()
+ {
+ TRACFCOMP(g_trac_runtime, "testAddressAboveHbResMemRange running");
+ errlHndl_t l_errl = nullptr;
+ l_errl = RUNTIME::checkHbResMemLimit(RUNTIME::HB_RES_MEM_UPPER_LIMIT, //i_addr
+ 10); //i_size
+ do{
+
+ if(l_errl)
+ {
+ TRACDCOMP(g_trac_runtime, "testAddressAboveHbResMemRange:"
+ " errl returned (expected)");
+
+ //Check module id and reason code
+ if((l_errl->moduleId() == RUNTIME::MOD_CHECK_HB_RES_MEM_LIMIT) and
+ (l_errl->reasonCode() == RUNTIME::RC_HB_RES_MEM_EXCEEDED))
+ {
+ TRACDCOMP(g_trac_runtime, "testAddressAboveHbResMemRange:"
+ " error's module id and reason code match expected values");
+ }
+ else
+ {
+ TS_FAIL("testAddressAboveHbResMemRange: error with unexpected"
+ " module id/reason code returned. Expected module id = "
+ "0x%x returned module id = 0x%x; expected reason code ="
+ " 0x%x returned reason code = 0x%x",
+ RUNTIME::MOD_CHECK_HB_RES_MEM_LIMIT,
+ l_errl->moduleId(),
+ RUNTIME::RC_HB_RES_MEM_EXCEEDED,
+ l_errl->reasonCode());
+ errlCommit(l_errl, CXXTEST_COMP_ID);
+ break;
+ }
+ delete l_errl;
+ l_errl = nullptr;
+ }
+ else
+ {
+ TS_FAIL("testAddressAboveHbResMemRange: no errl returned from"
+ " checkHbResMemLimit under error condition");
+ }
+
+ }while(0);
+ TRACFCOMP(g_trac_runtime, "testAddressAboveHbResMemRange finished");
+ }
+
+ void testAddressBelowHbResMemRange()
+ {
+ TRACFCOMP(g_trac_runtime, "testAddressBelowHbResMemRange running");
+
+ errlHndl_t l_errl = nullptr;
+ l_errl = RUNTIME::checkHbResMemLimit(RUNTIME::HB_RES_MEM_LOWER_LIMIT
+ - 11, //i_addr
+ 10); //i_size
+ do{
+
+ if(l_errl)
+ {
+ TRACDCOMP(g_trac_runtime, "testAddressBelowHbResMemRange:"
+ " errl returned (expected).");
+ //Check module id and reason code
+ if((l_errl->moduleId() == RUNTIME::MOD_CHECK_HB_RES_MEM_LIMIT) and
+ (l_errl->reasonCode() == RUNTIME::RC_HB_RES_MEM_EXCEEDED))
+ {
+ TRACDCOMP(g_trac_runtime, "testAddressBelowHbResMemRange:"
+ " error's module id and reason code match expected values");
+ }
+ else
+ {
+ TS_FAIL("testAddressBelowHbResMemRange: error with unexpected"
+ " module id/reason code returned. Expected module id = "
+ "0x%x returned module id = 0x%x; expected reason code ="
+ " 0x%x returned reason code = 0x%x",
+ RUNTIME::MOD_CHECK_HB_RES_MEM_LIMIT,
+ l_errl->moduleId(),
+ RUNTIME::RC_HB_RES_MEM_EXCEEDED,
+ l_errl->reasonCode());
+ errlCommit(l_errl, CXXTEST_COMP_ID);
+ break;
+ }
+ delete l_errl;
+ l_errl = nullptr;
+ }
+ else
+ {
+ TS_FAIL("testAddressBelowHbResMemRange: no errl returned from"
+ " checkHbResMemLimit under error condition");
+ }
+
+ }while(0);
+ TRACFCOMP(g_trac_runtime, "testAddressBelowHbResMemRange finished");
+ }
+};
+
+
+#endif
OpenPOWER on IntegriCloud