blob: f3dd7ee8198ac80b3cd3126a9c12329f4816bb23 [file] [log] [blame]
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include <console/console.h>
#include <intelblocks/cse.h>
#include <timestamp.h>
#define MSEC_TO_USEC(x) (x * 1000)
static void cbmem_inject_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]);
}
void cse_get_telemetry_data(void)
{
/* If CSE is already hidden then accessing CSE registers should be avoided */
if (!is_cse_enabled()) {
printk(BIOS_DEBUG, "CSE is disabled, not sending `Get Boot Perf` message\n");
return;
}
cbmem_inject_telemetry_data();
}