summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/include/runtime/interface.h20
-rw-r--r--src/include/usr/isteps/nvdimm/nvdimm.H70
-rw-r--r--src/include/usr/isteps/nvdimm/nvdimmreasoncodes.H4
-rw-r--r--src/include/usr/targeting/common/util.H16
-rw-r--r--src/usr/isteps/nvdimm/nvdimm.C151
-rw-r--r--src/usr/isteps/nvdimm/nvdimm.H13
-rw-r--r--src/usr/isteps/nvdimm/runtime/makefile4
-rw-r--r--src/usr/isteps/nvdimm/runtime/nvdimm_rt.C433
-rw-r--r--src/usr/isteps/pm/pm_common.C22
-rw-r--r--src/usr/isteps/pm/runtime/rt_pm.C40
-rw-r--r--src/usr/targeting/common/util.C45
-rw-r--r--src/usr/targeting/common/xmltohb/attribute_types.xml35
-rw-r--r--src/usr/targeting/common/xmltohb/target_types.xml3
-rwxr-xr-xsrc/usr/targeting/targetservicestart.C9
-rw-r--r--src/usr/util/runtime/rt_cmds.C69
-rw-r--r--src/usr/util/runtime/rt_fwreq_helper.C60
16 files changed, 764 insertions, 230 deletions
diff --git a/src/include/runtime/interface.h b/src/include/runtime/interface.h
index 70b6e7e1d..31f5eaddc 100644
--- a/src/include/runtime/interface.h
+++ b/src/include/runtime/interface.h
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2013,2018 */
+/* Contributors Listed Below - COPYRIGHT 2013,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -98,7 +98,7 @@ enum MemoryError_t
#define HBRT_RC_NEXT_OPEN_RC ((int)(0x0u - 0x1009u)) /* 0xFFFF_EFF7 */
/** End return codes for scom_read, scom_write. */
-
+
/**
* I2C Master Description: chip, engine and port packed into
@@ -551,6 +551,14 @@ typedef struct hostInterfaces
HBRT_FW_MSG_HBRT_FSP_RESP = 6,
HBRT_FW_MSG_TYPE_I2C_LOCK = 7,
HBRT_FW_MSG_TYPE_SBE_STATE = 8,
+ HBRT_FW_MSG_TYPE_NVDIMM_PROTECTION = 9,
+ };
+
+ // NVDIMM protection state enum
+ enum
+ {
+ HBRT_FW_NVDIMM_NOT_PROTECTED = 0,
+ HBRT_FW_NVDIMM_PROTECTED = 1
};
struct hbrt_fw_msg // define struct hbrt_fw_msg
@@ -616,6 +624,14 @@ typedef struct hostInterfaces
} __attribute__ ((packed)) sbe_state;
// This struct is sent from HBRT with
+ // io_type set to HBRT_FW_MSG_TYPE_NVDIMM_PROTECTION
+ struct
+ {
+ uint64_t i_procId; // processor ID of the NVDIMM with/without OCC protection
+ uint64_t i_state; // NVDIMM protection state enum
+ } __attribute__ ((packed)) nvdimm_protection_state;
+
+ // This struct is sent from HBRT with
// io_type set to HBRT_FW_MSG_HBRT_FSP_REQ or
// HBRT_FW_MSG_HBRT_FSP_RESP
// This struct sends/receives an MBox message to the FSP
diff --git a/src/include/usr/isteps/nvdimm/nvdimm.H b/src/include/usr/isteps/nvdimm/nvdimm.H
index bfe39fcd0..c1df3033e 100644
--- a/src/include/usr/isteps/nvdimm/nvdimm.H
+++ b/src/include/usr/isteps/nvdimm/nvdimm.H
@@ -55,26 +55,29 @@ enum
void nvdimm_restore(TARGETING::TargetHandleList &i_nvdimmList);
#endif
+
/**
- * @brief This function arms the trigger to enable backup in the event
- * of power loss (DDR Reset_n goes low)
+ * @brief This function erases image on the nvdimm target
*
* @param[in] i_nvdimm - nvdimm target with NV controller
*
* @return errlHndl_t - Null if successful, otherwise a pointer to
* the error log.
*/
-errlHndl_t nvdimmArmResetN(TARGETING::Target *i_nvdimm);
+errlHndl_t nvdimmEraseNF(TARGETING::Target *i_nvdimm);
/**
- * @brief This function erases image on the nvdimm target
+ * @brief Set the status flag
*
- * @param[in] i_nvdimm - nvdimm target with NV controller
+ * @param[in] i_nvdimm - nvdimm target
+ *
+ * @param[in] i_status_flag - status flag to set for each nvdimm
*
- * @return errlHndl_t - Null if successful, otherwise a pointer to
- * the error log.
*/
-errlHndl_t nvdimmEraseNF(TARGETING::Target *i_nvdimm);
+void nvdimmSetStatusFlag(TARGETING::Target *i_nvdimm, const uint8_t i_status_flag);
+
+
+#ifdef __HOSTBOOT_RUNTIME
/**
* @brief Check nvdimm error state
@@ -86,14 +89,57 @@ errlHndl_t nvdimmEraseNF(TARGETING::Target *i_nvdimm);
bool nvdimmInErrorState(TARGETING::Target *i_nvdimm);
/**
- * @brief Set the status flag
+ * @brief This function arms the trigger to enable backup in the event
+ * of power loss (DDR Reset_n goes low)
*
- * @param[in] i_nvdimm - nvdimm target
+ * @param[in] i_nvdimm - nvdimm target with NV controller
*
- * @param[in] i_status_flag - status flag to set for each nvdimm
+ * @return errlHndl_t - Null if successful, otherwise a pointer to
+ * the error log.
+ */
+errlHndl_t nvdimmArmResetN(TARGETING::Target *i_nvdimm);
+
+/**
+ * @brief Arms the trigger to enable backup in the event of a power loss
+ * on each NVDIMM
+ *
+ * The trigger (DDR_RESETN to the DIMM) is used to tell the NVDIMM
+ * that we have an EPOW event, so the NV controller can backup the
+ * data from the DRAM to flash. This will enable the NV controller
+ * to react when it sees the trigger toggles.
*
+ * @param[in] i_nvdimmTargetList : list of dimms that are NVDIMMs
+ * @return true if no errors logged, else false
*/
-void nvdimmSetStatusFlag(TARGETING::Target *i_nvdimm, const uint8_t i_status_flag);
+bool nvdimmArm(TARGETING::TargetHandleList &i_nvdimmTargetList);
+
+
+/**
+ * @brief NVDIMM protection state
+ *
+ * NOT_PROTECTED - default state
+ * PROTECTED - switches to this when armed & OCC is in control
+ * UNPROTECTED_BECAUSE_ERROR - PRD detected error on NV controller
+ * Note: error will stay with target preventing PROTECTED status
+ * until power is cycled again
+ */
+enum nvdimm_protection_t
+{
+ NOT_PROTECTED = 0,
+ PROTECTED = 1,
+ UNPROTECTED_BECAUSE_ERROR = 2
+};
+
+/**
+ * @brief Notify PHYP of NVDIMM protection status
+ *
+ * @param i_target Processor with NVDIMM
+ * @param i_state Protection state of NVDIMM
+ */
+errlHndl_t notifyNvdimmProtectionChange(TARGETING::Target* i_target,
+ const nvdimm_protection_t i_state);
+#endif
+
}
#endif // NVDIMM_EXT_H__
diff --git a/src/include/usr/isteps/nvdimm/nvdimmreasoncodes.H b/src/include/usr/isteps/nvdimm/nvdimmreasoncodes.H
index bde22b942..0b48e94a0 100644
--- a/src/include/usr/isteps/nvdimm/nvdimmreasoncodes.H
+++ b/src/include/usr/isteps/nvdimm/nvdimmreasoncodes.H
@@ -72,7 +72,7 @@ enum nvdimmModuleId
NVDIMM_CHECK_ERASE = 0x16,
NVDIMM_ARM_ERASE = 0x17,
NVDIMM_CHECK_READY = 0x18,
-
+ NOTIFY_NVDIMM_PROTECTION_CHG = 0x19,
};
/**
@@ -111,7 +111,7 @@ enum nvdimmReasonCode
NVDIMM_ERASE_FAILED = NVDIMM_COMP_ID | 0x19, // Failure to erase
NVDIMM_RESTORE_FAILED = NVDIMM_COMP_ID | 0x1A, // Failure to restore
NVDIMM_NOT_READY = NVDIMM_COMP_ID | 0x1B, // NVDIMM not ready for host to access
-
+ NVDIMM_NULL_FIRMWARE_REQUEST_PTR = NVDIMM_COMP_ID | 0x1C, // Firmware request is NULL
};
enum UserDetailsTypes
diff --git a/src/include/usr/targeting/common/util.H b/src/include/usr/targeting/common/util.H
index 971408d16..e26e0c795 100644
--- a/src/include/usr/targeting/common/util.H
+++ b/src/include/usr/targeting/common/util.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2012,2018 */
+/* Contributors Listed Below - COPYRIGHT 2012,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -38,6 +38,8 @@ namespace TARGETING
{
class Target;
+typedef Target* TargetHandle_t;
+typedef std::vector<TargetHandle_t> TargetHandleList;
/**
* @brief Macro which indicates whether to translate addresses or not
@@ -172,6 +174,7 @@ bool orderByNodeAndPosition( Target* i_firstProc,
*/
uint8_t is_fused_mode( );
+
/**
* @brief Determine if the given dimm target is an NVDIMM
*
@@ -181,6 +184,15 @@ uint8_t is_fused_mode( );
*/
bool isNVDIMM( TARGETING::Target * i_target );
-}
+/**
+ * @brief Grab list of NVDIMMs under the processor
+ *
+ * @param[in] i_proc : processor under which to search for NVDIMMs
+ *
+ * @return List of DIMM targets that are NVDIMMs
+ */
+TARGETING::TargetHandleList getProcNVDIMMs( TARGETING::Target * i_proc );
+
+} // TARGETING
#endif // __TARGETING_COMMON_UTIL_H
diff --git a/src/usr/isteps/nvdimm/nvdimm.C b/src/usr/isteps/nvdimm/nvdimm.C
index 9d5b668c0..fdc0240a9 100644
--- a/src/usr/isteps/nvdimm/nvdimm.C
+++ b/src/usr/isteps/nvdimm/nvdimm.C
@@ -205,26 +205,6 @@ void nvdimmSetStatusFlag(Target *i_nvdimm, const uint8_t i_status_flag)
,TARGETING::get_huid(i_nvdimm), i_status_flag);
}
-/**
- * @brief Check nvdimm error state
- *
- * @param[in] i_nvdimm - nvdimm target
- *
- * @return bool - true if nvdimm is in any error state, false otherwise
- */
-bool nvdimmInErrorState(Target *i_nvdimm)
-{
- TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmInErrorState() HUID[%X]",TARGETING::get_huid(i_nvdimm));
-
- uint8_t l_statusFlag = i_nvdimm->getAttr<TARGETING::ATTR_NV_STATUS_FLAG>();
- bool l_ret = true;
-
- if ((l_statusFlag & NSTD_ERR) == 0)
- l_ret = false;
-
- TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmInErrorState() HUID[%X]",TARGETING::get_huid(i_nvdimm));
- return l_ret;
-}
/**
* @brief Check NV controller ready state
@@ -447,31 +427,6 @@ errlHndl_t nvdimmPollEraseDone(Target* i_nvdimm,
return l_err;
}
-/**
- * @brief This function polls the command status register for arm completion
- * (does not indicate success or fail)
- *
- * @param[in] i_nvdimm - nvdimm target with NV controller
- *
- * @param[out] o_poll - total polled time in ms
- *
- * @return errlHndl_t - Null if successful, otherwise a pointer to
- * the error log.
- */
-errlHndl_t nvdimmPollArmDone(Target* i_nvdimm,
- uint32_t &o_poll)
-{
- TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmPollArmDone() nvdimm[%X]", TARGETING::get_huid(i_nvdimm) );
-
- errlHndl_t l_err = nullptr;
-
- l_err = nvdimmPollStatus ( i_nvdimm, ARM, o_poll);
-
- TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmPollArmDone() nvdimm[%X]",
- TARGETING::get_huid(i_nvdimm));
-
- return l_err;
-}
/**
* @brief This function polls the command status register for backup power
@@ -611,113 +566,7 @@ errlHndl_t nvdimmSetESPolicy(Target* i_nvdimm)
}
-/**
- * @brief This function checks the arm status register to make sure
- * the trigger has been armed to ddr_reset_n
- *
- * @param[in] i_nvdimm - nvdimm target with NV controller
- *
- * @return errlHndl_t - Null if successful, otherwise a pointer to
- * the error log.
- */
-errlHndl_t nvdimmCheckArmSuccess(Target *i_nvdimm)
-{
- TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmCheckArmSuccess() nvdimm[%X]",
- TARGETING::get_huid(i_nvdimm));
-
- errlHndl_t l_err = nullptr;
- uint8_t l_data = 0;
-
- l_err = nvdimmReadReg(i_nvdimm, ARM_STATUS, l_data);
-
- if (l_err)
- {
- TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmCheckArmSuccess() nvdimm[%X]"
- "failed to read arm status reg!",TARGETING::get_huid(i_nvdimm));
- }
- else if ((l_data & ARM_SUCCESS) != ARM_SUCCESS)
- {
- TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmCheckArmSuccess() nvdimm[%X]"
- "failed to arm!",TARGETING::get_huid(i_nvdimm));
- /*@
- *@errortype
- *@reasoncode NVDIMM_ARM_FAILED
- *@severity ERRORLOG_SEV_PREDICTIVE
- *@moduleid NVDIMM_SET_ARM
- *@userdata1[0:31] Related ops (0xff = NA)
- *@userdata1[32:63] Target Huid
- *@userdata2 <UNUSED>
- *@devdesc Encountered error arming the catastrophic save
- * trigger on NVDIMM. Make sure an energy source
- * is connected to the NVDIMM and the ES policy
- * is set properly
- *@custdesc NVDIMM encountered error arming save trigger
- */
- l_err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_PREDICTIVE,
- NVDIMM_SET_ARM,
- NVDIMM_ARM_FAILED,
- NVDIMM_SET_USER_DATA_1(ARM, TARGETING::get_huid(i_nvdimm)),
- 0x0,
- ERRORLOG::ErrlEntry::NO_SW_CALLOUT );
-
- l_err->collectTrace(NVDIMM_COMP_NAME, 256 );
- //@TODO RTC 199645 - add HW callout on dimm target
- //failure to arm could mean internal NV controller error or
- //even error on the battery pack. NVDIMM will lose persistency
- //if failed to arm trigger
- }
-
- TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmCheckArmSuccess() nvdimm[%X] ret[%X]",
- TARGETING::get_huid(i_nvdimm), l_data);
-
- return l_err;
-}
-
-/**
- * @brief This function arms the trigger to enable backup in the event
- * of power loss (DDR Reset_n goes low) in conjunction with
- * ATOMIC_SAVE_AND_ERASE. A separate erase command is not required
- * as the image will get erased immediately before backup on the
- * next catastrophic event.
- *
- * @param[in] i_nvdimm - nvdimm target with NV controller
- *
- * @return errlHndl_t - Null if successful, otherwise a pointer to
- * the error log.
- */
-errlHndl_t nvdimmArmResetN(Target *i_nvdimm)
-{
- TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmArmResetN() nvdimm[%X]",
- TARGETING::get_huid(i_nvdimm));
-
- errlHndl_t l_err = nullptr;
-
- // Setting ATOMIC_SAVE_AND_ERASE in conjunction with ARM_RESETN. With this,
- // the content of the persistent data is not erased until immediately after
- // the next catastrophic event has occurred.
- l_err = nvdimmWriteReg(i_nvdimm, ARM_CMD, ARM_RESETN_AND_ATOMIC_SAVE_AND_ERASE);
-
- if (l_err)
- {
- TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmArmResetN() nvdimm[%X] error arming nvdimm!!",
- TARGETING::get_huid(i_nvdimm));
- }
- else
- {
- // Arm happens one module at a time. No need to set any offset on the counter
- uint32_t l_poll = 0;
- l_err = nvdimmPollArmDone(i_nvdimm, l_poll);
- if (!l_err)
- {
- l_err = nvdimmCheckArmSuccess(i_nvdimm);
- }
- }
-
- TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmArmResetN() nvdimm[%X]",
- TARGETING::get_huid(i_nvdimm));
- return l_err;
-}
/**
* @brief This function checks for valid image on the given target
diff --git a/src/usr/isteps/nvdimm/nvdimm.H b/src/usr/isteps/nvdimm/nvdimm.H
index f4d9e0dac..9e60d3224 100644
--- a/src/usr/isteps/nvdimm/nvdimm.H
+++ b/src/usr/isteps/nvdimm/nvdimm.H
@@ -149,6 +149,19 @@ errlHndl_t nvdimmReadReg(TARGETING::Target* i_nvdimm, uint8_t i_addr, uint8_t &
*/
errlHndl_t nvdimmWriteReg(TARGETING::Target* i_nvdimm, uint8_t i_addr, uint8_t i_data );
+/**
+ * @brief This function polls the status register for the given ops_id
+ *
+ * @param[in] i_nvdimm - nvdimm target with NV controller
+ *
+ * @param[in] i_ops_id - id assigned to each operation in nvdimm.H
+ *
+ * @param[out] o_poll - total polled time in ms
+ *
+ * @return errlHndl_t - Null if successful, otherwise a pointer to
+ * the error log.
+ */
+errlHndl_t nvdimmPollStatus(TARGETING::Target *i_nvdimm, ops_id i_ops_id, uint32_t &o_poll);
} //End NVDIMM namespace
diff --git a/src/usr/isteps/nvdimm/runtime/makefile b/src/usr/isteps/nvdimm/runtime/makefile
index 85433ea66..a7da50d08 100644
--- a/src/usr/isteps/nvdimm/runtime/makefile
+++ b/src/usr/isteps/nvdimm/runtime/makefile
@@ -27,8 +27,10 @@ HOSTBOOT_RUNTIME = 1
ROOTPATH = ../../../../..
VPATH += ../
-
MODULE = nvdimm_rt
include ../nvdimm.mk
+
+OBJS += nvdimm_rt.o
+
include ${ROOTPATH}/config.mk
diff --git a/src/usr/isteps/nvdimm/runtime/nvdimm_rt.C b/src/usr/isteps/nvdimm/runtime/nvdimm_rt.C
new file mode 100644
index 000000000..9919c9c61
--- /dev/null
+++ b/src/usr/isteps/nvdimm/runtime/nvdimm_rt.C
@@ -0,0 +1,433 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/isteps/nvdimm/runtime/nvdimm_rt.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2019 */
+/* [+] 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 nvdimm_rt.C
+ *
+ * @brief NVDIMM functions only needed for runtime
+ */
+#include <trace/interface.H>
+#include <errl/errlentry.H>
+#include <errl/errlmanager.H>
+#include <util/runtime/rt_fwreq_helper.H>
+#include <targeting/common/attributes.H>
+#include <targeting/common/commontargeting.H>
+#include <targeting/common/util.H>
+#include <targeting/common/utilFilter.H>
+#include <usr/runtime/rt_targeting.H>
+#include <runtime/interface.h>
+#include <isteps/nvdimm/nvdimmreasoncodes.H>
+#include <isteps/nvdimm/nvdimm.H> // implements some of these
+#include "../nvdimm.H" // for g_trac_nvdimm
+
+//#define TRACUCOMP(args...) TRACFCOMP(args)
+#define TRACUCOMP(args...)
+
+namespace NVDIMM
+{
+
+/**
+* @brief Notify PHYP of NVDIMM OCC protection status
+*/
+errlHndl_t notifyNvdimmProtectionChange(TARGETING::Target* i_target,
+ const nvdimm_protection_t i_state)
+{
+ errlHndl_t l_err = nullptr;
+
+ // default to send a not protected status
+ uint64_t l_nvdimm_protection_state =
+ hostInterfaces::HBRT_FW_NVDIMM_NOT_PROTECTED;
+
+ TRACFCOMP( g_trac_nvdimm, ENTER_MRK
+ "notifyNvdimmProtectionChange: Target huid 0x%.8X, state %d",
+ get_huid(i_target), i_state);
+ do
+ {
+ TARGETING::TargetHandleList l_nvdimmTargetList =
+ TARGETING::getProcNVDIMMs(i_target);
+
+ // Only send command if the processor has an NVDIMM under it
+ if (l_nvdimmTargetList.empty())
+ {
+ TRACFCOMP( g_trac_nvdimm,
+ "notifyNvdimmProtectionChange: No NVDIMM found under processor 0x%.8X",
+ get_huid(i_target));
+ break;
+ }
+
+ TARGETING::ATTR_NVDIMM_ARMED_type l_nvdimm_armed_state =
+ i_target->getAttr<TARGETING::ATTR_NVDIMM_ARMED>();
+
+ // Only notify protected state if NVDIMM controllers are
+ // armed and no error was or is detected
+ if (i_state == NVDIMM::PROTECTED)
+ {
+ // Exit without notifying phyp if in error state
+ if (l_nvdimm_armed_state.error_detected)
+ {
+ // State can't go to protected after error is detected
+ break;
+ }
+ // check if we need to rearm the NVDIMM(s)
+ else if (!l_nvdimm_armed_state.armed)
+ {
+ bool nvdimms_armed =
+ NVDIMM::nvdimmArm(l_nvdimmTargetList);
+ if (nvdimms_armed)
+ {
+ // NVDIMMs are now armed and ready for backup
+ l_nvdimm_armed_state.armed = 1;
+ i_target->setAttr<TARGETING::ATTR_NVDIMM_ARMED>(l_nvdimm_armed_state);
+
+ l_nvdimm_protection_state = hostInterfaces::HBRT_FW_NVDIMM_PROTECTED;
+ }
+ else
+ {
+ // If nvdimm arming failed,
+ // do NOT post that the dimms are now protected.
+
+ // Remember this error, only try arming once
+ if (!l_nvdimm_armed_state.error_detected)
+ {
+ l_nvdimm_armed_state.error_detected = 1;
+ i_target->setAttr<TARGETING::ATTR_NVDIMM_ARMED>(l_nvdimm_armed_state);
+ }
+
+ // Exit without notifying phyp of any protection change
+ break;
+ }
+ }
+ else
+ {
+ // NVDIMM already armed and no error found
+ l_nvdimm_protection_state = hostInterfaces::HBRT_FW_NVDIMM_PROTECTED;
+ }
+ }
+ else if (i_state == NVDIMM::UNPROTECTED_BECAUSE_ERROR)
+ {
+ // Remember that this NV controller has an error so
+ // we don't rearm this until next IPL
+ if (!l_nvdimm_armed_state.error_detected)
+ {
+ l_nvdimm_armed_state.error_detected = 1;
+ i_target->setAttr<TARGETING::ATTR_NVDIMM_ARMED>(l_nvdimm_armed_state);
+ }
+ // still notify phyp that NVDIMM is Not Protected
+ }
+
+
+ // Get the Proc Chip Id
+ RT_TARG::rtChipId_t l_chipId = 0;
+
+ l_err = RT_TARG::getRtTarget(i_target, l_chipId);
+ if(l_err)
+ {
+ TRACFCOMP( g_trac_nvdimm,
+ ERR_MRK"notifyNvdimmProtectionChange: getRtTarget ERROR" );
+ break;
+ }
+
+ // send the notification msg
+ if ((nullptr == g_hostInterfaces) ||
+ (nullptr == g_hostInterfaces->firmware_request))
+ {
+ TRACFCOMP( g_trac_nvdimm, ERR_MRK"notifyNvdimmProtectionChange: "
+ "Hypervisor firmware_request interface not linked");
+
+ // need to safely convert struct type into uint32_t
+ union {
+ TARGETING::ATTR_NVDIMM_ARMED_type tNvdimmArmed;
+ uint32_t nvdimmArmed_int;
+ } armed_state_union;
+ armed_state_union.tNvdimmArmed = l_nvdimm_armed_state;
+
+ /*@
+ * @errortype
+ * @severity ERRL_SEV_PREDICTIVE
+ * @moduleid NOTIFY_NVDIMM_PROTECTION_CHG
+ * @reasoncode NVDIMM_NULL_FIRMWARE_REQUEST_PTR
+ * @userdata1 HUID of processor target
+ * @userdata2[0:31] Requested protection state
+ * @userdata2[32:63] Current armed state
+ * @devdesc Unable to inform PHYP of NVDIMM protection
+ * @custdesc Internal firmware error
+ */
+ l_err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_PREDICTIVE,
+ NOTIFY_NVDIMM_PROTECTION_CHG,
+ NVDIMM_NULL_FIRMWARE_REQUEST_PTR,
+ get_huid(i_target),
+ TWO_UINT32_TO_UINT64(
+ l_nvdimm_protection_state,
+ armed_state_union.nvdimmArmed_int)
+ );
+
+ l_err->addProcedureCallout(HWAS::EPUB_PRC_PHYP_CODE,
+ HWAS::SRCI_PRIORITY_HIGH);
+
+ break;
+ }
+
+ TRACFCOMP( g_trac_nvdimm,
+ "notifyNvdimmProtectionChange: 0x%.8X processor NVDIMMS are "
+ "%s protected (current armed_state: 0x%02X)",
+ get_huid(i_target),
+ (l_nvdimm_protection_state == hostInterfaces::HBRT_FW_NVDIMM_PROTECTED)?"now":"NOT",
+ l_nvdimm_armed_state );
+
+ // Create the firmware_request request struct to send data
+ hostInterfaces::hbrt_fw_msg l_req_fw_msg;
+ memset(&l_req_fw_msg, 0, sizeof(l_req_fw_msg)); // clear it all
+
+ // actual msg size (one type of hbrt_fw_msg)
+ uint64_t l_req_fw_msg_size = hostInterfaces::HBRT_FW_MSG_BASE_SIZE +
+ sizeof(l_req_fw_msg.nvdimm_protection_state);
+
+ // Populate the firmware_request request struct with given data
+ l_req_fw_msg.io_type =
+ hostInterfaces::HBRT_FW_MSG_TYPE_NVDIMM_PROTECTION;
+ l_req_fw_msg.nvdimm_protection_state.i_procId = l_chipId;
+ l_req_fw_msg.nvdimm_protection_state.i_state =
+ l_nvdimm_protection_state;
+
+ // Create the firmware_request response struct to receive data
+ hostInterfaces::hbrt_fw_msg l_resp_fw_msg;
+ uint64_t l_resp_fw_msg_size = sizeof(l_resp_fw_msg);
+ memset(&l_resp_fw_msg, 0, l_resp_fw_msg_size);
+
+ // Make the firmware_request call
+ l_err = firmware_request_helper(l_req_fw_msg_size,
+ &l_req_fw_msg,
+ &l_resp_fw_msg_size,
+ &l_resp_fw_msg);
+
+ } while (0);
+
+ TRACFCOMP( g_trac_nvdimm,
+ EXIT_MRK "notifyNvdimmProtectionChange(%.8X, %d) - ERRL %.8X:%.4X",
+ get_huid(i_target), i_state,
+ ERRL_GETEID_SAFE(l_err), ERRL_GETRC_SAFE(l_err) );
+
+ return l_err;
+}
+
+
+bool nvdimmArm(TARGETING::TargetHandleList &i_nvdimmTargetList)
+{
+ bool o_arm_successful = true;
+
+ TRACFCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmArm() %d",
+ i_nvdimmTargetList.size());
+
+ errlHndl_t l_err = nullptr;
+
+ for (auto const l_nvdimm : i_nvdimmTargetList)
+ {
+ // skip if the nvdimm is in error state
+ if (NVDIMM::nvdimmInErrorState(l_nvdimm))
+ {
+ // error state means arming not successful
+ o_arm_successful = false;
+ continue;
+ }
+
+ l_err = NVDIMM::nvdimmArmResetN(l_nvdimm);
+ // If we run into any error here we will just
+ // commit the error log and move on. Let the
+ // system continue to boot and let the user
+ // salvage the data
+ if (l_err)
+ {
+ NVDIMM::nvdimmSetStatusFlag(l_nvdimm, NVDIMM::NSTD_ERR_NOBKUP);
+ // Committing the error as we don't want this to interrupt
+ // the boot. This will notify the user that action is needed
+ // on this module
+ l_err->setSev(ERRORLOG::ERRL_SEV_PREDICTIVE);
+ l_err->collectTrace(NVDIMM_COMP_NAME, 1024);
+ errlCommit( l_err, NVDIMM_COMP_ID );
+ o_arm_successful = false;
+ continue;
+ }
+ }
+
+ TRACFCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmArm() returning %d",
+ o_arm_successful);
+ return o_arm_successful;
+}
+
+/**
+ * @brief This function polls the command status register for arm completion
+ * (does not indicate success or fail)
+ *
+ * @param[in] i_nvdimm - nvdimm target with NV controller
+ *
+ * @param[out] o_poll - total polled time in ms
+ *
+ * @return errlHndl_t - Null if successful, otherwise a pointer to
+ * the error log.
+ */
+errlHndl_t nvdimmPollArmDone(TARGETING::Target* i_nvdimm,
+ uint32_t &o_poll)
+{
+ TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmPollArmDone() nvdimm[%X]", TARGETING::get_huid(i_nvdimm) );
+
+ errlHndl_t l_err = nullptr;
+
+ l_err = nvdimmPollStatus ( i_nvdimm, ARM, o_poll);
+
+ TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmPollArmDone() nvdimm[%X]",
+ TARGETING::get_huid(i_nvdimm));
+
+ return l_err;
+}
+
+/**
+ * @brief This function checks the arm status register to make sure
+ * the trigger has been armed to ddr_reset_n
+ *
+ * @param[in] i_nvdimm - nvdimm target with NV controller
+ *
+ * @return errlHndl_t - Null if successful, otherwise a pointer to
+ * the error log.
+ */
+errlHndl_t nvdimmCheckArmSuccess(TARGETING::Target *i_nvdimm)
+{
+ TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmCheckArmSuccess() nvdimm[%X]",
+ TARGETING::get_huid(i_nvdimm));
+
+ errlHndl_t l_err = nullptr;
+ uint8_t l_data = 0;
+
+ l_err = nvdimmReadReg(i_nvdimm, ARM_STATUS, l_data);
+
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmCheckArmSuccess() nvdimm[%X]"
+ "failed to read arm status reg!",TARGETING::get_huid(i_nvdimm));
+ }
+ else if ((l_data & ARM_SUCCESS) != ARM_SUCCESS)
+ {
+
+ TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmCheckArmSuccess() nvdimm[%X]"
+ "failed to arm!",TARGETING::get_huid(i_nvdimm));
+ /*@
+ *@errortype
+ *@reasoncode NVDIMM_ARM_FAILED
+ *@severity ERRORLOG_SEV_PREDICTIVE
+ *@moduleid NVDIMM_SET_ARM
+ *@userdata1[0:31] Related ops (0xff = NA)
+ *@userdata1[32:63] Target Huid
+ *@userdata2 <UNUSED>
+ *@devdesc Encountered error arming the catastrophic save
+ * trigger on NVDIMM. Make sure an energy source
+ * is connected to the NVDIMM and the ES policy
+ * is set properly
+ *@custdesc NVDIMM encountered error arming save trigger
+ */
+ l_err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_PREDICTIVE,
+ NVDIMM_SET_ARM,
+ NVDIMM_ARM_FAILED,
+ TWO_UINT32_TO_UINT64(ARM, TARGETING::get_huid(i_nvdimm)),
+ 0x0,
+ ERRORLOG::ErrlEntry::NO_SW_CALLOUT );
+
+ l_err->collectTrace(NVDIMM_COMP_NAME, 256 );
+ //@TODO RTC 199645 - add HW callout on dimm target
+ //failure to arm could mean internal NV controller error or
+ //even error on the battery pack. NVDIMM will lose persistency
+ //if failed to arm trigger
+ }
+
+ TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmCheckArmSuccess() nvdimm[%X] ret[%X]",
+ TARGETING::get_huid(i_nvdimm), l_data);
+
+ return l_err;
+}
+
+/**
+ * @brief This function arms the trigger to enable backup in the event
+ * of power loss (DDR Reset_n goes low) in conjunction with
+ * ATOMIC_SAVE_AND_ERASE. A separate erase command is not required
+ * as the image will get erased immediately before backup on the
+ * next catastrophic event.
+ *
+ * @param[in] i_nvdimm - nvdimm target with NV controller
+ *
+ * @return errlHndl_t - Null if successful, otherwise a pointer to
+ * the error log.
+ */
+errlHndl_t nvdimmArmResetN(TARGETING::Target *i_nvdimm)
+{
+ TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmArmResetN() nvdimm[%X]",
+ TARGETING::get_huid(i_nvdimm));
+
+ errlHndl_t l_err = nullptr;
+
+ // Setting ATOMIC_SAVE_AND_ERASE in conjunction with ARM_RESETN. With this,
+ // the content of the persistent data is not erased until immediately after
+ // the next catastrophic event has occurred.
+ l_err = nvdimmWriteReg(i_nvdimm, ARM_CMD, ARM_RESETN_AND_ATOMIC_SAVE_AND_ERASE);
+
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmArmResetN() nvdimm[%X] error arming nvdimm!!",
+ TARGETING::get_huid(i_nvdimm));
+ }
+ else
+ {
+ // Arm happens one module at a time. No need to set any offset on the counter
+ uint32_t l_poll = 0;
+ l_err = nvdimmPollArmDone(i_nvdimm, l_poll);
+ if (!l_err)
+ {
+ l_err = nvdimmCheckArmSuccess(i_nvdimm);
+ }
+ }
+
+ TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmArmResetN() nvdimm[%X]",
+ TARGETING::get_huid(i_nvdimm));
+ return l_err;
+}
+
+/**
+ * @brief Check nvdimm error state
+ *
+ * @param[in] i_nvdimm - nvdimm target
+ *
+ * @return bool - true if nvdimm is in any error state, false otherwise
+ */
+bool nvdimmInErrorState(TARGETING::Target *i_nvdimm)
+{
+ TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmInErrorState() HUID[%X]",TARGETING::get_huid(i_nvdimm));
+
+ uint8_t l_statusFlag = i_nvdimm->getAttr<TARGETING::ATTR_NV_STATUS_FLAG>();
+ bool l_ret = true;
+
+ if ((l_statusFlag & NSTD_ERR) == 0)
+ l_ret = false;
+
+ TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmInErrorState() HUID[%X]",TARGETING::get_huid(i_nvdimm));
+ return l_ret;
+}
+
+} // end NVDIMM namespace
diff --git a/src/usr/isteps/pm/pm_common.C b/src/usr/isteps/pm/pm_common.C
index 3aef6a713..c66e75727 100644
--- a/src/usr/isteps/pm/pm_common.C
+++ b/src/usr/isteps/pm/pm_common.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2016,2018 */
+/* Contributors Listed Below - COPYRIGHT 2016,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -86,6 +86,10 @@
#include <diag/prdf/prdfWriteHomerFirData.H>
#endif
+#if defined(__HOSTBOOT_RUNTIME) && defined(CONFIG_NVDIMM)
+#include <isteps/nvdimm/nvdimm.H> // notify NVDIMM protection change
+#endif
+
// Easy macro replace for unit testing
//#define TRACUCOMP(args...) TRACFCOMP(args)
#define TRACUCOMP(args...)
@@ -935,6 +939,20 @@ namespace HBPM
break;
}
+#if defined(__HOSTBOOT_RUNTIME) && defined(CONFIG_NVDIMM)
+ // Notify PHYP that NVDIMMs are not protected from power off event
+ l_errl = NVDIMM::notifyNvdimmProtectionChange(i_target, NVDIMM::NOT_PROTECTED);
+ if (l_errl)
+ {
+ TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
+ ERR_MRK"resetPMComplex: unable to notify PHYP that NVDIMM"
+ " is not protected for HUID=0x%.8X", get_huid(i_target) );
+
+ l_errl->collectTrace("ISTEPS_TRACE",256);
+ errlCommit(l_errl, ISTEP_COMP_ID);
+ }
+#endif
+
// Reset path
// p9_pm_init.C enum: PM_RESET
FAPI_INVOKE_HWP( l_errl,
@@ -999,7 +1017,7 @@ namespace HBPM
"resetPMComplex:" "unmap, RC=0x%X" ,
lRc );
}
-
+
TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
EXIT_MRK"resetPMComplex: RC=0x%X, PLID=0x%lX",
ERRL_GETRC_SAFE(l_errl), ERRL_GETPLID_SAFE(l_errl) );
diff --git a/src/usr/isteps/pm/runtime/rt_pm.C b/src/usr/isteps/pm/runtime/rt_pm.C
index 3e5ab8c10..9397d0e83 100644
--- a/src/usr/isteps/pm/runtime/rt_pm.C
+++ b/src/usr/isteps/pm/runtime/rt_pm.C
@@ -40,7 +40,6 @@
#include <runtime/rt_targeting.H>
#include <runtime/runtime_reasoncodes.H>
-
#include <initservice/isteps_trace.H>
// targeting support
@@ -262,44 +261,6 @@ namespace RTPM
break;
}
-#ifdef CONFIG_NVDIMM
- //@TODO RTC 199645 - additional delay needed to ensure OCC is
- // full functional
-
- // Only run this if PM complex started successfully
- // as EPOW save trigger is done by the OCC
- TARGETING::TargetHandleList l_dimmTargetList;
- getChildAffinityTargets( l_dimmTargetList, proc_target, CLASS_NA, TYPE_DIMM );
-
- for (auto const l_dimm : l_dimmTargetList)
- {
- if (TARGETING::isNVDIMM(l_dimm))
- {
- // skip if the nvdimm is in error state
- if (NVDIMM::nvdimmInErrorState(l_dimm))
- {
- continue;
- }
-
- l_err = NVDIMM::nvdimmArmResetN(l_dimm);
- // If we run into any error here we will just
- // commit the error log and move on. Let the
- // system continue to boot and let the user
- // salvage the data
- if (l_err)
- {
- NVDIMM::nvdimmSetStatusFlag(l_dimm, NVDIMM::NSTD_ERR_NOBKUP);
- // Committing the error as we don't want the this to interrupt
- // the boot. This will notifiy the user that action is needed
- // on this module
- l_err->setSev(ERRL_SEV_INFORMATIONAL);
- l_err->collectTrace(NVDIMM_COMP_NAME,1024);
- errlCommit( l_err, NVDIMM_COMP_ID );
- continue;
- }
- }
- }
-#endif
} while(0);
if ( l_err )
@@ -599,4 +560,3 @@ namespace RTPM
registerPm g_registerPm;
};
-
diff --git a/src/usr/targeting/common/util.C b/src/usr/targeting/common/util.C
index a5a9bb7a9..71811366f 100644
--- a/src/usr/targeting/common/util.C
+++ b/src/usr/targeting/common/util.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2012,2018 */
+/* Contributors Listed Below - COPYRIGHT 2012,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -38,9 +38,6 @@
#include <targeting/common/utilFilter.H>
#include <targeting/common/trace.H>
-#define MCA_PER_MCS 2
-#define DIMM_PER_MCA 2
-
namespace TARGETING
{
@@ -284,18 +281,12 @@ uint8_t is_fused_mode( )
} // end is_fused_mode
-/**
- * @brief Determine if the given dimm target is an NVDIMM
- *
- * @param[in] i_target : dimm target to check
- *
- * @return bool - True if the given target is an NVDIMM
- */
+
bool isNVDIMM( TARGETING::Target * i_target )
{
// Not the most elegant way of doing it but the hybrid attributes
// are at the MCS level. Need to find my way up to MCS and check
- // if the dimm is hybrid
+ // if the dimm is hybrid
TARGETING::TargetHandleList l_mcaList;
getParentAffinityTargets(l_mcaList, i_target, TARGETING::CLASS_UNIT, TARGETING::TYPE_MCA);
@@ -313,10 +304,17 @@ bool isNVDIMM( TARGETING::Target * i_target )
if( l_mcsList[0]->tryGetAttr<TARGETING::ATTR_EFF_HYBRID>(l_hybrid) &&
l_mcsList[0]->tryGetAttr<TARGETING::ATTR_EFF_HYBRID_MEMORY_TYPE>(l_hybrid_type) )
{
- //Using relative position to lookup the hybrid attribute for the current dimm
+ //Using relative position to lookup the hybrid attribute for the current dimm
TARGETING::ATTR_REL_POS_type l_dimm_rel_pos = i_target->getAttr<ATTR_REL_POS>();
TARGETING::ATTR_REL_POS_type l_mca_rel_pos = l_mcaList[0]->getAttr<ATTR_REL_POS>();
+ // Verify code is not accessing outside of the array boundaries
+ // Check if l_dimm_rel_pos is outside of l_hybrid column boundary
+ assert(l_dimm_rel_pos < sizeof(l_hybrid[0]));
+
+ // Check if l_mca_rel_pos is outside of l_hybrid row boundary
+ assert(l_mca_rel_pos < (sizeof(l_hybrid)/sizeof(l_hybrid[0])));
+
return (l_hybrid[l_mca_rel_pos][l_dimm_rel_pos] == TARGETING::EFF_HYBRID_IS_HYBRID &&
l_hybrid_type[l_mca_rel_pos][l_dimm_rel_pos] == TARGETING::EFF_HYBRID_MEMORY_TYPE_NVDIMM);
}
@@ -326,4 +324,25 @@ bool isNVDIMM( TARGETING::Target * i_target )
return false;
}
+
+TARGETING::TargetHandleList getProcNVDIMMs( TARGETING::Target * i_proc )
+{
+ TargetHandleList o_nvdimmList;
+
+ TargetHandleList l_dimmTargetList;
+ getChildAffinityTargets( l_dimmTargetList, i_proc, CLASS_NA, TYPE_DIMM );
+
+ for (TargetHandleList::iterator it = l_dimmTargetList.begin();
+ it != l_dimmTargetList.end(); ++it)
+ {
+ TARGETING::Target* l_dimm = *it;
+ if (TARGETING::isNVDIMM(l_dimm))
+ {
+ // Found a valid NVDIMM
+ o_nvdimmList.push_back(l_dimm);
+ }
+ }
+ return o_nvdimmList;
+}
+
} // end namespace TARGETING
diff --git a/src/usr/targeting/common/xmltohb/attribute_types.xml b/src/usr/targeting/common/xmltohb/attribute_types.xml
index eb281a157..c31202b92 100644
--- a/src/usr/targeting/common/xmltohb/attribute_types.xml
+++ b/src/usr/targeting/common/xmltohb/attribute_types.xml
@@ -4925,6 +4925,41 @@
</attribute>
<attribute>
+ <description>
+ NVDIMM(s) are armed for backup incase of power loss (DDR Reset_n goes low)
+ This keeps track of the armed state
+ </description>
+ <persistency>volatile-zeroed</persistency>
+ <readable/>
+ <writeable/>
+ <complexType>
+ <description>Armed State</description>
+ <field>
+ <bits>1</bits>
+ <default>0</default>
+ <description>Is NVDIMM armed</description>
+ <name>armed</name>
+ <type>uint8_t</type>
+ </field>
+ <field>
+ <bits>1</bits>
+ <default>0</default>
+ <description>NVDIMM controller error detected</description>
+ <name>error_detected</name>
+ <type>uint8_t</type>
+ </field>
+ <field>
+ <bits>6</bits>
+ <default>0</default>
+ <description>Reserved for future use</description>
+ <name>reserved</name>
+ <type>uint8_t</type>
+ </field>
+ </complexType>
+ <id>NVDIMM_ARMED</id>
+ </attribute>
+
+ <attribute>
<id>NV_OPS_TIMEOUT_MSEC</id>
<description>
NVDIMM timeout value for 6 main operations
diff --git a/src/usr/targeting/common/xmltohb/target_types.xml b/src/usr/targeting/common/xmltohb/target_types.xml
index 1189f9954..197a591ae 100644
--- a/src/usr/targeting/common/xmltohb/target_types.xml
+++ b/src/usr/targeting/common/xmltohb/target_types.xml
@@ -538,6 +538,9 @@
<id>LOCATION_CODE</id>
</attribute>
<attribute>
+ <id>NVDIMM_ARMED</id>
+ </attribute>
+ <attribute>
<default>
<field>
<id>reserved</id>
diff --git a/src/usr/targeting/targetservicestart.C b/src/usr/targeting/targetservicestart.C
index 9d318bce4..1b86a9c6b 100755
--- a/src/usr/targeting/targetservicestart.C
+++ b/src/usr/targeting/targetservicestart.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2012,2018 */
+/* Contributors Listed Below - COPYRIGHT 2012,2019 */
/* [+] Google Inc. */
/* [+] International Business Machines Corp. */
/* */
@@ -584,6 +584,13 @@ static void initializeAttributes(TargetService& i_targetService,
l_chip->setAttr<ATTR_HB_INITIATED_PM_RESET>
(HB_INITIATED_PM_RESET_INACTIVE);
+ // clear the NVDIMM arming status so it gets redone when OCC is active
+ ATTR_NVDIMM_ARMED_type l_nvdimms_armed_state =
+ l_chip->getAttr<ATTR_NVDIMM_ARMED>();
+ // Only force rearming (error setting should persist)
+ l_nvdimms_armed_state.armed = 0;
+ l_chip->setAttr<ATTR_NVDIMM_ARMED>(l_nvdimms_armed_state);
+
if (l_chip == l_pMasterProcChip)
{
// Need to set PROC_MASTER_TYPE to reflect the
diff --git a/src/usr/util/runtime/rt_cmds.C b/src/usr/util/runtime/rt_cmds.C
index bab3a85d4..c015215b5 100644
--- a/src/usr/util/runtime/rt_cmds.C
+++ b/src/usr/util/runtime/rt_cmds.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2015,2018 */
+/* Contributors Listed Below - COPYRIGHT 2015,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -46,6 +46,9 @@
#include <scom/runtime/rt_scomif.H> // sendScomOpToFsp,
// sendMultiScomReadToFsp,
// switchToFspScomAccess
+#ifdef CONFIG_NVDIMM
+#include <isteps/nvdimm/nvdimm.H> // notify NVDIMM protection change
+#endif
extern char hbi_ImageId;
@@ -1153,6 +1156,49 @@ void cmd_sendMultiScomReadToFSP( char* &o_output,
}
}
+#ifdef CONFIG_NVDIMM
+void cmd_nvdimm_protection_msg( char* &o_output, uint32_t i_huid,
+ uint32_t protection )
+{
+ errlHndl_t l_err = nullptr;
+ o_output = new char[500];
+ uint8_t l_notifyType = NVDIMM::NOT_PROTECTED;
+
+ TARGETING::Target* l_targ{};
+ l_targ = getTargetFromHUID(i_huid);
+ if (l_targ != NULL)
+ {
+ if (protection == 1)
+ {
+ l_notifyType = NVDIMM::PROTECTED;
+ l_err = notifyNvdimmProtectionChange(l_targ, NVDIMM::PROTECTED);
+ }
+ else if (protection == 2)
+ {
+ l_notifyType = NVDIMM::UNPROTECTED_BECAUSE_ERROR;
+ l_err = notifyNvdimmProtectionChange(l_targ, NVDIMM::UNPROTECTED_BECAUSE_ERROR);
+ }
+ else
+ {
+ l_err = notifyNvdimmProtectionChange(l_targ, NVDIMM::NOT_PROTECTED);
+ }
+ if (l_err)
+ {
+ sprintf( o_output, "Error on call to notifyNvdimmProtectionChange"
+ "(0x%.8X, %d), rc=0x%.8X, plid=0x%.8X",
+ i_huid, l_notifyType, ERRL_GETRC_SAFE(l_err), l_err->plid() );
+ errlCommit(l_err, UTIL_COMP_ID);
+ return;
+ }
+ }
+ else
+ {
+ sprintf( o_output, "cmd_nvdimm_protection_msg: HUID 0x%.8X not found",
+ i_huid );
+ return;
+ }
+}
+#endif
/**
* @brief Execute an arbitrary command inside Hostboot Runtime
@@ -1473,6 +1519,22 @@ int hbrtCommand( int argc,
"ERROR: multiScomReadToFsp <huid> <scomAddrs>");
}
}
+#ifdef CONFIG_NVDIMM
+ else if( !strcmp( argv[0], "nvdimm_protection" ) )
+ {
+ if (argc >= 3)
+ {
+ uint32_t huid = strtou64(argv[1], NULL, 16);
+ uint32_t protection = strtou64( argv[2], NULL, 16);
+ cmd_nvdimm_protection_msg( *l_output, huid, protection );
+ }
+ else
+ {
+ *l_output = new char[100];
+ sprintf(*l_output, "ERROR: nvdimm_protection <huid> <0 or 1>");
+ }
+ }
+#endif
else
{
*l_output = new char[50+100*12];
@@ -1509,6 +1571,11 @@ int hbrtCommand( int argc,
strcat( *l_output, l_tmpstr );
sprintf( l_tmpstr, "multiScomReadToFsp <huid> <scomAddrs>\n");
strcat( *l_output, l_tmpstr );
+#ifdef CONFIG_NVDIMM
+ sprintf( l_tmpstr, "nvdimm_protection <huid> <0 or 1>\n");
+ strcat( *l_output, l_tmpstr );
+#endif
+
}
if( l_traceOut && (*l_output != NULL) )
diff --git a/src/usr/util/runtime/rt_fwreq_helper.C b/src/usr/util/runtime/rt_fwreq_helper.C
index 40a8373e5..f94dab238 100644
--- a/src/usr/util/runtime/rt_fwreq_helper.C
+++ b/src/usr/util/runtime/rt_fwreq_helper.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2013,2018 */
+/* Contributors Listed Below - COPYRIGHT 2013,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -250,6 +250,34 @@ errlHndl_t firmware_request_helper(uint64_t i_reqLen, void *i_req,
}
break; // END case hostInterfaces::HBRT_FW_MSG_TYPE_SBE_STATE:
+ case hostInterfaces::HBRT_FW_MSG_TYPE_NVDIMM_PROTECTION:
+ {
+ TRACFCOMP(g_trac_runtime,
+ ERR_MRK"FSP is doing a reset/reload, "
+ "Send NVDIMM state to PHYP failed. "
+ "retry:%d/%d, rc:%d, procId:0x%.8X, "
+ "state:%d - %s",
+ i,
+ HBRT_FW_REQUEST_RETRIES,
+ rc,
+ l_req_fw_msg->sbe_state.i_procId,
+ l_req_fw_msg->sbe_state.i_state,
+ l_req_fw_msg->sbe_state.i_state?
+ "protected":"not protected");
+
+ // Pack user data 1 with Hypervisor return code and
+ // firmware request message type
+ l_userData1 = TWO_UINT32_TO_UINT64(rc,
+ l_req_fw_msg->io_type);
+
+ // Pack user data 2 with processor ID of NVDIMM
+ // and state of the NVDIMM
+ l_userData2 = TWO_UINT32_TO_UINT64(
+ l_req_fw_msg->nvdimm_protection_state.i_procId,
+ l_req_fw_msg->nvdimm_protection_state.i_state);
+ }
+ break; // END case hostInterfaces::HBRT_FW_MSG_TYPE_NVDIMM_PROTECTION:
+
default:
break;
} // END switch (l_req_fw_msg->io_type)
@@ -270,7 +298,8 @@ errlHndl_t firmware_request_helper(uint64_t i_reqLen, void *i_req,
chipID
* @userdata2[32:63] SCOM data (HCODE Update) ||
Message Type (FSP MSG) ||
- SBE state
+ SBE state ||
+ NVDIMM protection
* @devdesc The Firmware Request call failed
*/
l_err = new ErrlEntry(ERRL_SEV_INFORMATIONAL,
@@ -439,6 +468,30 @@ errlHndl_t firmware_request_helper(uint64_t i_reqLen, void *i_req,
}
break; // END case hostInterfaces::HBRT_FW_MSG_TYPE_SBE_STATE:
+ case hostInterfaces::HBRT_FW_MSG_TYPE_NVDIMM_PROTECTION:
+ {
+ TRACFCOMP(g_trac_runtime,
+ ERR_MRK"Failed sending NVDIMM protection state to PHYP."
+ " rc:0x%X, procId:0x%.8X, state:%d - %s",
+ rc,
+ l_req_fw_msg->sbe_state.i_procId,
+ l_req_fw_msg->sbe_state.i_state,
+ l_req_fw_msg->sbe_state.i_state?
+ "protected":"not protected");
+
+ // Pack user data 1 with Hypervisor return code and
+ // firmware request message type
+ l_userData1 = TWO_UINT32_TO_UINT64(rc,
+ l_req_fw_msg->io_type);
+
+ // Pack user data 2 with processor ID of NVDIMM
+ // and state of the NVDIMM
+ l_userData2 = TWO_UINT32_TO_UINT64(
+ l_req_fw_msg->nvdimm_protection_state.i_procId,
+ l_req_fw_msg->nvdimm_protection_state.i_state);
+ }
+ break; // END case hostInterfaces::HBRT_FW_MSG_TYPE_NVDIMM_PROTECTION:
+
default:
break;
} // END switch (l_req_fw_msg->io_type)
@@ -459,7 +512,8 @@ errlHndl_t firmware_request_helper(uint64_t i_reqLen, void *i_req,
chipId
* @userdata2[32:63] SCOM data (HCODE Update) ||
Message Type (FSP MSG) ||
- SBE state
+ SBE state ||
+ NVDIMM protection state
* @devdesc The Firmware Request call failed
*/
l_err = new ErrlEntry(ERRL_SEV_PREDICTIVE,
OpenPOWER on IntegriCloud