summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMary Ruthven <mruthven@chromium.org>2021-04-16 22:30:14 +0000
committerCommit Bot <commit-bot@chromium.org>2021-05-11 17:59:33 +0000
commitf42ae66a8149e367f963db17e371122d4546bed4 (patch)
tree2f9f20f9f9d555068e10f5159a58e3f550371a08
parentafdc6bf6cefd4afa83b68967d34a512ac02f6544 (diff)
downloadchrome-ec-stabilize-13971.B-cr50_stab.tar.gz
cr50: debounce successive TPM reset pulses (take two)stabilize-13971.B-cr50_stabstabilize-13970.B-cr50_stab
Some platforms generate more than one pulse when resetting, many Intel SOCs generate two pulses, some other chips could go even higher. TPM reset on Cr50 is processed asynchronously, repetitive pulses result in multiple reset processing cycles.In case pulses are coming too soon one after another this could cause some race conditions. Let's ignore repetitive reset pulses unless there has been an attempt by the host to read a register (which is usually the very first action of the AP when booting up). Clear reset_in_progress when the TPM is stopped to ensure they aren't set at the same time. TPM stop disables tpm communication until the TPM is reset. reset_in_progress blocks resetting the tpm until there's tpm communication. We need to ensure these aren't both set at the same time otherwise the system will get into a state where it rejects tpm resets and tpm communication forever. This fixes the ccd open issue from take one where the tpm would stay disabled after opening ccd because cr50 rejected the tpm resets that would clear if_stop. BUG=b:164130916 TEST=observed that only one reset is happening on an Octopus device, while there are two pulses present on the PLT_RST_L line. Verified proper reboot multiple times in a row. use rma_auth to open ccd. Verify subsequent tpm resets reset the TPM and don't say reset already in progress. Change-Id: I62717bf3f0e9bc6d9090122e5b15d13c8f4825e5 Signed-off-by: Mary Ruthven <mruthven@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2832434 Reviewed-by: Vadim Bendebury <vbendeb@chromium.org>
-rw-r--r--common/tpm_registers.c15
1 files changed, 10 insertions, 5 deletions
diff --git a/common/tpm_registers.c b/common/tpm_registers.c
index fdbe771dec..db974f05b9 100644
--- a/common/tpm_registers.c
+++ b/common/tpm_registers.c
@@ -436,9 +436,6 @@ void tpm_register_put(uint32_t regaddr, const uint8_t *data, uint32_t data_size)
{
uint32_t i;
- if (reset_in_progress)
- return;
-
CPRINTF("%s(0x%03x, %d,", __func__, regaddr, data_size);
for (i = 0; i < data_size && i < 4; i++)
CPRINTF(" %02x", data[i]);
@@ -515,6 +512,8 @@ void tpm_register_get(uint32_t regaddr, uint8_t *dest, uint32_t data_size)
static uint32_t last_sts;
static uint32_t checked_sts;
+ reset_in_progress = 0;
+
if (regaddr != TPM_STS) {
CPRINTF("%s(0x%06x, %d)\n", __func__, regaddr, data_size);
checked_sts = 0;
@@ -899,8 +898,6 @@ static void tpm_reset_now(int wipe_first)
*/
hook_call_deferred(&reinstate_nvmem_commits_data, 3 * SECOND);
- reset_in_progress = 0;
-
if_start();
}
@@ -916,6 +913,14 @@ void tpm_stop(void)
/* Stop the TPM interface if it has been initialized. */
if (if_stop)
if_stop();
+ /*
+ * tpm_stop stops tpm communication until the tpm is reset.
+ * reset_in_progress blocks tpm resets until there's tpm communication.
+ * If reset_in_progress is 1 when the tpm is stopped, the system will
+ * not be able to clear either.
+ * Clear reset in progress to ensure that doesn't happen.
+ */
+ reset_in_progress = 0;
}
void tpm_task(void *u)