From 860672e9879e52820d453e3bc41d151116facb1a Mon Sep 17 00:00:00 2001 From: Bora Guvendik Date: Sun, 26 Sep 2021 17:25:48 -0700 Subject: [PATCH] soc/intel/alderlake: Inject CSE TS into CBMEM timestamp table Get boot performance timestamps from CSE and inject them into CBMEM timestamp table after normalizing to the zero-point value. Although consumer CSE sku also supports this feature, it was validated on CSE Lite sku only. BUG=b:182575295 TEST=Able to see TS elapse prior to IA reset on Brya/Redrix 990:CSME ROM started execution 0 944:CSE sent 'Boot Stall Done' to PMC 88,000 945:CSE started to handle ICC configuration 88,000 (0) 946:CSE sent 'Host BIOS Prep Done' to PMC 90,000 (2,000) 947:CSE received 'CPU Reset Done Ack sent' from PMC 282,000 (192,000) 0:1st timestamp 330,857 (48,857) 11:start of bootblock 341,811 (10,953) 12:end of bootblock 349,299 (7,487) Signed-off-by: Bora Guvendik Change-Id: Idcdbb69538ca2977cd97ce1ef9b211ff6510a3f8 Reviewed-on: https://review.coreboot.org/c/coreboot/+/59507 Tested-by: build bot (Jenkins) Reviewed-by: Tim Wawrzynczak --- src/soc/intel/alderlake/romstage/romstage.c | 4 + src/soc/intel/common/block/cse/Kconfig | 7 ++ src/soc/intel/common/block/cse/Makefile.inc | 1 + src/soc/intel/common/block/cse/telemetry.c | 74 +++++++++++++++++++ .../common/block/include/intelblocks/cse.h | 6 ++ 5 files changed, 92 insertions(+) create mode 100644 src/soc/intel/common/block/cse/telemetry.c 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