From 7508722e0908dae7096a98d502dbef9917f5857a Mon Sep 17 00:00:00 2001 From: Corey Swenson Date: Wed, 12 Jun 2019 11:59:56 -0500 Subject: Handle NVDIMM encryption errors Update ATTR_NVDIMM_ARMED and ATTR_NV_STATUS_FLAG Update notifyNvdimmProtectionChange() Set encryption error and check before arm/disarm Change-Id: I1edf738af3460684ee93b02f06ff417c3e72d4e3 RTC:210689 Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/78828 Tested-by: Jenkins Server Reviewed-by: Daniel M. Crowell --- src/include/usr/isteps/nvdimm/nvdimm.H | 32 +- src/usr/isteps/nvdimm/nvdimm.C | 78 ++--- src/usr/isteps/nvdimm/nvdimm.H | 11 + src/usr/isteps/nvdimm/runtime/nvdimm_rt.C | 324 ++++++++++++++------- src/usr/isteps/pm/pm_common.C | 2 +- .../targeting/common/xmltohb/attribute_types.xml | 40 ++- src/usr/targeting/targetservicestart.C | 23 +- src/usr/util/runtime/rt_cmds.C | 39 ++- src/usr/util/runtime/rt_fwnotify.C | 15 +- 9 files changed, 386 insertions(+), 178 deletions(-) diff --git a/src/include/usr/isteps/nvdimm/nvdimm.H b/src/include/usr/isteps/nvdimm/nvdimm.H index 7325c9a7c..9b37765f8 100644 --- a/src/include/usr/isteps/nvdimm/nvdimm.H +++ b/src/include/usr/isteps/nvdimm/nvdimm.H @@ -83,9 +83,6 @@ bool nvdimm_encrypt_unlock(TARGETING::TargetHandleList &i_nvdimmList); #endif -// TODO RTC:210689 Handle return pass/fail -// Need to define what return=false means for the caller -// For all of the functions in this file /** * @brief Entry function to NVDIMM generate keys * Generate encryption keys and set the FW key attribute @@ -198,23 +195,34 @@ bool nvdimmDisarm(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 + * NVDIMM_ARMED - set armed state + * NVDIMM_DISARMED - set disarmed state + * OCC_ACTIVE - set active state + * OCC_INACTIVE - set inactive state + * NVDIMM_FATAL_HW_ERROR - set fatal hw state + * NVDIMM_RISKY_HW_ERROR - set risky hw state + * Note: fatal 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 + NVDIMM_ARMED = 0, + NVDIMM_DISARMED = 1, + OCC_ACTIVE = 2, + OCC_INACTIVE = 3, + NVDIMM_FATAL_HW_ERROR = 4, + NVDIMM_RISKY_HW_ERROR = 5, + /* deprecated, still used by PRD */ + UNPROTECTED_BECAUSE_ERROR = 4, }; /** * @brief Notify PHYP of NVDIMM protection status * - * @param i_target Processor with NVDIMM + * @param i_target Processor with NVDIMM or NVDIMM itself + * - ARMED state updated per NVDIMM + * - ERROR states updated per NVDIMM + * - OCC state updated per PROC * @param i_state Protection state of NVDIMM */ errlHndl_t notifyNvdimmProtectionChange(TARGETING::Target* i_target, diff --git a/src/usr/isteps/nvdimm/nvdimm.C b/src/usr/isteps/nvdimm/nvdimm.C index 1cae5d9f3..eeb1713b7 100644 --- a/src/usr/isteps/nvdimm/nvdimm.C +++ b/src/usr/isteps/nvdimm/nvdimm.C @@ -1718,8 +1718,7 @@ bool nvdimm_encrypt_unlock(TargetHandleList &i_nvdimmList) { TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_encrypt_unlock() nvdimm[%X] error reading ENCRYPTION_CONFIG_STATUS",get_huid(l_nvdimm)); errlCommit( l_err, NVDIMM_COMP_ID ); - // TODO RTC:210689 Handle status flag - //nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOBKUP); + nvdimmSetEncryptionError(l_nvdimm); l_success = false; continue; } @@ -1743,8 +1742,7 @@ bool nvdimm_encrypt_unlock(TargetHandleList &i_nvdimmList) if (l_err) { errlCommit( l_err, NVDIMM_COMP_ID ); - // TODO RTC:210689 Handle status flag - //nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOBKUP); + nvdimmSetEncryptionError(l_nvdimm); l_success = false; continue; } @@ -1757,8 +1755,7 @@ bool nvdimm_encrypt_unlock(TargetHandleList &i_nvdimmList) { TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_encrypt_unlock() nvdimm[%X] error reading ENCRYPTION_CONFIG_STATUS after unlock",get_huid(l_nvdimm)); errlCommit( l_err, NVDIMM_COMP_ID ); - // TODO RTC:210689 Handle status flag - //nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOBKUP); + nvdimmSetEncryptionError(l_nvdimm); l_success = false; continue; } @@ -1789,9 +1786,8 @@ bool nvdimm_encrypt_unlock(TargetHandleList &i_nvdimmList) HWAS::NV_CONTROLLER_PART_TYPE, HWAS::SRCI_PRIORITY_HIGH); - // TODO RTC:210689 Handle status flag - //nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOBKUP); errlCommit( l_err, NVDIMM_COMP_ID ); + nvdimmSetEncryptionError(l_nvdimm); l_success = false; } else @@ -1809,6 +1805,23 @@ bool nvdimm_encrypt_unlock(TargetHandleList &i_nvdimmList) #endif +void nvdimmSetEncryptionError(Target *i_nvdimm) +{ + ATTR_NVDIMM_ARMED_type l_armed_state = {}; + // TODO: RTC 211510 Move ATTR_NVDIMM_ARMED from proc_type to dimm type + //l_armed_state = i_nvdimm->getAttr(); + uint8_t l_tmp = i_nvdimm->getAttr(); + memcpy(&l_armed_state, &l_tmp, sizeof(l_tmp)); + + l_armed_state.encryption_error_detected = 1; + + // TODO: RTC 211510 Move ATTR_NVDIMM_ARMED from proc_type to dimm type + //i_nvdimm->setAttr(l_armed_state); + memcpy(&l_tmp, &l_armed_state, sizeof(l_tmp)); + i_nvdimm->setAttr(l_tmp); +} + + bool nvdimm_keyifyRandomNumber(uint8_t* o_genData, uint8_t* i_xtraData) { bool l_failed = false; @@ -1941,7 +1954,6 @@ errlHndl_t nvdimm_handleConflictingKeys( false); if (l_err) { - // RTC 210689 Handle return values break; } @@ -1953,7 +1965,6 @@ errlHndl_t nvdimm_handleConflictingKeys( if (l_err) { TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_handleConflictingKeys() nvdimm[%X] error reading ENCRYPTION_KEY_VALIDATION",get_huid(l_nvdimm)); - // RTC 210689 Handle return values break; } if (l_keyValid.erase_key_valid) @@ -2155,12 +2166,12 @@ bool nvdimm_gen_keys(void) errlCommit( l_err, NVDIMM_COMP_ID ); l_success = false; - // Set the status flag for all nvdimms + // Set the encryption error for all nvdimms TargetHandleList l_nvdimmTargetList; nvdimm_getNvdimmList(l_nvdimmTargetList); for (const auto & l_nvdimm : l_nvdimmTargetList) { - nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOBKUP); + nvdimmSetEncryptionError(l_nvdimm); } } @@ -2174,6 +2185,7 @@ bool nvdimm_remove_keys(void) TRACFCOMP(g_trac_nvdimm, ENTER_MRK"nvdimm_remove_keys()"); bool l_success = true; + // Get the sys pointer, attribute keys are system level Target* l_sys = nullptr; targetService().getTopLevelTarget( l_sys ); assert(l_sys, "nvdimm_remove_keys() no TopLevelTarget"); @@ -2351,8 +2363,7 @@ bool nvdimm_encrypt_enable(TargetHandleList &i_nvdimmList) { TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_encrypt_enable() nvdimm[%X] error reading ENCRYPTION_CONFIG_STATUS",get_huid(l_nvdimm)); errlCommit( l_err, NVDIMM_COMP_ID ); - // TODO RTC:210689 Handle status flag - //nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOBKUP); + nvdimmSetEncryptionError(l_nvdimm); l_success = false; continue; } @@ -2383,8 +2394,7 @@ bool nvdimm_encrypt_enable(TargetHandleList &i_nvdimmList) if (l_err) { errlCommit( l_err, NVDIMM_COMP_ID ); - // TODO RTC:210689 Handle status flag - //nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOBKUP); + nvdimmSetEncryptionError(l_nvdimm); l_success = false; continue; } @@ -2398,8 +2408,7 @@ bool nvdimm_encrypt_enable(TargetHandleList &i_nvdimmList) if (l_err) { errlCommit( l_err, NVDIMM_COMP_ID ); - // TODO RTC:210689 Handle status flag - //nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOBKUP); + nvdimmSetEncryptionError(l_nvdimm); l_success = false; continue; } @@ -2413,8 +2422,7 @@ bool nvdimm_encrypt_enable(TargetHandleList &i_nvdimmList) if (l_err) { errlCommit( l_err, NVDIMM_COMP_ID ); - // TODO RTC:210689 Handle status flag - //nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOBKUP); + nvdimmSetEncryptionError(l_nvdimm); l_success = false; continue; } @@ -2427,8 +2435,7 @@ bool nvdimm_encrypt_enable(TargetHandleList &i_nvdimmList) { TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_encrypt_enable() nvdimm[%X] error reading ENCRYPTION_CONFIG_STATUS after enable",get_huid(l_nvdimm)); errlCommit( l_err, NVDIMM_COMP_ID ); - // TODO RTC:210689 Handle status flag - //nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOBKUP); + nvdimmSetEncryptionError(l_nvdimm); l_success = false; continue; } @@ -2459,8 +2466,7 @@ bool nvdimm_encrypt_enable(TargetHandleList &i_nvdimmList) HWAS::SRCI_PRIORITY_HIGH); errlCommit( l_err, NVDIMM_COMP_ID ); - // TODO RTC:210689 Handle status flag - //nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOBKUP); + nvdimmSetEncryptionError(l_nvdimm); l_success = false; } else @@ -2522,6 +2528,7 @@ bool nvdimm_crypto_erase(TargetHandleList &i_nvdimmList) { TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_crypto_erase() nvdimm[%X] error reading ENCRYPTION_CONFIG_STATUS",get_huid(l_nvdimm)); errlCommit( l_err, NVDIMM_COMP_ID ); + nvdimmSetEncryptionError(l_nvdimm); l_success = false; continue; } @@ -2529,7 +2536,7 @@ bool nvdimm_crypto_erase(TargetHandleList &i_nvdimmList) if (!l_encStatus.encryption_enabled) { TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_crypto_erase() nvdimm[%X] encryption not enabled, will not cypto erase 0x%.02x",get_huid(l_nvdimm),l_encStatus.whole); - // TODO RTC:210689 Handle function return pass/fail + l_success = false; continue; } else @@ -2546,8 +2553,7 @@ bool nvdimm_crypto_erase(TargetHandleList &i_nvdimmList) if (l_err) { errlCommit( l_err, NVDIMM_COMP_ID ); - // TODO RTC:210689 Handle status flag - //nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOBKUP); + nvdimmSetEncryptionError(l_nvdimm); l_success = false; continue; } @@ -2560,8 +2566,7 @@ bool nvdimm_crypto_erase(TargetHandleList &i_nvdimmList) { TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_crypto_erase() nvdimm[%X] error reading ENCRYPTION_CONFIG_STATUS",get_huid(l_nvdimm)); errlCommit( l_err, NVDIMM_COMP_ID ); - // TODO RTC:210689 Handle status flag - //nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOBKUP); + nvdimmSetEncryptionError(l_nvdimm); l_success = false; continue; } @@ -2593,8 +2598,7 @@ bool nvdimm_crypto_erase(TargetHandleList &i_nvdimmList) HWAS::SRCI_PRIORITY_HIGH); errlCommit( l_err, NVDIMM_COMP_ID ); - // TODO RTC:210689 Handle status flag - //nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOBKUP); + nvdimmSetEncryptionError(l_nvdimm); l_success = false; continue; } @@ -2609,8 +2613,7 @@ bool nvdimm_crypto_erase(TargetHandleList &i_nvdimmList) if (l_err) { errlCommit( l_err, NVDIMM_COMP_ID ); - // TODO RTC:210689 Handle status flag - //nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOBKUP); + nvdimmSetEncryptionError(l_nvdimm); l_success = false; continue; } @@ -2624,8 +2627,7 @@ bool nvdimm_crypto_erase(TargetHandleList &i_nvdimmList) if (l_err) { errlCommit( l_err, NVDIMM_COMP_ID ); - // TODO RTC:210689 Handle status flag - //nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOBKUP); + nvdimmSetEncryptionError(l_nvdimm); l_success = false; continue; } @@ -2638,8 +2640,7 @@ bool nvdimm_crypto_erase(TargetHandleList &i_nvdimmList) { TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_crypto_erase() nvdimm[%X] error reading ENCRYPTION_CONFIG_STATUS",get_huid(l_nvdimm)); errlCommit( l_err, NVDIMM_COMP_ID ); - // TODO RTC:210689 Handle status flag - //nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOBKUP); + nvdimmSetEncryptionError(l_nvdimm); l_success = false; continue; } @@ -2671,8 +2672,7 @@ bool nvdimm_crypto_erase(TargetHandleList &i_nvdimmList) HWAS::SRCI_PRIORITY_HIGH); errlCommit( l_err, NVDIMM_COMP_ID ); - // TODO RTC:210689 Handle status flag - //nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOBKUP); + nvdimmSetEncryptionError(l_nvdimm); l_success = false; continue; } diff --git a/src/usr/isteps/nvdimm/nvdimm.H b/src/usr/isteps/nvdimm/nvdimm.H index 3caa2c6e3..df1487974 100644 --- a/src/usr/isteps/nvdimm/nvdimm.H +++ b/src/usr/isteps/nvdimm/nvdimm.H @@ -561,6 +561,17 @@ bool nvdimm_keyifyRandomNumber(uint8_t* o_genData, uint8_t* i_xtraData); */ bool nvdimm_validRandomNumber(uint8_t* i_genData); + +/** + * @brief Helper function to set encryption error + * in ATTR_NVDIMM_ARMED + * + * @param[in] i_nvdimm - nvdimm target + * + */ +void nvdimmSetEncryptionError(TARGETING::Target *i_nvdimm); + + #ifndef __HOSTBOOT_RUNTIME /** diff --git a/src/usr/isteps/nvdimm/runtime/nvdimm_rt.C b/src/usr/isteps/nvdimm/runtime/nvdimm_rt.C index 75515a761..9660dfa45 100644 --- a/src/usr/isteps/nvdimm/runtime/nvdimm_rt.C +++ b/src/usr/isteps/nvdimm/runtime/nvdimm_rt.C @@ -45,103 +45,170 @@ //#define TRACUCOMP(args...) TRACFCOMP(args) #define TRACUCOMP(args...) +using namespace TARGETING; + namespace NVDIMM { +const uint8_t NV_STATUS_UNPROTECTED_SET = 0x01; +const uint8_t NV_STATUS_UNPROTECTED_CLEAR = 0xFE; +const uint8_t NV_STATUS_POSSIBLY_UNPROTECTED_SET = 0x40; +const uint8_t NV_STATUS_POSSIBLY_UNPROTECTED_CLEAR = 0xBF; + +const uint8_t NV_STATUS_OR_MASK = 0xFB; +const uint8_t NV_STATUS_AND_MASK = 0x04; + /** * @brief Notify PHYP of NVDIMM OCC protection status */ -errlHndl_t notifyNvdimmProtectionChange(TARGETING::Target* i_target, +errlHndl_t notifyNvdimmProtectionChange(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); + + errlHndl_t l_err = nullptr; + do { - TARGETING::TargetHandleList l_nvdimmTargetList = - TARGETING::getProcNVDIMMs(i_target); + // Get the type of target passed in + // It could be proc_type for OCC state + // Or dimm_type for ARM/ERROR state + ATTR_TYPE_type l_type = i_target->getAttr(); + assert((l_type == TYPE_PROC)||(l_type == TYPE_DIMM), + "notifyNvdimmProtectionChange invalid target type"); + + // Load the nvdimm list + TargetHandleList l_nvdimmTargetList; + Target* l_proc = nullptr; + if (l_type == TYPE_PROC) + { + // Get the nvdimms under this proc target + l_nvdimmTargetList = 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; + } - // Only send command if the processor has an NVDIMM under it - if (l_nvdimmTargetList.empty()) + // The proc target is the passed-in target + l_proc = i_target; + } + else { - TRACFCOMP( g_trac_nvdimm, - "notifyNvdimmProtectionChange: No NVDIMM found under processor 0x%.8X", - get_huid(i_target)); - break; + // Only a list of one but keep consistent with proc type + l_nvdimmTargetList.push_back(i_target); + + // Find the proc target from nvdimm target passed in + TargetHandleList l_procList; + getParentAffinityTargets(l_procList, + i_target, + CLASS_CHIP, + TYPE_PROC, + UTIL_FILTER_ALL); + assert(l_procList.size() == 1, "notifyNvdimmProtectionChange:" + "getParentAffinityTargets size != 1"); + l_proc = l_procList[0]; } - TARGETING::ATTR_NVDIMM_ARMED_type l_nvdimm_armed_state = - i_target->getAttr(); - // Only notify protected state if NVDIMM controllers are - // armed and no error was or is detected - if (i_state == NVDIMM::PROTECTED) + // Update the nvdimm status attributes + for (auto const l_nvdimm : l_nvdimmTargetList) { - // Exit without notifying phyp if in error state - if (l_nvdimm_armed_state.error_detected) + // Get the armed status attr and update it + ATTR_NVDIMM_ARMED_type l_armed_state = {}; + // TODO: RTC 211510 Move ATTR_NVDIMM_ARMED from proc_type to dimm type + //l_armed_state = l_nvdimm->getAttr(); + uint8_t l_tmp = l_nvdimm->getAttr(); + memcpy(&l_armed_state, &l_tmp, sizeof(l_tmp)); + + switch (i_state) { - // State can't go to protected after error is detected - break; + case NVDIMM_ARMED: + l_armed_state.armed = 1; + break; + case NVDIMM_DISARMED: + l_armed_state.armed = 0; + break; + case OCC_ACTIVE: + l_armed_state.occ_active = 1; + break; + case OCC_INACTIVE: + l_armed_state.occ_active = 0; + break; + case NVDIMM_FATAL_HW_ERROR: + l_armed_state.fatal_error_detected = 1; + break; + case NVDIMM_RISKY_HW_ERROR: + l_armed_state.risky_error_detected = 1; + break; } - // check if we need to rearm the NVDIMM(s) - else if (!l_nvdimm_armed_state.armed) + + // TODO: RTC 211510 Move ATTR_NVDIMM_ARMED from proc_type to dimm type + //l_nvdimm->setAttr(l_armed_state); + memcpy(&l_tmp, &l_armed_state, sizeof(l_tmp)); + l_nvdimm->setAttr(l_tmp); + + + // Get the nv status flag attr and update it + ATTR_NV_STATUS_FLAG_type l_nv_status = + l_nvdimm->getAttr(); + + // Clear bit 0 if protected nv state + if (l_armed_state.armed && + l_armed_state.occ_active && + !l_armed_state.fatal_error_detected) { - 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(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(l_nvdimm_armed_state); - } - - // Exit without notifying phyp of any protection change - break; - } + l_nv_status &= NV_STATUS_UNPROTECTED_CLEAR; } + + // Set bit 0 if unprotected nv state else { - // NVDIMM already armed and no error found - l_nvdimm_protection_state = hostInterfaces::HBRT_FW_NVDIMM_PROTECTED; + l_nv_status |= NV_STATUS_UNPROTECTED_SET; } - } - 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) + + // Set bit 6 if risky error + if (l_armed_state.risky_error_detected) { - l_nvdimm_armed_state.error_detected = 1; - i_target->setAttr(l_nvdimm_armed_state); + l_nv_status |= NV_STATUS_POSSIBLY_UNPROTECTED_SET; } - // still notify phyp that NVDIMM is Not Protected + + l_nvdimm->setAttr(l_nv_status); + + } // for nvdimm list + + + // Generate combined nvdimm status for the proc + // Bit 2 of NV_STATUS_FLAG is 'Device contents are persisted' + // and must be ANDed for all nvdimms + // the rest of the bits are ORed for all nvdimms + ATTR_NV_STATUS_FLAG_type l_combined_or = 0x00; + ATTR_NV_STATUS_FLAG_type l_combined_and = 0xFF; + ATTR_NV_STATUS_FLAG_type l_combined_status = 0x00; + l_nvdimmTargetList = getProcNVDIMMs(l_proc); + for (auto const l_nvdimm : l_nvdimmTargetList) + { + l_combined_or |= l_nvdimm->getAttr(); + l_combined_and &= l_nvdimm->getAttr(); } + // Bit 2 of NV_STATUS_FLAG is 'Device contents are persisted' + l_combined_status = + (l_combined_or & NV_STATUS_OR_MASK) | + (l_combined_and & NV_STATUS_AND_MASK); + + // Send combined status to phyp // Get the Proc Chip Id RT_TARG::rtChipId_t l_chipId = 0; - l_err = RT_TARG::getRtTarget(i_target, l_chipId); + l_err = RT_TARG::getRtTarget(l_proc, l_chipId); if(l_err) { TRACFCOMP( g_trac_nvdimm, @@ -156,31 +223,24 @@ errlHndl_t notifyNvdimmProtectionChange(TARGETING::Target* i_target, 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 + * @userdata2[0:31] NV_STATUS to PHYP + * @userdata2[32:63] In state change * @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), + get_huid(l_proc), TWO_UINT32_TO_UINT64( - l_nvdimm_protection_state, - armed_state_union.nvdimmArmed_int) + l_combined_status, + i_state) ); l_err->addProcedureCallout(HWAS::EPUB_PRC_PHYP_CODE, @@ -190,11 +250,10 @@ errlHndl_t notifyNvdimmProtectionChange(TARGETING::Target* i_target, } 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 ); + "notifyNvdimmProtectionChange: 0x%.8X " + "NV_STATUS to PHYP: 0x%02X", + get_huid(l_proc), + l_combined_status ); // Create the firmware_request request struct to send data hostInterfaces::hbrt_fw_msg l_req_fw_msg; @@ -208,8 +267,7 @@ errlHndl_t notifyNvdimmProtectionChange(TARGETING::Target* i_target, 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; + l_req_fw_msg.nvdimm_protection_state.i_state = l_combined_status; // Create the firmware_request response struct to receive data hostInterfaces::hbrt_fw_msg l_resp_fw_msg; @@ -243,17 +301,17 @@ errlHndl_t notifyNvdimmProtectionChange(TARGETING::Target* i_target, * @return errlHndl_t - Null if successful, otherwise a pointer to * the error log. */ -errlHndl_t nvdimmPollArmDone(TARGETING::Target* i_nvdimm, +errlHndl_t nvdimmPollArmDone(Target* i_nvdimm, uint32_t &o_poll) { - TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmPollArmDone() nvdimm[%X]", TARGETING::get_huid(i_nvdimm) ); + TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmPollArmDone() nvdimm[%X]", 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)); + get_huid(i_nvdimm)); return l_err; } @@ -267,10 +325,10 @@ errlHndl_t nvdimmPollArmDone(TARGETING::Target* i_nvdimm, * @return errlHndl_t - Null if successful, otherwise a pointer to * the error log. */ -errlHndl_t nvdimmCheckArmSuccess(TARGETING::Target *i_nvdimm) +errlHndl_t nvdimmCheckArmSuccess(Target *i_nvdimm) { TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmCheckArmSuccess() nvdimm[%X]", - TARGETING::get_huid(i_nvdimm)); + get_huid(i_nvdimm)); errlHndl_t l_err = nullptr; uint8_t l_data = 0; @@ -280,13 +338,13 @@ errlHndl_t nvdimmCheckArmSuccess(TARGETING::Target *i_nvdimm) if (l_err) { TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmCheckArmSuccess() nvdimm[%X]" - "failed to read arm status reg!",TARGETING::get_huid(i_nvdimm)); + "failed to read arm status reg!",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)); + "failed to arm!",get_huid(i_nvdimm)); /*@ *@errortype *@reasoncode NVDIMM_ARM_FAILED @@ -304,7 +362,7 @@ errlHndl_t nvdimmCheckArmSuccess(TARGETING::Target *i_nvdimm) 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)), + TWO_UINT32_TO_UINT64(ARM, get_huid(i_nvdimm)), 0x0, ERRORLOG::ErrlEntry::NO_SW_CALLOUT ); @@ -325,12 +383,12 @@ errlHndl_t nvdimmCheckArmSuccess(TARGETING::Target *i_nvdimm) } TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmCheckArmSuccess() nvdimm[%X] ret[%X]", - TARGETING::get_huid(i_nvdimm), l_data); + get_huid(i_nvdimm), l_data); return l_err; } -bool nvdimmArm(TARGETING::TargetHandleList &i_nvdimmTargetList) +bool nvdimmArm(TargetHandleList &i_nvdimmTargetList) { bool o_arm_successful = true; @@ -341,6 +399,18 @@ bool nvdimmArm(TARGETING::TargetHandleList &i_nvdimmTargetList) for (auto const l_nvdimm : i_nvdimmTargetList) { + // skip if the nvdimm is already armed + ATTR_NVDIMM_ARMED_type l_armed_state = {}; + // TODO: RTC 211510 Move ATTR_NVDIMM_ARMED from proc_type to dimm type + //l_armed_state = l_nvdimm->getAttr(); + uint8_t l_tmp = l_nvdimm->getAttr(); + memcpy(&l_armed_state, &l_tmp, sizeof(l_tmp)); + if (l_armed_state.armed) + { + TRACFCOMP(g_trac_nvdimm, "nvdimmArm() nvdimm[%X] called when already armed", get_huid(l_nvdimm)); + continue; + } + // skip if the nvdimm is in error state if (NVDIMM::nvdimmInErrorState(l_nvdimm)) { @@ -432,7 +502,7 @@ bool nvdimmArm(TARGETING::TargetHandleList &i_nvdimmTargetList) if (l_err) { TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmArm() nvdimm[%X], error disarming the nvdimm!", - TARGETING::get_huid(l_nvdimm)); + get_huid(l_nvdimm)); l_err->setSev(ERRORLOG::ERRL_SEV_PREDICTIVE); l_err->collectTrace(NVDIMM_COMP_NAME); errlCommit(l_err, NVDIMM_COMP_ID); @@ -440,6 +510,16 @@ bool nvdimmArm(TARGETING::TargetHandleList &i_nvdimmTargetList) continue; } + + // Arm successful, update armed status + l_err = NVDIMM::notifyNvdimmProtectionChange(l_nvdimm, + NVDIMM::NVDIMM_ARMED); + if (l_err) + { + l_err->setSev(ERRORLOG::ERRL_SEV_PREDICTIVE); + l_err->collectTrace(NVDIMM_COMP_NAME); + errlCommit(l_err, NVDIMM_COMP_ID); + } } TRACFCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmArm() returning %d", @@ -447,7 +527,7 @@ bool nvdimmArm(TARGETING::TargetHandleList &i_nvdimmTargetList) return o_arm_successful; } -bool nvdimmDisarm(TARGETING::TargetHandleList &i_nvdimmTargetList) +bool nvdimmDisarm(TargetHandleList &i_nvdimmTargetList) { bool o_disarm_successful = true; @@ -458,12 +538,15 @@ bool nvdimmDisarm(TARGETING::TargetHandleList &i_nvdimmTargetList) for (auto const l_nvdimm : i_nvdimmTargetList) { - // skip if the nvdimm is in error state - if (NVDIMM::nvdimmInErrorState(l_nvdimm)) + // skip if the nvdimm is already disarmed + ATTR_NVDIMM_ARMED_type l_armed_state = {}; + // TODO: RTC 211510 Move ATTR_NVDIMM_ARMED from proc_type to dimm type + //l_armed_state = l_nvdimm->getAttr(); + uint8_t l_tmp = l_nvdimm->getAttr(); + memcpy(&l_armed_state, &l_tmp, sizeof(l_tmp)); + if (!l_armed_state.armed) { - // error state means arming not successful - // RTC 210689 Handle return values - o_disarm_successful = false; + TRACFCOMP(g_trac_nvdimm, "nvdimmDisarm() nvdimm[%X] called when already disarmed", get_huid(l_nvdimm)); continue; } @@ -484,6 +567,16 @@ bool nvdimmDisarm(TARGETING::TargetHandleList &i_nvdimmTargetList) o_disarm_successful = false; continue; } + + // Disarm successful, update armed status + l_err = NVDIMM::notifyNvdimmProtectionChange(l_nvdimm, + NVDIMM::NVDIMM_DISARMED); + if (l_err) + { + l_err->setSev(ERRORLOG::ERRL_SEV_PREDICTIVE); + l_err->collectTrace(NVDIMM_COMP_NAME); + errlCommit(l_err, NVDIMM_COMP_ID); + } } TRACFCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmDisarm() returning %d", @@ -498,17 +591,39 @@ bool nvdimmDisarm(TARGETING::TargetHandleList &i_nvdimmTargetList) * * @return bool - true if nvdimm is in any error state, false otherwise */ -bool nvdimmInErrorState(TARGETING::Target *i_nvdimm) +bool nvdimmInErrorState(Target *i_nvdimm) { - TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmInErrorState() HUID[%X]",TARGETING::get_huid(i_nvdimm)); + TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimmInErrorState() HUID[%X]",get_huid(i_nvdimm)); - uint8_t l_statusFlag = i_nvdimm->getAttr(); + uint8_t l_statusFlag = i_nvdimm->getAttr(); bool l_ret = true; - if ((l_statusFlag & NSTD_ERR) == 0) + // Just checking bit 1 for now, need to investigate these + // Should be checking NVDIMM_ARMED instead + //if ((l_statusFlag & NSTD_ERR) == 0) + if ((l_statusFlag & NSTD_ERR_NOPRSV) == 0) + { l_ret = false; + } + + // Also check the encryption error status + Target* l_sys = nullptr; + targetService().getTopLevelTarget( l_sys ); + assert(l_sys, "nvdimmInErrorState: no TopLevelTarget"); + if (l_sys->getAttr()) + { + ATTR_NVDIMM_ARMED_type l_armed_state = {}; + // TODO: RTC 211510 Move ATTR_NVDIMM_ARMED from proc_type to dimm type + //l_armed_state = i_nvdimm->getAttr(); + uint8_t l_tmp = i_nvdimm->getAttr(); + memcpy(&l_armed_state, &l_tmp, sizeof(l_tmp)); + if (l_armed_state.encryption_error_detected) + { + l_ret = true; + } + } - TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmInErrorState() HUID[%X]",TARGETING::get_huid(i_nvdimm)); + TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimmInErrorState() HUID[%X]",get_huid(i_nvdimm)); return l_ret; } @@ -601,4 +716,5 @@ errlHndl_t nvdimm_getRandom(uint8_t* o_genData) return l_err; } + } // end NVDIMM namespace diff --git a/src/usr/isteps/pm/pm_common.C b/src/usr/isteps/pm/pm_common.C index ea8f16118..48e5c420a 100644 --- a/src/usr/isteps/pm/pm_common.C +++ b/src/usr/isteps/pm/pm_common.C @@ -1015,7 +1015,7 @@ namespace HBPM #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); + l_errl = NVDIMM::notifyNvdimmProtectionChange(i_target, NVDIMM::OCC_INACTIVE); if (l_errl) { TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, diff --git a/src/usr/targeting/common/xmltohb/attribute_types.xml b/src/usr/targeting/common/xmltohb/attribute_types.xml index 2ec701237..1637e2903 100644 --- a/src/usr/targeting/common/xmltohb/attribute_types.xml +++ b/src/usr/targeting/common/xmltohb/attribute_types.xml @@ -5095,12 +5095,33 @@ 1 0 - NVDIMM controller error detected - error_detected + Is OCC active + occ_active uint8_t - 6 + 1 + 0 + NVDIMM controller fatal error detected + fatal_error_detected + uint8_t + + + 1 + 0 + NVDIMM controller risky error detected + risky_error_detected + uint8_t + + + 1 + 0 + NVDIMM encryption error detected + encryption_error_detected + uint8_t + + + 3 0 Reserved for future use reserved @@ -5211,10 +5232,15 @@ NVDIMM status flag. This is used to record the status and later report to OPAL/PHYP. Possible values: - 0x08 - contents not preserved (genesis) - 0x04 - contents preserved - 0x02 - failed to preserve contents - 0x01 - unable to preserve future contents + 0x01 - SCM device unable to persist memory contents + 0x02 - SCM device failed to persist memory contents + 0x04 - SCM device contents are persisted from previous IPL + 0x08 - SCM device contents are not persisted from previous IPL + 0x10 - SCM device memory life remaining is critically low + 0x20 - SCM device will be garded off next IPL due to failure + 0x40 - SCM contents cannot persist due to current platform health status + 0x80 - SCM device unable to persist memory contents, certain conditions + NOTE: set for virtual SCM devices, does not persist across reboot diff --git a/src/usr/targeting/targetservicestart.C b/src/usr/targeting/targetservicestart.C index 943b7befc..8e0d5dcdb 100755 --- a/src/usr/targeting/targetservicestart.C +++ b/src/usr/targeting/targetservicestart.C @@ -591,11 +591,24 @@ static void initializeAttributes(TargetService& i_targetService, (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(); - // Only force rearming (error setting should persist) - l_nvdimms_armed_state.armed = 0; - l_chip->setAttr(l_nvdimms_armed_state); + TargetHandleList l_nvdimmTargetList = getProcNVDIMMs(l_chip); + for (auto const l_nvdimm : l_nvdimmTargetList) + { + ATTR_NVDIMM_ARMED_type l_armed_state = {}; + // TODO: RTC 211510 Move ATTR_NVDIMM_ARMED from proc_type to dimm type + //l_armed_state = l_nvdimm->getAttr(); + uint8_t l_tmp = l_nvdimm->getAttr(); + memcpy(&l_armed_state, &l_tmp, sizeof(l_tmp)); + + // Only force rearming (error setting should persist) + l_armed_state.armed = 0; + l_armed_state.occ_active = 0; + + // TODO: RTC 211510 Move ATTR_NVDIMM_ARMED from proc_type to dimm type + //l_nvdimm->setAttr(l_armed_state); + memcpy(&l_tmp, &l_armed_state, sizeof(l_tmp)); + l_nvdimm->setAttr(l_tmp); + } if (l_chip == l_pMasterProcChip) { diff --git a/src/usr/util/runtime/rt_cmds.C b/src/usr/util/runtime/rt_cmds.C index c015215b5..fa50b0684 100644 --- a/src/usr/util/runtime/rt_cmds.C +++ b/src/usr/util/runtime/rt_cmds.C @@ -1162,25 +1162,48 @@ void cmd_nvdimm_protection_msg( char* &o_output, uint32_t i_huid, { errlHndl_t l_err = nullptr; o_output = new char[500]; - uint8_t l_notifyType = NVDIMM::NOT_PROTECTED; + uint8_t l_notifyType = 0; TARGETING::Target* l_targ{}; l_targ = getTargetFromHUID(i_huid); if (l_targ != NULL) { - if (protection == 1) + if (protection == NVDIMM::NVDIMM_ARMED) { - l_notifyType = NVDIMM::PROTECTED; - l_err = notifyNvdimmProtectionChange(l_targ, NVDIMM::PROTECTED); + l_notifyType = NVDIMM::NVDIMM_ARMED; + l_err = notifyNvdimmProtectionChange(l_targ, NVDIMM::NVDIMM_ARMED); } - else if (protection == 2) + else if (protection == NVDIMM::NVDIMM_DISARMED) { - l_notifyType = NVDIMM::UNPROTECTED_BECAUSE_ERROR; - l_err = notifyNvdimmProtectionChange(l_targ, NVDIMM::UNPROTECTED_BECAUSE_ERROR); + l_notifyType = NVDIMM::NVDIMM_DISARMED; + l_err = notifyNvdimmProtectionChange(l_targ, NVDIMM::NVDIMM_DISARMED); + } + else if (protection == NVDIMM::OCC_ACTIVE) + { + l_notifyType = NVDIMM::OCC_ACTIVE; + l_err = notifyNvdimmProtectionChange(l_targ, NVDIMM::OCC_ACTIVE); + } + else if (protection == NVDIMM::OCC_INACTIVE) + { + l_notifyType = NVDIMM::OCC_INACTIVE; + l_err = notifyNvdimmProtectionChange(l_targ, NVDIMM::OCC_INACTIVE); + } + else if (protection == NVDIMM::NVDIMM_FATAL_HW_ERROR) + { + l_notifyType = NVDIMM::NVDIMM_FATAL_HW_ERROR; + l_err = notifyNvdimmProtectionChange(l_targ, NVDIMM::NVDIMM_FATAL_HW_ERROR); + } + else if (protection == NVDIMM::NVDIMM_RISKY_HW_ERROR) + { + l_notifyType = NVDIMM::NVDIMM_RISKY_HW_ERROR; + l_err = notifyNvdimmProtectionChange(l_targ, NVDIMM::NVDIMM_RISKY_HW_ERROR); } else { - l_err = notifyNvdimmProtectionChange(l_targ, NVDIMM::NOT_PROTECTED); + sprintf( o_output, + "cmd_nvdimm_protection_msg: HUID 0x%.8X " + "unknown protection type 0x%.2X", + i_huid, protection ); } if (l_err) { diff --git a/src/usr/util/runtime/rt_fwnotify.C b/src/usr/util/runtime/rt_fwnotify.C index 44a5a7dba..589f8d72f 100644 --- a/src/usr/util/runtime/rt_fwnotify.C +++ b/src/usr/util/runtime/rt_fwnotify.C @@ -263,12 +263,12 @@ void occActiveNotification( void * i_data ) if (*l_active) { l_err = NVDIMM::notifyNvdimmProtectionChange(l_proc, - NVDIMM::PROTECTED); + NVDIMM::OCC_ACTIVE); } else { l_err = NVDIMM::notifyNvdimmProtectionChange(l_proc, - NVDIMM::NOT_PROTECTED); + NVDIMM::OCC_INACTIVE); } // commit error if it exists @@ -479,6 +479,17 @@ void doNvDimmOperation(const hostInterfaces::nvdimm_operation_t& nvDimmOp) // Enable encryption on the NVDIMM if (nvDimmOp.opType & hostInterfaces::HBRT_FW_NVDIMM_ENABLE_ENCRYPTION) { + // Set the encryption enable attribute + Target* l_sys = nullptr; + targetService().getTopLevelTarget( l_sys ); + assert(l_sys, "doNvDimmOperation: no TopLevelTarget"); + if (!l_sys->getAttr()) + { + l_sys->setAttr(0x1); + + // TODO RTC 210692 Update HWSV with enable attribute value + } + // Make call to generate keys before enabling encryption if(!nvdimm_gen_keys()) { -- cgit v1.2.1