summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Bendebury <vbendeb@chromium.org>2016-12-27 09:44:53 -0800
committerchrome-bot <chrome-bot@chromium.org>2017-01-05 21:13:12 -0800
commit5659d103a669ada5fd173f7b801ed7b0a1066881 (patch)
tree38af5c4b7ce0619e2c16c53e0a921aa542f0c53d
parenta59b978317cee5acee51b4e09f91e0fb4dffff99 (diff)
downloadchrome-ec-5659d103a669ada5fd173f7b801ed7b0a1066881.tar.gz
cr50: Avoiding nvram commits at startup
This patch eliminates NVMEM commits at system startup, namely between the moment the TPM is reset and the moment the AP is trying to read a PCR (which is an indication of the AP having booted into OS). To avoid losing NVMEM changes in case TPM is reset before PCR Read command is issued, pending changes (if any) are saved before TPM reset is processed. For the same reason TPM reset invocation is being added to the hard reboot path; this will kick in when there is a restart after cr50 firmware update. BRANCH=none BUG=chrome-os-partner:59873 TEST=with instrumented coreboot/depthcharge observed the following execution times for various TPM command issued at startup command 0x144, 15203 us command 0x14e, 11814 us command 0x182, 12461 us command 0x182, 12456 us command 0x138, 11503 us command 0x138, 11512 us command 0x14e, 14648 us command 0x14e, 12597 us command 0x121, 11353 us which totals 113 ms and shaves more than 200 ms off the boot time. Change-Id: Ic52309291fdb9c3ede96e0ad015ad9fc076bddc5 Signed-off-by: Vadim Bendebury <vbendeb@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/424063 Reviewed-by: Aaron Durbin <adurbin@chromium.org> Reviewed-by: Andrey Pronin <apronin@chromium.org>
-rw-r--r--board/cr50/board.c14
-rw-r--r--common/nvmem.c32
-rw-r--r--common/tpm_registers.c22
-rw-r--r--include/nvmem.h9
4 files changed, 72 insertions, 5 deletions
diff --git a/board/cr50/board.c b/board/cr50/board.c
index ab3f959a62..229f4ab1f0 100644
--- a/board/cr50/board.c
+++ b/board/cr50/board.c
@@ -403,11 +403,17 @@ void sys_rst_asserted(enum gpio_signal signal)
return;
}
- if (reboot_request_posted)
+ if (reboot_request_posted) {
+ /*
+ * Reset TPM and wait to completion to make sure nvmem is
+ * committed before reboot.
+ */
+ tpm_reset(1, 0);
system_reset(SYSTEM_RESET_HARD); /* This will never return. */
-
- /* Re-initialize the TPM software state */
- tpm_reset(0, 0);
+ } else {
+ /* Reset TPM, no need to wait for completion. */
+ tpm_reset(0, 0);
+ }
}
void assert_sys_rst(void)
diff --git a/common/nvmem.c b/common/nvmem.c
index ffdb78bb2d..a93852191c 100644
--- a/common/nvmem.c
+++ b/common/nvmem.c
@@ -45,6 +45,9 @@ struct nvmem_cache {
struct nvmem_cache cache;
+static uint8_t commits_enabled;
+static uint8_t commits_skipped;
+
/* NvMem error state */
static int nvmem_error_state;
/* Flag to track if an Nv write/move is not completed */
@@ -375,6 +378,9 @@ int nvmem_init(void)
}
CPRINTS("Active NVram partition set to %d", nvmem_act_partition);
+ commits_enabled = 1;
+ commits_skipped = 0;
+
return EC_SUCCESS;
}
@@ -510,6 +516,26 @@ int nvmem_move(uint32_t src_offset, uint32_t dest_offset, uint32_t size,
return EC_SUCCESS;
}
+void nvmem_enable_commits(void)
+{
+ if (commits_enabled)
+ return;
+
+ commits_enabled = 1;
+ if (!commits_skipped)
+ return;
+
+ CPRINTS("Committing NVMEM changes.");
+ nvmem_commit();
+ commits_skipped = 0;
+}
+
+void nvmem_disable_commits(void)
+{
+ commits_enabled = 0;
+ commits_skipped = 0;
+}
+
int nvmem_commit(void)
{
int nvmem_offset;
@@ -517,6 +543,12 @@ int nvmem_commit(void)
uint16_t version;
struct nvmem_partition *p_part;
+ if (!commits_enabled) {
+ commits_skipped = 1;
+ CPRINTS("Skipping commit");
+ return EC_SUCCESS;
+ }
+
/* Ensure that all writes/moves prior to commit call succeeded */
if (nvmem_write_error) {
CPRINTS("NvMem: Write Error, commit abandoned");
diff --git a/common/tpm_registers.c b/common/tpm_registers.c
index 62e4414a52..9c5bb4a3b0 100644
--- a/common/tpm_registers.c
+++ b/common/tpm_registers.c
@@ -730,6 +730,14 @@ static void tpm_reset_now(int wipe_first)
* reset, this is the place to do it.
*/
+ /*
+ * If TPM was reset while commits were disabled, save whatever changes
+ * might have accumulated.
+ */
+ nvmem_enable_commits();
+
+ /* Prevent NVRAM commits until further notice. */
+ nvmem_disable_commits();
/* Re-initialize our registers */
tpm_init();
@@ -793,8 +801,20 @@ void tpm_task(void)
* TODO(vbendeb): revisit this when
* crosbug.com/p/55667 has been addressed.
*/
- if (command_code == TPM2_PCR_Read)
+ if (command_code == TPM2_PCR_Read) {
system_process_retry_counter();
+ /*
+ * The AP issuing a PCR Read command is
+ * considered an indication of the boot
+ * process being finished.
+ *
+ * There is no need to speed up TPM operations
+ * any more, pending NVMEM changes should be
+ * committed and future NVMEM commits should
+ * not be postponed.
+ */
+ nvmem_enable_commits();
+ }
#ifdef CONFIG_EXTENSION_COMMAND
if (!IS_CUSTOM_CODE(command_code))
#endif
diff --git a/include/nvmem.h b/include/nvmem.h
index 740c845d9d..730870345a 100644
--- a/include/nvmem.h
+++ b/include/nvmem.h
@@ -177,4 +177,13 @@ int nvmem_setup(uint8_t version);
void nvmem_compute_sha(uint8_t *p_buf, int num_bytes, uint8_t *p_sha,
int sha_len);
+/*
+ * Temporarily stopping NVMEM commits could be beneficial. One use case is
+ * when TPM operations need to be sped up.
+ *
+ * Both below functions should be called from the same task.
+ */
+void nvmem_enable_commits(void);
+void nvmem_disable_commits(void);
+
#endif /* __CROS_EC_NVMEM_UTILS_H */