diff --git a/src/soc/intel/alderlake/romstage/romstage.c b/src/soc/intel/alderlake/romstage/romstage.c index 9720d9e549..45421c810b 100644 --- a/src/soc/intel/alderlake/romstage/romstage.c +++ b/src/soc/intel/alderlake/romstage/romstage.c @@ -142,6 +142,10 @@ void mainboard_romstage_entry(void) timestamp_add_now(TS_CSE_FW_SYNC_END); } + /* Update coreboot timestamp table with CSE timestamps */ + if (CONFIG(SOC_INTEL_CSE_PRE_CPU_RESET_TELEMETRY)) + cse_get_telemetry_data(); + /* * Set low maximum temp threshold value used for dynamic thermal sensor * shutdown consideration. diff --git a/src/soc/intel/common/block/cse/Kconfig b/src/soc/intel/common/block/cse/Kconfig index e30244799e..9621e9ad5f 100644 --- a/src/soc/intel/common/block/cse/Kconfig +++ b/src/soc/intel/common/block/cse/Kconfig @@ -166,6 +166,13 @@ config SOC_INTEL_CSE_LITE_COMPRESS_ME_RW help Enable compression on Intel CSE CBFS RW blob +config SOC_INTEL_CSE_PRE_CPU_RESET_TELEMETRY + def_bool n + depends on SOC_INTEL_CSE_LITE_SKU + help + Mainboard user to select this Kconfig in order to capture pre-cpu + reset boot performance telemetry data. + if STITCH_ME_BIN config CSE_COMPONENTS_PATH diff --git a/src/soc/intel/common/block/cse/Makefile.inc b/src/soc/intel/common/block/cse/Makefile.inc index 472ae9550c..0c307cab7b 100644 --- a/src/soc/intel/common/block/cse/Makefile.inc +++ b/src/soc/intel/common/block/cse/Makefile.inc @@ -6,6 +6,7 @@ ramstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_CSE) += disable_heci.c smm-$(CONFIG_SOC_INTEL_COMMON_BLOCK_CSE) += disable_heci.c ramstage-$(CONFIG_SOC_INTEL_CSE_SET_EOP) += cse_eop.c +romstage-$(CONFIG_SOC_INTEL_CSE_PRE_CPU_RESET_TELEMETRY) += telemetry.c ifeq ($(CONFIG_STITCH_ME_BIN),y) diff --git a/src/soc/intel/common/block/cse/telemetry.c b/src/soc/intel/common/block/cse/telemetry.c new file mode 100644 index 0000000000..544de802d1 --- /dev/null +++ b/src/soc/intel/common/block/cse/telemetry.c @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include +#include +#include + +#define MSEC_TO_USEC(x) (x * 1000) + +void cse_get_telemetry_data(void) +{ + struct cse_boot_perf_rsp cse_perf_data; + s64 ts[NUM_CSE_BOOT_PERF_DATA] = {0}; + s64 current_time, start_stamp; + int zero_point_idx = 0; + + /* + * 1. Each TS holds the time elapsed between the "Zero-Point" till the TS itself + * happened. + * 2. In case CSME did not hit some of the TS in the latest boot flow that value of + * these TS will be 0x00000000. + * 3. In case of error, TS value will be set to 0xFFFFFFFF. + * 4. All other TS values will be relative to the zero point. The API caller should + * normalize the TS values to the zero-point value. + */ + if (!cse_get_boot_performance_data(&cse_perf_data)) + return; + + current_time = timestamp_get(); + + for (unsigned int i = 0; i < NUM_CSE_BOOT_PERF_DATA; i++) { + + if (cse_perf_data.timestamp[i] == 0xffffffff) { + printk(BIOS_ERR, "%s: CSME timestamps invalid\n", __func__); + return; + } + + ts[i] = (s64)MSEC_TO_USEC(cse_perf_data.timestamp[i]) * + timestamp_tick_freq_mhz(); + } + + /* Find zero-point */ + for (unsigned int i = 0; i < NUM_CSE_BOOT_PERF_DATA; i++) { + if (cse_perf_data.timestamp[i] != 0) { + zero_point_idx = i; + break; + } + } + + /* Normalize TS values to zero-point */ + for (unsigned int i = zero_point_idx + 1; i < NUM_CSE_BOOT_PERF_DATA; i++) { + + if (ts[i] && ts[i] < ts[zero_point_idx]) { + printk(BIOS_ERR, "%s: CSME timestamps invalid," + " wraparound detected\n", __func__); + return; + } + + if (ts[i]) + ts[i] -= ts[zero_point_idx]; + } + + /* Inject CSME timestamps into the coreboot timestamp table */ + start_stamp = current_time - ts[PERF_DATA_CSME_GET_PERF_RESPONSE]; + + timestamp_add(TS_ME_ROM_START, start_stamp); + timestamp_add(TS_ME_BOOT_STALL_END, + start_stamp + ts[PERF_DATA_CSME_RBE_BOOT_STALL_DONE_TO_PMC]); + timestamp_add(TS_ME_ICC_CONFIG_START, + start_stamp + ts[PERF_DATA_CSME_POLL_FOR_PMC_PPS_START]); + timestamp_add(TS_ME_HOST_BOOT_PREP_END, + start_stamp + ts[PERF_DATA_CSME_HOST_BOOT_PREP_DONE]); + timestamp_add(TS_ME_RECEIVED_CRDA_FROM_PMC, + start_stamp + ts[PERF_DATA_PMC_SENT_CRDA]); +} diff --git a/src/soc/intel/common/block/include/intelblocks/cse.h b/src/soc/intel/common/block/include/intelblocks/cse.h index f031ad5105..f94fc73ae3 100644 --- a/src/soc/intel/common/block/include/intelblocks/cse.h +++ b/src/soc/intel/common/block/include/intelblocks/cse.h @@ -509,4 +509,10 @@ void cse_send_end_of_post(void); */ void soc_disable_heci1_using_pcr(void); +/* + * Get all the timestamps CSE collected using cse_get_boot_performance_data() and + * insert them into the CBMEM timestamp table. + */ +void cse_get_telemetry_data(void); + #endif // SOC_INTEL_COMMON_CSE_H