From 7a2778ea9c85a385193b46c4258996d53e5ea960 Mon Sep 17 00:00:00 2001 From: Vadim Bendebury Date: Wed, 8 May 2019 09:02:29 -0700 Subject: g: improve trng error handling We want to be able to track TRNG stalls happening in the field. This patch adds a log message to report detected TRNG stalls. The code detecting the stall is being modified to monitor a different status bit as per chip designer recommendation. A console command allowing to test TRNG is being added, compiled in only if TEST_TRNG is defined. BRANCH=cr50, cr50-mp BUG=b:27646393 TEST=compiled the test command in, ran the command rand 10000000 several times, observed reasonable stats and no stall reports. Change-Id: Idcf83ff2c41e23f601b8da8c46fa4d4d1cde0270 Signed-off-by: Vadim Bendebury Reviewed-on: https://chromium-review.googlesource.com/1601470 Legacy-Commit-Queue: Commit Bot Reviewed-by: Andrey Pronin --- chip/g/trng.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++- include/flash_log.h | 1 + 2 files changed, 70 insertions(+), 1 deletion(-) diff --git a/chip/g/trng.c b/chip/g/trng.c index f715a1f833..69e4ce1d87 100644 --- a/chip/g/trng.c +++ b/chip/g/trng.c @@ -3,6 +3,8 @@ * found in the LICENSE file. */ +#include "common.h" +#include "flash_log.h" #include "init_chip.h" #include "registers.h" #include "trng.h" @@ -34,9 +36,12 @@ void init_trng(void) uint32_t rand(void) { while (GREAD(TRNG, EMPTY)) { - if (GREAD_FIELD(TRNG, FSM_STATE, FSM_TIMEOUT)) { + if (GREAD_FIELD(TRNG, FSM_STATE, FSM_IDLE)) { /* TRNG timed out, restart */ GWRITE(TRNG, STOP_WORK, 1); +#if !defined(SECTION_IS_RO) && defined(CONFIG_FLASH_LOG) + flash_log_add_event(FE_LOG_TRNG_STALL, 0, NULL); +#endif GWRITE(TRNG, GO_EVENT, 1); } } @@ -64,3 +69,66 @@ void rand_bytes(void *buffer, size_t len) ((random_togo-- - 1) * 8); } } + +#if !defined(SECTION_IS_RO) && defined(TEST_TRNG) +#include "console.h" +#include "watchdog.h" + +static uint32_t histogram[256]; +static int command_rand(int argc, char **argv) +{ + int count = 1000; /* Default number of cycles. */ + struct pair { + uint32_t value; + uint32_t count; + }; + struct pair min; + struct pair max; + + if (argc == 2) + count = strtoi(argv[1], NULL, 10); + + memset(histogram, 0, sizeof(histogram)); + ccprintf("Retrieving %d random words.\n", count); + while (count-- > 0) { + uint32_t rvalue; + int size; + + rvalue = rand(); + for (size = 0; size < sizeof(rvalue); size++) + histogram[((uint8_t *)&rvalue)[size]]++; + + if (!(count % 10000)) + watchdog_reload(); + } + + min.count = ~0; + max.count = 0; + for (count = 0; count < ARRAY_SIZE(histogram); count++) { + if (histogram[count] > max.count) { + max.count = histogram[count]; + max.value = count; + continue; + } + if (histogram[count] >= min.count) + continue; + + min.count = histogram[count]; + min.value = count; + } + + ccprintf("min %d(%d), max %d(%d)", min.count, min.value, + max.count, max.value); + + for (count = 0; count < ARRAY_SIZE(histogram); count++) { + if (!(count % 8)) { + ccprintf("\n"); + cflush(); + } + ccprintf(" %6d", histogram[count]); + } + ccprintf("\n"); + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(rand, command_rand, NULL, NULL); +#endif /* !defined(SECTION_IS_RO) && defined(TEST_TRNG) */ diff --git a/include/flash_log.h b/include/flash_log.h index ee56226be6..3e2dca8c2c 100644 --- a/include/flash_log.h +++ b/include/flash_log.h @@ -19,6 +19,7 @@ enum flash_event_type { FE_LOG_LOCKS = 4, /* A single byte, lock failures counter. */ FE_LOG_NVMEM = 5, /* NVMEM failure, variable structure. */ FE_LOG_TPM_WIPE_ERROR = 6, /* Failed to wipe the TPM */ + FE_LOG_TRNG_STALL = 7, /* Stall while retrieving a random number. */ /* * Fixed padding value makes it easier to parse log space -- cgit v1.2.1