From d26d782b532cce24b36376ad7d4859be7d3cf526 Mon Sep 17 00:00:00 2001 From: Brian Vanderpool Date: Wed, 15 Jun 2016 07:40:11 -0500 Subject: L2 Delivery for p9_query_stop_state Change-Id: I11121d7a97aa747ea4595f58b4f76bcaf74dd85e Original-Change-Id: Id3dde77409b398710cd8b115a6c0867380b3fa1e RTC:148980 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/25847 Tested-by: Jenkins Server Tested-by: Hostboot CI Reviewed-by: Gregory S. Still Reviewed-by: DHRUVARAJ SUBHASH CHANDRAN Reviewed-by: Jennifer A. Stofer Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/27573 Tested-by: FSP CI Jenkins Reviewed-by: Daniel M. Crowell --- .../p9/procedures/hwp/pm/p9_query_stop_state.C | 378 +++++++++++++++++++-- 1 file changed, 350 insertions(+), 28 deletions(-) (limited to 'src/import/chips/p9/procedures/hwp/pm/p9_query_stop_state.C') diff --git a/src/import/chips/p9/procedures/hwp/pm/p9_query_stop_state.C b/src/import/chips/p9/procedures/hwp/pm/p9_query_stop_state.C index 2f6bdfbf5..b6fa27020 100644 --- a/src/import/chips/p9/procedures/hwp/pm/p9_query_stop_state.C +++ b/src/import/chips/p9/procedures/hwp/pm/p9_query_stop_state.C @@ -28,7 +28,7 @@ // *HWP Backup HWP Owner: Greg Still // *HWP FW Owner: Sangeetha T S // *HWP Team: PM -// *HWP Level: 1 +// *HWP Level: 2 // *HWP Consumed by: FSP:HS /// /// @@ -38,17 +38,21 @@ /// - For each EX, check the PPMC stop state history to know the state /// of the core. Check the PPMQ stop state history to know the state of L2/L3 /// -/// Set ATTRs to know the scommable/scannable state of the logic -/// L2_IS_SCOMABLE indicates the L2 region has clocks running and scommable -/// L3_IS_SCOMABLE indicates the L3 region has clocks running and scommable -/// C0_EXEC_IS_SCOMABLE indicates the execution units in core 0 have clocks running and scommable -/// C1_EXEC_IS_SCOMABLE indicates the execution units in core 1 have clocks running and scommable -/// C0_PC_IS_SCOMABLE indicates the core pervasive unit in core 0 has clocks running and scommable -/// C1_PC_IS_SCOMABLE indicates the core pervasive unit in core 1 has clocks running and scommable -/// L2_IS_SCANABLE indicates L2 has power and has valid latch state that could be scanned -/// L3_IS_SCANABLE indicates L3 has power and has valid latch state that could be scanned -/// C0_IS_SCANABLE indicates core 0 has power and has valid latch state that could be scanned -/// C1_IS_SCANABLE indicates core 1 has power and has valid latch state that could be scanned +/// - Then read the PFETSNS in the C/QPPM and CLOCK_STAT registers in the EPS to determine +/// the actual state of the hardware. Use the HW values to print out a warning if +/// different, and override the attributes +/// +/// - Set ATTRs to know the scommable/scannable state of the logic +/// L2_HASCLOCKS indicates the L2 region has clocks running and scommable +/// L3_HASCLOCKS indicates the L3 region has clocks running and scommable +/// C0_EXEC_HASCLOCKS indicates the execution units in core 0 have clocks running and scommable +/// C1_EXEC_HASCLOCKS indicates the execution units in core 1 have clocks running and scommable +/// C0_PC_HASCLOCKS indicates the core pervasive unit in core 0 has clocks running and scommable +/// C1_PC_HASCLOCKS indicates the core pervasive unit in core 1 has clocks running and scommable +/// L2_HASPOWER indicates L2 has power and has valid latch state that could be scanned +/// L3_HASPOWER indicates L3 has power and has valid latch state that could be scanned +/// C0_HASPOWER indicates core 0 has power and has valid latch state that could be scanned +/// C1_HASPOWER indicates core 1 has power and has valid latch state that could be scanned /// @endverbatim /// //------------------------------------------------------------------------------ @@ -60,37 +64,355 @@ #include "p9_query_stop_state.H" + +// ---------------------------------------------------------------------- +// Data Structure Definitions +// ---------------------------------------------------------------------- + +typedef struct +{ + uint8_t l2_hasclocks; + uint8_t l3_hasclocks; + uint8_t c0_exec_hasclocks; // these could be put in an array, but is broken out since attributes are separate + uint8_t c1_exec_hasclocks; + uint8_t c0_pc_hasclocks; + uint8_t c1_pc_hasclocks; + + uint8_t l2_haspower; + uint8_t l3_haspower; + uint8_t c0_haspower; + uint8_t c1_haspower; +} stop_attrs_t; + +typedef struct +{ + + uint8_t l2_hasclocks; + uint8_t l3_hasclocks; + uint8_t c_exec_hasclocks[2]; + uint8_t c_pc_hasclocks[2]; + + uint8_t vdd_pfet_disable_quad; + uint8_t vcs_pfet_disable_quad; + uint8_t vdd_pfet_disable_core[2]; + + + bool c0_haspower() + { + return !vdd_pfet_disable_core[0]; + } + + bool c1_haspower() + { + return !vdd_pfet_disable_core[1]; + } + + bool l2_haspower() + { + return (!vdd_pfet_disable_quad && !vcs_pfet_disable_quad); + } + + bool l3_haspower() + { + return (!vdd_pfet_disable_quad && !vcs_pfet_disable_quad); + } + +} hw_state_t; + +// Bit positions in the CLOCK_SL register for the L20, L21 and L30, L31 running state +const uint32_t eq_clk_l2_pos[] = {8, 9}; +const uint32_t eq_clk_l3_pos[] = {6, 7}; + +// ---------------------------------------------------------------------- +// Procedure Prototypes +// ---------------------------------------------------------------------- + +void compare_ss_hw(const char* msg, const uint8_t hw_state, uint8_t& stop_state); + + + // ---------------------------------------------------------------------- // Procedure Function // ---------------------------------------------------------------------- +void compare_ss_hw(const char* msg, const uint8_t hw_state, uint8_t& stop_state) +{ + + // Compare the HW (pfet/clock) state with the value the stop state history registers would indicate, + // and if there is a mismatch, use the HW value. + + if (hw_state != stop_state) + { + FAPI_INF("WARNING: %s mismatch. HW(%d) StopState(%d). Using HW value", msg, hw_state, stop_state); + // Use the HW value + stop_state = hw_state; + } +} + fapi2::ReturnCode p9_query_stop_state( const fapi2::Target& i_ex_target) { - fapi2::buffer l_data8; + + fapi2::buffer l_qsshsrc, l_csshsrc[2], l_qpfetsense, l_cpfetsense[2]; + fapi2::buffer l_data64; + uint8_t l_chpltNumber = 0; + uint32_t l_quadStopLevel = 0; + uint32_t l_exPos = 0; + uint32_t l_coreStopLevel[2] = {0, 0}; + + stop_attrs_t l_stop_attrs = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; // Initialize all fields to 1 + hw_state_t l_clk_pfet = {0, 0, {0, 0}, {0, 0}, 0, 0, {0, 0}}; // Initialize all fields to 0 + FAPI_INF("> p9_query_stop_state..."); - // The list of attributes this procedure will set. - // For level 1 delivery, set them all to 1. - l_data8 = 1; + // Get the parent EQ and core children + auto l_eq_target = i_ex_target.getParent(); + auto l_coreChiplets = i_ex_target.getChildren(fapi2::TARGET_STATE_FUNCTIONAL); + + + FAPI_DBG(" Read QPPM Stop State History"); + FAPI_TRY(fapi2::getScom(l_eq_target, EQ_PPM_SSHSRC, l_qsshsrc), "Error reading data from QPPM SSHSRC"); + + + // Get the status of each SSHSRC in each configured CPPM. + // Initialize both states to disabled in case one core is deconfigured + l_csshsrc[0].flush<0>().insertFromRight<0, 12>(0x80F); + l_csshsrc[1].flush<0>().insertFromRight<0, 12>(0x80F); + + for (auto l_core_chplt : l_coreChiplets) + { + // Fetch the position of the Core target + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, l_core_chplt, l_chpltNumber), + "ERROR: Failed to get the position of the Core:0x%08X", + l_core_chplt); + + //In case a core is deconfigured, figure out if this is the odd or even core and write the appropriate array + uint32_t l_pos = l_chpltNumber % 2; + + FAPI_DBG(" Read CPPM Stop State History for core %d", l_chpltNumber); + FAPI_TRY(fapi2::getScom(l_core_chplt, C_PPM_SSHSRC, l_csshsrc[l_pos]), "Error reading data from CPPM SSHSRC"); + + } + + // A unit is scomable if clocks are running + // A unit is scannable if the unit is powered up. + + // Extract the quad and core stop states + l_qsshsrc.extractToRight(l_quadStopLevel, 8, 4); + l_csshsrc[0].extractToRight(l_coreStopLevel[0], 8, 4); + l_csshsrc[1].extractToRight(l_coreStopLevel[1], 8, 4); + + FAPI_INF("EX Stop States: Q(%d) C0(%d) C1(%d)", l_quadStopLevel, l_coreStopLevel[0], l_coreStopLevel[1]); + + // Error check that the core stop states are >= the quad stop state + FAPI_ASSERT( (l_coreStopLevel[0] >= l_quadStopLevel) && (l_coreStopLevel[1] >= l_quadStopLevel), + fapi2::P9_QUERY_STOP_STATE_INCONSISTENT() + .set_QSSHSRC(l_quadStopLevel) + .set_C0SSHSRC(l_coreStopLevel[0]) + .set_C1SSHSRC(l_coreStopLevel[1]), + "ERROR: Stop States are inconsistent Q(%d) C0(%d) C1(%d)", + l_quadStopLevel, l_coreStopLevel[0], l_coreStopLevel[1]); + + + //---------------------------------------------------------------------------------- + // Based on the stop state history registers, + // Set the attributes for the L2, L3 scanable and scomable + //---------------------------------------------------------------------------------- + + // STOP1 - NAP + // VSU, ISU are clocked off + if (l_coreStopLevel[0] >= 1) + { + l_stop_attrs.c0_exec_hasclocks = 0; + } + + if (l_coreStopLevel[1] >= 1) + { + l_stop_attrs.c1_exec_hasclocks = 0; + } + + // STOP2 - Fast Sleep + // VSU, ISU are clocked off + // IFU, LSU are clocked off + // PC, Core EPS are clocked off + if (l_coreStopLevel[0] >= 2) + { + l_stop_attrs.c0_pc_hasclocks = 0; + } + + if (l_coreStopLevel[1] >= 2) + { + l_stop_attrs.c1_pc_hasclocks = 0; + } + + // STOP4 - Deep Sleep (special exception for stop 9 - lab use only) + // VSU, ISU are powered off + // IFU, LSU are powered off + // PC, Core EPS are powered off + if (l_coreStopLevel[0] >= 4 && l_coreStopLevel[0] != 9) + { + l_stop_attrs.c0_haspower = 0; + } + + if (l_coreStopLevel[1] >= 4 && l_coreStopLevel[1] != 9) + { + l_stop_attrs.c1_haspower = 0; + } + + + // STOP8 - Half Quad Deep Sleep + // VSU, ISU are powered off + // IFU, LSU are powered off + // PC, Core EPS are powered off + // L20-EX0 is clocked off if both cores are >= 8 + // L20-EX1 is clocked off if both cores are >= 8 + if (l_quadStopLevel >= 8) + { + + // The FAPI_ASSERT above ensures both cores are >= the quad stop state + l_stop_attrs.l2_hasclocks = 0; + } + + // STOP9 - Fast Winkle (lab use only) + // Both cores and cache are clocked off + if (l_quadStopLevel >= 9) + { + l_stop_attrs.l3_hasclocks = 0; + } + + // STOP11 - Deep Winkle + // Both cores and cache are powered off + if (l_quadStopLevel >= 11) + { + l_stop_attrs.l2_haspower = 0; + l_stop_attrs.l3_haspower = 0; + } + + //---------------------------------------------------------------------------------- + // Read clock status and pfet_sense_disabled to confirm stop state history is accurate + //---------------------------------------------------------------------------------- + + // Read voltage state to make sure pfets are enabled. + FAPI_DBG(" Read QPPM PFETSENSE"); + FAPI_TRY(fapi2::getScom(l_eq_target, EQ_PPM_PFSNS, l_qpfetsense), "Error reading data from QPPM PFSNS"); + + // Get the status of each PFSNS in each configured CPPM. + // Initialize variables as disabled (bits 1 (VDD) and 3 (VCS)) for partial good readiness + l_cpfetsense[0].flush<0>().insertFromRight<0, 4>(0x5); + l_cpfetsense[1].flush<0>().insertFromRight<0, 4>(0x5); + + for (auto l_core_chplt : l_coreChiplets) + { + // Fetch the position of the Core target + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, l_core_chplt, l_chpltNumber), + "ERROR: Failed to get the position of the Core:0x%08X", + l_core_chplt); + + FAPI_DBG(" Read CPPM PFETSENSE for core %d", l_chpltNumber); + //In case a core is deconfigured, figure out if this is the odd or even core and write the appropriate array + uint32_t l_pos = l_chpltNumber % 2; + + FAPI_TRY(fapi2::getScom(l_core_chplt, C_PPM_PFSNS, l_cpfetsense[l_pos]), "Error reading data from CPPM SSHSRC"); + + } + + // Extract out the disabled bits + l_qpfetsense.extractToRight(l_clk_pfet.vdd_pfet_disable_quad, 1, 1); + l_qpfetsense.extractToRight(l_clk_pfet.vcs_pfet_disable_quad, 3, 1); + + l_cpfetsense[0].extractToRight(l_clk_pfet.vdd_pfet_disable_core[0], 1, 1); + l_cpfetsense[1].extractToRight(l_clk_pfet.vdd_pfet_disable_core[1], 1, 1); + + + // Read clocks running registers + + // Determine if this is an odd or even EX for checking EX clock state + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, i_ex_target, l_chpltNumber), + "ERROR: Failed to get the position of the EX:0x%08X", + i_ex_target); + + l_exPos = l_chpltNumber % 2; + + FAPI_TRY(fapi2::getScom(l_eq_target, EQ_CLOCK_STAT_SL, l_data64), "Error reading data from EQ_CLOCK_STAT_SL"); + + + l_data64.extractToRight(l_clk_pfet.l2_hasclocks, eq_clk_l2_pos[l_exPos], 1); + l_data64.extractToRight(l_clk_pfet.l3_hasclocks, eq_clk_l3_pos[l_exPos], 1); + + for (auto l_core_chplt : l_coreChiplets) + { + // Fetch the position of the Core target + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, l_core_chplt, l_chpltNumber), + "ERROR: Failed to get the position of the Core:0x%08X", + l_core_chplt); + + FAPI_DBG(" Read Core EPS clock status for core %d", l_chpltNumber); + //In case a core is deconfigured, figure out if this is the odd or even core and write the appropriate array + uint32_t l_pos = l_chpltNumber % 2; + + FAPI_TRY(fapi2::getScom(l_core_chplt, C_CLOCK_STAT_SL, l_data64), "Error reading data from C_CLOCK_STAT_SL"); + + l_data64.extractToRight(l_clk_pfet.c_exec_hasclocks[l_pos], 6, 1); + l_data64.extractToRight(l_clk_pfet.c_pc_hasclocks[l_pos], 5, 1); + + } + + FAPI_DBG("Comparing Stop State vs Actual HW settings"); + FAPI_DBG("C0_EXEC_HASCLOCKS ATTR(%d) HW(%d)", l_stop_attrs.c0_exec_hasclocks, l_clk_pfet.c_exec_hasclocks[0]); + FAPI_DBG("C1_EXEC_HASCLOCKS ATTR(%d) HW(%d)", l_stop_attrs.c1_exec_hasclocks, l_clk_pfet.c_exec_hasclocks[1]); + + FAPI_DBG("C0_PC_HASCLOCKS ATTR(%d) HW(%d)", l_stop_attrs.c0_pc_hasclocks, l_clk_pfet.c_pc_hasclocks[0]); + FAPI_DBG("C1_PC_HASCLOCKS ATTR(%d) HW(%d)", l_stop_attrs.c1_pc_hasclocks, l_clk_pfet.c_pc_hasclocks[1]); + + FAPI_DBG("L2_HASCLOCKS ATTR(%d) HW(%d)", l_stop_attrs.l2_hasclocks, l_clk_pfet.l2_hasclocks); + FAPI_DBG("L3_HASCLOCKS ATTR(%d) HW(%d)", l_stop_attrs.l3_hasclocks, l_clk_pfet.l3_hasclocks); + + + + FAPI_DBG("C0_HASPOWER ATTR(%d) HW(%d)", l_stop_attrs.c0_haspower, l_clk_pfet.c0_haspower()); + FAPI_DBG("C1_HASPOWER ATTR(%d) HW(%d)", l_stop_attrs.c1_haspower, l_clk_pfet.c1_haspower()); + + FAPI_DBG("L2_HASPOWER ATTR(%d) HW(%d)", l_stop_attrs.l2_haspower, l_clk_pfet.l2_haspower()); + FAPI_DBG("L3_HASPOWER ATTR(%d) HW(%d)", l_stop_attrs.l3_haspower, l_clk_pfet.l3_haspower()); + + //---------------------------------------------------------------------------------- + // Compare Hardware status vs stop state status. If there is a mismatch, the HW value overrides the stop state + //---------------------------------------------------------------------------------- + + compare_ss_hw("C0_exec_HASCLOCKS", l_clk_pfet.c_exec_hasclocks[0], l_stop_attrs.c0_exec_hasclocks); + compare_ss_hw("C1_exec_HASCLOCKS", l_clk_pfet.c_exec_hasclocks[1], l_stop_attrs.c1_exec_hasclocks); + compare_ss_hw("C0_pc_HASCLOCKS", l_clk_pfet.c_pc_hasclocks[0], l_stop_attrs.c0_pc_hasclocks); + compare_ss_hw("C1_pc_HASCLOCKS", l_clk_pfet.c_pc_hasclocks[1], l_stop_attrs.c1_pc_hasclocks); + compare_ss_hw("L2_HASCLOCKS", l_clk_pfet.l2_hasclocks, l_stop_attrs.l2_hasclocks); + compare_ss_hw("L3_HASCLOCKS", l_clk_pfet.l3_hasclocks, l_stop_attrs.l3_hasclocks); + + compare_ss_hw("C0_HASPOWER", l_clk_pfet.c0_haspower(), l_stop_attrs.c0_haspower); + compare_ss_hw("C1_HASPOWER", l_clk_pfet.c1_haspower(), l_stop_attrs.c1_haspower); + compare_ss_hw("L2_HASPOWER", l_clk_pfet.l2_haspower(), l_stop_attrs.l2_haspower); + compare_ss_hw("L3_HASPOWER", l_clk_pfet.l3_haspower(), l_stop_attrs.l3_haspower); + - // Is Scomable attributes - FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_L2_IS_SCOMABLE, i_ex_target, l_data8)); - FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_L3_IS_SCOMABLE, i_ex_target, l_data8)); - FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_C0_EXEC_IS_SCOMABLE, i_ex_target, l_data8)); - FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_C1_EXEC_IS_SCOMABLE, i_ex_target, l_data8)); - FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_C0_PC_IS_SCOMABLE, i_ex_target, l_data8)); - FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_C1_PC_IS_SCOMABLE, i_ex_target, l_data8)); + //---------------------------------------------------------------------------------- + // Set the Attributes + //---------------------------------------------------------------------------------- + FAPI_DBG("Setting attributes\n"); + // HASCLOCKS attributes (scomable) + FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_L2_HASCLOCKS, i_ex_target, l_stop_attrs.l2_hasclocks)); + FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_L3_HASCLOCKS, i_ex_target, l_stop_attrs.l3_hasclocks)); + FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_C0_EXEC_HASCLOCKS, i_ex_target, l_stop_attrs.c0_exec_hasclocks)); + FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_C1_EXEC_HASCLOCKS, i_ex_target, l_stop_attrs.c1_exec_hasclocks)); + FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_C0_PC_HASCLOCKS, i_ex_target, l_stop_attrs.c0_pc_hasclocks)); + FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_C1_PC_HASCLOCKS, i_ex_target, l_stop_attrs.c1_pc_hasclocks)); - // Is Scanable attributes - FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_L2_IS_SCANABLE, i_ex_target, l_data8)); - FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_L3_IS_SCANABLE, i_ex_target, l_data8)); - FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_C0_IS_SCANABLE, i_ex_target, l_data8)); - FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_C1_IS_SCANABLE, i_ex_target, l_data8)); + // HASPOWER attributes (scanable) + FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_L2_HASPOWER, i_ex_target, l_stop_attrs.l2_haspower)); + FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_L3_HASPOWER, i_ex_target, l_stop_attrs.l3_haspower)); + FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_C0_HASPOWER, i_ex_target, l_stop_attrs.c0_haspower)); + FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_C1_HASPOWER, i_ex_target, l_stop_attrs.c1_haspower)); fapi_try_exit: FAPI_INF("< p9_query_stop_state..."); -- cgit v1.2.1