From 2fe9ab3dcaa6a7208cb5f92619dbc0f5fd83201f Mon Sep 17 00:00:00 2001 From: Doug Gilbert Date: Wed, 30 Aug 2017 11:49:34 -0500 Subject: Add Droop counter sensors Change-Id: If4c367eaeaaf746619d537d4d8424cf018591563 RTC: 155684 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/45574 Tested-by: FSP CI Jenkins Reviewed-by: Andres A. Lugo-Reyes Reviewed-by: Martha Broyles --- src/occ_gpe0/core_data.c | 101 ++++++++++++++++++++++++++++++----------------- 1 file changed, 64 insertions(+), 37 deletions(-) (limited to 'src/occ_gpe0/core_data.c') diff --git a/src/occ_gpe0/core_data.c b/src/occ_gpe0/core_data.c index 7dcb613..d4346f3 100644 --- a/src/occ_gpe0/core_data.c +++ b/src/occ_gpe0/core_data.c @@ -31,19 +31,25 @@ #include "p9_config.h" #include "ppe42_msr.h" #include "ppe42_scom.h" +#include "cme_register_addresses.h" + +#define CME_VDSR_BASE (CME_SCOM_VDSR & 0x00ffffff) + +// Global variables +uint32_t g_vdm_cache_large_droop_count[MAX_NUM_QUADS]__attribute__((section (".sbss"))); +uint32_t g_vdm_core_small_droop_count[MAX_NUM_CORES]__attribute__((section (".sbss"))); uint32_t get_core_data(uint32_t i_core, CoreData* o_data) { uint32_t rc = 0; - uint32_t size = sizeof(CoreData) / 8; + uint32_t size = sizeof(CoreData) / sizeof(uint64_t); uint64_t* ptr = (uint64_t*)o_data; uint32_t coreSelect = CHIPLET_CORE_ID(i_core); - uint32_t quadSelect = CHIPLET_CACHE_ID((i_core / 4)); - //volatile uint64_t* scom_reg = (uint64_t*)(0); + uint32_t quadSelect = CHIPLET_CACHE_ID((i_core / CORES_PER_QUAD)); uint64_t value64 = 0; - uint32_t i; + uint32_t i,idx; for(i = 0; i < size; ++i) { @@ -51,28 +57,22 @@ uint32_t get_core_data(uint32_t i_core, } // Turn off MCR bit to prevent machine check on error on scom readings bits 1:7 - // rc == 1 resource occupied (see ppe42_scom.h) Action: return with rc - // rc == 2 Core is fenced, offline Action: return with rc + // rc == 1 resource occupied (see ppe42_scom.h) + // rc == 2 Core is fenced, offline // rc == 3 partial good // rc == 4 address error (Can be caused by other device using bus) // rc == 5 clock error // rc == 6 packet error // rc == 7 timeout - // ACTIONS: - // rc 1,2:- mask the machine check, return rc - // 3-7 Leave as machine check (or as it was) uint32_t org_sem = mfmsr() & MSR_SEM; // Clear SIBRC and SIBRCA - // mask off resource occupied/offline errors - will return these) - // SIB rc 3-7 will machine check (unless already masked) - mtmsr((mfmsr() & ~(MSR_SIBRC | MSR_SIBRCA)) - | 0xe8000000); //MASK SIBRC == 1 | SIBRC == 2 | SIBRC == 4 + // mask off SIB errors as machine checks, return rc instead + mtmsr((mfmsr() & ~(MSR_SIBRC | MSR_SIBRCA)) | MSR_SEM); + // DTS dts_sensor_result_reg_t dts_scom_data; - //scom_reg = (uint64_t*)(quadSelect + THERM_DTS_RESULT); - //dts_scom_data.value = *scom_reg; PPE_LVD(quadSelect + THERM_DTS_RESULT, value64); dts_scom_data.value = value64; @@ -80,57 +80,93 @@ uint32_t get_core_data(uint32_t i_core, o_data->dts.cache[0].result = dts_scom_data.half_words.reading[0]; o_data->dts.cache[1].result = dts_scom_data.half_words.reading[1]; - //scom_reg = (uint64_t*)(coreSelect + THERM_DTS_RESULT); - //dts_scom_data.value = *scom_reg; PPE_LVD(coreSelect + THERM_DTS_RESULT, value64); dts_scom_data.value = value64; o_data->dts.core[0].result = dts_scom_data.half_words.reading[0]; o_data->dts.core[1].result = dts_scom_data.half_words.reading[1]; + // DROOP + // Read Droop events. Event bit == 0 indicates event occurred. + // Side effect of read: event bits are reset to 1 (no event) in hw + // Only quad large droop and core small drop events are of interest + PPE_LVD(quadSelect + CME_VDSR_BASE, value64); + + if((value64 & CACHE_VDM_LARGE_DROOP) == 0) + { + ++g_vdm_cache_large_droop_count[i_core / CORES_PER_QUAD]; + } + + idx = (i_core / CORES_PER_QUAD) * CORES_PER_QUAD; + + if((value64 & CORE0_VDM_SMALL_DROOP) == 0) + { + ++g_vdm_core_small_droop_count[idx]; + } + + if((value64 & CORE1_VDM_SMALL_DROOP) == 0) + { + ++g_vdm_core_small_droop_count[idx+1]; + } + + if((value64 & CORE2_VDM_SMALL_DROOP) == 0) + { + ++g_vdm_core_small_droop_count[idx+2]; + } + + if((value64 & CORE3_VDM_SMALL_DROOP) == 0) + { + ++g_vdm_core_small_droop_count[idx+3]; + } + + // return the event status for the requested core and + // corresponding quad. + // Clear the counter for only the droop events returned. + if(g_vdm_cache_large_droop_count[i_core / CORES_PER_QUAD] != 0) + { + o_data->droop.cache_large_event = 1; + g_vdm_cache_large_droop_count[i_core / CORES_PER_QUAD] = 0; + } + + if(g_vdm_core_small_droop_count[i_core] != 0) + { + o_data->droop.core_small_event = 1; + g_vdm_core_small_droop_count[i_core] = 0; + } + + // EMPATH // Send command to select which emmpath counter to read uint64_t empath_scom_data = CORE_RAW_CYCLES; - //scom_reg = (uint64_t*)(coreSelect + PC_OCC_SPRC); - //*scom_reg = empath_scom_data; PPE_STVD(coreSelect + PC_OCC_SPRC, empath_scom_data) - // Read counters. // Counter selected auto increments to the next counter after each read. //CORE_RAW_CYCLES - //scom_reg = (uint64_t*)(coreSelect + PC_OCC_SPRD); - //empath_scom_data = *scom_reg; PPE_LVD(coreSelect + PC_OCC_SPRD, empath_scom_data); o_data->empath.raw_cycles = (uint32_t)empath_scom_data; //CORE_RUN_CYCLES - //empath_scom_data = *scom_reg; PPE_LVD(coreSelect + PC_OCC_SPRD, empath_scom_data); o_data->empath.run_cycles = (uint32_t)empath_scom_data; //CORE_WORKRATE_BUSY - //empath_scom_data = *scom_reg; PPE_LVD(coreSelect + PC_OCC_SPRD, empath_scom_data); o_data->empath.freq_sens_busy = (uint32_t)empath_scom_data; //CORE_WORKRATE_FINISH - //empath_scom_data = *scom_reg; PPE_LVD(coreSelect + PC_OCC_SPRD, empath_scom_data); o_data->empath.freq_sens_finish = (uint32_t)empath_scom_data; //CORE_MEM_HIER_A_LATENCY - // empath_scom_data = *scom_reg; PPE_LVD(coreSelect + PC_OCC_SPRD, empath_scom_data); o_data->empath.mem_latency_a = (uint32_t)empath_scom_data; //CORE_MEM_HIER_B_LATENCY - // empath_scom_data = *scom_reg; PPE_LVD(coreSelect + PC_OCC_SPRD, empath_scom_data); o_data->empath.mem_latency_b = (uint32_t)empath_scom_data; //CORE_MEM_HIER_C_ACCESS - //empath_scom_data = *scom_reg; PPE_LVD(coreSelect + PC_OCC_SPRD, empath_scom_data); o_data->empath.mem_access_c = (uint32_t)empath_scom_data; @@ -139,45 +175,36 @@ uint32_t get_core_data(uint32_t i_core, for( ; thread < EMPATH_CORE_THREADS; ++thread ) { // THREAD_RUN_CYCLES - //empath_scom_data = *scom_reg; PPE_LVD(coreSelect + PC_OCC_SPRD, empath_scom_data); o_data->per_thread[thread].run_cycles = (uint32_t)empath_scom_data; // THREAD_INST_DISP_UTIL - //empath_scom_data = *scom_reg; PPE_LVD(coreSelect + PC_OCC_SPRD, empath_scom_data); o_data->per_thread[thread].dispatch = (uint32_t)empath_scom_data; // THREAD_INST_COMP_UTIL - //empath_scom_data = *scom_reg; PPE_LVD(coreSelect + PC_OCC_SPRD, empath_scom_data); o_data->per_thread[thread].completion = (uint32_t)empath_scom_data; // THREAD_MEM_HEIR_C_ACCESS - //empath_scom_data = *scom_reg; PPE_LVD(coreSelect + PC_OCC_SPRD, empath_scom_data); o_data->per_thread[thread].mem_c = (uint32_t)empath_scom_data; } //IFU_THROTTLE_BLOCK_FETCH - //empath_scom_data = *scom_reg; PPE_LVD(coreSelect + PC_OCC_SPRD, empath_scom_data); o_data->throttle.ifu_throttle = (uint32_t)empath_scom_data; //IFU_THROTTLE_ACTIVE - //empath_scom_data = *scom_reg; PPE_LVD(coreSelect + PC_OCC_SPRD, empath_scom_data); o_data->throttle.ifu_active = (uint32_t)empath_scom_data; //VOLT_DROOP_THROTTLE_ACTIVE - //empath_scom_data = *scom_reg; PPE_LVD(coreSelect + PC_OCC_SPRD, empath_scom_data); o_data->throttle.v_droop = (uint32_t)empath_scom_data; // TOD value - //scom_reg = (uint64_t*)TOD_VALUE_REG; PPE_LVD(TOD_VALUE_REG, empath_scom_data); - //empath_scom_data = *scom_reg; o_data->empath.tod_2mhz = (uint32_t)(empath_scom_data >> 8); //[24..56] // STOP_STATE_HIST_OCC_REG -- cgit v1.2.1