Skip to content

Commit db6f460

Browse files
committed
[ot] hw/opentitan: ot_otp_engine: Replace digest BH with a timer
From testing, it seems that the use of Bottom Halves on hosts under higher processing loads (where QEMU is more often pre-empted) can produce inconsistent / slow results. Timers with a short timeout provide the same decoupling functionality as the BH but with more consistency and expedience. This could be especially problematic for SW which expects digest writes to be processed within a certain time. If handling of the BH was deferred long enough, then enough guest code could be processed for it to look like e.g. 10 ms had passed, exceeding common SW timeouts. This could be seen happening occasionally under high processing loads. Signed-off-by: Alex Jones <alex.jones@lowrisc.org>
1 parent 41b4ca0 commit db6f460

File tree

2 files changed

+11
-6
lines changed

2 files changed

+11
-6
lines changed

hw/opentitan/ot_otp_engine.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,11 @@
5757
#define OT_OTP_HW_CLOCK QEMU_CLOCK_VIRTUAL_RT
5858

5959
/* the following delays are arbitrary for now */
60-
#define DAI_DIGEST_DELAY_NS 50000u /* 50us */
61-
#define LCI_PROG_SCHED_NS 1000u /* 1us*/
60+
#define DAI_DIGEST_DELAY_NS 50000 /* 50us */
61+
#define LCI_PROG_SCHED_NS 1000 /* 1us */
62+
63+
/* Use a timer with a small delay instead of a BH for reliability */
64+
#define DIGEST_DECOUPLE_DELAY_NS 100 /* 100 ns */
6265

6366
/* The size of keys used for OTP scrambling */
6467
#define OTP_SCRAMBLING_KEY_WIDTH 128u
@@ -1622,7 +1625,8 @@ static void ot_otp_engine_dai_complete(void *opaque)
16221625
break;
16231626
case OT_OTP_DAI_DIG_WAIT:
16241627
g_assert(s->dai->partition >= 0);
1625-
qemu_bh_schedule(s->dai->digest_bh);
1628+
int64_t now = qemu_clock_get_ns(OT_VIRTUAL_CLOCK);
1629+
timer_mod(s->dai->digest_write, now + DIGEST_DECOUPLE_DELAY_NS);
16261630
break;
16271631
case OT_OTP_DAI_ERROR:
16281632
break;
@@ -2746,11 +2750,11 @@ static void ot_otp_engine_reset_enter(Object *obj, ResetType type)
27462750
c->parent_phases.enter(obj, type);
27472751
}
27482752

2749-
qemu_bh_cancel(s->dai->digest_bh);
27502753
qemu_bh_cancel(s->lc_broadcast.bh);
27512754
qemu_bh_cancel(s->pwr_otp_bh);
27522755

27532756
timer_del(s->dai->delay);
2757+
timer_del(s->dai->digest_write);
27542758
timer_del(s->lci->prog_delay);
27552759
qemu_bh_cancel(s->keygen->entropy_bh);
27562760
s->keygen->edn_sched = false;
@@ -2900,7 +2904,8 @@ static void ot_otp_engine_init(Object *obj)
29002904

29012905
s->dai->delay =
29022906
timer_new_ns(OT_VIRTUAL_CLOCK, &ot_otp_engine_dai_complete, s);
2903-
s->dai->digest_bh = qemu_bh_new(&ot_otp_engine_dai_write_digest, s);
2907+
s->dai->digest_write =
2908+
timer_new_ns(OT_VIRTUAL_CLOCK, &ot_otp_engine_dai_write_digest, s);
29042909
s->lci->prog_delay =
29052910
timer_new_ns(OT_OTP_HW_CLOCK, &ot_otp_engine_lci_write_word, s);
29062911
s->pwr_otp_bh = qemu_bh_new(&ot_otp_engine_pwr_otp_bh, s);

include/hw/opentitan/ot_otp_engine.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ typedef struct {
165165

166166
typedef struct OtOTPDAIController {
167167
QEMUTimer *delay; /* simulate delayed access completion */
168-
QEMUBH *digest_bh; /* write computed digest to OTP cell */
168+
QEMUTimer *digest_write; /* write computed digest to OTP cell */
169169
OtOTPDAIState state;
170170
int partition; /* current partition being worked on or -1 */
171171
} OtOTPDAIController;

0 commit comments

Comments
 (0)