summaryrefslogtreecommitdiffstats
path: root/src/occ/main.c
diff options
context:
space:
mode:
authorStephan Broyles <sbroyles@us.ibm.com>2015-02-24 16:36:44 -0600
committerStephan Broyles <sbroyles@us.ibm.com>2015-04-13 13:05:36 -0500
commit8fdf501b07d6eaf715539fae9977372b12673da8 (patch)
tree89d7b4b51dec8c2e21b081a636e082d008a081de /src/occ/main.c
parentc473df288f702b1803205ac6eda4cc1781fec4f8 (diff)
downloadtalos-occ-8fdf501b07d6eaf715539fae9977372b12673da8.tar.gz
talos-occ-8fdf501b07d6eaf715539fae9977372b12673da8.zip
Adding firdata feature to OCC
Adding the fir data collection code to capture FIR information to PNOR upon a runtime checkstop. Change-Id: Ia7d6f9a234ca2c86783f7ac8f51407c15895358e RTC: 115282 Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/15970 Reviewed-by: Stephan Broyles <sbroyles@us.ibm.com> Tested-by: Stephan Broyles <sbroyles@us.ibm.com>
Diffstat (limited to 'src/occ/main.c')
-rwxr-xr-xsrc/occ/main.c307
1 files changed, 193 insertions, 114 deletions
diff --git a/src/occ/main.c b/src/occ/main.c
index 6700964..06e9702 100755
--- a/src/occ/main.c
+++ b/src/occ/main.c
@@ -5,10 +5,10 @@
/* */
/* OpenPOWER OnChipController Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2011,2014 */
-/* [+] Google Inc. */
+/* Contributors Listed Below - COPYRIGHT 2011,2015 */
/* [+] 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 */
@@ -53,6 +53,7 @@
#include <amec_freq.h>
#include <thrm_thread.h>
#include "scom.h"
+#include <fir_data_collect.h>
extern void __ssx_boot;
extern uint32_t G_occ_phantom_critical_count;
@@ -68,7 +69,6 @@ IMAGE_HEADER (G_mainAppImageHdr,__ssx_boot,MAIN_APP_ID,ID_NUM_INVALID);
SimicsStdio G_simics_stdout;
SimicsStdio G_simics_stderr;
-
// Critical /non Critical Stacks
uint8_t G_noncritical_stack[NONCRITICAL_STACK_SIZE];
uint8_t G_critical_stack[CRITICAL_STACK_SIZE];
@@ -85,8 +85,14 @@ SsxSemaphore G_ffdcSem;
// Timer for posting thermal, health monitor and FFDC semaphore
SsxTimer G_mainThrdTimer;
-// @sb022 Variable holding main thread loop count
+// Variable holding main thread loop count
uint32_t G_mainThreadLoopCounter = 0x0;
+// Global flag indicating FIR collection is required
+bool G_fir_collection_required = FALSE;
+
+extern uint8_t g_trac_inf_buffer[];
+extern uint8_t g_trac_imp_buffer[];
+extern uint8_t g_trac_err_buffer[];
void pmc_hw_error_isr(void *private, SsxIrqId irq, int priority);
@@ -337,7 +343,7 @@ void occ_irq_setup()
if(l_rc)
{
//single error for all error cases, just look at trace to see where it failed.
- /*@
+ /* @
* @moduleid OCC_IRQ_SETUP
* @reasonCode SSX_GENERIC_FAILURE
* @severity ERRL_SEV_UNRECOVERABLE
@@ -703,7 +709,7 @@ void Main_thread_routine(void *private)
TRAC_INFO("Main Thread Started ... " );
- workaround_HW258436(); //gm016
+ workaround_HW258436();
// NOTE: At present, we are not planning to use any config data from
// mainstore. OCC Role will be provided by FSP after FSP communication
@@ -711,7 +717,6 @@ void Main_thread_routine(void *private)
// dcom_initialize_roles. If in future design changes, we will make
// change to use config_data_init at that time.
// Default role initialization and determine OCC/Chip Id
- // @03a get our role
dcom_initialize_roles();
CHECKPOINT(ROLES_INITIALIZED);
@@ -721,16 +726,9 @@ void Main_thread_routine(void *private)
sensor_init_all();
CHECKPOINT(SENSORS_INITIALIZED);
- // SPIVID Initialization
- // Must be done before Pstates
- // @sb001 Removed SPIVID inits
+ // SPIVID Initialization must be done before Pstates
// All SPIVID inits are done by Hostboot, remove this section.
- //#if 0
- // o2s_initialize();
- // spivid_initialize(7);
- //#endif
- //@04a
//Initialize structures for collecting core data.
//It needs to run before RTLoop start as pore initialization needs to be
// done before task to collect core data starts.
@@ -739,10 +737,9 @@ void Main_thread_routine(void *private)
// Run slave OCC init on all OCCs. Master-only initialization will be
// done after determining actual role. By default all OCCs are slave.
- slave_occ_init(); // @th00b - Moved after proc core init
+ slave_occ_init();
CHECKPOINT(SLAVE_OCC_INITIALIZED);
-#ifndef OCC_SIMICS_RESPONDER
// Initialize watchdog timers. This needs to be right before
// start rtl to make sure timer doesn't timeout. This timer is being
// reset from the rtl task.
@@ -753,18 +750,13 @@ void Main_thread_routine(void *private)
// Initialize Real time Loop Timer Interrupt
rtl_ocb_init();
CHECKPOINT(RTL_TIMER_INITIALIZED);
-#else
- TRAC_ERR("---------------------------------");
- TRAC_ERR(" OCC Responder for Simics");
- TRAC_ERR("---------------------------------");
-#endif
// Initialize semaphores and timer for handling thermal, health monitor and
// FFDC functions.
initMainThrdSemAndTimer();
CHECKPOINT(SEMS_AND_TIMERS_INITIALIZED);
- //Initialize the Applet Manager @02a
+ //Initialize the Applet Manager
// This needs to be done before initThreadScheduler because command line
// handler thread might start using applet as soon as it starts. Command
// line handler thread is started as part of the initThreadScheduler along
@@ -778,28 +770,57 @@ void Main_thread_routine(void *private)
// through cmd handler thread in middle of the initialization.
initThreadScheduler();
-#ifdef FSPLESS_SIMICS
- // In order to avoid having to run a ton of separate commands to each
- // occ when we want to test in Simics w/o FSP, we can run with a FSPLESS
- // config, using hardcoded default data from occ_sys_config.c
- sysConfigFspLess();
-#endif
-
int l_ssxrc = SSX_OK;
- // @sb022 initWatchdogTimers called before will start running the timer but
+ // initWatchdogTimers called before will start running the timer but
// the interrupt handler will just restart the timer until we use this
// enable switch to actually start the watchdog function.
ENABLE_WDOG;
while (TRUE)
{
- // @sb022 Count each loop so the watchdog can tell the main thread is
+ // Count each loop so the watchdog can tell the main thread is
// running.
G_mainThreadLoopCounter++;
+ // Flush the loop counter and trace buffers on each loop, this makes
+ // debug easier if the cmd interface doesn't respond
+ dcache_flush_line(&G_mainThreadLoopCounter);
+ dcache_flush(g_trac_inf_buffer, TRACE_BUFFER_SIZE);
+ dcache_flush(g_trac_imp_buffer, TRACE_BUFFER_SIZE);
+ dcache_flush(g_trac_err_buffer, TRACE_BUFFER_SIZE);
+
// Wait for thermal semaphore
l_ssxrc = ssx_semaphore_pend(&G_thrmSem,SSX_WAIT_FOREVER);
+ static bool L_fir_collection_completed = FALSE;
+ // Look for FIR collection flag and status
+ if (G_fir_collection_required && !L_fir_collection_completed)
+ {
+ // If this OCC is the FIR master and PNOR access is allowed perform
+ // FIR collection
+ if (OCC_IS_FIR_MASTER() && pnor_access_allowed())
+ {
+ fir_data_collect();
+ L_fir_collection_completed = TRUE;
+ }
+
+ G_fir_collection_required = FALSE;
+ // Error reporting is skipped while FIR collection is required so we
+ // don't get reset in flight. If anyone is listening send the
+ // error alert now.
+ // If this system is using PSIHB complex, send an interrupt to Host so that
+ // Host can inform HTMGT to collect the error log
+ if (G_occ_interrupt_type == PSIHB_INTERRUPT)
+ {
+ // From OCC OpenPower Interface v1.1, OCC needs to set bits 0 and 1 of
+ // the OCB_OCCMISC register
+ ocb_occmisc_t l_occmiscreg;
+ l_occmiscreg.fields.core_ext_intr = 1;
+ l_occmiscreg.fields.reason_intr = 1;
+ out32(OCB_OCCMISC_OR, l_occmiscreg.value);
+ }
+ }
+
if ( l_ssxrc != SSX_OK )
{
TRAC_ERR("thermal Semaphore pending failure RC[0x%08X]", -l_ssxrc );
@@ -883,6 +904,7 @@ void Main_thread_routine(void *private)
int main(int argc, char **argv)
{
int l_ssxrc;
+ int l_ssxrc2;
// ----------------------------------------------------
// Initialize TLB for Linear Window access here so we
@@ -896,6 +918,7 @@ int main(int argc, char **argv)
TLBLO_WR | TLBLO_I,
NULL
);
+
if(l_ssxrc != SSX_OK)
{
//failure means we can't talk to FSP.
@@ -910,26 +933,58 @@ int main(int argc, char **argv)
TLBLO_I,
NULL
);
+
if(l_ssxrc != SSX_OK)
{
//failure means we can't talk to FSP.
SSX_PANIC(0x01000002);
}
+ // Setup the TLB for writing to the FIR parms section
+ l_ssxrc = ppc405_mmu_map(FIR_PARMS_SECTION_BASE_ADDRESS,
+ FIR_PARMS_SECTION_BASE_ADDRESS,
+ FIR_PARMS_SECTION_SIZE,
+ 0,
+ TLBLO_WR | TLBLO_I,
+ NULL);
+
+ if (l_ssxrc != SSX_OK)
+ {
+ // Panic, this section is required for FIR collection on checkstops
+ SSX_PANIC(0x01000003);
+ }
+
+ // Setup the TLB for writing to the FIR heap section
+ l_ssxrc = ppc405_mmu_map(FIR_HEAP_SECTION_BASE_ADDRESS,
+ FIR_HEAP_SECTION_BASE_ADDRESS,
+ FIR_HEAP_SECTION_SIZE,
+ 0,
+ TLBLO_WR | TLBLO_I,
+ NULL);
+
+ if (l_ssxrc != SSX_OK)
+ {
+ // Panic, this section is required for FIR collection on checkstops
+ SSX_PANIC(0x01000004);
+ }
+
CHECKPOINT_INIT();
CHECKPOINT(MAIN_STARTED);
- // Initialize stdout so we can do printf from within simics env
-#ifdef OCC_SIMICS_RESPONDER
- simics_stdout_create(&G_simics_stdout);
- simics_stderr_create(&G_simics_stderr);
- stdout = (FILE *)(&G_simics_stdout);
- stderr = (FILE *)(&G_simics_stderr);
- ssxout = (FILE *)(&G_simics_stdout);
-#endif
+ homer_rc_t l_homerrc = HOMER_SUCCESS;
+ homer_rc_t l_homerrc2 = HOMER_SUCCESS;
+
+ // Get the homer version
+ uint32_t l_homer_version = 0;
+ l_homerrc = homer_hd_map_read_unmap(HOMER_VERSION,
+ &l_homer_version,
+ &l_ssxrc);
- // Initialize SSX Stacks
- // NOTE: This also reinitializes the time base to 0
+ if ((HOMER_SUCCESS != l_homerrc) && (HOMER_SSX_UNMAP_ERR != l_homerrc))
+ {
+ // Attempt to use max version if we can't read the homer.
+ l_homer_version = HOMER_VERSION_MAX;
+ }
// Get proc_pb_frequency from HOMER host data and calculate the timebase
// frequency for the OCC. Pass the timebase frequency to ssx_initialize.
@@ -937,16 +992,19 @@ int main(int argc, char **argv)
// frequency so the passed value is 1/4 of the proc_pb_frequency from the
// HOMER, ie. if the MRW says that proc_pb_frequency is 2400 MHz, then
// pass 600000000 (600MHz)
+
// The offset from the start of the HOMER is 0x00100000, we will need to
// create a temporary mapping to this section of the HOMER with ppc405_mmu_map
// (at address 0x00000000) read the value, convert it, and then unmap.
- homer_rc_t l_homerrc = HOMER_SUCCESS;
+
+ // Don't do a version check before reading the nest freq, it's present in
+ // all HOMER versions.
uint32_t l_tb_freq_hz = 0;
- l_homerrc = homer_hd_map_read_unmap(HOMER_NEST_FREQ,
- &l_tb_freq_hz,
- &l_ssxrc);
+ l_homerrc2 = homer_hd_map_read_unmap(HOMER_NEST_FREQ,
+ &l_tb_freq_hz,
+ &l_ssxrc2);
- if ((HOMER_SUCCESS == l_homerrc) || (HOMER_SSX_UNMAP_ERR == l_homerrc))
+ if ((HOMER_SUCCESS == l_homerrc2) || (HOMER_SSX_UNMAP_ERR == l_homerrc2))
{
// Data is in Mhz upon return and needs to be converted to Hz and then
// quartered.
@@ -958,25 +1016,9 @@ int main(int argc, char **argv)
l_tb_freq_hz = 400000000;
}
-
- // Get OCC interrupt type from HOMER host data area. This will tell OCC
- // which interrupt to Host it should be using.
- uint32_t l_occ_int_type = 0;
- l_homerrc = homer_hd_map_read_unmap(HOMER_INT_TYPE,
- &l_occ_int_type,
- &l_ssxrc);
-
- if ((HOMER_SUCCESS == l_homerrc) || (HOMER_SSX_UNMAP_ERR == l_homerrc))
- {
- G_occ_interrupt_type = (uint8_t) l_occ_int_type;
- }
- else
- {
- G_occ_interrupt_type = FSP_SUPPORTED_OCC;
- }
-
CHECKPOINT(SSX_STARTING);
+ // Initialize SSX Stacks. This also reinitializes the time base to 0
ssx_initialize((SsxAddress)G_noncritical_stack,
NONCRITICAL_STACK_SIZE,
(SsxAddress)G_critical_stack,
@@ -986,67 +1028,104 @@ int main(int argc, char **argv)
CHECKPOINT(SSX_INITIALIZED);
- // TRAC_XXX needs ssx service, so they can only be called after ssx_initialize
+ // TRAC_XXX needs ssx services, traces can only be done after ssx_initialize
TRAC_init_buffers();
CHECKPOINT(TRACE_INITIALIZED);
TRAC_INFO("Inside OCC Main");
// Trace what happened before ssx initialization
- TRAC_INFO("HOMER accessed, rc=%d, nest_freq=%d, int_type=%d, ssx_rc=%d",
- l_homerrc, l_tb_freq_hz, l_occ_int_type, l_ssxrc);
+ TRAC_INFO("HOMER accessed, rc=%d, version=%d, ssx_rc=%d",
+ l_homerrc, l_homer_version, l_ssxrc);
+
+ TRAC_INFO("HOMER accessed, rc=%d, nest_freq=%d, ssx_rc=%d",
+ l_homerrc2, l_tb_freq_hz, l_ssxrc2);
+
+ // Handle any errors from the version access
+ homer_log_access_error(l_homerrc,
+ l_ssxrc,
+ l_homer_version);
+
+ // Handle any errors from the nest freq access
+ homer_log_access_error(l_homerrc2,
+ l_ssxrc2,
+ l_tb_freq_hz);
+
+ // Time to access any initialization data needed from the HOMER (besides the
+ // nest frequency which was required above to enable SSX and tracing).
+ CHECKPOINT(HOMER_ACCESS_INITS);
- // Catch and log the homer error after inits are done
- if (HOMER_SUCCESS != l_homerrc)
+ if (l_homer_version >= HOMER_VERSION_2)
{
- // We could potentially have both an internal error dealing with the
- // homer and an SSX error, for example we could find an unsupported
- // version number in the homer and then have an ssx error trying to
- // unmap the homer address space. This in catches all those cases
- if (SSX_OK != l_ssxrc)
+ // Get OCC interrupt type from HOMER host data area. This will tell OCC
+ // which interrupt to Host it should be using.
+ uint32_t l_occ_int_type = 0;
+ l_homerrc = homer_hd_map_read_unmap(HOMER_INT_TYPE,
+ &l_occ_int_type,
+ &l_ssxrc);
+
+ if ((HOMER_SUCCESS == l_homerrc) || (HOMER_SSX_UNMAP_ERR == l_homerrc))
{
- /* @
- * @errortype
- * @moduleid MAIN_MID
- * @reasoncode SSX_GENERIC_FAILURE
- * @userdata1 HOMER and SSX return codes
- * @userdata2 Timebase frequency applied
- * @userdata4 ERC_HOMER_MAIN_SSX_ERROR
- * @devdesc An SSX error ocurred mapping the HOMER host data
- * into the OCC address space. User word 1 contains
- * both the internal and SSX return codes returned
- * by the method used to access the HOMER data.
- */
- errlHndl_t l_err = createErrl(MAIN_MID, //modId
- SSX_GENERIC_FAILURE, //reasoncode
- ERC_HOMER_MAIN_SSX_ERROR, //Extended reason code
- ERRL_SEV_PREDICTIVE, //Severity
- NULL, //Trace Buf
- DEFAULT_TRACE_SIZE, //Trace Size
- (l_homerrc << 16) | (0xFFFF & (uint32_t)l_ssxrc), //userdata1
- l_tb_freq_hz); //userdata2
- commitErrl(&l_err);
+ G_occ_interrupt_type = (uint8_t) l_occ_int_type;
}
else
{
- /* @
- * @errortype
- * @moduleid MAIN_MID
- * @reasoncode INTERNAL_FAILURE
- * @userdata1 HOMER return code
- * @userdata2 Default timebase frequency applied
- * @userdata4 ERC_HOMER_MAIN_ACCESS_ERROR
- * @devdesc Error accessing initialization data
- */
- errlHndl_t l_err = createErrl(MAIN_MID, //modId
- INTERNAL_FAILURE, //reasoncode
- ERC_HOMER_MAIN_ACCESS_ERROR,//Extended reason code
- ERRL_SEV_INFORMATIONAL, //Severity
- NULL, //Trace Buf
- DEFAULT_TRACE_SIZE, //Trace Size
- l_homerrc, //userdata1
- l_tb_freq_hz); //userdata2
- commitErrl(&l_err);
+ G_occ_interrupt_type = FSP_SUPPORTED_OCC;
+ }
+
+ TRAC_INFO("HOMER accessed, rc=%d, host interrupt type=%d, ssx_rc=%d",
+ l_homerrc, l_occ_int_type, l_ssxrc);
+
+ // Handle any errors from the interrupt type access
+ homer_log_access_error(l_homerrc,
+ l_ssxrc,
+ l_occ_int_type);
+ }
+
+ if (l_homer_version >= HOMER_VERSION_3)
+ {
+ // Get the FIR Master indicator
+ uint32_t l_fir_master = FIR_OCC_NOT_FIR_MASTER;
+ l_homerrc = homer_hd_map_read_unmap(HOMER_FIR_MASTER,
+ &l_fir_master,
+ &l_ssxrc);
+
+ if (((HOMER_SUCCESS == l_homerrc) || (HOMER_SSX_UNMAP_ERR == l_homerrc))
+ &&
+ (FIR_OCC_IS_FIR_MASTER == l_fir_master))
+ {
+ OCC_SET_FIR_MASTER(FIR_OCC_IS_FIR_MASTER);
+ }
+ else
+ {
+ OCC_SET_FIR_MASTER(FIR_OCC_NOT_FIR_MASTER);
+ }
+
+ TRAC_INFO("HOMER accessed, rc=%d, FIR master=%d, ssx_rc=%d",
+ l_homerrc, l_fir_master, l_ssxrc);
+
+ // Handle any errors from the FIR master access
+ homer_log_access_error(l_homerrc,
+ l_ssxrc,
+ l_fir_master);
+
+ // If this OCC is the FIR master read in the FIR collection parms
+ if (OCC_IS_FIR_MASTER())
+ {
+ TRAC_IMP("I am the FIR master");
+
+ // Read the FIR parms buffer
+ l_homerrc = homer_hd_map_read_unmap(HOMER_FIR_PARMS,
+ &G_fir_data_parms[0],
+ &l_ssxrc);
+
+ TRAC_INFO("HOMER accessed, rc=%d, FIR parms buffer 0x%x, ssx_rc=%d",
+ l_homerrc, &G_fir_data_parms[0], l_ssxrc);
+
+ // Handle any errors from the FIR master access
+ homer_log_access_error(l_homerrc,
+ l_ssxrc,
+ (uint32_t)&G_fir_data_parms[0]);
}
}
@@ -1086,7 +1165,7 @@ int main(int argc, char **argv)
-l_rc, //userdata1
0); //userdata2
// Commit Error log
- REQUEST_RESET(l_err); // @gm006
+ REQUEST_RESET(l_err);
}
// Enter SSX Kernel
OpenPOWER on IntegriCloud