coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
telemetry.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #include <console/console.h>
4 #include <intelblocks/cse.h>
5 #include <timestamp.h>
6 
7 #define MSEC_TO_USEC(x) (x * 1000)
8 
9 static void cbmem_inject_telemetry_data(void)
10 {
11  struct cse_boot_perf_rsp cse_perf_data;
12  s64 ts[NUM_CSE_BOOT_PERF_DATA] = {0};
13  s64 current_time, start_stamp;
14  int zero_point_idx = 0;
15 
16  /*
17  * 1. Each TS holds the time elapsed between the "Zero-Point" till the TS itself
18  * happened.
19  * 2. In case CSME did not hit some of the TS in the latest boot flow that value of
20  * these TS will be 0x00000000.
21  * 3. In case of error, TS value will be set to 0xFFFFFFFF.
22  * 4. All other TS values will be relative to the zero point. The API caller should
23  * normalize the TS values to the zero-point value.
24  */
25  if (!cse_get_boot_performance_data(&cse_perf_data))
26  return;
27 
28  current_time = timestamp_get();
29 
30  for (unsigned int i = 0; i < NUM_CSE_BOOT_PERF_DATA; i++) {
31 
32  if (cse_perf_data.timestamp[i] == 0xffffffff) {
33  printk(BIOS_ERR, "%s: CSME timestamps invalid\n", __func__);
34  return;
35  }
36 
37  ts[i] = (s64)MSEC_TO_USEC(cse_perf_data.timestamp[i]) *
39  }
40 
41  /* Find zero-point */
42  for (unsigned int i = 0; i < NUM_CSE_BOOT_PERF_DATA; i++) {
43  if (cse_perf_data.timestamp[i] != 0) {
44  zero_point_idx = i;
45  break;
46  }
47  }
48 
49  /* Normalize TS values to zero-point */
50  for (unsigned int i = zero_point_idx + 1; i < NUM_CSE_BOOT_PERF_DATA; i++) {
51 
52  if (ts[i] && ts[i] < ts[zero_point_idx]) {
53  printk(BIOS_ERR, "%s: CSME timestamps invalid,"
54  " wraparound detected\n", __func__);
55  return;
56  }
57 
58  if (ts[i])
59  ts[i] -= ts[zero_point_idx];
60  }
61 
62  /* Inject CSME timestamps into the coreboot timestamp table */
63  start_stamp = current_time - ts[PERF_DATA_CSME_GET_PERF_RESPONSE];
64 
65  timestamp_add(TS_ME_ROM_START, start_stamp);
69  start_stamp + ts[PERF_DATA_CSME_POLL_FOR_PMC_PPS_START]);
71  start_stamp + ts[PERF_DATA_CSME_HOST_BOOT_PREP_DONE]);
73  start_stamp + ts[PERF_DATA_PMC_SENT_CRDA]);
74 }
75 
77 {
78  /* If CSE is already hidden then accessing CSE registers should be avoided */
79  if (!is_cse_enabled()) {
80  printk(BIOS_DEBUG, "CSE is disabled, not sending `Get Boot Perf` message\n");
81  return;
82  }
83 
85 }
int timestamp_tick_freq_mhz(void)
Definition: timestamp.c:11
bool is_cse_enabled(void)
Definition: cse.c:640
#define printk(level,...)
Definition: stdlib.h:16
@ PERF_DATA_CSME_POLL_FOR_PMC_PPS_START
Definition: cse.h:229
@ PERF_DATA_CSME_RBE_BOOT_STALL_DONE_TO_PMC
Definition: cse.h:226
@ PERF_DATA_CSME_GET_PERF_RESPONSE
Definition: cse.h:312
@ PERF_DATA_CSME_HOST_BOOT_PREP_DONE
Definition: cse.h:238
@ PERF_DATA_PMC_SENT_CRDA
Definition: cse.h:265
#define NUM_CSE_BOOT_PERF_DATA
Definition: cse.h:67
bool cse_get_boot_performance_data(struct cse_boot_perf_rsp *boot_perf_rsp)
Definition: cse_lite.c:133
void timestamp_add(enum timestamp_id id, int64_t ts_time)
Definition: timestamp.c:120
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
#define BIOS_ERR
BIOS_ERR - System in incomplete state.
Definition: loglevel.h:72
int64_t s64
Definition: stdint.h:53
uint32_t timestamp[NUM_CSE_BOOT_PERF_DATA]
Definition: cse.h:326
#define MSEC_TO_USEC(x)
Definition: telemetry.c:7
static void cbmem_inject_telemetry_data(void)
Definition: telemetry.c:9
void cse_get_telemetry_data(void)
Definition: telemetry.c:76
#define timestamp_get()
Workaround for guard combination above.
Definition: timestamp.h:52
@ TS_ME_ICC_CONFIG_START
@ TS_ME_HOST_BOOT_PREP_END
@ TS_ME_BOOT_STALL_END
@ TS_ME_ROM_START
@ TS_ME_RECEIVED_CRDA_FROM_PMC