From 3c83843e111ece30d3dfb5143d5e6aed6164d587 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sat, 11 Feb 2023 15:07:00 +0000 Subject: [PATCH] [rng] Check for several functioning RTC interrupts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 74222cd ("[rng] Check for functioning RTC interrupt") added a check that the RTC is capable of generating interrupts via the legacy PIC, since this mechanism appears to be broken in some Hyper-V virtual machines. Experimentation shows that the RTC is sometimes capable of generating a single interrupt, but will then generate no subsequent interrupts. This currently causes rtc_entropy_check() to falsely detect that the entropy gathering mechanism is functional. Fix by checking for several RTC interrupts before declaring that it is a functional entropy source. Reported-by: Andreas Hammarskjöld Signed-off-by: Michael Brown --- src/arch/x86/interface/pcbios/rtc_entropy.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/arch/x86/interface/pcbios/rtc_entropy.c b/src/arch/x86/interface/pcbios/rtc_entropy.c index e0c175685..c400d8a78 100644 --- a/src/arch/x86/interface/pcbios/rtc_entropy.c +++ b/src/arch/x86/interface/pcbios/rtc_entropy.c @@ -42,6 +42,9 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); /** Maximum time to wait for an RTC interrupt, in milliseconds */ #define RTC_MAX_WAIT_MS 100 +/** Number of RTC interrupts to check for */ +#define RTC_CHECK_COUNT 3 + /** RTC interrupt handler */ extern void rtc_isr ( void ); @@ -145,6 +148,7 @@ static void rtc_disable_int ( void ) { * @ret rc Return status code */ static int rtc_entropy_check ( void ) { + unsigned int count = 0; unsigned int i; /* Check that RTC interrupts are working */ @@ -158,14 +162,18 @@ static int rtc_entropy_check ( void ) { "cli\n\t" ); /* Check for RTC interrupt flag */ - if ( rtc_flag ) - return 0; + if ( rtc_flag ) { + rtc_flag = 0; + if ( ++count >= RTC_CHECK_COUNT ) + return 0; + } /* Delay */ mdelay ( 1 ); } - DBGC ( &rtc_flag, "RTC timed out waiting for interrupt\n" ); + DBGC ( &rtc_flag, "RTC timed out waiting for interrupt %d/%d\n", + ( count + 1 ), RTC_CHECK_COUNT ); return -ETIMEDOUT; }