diff options
author | Missy Connell <missyc@us.ibm.com> | 2012-10-29 13:55:23 -0500 |
---|---|---|
committer | A. Patrick Williams III <iawillia@us.ibm.com> | 2012-11-09 08:51:25 -0600 |
commit | 0db3db91302876adc4490b9c3c1ff10945b38044 (patch) | |
tree | 3ec7d6bd4730420e7103bb0b6b326c01f295092d /src/kernel | |
parent | ed66b035444144109e66283e4b97087b918c6b93 (diff) | |
download | talos-hostboot-0db3db91302876adc4490b9c3c1ff10945b38044.tar.gz talos-hostboot-0db3db91302876adc4490b9c3c1ff10945b38044.zip |
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 <iawillia@us.ibm.com>
Diffstat (limited to 'src/kernel')
-rw-r--r-- | src/kernel/cpumgr.C | 54 | ||||
-rw-r--r-- | src/kernel/misc.C | 142 | ||||
-rw-r--r-- | src/kernel/syscall.C | 15 | ||||
-rw-r--r-- | src/kernel/terminate.C | 38 |
4 files changed, 181 insertions, 68 deletions
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 <errno.h> #include <kernel/deferred.H> #include <kernel/misc.H> +#include <kernel/terminate.H> +#include <kernel/hbterminatetypes.H> +#include <kernel/kernel_reasoncodes.H> 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 <kernel/barrier.H> #include <kernel/scheduler.H> #include <assert.h> +#include <kernel/terminate.H> +#include <kernel/hbterminatetypes.H> 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 <kernel/console.H> #include <builtins.h> +#include <kernel/kernel_reasoncodes.H> 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; } |