aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKangheui Won <khwon@chromium.org>2020-09-17 17:04:12 +1000
committerAaron Durbin <adurbin@chromium.org>2020-11-02 22:17:37 +0000
commit1464b0edeac0581af837f90680f0bf05364a8b2f (patch)
treee5c226e2e2f2e2e55c527197ee473488a6ea7692
parent9f7df5c18a426947e173277a294537d7534eef48 (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.c63
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);
}