blob: b92975fb1382fefc504b878f09573fd3d4de9686 [file] [log] [blame]
Angel Pons118a9c72020-04-02 23:48:34 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Vadim Bendebury6f72d692011-09-21 16:12:39 -07002
Aaron Durbin1936f6c2015-07-03 17:04:21 -05003#include <assert.h>
Vadim Bendebury6f72d692011-09-21 16:12:39 -07004#include <stdint.h>
5#include <console/console.h>
6#include <cbmem.h>
Aaron Durbin1936f6c2015-07-03 17:04:21 -05007#include <symbols.h>
Aaron Durbin2daadf82015-05-01 16:48:54 -05008#include <timer.h>
Vadim Bendebury6f72d692011-09-21 16:12:39 -07009#include <timestamp.h>
Kyösti Mälkki5a5c8862014-01-26 14:41:54 +020010#include <smp/node.h>
Vadim Bendebury6f72d692011-09-21 16:12:39 -070011
Raul E Rangelb3e02202018-05-11 11:08:08 -060012#define MAX_TIMESTAMPS 192
Vadim Bendebury6f72d692011-09-21 16:12:39 -070013
Kyösti Mälkki8b936892019-09-12 13:45:15 +030014/* This points to the active timestamp_table and can change within a stage
Kyösti Mälkki3dd23a52019-08-22 15:06:50 +030015 as CBMEM comes available. */
Arthur Heymans1a711632019-11-20 20:38:29 +010016static struct timestamp_table *glob_ts_table;
Aaron Durbin1936f6c2015-07-03 17:04:21 -050017
Kyösti Mälkki3c559e72019-09-07 13:25:47 +030018static void timestamp_cache_init(struct timestamp_table *ts_cache,
Aaron Durbin1936f6c2015-07-03 17:04:21 -050019 uint64_t base)
20{
Kyösti Mälkki3c559e72019-09-07 13:25:47 +030021 ts_cache->num_entries = 0;
Kyösti Mälkki3c559e72019-09-07 13:25:47 +030022 ts_cache->base_time = base;
Kyösti Mälkki8b936892019-09-12 13:45:15 +030023 ts_cache->max_entries = (REGION_SIZE(timestamp) -
24 offsetof(struct timestamp_table, entries))
25 / sizeof(struct timestamp_entry);
Aaron Durbin1936f6c2015-07-03 17:04:21 -050026}
27
Kyösti Mälkki3c559e72019-09-07 13:25:47 +030028static struct timestamp_table *timestamp_cache_get(void)
Aaron Durbin1936f6c2015-07-03 17:04:21 -050029{
Kyösti Mälkki3c559e72019-09-07 13:25:47 +030030 struct timestamp_table *ts_cache = NULL;
Aaron Durbin1936f6c2015-07-03 17:04:21 -050031
Kyösti Mälkki8b936892019-09-12 13:45:15 +030032 if (!ENV_ROMSTAGE_OR_BEFORE)
33 return NULL;
34
35 if (REGION_SIZE(timestamp) < sizeof(*ts_cache)) {
36 BUG();
37 } else {
Kyösti Mälkki3dd23a52019-08-22 15:06:50 +030038 ts_cache = (void *)_timestamp;
Aaron Durbin1936f6c2015-07-03 17:04:21 -050039 }
40
Aaron Durbin1936f6c2015-07-03 17:04:21 -050041 return ts_cache;
42}
43
44static struct timestamp_table *timestamp_alloc_cbmem_table(void)
Vadim Bendebury6f72d692011-09-21 16:12:39 -070045{
Lee Leahyb2d834a2017-03-08 16:52:22 -080046 struct timestamp_table *tst;
Vadim Bendebury6f72d692011-09-21 16:12:39 -070047
48 tst = cbmem_add(CBMEM_ID_TIMESTAMP,
49 sizeof(struct timestamp_table) +
50 MAX_TIMESTAMPS * sizeof(struct timestamp_entry));
51
Kyösti Mälkkie0344172015-05-26 06:23:02 +030052 if (!tst)
Aaron Durbin1936f6c2015-07-03 17:04:21 -050053 return NULL;
Vadim Bendebury6f72d692011-09-21 16:12:39 -070054
Aaron Durbin1936f6c2015-07-03 17:04:21 -050055 tst->base_time = 0;
Vadim Bendebury6f72d692011-09-21 16:12:39 -070056 tst->max_entries = MAX_TIMESTAMPS;
57 tst->num_entries = 0;
Kyösti Mälkkib766b1c2013-09-07 17:26:08 +030058
Aaron Durbin1936f6c2015-07-03 17:04:21 -050059 return tst;
Vadim Bendebury6f72d692011-09-21 16:12:39 -070060}
61
Aaron Durbin2daadf82015-05-01 16:48:54 -050062/* Determine if one should proceed into timestamp code. This is for protecting
63 * systems that have multiple processors running in romstage -- namely AMD
64 * based x86 platforms. */
65static int timestamp_should_run(void)
66{
Subrata Banik42c44c22019-05-15 20:27:04 +053067 /*
68 * Only check boot_cpu() in other stages than
69 * ENV_PAYLOAD_LOADER on x86.
70 */
Kyösti Mälkki7336f972020-06-08 06:05:03 +030071 if ((!ENV_PAYLOAD_LOADER && ENV_X86) && !boot_cpu())
Aaron Durbin2daadf82015-05-01 16:48:54 -050072 return 0;
73
74 return 1;
75}
76
Aaron Durbin1936f6c2015-07-03 17:04:21 -050077static struct timestamp_table *timestamp_table_get(void)
Vadim Bendebury6f72d692011-09-21 16:12:39 -070078{
Arthur Heymans1a711632019-11-20 20:38:29 +010079 if (glob_ts_table)
80 return glob_ts_table;
Kyösti Mälkkib766b1c2013-09-07 17:26:08 +030081
Arthur Heymans1a711632019-11-20 20:38:29 +010082 glob_ts_table = timestamp_cache_get();
Aaron Durbin1936f6c2015-07-03 17:04:21 -050083
Arthur Heymans1a711632019-11-20 20:38:29 +010084 return glob_ts_table;
Aaron Durbin1936f6c2015-07-03 17:04:21 -050085}
86
Kyösti Mälkki3dd23a52019-08-22 15:06:50 +030087static void timestamp_table_set(struct timestamp_table *ts)
88{
Arthur Heymans1a711632019-11-20 20:38:29 +010089 glob_ts_table = ts;
Kyösti Mälkki3dd23a52019-08-22 15:06:50 +030090}
91
Martin Rothb22bbe22018-03-07 15:32:16 -070092static const char *timestamp_name(enum timestamp_id id)
93{
94 int i;
95
96 for (i = 0; i < ARRAY_SIZE(timestamp_ids); i++) {
97 if (timestamp_ids[i].id == id)
98 return timestamp_ids[i].name;
99 }
100
101 return "Unknown timestamp ID";
102}
103
Aaron Durbin1936f6c2015-07-03 17:04:21 -0500104static void timestamp_add_table_entry(struct timestamp_table *ts_table,
Bora Guvendikbf73c492021-11-22 16:03:39 -0800105 enum timestamp_id id, int64_t ts_time)
Aaron Durbin1936f6c2015-07-03 17:04:21 -0500106{
107 struct timestamp_entry *tse;
108
Ben Gardnerf5fd4c92015-11-20 13:25:25 -0600109 if (ts_table->num_entries >= ts_table->max_entries)
Kyösti Mälkkib766b1c2013-09-07 17:26:08 +0300110 return;
Vadim Bendebury6f72d692011-09-21 16:12:39 -0700111
112 tse = &ts_table->entries[ts_table->num_entries++];
113 tse->entry_id = id;
Kyösti Mälkkid548edd2020-01-09 08:41:46 +0200114 tse->entry_stamp = ts_time;
Ben Gardnerf5fd4c92015-11-20 13:25:25 -0600115
116 if (ts_table->num_entries == ts_table->max_entries)
Julius Wernere9665952022-01-21 17:06:20 -0800117 printk(BIOS_ERR, "Timestamp table full\n");
Vadim Bendebury6f72d692011-09-21 16:12:39 -0700118}
119
Bora Guvendikbf73c492021-11-22 16:03:39 -0800120void timestamp_add(enum timestamp_id id, int64_t ts_time)
Aaron Durbin1936f6c2015-07-03 17:04:21 -0500121{
122 struct timestamp_table *ts_table;
123
Kyösti Mälkki187e4c42019-02-20 17:38:45 +0200124 if (!timestamp_should_run())
125 return;
126
Aaron Durbin1936f6c2015-07-03 17:04:21 -0500127 ts_table = timestamp_table_get();
128
129 if (!ts_table) {
Julius Wernere9665952022-01-21 17:06:20 -0800130 printk(BIOS_ERR, "No timestamp table found\n");
Aaron Durbin1936f6c2015-07-03 17:04:21 -0500131 return;
132 }
133
Kyösti Mälkkid548edd2020-01-09 08:41:46 +0200134 ts_time -= ts_table->base_time;
Aaron Durbin1936f6c2015-07-03 17:04:21 -0500135 timestamp_add_table_entry(ts_table, id, ts_time);
Kyösti Mälkki8b93cb72020-01-09 08:41:46 +0200136
137 if (CONFIG(TIMESTAMPS_ON_CONSOLE))
Bora Guvendikbf73c492021-11-22 16:03:39 -0800138 printk(BIOS_INFO, "Timestamp - %s: %lld\n", timestamp_name(id), ts_time);
Aaron Durbin1936f6c2015-07-03 17:04:21 -0500139}
140
Vadim Bendebury6f72d692011-09-21 16:12:39 -0700141void timestamp_add_now(enum timestamp_id id)
142{
Stefan Reinauer3a6550d2013-08-01 13:31:44 -0700143 timestamp_add(id, timestamp_get());
Vadim Bendebury6f72d692011-09-21 16:12:39 -0700144}
Stefan Reinauer4221a192012-10-15 15:23:20 -0700145
Stefan Reinauer3a6550d2013-08-01 13:31:44 -0700146void timestamp_init(uint64_t base)
Kyösti Mälkkib766b1c2013-09-07 17:26:08 +0300147{
Kyösti Mälkki3c559e72019-09-07 13:25:47 +0300148 struct timestamp_table *ts_cache;
Aaron Durbin1936f6c2015-07-03 17:04:21 -0500149
Kyösti Mälkki3dd23a52019-08-22 15:06:50 +0300150 assert(ENV_ROMSTAGE_OR_BEFORE);
151
Aaron Durbin2daadf82015-05-01 16:48:54 -0500152 if (!timestamp_should_run())
Kyösti Mälkkif56ff902013-09-08 13:10:28 +0300153 return;
154
Aaron Durbin1936f6c2015-07-03 17:04:21 -0500155 ts_cache = timestamp_cache_get();
Kyösti Mälkkib766b1c2013-09-07 17:26:08 +0300156
Aaron Durbin1936f6c2015-07-03 17:04:21 -0500157 if (!ts_cache) {
Julius Wernere9665952022-01-21 17:06:20 -0800158 printk(BIOS_ERR, "No timestamp cache to init\n");
Kyösti Mälkkib766b1c2013-09-07 17:26:08 +0300159 return;
160 }
Kyösti Mälkkib766b1c2013-09-07 17:26:08 +0300161
Aaron Durbin1936f6c2015-07-03 17:04:21 -0500162 timestamp_cache_init(ts_cache, base);
Kyösti Mälkki3c559e72019-09-07 13:25:47 +0300163 timestamp_table_set(ts_cache);
Kyösti Mälkkib766b1c2013-09-07 17:26:08 +0300164}
165
Kyösti Mälkki72e634f2019-09-05 18:16:25 +0300166static void timestamp_sync_cache_to_cbmem(struct timestamp_table *ts_cbmem_table)
Kyösti Mälkkib766b1c2013-09-07 17:26:08 +0300167{
Aaron Durbin1936f6c2015-07-03 17:04:21 -0500168 uint32_t i;
Aaron Durbin1936f6c2015-07-03 17:04:21 -0500169 struct timestamp_table *ts_cache_table;
Kyösti Mälkki3dd23a52019-08-22 15:06:50 +0300170
171 ts_cache_table = timestamp_table_get();
172 if (!ts_cache_table) {
Julius Wernere9665952022-01-21 17:06:20 -0800173 printk(BIOS_ERR, "No timestamp cache found\n");
Aaron Durbin1936f6c2015-07-03 17:04:21 -0500174 return;
175 }
176
177 /*
178 * There's no need to worry about the base_time fields being out of
Kyösti Mälkki513a1a82018-06-03 12:29:50 +0300179 * sync because only the following configuration is used/supported:
Aaron Durbin1936f6c2015-07-03 17:04:21 -0500180 *
Kyösti Mälkki513a1a82018-06-03 12:29:50 +0300181 * Timestamps get initialized before ramstage, which implies
182 * CBMEM initialization in romstage.
Julius Werner8c093772016-02-09 16:09:15 -0800183 * This requires the board to define a TIMESTAMP() region in its
184 * memlayout.ld (default on x86). The base_time from timestamp_init()
185 * (usually called from bootblock.c on most non-x86 boards) persists
186 * in that region until it gets synced to CBMEM in romstage.
187 * In ramstage, the BSS cache's base_time will be 0 until the second
188 * sync, which will adjust the timestamps in there to the correct
189 * base_time (from CBMEM) with the timestamp_add_table_entry() below.
Aaron Durbin1936f6c2015-07-03 17:04:21 -0500190 *
Julius Werner8c093772016-02-09 16:09:15 -0800191 * If you try to initialize timestamps before ramstage but don't define
192 * a TIMESTAMP region, all operations will fail (safely), and coreboot
Kyösti Mälkkid548edd2020-01-09 08:41:46 +0200193 * will behave as if timestamps collection was disabled.
Aaron Durbin1936f6c2015-07-03 17:04:21 -0500194 */
Kyösti Mälkki3dd23a52019-08-22 15:06:50 +0300195
Kyösti Mälkkid548edd2020-01-09 08:41:46 +0200196 /* Inherit cache base_time. */
197 ts_cbmem_table->base_time = ts_cache_table->base_time;
198
Aaron Durbin1936f6c2015-07-03 17:04:21 -0500199 for (i = 0; i < ts_cache_table->num_entries; i++) {
200 struct timestamp_entry *tse = &ts_cache_table->entries[i];
201 timestamp_add_table_entry(ts_cbmem_table, tse->entry_id,
202 tse->entry_stamp);
203 }
204
Aaron Durbin1936f6c2015-07-03 17:04:21 -0500205 /* Cache no longer required. */
206 ts_cache_table->num_entries = 0;
Kyösti Mälkki3d45c402013-09-07 20:26:36 +0300207}
Kyösti Mälkkicbf5bdf2013-09-10 00:07:21 +0300208
Kyösti Mälkki72e634f2019-09-05 18:16:25 +0300209static void timestamp_reinit(int is_recovery)
210{
211 struct timestamp_table *ts_cbmem_table;
212
213 if (!timestamp_should_run())
214 return;
215
Kyösti Mälkkib6b13c92019-09-12 12:58:50 +0300216 /* First time into romstage we make a clean new table. For platforms that travel
217 through this path on resume, ARCH_X86 S3, timestamps are also reset. */
218 if (ENV_ROMSTAGE) {
Kyösti Mälkki72e634f2019-09-05 18:16:25 +0300219 ts_cbmem_table = timestamp_alloc_cbmem_table();
Kyösti Mälkkib6b13c92019-09-12 12:58:50 +0300220 } else {
221 /* Find existing table in cbmem. */
222 ts_cbmem_table = cbmem_find(CBMEM_ID_TIMESTAMP);
223 }
Kyösti Mälkki72e634f2019-09-05 18:16:25 +0300224
225 if (ts_cbmem_table == NULL) {
Julius Wernere9665952022-01-21 17:06:20 -0800226 printk(BIOS_ERR, "No timestamp table allocated\n");
Kyösti Mälkki72e634f2019-09-05 18:16:25 +0300227 timestamp_table_set(NULL);
228 return;
229 }
230
231 if (ENV_ROMSTAGE)
232 timestamp_sync_cache_to_cbmem(ts_cbmem_table);
233
234 /* Seed the timestamp tick frequency in ENV_PAYLOAD_LOADER. */
235 if (ENV_PAYLOAD_LOADER)
236 ts_cbmem_table->tick_freq_mhz = timestamp_tick_freq_mhz();
237
238 timestamp_table_set(ts_cbmem_table);
239}
240
Kyösti Mälkki806ea08b2017-07-15 20:42:20 +0300241void timestamp_rescale_table(uint16_t N, uint16_t M)
242{
243 uint32_t i;
244 struct timestamp_table *ts_table;
245
246 if (!timestamp_should_run())
247 return;
248
249 if (N == 0 || M == 0)
250 return;
251
252 ts_table = timestamp_table_get();
253
254 /* No timestamp table found */
255 if (ts_table == NULL) {
Julius Wernere9665952022-01-21 17:06:20 -0800256 printk(BIOS_ERR, "No timestamp table found\n");
Kyösti Mälkki806ea08b2017-07-15 20:42:20 +0300257 return;
258 }
259
260 ts_table->base_time /= M;
261 ts_table->base_time *= N;
262 for (i = 0; i < ts_table->num_entries; i++) {
263 struct timestamp_entry *tse = &ts_table->entries[i];
264 tse->entry_stamp /= M;
265 tse->entry_stamp *= N;
266 }
267}
268
Werner Zeh35cceb82017-09-12 07:42:54 +0200269/*
270 * Get the time in microseconds since boot (or more precise: since timestamp
271 * table was initialized).
272 */
273uint32_t get_us_since_boot(void)
274{
275 struct timestamp_table *ts = timestamp_table_get();
276
277 if (ts == NULL || ts->tick_freq_mhz == 0)
278 return 0;
279 return (timestamp_get() - ts->base_time) / ts->tick_freq_mhz;
280}
281
Kyösti Mälkki72e634f2019-09-05 18:16:25 +0300282ROMSTAGE_CBMEM_INIT_HOOK(timestamp_reinit)
283POSTCAR_CBMEM_INIT_HOOK(timestamp_reinit)
284RAMSTAGE_CBMEM_INIT_HOOK(timestamp_reinit)
Aaron Durbin9e80e272015-05-01 16:48:54 -0500285
286/* Provide default timestamp implementation using monotonic timer. */
Aaron Durbin64031672018-04-21 14:45:32 -0600287uint64_t __weak timestamp_get(void)
Aaron Durbin9e80e272015-05-01 16:48:54 -0500288{
289 struct mono_time t1, t2;
290
Julius Wernercd49cce2019-03-05 16:53:33 -0800291 if (!CONFIG(HAVE_MONOTONIC_TIMER))
Aaron Durbin7aafe532015-05-07 11:32:30 -0500292 return 0;
293
Aaron Durbin9e80e272015-05-01 16:48:54 -0500294 mono_time_set_usecs(&t1, 0);
295 timer_monotonic_get(&t2);
296
297 return mono_time_diff_microseconds(&t1, &t2);
298}
Aaron Durbinc49014e2015-08-30 21:19:55 -0500299
300/* Like timestamp_get() above this matches up with microsecond granularity. */
Aaron Durbin64031672018-04-21 14:45:32 -0600301int __weak timestamp_tick_freq_mhz(void)
Aaron Durbinc49014e2015-08-30 21:19:55 -0500302{
303 return 1;
304}