diff options
author | Kangheui Won <khwon@chromium.org> | 2020-09-17 17:04:12 +1000 |
---|---|---|
committer | Aaron Durbin <adurbin@chromium.org> | 2020-11-02 22:17:37 +0000 |
commit | 1464b0edeac0581af837f90680f0bf05364a8b2f (patch) | |
tree | e5c226e2e2f2e2e55c527197ee473488a6ea7692 | |
parent | 9f7df5c18a426947e173277a294537d7534eef48 (diff) |
soc/amd/picasso: pass verstage timestamps to x86
Initialize timestamp table with data from psp_verstage on bootblock.
PSP keeps its own timestamp and pass it in transfer_buffer. However PSP
timestamp and TSC may be out of sync so we can't just merge two tables
without modification.
info->timestamp contains PSP's clock value (in us) when x86 processor
released and base_timestamp contains TSC value when bootblock is
started. The time between x86 release and bootblock entry should be very
short so we can think those two happened at the same time and use them
for sync.
In some cases there will be underflow in timestamp entries but cbmem
utility can handle wrap-over in entries. Few timestamp values including
1st timestamp can be very large but we can still get the time spent on
boot without any problem.
BUG=b:159220781, b:167148121, b:171422583
BRANCH=zork
TEST=boot to kernel, run 'cbmem -t' and check verstage timestamps are
included in the result.
Change-Id: I5e89bb54f478153fb40ba51b5ab61fa20af3b99a
Signed-off-by: Kangheui Won <khwon@chromium.org>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/45059
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
-rw-r--r-- | src/soc/amd/picasso/bootblock/bootblock.c | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/src/soc/amd/picasso/bootblock/bootblock.c b/src/soc/amd/picasso/bootblock/bootblock.c index c715324973..4bff042a91 100644 --- a/src/soc/amd/picasso/bootblock/bootblock.c +++ b/src/soc/amd/picasso/bootblock/bootblock.c @@ -3,6 +3,7 @@ #include <stdint.h> #include <symbols.h> #include <amdblocks/reset.h> +#include <timestamp.h> #include <bootblock_common.h> #include <console/console.h> #include <cpu/x86/cache.h> @@ -10,6 +11,7 @@ #include <cpu/amd/msr.h> #include <cpu/x86/mtrr.h> #include <cpu/amd/mtrr.h> +#include <cpu/x86/tsc.h> #include <pc80/mc146818rtc.h> #include <soc/psp_transfer.h> #include <soc/southbridge.h> @@ -108,12 +110,73 @@ static void write_resume_eip(void) wrmsr(S3_RESUME_EIP_MSR, s3_resume_entry); } +static int transfer_buffer_valid(const struct transfer_info_struct *ptr) +{ + if (ptr->magic_val == TRANSFER_MAGIC_VAL) + return 1; + else + return 0; +} + +static void boot_with_psp_timestamp(uint64_t base_timestamp) +{ + const struct transfer_info_struct *info = (const struct transfer_info_struct *) + (void *)(uintptr_t)_transfer_buffer; + + if (!transfer_buffer_valid(info) || info->timestamp == 0) + return; + + /* + * info->timestamp is PSP's timestamp (in microseconds) + * when x86 processor is released. + */ + uint64_t psp_last_ts = info->timestamp; + + int i; + struct timestamp_table *psp_ts_table = + (struct timestamp_table *)(void *) + ((uintptr_t)_transfer_buffer + info->timestamp_offset); + /* new base_timestamp will be offset for all PSP timestamps. */ + base_timestamp -= psp_last_ts; + + for (i = 0; i < psp_ts_table->num_entries; i++) { + struct timestamp_entry *tse = &psp_ts_table->entries[i]; + /* + * We ignore the time between x86 processor release and bootblock. + * Since timestamp_add subtracts base_time, we first add old base_time + * to make it absolute then add base_timestamp again since + * it'll be a new base_time. + * + * We don't need to convert unit since both PSP and coreboot + * will use 1us granularity. + * + */ + tse->entry_stamp += psp_ts_table->base_time + base_timestamp; + } + + bootblock_main_with_timestamp(base_timestamp, psp_ts_table->entries, + psp_ts_table->num_entries); +} + asmlinkage void bootblock_c_entry(uint64_t base_timestamp) { set_caching(); write_resume_eip(); enable_pci_mmconf(); + /* + * base_timestamp is raw tsc value. We need to divide by tsc_freq_mhz + * when we use micro-seconds granularity for Zork + */ + base_timestamp /= tsc_freq_mhz(); + + if (CONFIG(VBOOT_STARTS_BEFORE_BOOTBLOCK)) + boot_with_psp_timestamp(base_timestamp); + + /* + * if VBOOT_STARTS_BEFORE_BOOTBLOCK is not selected or + * previous step did nothing, proceed with normal bootblock main. + */ bootblock_main_with_basetime(base_timestamp); } |