summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rwxr-xr-xsrc/build/tools/verify-commit2
-rw-r--r--src/include/sys/mmio.h11
-rw-r--r--src/include/usr/ibscom/ibscomreasoncodes.H7
-rw-r--r--src/kernel/exception.C92
-rw-r--r--src/usr/errl/errludlogregister.C2
-rw-r--r--src/usr/hwpf/hwp/dmi_training/dmi_training.C136
-rw-r--r--src/usr/ibscom/ibscom.C412
-rw-r--r--src/usr/ibscom/ibscom.H2
-rw-r--r--src/usr/ibscom/test/ibscomtest.H187
-rw-r--r--src/usr/targeting/common/xmltohb/attribute_types_hb.xml18
-rw-r--r--src/usr/targeting/common/xmltohb/target_types_hb.xml7
11 files changed, 727 insertions, 149 deletions
diff --git a/src/build/tools/verify-commit b/src/build/tools/verify-commit
index 627f93c95..4029c0441 100755
--- a/src/build/tools/verify-commit
+++ b/src/build/tools/verify-commit
@@ -125,6 +125,8 @@ sub verifyFileLine
{
# Allow trace statements to slide.
if (($line =~ m/TRAC[DSF]/) ||
+ ($line =~m/TS_FAIL/) ||
+ ($line =~m/printk/) ||
($line =~ m/FAPI_(INF|IMP|ERR|DBG|SCAN)/))
{
}
diff --git a/src/include/sys/mmio.h b/src/include/sys/mmio.h
index 76c9c7866..273965a88 100644
--- a/src/include/sys/mmio.h
+++ b/src/include/sys/mmio.h
@@ -144,6 +144,17 @@ void mmio_scratch_write(uint64_t which, uint64_t value);
*/
mutex_t * mmio_xscom_mutex();
+/** Constant used by kernel to signal to IBSCOM device driver
+ * that a UE was triggered during the IBSCOM Read operation
+ * Value is "SCOMFAIL" in ASCII.
+ */
+static const uint64_t MMIO_IBSCOM_UE_DETECTED = 0x53434F4D4641494C;
+
+/** Constants used to define IBSCOM MMIO address range
+*/
+static const uint64_t MMIO_IBSCOM_START = 0x0003E00000000000;
+static const uint64_t MMIO_IBSCOM_END = 0x0003F02000000000;
+
#ifdef __cplusplus
}
#endif
diff --git a/src/include/usr/ibscom/ibscomreasoncodes.H b/src/include/usr/ibscom/ibscomreasoncodes.H
index fde2f8f7a..011660859 100644
--- a/src/include/usr/ibscom/ibscomreasoncodes.H
+++ b/src/include/usr/ibscom/ibscomreasoncodes.H
@@ -5,7 +5,7 @@
/* */
/* IBM CONFIDENTIAL */
/* */
-/* COPYRIGHT International Business Machines Corp. 2012 */
+/* COPYRIGHT International Business Machines Corp. 2012,2013 */
/* */
/* p1 */
/* */
@@ -33,6 +33,7 @@ namespace IBSCOM
IBSCOM_PERFORM_OP = 0x01,
IBSCOM_SANITY_CHECK = 0x02,
IBSCOM_GET_TARG_VIRT_ADDR = 0x03,
+ IBSCOM_DO_IBSCOM = 0x04,
};
enum ibscomReasonCode
@@ -40,6 +41,10 @@ namespace IBSCOM
IBSCOM_INVALID_DATA_BUFFER = IBSCOM_COMP_ID | 0x01,
IBSCOM_INVALID_OP_TYPE = IBSCOM_COMP_ID | 0x02,
IBSCOM_INVALID_CONFIG = IBSCOM_COMP_ID | 0x03,
+ IBSCOM_SUE_OCCURRED = IBSCOM_COMP_ID | 0x04,
+ IBSCOM_SUE_IN_ERR_PATH = IBSCOM_COMP_ID | 0x05,
+ IBSCOM_BUS_FAILURE = IBSCOM_COMP_ID | 0x06,
+ IBSCOM_INVALID_ADDRESS = IBSCOM_COMP_ID | 0x07,
};
};
diff --git a/src/kernel/exception.C b/src/kernel/exception.C
index c82bfec98..ba2d803b5 100644
--- a/src/kernel/exception.C
+++ b/src/kernel/exception.C
@@ -233,16 +233,104 @@ void kernel_execute_softpatch()
}
}
+const uint64_t EXCEPTION_MSR_PR_BIT_MASK = 0x0000000000004000;
+const uint64_t EXCEPTION_SRR1_LOADSTORE_ERR = 0x0000000000200000;
+const uint64_t EXCEPTION_DSISR_LDX_UE_INTERRUPT = 0x0000000000008000;
+const uint32_t EXCEPTION_LDX_INSTR_MASK = 0xFC0007FE;
+const uint32_t EXCEPTION_LDX_INSTR = 0x7C00002A;
+const uint32_t EXCEPTION_RA_MASK = 0x001F0000;
+const uint32_t EXCEPTION_RB_MASK = 0x0000F800;
+const uint32_t EXCEPTION_RT_MASK = 0x03E00000;
+
extern "C"
void kernel_execute_machine_check()
{
task_t* t = TaskManager::getCurrentTask();
- printk("Machine check in %d on %ld:\n"
+
+ //PR (bit 49) = 0 indicates hypervisor mode
+ // Which indicates kernel mode in Hostboot env.
+ if(!(getSRR1() & EXCEPTION_MSR_PR_BIT_MASK))
+ {
+ //Not much we can do to recover in Kernel, just assert
+ printk("Kernel Space Machine check in %d on %ld:\n"
+ "\tSRR0 = %lx, SRR1 = %lx\n"
+ "\tDSISR = %lx, DAR = %lx\n",
+ t->tid, getPIR(),
+ getSRR0(), getSRR1(), getDSISR(), getDAR());
+ kassert(false);
+ }
+
+ //User Space MC
+ printk("User Space Machine check in %d on %ld:\n"
"\tSRR0 = %lx, SRR1 = %lx\n"
"\tDSISR = %lx, DAR = %lx\n",
t->tid, getPIR(),
getSRR0(), getSRR1(), getDSISR(), getDAR());
- kassert(false);
+
+
+ //Determine if this Machine Check was triggered by a SUE on
+ //CI (Cache Inhibited) Load.
+ if(!((getSRR1() & EXCEPTION_SRR1_LOADSTORE_ERR) &&
+ (getDSISR() & EXCEPTION_DSISR_LDX_UE_INTERRUPT)))
+ {
+ //SUE not caused by CI Load, unhandled exception.
+ TaskManager::endTask(t, NULL, TASK_STATUS_CRASHED);
+ }
+
+ //Get instruction that caused the SUE
+ uint64_t phys_addr = VmmManager::findKernelAddress(
+ reinterpret_cast<uint64_t>(t->context.nip));
+
+ sync();
+ uint32_t* instruction = reinterpret_cast<uint32_t*>(phys_addr);
+
+ if(!((*instruction & EXCEPTION_LDX_INSTR_MASK) ==
+ EXCEPTION_LDX_INSTR))
+ {
+ //Not an LDX instruction, unhandled exception
+ printk("kernel_execute_machine_check: Instruction 0x%.8x not an LDX instruction. Ending task\n", *instruction);
+ TaskManager::endTask(t, NULL, TASK_STATUS_CRASHED);
+
+ }
+
+ //Compute the accessed address
+ uint32_t rA = (*instruction & EXCEPTION_RA_MASK) >> 16;
+ uint32_t rB = (*instruction & EXCEPTION_RB_MASK) >> 11;
+
+ uint64_t vaddr = 0;
+ if(rA != 0)
+ {
+ vaddr = t->context.gprs[rA] +
+ t->context.gprs[rB];
+ }
+ else
+ {
+ vaddr = t->context.gprs[rB];
+ }
+
+ uint64_t phys = VmmManager::findPhysicalAddress(vaddr);
+
+ //Check if address is in IBSCOM MMIO Range.
+ if( (phys >= MMIO_IBSCOM_START) &&
+ (phys <= MMIO_IBSCOM_END) )
+ {
+ //Read occured during IBSCOM read. Indicate error to caller
+ //by setting known pattern (ascii SCOMFAIL) in rT
+ uint32_t rT = (*instruction & EXCEPTION_RT_MASK) >> 21;
+
+ //set rT = MMIO_IBSCOM_UE_DETECTED
+ t->context.gprs[rT] = MMIO_IBSCOM_UE_DETECTED;
+ //Advance to next instruction
+ uint32_t* nextInst = reinterpret_cast<uint32_t*>(t->context.nip);
+ nextInst++;
+ t->context.nip = reinterpret_cast<void*>(nextInst);
+ }
+ else
+ {
+ printk("kernel_execute_machine_check: Unrecognized memory address(%lx) - ending Task\n",
+ phys);
+ TaskManager::endTask(t, NULL, TASK_STATUS_CRASHED);
+ }
}
extern "C"
diff --git a/src/usr/errl/errludlogregister.C b/src/usr/errl/errludlogregister.C
index 96b17c614..e68c521a6 100644
--- a/src/usr/errl/errludlogregister.C
+++ b/src/usr/errl/errludlogregister.C
@@ -126,6 +126,7 @@ void ErrlUserDetailsLogRegister::readRegister(
case DeviceFW::SPD: // userif.H
case DeviceFW::XSCOM: // driverif.H
case DeviceFW::FSISCOM: // driverif.H
+ case DeviceFW::IBSCOM: // driverif.H
{
numAddressArgs = 1;
break;
@@ -207,6 +208,7 @@ void ErrlUserDetailsLogRegister::copyRegisterData(
case DeviceFW::SPD: // userif.H
case DeviceFW::XSCOM: // driverif.H
case DeviceFW::FSISCOM: // driverif.H
+ case DeviceFW::IBSCOM: // driverif.H
{
numAddressArgs = 1;
break;
diff --git a/src/usr/hwpf/hwp/dmi_training/dmi_training.C b/src/usr/hwpf/hwp/dmi_training/dmi_training.C
index c18461029..2b419dc12 100644
--- a/src/usr/hwpf/hwp/dmi_training/dmi_training.C
+++ b/src/usr/hwpf/hwp/dmi_training/dmi_training.C
@@ -1026,69 +1026,111 @@ void* call_host_attnlisten_cen( void *io_pArgs )
void* call_cen_set_inband_addr( void *io_pArgs )
{
IStepError l_StepError;
+ errlHndl_t l_err = NULL;;
TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
- "call_cen_set_inband_addr entry" );
+ "call_cen_set_inband_addr entry" );
- // get the mcs chiplets
- TARGETING::TargetHandleList l_mcsTargetList;
- getAllChiplets(l_mcsTargetList, TYPE_MCS);
+ do{
+ // get the mcs chiplets
+ TARGETING::TargetHandleList l_mcsTargetList;
+ getAllChiplets(l_mcsTargetList, TYPE_MCS);
- for (TargetHandleList::const_iterator
- l_mcs_iter = l_mcsTargetList.begin();
- l_mcs_iter != l_mcsTargetList.end();
- ++l_mcs_iter)
- {
- TARGETING::Target* l_pTarget = *l_mcs_iter;
- const fapi::Target l_fapi_target( TARGET_TYPE_MCS_CHIPLET,
- (const_cast<TARGETING::Target*>(l_pTarget)));
+ for (TargetHandleList::const_iterator
+ l_mcs_iter = l_mcsTargetList.begin();
+ l_mcs_iter != l_mcsTargetList.end();
+ ++l_mcs_iter)
+ {
+ TARGETING::Target* l_pTarget = *l_mcs_iter;
+ const fapi::Target
+ l_fapi_target( TARGET_TYPE_MCS_CHIPLET,
+ (const_cast<TARGETING::Target*>(l_pTarget)));
- TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
- "Running cen_set_inband_addr HWP on "
- "target HUID %.8X", TARGETING::get_huid(l_pTarget));
+ TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
+ "Running cen_set_inband_addr HWP on "
+ "target HUID %.8X", TARGETING::get_huid(l_pTarget));
- errlHndl_t l_err = NULL;
- FAPI_INVOKE_HWP(l_err, proc_cen_set_inband_addr, l_fapi_target);
- if ( l_err )
- {
- TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
- "ERROR 0x%.8X : proc_cen_set_inband_addr HWP", l_err->reasonCode());
+ FAPI_INVOKE_HWP(l_err, proc_cen_set_inband_addr, l_fapi_target);
+ if ( l_err )
+ {
+ TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
+ "ERROR 0x%.8X : proc_cen_set_inband_addr HWP",
+ l_err->reasonCode());
- // capture the target data in the elog
- ErrlUserDetailsTarget(l_pTarget).addToLog( l_err );
+ // capture the target data in the elog
+ ErrlUserDetailsTarget(l_pTarget).addToLog( l_err );
- /*@
- * @errortype
- * @reasoncode ISTEP_DMI_TRAINING_FAILED
- * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE
- * @moduleid ISTEP_PROC_CEN_SET_INBAND_ADDR
- * @userdata1 bytes 0-1: plid identifying first error
- * bytes 2-3: reason code of first error
- * @userdata2 bytes 0-1: total number of elogs included
- * bytes 2-3: N/A
- * @devdesc call to proc_cen_set_inband_addr has failed
- *
- */
- l_StepError.addErrorDetails(ISTEP_DMI_TRAINING_FAILED,
- ISTEP_PROC_CEN_SET_INBAND_ADDR,
- l_err);
+ /*@
+ * @errortype
+ * @reasoncode ISTEP_DMI_TRAINING_FAILED
+ * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE
+ * @moduleid ISTEP_PROC_CEN_SET_INBAND_ADDR
+ * @userdata1 bytes 0-1: plid identifying first error
+ * bytes 2-3: reason code of first error
+ * @userdata2 bytes 0-1: total number of elogs included
+ * bytes 2-3: N/A
+ * @devdesc call to proc_cen_set_inband_addr has failed
+ *
+ */
+ l_StepError.addErrorDetails(ISTEP_DMI_TRAINING_FAILED,
+ ISTEP_PROC_CEN_SET_INBAND_ADDR,
+ l_err);
- errlCommit( l_err, HWPF_COMP_ID );
+ errlCommit( l_err, HWPF_COMP_ID );
- break; // break out of mcs loop
- }
- else
+ break; // break out of mcs loop
+ }
+ else
+ {
+ TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
+ "SUCCESS : proc_cen_set_inband_addr HWP");
+ }
+ } // end for mcs
+
+ l_err = l_StepError.getErrorHandle();
+ if(l_err)
{
- TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
- "SUCCESS : proc_cen_set_inband_addr HWP");
+ break;
}
- } // end for mcs
+/* TODO enable with RTC: 68733
+ //Now enable Inband SCOM for all membuf chips.
+ TARGETING::TargetHandleList membufChips;
+ getAllChips(membufChips, TYPE_MEMBUF, true);
+
+ for(uint32_t i=0; i<membufChips.size(); i++)
+ {
+ // If the membuf chip supports IBSCOM..
+ if (membufChips[i]->getAttr<ATTR_PRIMARY_CAPABILITIES>()
+ .supportsInbandScom)
+ {
+ ScomSwitches l_switches =
+ membufChips[i]->getAttr<ATTR_SCOM_SWITCHES>();
+
+ // If Inband Scom is not already enabled.
+ if ((l_switches.useInbandScom != 1) ||
+ (l_switches.useFsiScom != 0))
+ {
+ l_switches.useFsiScom = 0;
+ l_switches.useInbandScom = 1;
+
+ // Turn off FSI scom and turn on Inband Scom.
+ membufChips[i]->setAttr<ATTR_SCOM_SWITCHES>(l_switches);
+
+ TRACDCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
+ "Enable IBSCOM on target HUID %.8X",
+ TARGETING::get_huid(membufChips[i]));
+
+ }
+ }
+ }
+*/
+ }while(0);
TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
- "call_cen_set_inband_addr exit" );
+ "call_cen_set_inband_addr exit" );
- return l_StepError.getErrorHandle();
+ return l_err;
}
//
diff --git a/src/usr/ibscom/ibscom.C b/src/usr/ibscom/ibscom.C
index f379289ca..a6d17a2a6 100644
--- a/src/usr/ibscom/ibscom.C
+++ b/src/usr/ibscom/ibscom.C
@@ -33,12 +33,17 @@
#include <trace/interface.H>
#include <errl/errlentry.H>
#include <errl/errlmanager.H>
+#include <errl/errludlogregister.H>
#include <targeting/common/targetservice.H>
#include <ibscom/ibscomreasoncodes.H>
#include "ibscom.H"
#include <assert.h>
#include <limits.h>
+// Easy macro replace for unit testing
+//#define TRACUCOMP(args...) TRACFCOMP(args)
+#define TRACUCOMP(args...)
+
// Trace definition
trace_desc_t* g_trac_ibscom = NULL;
TRAC_INIT(&g_trac_ibscom, "IBSCOM", KILOBYTE);
@@ -49,16 +54,12 @@ using namespace TARGETING;
namespace IBSCOM
{
-
// Register XSCcom access functions to DD framework
DEVICE_REGISTER_ROUTE(DeviceFW::WILDCARD,
DeviceFW::IBSCOM,
TYPE_MEMBUF,
ibscomPerformOp);
-
-
-
/**
* @brief Internal routine that verifies the validity of input parameters
* for an inband scom access.
@@ -84,6 +85,30 @@ errlHndl_t ibscomOpSanityCheck(const DeviceFW::OperationType i_opType,
do
{
+ // Verify address is somewhat valid (not over 32-bits long)
+ if(0 != (i_addr & 0xFFFFFFFF00000000))
+ {
+ TRACFCOMP(g_trac_ibscom, ERR_MRK"ibscomOpSanityCheck: Impossible address. i_addr=0x%.16X",
+ i_buflen);
+ /*@
+ * @errortype
+ * @moduleid IBSCOM_SANITY_CHECK
+ * @reasoncode IBSCOM_INVALID_ADDRESS
+ * @userdata1 Inband Scom address
+ * @userdata2 <none>
+ * @devdesc The provided address is over 32 bits long
+ * which makes it invalid.
+ */
+ l_err = new ErrlEntry(ERRL_SEV_UNRECOVERABLE,
+ IBSCOM_SANITY_CHECK,
+ IBSCOM_INVALID_ADDRESS,
+ i_addr,
+ 0);
+ l_err->addProcedureCallout(HWAS::EPUB_PRC_HB_CODE,
+ HWAS::SRCI_PRIORITY_HIGH);
+ break;
+ }
+
// Verify data buffer
if ( (i_buflen < IBSCOM_BUFFER_SIZE) ||
(i_buffer == NULL) )
@@ -105,6 +130,8 @@ errlHndl_t ibscomOpSanityCheck(const DeviceFW::OperationType i_opType,
IBSCOM_INVALID_DATA_BUFFER,
i_buflen,
i_addr);
+ l_err->addProcedureCallout(HWAS::EPUB_PRC_HB_CODE,
+ HWAS::SRCI_PRIORITY_HIGH);
break;
}
@@ -128,6 +155,8 @@ errlHndl_t ibscomOpSanityCheck(const DeviceFW::OperationType i_opType,
IBSCOM_INVALID_OP_TYPE,
i_opType,
i_addr);
+ l_err->addProcedureCallout(HWAS::EPUB_PRC_HB_CODE,
+ HWAS::SRCI_PRIORITY_HIGH);
break;
}
@@ -214,6 +243,8 @@ errlHndl_t getTargetVirtualAddress(Target* i_target,
get_huid(i_target),
0),
0);
+ l_err->addProcedureCallout(HWAS::EPUB_PRC_HB_CODE,
+ HWAS::SRCI_PRIORITY_HIGH);
break;
}
parentMCS = *(mcs_list.begin());
@@ -221,7 +252,7 @@ errlHndl_t getTargetVirtualAddress(Target* i_target,
l_IBScomBaseAddr =
parentMCS->getAttr<ATTR_IBSCOM_MCS_BASE_ADDR>();
- TRACFCOMP(g_trac_ibscom, INFO_MRK
+ TRACUCOMP(g_trac_ibscom, INFO_MRK
"getTargetVirtualAddress: From Attribute query l_IBScomBaseAddr=0x%llX, i_target=0x%.8x",
l_IBScomBaseAddr,
i_target->getAttr<ATTR_HUID>());
@@ -235,6 +266,20 @@ errlHndl_t getTargetVirtualAddress(Target* i_target,
THIRTYTWO_GB));
// Save the virtual address attribute.
+
+ // Leaving the comments as a discussion point...
+ // This issue is tracked under RTC: 35315
+ // Technically there is a race condition here. The mutex is
+ // a per-hardware thread mutex, not a mutex for the whole XSCOM
+ // logic. So there is possibility that this same thread is running
+ // on another thread at the exact same time. We can use atomic
+ // update instructions here.
+ // Comment for Nick: This is a good candidate for having a way
+ // to return a reference to the attribute instead of requiring
+ // to call setAttr. We currently have no way to SMP-safely update
+ // this attribute, where as if we had a reference to it we could use
+ // the atomic update functions (_sync_bool_compare_and_swap in
+ // this case.
i_target->setAttr<ATTR_IBSCOM_VIRTUAL_ADDR>
(reinterpret_cast<uint64_t>(o_virtAddr));
}
@@ -252,25 +297,26 @@ errlHndl_t getTargetVirtualAddress(Target* i_target,
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
-errlHndl_t ibscomPerformOp(DeviceFW::OperationType i_opType,
+errlHndl_t doIBScom(DeviceFW::OperationType i_opType,
Target* i_target,
void* io_buffer,
size_t& io_buflen,
- int64_t i_accessType,
- va_list i_args)
+ uint64_t i_addr,
+ bool i_errDataPath)
{
errlHndl_t l_err = NULL;
- uint64_t l_addr = va_arg(i_args,uint64_t);
+ mutex_t* l_mutex = NULL;
+ bool need_unlock = false;
do
{
- TRACDCOMP(g_trac_ibscom, INFO_MRK
- ">>ibscomPerformOp: Perform op to SCOM Address 0x%X",
- l_addr);
+ TRACUCOMP(g_trac_ibscom, INFO_MRK
+ ">>doIBScom: Perform op to SCOM Address 0x%X",
+ i_addr);
// inband scom operation sanity check
l_err = ibscomOpSanityCheck(i_opType, i_target, io_buffer,
- io_buflen, l_addr);
+ io_buflen, i_addr);
if (l_err)
{
break;
@@ -287,44 +333,344 @@ errlHndl_t ibscomPerformOp(DeviceFW::OperationType i_opType,
break;
}
+ TRACDCOMP(g_trac_ibscom,
+ "doIBScom: Base Virt Addr: 0x%.16X, Read addr: 0x%.16X",
+ l_virtAddr, &(l_virtAddr[i_addr]));
+
+
// The dereferencing should handle Cache inhibited internally
// Use local variable and memcpy to avoid unaligned memory access
uint64_t l_data = 0;
+ bool rw_error = false;
+
+ //Device already locked when re-entering function for error collection..
+ if(!i_errDataPath)
+ {
+ l_mutex = i_target->getHbMutexAttr<TARGETING::ATTR_IBSCOM_MUTEX>();
+ mutex_lock(l_mutex);
+ need_unlock = true;
+ }
if (i_opType == DeviceFW::READ)
{
- //TODO: Check that address isn't greater than allocated 32GB range
- // RTC: 47212
- l_data = l_virtAddr[l_addr];
+ //This is the actual MMIO Read
+ l_data = l_virtAddr[i_addr];
+ eieio();
- memcpy(io_buffer, &l_data, sizeof(l_data));
- TRACDCOMP(g_trac_ibscom,
- "ibscomPerformOp: Read data: %.16llx",
- l_data);
+ TRACUCOMP(g_trac_ibscom,
+ "doIBScom: Read address: 0x%.8X data: %.16X",
+ i_addr, l_data);
+ // Check for error or done
+ if(l_data == MMIO_IBSCOM_UE_DETECTED)
+ {
+ if(i_errDataPath)
+ {
+ TRACFCOMP(g_trac_ibscom, ERR_MRK"doIBScom: SUE Occurred during IBSCOM Error path");
+ /*@
+ * @errortype
+ * @moduleid IBSCOM_DO_IBSCOM
+ * @reasoncode IBSCOM_SUE_IN_ERR_PATH
+ * @userdata1[0:31] HUID of Centaur Target
+ * @userdata1[32:64] SCOM Address
+ * @userdata2 Not Used
+ * @devdesc SUE Encountered when collecting IBSCOM
+ * Error Data
+ */
+ l_err =
+ new ErrlEntry(ERRL_SEV_UNRECOVERABLE,
+ IBSCOM_DO_IBSCOM,
+ IBSCOM_SUE_IN_ERR_PATH,
+ TWO_UINT32_TO_UINT64(
+ get_huid(i_target),
+ i_addr),
+ 0);
+ //This error should NEVER get returned to caller, so it's a
+ //FW bug if it actually gets comitted.
+ l_err->addProcedureCallout(HWAS::EPUB_PRC_HB_CODE,
+ HWAS::SRCI_PRIORITY_HIGH);
+ break;
+ }
+ else
+ {
+ TRACFCOMP(g_trac_ibscom,
+ "doIBScom: Error code found in read data");
+ rw_error = true;
+ }
+ }
+ else
+ {
+ //Copy data to user buffer
+ memcpy(io_buffer, &l_data, sizeof(l_data));
+ }
}
- else
+ else //i_opType == DeviceFW::WRITE
{
- TRACDCOMP(g_trac_ibscom,
- "ibscomPerformOp: Write data: %.16llx",
- l_data);
memcpy(&l_data, io_buffer, sizeof(l_data));
- l_virtAddr[l_addr] = l_data;
+ TRACUCOMP(g_trac_ibscom,
+ "doIBScom: Write addr: 0x%.8X data: %.16X",
+ i_addr, l_data);
+ //This is the actual MMIO Write
+ l_virtAddr[i_addr] = l_data;
+ eieio();
+
+ TRACDCOMP(g_trac_ibscom,
+ "doIBScom: Read MBSIBWRSTAT to check for error");
+ //Read MBSIBWRSTAT to check for errors
+ //If an error occured on last write, reading MBSIBWRSTAT will
+ //trigger a SUE.
+ const uint32_t MBSIBWRSTAT = 0x201141D;
+ uint64_t statData = 0;
+ size_t readSize = sizeof(uint64_t);
+ l_err = doIBScom(DeviceFW::READ,
+ i_target,
+ &statData,
+ readSize,
+ MBSIBWRSTAT,
+ true);
+ if(l_err != NULL)
+ {
+ if( IBSCOM_SUE_IN_ERR_PATH == l_err->reasonCode() )
+ {
+ TRACFCOMP(g_trac_ibscom, ERR_MRK
+ "doIBScom: SUE on write detected");
+ delete l_err;
+ l_err = NULL;
+ rw_error = true;
+ }
+ else
+ {
+ TRACFCOMP(g_trac_ibscom, ERR_MRK"doIBScom: Unexpected error when checking for SUE");
+ break;
+ }
+ }
+
}
- // Check for error or done
- //TODO - check for errors RTC: 47212
- //assume successful for now
- io_buflen = sizeof(uint64_t);
+ if(rw_error)
+ {
+ bool busDown = false;
+ TRACUCOMP(g_trac_ibscom,
+ "doIBScom: Get Error data, read MBSIBERR0");
+ const uint32_t MBSIBERR0 = 0x201141B;
+ const uint64_t HOST_ERROR_VALID = 0x0000000080000000;
+ const uint64_t PIB_ERROR_STATUS_MASK = 0x0000000070000000;
+ const uint64_t PIB_ERROR_SHIFT = 28;
+ uint64_t errData = 0;
+ size_t readSize = sizeof(uint64_t);
+
+ //Use FSISCOM as workaround for DD1.x centaur chips (HW246298)
+ if(i_target->getAttr<TARGETING::ATTR_EC>() < 0x20)
+ {
+ //Need to explicitly use FSI SCOM in DD1X chips
+ l_err = deviceOp( DeviceFW::READ,
+ i_target,
+ &errData,
+ readSize,
+ DEVICE_FSISCOM_ADDRESS(MBSIBERR0) );
+ if(l_err)
+ {
+ TRACFCOMP(g_trac_ibscom, ERR_MRK
+ "doIBScom: Error reading MBSIBERR0 over FSI");
+ //Save away the IBSCOM address
+ ERRORLOG::ErrlUserDetailsLogRegister
+ l_logReg(i_target);
+ //Really just want to save the addres, so stick in some
+ //obvious dummy data
+ uint64_t dummyData = 0x00000000DEADBEEF;
+ l_logReg.addDataBuffer(&dummyData, sizeof(dummyData),
+ DEVICE_IBSCOM_ADDRESS(i_addr));
+ l_logReg.addToLog(l_err);
+ break;
+ }
+ TRACUCOMP(g_trac_ibscom,
+ "doIBScom: MBSIBERR0(0x%.16x) = 0x%.16X",
+ MBSIBERR0, errData);
+
+ //attempt to clear the error register so future accesses
+ //will work
+ uint64_t zeroData = 0x0;
+ readSize = sizeof(uint64_t);
+ l_err = deviceOp( DeviceFW::WRITE,
+ i_target,
+ &zeroData,
+ readSize,
+ DEVICE_FSISCOM_ADDRESS(MBSIBERR0) );
+ if(l_err )
+ {
+ errlCommit(l_err,IBSCOM_COMP_ID);
+ l_err = NULL;
+ }
+
+
+ uint64_t pib_code = (errData && PIB_ERROR_STATUS_MASK)
+ >> PIB_ERROR_SHIFT;
+ if((errData & HOST_ERROR_VALID) &&//bit 32
+ // technically between 0x001 && 0x7, but only 3
+ // bits are valid.
+ (pib_code > 0x000))
+ {
+ //TODO RTC: 35064 - This will be the same as the FSI SCOM
+ //error handling.
+ //Look at data to decide if bus is down
+ //Make smart decisions based on PIB error code.
+
+ //Assume caller provided bad address for now.
+ TRACFCOMP(g_trac_ibscom, "doIBScom: MBSIBERR0 bit 0 set, caller most likely used a bad address (0x%.8x)",
+ i_addr);
+
+ /*@
+ * @errortype
+ * @moduleid IBSCOM_DO_IBSCOM
+ * @reasoncode IBSCOM_INVALID_ADDRESS
+ * @userdata1[0:31] HUID of Centaur Target
+ * @userdata1[32:64] SCOM Address
+ * @userdata2 Contents of MBSIBERR0 register
+ * @devdesc Operation rejected by HW due to bad
+ * address.
+ */
+ l_err =
+ new ErrlEntry(ERRL_SEV_UNRECOVERABLE,
+ IBSCOM_DO_IBSCOM,
+ IBSCOM_INVALID_ADDRESS,
+ TWO_UINT32_TO_UINT64(
+ get_huid(i_target),
+ i_addr),
+ errData);
+ l_err->addProcedureCallout(HWAS::EPUB_PRC_HB_CODE,
+ HWAS::SRCI_PRIORITY_HIGH);
+ break;
+ }
+ else
+ {
+ //Bus is down
+ busDown = true;
+ }
- TRACDCOMP(g_trac_ibscom,
- "ibscomPerformOp: OpType 0x%.16llX, SCOM Address 0x%llX, Virtual Address 0x%llX",
+
+ }
+ else // >= DD20
+ {
+ //TODO RTC: 68984: Validate error path on DD2.0 Centaurs
+ l_err = doIBScom(DeviceFW::READ,
+ i_target,
+ &errData,
+ readSize,
+ MBSIBERR0,
+ true);
+ if(l_err != NULL)
+ {
+ if( IBSCOM_SUE_IN_ERR_PATH == l_err->reasonCode() )
+ {
+ TRACFCOMP(g_trac_ibscom, ERR_MRK
+ "doIBScom: SUE on write detected");
+ delete l_err;
+ l_err = NULL;
+ busDown = true;
+ }
+ else
+ {
+ TRACFCOMP(g_trac_ibscom, ERR_MRK"doIBScom: Unexpected error when checking for SUE");
+ break;
+ }
+ }
+ else //MBSIBERR0 returned valid data
+ {
+ //TODO RTC: 35064 - This will be the same as the FSI SCOM
+ //error handling.
+ //Look at data to decide if bus is down
+ //Make smart decisions based on PIB error code.
+
+ //For now, assume bus is Down
+ busDown = true;
+
+ }
+ } // >= DD20
+
+ if(busDown)
+ {
+ //TODO RTC: 69115 - call PRD to do FIR analysis, return PRD
+ //error instead.
+ /*@
+ * @errortype
+ * @moduleid IBSCOM_DO_IBSCOM
+ * @reasoncode IBSCOM_BUS_FAILURE
+ * @userdata1[0:31] HUID of Centaur Target
+ * @userdata1[32:64] SCOM Address
+ * @userdata2 Contents of MBSIBERR0 register
+ * @devdesc Bus failure when attempting to perform
+ * IBSCOM operation. IBSCOM disabled.
+ */
+ l_err =
+ new ErrlEntry(ERRL_SEV_UNRECOVERABLE,
+ IBSCOM_DO_IBSCOM,
+ IBSCOM_BUS_FAILURE,
+ TWO_UINT32_TO_UINT64(
+ get_huid(i_target),
+ i_addr),
+ errData);
+
+ l_err->addHwCallout(i_target,
+ HWAS::SRCI_PRIORITY_HIGH,
+ HWAS::NO_DECONFIG,
+ HWAS::GARD_NULL);
+
+ //disable IBSCOM
+ ScomSwitches l_switches =
+ i_target->getAttr<ATTR_SCOM_SWITCHES>();
+
+ // If IBSCOM is not already disabled.
+ if ((l_switches.useFsiScom != 1) ||
+ (l_switches.useInbandScom != 0))
+ {
+ l_switches.useFsiScom = 1;
+ l_switches.useInbandScom = 0;
+
+ // Turn off IBSCOM and turn on FSI SCOM.
+ i_target->setAttr<ATTR_SCOM_SWITCHES>(l_switches);
+ }
+ break;
+ }
+ }
+ else
+ {
+ //Operation was a success, set buffer length
+ io_buflen = sizeof(uint64_t);
+ }
+
+ TRACDCOMP(g_trac_ibscom,"doIBScom: OpType 0x%.16llX, SCOM Address 0x%llX, Virtual Address 0x%llX",
static_cast<uint64_t>(i_opType),
- l_addr,
- &(l_virtAddr[l_addr]));
+ i_addr,
+ &(l_virtAddr[i_addr]));
} while (0);
+ if( need_unlock && l_mutex )
+ {
+ mutex_unlock(l_mutex);
+ }
+
+ return l_err;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+errlHndl_t ibscomPerformOp(DeviceFW::OperationType i_opType,
+ Target* i_target,
+ void* io_buffer,
+ size_t& io_buflen,
+ int64_t i_accessType,
+ va_list i_args)
+{
+ errlHndl_t l_err = NULL;
+ uint64_t l_addr = va_arg(i_args,uint64_t);
+
+ l_err = doIBScom(i_opType,
+ i_target,
+ io_buffer,
+ io_buflen,
+ l_addr,
+ false);
return l_err;
}
diff --git a/src/usr/ibscom/ibscom.H b/src/usr/ibscom/ibscom.H
index 7bb17b9ad..3ba3c34f1 100644
--- a/src/usr/ibscom/ibscom.H
+++ b/src/usr/ibscom/ibscom.H
@@ -5,7 +5,7 @@
/* */
/* IBM CONFIDENTIAL */
/* */
-/* COPYRIGHT International Business Machines Corp. 2012 */
+/* COPYRIGHT International Business Machines Corp. 2012,2013 */
/* */
/* p1 */
/* */
diff --git a/src/usr/ibscom/test/ibscomtest.H b/src/usr/ibscom/test/ibscomtest.H
index 189f78049..e6be9f7c8 100644
--- a/src/usr/ibscom/test/ibscomtest.H
+++ b/src/usr/ibscom/test/ibscomtest.H
@@ -5,7 +5,7 @@
/* */
/* IBM CONFIDENTIAL */
/* */
-/* COPYRIGHT International Business Machines Corp. 2012 */
+/* COPYRIGHT International Business Machines Corp. 2012,2013 */
/* */
/* p1 */
/* */
@@ -47,14 +47,11 @@ class IBscomTest: public CxxTest::TestSuite
/**
* @brief inband scom test #1
- * Write value and read back to verify
+ * Write values and read back to verify
*/
void test_IBscom(void)
{
- //TODO Enable and improve test cases RTC: 52900
- return;
-
uint64_t fails = 0;
uint64_t total = 0;
errlHndl_t l_err = NULL;
@@ -88,77 +85,146 @@ class IBscomTest: public CxxTest::TestSuite
}
l_testTarget = *(centaur_list.begin());
- uint64_t addr = 0x03010E03;
- uint64_t orig_data = 0;
- uint64_t data = 0x12345678FEEDB0B0;
+ TRACDCOMP(g_trac_ibscom,
+ "IBscomTest::test_IBscom> Read orignal data from Centaur");
+
+
+ const uint64_t addrs[] = {0x0201164F, 0x0301069A};
+ uint64_t orig_data[2] = {0};
+ uint64_t new_data[] = {0x1234567ABABABA00, 0xFEEDB0B0FEDCBA00};
+ uint64_t read_data[2] = {0};
+ uint64_t read_data_fsi[2] = {0};
size_t op_size = sizeof(uint64_t);
//Save of initial register content
- l_err = deviceRead( l_testTarget,
- &orig_data,
- op_size,
- DEVICE_SCOM_ADDRESS(addr) );
- if( l_err )
+ for(uint32_t i=0; i<2; i++)
{
- TRACFCOMP(g_trac_ibscom,
- "IBscomTest::test_IBscom> Orig Read: Error from device : addr=0x%X, RC=%X",
- addr, l_err->reasonCode() );
- TS_FAIL( "test_IBscom1> ERROR : Unexpected error log from read1" );
- fails++;
- errlCommit(l_err,IBSCOM_COMP_ID);
+ op_size = sizeof(uint64_t);
+ l_err = deviceRead( l_testTarget,
+ &orig_data[i],
+ op_size,
+ DEVICE_SCOM_ADDRESS(addrs[i]) );
+ if( l_err )
+ {
+ TRACFCOMP(g_trac_ibscom,"IBscomTest::test_IBscom> Orig Read: Error from device : addr=0x%X, RC=%X",
+ addrs[i], l_err->reasonCode() );
+ TS_FAIL( "test_IBscom1> ERROR : Unexpected error log from saving original data." );
+ fails++;
+ errlCommit(l_err,IBSCOM_COMP_ID);
+ }
+ total++;
+
}
- l_err = deviceOp( DeviceFW::WRITE,
- l_testTarget,
- &data,
- op_size,
- DEVICE_IBSCOM_ADDRESS(addr) );
- if( l_err )
+ //Write in some new data
+ for(uint32_t i=0; i<2; i++)
{
- TRACFCOMP(g_trac_ibscom,
- "IBscomTest::test_IBscom> Write: Error from device : addr=0x%X, RC=%X",
- addr, l_err->reasonCode() );
- TS_FAIL( "ScomTest::test_IBscom> ERROR : Error log from write1" );
- fails++;
- errlCommit(l_err,IBSCOM_COMP_ID);
+ TRACDCOMP(g_trac_ibscom,"IBscomTest::test_IBscom> Write new pattern: 0x%.16X", new_data[i]);
+
+ op_size = sizeof(uint64_t);
+ l_err = deviceOp( DeviceFW::WRITE,
+ l_testTarget,
+ &new_data[i],
+ op_size,
+ DEVICE_IBSCOM_ADDRESS(addrs[i]) );
+ if( l_err )
+ {
+ TRACFCOMP(g_trac_ibscom,"IBscomTest::test_IBscom> Write: Error from device : addr=0x%X, RC=%X",
+ addrs[i], l_err->reasonCode() );
+ TS_FAIL( "ScomTest::test_IBscom> ERROR : Error log from IBSCOM Write" );
+ fails++;
+ errlCommit(l_err,IBSCOM_COMP_ID);
+ }
+
+ total++;
}
- total++;
-
- l_err = deviceOp( DeviceFW::READ,
- l_testTarget,
- &data,
- op_size,
- DEVICE_IBSCOM_ADDRESS(addr) );
- if( l_err )
+ //Read the data back with IBSCOM
+ for(uint32_t i=0; i<2; i++)
{
- TRACFCOMP(g_trac_ibscom,
- "IBscomTest::test_IBscom> Read: Error from device : addr=0x%X, RC=%X",
- addr, l_err->reasonCode() );
- TS_FAIL( "test_IBscom> ERROR : Error log from read2" );
- fails++;
- errlCommit(l_err,IBSCOM_COMP_ID);
+ TRACDCOMP(g_trac_ibscom,
+ "IBscomTest::test_IBscom> Read data back");
+
+ //reset size
+ op_size = sizeof(uint64_t);
+ l_err = deviceOp( DeviceFW::READ,
+ l_testTarget,
+ &read_data[i],
+ op_size,
+ DEVICE_IBSCOM_ADDRESS(addrs[i]) );
+ if( l_err )
+ {
+ TRACFCOMP(g_trac_ibscom,"IBscomTest::test_IBscom> Read: Error from device : addr=0x%X, RC=%X",
+ addrs[i], l_err->reasonCode() );
+ TS_FAIL( "test_IBscom> ERROR : Error log from IBSCOM read" );
+ fails++;
+ errlCommit(l_err,IBSCOM_COMP_ID);
+ }
+
+ if(new_data[i] != read_data[i])
+ {
+ TS_FAIL( "test_IBscom> ERROR : Data miss-match on IBSCOM read-back check." );
+
+ TRACFCOMP(g_trac_ibscom,"IBscomTest::test_IBscom>ERROR: addr=0x%.8x: Write data=0x%.16X, IBSCOM read data=0x%.16X",
+ addrs[i], new_data[i], read_data[i]);
+ fails++;
+ }
+
+ total++;
}
- total++;
+ //Read the data back with FSISCOM
+ for(uint32_t i=0; i<2; i++)
+ {
+ TRACDCOMP(g_trac_ibscom,
+ "IBscomTest::test_IBscom> Read data back");
+
+ //reset size
+ op_size = sizeof(uint64_t);
+ l_err = deviceOp( DeviceFW::READ,
+ l_testTarget,
+ &read_data_fsi[i],
+ op_size,
+ DEVICE_FSISCOM_ADDRESS(addrs[i]) );
+ if( l_err )
+ {
+ TRACFCOMP(g_trac_ibscom, "IBscomTest::test_IBscom> Read: Error from device : addr=0x%X, RC=%X",
+ addrs[i], l_err->reasonCode() );
+ TS_FAIL( "test_IBscom> ERROR : Error log from FSI Read" );
+ fails++;
+ errlCommit(l_err,IBSCOM_COMP_ID);
+ }
+
+ if(new_data[i] != read_data_fsi[i])
+ {
+ TS_FAIL( "test_IBscom> ERROR : Data miss-match on FSI read-back check." );
+
+ TRACFCOMP(g_trac_ibscom, "IBscomTest::test_IBscom>ERROR: addr=0x%.8x: Write data=0x%.16X, FSI read data=0x%.16X",
+ addrs[i], new_data[i], read_data_fsi[i]);
+ fails++;
+ }
+ total++;
+ }
//Restore original data.
- l_err = deviceWrite( l_testTarget,
- &orig_data,
- op_size,
- DEVICE_SCOM_ADDRESS(addr) );
-
- if( l_err )
+ for(uint32_t i=0; i<2; i++)
{
- TRACFCOMP(g_trac_ibscom,
- "IBscomTest::test_IBscom> Write Orig Data: Error from device : addr=0x%X, RC=%X",
- addr, l_err->reasonCode() );
- TS_FAIL( "test_IBscom> ERROR : Error log from write2" );
- fails++;
- errlCommit(l_err,IBSCOM_COMP_ID);
+ op_size = sizeof(uint64_t);
+ l_err = deviceWrite( l_testTarget,
+ &orig_data[i],
+ op_size,
+ DEVICE_SCOM_ADDRESS(addrs[i]) );
+
+ if( l_err )
+ {
+ TRACFCOMP(g_trac_ibscom,"IBscomTest::test_IBscom> Write Orig Data: Error from device : addr=0x%X, RC=%X",
+ addrs[i], l_err->reasonCode() );
+ TS_FAIL( "test_IBscom> ERROR : Error log from write2" );
+ fails++;
+ errlCommit(l_err,IBSCOM_COMP_ID);
+ }
}
-
TS_TRACE("test_IBscom runs successfully!");
TRACFCOMP(g_trac_ibscom,
"IBscomTest::test_IBscom> %d/%d fails",
@@ -167,7 +233,8 @@ class IBscomTest: public CxxTest::TestSuite
return;
}
-
+ //TODO RTC: 68733: Add error path test cases when simics support
+ //is available
};
diff --git a/src/usr/targeting/common/xmltohb/attribute_types_hb.xml b/src/usr/targeting/common/xmltohb/attribute_types_hb.xml
index c64a2506a..febddc88d 100644
--- a/src/usr/targeting/common/xmltohb/attribute_types_hb.xml
+++ b/src/usr/targeting/common/xmltohb/attribute_types_hb.xml
@@ -1,11 +1,11 @@
<!-- IBM_PROLOG_BEGIN_TAG -->
<!-- This is an automatically generated prolog. -->
<!-- -->
-<!-- $Source: src/usr/targeting/common/xmltohb/attribute_types.xml $ -->
+<!-- $Source: src/usr/targeting/common/xmltohb/attribute_types_hb.xml $ -->
<!-- -->
<!-- IBM CONFIDENTIAL -->
<!-- -->
-<!-- COPYRIGHT International Business Machines Corp. 2011,2012 -->
+<!-- COPYRIGHT International Business Machines Corp. 2011,2013 -->
<!-- -->
<!-- p1 -->
<!-- -->
@@ -203,5 +203,17 @@
<writeable/>
<hbOnly/>
</attribute>
-
+<attribute>
+ <id>IBSCOM_MUTEX</id>
+ <description>Mutex for Inband SCOM Operations</description>
+ <simpleType>
+ <hbmutex>
+ <default>0</default>
+ </hbmutex>
+ </simpleType>
+ <persistency>volatile-zeroed</persistency>
+ <readable/>
+ <writeable/>
+ <hbOnly/>
+</attribute>
</attributes>
diff --git a/src/usr/targeting/common/xmltohb/target_types_hb.xml b/src/usr/targeting/common/xmltohb/target_types_hb.xml
index 6267e937d..1b2495c9b 100644
--- a/src/usr/targeting/common/xmltohb/target_types_hb.xml
+++ b/src/usr/targeting/common/xmltohb/target_types_hb.xml
@@ -1,11 +1,11 @@
<!-- IBM_PROLOG_BEGIN_TAG -->
<!-- This is an automatically generated prolog. -->
<!-- -->
-<!-- $Source: src/usr/targeting/common/xmltohb/target_types.xml $ -->
+<!-- $Source: src/usr/targeting/common/xmltohb/target_types_hb.xml $ -->
<!-- -->
<!-- IBM CONFIDENTIAL -->
<!-- -->
-<!-- COPYRIGHT International Business Machines Corp. 2011,2012 -->
+<!-- COPYRIGHT International Business Machines Corp. 2011,2013 -->
<!-- -->
<!-- p1 -->
<!-- -->
@@ -88,6 +88,9 @@
<id>IBSCOM_VIRTUAL_ADDR</id>
</attribute>
<attribute>
+ <id>IBSCOM_MUTEX</id>
+ </attribute>
+ <attribute>
<id>I2C_ENGINE_MUTEX_0</id>
<default>0</default>
</attribute>
OpenPOWER on IntegriCloud