git: e23ad9c4ba2d - main - tpm: Fix entropy harvesting logic

From: Kornel Dulęba <kd_at_FreeBSD.org>
Date: Fri, 02 Sep 2022 11:19:45 UTC
The branch main has been updated by kd:

URL: https://cgit.FreeBSD.org/src/commit/?id=e23ad9c4ba2d2fd235fc3dc988ca422ef4e7ca3b

commit e23ad9c4ba2d2fd235fc3dc988ca422ef4e7ca3b
Author:     Kornel Dulęba <kd@FreeBSD.org>
AuthorDate: 2022-09-02 11:07:03 +0000
Commit:     Kornel Dulęba <kd@FreeBSD.org>
CommitDate: 2022-09-02 11:09:41 +0000

    tpm: Fix entropy harvesting logic
    
    Use a taskqueue instead of a callout.
    Callout functions mustn't sleep, where as the TPM driver
    uses a sx lock in order to serialize accesses to the device.
    Since the entropy harvesting feature is not enabled by default,
    this commit should not bring any functional changes to the GENERIC
    kernel.
    
    Approved by:    mw(mentor)
    Sponsored by:   Stormshield
    Obtained from:  Semihalf
    MFC after:      1 week
    Differential Revision:  https://reviews.freebsd.org/D36412
---
 sys/dev/tpm/tpm20.c | 24 +++++++++++++-----------
 sys/dev/tpm/tpm20.h |  4 ++--
 2 files changed, 15 insertions(+), 13 deletions(-)

diff --git a/sys/dev/tpm/tpm20.c b/sys/dev/tpm/tpm20.c
index 68a30cfb51dd..3f444176732c 100644
--- a/sys/dev/tpm/tpm20.c
+++ b/sys/dev/tpm/tpm20.c
@@ -39,13 +39,13 @@ __FBSDID("$FreeBSD$");
  * we don't want to execute this too often
  * as the chip is likely to be used by others too.
  */
-#define TPM_HARVEST_INTERVAL 10000000
+#define TPM_HARVEST_INTERVAL 10
 
 MALLOC_DEFINE(M_TPM20, "tpm_buffer", "buffer for tpm 2.0 driver");
 
 static void tpm20_discard_buffer(void *arg);
 #ifdef TPM_HARVEST
-static void tpm20_harvest(void *arg);
+static void tpm20_harvest(void *arg, int unused);
 #endif
 static int  tpm20_save_state(device_t dev, bool suspend);
 
@@ -192,11 +192,6 @@ tpm20_init(struct tpm_sc *sc)
 
 	cv_init(&sc->buf_cv, "TPM buffer cv");
 	callout_init(&sc->discard_buffer_callout, 1);
-#ifdef TPM_HARVEST
-	sc->harvest_ticks = TPM_HARVEST_INTERVAL / tick;
-	callout_init(&sc->harvest_callout, 1);
-	callout_reset(&sc->harvest_callout, 0, tpm20_harvest, sc);
-#endif
 	sc->pending_data_length = 0;
 
 	make_dev_args_init(&args);
@@ -209,6 +204,12 @@ tpm20_init(struct tpm_sc *sc)
 	if (result != 0)
 		tpm20_release(sc);
 
+#ifdef TPM_HARVEST
+	TIMEOUT_TASK_INIT(taskqueue_thread, &sc->harvest_task, 0,
+	    tpm20_harvest, sc);
+	taskqueue_enqueue_timeout(taskqueue_thread, &sc->harvest_task, 0);
+#endif
+
 	return (result);
 
 }
@@ -218,7 +219,8 @@ tpm20_release(struct tpm_sc *sc)
 {
 
 #ifdef TPM_HARVEST
-	callout_drain(&sc->harvest_callout);
+	if (device_is_attached(sc->dev))
+		taskqueue_drain_timeout(taskqueue_thread, &sc->harvest_task);
 #endif
 
 	if (sc->buf != NULL)
@@ -243,13 +245,12 @@ tpm20_shutdown(device_t dev)
 }
 
 #ifdef TPM_HARVEST
-
 /*
  * Get TPM_HARVEST_SIZE random bytes and add them
  * into system entropy pool.
  */
 static void
-tpm20_harvest(void *arg)
+tpm20_harvest(void *arg, int unused)
 {
 	struct tpm_sc *sc;
 	unsigned char entropy[TPM_HARVEST_SIZE];
@@ -290,7 +291,8 @@ tpm20_harvest(void *arg)
 	if (entropy_size > 0)
 		random_harvest_queue(entropy, entropy_size, RANDOM_PURE_TPM);
 
-	callout_reset(&sc->harvest_callout, sc->harvest_ticks, tpm20_harvest, sc);
+	taskqueue_enqueue_timeout(taskqueue_thread, &sc->harvest_task,
+	    hz * TPM_HARVEST_INTERVAL);
 }
 #endif	/* TPM_HARVEST */
 
diff --git a/sys/dev/tpm/tpm20.h b/sys/dev/tpm/tpm20.h
index 6911ca0cb6fe..bda4987120b0 100644
--- a/sys/dev/tpm/tpm20.h
+++ b/sys/dev/tpm/tpm20.h
@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/module.h>
 #include <sys/rman.h>
 #include <sys/sx.h>
+#include <sys/taskqueue.h>
 #include <sys/uio.h>
 
 #include <machine/bus.h>
@@ -125,8 +126,7 @@ struct tpm_sc {
 
 	struct callout 	discard_buffer_callout;
 #ifdef TPM_HARVEST
-	struct callout 	harvest_callout;
-	int		harvest_ticks;
+	struct timeout_task 	harvest_task;
 #endif
 
 	int		(*transmit)(struct tpm_sc *, size_t);