diff options
author | Mary Ruthven <mruthven@chromium.org> | 2021-04-16 22:30:14 +0000 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2021-05-11 17:59:33 +0000 |
commit | f42ae66a8149e367f963db17e371122d4546bed4 (patch) | |
tree | 2f9f20f9f9d555068e10f5159a58e3f550371a08 | |
parent | afdc6bf6cefd4afa83b68967d34a512ac02f6544 (diff) | |
download | chrome-ec-f42ae66a8149e367f963db17e371122d4546bed4.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.c | 15 |
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) |