diff --git a/hw/opentitan/ot_otp_engine.c b/hw/opentitan/ot_otp_engine.c index 9ffcccfb83568..7ae0657af0ca4 100644 --- a/hw/opentitan/ot_otp_engine.c +++ b/hw/opentitan/ot_otp_engine.c @@ -57,8 +57,12 @@ #define OT_OTP_HW_CLOCK QEMU_CLOCK_VIRTUAL_RT /* the following delays are arbitrary for now */ -#define DAI_DIGEST_DELAY_NS 50000u /* 50us */ -#define LCI_PROG_SCHED_NS 1000u /* 1us*/ +#define DAI_DIGEST_DELAY_NS 50000 /* 50us */ +#define LCI_PROG_SCHED_NS 1000 /* 1us */ + +/* Use a timer with a small delay instead of a BH for reliability */ +#define DIGEST_DECOUPLE_DELAY_NS 100 /* 100 ns */ +#define ENTROPY_RESCHEDULE_DELAY_NS 100 /* 100 ns */ /* The size of keys used for OTP scrambling */ #define OTP_SCRAMBLING_KEY_WIDTH 128u @@ -203,7 +207,7 @@ struct OtOTPScrmblKeyInit_ { }; struct OtOTPKeyGen_ { - QEMUBH *entropy_bh; + QEMUTimer *request_entropy; OtPresentState *present; OtPrngState *prng; OtFifo32 entropy_buf; @@ -1622,7 +1626,8 @@ static void ot_otp_engine_dai_complete(void *opaque) break; case OT_OTP_DAI_DIG_WAIT: g_assert(s->dai->partition >= 0); - qemu_bh_schedule(s->dai->digest_bh); + int64_t now = qemu_clock_get_ns(OT_VIRTUAL_CLOCK); + timer_mod(s->dai->digest_write, now + DIGEST_DECOUPLE_DELAY_NS); break; case OT_OTP_DAI_ERROR: break; @@ -1644,7 +1649,7 @@ static const OtOTPHWCfg *ot_otp_engine_get_hw_cfg(const OtOTPIf *dev) return (const OtOTPHWCfg *)s->hw_cfg; } -static void ot_otp_engine_request_entropy_bh(void *opaque) +static void ot_otp_engine_request_entropy(void *opaque) { OtOTPEngineState *s = opaque; @@ -1679,7 +1684,9 @@ ot_otp_engine_keygen_push_entropy(void *opaque, uint32_t bits, bool fips) resched); if (resched && !s->keygen->edn_sched) { - qemu_bh_schedule(s->keygen->entropy_bh); + int64_t now = qemu_clock_get_ns(OT_OTP_HW_CLOCK); + timer_mod(s->keygen->request_entropy, + now + ENTROPY_RESCHEDULE_DELAY_NS); } } @@ -1813,7 +1820,9 @@ static void ot_otp_engine_generate_scrambling_key( if (needed_entropy) { /* some entropy bits have been used, refill the buffer */ - qemu_bh_schedule(s->keygen->entropy_bh); + int64_t now = qemu_clock_get_ns(OT_OTP_HW_CLOCK); + timer_mod(s->keygen->request_entropy, + now + ENTROPY_RESCHEDULE_DELAY_NS); } } @@ -2746,13 +2755,13 @@ static void ot_otp_engine_reset_enter(Object *obj, ResetType type) c->parent_phases.enter(obj, type); } - qemu_bh_cancel(s->dai->digest_bh); qemu_bh_cancel(s->lc_broadcast.bh); qemu_bh_cancel(s->pwr_otp_bh); timer_del(s->dai->delay); + timer_del(s->dai->digest_write); timer_del(s->lci->prog_delay); - qemu_bh_cancel(s->keygen->entropy_bh); + timer_del(s->keygen->request_entropy); s->keygen->edn_sched = false; memset(s->hw_cfg, 0, sizeof(*s->hw_cfg)); @@ -2811,7 +2820,8 @@ static void ot_otp_engine_reset_exit(Object *obj, ResetType type) ot_edn_connect_endpoint(s->edn, s->edn_ep, &ot_otp_engine_keygen_push_entropy, s); - qemu_bh_schedule(s->keygen->entropy_bh); + int64_t now = qemu_clock_get_ns(OT_OTP_HW_CLOCK); + timer_mod(s->keygen->request_entropy, now + ENTROPY_RESCHEDULE_DELAY_NS); } static void ot_otp_engine_realize(DeviceState *dev, Error **errp) @@ -2900,12 +2910,14 @@ static void ot_otp_engine_init(Object *obj) s->dai->delay = timer_new_ns(OT_VIRTUAL_CLOCK, &ot_otp_engine_dai_complete, s); - s->dai->digest_bh = qemu_bh_new(&ot_otp_engine_dai_write_digest, s); + s->dai->digest_write = + timer_new_ns(OT_VIRTUAL_CLOCK, &ot_otp_engine_dai_write_digest, s); s->lci->prog_delay = timer_new_ns(OT_OTP_HW_CLOCK, &ot_otp_engine_lci_write_word, s); + s->keygen->request_entropy = + timer_new_ns(OT_OTP_HW_CLOCK, &ot_otp_engine_request_entropy, s); s->pwr_otp_bh = qemu_bh_new(&ot_otp_engine_pwr_otp_bh, s); s->lc_broadcast.bh = qemu_bh_new(&ot_otp_engine_lc_broadcast_bh, s); - s->keygen->entropy_bh = qemu_bh_new(&ot_otp_engine_request_entropy_bh, s); for (unsigned part_ix = 0; part_ix < s->part_count; part_ix++) { if (!s->part_descs[part_ix].buffered) { diff --git a/include/hw/opentitan/ot_otp_engine.h b/include/hw/opentitan/ot_otp_engine.h index 07ee708ed7a8f..6bfde4c8d300a 100644 --- a/include/hw/opentitan/ot_otp_engine.h +++ b/include/hw/opentitan/ot_otp_engine.h @@ -165,7 +165,7 @@ typedef struct { typedef struct OtOTPDAIController { QEMUTimer *delay; /* simulate delayed access completion */ - QEMUBH *digest_bh; /* write computed digest to OTP cell */ + QEMUTimer *digest_write; /* write computed digest to OTP cell */ OtOTPDAIState state; int partition; /* current partition being worked on or -1 */ } OtOTPDAIController;