xref: /aosp_15_r20/external/coreboot/src/soc/intel/common/block/cse/telemetry.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
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 
process_cse_telemetry_data(void)9 static void process_cse_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;
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) != CB_SUCCESS)
26 		return;
27 
28 	current_time = timestamp_get();
29 
30 	for (unsigned int i = 0; i < NUM_CSE_BOOT_PERF_DATA; i++) {
31 		if (cse_perf_data.timestamp[i] == 0xffffffff) {
32 			printk(BIOS_ERR, "%s: CSME timestamps invalid\n", __func__);
33 			return;
34 		}
35 
36 		ts[i] = (s64)MSEC_TO_USEC(cse_perf_data.timestamp[i]) *
37 							timestamp_tick_freq_mhz();
38 	}
39 
40 	/* Find zero-point */
41 	for (unsigned int i = 0; i < NUM_CSE_BOOT_PERF_DATA; i++) {
42 		if (cse_perf_data.timestamp[i] != 0) {
43 			zero_point_idx = i;
44 			break;
45 		}
46 	}
47 
48 	/* Normalize TS values to zero-point */
49 	for (unsigned int i = zero_point_idx + 1; i < NUM_CSE_BOOT_PERF_DATA; i++) {
50 		if (ts[i] && ts[i] < ts[zero_point_idx]) {
51 			printk(BIOS_ERR, "%s: CSME timestamps invalid,"
52 					" wraparound detected\n", __func__);
53 			return;
54 		}
55 
56 		if (ts[i])
57 			ts[i] -= ts[zero_point_idx];
58 	}
59 
60 	/* Inject CSME timestamps into the coreboot timestamp table */
61 	soc_cbmem_inject_telemetry_data(ts, current_time);
62 }
63 
cse_get_telemetry_data(void)64 void cse_get_telemetry_data(void)
65 {
66 	/* If CSE is already hidden then accessing CSE registers should be avoided */
67 	if (!is_cse_enabled()) {
68 		printk(BIOS_DEBUG, "CSE is disabled, not sending `Get Boot Perf` message\n");
69 		return;
70 	}
71 
72 	process_cse_telemetry_data();
73 }
74