diff --git a/src/include/arch/pvrformat.H b/src/include/arch/pvrformat.H new file mode 100644 index 00000000000..7915891fe8b --- /dev/null +++ b/src/include/arch/pvrformat.H @@ -0,0 +1,135 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/include/arch/pvrformat.H $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2017 */ +/* [+] 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 */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +#ifndef _PVRFORMAT_H +#define _PVRFORMAT_H + +/** + * @brief Format of Processor Version Register (PVR) for P9 + */ +struct PVR_t +{ + union + { + // Layout of the PVR is (32-bit): + uint32_t word; + + //Nimbus DD1.0 + // 2 nibbles reserved. + // 2 nibbles chip family. + // = x'4E' - P9 + // 1 nibble technology. + // 1 nibble major DD. + // 1 nibble reserved. + // 1 nibble minor DD. + struct + { + uint32_t dd1_reserved0:8; // 00:07 = unused + uint32_t dd1_chipFamily:8; // 08:15 = chip type + uint32_t dd1_tech:4; // 16:19 = technology + uint32_t dd1_majorDD:4; // 20:23 = Major DD + uint32_t dd1_reserved1:4; // 24:27 = unused + uint32_t dd1_minorDD:4; // 28:31 = Minor DD + } PACKED; + + + //Nimbus DD2+, Cumulus + // 2 nibbles reserved. + // 2 nibbles chip family. + // = x'4E' - P9 + // 2 bits Simics indicator. + // 1 bit chip type. + // = x'0' - Nimbus + // = x'1' - Cumulus + // 1 bit SMT mode. + // = x'0' - 12 core (SMT8) + // = x'1' - 24 core (SMT4) + // 1 nibble major DD. + // 1 nibble reserved. + // 1 nibble minor DD. + struct + { + uint32_t reserved0:8; // 00:07 = unused + uint32_t chipFamily:8; // 08:15 = chip family + uint32_t simics:2; // 16:17 = Simics flag + uint32_t chipType:1; // 18 = chip type + uint32_t smt:1; // 19 = SMT mode + uint32_t majorDD:4; // 20:23 = Major DD + uint32_t reserved1:4; // 24:27 = unused + uint32_t minorDD:4; // 28:31 = Minor DD + } PACKED; + }; + + // Populate with a 32-bit data word + PVR_t(uint32_t i_word = 0) : word(i_word) {} + + // Populate with a 64-bit data word + PVR_t(uint64_t i_word = 0) + : word(static_cast(i_word & 0xFFFFFFFF)) {} + + PVR_t operator= (uint32_t i_word) + { + word = i_word; + return word; + } + + PVR_t operator= (uint64_t i_word) + { + word = static_cast(i_word & 0xFFFFFFFF); + return word; + } + + /** + * @brief Return Major.Minor DD level + * @return 8-bit DD level + */ + inline uint8_t getDDLevel() { + return (majorDD << 4) | minorDD; + } + + /** + * @brief A bunch of constants + */ + enum + { + CHIP_DD_MASK = 0x00FF0F0F, + IS_NIMBUS_DD1 = 0x004E0100, + + // Field: chipType + NIMBUS_CHIP = 0, + CUMULUS_CHIP = 1, + + // Field: smt + SMT8_MODE = 0, + SMT4_MODE = 1, + + // Field: chipFamily + P8_MURANO = 0x4B, + P8_NAPLES = 0x4C, + P8_VENICE = 0x4D, + P9_ALL = 0x4E, + }; +}; + +#endif //_PVRFORMAT_H diff --git a/src/kernel/cpuid.C b/src/kernel/cpuid.C index 576c740437c..f65612ae163 100644 --- a/src/kernel/cpuid.C +++ b/src/kernel/cpuid.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2015 */ +/* Contributors Listed Below - COPYRIGHT 2011,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -27,37 +27,45 @@ */ #include +#include namespace CpuID { ProcessorCoreType getCpuType() { - uint64_t l_pvr = getPVR(); + PVR_t l_pvr( getPVR() ); - // Layout of the PVR is (32-bit): - // 2 nibbles reserved. - // 2 nibbles chip type. - // 1 nibble technology. - // 1 nibble major DD. - // 1 nibble reserved. - // 1 nibble minor DD. - - switch(l_pvr & 0xFFFF0000) + switch(l_pvr.chipFamily) { - case 0x004B0000: + case PVR_t::P8_MURANO: return CORE_POWER8_MURANO; - case 0x004C0000: + case PVR_t::P8_NAPLES: return CORE_POWER8_NAPLES; - case 0x004D0000: + case PVR_t::P8_VENICE: return CORE_POWER8_VENICE; - case 0x004E0000: - return CORE_POWER9_NIMBUS; + case PVR_t::P9_ALL: + { + // Nimbus DD1.0 has a different PVR format + if( (l_pvr.word & PVR_t::CHIP_DD_MASK) == PVR_t::IS_NIMBUS_DD1) + { + return CORE_POWER9_NIMBUS; + } + + switch(l_pvr.chipType) + { + case PVR_t::NIMBUS_CHIP: + return CORE_POWER9_NIMBUS; + + case PVR_t::CUMULUS_CHIP: + return CORE_POWER9_CUMULUS; - case 0x004F0000: - return CORE_POWER9_CUMULUS; + default: + return CORE_UNKNOWN; + } + } default: return CORE_UNKNOWN; @@ -66,8 +74,8 @@ namespace CpuID uint8_t getCpuDD() { - uint64_t l_pvr = getPVR(); - return ((l_pvr & 0x0F00) >> 4) | (l_pvr & 0x000F); + PVR_t l_pvr( getPVR() ); + return l_pvr.getDDLevel(); } }; diff --git a/src/kernel/cpumgr.C b/src/kernel/cpumgr.C index e6bf08dd905..f7cb25961b3 100644 --- a/src/kernel/cpumgr.C +++ b/src/kernel/cpumgr.C @@ -46,6 +46,7 @@ #include #include #include +#include cpu_t** CpuManager::cv_cpus[KERNEL_MAX_SUPPORTED_NODES]; bool CpuManager::cv_shutdown_requested = false; @@ -472,6 +473,9 @@ size_t CpuManager::getThreadCount() case CORE_UNKNOWN: default: + PVR_t l_pvr( getPVR() ); + printk("cputype=%d, pvr=%.8X\n", + CpuID::getCpuType(), l_pvr.word); kassert(false); break; } diff --git a/src/usr/intr/intrrp.C b/src/usr/intr/intrrp.C index fe010ed111c..85d8f54f14d 100644 --- a/src/usr/intr/intrrp.C +++ b/src/usr/intr/intrrp.C @@ -51,6 +51,7 @@ #include #include #include +#include #include #include @@ -397,11 +398,13 @@ errlHndl_t IntrRp::resetIntUnit(intr_hdlr_t* i_proc) TARGETING::Target* procTarget = i_proc->proc; do { - - //TODO RTC 160361 - Replace attribute with EC check. Anything greater - // DD20 should do the HW-based reset - uint8_t l_doHwReset = - iv_masterHdlr->proc->getAttr(); + //Anything greater than DD10 should do the HW-based reset + bool l_doHwReset = true; + uint32_t l_pvr = mmio_pvr_read() & 0xFFFFFFFF; + if( (l_pvr & PVR_t::CHIP_DD_MASK) == PVR_t::IS_NIMBUS_DD1 ) + { + l_doHwReset = false; + } if (l_doHwReset) {