From 8c7a27be94470541d184cfec495b6cfe63953733 Mon Sep 17 00:00:00 2001 From: Patrick Williams Date: Wed, 26 Mar 2014 17:06:32 -0500 Subject: Use per-core mutex for XSCOM for P8 errata. See HW822317. The HMER register in P8 is not implemented to handle multi-threaded XSCOM properly, so we need to move the XSCOM mutex from per-thread to per-core. Also, there is an issue where the 'done' bit can come on 1 cycle before the error indicators, so need to potentially read the HMER a second time. Change-Id: I495031a6e425fe7d5c6ffef8dda1e7a71caac9f2 CQ: SW250902 Backport: release-fips810 Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/9929 Reviewed-by: Michael Baiocchi Reviewed-by: A. Patrick Williams III Tested-by: Jenkins Server --- src/kernel/cpumgr.C | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) (limited to 'src/kernel/cpumgr.C') diff --git a/src/kernel/cpumgr.C b/src/kernel/cpumgr.C index 624751b5c..ac0e09dff 100644 --- a/src/kernel/cpumgr.C +++ b/src/kernel/cpumgr.C @@ -5,7 +5,7 @@ /* */ /* IBM CONFIDENTIAL */ /* */ -/* COPYRIGHT International Business Machines Corp. 2010,2013 */ +/* COPYRIGHT International Business Machines Corp. 2010,2014 */ /* */ /* p1 */ /* */ @@ -42,6 +42,7 @@ #include #include #include +#include cpu_t** CpuManager::cv_cpus[KERNEL_MAX_SUPPORTED_NODES]; bool CpuManager::cv_shutdown_requested = false; @@ -214,7 +215,34 @@ void CpuManager::startCPU(ssize_t i) reinterpret_cast(cpu->kernel_stack_bottom) + kernel_page_offset); - cpu->xscom_mutex = (mutex_t)MUTEX_INITIALIZER; + cpu->xscom_mutex = NULL; + + // xscom workaround for HW822317 : Power8 Errata. + // Need to make the xscom mutex a per-core mutex to prevent + // multi-threaded access to the HMER. + if ((CpuID::getCpuType() == CORE_POWER8_MURANO) || + (CpuID::getCpuType() == CORE_POWER8_VENICE)) + { + const size_t num_threads = getThreadCount(); + size_t cpu_idx = (cpuId / num_threads) * num_threads; + + for(size_t i = 0; i < getThreadCount(); ++i) + { + if ((NULL != cv_cpus[nodeId][cpu_idx + i]) && + (NULL != cv_cpus[nodeId][cpu_idx + i]->xscom_mutex)) + { + cpu->xscom_mutex = + cv_cpus[nodeId][cpu_idx + i]->xscom_mutex; + break; + } + } + } + + if (NULL == cpu->xscom_mutex) + { + cpu->xscom_mutex = new mutex_t; + mutex_init(cpu->xscom_mutex); + } // Create idle task. cpu->idle_task = TaskManager::createIdleTask(); -- cgit v1.2.1