From 0db3db91302876adc4490b9c3c1ff10945b38044 Mon Sep 17 00:00:00 2001 From: Missy Connell Date: Mon, 29 Oct 2012 13:55:23 -0500 Subject: Terminate Immediate on a shutdown and assert Change-Id: I37c8956afb11c69201f4936821cff5e153327780 RTC:43793 Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/2194 Tested-by: Jenkins Server Reviewed-by: A. Patrick Williams III --- src/include/kernel/cpumgr.H | 7 ++ src/include/kernel/hbterminatetypes.H | 51 ++++++++- src/include/kernel/kernel_reasoncodes.H | 43 ++++++++ src/include/kernel/syscalls.H | 3 + src/include/kernel/terminate.H | 30 ++++-- src/include/sys/misc.h | 9 ++ src/include/usr/hbotcompid.H | 10 +- src/kernel/cpumgr.C | 54 ++++++++++ src/kernel/misc.C | 142 +++++++++++++++----------- src/kernel/syscall.C | 15 +++ src/kernel/terminate.C | 38 +++++-- src/lib/assert.C | 19 ++-- src/lib/syscall_misc.C | 5 + src/usr/initservice/baseinitsvc/initservice.C | 9 +- 14 files changed, 343 insertions(+), 92 deletions(-) create mode 100644 src/include/kernel/kernel_reasoncodes.H (limited to 'src') diff --git a/src/include/kernel/cpumgr.H b/src/include/kernel/cpumgr.H index 3d9fd2e02..f55bf0ff5 100644 --- a/src/include/kernel/cpumgr.H +++ b/src/include/kernel/cpumgr.H @@ -145,6 +145,13 @@ class CpuManager */ static void forceMemoryPeriodic(); + + /** @fn critAssert() + * Functional call to force terminate immediate on all threads + * @param[in] i_failAddr - Address from where the assert was called + */ + static void critAssert(uint64_t i_failAddr); + /** Desired value for MSR after wakeup. * * bit 0 - 64 bit mode. diff --git a/src/include/kernel/hbterminatetypes.H b/src/include/kernel/hbterminatetypes.H index 353dea06f..487704b96 100644 --- a/src/include/kernel/hbterminatetypes.H +++ b/src/include/kernel/hbterminatetypes.H @@ -27,6 +27,47 @@ #define __KERNEL_HBTERMINATETYPES_H #include +/** @struct HB_T_SRC_DataAreaw + * @brief Defines the data space recreating an SRC needed for a TI from kernel + * space + */ +struct HB_T_SRC_DataArea +{ + + union{ + struct { + uint32_t ID:8; /**< B1 or what we are using now*/ + uint32_t subsystem:8; /**< Caller of the TI */ + uint32_t reasoncode:16; /**< reasoncode */ + }; + uint32_t SRCword0; /**< Full SRC word0 */ + }; + uint32_t SRCword1; /**< Full SRC word2 */ + union{ + struct { + uint32_t bpCCIN:16; /**< BP CCIN*/ + uint32_t moduleID:8; /**< Module ID */ + uint32_t FSP:8; /**< subsystem */ + }; + uint32_t SRCword2; /**< Full SRC word1 */ + }; + + uint32_t SRCword3; /**< Full SRC word3 */ + uint32_t SRCword4; /**< Full SRC word4 */ + /* Word 5-8 - user data */ + union{ + struct { + uint32_t iType:16; /**< SRC of PLID failure*/ + uint32_t iSource:16; /**< Source of the src */ + }; + uint32_t SRCword5; /**< Full Dword5 */ + }; + uint32_t word6; /**< Full Dword6 */ + + uint32_t word7; /**< Full Dword7 */ + uint32_t word8; /**< Full Dword8 */ + +}; /** @struct TI_DataArea @@ -43,10 +84,10 @@ struct HB_TI_DataArea uint64_t reserved2:16; /**< Reserved space */ uint64_t reserved3:16; /**< Reserved space */ }; - uint64_t flag; /**< Full Dword0 */ - }; - uint64_t src[4]; - uint64_t plid; + uint64_t flag; /**< Full word - flag */ + }; + uint64_t plid; /**< Plid */ + HB_T_SRC_DataArea src; /**< SRC */ }; // Enum indicating whether a SRC or PLID is stored @@ -59,7 +100,7 @@ enum hb_terminate_type // Enum used in the flag indicating who initiated the TI enum hb_terminate_source { - TI_KERNAL_ASSERT = 0x0001, + TI_KERNEL_ASSERT = 0x0001, TI_CRIT_ASSERT = 0x0002, TI_SHUTDOWN = 0x0003, }; diff --git a/src/include/kernel/kernel_reasoncodes.H b/src/include/kernel/kernel_reasoncodes.H new file mode 100644 index 000000000..fe4748a19 --- /dev/null +++ b/src/include/kernel/kernel_reasoncodes.H @@ -0,0 +1,43 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/include/kernel/kernel_reasoncodes.H $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* COPYRIGHT International Business Machines Corp. 2012 */ +/* */ +/* p1 */ +/* */ +/* Object Code Only (OCO) source materials */ +/* Licensed Internal Code Source Materials */ +/* IBM HostBoot Licensed Internal Code */ +/* */ +/* The source code for this program is not published or otherwise */ +/* divested of its trade secrets, irrespective of what has been */ +/* deposited with the U.S. Copyright Office. */ +/* */ +/* Origin: 30 */ +/* */ +/* IBM_PROLOG_END_TAG */ +#ifndef __KERNEL_REASONCODES_H +#define __KERNEL_REASONCODES_H + + +#include + + + enum KernelModuleId + { + MOD_KERNEL_INVALID = 0x00, /**< Zero is an invalid module id */ + MOD_KERNEL_TERMINATE = 0x01, /**< terminate.C : save SRC */ + + }; + + enum KernelReasonCode + { + RC_ASSERT = KERNEL_COMP_ID | 0x01, /**< Assert */ + RC_SHUTDOWN = KERNEL_COMP_ID | 0x02, /**< Shutdown */ + }; + +#endif diff --git a/src/include/kernel/syscalls.H b/src/include/kernel/syscalls.H index 2a3ba6095..b8f252258 100644 --- a/src/include/kernel/syscalls.H +++ b/src/include/kernel/syscalls.H @@ -116,6 +116,9 @@ namespace Systemcalls /** mm_linear_map() */ MM_LINEAR_MAP, + /** critassert() */ + MISC_CRITASSERT, + SYSCALL_MAX }; diff --git a/src/include/kernel/terminate.H b/src/include/kernel/terminate.H index db93a1b0b..3cedf6a72 100644 --- a/src/include/kernel/terminate.H +++ b/src/include/kernel/terminate.H @@ -28,18 +28,30 @@ #include -/** @fn terminateAndUpdateSaveArea - * Update TI data area with src or PLID and force a TI - * @param[in] i_type : indicates if an src or plid is stored + +/** @fn terminateExecuteTI + * @brief Sequence to execute a TI attn + */ +void terminateExecuteTI(); + +/** @fn termWritePlid + * Update TI data area with a PLID. * @param[in] i_source: indicates what type of fail forced the TI - * @param[in] *i_src: SRC to be stored * @param[in] i_plid: plid to be stored * @param[out] NONE: */ -void terminateAndUpdateSaveArea(uint16_t i_type, - uint16_t i_source, - uint64_t *i_src, - uint64_t plid = 0); - +void termWritePlid(uint16_t i_source, uint64_t plid); + +/** @fn termWriteSRC + * Create an SRC and Update the TI data area with the src created + * @param[in] i_source: indicates what type of fail forced the TI + * @param[in] i_reasoncode: reasoncode for the failure(assert or shutdown) + * @param[in] i_failAddr: i_linkRegister() value (address of failure) + * @param[out] NONE: + */ +void termWriteSRC(uint16_t i_source, + uint16_t i_reasoncode, + uint64_t i_failAddr = 0); + #endif diff --git a/src/include/sys/misc.h b/src/include/sys/misc.h index 02338d1f8..c8d3ba510 100644 --- a/src/include/sys/misc.h +++ b/src/include/sys/misc.h @@ -142,6 +142,15 @@ uint64_t cpu_spr_value(CpuSprNames spr); */ int cpu_master_winkle(); +/** @fn cpu_crit_assert + * @brief Forces a Terminate Immediate after a crit-assert is issued + * @param[in] i_failAddr - value in the linkRegister of the address + * of where the fail ocured. + * + * @return none + */ +void cpu_crit_assert(uint64_t i_failAddr); + #ifdef __cplusplus } #endif diff --git a/src/include/usr/hbotcompid.H b/src/include/usr/hbotcompid.H index e5a8d36b9..5b6125185 100644 --- a/src/include/usr/hbotcompid.H +++ b/src/include/usr/hbotcompid.H @@ -257,6 +257,14 @@ const compId_t RUNTIME_COMP_ID = 0x1A00; const char RUNTIME_COMP_NAME[] = "runtime"; //@} +/** @name KERNEL + * KERNEL component + */ +//@{ +const compId_t KERNEL_COMP_ID = 0x1B00; +const char KERNEL_COMP_NAME[] = "kernel"; +//@} + /** @name HSVC * Host Services component * For the code running under PHYP @@ -264,7 +272,7 @@ const char RUNTIME_COMP_NAME[] = "runtime"; //@{ const compId_t HSVC_COMP_ID = 0x2000; const char HSVC_COMP_NAME[] = "hsvc"; -//@} + /** @name RESERVED * Reserved component ID. x3100 is the component ID diff --git a/src/kernel/cpumgr.C b/src/kernel/cpumgr.C index 162b49f41..47edb8ca2 100644 --- a/src/kernel/cpumgr.C +++ b/src/kernel/cpumgr.C @@ -39,6 +39,9 @@ #include #include #include +#include +#include +#include cpu_t** CpuManager::cv_cpus[KERNEL_MAX_SUPPORTED_NODES]; bool CpuManager::cv_shutdown_requested = false; @@ -107,6 +110,16 @@ void CpuManager::requestShutdown(uint64_t i_status) __sync_synchronize(); cv_shutdown_requested = true; + // If the shutdown was not called with a Good shutdown status + // then we know we are shutting down due to error and the + // status passed back is instead a PLID + if (i_status != SHUTDOWN_STATUS_GOOD) + { + termWritePlid(TI_SHUTDOWN, i_status); + + printk("TI initiated on all threads (shutdown)\n"); + } + class ExecuteShutdown : public DeferredWork { public: @@ -118,6 +131,8 @@ void CpuManager::requestShutdown(uint64_t i_status) if(c->master) HeapManager::stats(); #endif + + } void activeMainWork() @@ -395,3 +410,42 @@ void CpuManager::forceMemoryPeriodic() { cv_forcedMemPeriodic = true; } + + +void CpuManager::critAssert(uint64_t i_failAddr) +{ + /* create SRC amd call terminate immediate*/ + + termWriteSRC(TI_CRIT_ASSERT,RC_SHUTDOWN, i_failAddr); + + class ExecuteCritAssert : public DeferredWork + { + public: + void masterPreWork() + { + // print status to the console. + printk("TI initiated on all threads (crit_assert)\n"); + + } + + void activeMainWork() + { + // Call the function to perform the TI + terminateExecuteTI(); + } + + void nonactiveMainWork() + { + // Something wasn't synchronized correctly if we got to here. + // Should not have CPUs coming online while trying to execute + // a shutdown. + terminateExecuteTI(); + } + }; + + DeferredQueue::insert(new ExecuteCritAssert()); + + // Force executeion of the deferred queue. + DeferredQueue::execute(); + +} diff --git a/src/kernel/misc.C b/src/kernel/misc.C index beddbbb81..329bc4fbc 100644 --- a/src/kernel/misc.C +++ b/src/kernel/misc.C @@ -27,6 +27,8 @@ #include #include #include +#include +#include extern "C" void kernel_shutdown(size_t, uint64_t, uint64_t, uint64_t) NO_RETURN; @@ -42,19 +44,31 @@ namespace KernelMisc { // Update scratch SPR for shutdown status. cpu_t* c = CpuManager::getCurrentCPU(); + register uint64_t status = CpuManager::getShutdownStatus(); + if (c->master) { - register uint64_t status = CpuManager::getShutdownStatus(); - printk("Shutdown Requested. Status = 0x%lx\n", status); + // If good shutdown requested print out status + if(status == SHUTDOWN_STATUS_GOOD) + { + printk("Shutdown Requested. Status = 0x%lx\n", status); + } + // Shtudown was called due to error.. print out plid of the + // errorlog that caused the failure + else + { + printk("Shutdown Requested. PLID = %ld (due to failure)\n", + status); + } register uint64_t scratch_address = 0; // Values from PervSpec switch(CpuID::getCpuType()) { - case CORE_POWER8_MURANO: - case CORE_POWER8_VENICE: - case CORE_UNKNOWN: - scratch_address = 0x40; - break; + case CORE_POWER8_MURANO: + case CORE_POWER8_VENICE: + case CORE_UNKNOWN: + scratch_address = 0x40; + break; } asm volatile("mtspr 276, %0\n" @@ -63,69 +77,83 @@ namespace KernelMisc :: "r" (scratch_address), "r" (status)); } - // dump whatever is left in g_tracBinary - MAGIC_INSTRUCTION(MAGIC_CONTINUOUS_TRACE); - - // See magic_instruction_callback() in - // src/build/debug/simics-debug-framework.py - // for exactly how this is handled. - MAGIC_INSTRUCTION(MAGIC_SHUTDOWN); - - // Check for a valid payload address. - if ((0 == g_payload_base) && (0 == g_payload_entry)) + // If the Shutdown was called with a status of GOOD then + // perform a regular shutdown, otherwise assume we have an + // error with a status value of the plid and perform a TI. + if(status == SHUTDOWN_STATUS_GOOD) { - // We really don't know what we're suppose to do now, so just - // sleep all the processors. - if (c->master) - { - printk("No payload... nap'ing all threads.\n"); - } + // dump whatever is left in g_tracBinary + MAGIC_INSTRUCTION(MAGIC_CONTINUOUS_TRACE); - // Clear LPCR values that wakes up from nap. LPCR[49, 50, 51] - setLPCR(getLPCR() & (~0x0000000000007000)); - - while(1) - { - nap(); - } - } - else - { - static Barrier* l_barrier = new Barrier(CpuManager::getCpuCount()); - static uint64_t l_lowestPIR = 0xffffffffffffffffull; + // See magic_instruction_callback() in + // src/build/debug/simics-debug-framework.py + // for exactly how this is handled. + MAGIC_INSTRUCTION(MAGIC_SHUTDOWN); - if (c->master) + // Check for a valid payload address. + if ((0 == g_payload_base) && (0 == g_payload_entry)) { - printk("Preparing to enter payload...%lx:%lx\n", - g_payload_base, g_payload_entry); - } + // We really don't know what we're suppose to do now, so just + // sleep all the processors. - // Need to identify the thread with the lowest PIR because it needs - // to be the last one to jump to PHYP. - uint64_t l_pir = getPIR(); - do - { - uint64_t currentPIR = l_lowestPIR; - if (l_pir > currentPIR) + if (c->master) { - break; + printk("No payload... nap'ing all threads.\n"); } - if (__sync_bool_compare_and_swap(&l_lowestPIR, - currentPIR, l_pir)) + // Clear LPCR values that wakes up from nap. LPCR[49, 50, 51] + setLPCR(getLPCR() & (~0x0000000000007000)); + + while(1) { - break; + nap(); } + } + else + { + static Barrier* l_barrier = new Barrier(CpuManager::getCpuCount()); + static uint64_t l_lowestPIR = 0xffffffffffffffffull; - } while(1); - - l_barrier->wait(); + if (c->master) + { + printk("Preparing to enter payload...%lx:%lx\n", + g_payload_base, g_payload_entry); + } - kernel_shutdown(CpuManager::getCpuCount(), - g_payload_base, - g_payload_entry, - l_lowestPIR); + // Need to identify the thread with the lowest PIR because it needs + // to be the last one to jump to PHYP. + uint64_t l_pir = getPIR(); + do + { + uint64_t currentPIR = l_lowestPIR; + if (l_pir > currentPIR) + { + break; + } + + if (__sync_bool_compare_and_swap(&l_lowestPIR, + currentPIR, l_pir)) + { + break; + } + + } while(1); + + l_barrier->wait(); + + kernel_shutdown(CpuManager::getCpuCount(), + g_payload_base, + g_payload_entry, + l_lowestPIR); + } + } + else + { + // Got a nonzero status value indicating we had a shutdown request + // with a PLID and there force need to do TI. The plid info was + // written to the data area earlier in CpuManager::requestShutdown + terminateExecuteTI(); } } diff --git a/src/kernel/syscall.C b/src/kernel/syscall.C index 23239a8a3..6535e7c19 100644 --- a/src/kernel/syscall.C +++ b/src/kernel/syscall.C @@ -95,6 +95,7 @@ namespace Systemcalls void MmVirtToPhys(task_t *t); void MmExtend(task_t *t); void MmLinearMap(task_t *t); + void CritAssert(task_t *t); syscall syscalls[] = @@ -136,6 +137,8 @@ namespace Systemcalls &MmVirtToPhys, // MM_VIRT_TO_PHYS &MmExtend, // MM_EXTEND &MmLinearMap, // MM_LINEAR_MAP + &CritAssert, // MISC_CRITASSERT + }; }; @@ -822,5 +825,17 @@ namespace Systemcalls TASK_SETRTN(t, VmmManager::mmLinearMap(paddr,size)); } + /** + * Call Crit assert to perform the terminate Immediate + * @param[in] t: the task calling the critical assert + */ + void CritAssert(task_t* t) + { + uint64_t i_failAddr = (uint64_t)(TASK_GETARG0(t)); + + CpuManager::critAssert(i_failAddr); + } + + }; diff --git a/src/kernel/terminate.C b/src/kernel/terminate.C index b5834a7b3..10daec717 100644 --- a/src/kernel/terminate.C +++ b/src/kernel/terminate.C @@ -28,6 +28,7 @@ #include #include +#include extern "C" void p8_force_attn() NO_RETURN; @@ -38,19 +39,34 @@ HB_TI_DataArea kernel_TIDataArea; /* Instance of the HB desriptor struct */ HB_Descriptor kernel_hbDescriptor = {&kernel_TIDataArea}; -void terminateAndUpdateSaveArea(uint16_t i_type, uint16_t i_source, uint64_t *i_src, uint64_t - plid) + + +void terminateExecuteTI() { + // Call the function that actually executes the TI code. + p8_force_attn(); +} -printk("Inside terminateandupdateSaveArea!!!!!!!!!!!!!!! \n"); - kernel_TIDataArea.type = i_type; - kernel_TIDataArea.source = i_source; - memcpy(i_src, kernel_TIDataArea.src, sizeof (kernel_TIDataArea.src)); - kernel_TIDataArea.plid = plid; - +void termWritePlid(uint16_t i_source, uint64_t plid) +{ + kernel_TIDataArea.type = TI_WITH_PLID; + kernel_TIDataArea.source = i_source; + kernel_TIDataArea.plid = plid; +} + +void termWriteSRC(uint16_t i_source, uint16_t i_reasoncode,uint64_t i_failAddr) +{ + // Update the TI structure with the type of TI and who called. + kernel_TIDataArea.type = TI_WITH_SRC; + kernel_TIDataArea.source = i_source; -printk("Calling p8_force_attn!!! dying.... \n"); - // After the data is set up .. call the function that actually executes the TI. - p8_force_attn(); + // Update TID data area with the SRC info we have avail + kernel_TIDataArea.src.ID = 0xBC; + kernel_TIDataArea.src.subsystem = 0x11; + kernel_TIDataArea.src.reasoncode = i_reasoncode; + kernel_TIDataArea.src.moduleID = MOD_KERNEL_TERMINATE; + kernel_TIDataArea.src.iType = TI_WITH_SRC; + // Update User Data with address of fail location + kernel_TIDataArea.src.word6 = i_failAddr; } diff --git a/src/lib/assert.C b/src/lib/assert.C index dbfd8ed6a..ebf59fb3f 100644 --- a/src/lib/assert.C +++ b/src/lib/assert.C @@ -32,6 +32,8 @@ #include #include +#include +#include /** Hook location for trace module to set up when loaded. */ namespace TRACE { void (*traceCallback)(void*, size_t) = NULL; }; @@ -58,18 +60,23 @@ extern "C" void __assert(AssertBehavior i_assertb, int i_line) break; case ASSERT_CRITICAL: // Critical task, trace not available. - printk("Assertion failed @%p on line %d.\n", + printk("Assertion failed @%p on line %d.(Crit_Assert)\n", linkRegister(), i_line); - task_crash(); + + // Need to call the external CritAssert system call + cpu_crit_assert(reinterpret_cast(linkRegister())); break; case ASSERT_KERNEL: // Kernel assert called. - printk("Assertion failed @%p on line %d.\n", + printk("Assertion failed @%p on line %d. (kassert)\n", linkRegister(), i_line); - // Create and src - // Call function to save SRC and perform a TI - //terminateAndUpdateSaveArea(TI_WITH_SRC, TI_KERNAL_ASSERT, NULL); + // Call function to create SRC and update TI Data area + termWriteSRC(TI_KERNEL_ASSERT, RC_ASSERT, + reinterpret_cast(linkRegister())); + + // Call to force TI + terminateExecuteTI(); break; } diff --git a/src/lib/syscall_misc.C b/src/lib/syscall_misc.C index 6d6755a5c..b62a10662 100644 --- a/src/lib/syscall_misc.C +++ b/src/lib/syscall_misc.C @@ -90,3 +90,8 @@ int cpu_master_winkle() return rc; } + +void cpu_crit_assert(uint64_t i_failAddr) +{ + _syscall1(MISC_CRITASSERT, reinterpret_cast(i_failAddr)); +} diff --git a/src/usr/initservice/baseinitsvc/initservice.C b/src/usr/initservice/baseinitsvc/initservice.C index 7f7cba895..e7a260688 100644 --- a/src/usr/initservice/baseinitsvc/initservice.C +++ b/src/usr/initservice/baseinitsvc/initservice.C @@ -547,10 +547,12 @@ void InitService::init( void *io_ptr ) TRACFCOMP( g_trac_initsvc, "InitService: Committing errorlog %p", l_errl ); - errlCommit( l_errl, INITSVC_COMP_ID ); - // post bad shutdown status - l_shutdownStatus = SHUTDOWN_STATUS_INITSVC_FAILED; + // Set the shutdown status to be the plid to force a TI + l_shutdownStatus = l_errl->plid(); + + errlCommit( l_errl, INITSVC_COMP_ID ); + } // ===================================================================== @@ -671,6 +673,7 @@ void InitService::doShutdown(uint64_t i_status, } l_rb_iter++; } + shutdown(i_status, i_payload_base, i_payload_entry); } -- cgit v1.2.1