From e2f25d638bf4e15e3a875705b142d28db87ab677 Mon Sep 17 00:00:00 2001 From: Emmanuel Blot Date: Wed, 22 Oct 2025 12:51:37 +0200 Subject: [PATCH 01/18] [ot] hw/opentitan: ot_entropy_src: unify EarlGrey and Darjeeling versions - remove deprecated Darjeeling version - rename EarlGrey version as unique entropy src implementation - update machine definitions and dependencies Note that EarlGrey-1.0.0 version uses v2 while Darjeeling master uses v3, so execution of Darjeeling machine is broken for now, till the implementation also supports v3 Signed-off-by: Emmanuel Blot --- hw/opentitan/Kconfig | 6 +- hw/opentitan/meson.build | 3 +- .../{ot_entropy_src_eg.c => ot_entropy_src.c} | 416 ++-- hw/opentitan/ot_entropy_src_dj.c | 1691 ----------------- hw/riscv/Kconfig | 4 +- hw/riscv/ot_darjeeling.c | 48 +- hw/riscv/ot_earlgrey.c | 4 +- .../{ot_entropy_src_dj.h => ot_entropy_src.h} | 12 +- include/hw/opentitan/ot_entropy_src_eg.h | 37 - 9 files changed, 229 insertions(+), 1992 deletions(-) rename hw/opentitan/{ot_entropy_src_eg.c => ot_entropy_src.c} (80%) delete mode 100644 hw/opentitan/ot_entropy_src_dj.c rename include/hw/opentitan/{ot_entropy_src_dj.h => ot_entropy_src.h} (80%) delete mode 100644 include/hw/opentitan/ot_entropy_src_eg.h diff --git a/hw/opentitan/Kconfig b/hw/opentitan/Kconfig index 2dc93fd76fb4..154a7cf49f65 100644 --- a/hw/opentitan/Kconfig +++ b/hw/opentitan/Kconfig @@ -52,11 +52,7 @@ config OT_DMA config OT_EDN bool -config OT_ENTROPY_SRC_EG - select OT_RANDOM_SRC - bool - -config OT_ENTROPY_SRC_DJ +config OT_ENTROPY_SRC select OT_RANDOM_SRC bool diff --git a/hw/opentitan/meson.build b/hw/opentitan/meson.build index 77a612c9e146..75945c30c6a6 100644 --- a/hw/opentitan/meson.build +++ b/hw/opentitan/meson.build @@ -18,8 +18,7 @@ system_ss.add(when: 'CONFIG_OT_DEV_PROXY', if_true: files('ot_dev_proxy.c')) system_ss.add(when: 'CONFIG_OT_DM_TL', if_true: files('ot_dm_tl.c')) system_ss.add(when: 'CONFIG_OT_DMA', if_true: [files('ot_dma.c'), libtomcrypt_dep]) system_ss.add(when: 'CONFIG_OT_EDN', if_true: files('ot_edn.c')) -system_ss.add(when: 'CONFIG_OT_ENTROPY_SRC_DJ', if_true: [files('ot_entropy_src_dj.c'), libtomcrypt_dep]) -system_ss.add(when: 'CONFIG_OT_ENTROPY_SRC_EG', if_true: [files('ot_entropy_src_eg.c'), libtomcrypt_dep]) +system_ss.add(when: 'CONFIG_OT_ENTROPY_SRC', if_true: [files('ot_entropy_src.c'), libtomcrypt_dep]) system_ss.add(when: 'CONFIG_OT_FLASH', if_true: files('ot_flash.c')) system_ss.add(when: 'CONFIG_OT_GPIO_DJ', if_true: files('ot_gpio_dj.c')) system_ss.add(when: 'CONFIG_OT_GPIO_EG', if_true: files('ot_gpio_eg.c')) diff --git a/hw/opentitan/ot_entropy_src_eg.c b/hw/opentitan/ot_entropy_src.c similarity index 80% rename from hw/opentitan/ot_entropy_src_eg.c rename to hw/opentitan/ot_entropy_src.c index 5722ea8782e2..8ea0006a079a 100644 --- a/hw/opentitan/ot_entropy_src_eg.c +++ b/hw/opentitan/ot_entropy_src.c @@ -38,7 +38,7 @@ #include "hw/opentitan/ot_alert.h" #include "hw/opentitan/ot_ast_eg.h" #include "hw/opentitan/ot_common.h" -#include "hw/opentitan/ot_entropy_src_eg.h" +#include "hw/opentitan/ot_entropy_src.h" #include "hw/opentitan/ot_fifo32.h" #include "hw/opentitan/ot_otp.h" #include "hw/opentitan/ot_random_src.h" @@ -329,24 +329,23 @@ static const char *REG_NAMES[REGS_COUNT] = { #define ES_FILL_RATE_NS \ ((NANOSECONDS_PER_SECOND * ES_FILL_BITS) / \ ((uint64_t)OT_AST_EG_RANDOM_4BIT_RATE * 4u)) -#define OT_ENTROPY_SRC_EG_FILL_WORD_COUNT \ - (ES_FILL_BITS / (8u * sizeof(uint32_t))) -#define ES_WORD_COUNT (OT_RANDOM_SRC_WORD_COUNT) -#define ES_SWREAD_FIFO_WORD_COUNT ES_WORD_COUNT -#define ES_FINAL_FIFO_WORD_COUNT (ES_WORD_COUNT * ES_FINAL_FIFO_DEPTH) -#define ES_HEXBUF_SIZE ((8U * 2u + 1u) * ES_WORD_COUNT + 4u) +#define OT_ENTROPY_SRC_FILL_WORD_COUNT (ES_FILL_BITS / (8u * sizeof(uint32_t))) +#define ES_WORD_COUNT (OT_RANDOM_SRC_WORD_COUNT) +#define ES_SWREAD_FIFO_WORD_COUNT ES_WORD_COUNT +#define ES_FINAL_FIFO_WORD_COUNT (ES_WORD_COUNT * ES_FINAL_FIFO_DEPTH) +#define ES_HEXBUF_SIZE ((8U * 2u + 1u) * ES_WORD_COUNT + 4u) /* * see hw/ip/edn/doc/#multiple-edns-in-boot-time-request-mode * reduce initial delay in QEMU since it takes time to manage the entropy */ -#define OT_ENTROPY_SRC_EG_BOOT_DELAY_NS 500000LL /* 500 us */ +#define OT_ENTROPY_SRC_BOOT_DELAY_NS 500000LL /* 500 us */ /* * default delay to pace the entropy src client (CSRNG) when no entropy is * available. A better implementation would compute the remaining time before * the next available entropy packet. */ -#define OT_ENTROPY_SRC_EG_WAIT_DELAY_NS 2000LL /* 2 us */ +#define OT_ENTROPY_SRC_WAIT_DELAY_NS 2000LL /* 2 us */ enum { ALERT_RECOVERABLE, @@ -378,9 +377,9 @@ typedef enum { ENTROPY_SRC_EG_ALERT_STATE, ENTROPY_SRC_EG_ALERT_HANG, ENTROPY_SRC_EG_ERROR, -} OtEntropySrcEgFsmState; +} OtEntropySrcFsmState; -struct OtEntropySrcEgState { +struct OtEntropySrcState { SysBusDevice parent_obj; MemoryRegion mmio; @@ -396,7 +395,7 @@ struct OtEntropySrcEgState { OtFifo32 swread_fifo; OtFifo32 final_fifo; /* output FIFO */ hash_state sha3_state; /* libtomcrypt hash state */ - OtEntropySrcEgFsmState state; + OtEntropySrcFsmState state; unsigned cond_word; /* count of words processed with SHA3 till hash */ unsigned noise_count; /* count of consumed noise words since enabled */ unsigned packet_count; /* count of output packets since enabled */ @@ -406,7 +405,7 @@ struct OtEntropySrcEgState { OtOTPState *otp_ctrl; }; -struct OtEntropySrcEgClass { +struct OtEntropySrcClass { SysBusDeviceClass parent_class; ResettablePhases parent_phases; }; @@ -468,22 +467,22 @@ static const char *STATE_NAMES[] = { #define REG_MB4_IS_FALSE(_s_, _reg_, _fld_) \ (FIELD_EX32((_s_)->regs[R_##_reg_], _reg_, _fld_) == OT_MULTIBITBOOL4_FALSE) -#define xtrace_ot_entropy_src_eg_show_buffer(_msg_, _buf_, _len_) \ - ot_entropy_src_eg_show_buffer(__func__, __LINE__, _msg_, _buf_, _len_) +#define xtrace_ot_entropy_src_show_buffer(_msg_, _buf_, _len_) \ + ot_entropy_src_show_buffer(__func__, __LINE__, _msg_, _buf_, _len_) -static bool ot_entropy_src_eg_is_module_enabled(const OtEntropySrcEgState *s); -static bool ot_entropy_src_eg_is_fips_enabled(const OtEntropySrcEgState *s); -static bool ot_entropy_src_eg_is_hw_route(const OtEntropySrcEgState *s); -static bool ot_entropy_src_eg_is_fips_capable(const OtEntropySrcEgState *s); -static void ot_entropy_src_eg_update_alerts(OtEntropySrcEgState *s); -static void ot_entropy_src_eg_update_filler(OtEntropySrcEgState *s); +static bool ot_entropy_src_is_module_enabled(const OtEntropySrcState *s); +static bool ot_entropy_src_is_fips_enabled(const OtEntropySrcState *s); +static bool ot_entropy_src_is_hw_route(const OtEntropySrcState *s); +static bool ot_entropy_src_is_fips_capable(const OtEntropySrcState *s); +static void ot_entropy_src_update_alerts(OtEntropySrcState *s); +static void ot_entropy_src_update_filler(OtEntropySrcState *s); -static int ot_entropy_src_eg_get_random( +static int ot_entropy_src_get_random( OtRandomSrcIf *dev, uint64_t random[OT_RANDOM_SRC_DWORD_COUNT], bool *fips) { - OtEntropySrcEgState *s = OT_ENTROPY_SRC_EG(dev); + OtEntropySrcState *s = OT_ENTROPY_SRC(dev); - if (!ot_entropy_src_eg_is_module_enabled(s)) { + if (!ot_entropy_src_is_module_enabled(s)) { qemu_log_mask(LOG_GUEST_ERROR, "%s: entropy_src is down\n", __func__); return -1; } @@ -514,9 +513,9 @@ static int ot_entropy_src_eg_get_random( /* computed delay fits into a 31-bit value */ wait_ns = ((int64_t)timer_expire_time_ns(s->scheduler)) - qemu_clock_get_ns(OT_VIRTUAL_CLOCK); - wait_ns = MAX(wait_ns, OT_ENTROPY_SRC_EG_WAIT_DELAY_NS); + wait_ns = MAX(wait_ns, OT_ENTROPY_SRC_WAIT_DELAY_NS); } else { - wait_ns = OT_ENTROPY_SRC_EG_WAIT_DELAY_NS; + wait_ns = OT_ENTROPY_SRC_WAIT_DELAY_NS; } trace_ot_entropy_src_init_ongoing(STATE_NAME(s->state), s->state, (int)wait_ns); @@ -538,14 +537,14 @@ static int ot_entropy_src_eg_get_random( return -1; } - if (!ot_entropy_src_eg_is_hw_route(s)) { + if (!ot_entropy_src_is_hw_route(s)) { qemu_log_mask(LOG_GUEST_ERROR, "%s: HW route not selected\n", __func__); return -1; } if (ot_fifo32_num_used(&s->final_fifo) < ES_WORD_COUNT) { trace_ot_entropy_src_no_entropy(ot_fifo32_num_used(&s->final_fifo)); - return OT_ENTROPY_SRC_EG_WAIT_DELAY_NS; + return OT_ENTROPY_SRC_WAIT_DELAY_NS; } uint32_t *randu32 = (uint32_t *)random; @@ -555,20 +554,20 @@ static int ot_entropy_src_eg_get_random( randu32[pos++] = ot_fifo32_pop(&s->final_fifo); } - bool fips_capable = ot_entropy_src_eg_is_fips_capable(s); + bool fips_capable = ot_entropy_src_is_fips_capable(s); /* note: fips compliancy is only simulated here for now */ *fips = fips_compliant && fips_capable; trace_ot_entropy_src_get_random_fips( - STATE_NAME(s->state), ot_entropy_src_eg_is_fips_enabled(s), + STATE_NAME(s->state), ot_entropy_src_is_fips_enabled(s), REG_MB4_IS_TRUE(s, ENTROPY_CONTROL, ES_ROUTE), REG_MB4_IS_TRUE(s, ENTROPY_CONTROL, ES_TYPE), REG_MB4_IS_FALSE(s, CONF, RNG_BIT_ENABLE), fips_capable, fips_compliant, *fips); if (ot_fifo32_num_used(&s->final_fifo) < ES_WORD_COUNT) { - ot_entropy_src_eg_update_filler(s); + ot_entropy_src_update_filler(s); } return 0; @@ -578,7 +577,7 @@ static int ot_entropy_src_eg_get_random( /* Private implementation */ /* -------------------------------------------------------------------------- */ -static void ot_entropy_src_eg_show_buffer( +static void ot_entropy_src_show_buffer( const char *func, int line, const char *msg, const void *buf, unsigned size) { if (trace_event_get_state(TRACE_OT_ENTROPY_SRC_SHOW_BUFFER) && @@ -606,22 +605,22 @@ static void ot_entropy_src_eg_show_buffer( } } -static bool ot_entropy_src_eg_is_module_enabled(const OtEntropySrcEgState *s) +static bool ot_entropy_src_is_module_enabled(const OtEntropySrcState *s) { return REG_MB4_IS_TRUE(s, MODULE_ENABLE, MODULE_ENABLE); } -static bool ot_entropy_src_eg_is_module_disabled(const OtEntropySrcEgState *s) +static bool ot_entropy_src_is_module_disabled(const OtEntropySrcState *s) { return REG_MB4_IS_FALSE(s, MODULE_ENABLE, MODULE_ENABLE); } -static bool ot_entropy_src_eg_is_fips_enabled(const OtEntropySrcEgState *s) +static bool ot_entropy_src_is_fips_enabled(const OtEntropySrcState *s) { return REG_MB4_IS_TRUE(s, CONF, FIPS_ENABLE); } -static void ot_entropy_src_eg_update_irqs(OtEntropySrcEgState *s) +static void ot_entropy_src_update_irqs(OtEntropySrcState *s) { uint32_t levels = s->regs[R_INTR_STATE] & s->regs[R_INTR_ENABLE]; for (unsigned ix = 0; ix < PARAM_NUM_IRQS; ix++) { @@ -630,48 +629,47 @@ static void ot_entropy_src_eg_update_irqs(OtEntropySrcEgState *s) } static bool -ot_entropy_src_eg_is_final_fifo_slot_available(const OtEntropySrcEgState *s) +ot_entropy_src_is_final_fifo_slot_available(const OtEntropySrcState *s) { return ot_fifo32_num_free(&s->final_fifo) >= ES_WORD_COUNT; } -static bool ot_entropy_src_eg_is_hw_route(const OtEntropySrcEgState *s) +static bool ot_entropy_src_is_hw_route(const OtEntropySrcState *s) { return REG_MB4_IS_FALSE(s, ENTROPY_CONTROL, ES_ROUTE); } -static bool ot_entropy_src_eg_is_fw_route(const OtEntropySrcEgState *s) +static bool ot_entropy_src_is_fw_route(const OtEntropySrcState *s) { return REG_MB4_IS_TRUE(s, ENTROPY_CONTROL, ES_ROUTE); } -static bool ot_entropy_src_eg_is_bypass_mode(const OtEntropySrcEgState *s) +static bool ot_entropy_src_is_bypass_mode(const OtEntropySrcState *s) { - return !ot_entropy_src_eg_is_fips_enabled(s) || - (ot_entropy_src_eg_is_fw_route(s) && + return !ot_entropy_src_is_fips_enabled(s) || + (ot_entropy_src_is_fw_route(s) && REG_MB4_IS_TRUE(s, ENTROPY_CONTROL, ES_TYPE)); } -static bool ot_entropy_src_eg_is_fw_ov_mode(const OtEntropySrcEgState *s) +static bool ot_entropy_src_is_fw_ov_mode(const OtEntropySrcState *s) { return REG_MB4_IS_TRUE(s, FW_OV_CONTROL, FW_OV_MODE); } -static bool -ot_entropy_src_eg_is_fw_ov_entropy_insert(const OtEntropySrcEgState *s) +static bool ot_entropy_src_is_fw_ov_entropy_insert(const OtEntropySrcState *s) { return REG_MB4_IS_TRUE(s, FW_OV_CONTROL, FW_OV_ENTROPY_INSERT); } -static bool ot_entropy_src_eg_is_fips_capable(const OtEntropySrcEgState *s) +static bool ot_entropy_src_is_fips_capable(const OtEntropySrcState *s) { - return ot_entropy_src_eg_is_fips_enabled(s) && + return ot_entropy_src_is_fips_enabled(s) && !(REG_MB4_IS_TRUE(s, ENTROPY_CONTROL, ES_ROUTE) && REG_MB4_IS_TRUE(s, ENTROPY_CONTROL, ES_TYPE)) && REG_MB4_IS_FALSE(s, CONF, RNG_BIT_ENABLE); } -static unsigned ot_alert_get_alert_fail_count(const OtEntropySrcEgState *s) +static unsigned ot_alert_get_alert_fail_count(const OtEntropySrcState *s) { unsigned count; @@ -693,10 +691,10 @@ static unsigned ot_alert_get_alert_fail_count(const OtEntropySrcEgState *s) return count; } -static void ot_entropy_src_eg_change_state_line( - OtEntropySrcEgState *s, OtEntropySrcEgFsmState state, int line) +static void ot_entropy_src_change_state_line( + OtEntropySrcState *s, OtEntropySrcFsmState state, int line) { - OtEntropySrcEgFsmState old_state = s->state; + OtEntropySrcFsmState old_state = s->state; switch (s->state) { case ENTROPY_SRC_EG_ALERT_STATE: @@ -704,7 +702,7 @@ static void ot_entropy_src_eg_change_state_line( break; case ENTROPY_SRC_EG_ALERT_HANG: if ((state == ENTROPY_SRC_EG_IDLE) && - ot_entropy_src_eg_is_module_disabled(s)) { + ot_entropy_src_is_module_disabled(s)) { s->state = state; } break; @@ -721,14 +719,14 @@ static void ot_entropy_src_eg_change_state_line( if (s->state == ENTROPY_SRC_EG_ERROR) { s->regs[R_ERR_CODE] |= R_ERR_CODE_ES_MAIN_SM_ERR_MASK; - ot_entropy_src_eg_update_alerts(s); + ot_entropy_src_update_alerts(s); } } -#define ot_entropy_src_eg_change_state(_s_, _st_) \ - ot_entropy_src_eg_change_state_line(_s_, _st_, __LINE__) +#define ot_entropy_src_change_state(_s_, _st_) \ + ot_entropy_src_change_state_line(_s_, _st_, __LINE__) -static void ot_entropy_src_eg_update_alerts(OtEntropySrcEgState *s) +static void ot_entropy_src_update_alerts(OtEntropySrcState *s) { unsigned alert_threshold = FIELD_EX32(s->regs[R_ALERT_THRESHOLD], ALERT_THRESHOLD, ALERT_THRESHOLD); @@ -749,8 +747,8 @@ static void ot_entropy_src_eg_update_alerts(OtEntropySrcEgState *s) } } -static bool ot_entropy_src_eg_check_multibitboot( - OtEntropySrcEgState *s, uint8_t mbbool, uint32_t alert_bit) +static bool ot_entropy_src_check_multibitboot( + OtEntropySrcState *s, uint8_t mbbool, uint32_t alert_bit) { switch (mbbool) { case OT_MULTIBITBOOL4_TRUE: @@ -761,24 +759,24 @@ static bool ot_entropy_src_eg_check_multibitboot( } s->regs[R_RECOV_ALERT_STS] |= 1u << alert_bit; - ot_entropy_src_eg_update_alerts(s); + ot_entropy_src_update_alerts(s); return false; } -static bool ot_entropy_src_eg_can_consume_entropy(const OtEntropySrcEgState *s) +static bool ot_entropy_src_can_consume_entropy(const OtEntropySrcState *s) { - return ot_entropy_src_eg_is_module_enabled(s) && - !(ot_entropy_src_eg_is_fw_ov_entropy_insert(s) && - !ot_entropy_src_eg_is_fw_ov_mode(s)); + return ot_entropy_src_is_module_enabled(s) && + !(ot_entropy_src_is_fw_ov_entropy_insert(s) && + !ot_entropy_src_is_fw_ov_mode(s)); } -static void ot_entropy_src_eg_update_filler(OtEntropySrcEgState *s) +static void ot_entropy_src_update_filler(OtEntropySrcState *s) { - /* fill granule is OT_ENTROPY_SRC_EG_FILL_WORD_COUNT bits */ + /* fill granule is OT_ENTROPY_SRC_FILL_WORD_COUNT bits */ bool input = - ot_fifo32_num_free(&s->input_fifo) >= OT_ENTROPY_SRC_EG_FILL_WORD_COUNT; + ot_fifo32_num_free(&s->input_fifo) >= OT_ENTROPY_SRC_FILL_WORD_COUNT; bool output = ot_fifo32_num_free(&s->final_fifo) >= ES_WORD_COUNT; - bool process = ot_entropy_src_eg_can_consume_entropy(s); + bool process = ot_entropy_src_can_consume_entropy(s); bool accept_entropy = input && output && process; trace_ot_entropy_src_update_filler(input, output, process, accept_entropy); @@ -802,14 +800,13 @@ static void ot_entropy_src_eg_update_filler(OtEntropySrcEgState *s) } } -static bool -ot_entropy_src_eg_can_condition_entropy(const OtEntropySrcEgState *s) +static bool ot_entropy_src_can_condition_entropy(const OtEntropySrcState *s) { if (!ot_fifo32_is_full(&s->precon_fifo)) { /* room in preconditioner packer */ return true; } - if (ot_entropy_src_eg_is_final_fifo_slot_available(s)) { + if (ot_entropy_src_is_final_fifo_slot_available(s)) { /* room in output FIFO */ return true; } @@ -817,13 +814,13 @@ ot_entropy_src_eg_can_condition_entropy(const OtEntropySrcEgState *s) return false; } -static bool ot_entropy_src_eg_can_bypass_entropy(const OtEntropySrcEgState *s) +static bool ot_entropy_src_can_bypass_entropy(const OtEntropySrcState *s) { if (!ot_fifo32_is_full(&s->bypass_fifo)) { /* room in bypass packer */ return true; } - if (ot_entropy_src_eg_is_final_fifo_slot_available(s)) { + if (ot_entropy_src_is_final_fifo_slot_available(s)) { /* room in output FIFO */ return true; } @@ -831,13 +828,13 @@ static bool ot_entropy_src_eg_can_bypass_entropy(const OtEntropySrcEgState *s) return false; } -static bool ot_entropy_src_eg_push_entropy_to_conditioner( - OtEntropySrcEgState *s, uint32_t word) +static bool +ot_entropy_src_push_entropy_to_conditioner(OtEntropySrcState *s, uint32_t word) { int res; if (s->cond_word == 0) { res = sha3_384_init(&s->sha3_state); - ot_entropy_src_eg_change_state(s, ENTROPY_SRC_EG_SHA3_PREP); + ot_entropy_src_change_state(s, ENTROPY_SRC_EG_SHA3_PREP); g_assert(res == CRYPT_OK); } @@ -849,14 +846,13 @@ static bool ot_entropy_src_eg_push_entropy_to_conditioner( return false; } - ot_entropy_src_eg_change_state(s, ENTROPY_SRC_EG_SHA3_PROCESS); + ot_entropy_src_change_state(s, ENTROPY_SRC_EG_SHA3_PROCESS); uint32_t size; const uint32_t *buf; buf = ot_fifo32_peek_buf(&s->precon_fifo, s->precon_fifo.num, &size); g_assert(size == s->precon_fifo.num); - xtrace_ot_entropy_src_eg_show_buffer("sha3 in", buf, - size * sizeof(uint32_t)); + xtrace_ot_entropy_src_show_buffer("sha3 in", buf, size * sizeof(uint32_t)); res = sha3_process(&s->sha3_state, (const uint8_t *)buf, size * sizeof(uint32_t)); g_assert(res == CRYPT_OK); @@ -866,13 +862,13 @@ static bool ot_entropy_src_eg_push_entropy_to_conditioner( return true; } -static bool ot_entropy_src_eg_can_hash(const OtEntropySrcEgState *s) +static bool ot_entropy_src_can_hash(const OtEntropySrcState *s) { return ot_fifo32_is_empty(&s->precon_fifo) && (s->cond_word >= (2048 / (8u * sizeof(uint32_t)))); } -static void ot_entropy_src_eg_perform_hash(OtEntropySrcEgState *s) +static void ot_entropy_src_perform_hash(OtEntropySrcState *s) { uint32_t hash[OT_RANDOM_SRC_WORD_COUNT]; int res; @@ -880,11 +876,11 @@ static void ot_entropy_src_eg_perform_hash(OtEntropySrcEgState *s) g_assert(res == CRYPT_OK); s->cond_word = 0; - xtrace_ot_entropy_src_eg_show_buffer("sha3 md", hash, - OT_RANDOM_SRC_WORD_COUNT * - sizeof(uint32_t)); + xtrace_ot_entropy_src_show_buffer("sha3 md", hash, + OT_RANDOM_SRC_WORD_COUNT * + sizeof(uint32_t)); - ot_entropy_src_eg_change_state(s, ENTROPY_SRC_EG_SHA3_MSGDONE); + ot_entropy_src_change_state(s, ENTROPY_SRC_EG_SHA3_MSGDONE); for (unsigned ix = 0; ix < OT_RANDOM_SRC_WORD_COUNT; ix++) { g_assert(!ot_fifo32_is_full(&s->final_fifo)); @@ -892,20 +888,20 @@ static void ot_entropy_src_eg_perform_hash(OtEntropySrcEgState *s) } s->packet_count += 1u; - ot_entropy_src_eg_change_state(s, REG_MB4_IS_TRUE(s, FW_OV_SHA3_START, - FW_OV_INSERT_START) ? - ENTROPY_SRC_EG_IDLE : - ENTROPY_SRC_EG_CONT_HT_START); + ot_entropy_src_change_state(s, REG_MB4_IS_TRUE(s, FW_OV_SHA3_START, + FW_OV_INSERT_START) ? + ENTROPY_SRC_EG_IDLE : + ENTROPY_SRC_EG_CONT_HT_START); } static bool -ot_entropy_src_eg_push_bypass_entropy(OtEntropySrcEgState *s, uint32_t word) +ot_entropy_src_push_bypass_entropy(OtEntropySrcState *s, uint32_t word) { g_assert(!ot_fifo32_is_full(&s->bypass_fifo)); ot_fifo32_push(&s->bypass_fifo, word); if (!ot_fifo32_is_full(&s->bypass_fifo)) { - /* need a whole OT_ENTROPY_SRC_EG_PACKET_SIZE_BITS packet to move on */ + /* need a whole OT_ENTROPY_SRC_PACKET_SIZE_BITS packet to move on */ return false; } @@ -922,7 +918,7 @@ ot_entropy_src_eg_push_bypass_entropy(OtEntropySrcEgState *s, uint32_t word) return true; } -static void ot_entropy_src_eg_update_fw_route(OtEntropySrcEgState *s) +static void ot_entropy_src_update_fw_route(OtEntropySrcState *s) { if (ot_fifo32_num_used(&s->final_fifo) >= ES_WORD_COUNT) { trace_ot_entropy_src_info("FW ROUTE"); @@ -934,22 +930,21 @@ static void ot_entropy_src_eg_update_fw_route(OtEntropySrcEgState *s) } s->regs[R_INTR_STATE] |= INTR_ES_ENTROPY_VALID_MASK; trace_ot_entropy_src_available(STATE_NAME(s->state), s->state); - ot_entropy_src_eg_update_filler(s); + ot_entropy_src_update_filler(s); } } } -static bool -ot_entropy_src_eg_consume_entropy(OtEntropySrcEgState *s, uint32_t word) +static bool ot_entropy_src_consume_entropy(OtEntropySrcState *s, uint32_t word) { - bool fill_obs_fifo = ot_entropy_src_eg_is_fw_ov_mode(s); - bool hw_path = !ot_entropy_src_eg_is_fw_ov_entropy_insert(s); - bool bypass = ot_entropy_src_eg_is_bypass_mode(s); + bool fill_obs_fifo = ot_entropy_src_is_fw_ov_mode(s); + bool hw_path = !ot_entropy_src_is_fw_ov_entropy_insert(s); + bool bypass = ot_entropy_src_is_bypass_mode(s); if (hw_path) { /* check that HW accept data */ - hw_path = bypass ? ot_entropy_src_eg_can_bypass_entropy(s) : - ot_entropy_src_eg_can_condition_entropy(s); + hw_path = bypass ? ot_entropy_src_can_bypass_entropy(s) : + ot_entropy_src_can_condition_entropy(s); } if (!(fill_obs_fifo || hw_path)) { @@ -991,34 +986,34 @@ ot_entropy_src_eg_consume_entropy(OtEntropySrcEgState *s, uint32_t word) } if (hw_path) { - if (ot_entropy_src_eg_is_bypass_mode(s)) { - ot_entropy_src_eg_push_bypass_entropy(s, word); + if (ot_entropy_src_is_bypass_mode(s)) { + ot_entropy_src_push_bypass_entropy(s, word); } else { - if (ot_entropy_src_eg_push_entropy_to_conditioner(s, word)) { - if (ot_entropy_src_eg_can_hash(s)) { + if (ot_entropy_src_push_entropy_to_conditioner(s, word)) { + if (ot_entropy_src_can_hash(s)) { trace_ot_entropy_src_info("can hash"); - ot_entropy_src_eg_perform_hash(s); + ot_entropy_src_perform_hash(s); } } } } - if (ot_entropy_src_eg_is_fw_route(s)) { - ot_entropy_src_eg_update_fw_route(s); + if (ot_entropy_src_is_fw_route(s)) { + ot_entropy_src_update_fw_route(s); } return true; } -static bool ot_entropy_src_eg_fill_noise(OtEntropySrcEgState *s) +static bool ot_entropy_src_fill_noise(OtEntropySrcState *s) { unsigned count = ot_fifo32_num_free(&s->input_fifo); - if (count < OT_ENTROPY_SRC_EG_FILL_WORD_COUNT) { + if (count < OT_ENTROPY_SRC_FILL_WORD_COUNT) { /* no room left, should be resheduled */ return false; } - uint32_t buffer[OT_ENTROPY_SRC_EG_FILL_WORD_COUNT]; + uint32_t buffer[OT_ENTROPY_SRC_FILL_WORD_COUNT]; /* synchronous read */ ot_ast_eg_getrandom(buffer, sizeof(buffer)); @@ -1032,22 +1027,21 @@ static bool ot_entropy_src_eg_fill_noise(OtEntropySrcEgState *s) for (unsigned ix = 0; ix < ES_WORD_COUNT && !ot_fifo32_is_empty(&s->input_fifo); ix++) { - if (!ot_entropy_src_eg_consume_entropy(s, - ot_fifo32_pop(&s->input_fifo))) { + if (!ot_entropy_src_consume_entropy(s, ot_fifo32_pop(&s->input_fifo))) { break; } } - ot_entropy_src_eg_update_irqs(s); + ot_entropy_src_update_irqs(s); return true; } -static void ot_entropy_src_eg_noise_refill(void *opaque) +static void ot_entropy_src_noise_refill(void *opaque) { - OtEntropySrcEgState *s = opaque; + OtEntropySrcState *s = opaque; - if (!ot_entropy_src_eg_fill_noise(s)) { + if (!ot_entropy_src_fill_noise(s)) { trace_ot_entropy_src_info("FIFO already filled up"); return; } @@ -1055,11 +1049,11 @@ static void ot_entropy_src_eg_noise_refill(void *opaque) switch (s->state) { case ENTROPY_SRC_EG_BOOT_HT_RUNNING: if (s->packet_count > 0) { - ot_entropy_src_eg_change_state(s, ENTROPY_SRC_EG_BOOT_PHASE_DONE); + ot_entropy_src_change_state(s, ENTROPY_SRC_EG_BOOT_PHASE_DONE); } break; case ENTROPY_SRC_EG_STARTUP_HT_START: - ot_entropy_src_eg_change_state(s, ENTROPY_SRC_EG_CONT_HT_RUNNING); + ot_entropy_src_change_state(s, ENTROPY_SRC_EG_CONT_HT_RUNNING); break; case ENTROPY_SRC_EG_CONT_HT_RUNNING: case ENTROPY_SRC_EG_CONT_HT_START: @@ -1076,12 +1070,12 @@ static void ot_entropy_src_eg_noise_refill(void *opaque) break; } - ot_entropy_src_eg_update_filler(s); + ot_entropy_src_update_filler(s); } -static void ot_entropy_src_eg_scheduler(void *opaque) +static void ot_entropy_src_scheduler(void *opaque) { - OtEntropySrcEgState *s = opaque; + OtEntropySrcState *s = opaque; switch (s->state) { case ENTROPY_SRC_EG_BOOT_HT_RUNNING: @@ -1094,7 +1088,7 @@ static void ot_entropy_src_eg_scheduler(void *opaque) case ENTROPY_SRC_EG_SHA3_PROCESS: case ENTROPY_SRC_EG_SHA3_DONE: case ENTROPY_SRC_EG_SHA3_MSGDONE: - ot_entropy_src_eg_noise_refill(s); + ot_entropy_src_noise_refill(s); break; case ENTROPY_SRC_EG_IDLE: break; @@ -1113,14 +1107,14 @@ static void ot_entropy_src_eg_scheduler(void *opaque) STATE_NAME(s->state), s->state); } - ot_entropy_src_eg_update_alerts(s); - ot_entropy_src_eg_update_irqs(s); + ot_entropy_src_update_alerts(s); + ot_entropy_src_update_irqs(s); } static uint64_t -ot_entropy_src_eg_regs_read(void *opaque, hwaddr addr, unsigned size) +ot_entropy_src_regs_read(void *opaque, hwaddr addr, unsigned size) { - OtEntropySrcEgState *s = opaque; + OtEntropySrcState *s = opaque; (void)size; uint32_t val32; @@ -1194,15 +1188,15 @@ ot_entropy_src_eg_regs_read(void *opaque, hwaddr addr, unsigned size) break; case R_REGWEN: val32 = (uint32_t)(s->regs[R_SW_REGUPD] == R_SW_REGUPD_UPD_MASK && - ot_entropy_src_eg_is_module_disabled(s)); + ot_entropy_src_is_module_disabled(s)); break; case R_ALERT_SUMMARY_FAIL_COUNTS: val32 = (uint32_t)ot_alert_get_alert_fail_count(s); break; case R_ENTROPY_DATA: - if (ot_entropy_src_eg_is_module_enabled(s) && + if (ot_entropy_src_is_module_enabled(s) && REG_MB4_IS_TRUE(s, CONF, ENTROPY_DATA_REG_ENABLE) && - ot_entropy_src_eg_is_fw_route(s)) { + ot_entropy_src_is_fw_route(s)) { if (!ot_fifo32_is_empty(&s->swread_fifo)) { val32 = ot_fifo32_pop(&s->swread_fifo); } else { @@ -1218,12 +1212,12 @@ ot_entropy_src_eg_regs_read(void *opaque, hwaddr addr, unsigned size) break; case R_FW_OV_WR_FIFO_FULL: { bool can_write; - if (ot_entropy_src_eg_is_fw_ov_mode(s) && - ot_entropy_src_eg_is_fw_ov_entropy_insert(s)) { - if (ot_entropy_src_eg_is_bypass_mode(s)) { - can_write = ot_entropy_src_eg_can_bypass_entropy(s); + if (ot_entropy_src_is_fw_ov_mode(s) && + ot_entropy_src_is_fw_ov_entropy_insert(s)) { + if (ot_entropy_src_is_bypass_mode(s)) { + can_write = ot_entropy_src_can_bypass_entropy(s); } else { - can_write = ot_entropy_src_eg_can_condition_entropy(s); + can_write = ot_entropy_src_can_condition_entropy(s); } } else { can_write = false; @@ -1231,7 +1225,7 @@ ot_entropy_src_eg_regs_read(void *opaque, hwaddr addr, unsigned size) val32 = can_write ? 0u : R_FW_OV_WR_FIFO_FULL_VAL_MASK; } break; case R_FW_OV_RD_DATA: - if (ot_entropy_src_eg_is_fw_ov_mode(s)) { + if (ot_entropy_src_is_fw_ov_mode(s)) { if (!ot_fifo32_is_empty(&s->observe_fifo)) { val32 = ot_fifo32_pop(&s->observe_fifo); } else { @@ -1271,20 +1265,20 @@ ot_entropy_src_eg_regs_read(void *opaque, hwaddr addr, unsigned size) #define CHECK_MULTIBOOT(_s_, _r_, _b_) \ do { \ - if (!ot_entropy_src_eg_check_multibitboot((_s_), \ - FIELD_EX32(s->regs[R_##_r_], \ - _r_, _b_), \ - ALERT_STATUS_BIT(_b_))) { \ + if (!ot_entropy_src_check_multibitboot((_s_), \ + FIELD_EX32(s->regs[R_##_r_], \ + _r_, _b_), \ + ALERT_STATUS_BIT(_b_))) { \ qemu_log_mask(LOG_GUEST_ERROR, \ "%s: invalid multiboot value 0x%1x\n", __func__, \ FIELD_EX32(s->regs[R_##_r_], _r_, _b_)); \ } \ } while (0) -static void ot_entropy_src_eg_regs_write(void *opaque, hwaddr addr, - uint64_t val64, unsigned size) +static void ot_entropy_src_regs_write(void *opaque, hwaddr addr, uint64_t val64, + unsigned size) { - OtEntropySrcEgState *s = opaque; + OtEntropySrcState *s = opaque; (void)size; uint32_t val32 = (uint32_t)val64; @@ -1304,22 +1298,22 @@ static void ot_entropy_src_eg_regs_write(void *opaque, hwaddr addr, if (!ot_fifo32_is_empty(&s->observe_fifo)) { s->regs[R_INTR_STATE] |= INTR_ES_OBSERVE_FIFO_READY_MASK; } - ot_entropy_src_eg_update_irqs(s); + ot_entropy_src_update_irqs(s); break; case R_INTR_ENABLE: val32 &= INTR_MASK; s->regs[reg] = val32; - ot_entropy_src_eg_update_irqs(s); + ot_entropy_src_update_irqs(s); break; case R_INTR_TEST: val32 &= INTR_MASK; s->regs[R_INTR_STATE] |= val32; - ot_entropy_src_eg_update_irqs(s); + ot_entropy_src_update_irqs(s); break; case R_ALERT_TEST: val32 &= ALERT_TEST_MASK; s->regs[reg] = val32; - ot_entropy_src_eg_update_alerts(s); + ot_entropy_src_update_alerts(s); break; case R_ME_REGWEN: val32 &= R_ME_REGWEN_EN_MASK; @@ -1335,26 +1329,25 @@ static void ot_entropy_src_eg_regs_write(void *opaque, hwaddr addr, val32 &= R_MODULE_ENABLE_MODULE_ENABLE_MASK; s->regs[reg] = val32; CHECK_MULTIBOOT(s, MODULE_ENABLE, MODULE_ENABLE); - if (ot_entropy_src_eg_is_module_disabled(s)) { + if (ot_entropy_src_is_module_disabled(s)) { /* reset takes care of cancelling the scheduler timer */ resettable_reset(OBJECT(s), RESET_TYPE_COLD); break; } - if ((old ^ s->regs[reg]) && - ot_entropy_src_eg_is_module_enabled(s)) { - if (ot_entropy_src_eg_is_fips_enabled(s)) { + if ((old ^ s->regs[reg]) && ot_entropy_src_is_module_enabled(s)) { + if (ot_entropy_src_is_fips_enabled(s)) { /* start up phase */ - ot_entropy_src_eg_change_state( + ot_entropy_src_change_state( s, ENTROPY_SRC_EG_STARTUP_HT_START); } else { /* boot phase */ - ot_entropy_src_eg_change_state( - s, ENTROPY_SRC_EG_BOOT_HT_RUNNING); + ot_entropy_src_change_state(s, + ENTROPY_SRC_EG_BOOT_HT_RUNNING); } uint64_t now = qemu_clock_get_ns(OT_VIRTUAL_CLOCK); timer_mod(s->scheduler, (int64_t)(now + - (uint64_t)OT_ENTROPY_SRC_EG_BOOT_DELAY_NS)); + (uint64_t)OT_ENTROPY_SRC_BOOT_DELAY_NS)); } break; } @@ -1394,7 +1387,7 @@ static void ot_entropy_src_eg_regs_write(void *opaque, hwaddr addr, case R_EXTHT_LO_THRESHOLDS: if (s->regs[R_REGWEN]) { s->regs[reg] = val32; - ot_entropy_src_eg_update_alerts(s); + ot_entropy_src_update_alerts(s); } break; case R_ALERT_THRESHOLD: @@ -1405,7 +1398,7 @@ static void ot_entropy_src_eg_regs_write(void *opaque, hwaddr addr, } else { s->regs[reg] = val32; } - ot_entropy_src_eg_update_alerts(s); + ot_entropy_src_update_alerts(s); } break; case R_FW_OV_CONTROL: @@ -1414,11 +1407,11 @@ static void ot_entropy_src_eg_regs_write(void *opaque, hwaddr addr, s->regs[reg] = val32; CHECK_MULTIBOOT(s, FW_OV_CONTROL, FW_OV_MODE); CHECK_MULTIBOOT(s, FW_OV_CONTROL, FW_OV_ENTROPY_INSERT); - s->obs_fifo_en = ot_entropy_src_eg_is_fw_ov_mode(s); + s->obs_fifo_en = ot_entropy_src_is_fw_ov_mode(s); } break; case R_FW_OV_SHA3_START: - if (!ot_entropy_src_eg_is_module_enabled(s)) { + if (!ot_entropy_src_is_module_enabled(s)) { qemu_log_mask(LOG_GUEST_ERROR, "%s: module not enabled\n", __func__); break; @@ -1427,29 +1420,29 @@ static void ot_entropy_src_eg_regs_write(void *opaque, hwaddr addr, s->regs[reg] = val32; CHECK_MULTIBOOT(s, FW_OV_SHA3_START, FW_OV_INSERT_START); if (REG_MB4_IS_TRUE(s, FW_OV_SHA3_START, FW_OV_INSERT_START)) { - OtEntropySrcEgFsmState new_state; - new_state = ot_entropy_src_eg_is_bypass_mode(s) ? + OtEntropySrcFsmState new_state; + new_state = ot_entropy_src_is_bypass_mode(s) ? ENTROPY_SRC_EG_IDLE : ENTROPY_SRC_EG_FW_INSERT_START; - ot_entropy_src_eg_change_state(s, new_state); + ot_entropy_src_change_state(s, new_state); } else { /* default to false */ if (s->state == ENTROPY_SRC_EG_SHA3_PROCESS) { /* handle SHA3 processing */ if (ot_fifo32_is_empty(&s->precon_fifo)) { - ot_entropy_src_eg_perform_hash(s); - if (ot_entropy_src_eg_is_fw_route(s)) { - ot_entropy_src_eg_update_fw_route(s); + ot_entropy_src_perform_hash(s); + if (ot_entropy_src_is_fw_route(s)) { + ot_entropy_src_update_fw_route(s); } } else { qemu_log_mask(LOG_GUEST_ERROR, "%s: need 1 more word\n", __func__); } } else { - OtEntropySrcEgFsmState new_state; - new_state = ot_entropy_src_eg_is_bypass_mode(s) ? + OtEntropySrcFsmState new_state; + new_state = ot_entropy_src_is_bypass_mode(s) ? ENTROPY_SRC_EG_BOOT_HT_RUNNING : ENTROPY_SRC_EG_STARTUP_HT_START; - ot_entropy_src_eg_change_state(s, new_state); + ot_entropy_src_change_state(s, new_state); } } break; @@ -1458,23 +1451,23 @@ static void ot_entropy_src_eg_regs_write(void *opaque, hwaddr addr, s->regs[reg] &= val32; /* RW0C */ break; case R_FW_OV_WR_DATA: - if (!ot_entropy_src_eg_is_module_enabled(s)) { + if (!ot_entropy_src_is_module_enabled(s)) { qemu_log_mask(LOG_GUEST_ERROR, "%s: module not enabled\n", __func__); break; } - if (ot_entropy_src_eg_is_fw_ov_mode(s) && - ot_entropy_src_eg_is_fw_ov_entropy_insert(s)) { + if (ot_entropy_src_is_fw_ov_mode(s) && + ot_entropy_src_is_fw_ov_entropy_insert(s)) { bool can_write; - if (ot_entropy_src_eg_is_bypass_mode(s)) { - can_write = ot_entropy_src_eg_can_bypass_entropy(s); + if (ot_entropy_src_is_bypass_mode(s)) { + can_write = ot_entropy_src_can_bypass_entropy(s); if (can_write) { - ot_entropy_src_eg_push_bypass_entropy(s, val32); + ot_entropy_src_push_bypass_entropy(s, val32); } } else { - can_write = ot_entropy_src_eg_can_condition_entropy(s); + can_write = ot_entropy_src_can_condition_entropy(s); if (can_write) { - ot_entropy_src_eg_push_entropy_to_conditioner(s, val32); + ot_entropy_src_push_entropy_to_conditioner(s, val32); } } if (!can_write) { @@ -1490,7 +1483,7 @@ static void ot_entropy_src_eg_regs_write(void *opaque, hwaddr addr, if (s->regs[R_REGWEN]) { val32 &= R_OBSERVE_FIFO_THRESH_VAL_MASK; s->regs[reg] = val32; - ot_entropy_src_eg_update_irqs(s); + ot_entropy_src_update_irqs(s); } break; case R_RECOV_ALERT_STS: @@ -1500,8 +1493,8 @@ static void ot_entropy_src_eg_regs_write(void *opaque, hwaddr addr, case R_ERR_CODE_TEST: val32 &= R_ERR_CODE_TEST_VAL_MASK; s->regs[R_ERR_CODE_TEST] = val32; - ot_entropy_src_eg_update_irqs(s); - ot_entropy_src_eg_update_alerts(s); + ot_entropy_src_update_irqs(s); + ot_entropy_src_update_alerts(s); break; case R_REGWEN: case R_REV: @@ -1544,26 +1537,26 @@ static void ot_entropy_src_eg_regs_write(void *opaque, hwaddr addr, } }; -static Property ot_entropy_src_eg_properties[] = { - DEFINE_PROP_LINK("ast", OtEntropySrcEgState, ast, TYPE_OT_AST_EG, +static Property ot_entropy_src_properties[] = { + DEFINE_PROP_LINK("ast", OtEntropySrcState, ast, TYPE_OT_AST_EG, OtASTEgState *), - DEFINE_PROP_LINK("otp_ctrl", OtEntropySrcEgState, otp_ctrl, TYPE_OT_OTP, + DEFINE_PROP_LINK("otp_ctrl", OtEntropySrcState, otp_ctrl, TYPE_OT_OTP, OtOTPState *), DEFINE_PROP_END_OF_LIST(), }; -static const MemoryRegionOps ot_entropy_src_eg_regs_ops = { - .read = &ot_entropy_src_eg_regs_read, - .write = &ot_entropy_src_eg_regs_write, +static const MemoryRegionOps ot_entropy_src_regs_ops = { + .read = &ot_entropy_src_regs_read, + .write = &ot_entropy_src_regs_write, .endianness = DEVICE_NATIVE_ENDIAN, .impl.min_access_size = 4u, .impl.max_access_size = 4u, }; -static void ot_entropy_src_eg_reset_enter(Object *obj, ResetType type) +static void ot_entropy_src_reset_enter(Object *obj, ResetType type) { - OtEntropySrcEgClass *c = OT_ENTROPY_SRC_EG_GET_CLASS(obj); - OtEntropySrcEgState *s = OT_ENTROPY_SRC_EG(obj); + OtEntropySrcClass *c = OT_ENTROPY_SRC_GET_CLASS(obj); + OtEntropySrcState *s = OT_ENTROPY_SRC(obj); trace_ot_entropy_src_reset(); @@ -1610,7 +1603,7 @@ static void ot_entropy_src_eg_reset_enter(Object *obj, ResetType type) s->packet_count = 0u; s->obs_fifo_en = false; - ot_entropy_src_eg_update_irqs(s); + ot_entropy_src_update_irqs(s); for (unsigned ix = 0; ix < PARAM_NUM_ALERTS; ix++) { ibex_irq_set(&s->alerts[ix], 0); } @@ -1619,25 +1612,25 @@ static void ot_entropy_src_eg_reset_enter(Object *obj, ResetType type) const OtOTPEntropyCfg *entropy_cfg = oc->get_entropy_cfg(s->otp_ctrl); g_assert(entropy_cfg); - ot_entropy_src_eg_change_state(s, ENTROPY_SRC_EG_IDLE); + ot_entropy_src_change_state(s, ENTROPY_SRC_EG_IDLE); } -static void ot_entropy_src_eg_realize(DeviceState *dev, Error **errp) +static void ot_entropy_src_realize(DeviceState *dev, Error **errp) { (void)errp; - OtEntropySrcEgState *s = OT_ENTROPY_SRC_EG(dev); + OtEntropySrcState *s = OT_ENTROPY_SRC(dev); g_assert(s->ast); g_assert(s->otp_ctrl); } -static void ot_entropy_src_eg_init(Object *obj) +static void ot_entropy_src_init(Object *obj) { - OtEntropySrcEgState *s = OT_ENTROPY_SRC_EG(obj); + OtEntropySrcState *s = OT_ENTROPY_SRC(obj); - memory_region_init_io(&s->mmio, obj, &ot_entropy_src_eg_regs_ops, s, - TYPE_OT_ENTROPY_SRC_EG, REGS_SIZE); + memory_region_init_io(&s->mmio, obj, &ot_entropy_src_regs_ops, s, + TYPE_OT_ENTROPY_SRC, REGS_SIZE); sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->mmio); s->regs = g_new0(uint32_t, REGS_COUNT); @@ -1648,42 +1641,41 @@ static void ot_entropy_src_eg_init(Object *obj) ibex_qdev_init_irq(obj, &s->alerts[ix], OT_DEVICE_ALERT); } - ot_fifo32_create(&s->input_fifo, OT_ENTROPY_SRC_EG_FILL_WORD_COUNT * 2u); + ot_fifo32_create(&s->input_fifo, OT_ENTROPY_SRC_FILL_WORD_COUNT * 2u); ot_fifo32_create(&s->precon_fifo, sizeof(uint64_t) / sizeof(uint32_t)); ot_fifo32_create(&s->bypass_fifo, ES_WORD_COUNT); ot_fifo32_create(&s->observe_fifo, PARAM_OBSERVE_FIFO_DEPTH); ot_fifo32_create(&s->swread_fifo, ES_SWREAD_FIFO_WORD_COUNT); ot_fifo32_create(&s->final_fifo, ES_FINAL_FIFO_WORD_COUNT); - s->scheduler = - timer_new_ns(OT_VIRTUAL_CLOCK, &ot_entropy_src_eg_scheduler, s); + s->scheduler = timer_new_ns(OT_VIRTUAL_CLOCK, &ot_entropy_src_scheduler, s); } -static void ot_entropy_src_eg_class_init(ObjectClass *klass, void *data) +static void ot_entropy_src_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); (void)data; - dc->realize = &ot_entropy_src_eg_realize; - device_class_set_props(dc, ot_entropy_src_eg_properties); + dc->realize = &ot_entropy_src_realize; + device_class_set_props(dc, ot_entropy_src_properties); set_bit(DEVICE_CATEGORY_MISC, dc->categories); ResettableClass *rc = RESETTABLE_CLASS(klass); - OtEntropySrcEgClass *ec = OT_ENTROPY_SRC_EG_CLASS(klass); - resettable_class_set_parent_phases(rc, &ot_entropy_src_eg_reset_enter, NULL, + OtEntropySrcClass *ec = OT_ENTROPY_SRC_CLASS(klass); + resettable_class_set_parent_phases(rc, &ot_entropy_src_reset_enter, NULL, NULL, &ec->parent_phases); OtRandomSrcIfClass *rdc = OT_RANDOM_SRC_IF_CLASS(klass); - rdc->get_random_values = &ot_entropy_src_eg_get_random; + rdc->get_random_values = &ot_entropy_src_get_random; } -static const TypeInfo ot_entropy_src_eg_info = { - .name = TYPE_OT_ENTROPY_SRC_EG, +static const TypeInfo ot_entropy_src_info = { + .name = TYPE_OT_ENTROPY_SRC, .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(OtEntropySrcEgState), - .instance_init = &ot_entropy_src_eg_init, - .class_size = sizeof(OtEntropySrcEgClass), - .class_init = &ot_entropy_src_eg_class_init, + .instance_size = sizeof(OtEntropySrcState), + .instance_init = &ot_entropy_src_init, + .class_size = sizeof(OtEntropySrcClass), + .class_init = &ot_entropy_src_class_init, .interfaces = (InterfaceInfo[]){ { TYPE_OT_RANDOM_SRC_IF }, @@ -1691,9 +1683,9 @@ static const TypeInfo ot_entropy_src_eg_info = { }, }; -static void ot_entropy_src_eg_register_types(void) +static void ot_entropy_src_register_types(void) { - type_register_static(&ot_entropy_src_eg_info); + type_register_static(&ot_entropy_src_info); } -type_init(ot_entropy_src_eg_register_types); +type_init(ot_entropy_src_register_types); diff --git a/hw/opentitan/ot_entropy_src_dj.c b/hw/opentitan/ot_entropy_src_dj.c deleted file mode 100644 index fe648321c1d7..000000000000 --- a/hw/opentitan/ot_entropy_src_dj.c +++ /dev/null @@ -1,1691 +0,0 @@ -/* - * QEMU OpenTitan Darjeeling Entropy Source device - * - * Copyright (c) 2023-2025 Rivos, Inc. - * Copyright (c) 2025 lowRISC contributors. - * - * Author(s): - * Emmanuel Blot - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * Notes: - * - missing correct handling of ALERT_FAIL_COUNTS, currently never incremented. - * - missing some error handling? ES_MAIN_SM_ERR is the only error that can be - * triggered. - */ - -#include "qemu/osdep.h" -#include "qemu/log.h" -#include "qemu/timer.h" -#include "qemu/typedefs.h" -#include "hw/opentitan/ot_alert.h" -#include "hw/opentitan/ot_ast_eg.h" -#include "hw/opentitan/ot_common.h" -#include "hw/opentitan/ot_entropy_src_dj.h" -#include "hw/opentitan/ot_fifo32.h" -#include "hw/opentitan/ot_otp.h" -#include "hw/opentitan/ot_random_src.h" -#include "hw/qdev-properties.h" -#include "hw/registerfields.h" -#include "hw/riscv/ibex_common.h" -#include "hw/riscv/ibex_irq.h" -#include "hw/sysbus.h" -#include "tomcrypt.h" -#include "trace.h" - - -#define PARAM_NUM_IRQS 4u -#define PARAM_NUM_ALERTS 2u -#define PARAM_OBSERVE_FIFO_DEPTH 64u /* 2048 bits */ - -/* clang-format off */ -REG32(INTR_STATE, 0x0u) - SHARED_FIELD(INTR_ES_ENTROPY_VALID, 0u, 1u) - SHARED_FIELD(INTR_ES_HEALTH_TEST_FAILED, 1u, 1u) - SHARED_FIELD(INTR_ES_OBSERVE_FIFO_READY, 2u, 1u) - SHARED_FIELD(INTR_ES_FATAL_ERR, 3u, 1u) -REG32(INTR_ENABLE, 0x4u) -REG32(INTR_TEST, 0x8u) -REG32(ALERT_TEST, 0xcu) - FIELD(ALERT_TEST, RECOV_ALERT, 0u, 1u) - FIELD(ALERT_TEST, FATAL_ALERT, 1u, 1u) -REG32(ME_REGWEN, 0x10u) - FIELD(ME_REGWEN, EN, 0u, 1u) -REG32(SW_REGUPD, 0x14u) - FIELD(SW_REGUPD, UPD, 0u, 1u) -REG32(REGWEN, 0x18u) - FIELD(REGWEN, EN, 0u, 1u) -REG32(MODULE_ENABLE, 0x1cu) - FIELD(MODULE_ENABLE, MODULE_ENABLE, 0u, 4u) -REG32(CONF, 0x20u) - FIELD(CONF, FIPS_ENABLE, 0u, 4u) - FIELD(CONF, FIPS_FLAG, 4u, 4u) - FIELD(CONF, RNG_FIPS, 8u, 4u) - FIELD(CONF, RNG_BIT_ENABLE, 12u, 4u) - FIELD(CONF, RNG_BIT_SEL, 16u, 2u) - FIELD(CONF, THRESHOLD_SCOPE, 18u, 4u) - FIELD(CONF, ENTROPY_DATA_REG_ENABLE, 22u, 4u) -REG32(ENTROPY_CONTROL, 0x24u) - FIELD(ENTROPY_CONTROL, ES_ROUTE, 0u, 4u) - FIELD(ENTROPY_CONTROL, ES_TYPE, 4u, 4u) -REG32(ENTROPY_DATA, 0x28u) -REG32(HEALTH_TEST_WINDOWS, 0x2cu) - FIELD(HEALTH_TEST_WINDOWS, FIPS_WINDOW, 0u, 16u) - FIELD(HEALTH_TEST_WINDOWS, BYPASS_WINDOW, 16u, 16u) -REG32(REPCNT_THRESHOLDS, 0x30u) - SHARED_FIELD(THRESHOLDS_FIPS, 0u, 16u) - SHARED_FIELD(THRESHOLDS_BYPASS, 16u, 16u) -REG32(REPCNTS_THRESHOLDS, 0x34u) -REG32(ADAPTP_HI_THRESHOLDS, 0x38u) -REG32(ADAPTP_LO_THRESHOLDS, 0x3cu) -REG32(BUCKET_THRESHOLDS, 0x40u) -REG32(MARKOV_HI_THRESHOLDS, 0x44u) -REG32(MARKOV_LO_THRESHOLDS, 0x48u) -REG32(EXTHT_HI_THRESHOLDS, 0x4cu) -REG32(EXTHT_LO_THRESHOLDS, 0x50u) -REG32(REPCNT_HI_WATERMARKS, 0x54u) - SHARED_FIELD(WATERMARK_FIPS, 0u, 16u) - SHARED_FIELD(WATERMARK_BYPASS, 16u, 16u) -REG32(REPCNTS_HI_WATERMARKS, 0x58u) -REG32(ADAPTP_HI_WATERMARKS, 0x5cu) -REG32(ADAPTP_LO_WATERMARKS, 0x60u) -REG32(EXTHT_HI_WATERMARKS, 0x64u) -REG32(EXTHT_LO_WATERMARKS, 0x68u) -REG32(BUCKET_HI_WATERMARKS, 0x6cu) -REG32(MARKOV_HI_WATERMARKS, 0x70u) -REG32(MARKOV_LO_WATERMARKS, 0x74u) -REG32(REPCNT_TOTAL_FAILS, 0x78u) -REG32(REPCNTS_TOTAL_FAILS, 0x7cu) -REG32(ADAPTP_HI_TOTAL_FAILS, 0x80u) -REG32(ADAPTP_LO_TOTAL_FAILS, 0x84u) -REG32(BUCKET_TOTAL_FAILS, 0x88u) -REG32(MARKOV_HI_TOTAL_FAILS, 0x8cu) -REG32(MARKOV_LO_TOTAL_FAILS, 0x90u) -REG32(EXTHT_HI_TOTAL_FAILS, 0x94u) -REG32(EXTHT_LO_TOTAL_FAILS, 0x98u) -REG32(ALERT_THRESHOLD, 0x9cu) - FIELD(ALERT_THRESHOLD, ALERT_THRESHOLD, 0u, 16u) - FIELD(ALERT_THRESHOLD, ALERT_THRESHOLD_INV, 16u, 16u) -REG32(ALERT_SUMMARY_FAIL_COUNTS, 0xa0u) - FIELD(ALERT_SUMMARY_FAIL_COUNTS, ANY_FAIL_COUNT, 0u, 16u) -REG32(ALERT_FAIL_COUNTS, 0xa4u) - FIELD(ALERT_FAIL_COUNTS, REPCNT_FAIL_COUNT, 4u, 4u) - FIELD(ALERT_FAIL_COUNTS, ADAPTP_HI_FAIL_COUNT, 8u, 4u) - FIELD(ALERT_FAIL_COUNTS, ADAPTP_LO_FAIL_COUNT, 12u, 4u) - FIELD(ALERT_FAIL_COUNTS, BUCKET_FAIL_COUNT, 16u, 4u) - FIELD(ALERT_FAIL_COUNTS, MARKOV_HI_FAIL_COUNT, 20u, 4u) - FIELD(ALERT_FAIL_COUNTS, MARKOV_LO_FAIL_COUNT, 24u, 4u) - FIELD(ALERT_FAIL_COUNTS, REPCNTS_FAIL_COUNT, 28u, 4u) -REG32(EXTHT_FAIL_COUNTS, 0xa8u) - FIELD(EXTHT_FAIL_COUNTS, EXTHT_HI_FAIL_COUNT, 0u, 4u) - FIELD(EXTHT_FAIL_COUNTS, EXTHT_LO_FAIL_COUNT, 4u, 4u) -REG32(FW_OV_CONTROL, 0xacu) - FIELD(FW_OV_CONTROL, FW_OV_MODE, 0u, 4u) - FIELD(FW_OV_CONTROL, FW_OV_ENTROPY_INSERT, 4u, 4u) -REG32(FW_OV_SHA3_START, 0xb0u) - FIELD(FW_OV_SHA3_START, FW_OV_INSERT_START, 0u, 4u) -REG32(FW_OV_WR_FIFO_FULL, 0xb4u) - FIELD(FW_OV_WR_FIFO_FULL, VAL, 0u, 1u) -REG32(FW_OV_RD_FIFO_OVERFLOW, 0xb8u) - FIELD(FW_OV_RD_FIFO_OVERFLOW, VAL, 0u, 1u) -REG32(FW_OV_RD_DATA, 0xbcu) -REG32(FW_OV_WR_DATA, 0xc0u) -REG32(OBSERVE_FIFO_THRESH, 0xc4u) - FIELD(OBSERVE_FIFO_THRESH, VAL, 0u, 6u) -REG32(OBSERVE_FIFO_DEPTH, 0xc8u) - FIELD(OBSERVE_FIFO_DEPTH, VAL, 0u, 6u) -REG32(DEBUG_STATUS, 0xccu) - FIELD(DEBUG_STATUS, ENTROPY_FIFO_DEPTH, 0u, 2u) - FIELD(DEBUG_STATUS, SHA3_FSM, 3u, 3u) - FIELD(DEBUG_STATUS, SHA3_BLOCK_PR, 6u, 1u) - FIELD(DEBUG_STATUS, SHA3_SQUEEZING, 7u, 1u) - FIELD(DEBUG_STATUS, SHA3_ABSORBED, 8u, 1u) - FIELD(DEBUG_STATUS, SHA3_ERR, 9u, 1u) - FIELD(DEBUG_STATUS, MAIN_SM_IDLE, 16u, 1u) - FIELD(DEBUG_STATUS, MAIN_SM_BOOT_DONE, 17u, 1u) -REG32(RECOV_ALERT_STS, 0xd0u) - FIELD(RECOV_ALERT_STS, FIPS_ENABLE_FIELD_ALERT, 0u, 1u) - FIELD(RECOV_ALERT_STS, ENTROPY_DATA_REG_ENABLE_FIELD_ALERT, 1u, 1u) - FIELD(RECOV_ALERT_STS, MODULE_ENABLE_FIELD_ALERT, 2u, 1u) - FIELD(RECOV_ALERT_STS, THRESHOLD_SCOPE_FIELD_ALERT, 3u, 1u) - FIELD(RECOV_ALERT_STS, RNG_BIT_ENABLE_FIELD_ALERT, 5u, 1u) - FIELD(RECOV_ALERT_STS, FW_OV_INSERT_START_FIELD_ALERT, 7u, 1u) - FIELD(RECOV_ALERT_STS, FW_OV_MODE_FIELD_ALERT, 8u, 1u) - FIELD(RECOV_ALERT_STS, FW_OV_ENTROPY_INSERT_FIELD_ALERT, 9u, 1u) - FIELD(RECOV_ALERT_STS, ES_ROUTE_FIELD_ALERT, 10u, 1u) - FIELD(RECOV_ALERT_STS, ES_TYPE_FIELD_ALERT, 11u, 1u) - FIELD(RECOV_ALERT_STS, ES_MAIN_SM_ALERT, 12u, 1u) - FIELD(RECOV_ALERT_STS, ES_BUS_CMP_ALERT, 13u, 1u) - FIELD(RECOV_ALERT_STS, ES_THRESH_CFG_ALERT, 14u, 1u) - FIELD(RECOV_ALERT_STS, ES_FW_OV_WR_ALERT, 15u, 1u) - FIELD(RECOV_ALERT_STS, ES_FW_OV_DISABLE_ALERT, 16u, 1u) - FIELD(RECOV_ALERT_STS, FIPS_FLAG_FIELD_ALERT, 17u, 1u) - FIELD(RECOV_ALERT_STS, RNG_FIPS_FIELD_ALERT, 18u, 1u) - FIELD(RECOV_ALERT_STS, POSTHT_ENTROPY_DROP_ALERT, 31u, 1u) -REG32(ERR_CODE, 0xd4u) - FIELD(ERR_CODE, SFIFO_ESRNG_ERR, 0u, 1u) - FIELD(ERR_CODE, SFIFO_DISTR_ERR, 1u, 1u) - FIELD(ERR_CODE, SFIFO_OBSERVE_ERR, 2u, 1u) - FIELD(ERR_CODE, SFIFO_ESFINAL_ERR, 3u, 1u) - FIELD(ERR_CODE, ES_ACK_SM_ERR, 20u, 1u) - FIELD(ERR_CODE, ES_MAIN_SM_ERR, 21u, 1u) - FIELD(ERR_CODE, ES_CNTR_ERR, 22u, 1u) - FIELD(ERR_CODE, SHA3_STATE_ERR, 23u, 1u) - FIELD(ERR_CODE, SHA3_RST_STORAGE_ERR, 24u, 1u) - FIELD(ERR_CODE, FIFO_WRITE_ERR, 28u, 1u) - FIELD(ERR_CODE, FIFO_READ_ERR, 29u, 1u) - FIELD(ERR_CODE, FIFO_STATE_ERR, 30u, 1u) -REG32(ERR_CODE_TEST, 0xd8u) - FIELD(ERR_CODE_TEST, VAL, 0u, 5u) -REG32(MAIN_SM_STATE, 0xdcu) - FIELD(MAIN_SM_STATE, VAL, 0u, 9u) -/* clang-format on */ - -#define R32_OFF(_r_) ((_r_) / sizeof(uint32_t)) - -#define R_LAST_REG (R_MAIN_SM_STATE) -#define REGS_COUNT (R_LAST_REG + 1u) -#define REGS_SIZE (REGS_COUNT * sizeof(uint32_t)) -#define REG_NAME(_reg_) \ - ((((_reg_) <= REGS_COUNT) && REG_NAMES[_reg_]) ? REG_NAMES[_reg_] : "?") - -#define INTR_MASK \ - (INTR_ES_ENTROPY_VALID_MASK | INTR_ES_HEALTH_TEST_FAILED_MASK | \ - INTR_ES_OBSERVE_FIFO_READY_MASK | INTR_ES_FATAL_ERR_MASK) -#define ALERT_TEST_MASK \ - (R_ALERT_TEST_RECOV_ALERT_MASK | R_ALERT_TEST_FATAL_ALERT_MASK) -#define CONF_MASK \ - (R_CONF_FIPS_ENABLE_MASK | R_CONF_FIPS_FLAG_MASK | R_CONF_RNG_FIPS_MASK | \ - R_CONF_RNG_BIT_ENABLE_MASK | R_CONF_RNG_BIT_SEL_MASK | \ - R_CONF_THRESHOLD_SCOPE_MASK | R_CONF_ENTROPY_DATA_REG_ENABLE_MASK) -#define ENTROPY_CONTROL_MASK \ - (R_ENTROPY_CONTROL_ES_ROUTE_MASK | R_ENTROPY_CONTROL_ES_TYPE_MASK) -#define FW_OV_CONTROL_MASK \ - (R_FW_OV_CONTROL_FW_OV_MODE_MASK | \ - R_FW_OV_CONTROL_FW_OV_ENTROPY_INSERT_MASK) -#define RECOV_ALERT_STS_MASK \ - (R_RECOV_ALERT_STS_FIPS_ENABLE_FIELD_ALERT_MASK | \ - R_RECOV_ALERT_STS_ENTROPY_DATA_REG_ENABLE_FIELD_ALERT_MASK | \ - R_RECOV_ALERT_STS_MODULE_ENABLE_FIELD_ALERT_MASK | \ - R_RECOV_ALERT_STS_THRESHOLD_SCOPE_FIELD_ALERT_MASK | \ - R_RECOV_ALERT_STS_RNG_BIT_ENABLE_FIELD_ALERT_MASK | \ - R_RECOV_ALERT_STS_FW_OV_INSERT_START_FIELD_ALERT_MASK | \ - R_RECOV_ALERT_STS_FW_OV_MODE_FIELD_ALERT_MASK | \ - R_RECOV_ALERT_STS_FW_OV_ENTROPY_INSERT_FIELD_ALERT_MASK | \ - R_RECOV_ALERT_STS_ES_ROUTE_FIELD_ALERT_MASK | \ - R_RECOV_ALERT_STS_ES_TYPE_FIELD_ALERT_MASK | \ - R_RECOV_ALERT_STS_ES_MAIN_SM_ALERT_MASK | \ - R_RECOV_ALERT_STS_ES_BUS_CMP_ALERT_MASK | \ - R_RECOV_ALERT_STS_ES_THRESH_CFG_ALERT_MASK | \ - R_RECOV_ALERT_STS_ES_FW_OV_WR_ALERT_MASK | \ - R_RECOV_ALERT_STS_ES_FW_OV_DISABLE_ALERT_MASK | \ - R_RECOV_ALERT_STS_FIPS_FLAG_FIELD_ALERT_MASK | \ - R_RECOV_ALERT_STS_RNG_FIPS_FIELD_ALERT_MASK | \ - R_RECOV_ALERT_STS_POSTHT_ENTROPY_DROP_ALERT_MASK) -#define ERR_CODE_MASK \ - (R_ERR_CODE_SFIFO_ESRNG_ERR_MASK | R_ERR_CODE_SFIFO_DISTR_ERR_MASK | \ - R_ERR_CODE_SFIFO_OBSERVE_ERR_MASK | R_ERR_CODE_SFIFO_ESFINAL_ERR_MASK | \ - R_ERR_CODE_ES_ACK_SM_ERR_MASK | R_ERR_CODE_ES_MAIN_SM_ERR_MASK | \ - R_ERR_CODE_ES_CNTR_ERR_MASK | R_ERR_CODE_SHA3_STATE_ERR_MASK | \ - R_ERR_CODE_SHA3_RST_STORAGE_ERR_MASK | R_ERR_CODE_FIFO_WRITE_ERR_MASK | \ - R_ERR_CODE_FIFO_READ_ERR_MASK | R_ERR_CODE_FIFO_STATE_ERR_MASK) -#define ERR_CODE_FATAL_ERROR_MASK \ - (R_ERR_CODE_ES_ACK_SM_ERR_MASK | R_ERR_CODE_ES_MAIN_SM_ERR_MASK | \ - R_ERR_CODE_ES_CNTR_ERR_MASK | R_ERR_CODE_SHA3_STATE_ERR_MASK | \ - R_ERR_CODE_SHA3_RST_STORAGE_ERR_MASK) - -#define ALERT_STATUS_BIT(_x_) R_RECOV_ALERT_STS_##_x_##_FIELD_ALERT_SHIFT - -#define REG_NAME_ENTRY(_reg_) [R_##_reg_] = stringify(_reg_) -static const char *REG_NAMES[REGS_COUNT] = { - REG_NAME_ENTRY(INTR_STATE), - REG_NAME_ENTRY(INTR_ENABLE), - REG_NAME_ENTRY(INTR_TEST), - REG_NAME_ENTRY(ALERT_TEST), - REG_NAME_ENTRY(ME_REGWEN), - REG_NAME_ENTRY(SW_REGUPD), - REG_NAME_ENTRY(REGWEN), - REG_NAME_ENTRY(MODULE_ENABLE), - REG_NAME_ENTRY(CONF), - REG_NAME_ENTRY(ENTROPY_CONTROL), - REG_NAME_ENTRY(ENTROPY_DATA), - REG_NAME_ENTRY(HEALTH_TEST_WINDOWS), - REG_NAME_ENTRY(REPCNT_THRESHOLDS), - REG_NAME_ENTRY(REPCNTS_THRESHOLDS), - REG_NAME_ENTRY(ADAPTP_HI_THRESHOLDS), - REG_NAME_ENTRY(ADAPTP_LO_THRESHOLDS), - REG_NAME_ENTRY(BUCKET_THRESHOLDS), - REG_NAME_ENTRY(MARKOV_HI_THRESHOLDS), - REG_NAME_ENTRY(MARKOV_LO_THRESHOLDS), - REG_NAME_ENTRY(EXTHT_HI_THRESHOLDS), - REG_NAME_ENTRY(EXTHT_LO_THRESHOLDS), - REG_NAME_ENTRY(REPCNT_HI_WATERMARKS), - REG_NAME_ENTRY(REPCNTS_HI_WATERMARKS), - REG_NAME_ENTRY(ADAPTP_HI_WATERMARKS), - REG_NAME_ENTRY(ADAPTP_LO_WATERMARKS), - REG_NAME_ENTRY(EXTHT_HI_WATERMARKS), - REG_NAME_ENTRY(EXTHT_LO_WATERMARKS), - REG_NAME_ENTRY(BUCKET_HI_WATERMARKS), - REG_NAME_ENTRY(MARKOV_HI_WATERMARKS), - REG_NAME_ENTRY(MARKOV_LO_WATERMARKS), - REG_NAME_ENTRY(REPCNT_TOTAL_FAILS), - REG_NAME_ENTRY(REPCNTS_TOTAL_FAILS), - REG_NAME_ENTRY(ADAPTP_HI_TOTAL_FAILS), - REG_NAME_ENTRY(ADAPTP_LO_TOTAL_FAILS), - REG_NAME_ENTRY(BUCKET_TOTAL_FAILS), - REG_NAME_ENTRY(MARKOV_HI_TOTAL_FAILS), - REG_NAME_ENTRY(MARKOV_LO_TOTAL_FAILS), - REG_NAME_ENTRY(EXTHT_HI_TOTAL_FAILS), - REG_NAME_ENTRY(EXTHT_LO_TOTAL_FAILS), - REG_NAME_ENTRY(ALERT_THRESHOLD), - REG_NAME_ENTRY(ALERT_SUMMARY_FAIL_COUNTS), - REG_NAME_ENTRY(ALERT_FAIL_COUNTS), - REG_NAME_ENTRY(EXTHT_FAIL_COUNTS), - REG_NAME_ENTRY(FW_OV_CONTROL), - REG_NAME_ENTRY(FW_OV_SHA3_START), - REG_NAME_ENTRY(FW_OV_WR_FIFO_FULL), - REG_NAME_ENTRY(FW_OV_RD_FIFO_OVERFLOW), - REG_NAME_ENTRY(FW_OV_RD_DATA), - REG_NAME_ENTRY(FW_OV_WR_DATA), - REG_NAME_ENTRY(OBSERVE_FIFO_THRESH), - REG_NAME_ENTRY(OBSERVE_FIFO_DEPTH), - REG_NAME_ENTRY(DEBUG_STATUS), - REG_NAME_ENTRY(RECOV_ALERT_STS), - REG_NAME_ENTRY(ERR_CODE), - REG_NAME_ENTRY(ERR_CODE_TEST), - REG_NAME_ENTRY(MAIN_SM_STATE), -}; -#undef REG_NAME_ENTRY - -/** - * Use a 128-bit incoming packet size (HW uses 4-bit packet) in order to limit - * feed rate to ~0.7 ms max. 128-bit packet can be divided down to 32-bit - * FIFO packets. They are assembled into either 384-bit or 2048-bit packets. - */ -#define ES_FILL_BITS 128u -#define ES_FINAL_FIFO_DEPTH 4u -#define ES_FILL_RATE_NS \ - ((NANOSECONDS_PER_SECOND * ES_FILL_BITS) / \ - ((uint64_t)OT_AST_EG_RANDOM_4BIT_RATE * 4u)) -#define OT_ENTROPY_SRC_DJ_FILL_WORD_COUNT \ - (ES_FILL_BITS / (8u * sizeof(uint32_t))) -#define ES_WORD_COUNT (OT_RANDOM_SRC_WORD_COUNT) -#define ES_SWREAD_FIFO_WORD_COUNT ES_WORD_COUNT -#define ES_FINAL_FIFO_WORD_COUNT (ES_WORD_COUNT * ES_FINAL_FIFO_DEPTH) -#define ES_HEXBUF_SIZE ((8U * 2u + 1u) * ES_WORD_COUNT + 4u) - -/* - * see hw/ip/edn/doc/#multiple-edns-in-boot-time-request-mode - * reduce initial delay in QEMU since it takes time to manage the entropy - */ -#define OT_ENTROPY_SRC_DJ_BOOT_DELAY_NS 500000LL /* 500 us */ -/* - * default delay to pace the entropy src client (CSRNG) when no entropy is - * available. A better implementation would compute the remaining time before - * the next available entropy packet. - */ -#define OT_ENTROPY_SRC_DJ_WAIT_DELAY_NS 2000LL /* 2 us */ - -enum { - ALERT_RECOVERABLE, - ALERT_FATAL, - ALERT_COUNT, -}; - -static_assert(ALERT_COUNT == PARAM_NUM_ALERTS, "Invalid alert count"); - -typedef enum { - ENTROPY_SRC_DJ_IDLE, - ENTROPY_SRC_DJ_BOOT_HT_RUNNING, - ENTROPY_SRC_DJ_BOOT_POST_HT_CHK, - ENTROPY_SRC_DJ_BOOT_PHASE_DONE, - ENTROPY_SRC_DJ_STARTUP_HT_START, - ENTROPY_SRC_DJ_STARTUP_PHASE1, - ENTROPY_SRC_DJ_STARTUP_PASS1, - ENTROPY_SRC_DJ_STARTUP_FAIL1, - ENTROPY_SRC_DJ_CONT_HT_START, - ENTROPY_SRC_DJ_CONT_HT_RUNNING, - ENTROPY_SRC_DJ_FW_INSERT_START, - ENTROPY_SRC_DJ_FW_INSERT_MSG, - ENTROPY_SRC_DJ_SHA3_MSGDONE, - ENTROPY_SRC_DJ_SHA3_PREP, - ENTROPY_SRC_DJ_SHA3_PROCESS, - ENTROPY_SRC_DJ_SHA3_VALID, - ENTROPY_SRC_DJ_SHA3_DONE, - ENTROPY_SRC_DJ_SHA3_QUIESCE, - ENTROPY_SRC_DJ_ALERT_STATE, - ENTROPY_SRC_DJ_ALERT_HANG, - ENTROPY_SRC_DJ_ERROR, -} OtEntropySrcDjFsmState; - -struct OtEntropySrcDjState { - SysBusDevice parent_obj; - - MemoryRegion mmio; - IbexIRQ irqs[PARAM_NUM_IRQS]; - IbexIRQ alerts[PARAM_NUM_ALERTS]; - QEMUTimer *scheduler; - - uint32_t *regs; - OtFifo32 input_fifo; /* not in real HW, used to reduce feed rate */ - OtFifo32 precon_fifo; /* 32-to-64 SHA3 input packer */ - OtFifo32 bypass_fifo; /* 32-to-384 packer */ - OtFifo32 observe_fifo; - OtFifo32 swread_fifo; - OtFifo32 final_fifo; /* output FIFO */ - hash_state sha3_state; /* libtomcrypt hash state */ - OtEntropySrcDjFsmState state; - unsigned cond_word; /* count of words processed with SHA3 till hash */ - unsigned noise_count; /* count of consumed noise words since enabled */ - unsigned packet_count; /* count of output packets since enabled */ - bool obs_fifo_en; /* observe FIFO accept incoming data */ - - OtASTEgState *ast; - OtOTPState *otp_ctrl; -}; - -struct OtEntropySrcDjClass { - SysBusDeviceClass parent_class; - ResettablePhases parent_phases; -}; - -static const uint16_t OtEDNFsmStateCode[] = { - [ENTROPY_SRC_DJ_IDLE] = 0b011110101, - [ENTROPY_SRC_DJ_BOOT_HT_RUNNING] = 0b111010010, - [ENTROPY_SRC_DJ_BOOT_POST_HT_CHK] = 0b101101110, - [ENTROPY_SRC_DJ_BOOT_PHASE_DONE] = 0b010001110, - [ENTROPY_SRC_DJ_STARTUP_HT_START] = 0b000101100, - [ENTROPY_SRC_DJ_STARTUP_PHASE1] = 0b100000001, - [ENTROPY_SRC_DJ_STARTUP_PASS1] = 0b110100101, - [ENTROPY_SRC_DJ_STARTUP_FAIL1] = 0b000010111, - [ENTROPY_SRC_DJ_CONT_HT_START] = 0b001000000, - [ENTROPY_SRC_DJ_CONT_HT_RUNNING] = 0b110100010, - [ENTROPY_SRC_DJ_FW_INSERT_START] = 0b011000011, - [ENTROPY_SRC_DJ_FW_INSERT_MSG] = 0b001011001, - [ENTROPY_SRC_DJ_SHA3_MSGDONE] = 0b100001111, - [ENTROPY_SRC_DJ_SHA3_PREP] = 0b011111000, - [ENTROPY_SRC_DJ_SHA3_PROCESS] = 0b010111111, - [ENTROPY_SRC_DJ_SHA3_VALID] = 0b101110001, - [ENTROPY_SRC_DJ_SHA3_DONE] = 0b110011000, - [ENTROPY_SRC_DJ_SHA3_QUIESCE] = 0b111001101, - [ENTROPY_SRC_DJ_ALERT_STATE] = 0b111111011, - [ENTROPY_SRC_DJ_ALERT_HANG] = 0b101011100, - [ENTROPY_SRC_DJ_ERROR] = 0b100111101, -}; - -#define STATE_NAME_ENTRY(_st_) [ENTROPY_SRC_DJ_##_st_] = stringify(_st_) -static const char *STATE_NAMES[] = { - STATE_NAME_ENTRY(IDLE), - STATE_NAME_ENTRY(BOOT_HT_RUNNING), - STATE_NAME_ENTRY(BOOT_POST_HT_CHK), - STATE_NAME_ENTRY(BOOT_PHASE_DONE), - STATE_NAME_ENTRY(STARTUP_HT_START), - STATE_NAME_ENTRY(STARTUP_PHASE1), - STATE_NAME_ENTRY(STARTUP_PASS1), - STATE_NAME_ENTRY(STARTUP_FAIL1), - STATE_NAME_ENTRY(CONT_HT_START), - STATE_NAME_ENTRY(CONT_HT_RUNNING), - STATE_NAME_ENTRY(FW_INSERT_START), - STATE_NAME_ENTRY(FW_INSERT_MSG), - STATE_NAME_ENTRY(SHA3_MSGDONE), - STATE_NAME_ENTRY(SHA3_PREP), - STATE_NAME_ENTRY(SHA3_PROCESS), - STATE_NAME_ENTRY(SHA3_VALID), - STATE_NAME_ENTRY(SHA3_DONE), - STATE_NAME_ENTRY(SHA3_QUIESCE), - STATE_NAME_ENTRY(ALERT_STATE), - STATE_NAME_ENTRY(ALERT_HANG), - STATE_NAME_ENTRY(ERROR), -}; -#undef STATE_NAME_ENTRY -#define STATE_NAME(_st_) \ - ((_st_) >= 0 && (_st_) < ARRAY_SIZE(STATE_NAMES) ? STATE_NAMES[(_st_)] : \ - "?") -#define REG_MB4_IS_TRUE(_s_, _reg_, _fld_) \ - (FIELD_EX32((_s_)->regs[R_##_reg_], _reg_, _fld_) == OT_MULTIBITBOOL4_TRUE) -#define REG_MB4_IS_FALSE(_s_, _reg_, _fld_) \ - (FIELD_EX32((_s_)->regs[R_##_reg_], _reg_, _fld_) == OT_MULTIBITBOOL4_FALSE) - -#define xtrace_ot_entropy_src_dj_show_buffer(_msg_, _buf_, _len_) \ - ot_entropy_src_dj_show_buffer(__func__, __LINE__, _msg_, _buf_, _len_) - -static bool ot_entropy_src_dj_is_module_enabled(const OtEntropySrcDjState *s); -static bool ot_entropy_src_dj_is_fips_enabled(const OtEntropySrcDjState *s); -static bool ot_entropy_src_dj_is_hw_route(const OtEntropySrcDjState *s); -static bool ot_entropy_src_dj_is_fips_capable(const OtEntropySrcDjState *s); -static void ot_entropy_src_dj_update_alerts(OtEntropySrcDjState *s); -static void ot_entropy_src_dj_update_filler(OtEntropySrcDjState *s); - -static int ot_entropy_src_dj_get_random( - OtRandomSrcIf *dev, uint64_t random[OT_RANDOM_SRC_DWORD_COUNT], bool *fips) -{ - OtEntropySrcDjState *s = OT_ENTROPY_SRC_DJ(dev); - - if (!ot_entropy_src_dj_is_module_enabled(s)) { - qemu_log_mask(LOG_GUEST_ERROR, "%s: entropy_src is down\n", __func__); - return -1; - } - - bool fips_compliant; - - switch (s->state) { - case ENTROPY_SRC_DJ_BOOT_PHASE_DONE: - fips_compliant = false; - break; - case ENTROPY_SRC_DJ_CONT_HT_RUNNING: - case ENTROPY_SRC_DJ_CONT_HT_START: - case ENTROPY_SRC_DJ_SHA3_MSGDONE: - case ENTROPY_SRC_DJ_SHA3_PREP: - case ENTROPY_SRC_DJ_SHA3_PROCESS: - case ENTROPY_SRC_DJ_SHA3_VALID: - case ENTROPY_SRC_DJ_SHA3_DONE: - fips_compliant = true; - break; - case ENTROPY_SRC_DJ_BOOT_HT_RUNNING: - case ENTROPY_SRC_DJ_BOOT_POST_HT_CHK: - case ENTROPY_SRC_DJ_STARTUP_HT_START: - case ENTROPY_SRC_DJ_STARTUP_PHASE1: - case ENTROPY_SRC_DJ_STARTUP_PASS1: - case ENTROPY_SRC_DJ_STARTUP_FAIL1: { - int64_t wait_ns; - if (timer_pending(s->scheduler)) { - /* computed delay fits into a 31-bit value */ - wait_ns = ((int64_t)timer_expire_time_ns(s->scheduler)) - - qemu_clock_get_ns(OT_VIRTUAL_CLOCK); - wait_ns = MAX(wait_ns, OT_ENTROPY_SRC_DJ_WAIT_DELAY_NS); - } else { - wait_ns = OT_ENTROPY_SRC_DJ_WAIT_DELAY_NS; - } - trace_ot_entropy_src_init_ongoing(STATE_NAME(s->state), s->state, - (int)wait_ns); - /* not ready */ - return (int)wait_ns; - } - case ENTROPY_SRC_DJ_IDLE: - qemu_log_mask(LOG_GUEST_ERROR, "%s: module is not enabled\n", __func__); - return -1; - case ENTROPY_SRC_DJ_FW_INSERT_START: - case ENTROPY_SRC_DJ_FW_INSERT_MSG: - case ENTROPY_SRC_DJ_SHA3_QUIESCE: /* this state is never emulated */ - case ENTROPY_SRC_DJ_ALERT_STATE: - case ENTROPY_SRC_DJ_ALERT_HANG: - case ENTROPY_SRC_DJ_ERROR: - default: - qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid state: [%s:%d]\n", __func__, - STATE_NAME(s->state), s->state); - return -1; - } - - if (!ot_entropy_src_dj_is_hw_route(s)) { - qemu_log_mask(LOG_GUEST_ERROR, "%s: HW route not selected\n", __func__); - return -1; - } - - if (ot_fifo32_num_used(&s->final_fifo) < ES_WORD_COUNT) { - trace_ot_entropy_src_no_entropy(ot_fifo32_num_used(&s->final_fifo)); - return OT_ENTROPY_SRC_DJ_WAIT_DELAY_NS; - } - - uint32_t *randu32 = (uint32_t *)random; - size_t pos = 0; - while (pos < ES_WORD_COUNT) { - g_assert(!ot_fifo32_is_empty(&s->final_fifo)); - randu32[pos++] = ot_fifo32_pop(&s->final_fifo); - } - - bool fips_capable = ot_entropy_src_dj_is_fips_capable(s); - - /* note: fips compliancy is only simulated here for now */ - *fips = fips_compliant && fips_capable; - - trace_ot_entropy_src_get_random_fips( - STATE_NAME(s->state), ot_entropy_src_dj_is_fips_enabled(s), - REG_MB4_IS_TRUE(s, ENTROPY_CONTROL, ES_ROUTE), - REG_MB4_IS_TRUE(s, ENTROPY_CONTROL, ES_TYPE), - REG_MB4_IS_FALSE(s, CONF, RNG_BIT_ENABLE), fips_capable, fips_compliant, - *fips); - - if (ot_fifo32_num_used(&s->final_fifo) < ES_WORD_COUNT) { - ot_entropy_src_dj_update_filler(s); - } - - return 0; -} - -/* -------------------------------------------------------------------------- */ -/* Private implementation */ -/* -------------------------------------------------------------------------- */ - -static void ot_entropy_src_dj_show_buffer( - const char *func, int line, const char *msg, const void *buf, unsigned size) -{ - if (trace_event_get_state(TRACE_OT_ENTROPY_SRC_SHOW_BUFFER) && - qemu_loglevel_mask(LOG_TRACE)) { - static const char _hex[] = "0123456789ABCDEF"; - char hexstr[ES_HEXBUF_SIZE]; - unsigned len = MIN(size, ES_HEXBUF_SIZE / 2u - 4u); - const uint8_t *pbuf = (const uint8_t *)buf; - memset(hexstr, 0, sizeof(hexstr)); - unsigned hix = 0; - for (unsigned ix = 0u; ix < len; ix++) { - if (ix && !(ix & 0x3u)) { - hexstr[hix++] = '-'; - } - hexstr[hix++] = _hex[(pbuf[ix] >> 4u) & 0xfu]; - hexstr[hix++] = _hex[pbuf[ix] & 0xfu]; - } - if (len < size) { - hexstr[hix++] = '.'; - hexstr[hix++] = '.'; - hexstr[hix++] = '.'; - } - - trace_ot_entropy_src_show_buffer(func, line, msg, hexstr); - } -} - -static bool ot_entropy_src_dj_is_module_enabled(const OtEntropySrcDjState *s) -{ - return REG_MB4_IS_TRUE(s, MODULE_ENABLE, MODULE_ENABLE); -} - -static bool ot_entropy_src_dj_is_module_disabled(const OtEntropySrcDjState *s) -{ - return REG_MB4_IS_FALSE(s, MODULE_ENABLE, MODULE_ENABLE); -} - -static bool ot_entropy_src_dj_is_fips_enabled(const OtEntropySrcDjState *s) -{ - return REG_MB4_IS_TRUE(s, CONF, FIPS_ENABLE); -} - -static void ot_entropy_src_dj_update_irqs(OtEntropySrcDjState *s) -{ - uint32_t levels = s->regs[R_INTR_STATE] & s->regs[R_INTR_ENABLE]; - for (unsigned ix = 0; ix < PARAM_NUM_IRQS; ix++) { - ibex_irq_set(&s->irqs[ix], (int)((levels >> ix) & 0x1u)); - } -} - -static bool -ot_entropy_src_dj_is_final_fifo_slot_available(const OtEntropySrcDjState *s) -{ - return ot_fifo32_num_free(&s->final_fifo) >= ES_WORD_COUNT; -} - -static bool ot_entropy_src_dj_is_hw_route(const OtEntropySrcDjState *s) -{ - return REG_MB4_IS_FALSE(s, ENTROPY_CONTROL, ES_ROUTE); -} - -static bool ot_entropy_src_dj_is_fw_route(const OtEntropySrcDjState *s) -{ - return REG_MB4_IS_TRUE(s, ENTROPY_CONTROL, ES_ROUTE); -} - -static bool ot_entropy_src_dj_is_bypass_mode(const OtEntropySrcDjState *s) -{ - return !ot_entropy_src_dj_is_fips_enabled(s) || - (ot_entropy_src_dj_is_fw_route(s) && - REG_MB4_IS_TRUE(s, ENTROPY_CONTROL, ES_TYPE)); -} - -static bool ot_entropy_src_dj_is_fw_ov_mode(const OtEntropySrcDjState *s) -{ - return REG_MB4_IS_TRUE(s, FW_OV_CONTROL, FW_OV_MODE); -} - -static bool -ot_entropy_src_dj_is_fw_ov_entropy_insert(const OtEntropySrcDjState *s) -{ - return REG_MB4_IS_TRUE(s, FW_OV_CONTROL, FW_OV_ENTROPY_INSERT); -} - -static bool ot_entropy_src_dj_is_fips_capable(const OtEntropySrcDjState *s) -{ - return ot_entropy_src_dj_is_fips_enabled(s) && - !(REG_MB4_IS_TRUE(s, ENTROPY_CONTROL, ES_ROUTE) && - REG_MB4_IS_TRUE(s, ENTROPY_CONTROL, ES_TYPE)) && - REG_MB4_IS_FALSE(s, CONF, RNG_BIT_ENABLE); -} - -static unsigned ot_alert_get_alert_fail_count(const OtEntropySrcDjState *s) -{ - unsigned count; - - count = FIELD_EX32(s->regs[R_ALERT_FAIL_COUNTS], ALERT_FAIL_COUNTS, - REPCNT_FAIL_COUNT); - count += FIELD_EX32(s->regs[R_ALERT_FAIL_COUNTS], ALERT_FAIL_COUNTS, - ADAPTP_HI_FAIL_COUNT); - count += FIELD_EX32(s->regs[R_ALERT_FAIL_COUNTS], ALERT_FAIL_COUNTS, - ADAPTP_LO_FAIL_COUNT); - count += FIELD_EX32(s->regs[R_ALERT_FAIL_COUNTS], ALERT_FAIL_COUNTS, - BUCKET_FAIL_COUNT); - count += FIELD_EX32(s->regs[R_ALERT_FAIL_COUNTS], ALERT_FAIL_COUNTS, - MARKOV_HI_FAIL_COUNT); - count += FIELD_EX32(s->regs[R_ALERT_FAIL_COUNTS], ALERT_FAIL_COUNTS, - MARKOV_LO_FAIL_COUNT); - count += FIELD_EX32(s->regs[R_ALERT_FAIL_COUNTS], ALERT_FAIL_COUNTS, - REPCNTS_FAIL_COUNT); - - return count; -} - -static void ot_entropy_src_dj_change_state_line( - OtEntropySrcDjState *s, OtEntropySrcDjFsmState state, int line) -{ - OtEntropySrcDjFsmState old_state = s->state; - - switch (s->state) { - case ENTROPY_SRC_DJ_ALERT_STATE: - s->state = ENTROPY_SRC_DJ_ALERT_HANG; - break; - case ENTROPY_SRC_DJ_ALERT_HANG: - if ((state == ENTROPY_SRC_DJ_IDLE) && - ot_entropy_src_dj_is_module_disabled(s)) { - s->state = state; - } - break; - default: - s->state = state; - break; - } - - if (old_state != s->state) { - trace_ot_entropy_src_change_state(line, STATE_NAME(old_state), - old_state, STATE_NAME(s->state), - s->state); - } - - if (s->state == ENTROPY_SRC_DJ_ERROR) { - s->regs[R_ERR_CODE] |= R_ERR_CODE_ES_MAIN_SM_ERR_MASK; - ot_entropy_src_dj_update_alerts(s); - } -} - -#define ot_entropy_src_dj_change_state(_s_, _st_) \ - ot_entropy_src_dj_change_state_line(_s_, _st_, __LINE__) - -static void ot_entropy_src_dj_update_alerts(OtEntropySrcDjState *s) -{ - unsigned alert_threshold = FIELD_EX32(s->regs[R_ALERT_THRESHOLD], - ALERT_THRESHOLD, ALERT_THRESHOLD); - unsigned alert_count = ot_alert_get_alert_fail_count(s); - bool recoverable = (bool)s->regs[R_RECOV_ALERT_STS]; - uint32_t level = s->regs[R_ALERT_TEST]; - if (alert_count >= alert_threshold || recoverable) { - level |= 1u << ALERT_RECOVERABLE; - } - uint32_t fatal_alert = s->regs[R_ERR_CODE] & ERR_CODE_FATAL_ERROR_MASK; - fatal_alert |= (1u << s->regs[R_ERR_CODE_TEST]) & ERR_CODE_FATAL_ERROR_MASK; - if (fatal_alert) { - level |= 1u << ALERT_FATAL; - } - - for (unsigned ix = 0; ix < PARAM_NUM_ALERTS; ix++) { - ibex_irq_set(&s->alerts[ix], (int)((level >> ix) & 0x1u)); - } -} - -static bool ot_entropy_src_dj_check_multibitboot( - OtEntropySrcDjState *s, uint8_t mbbool, uint32_t alert_bit) -{ - switch (mbbool) { - case OT_MULTIBITBOOL4_TRUE: - case OT_MULTIBITBOOL4_FALSE: - return true; - default: - break; - } - - s->regs[R_RECOV_ALERT_STS] |= 1u << alert_bit; - ot_entropy_src_dj_update_alerts(s); - return false; -} - -static bool ot_entropy_src_dj_can_consume_entropy(const OtEntropySrcDjState *s) -{ - return ot_entropy_src_dj_is_module_enabled(s) && - !(ot_entropy_src_dj_is_fw_ov_entropy_insert(s) && - !ot_entropy_src_dj_is_fw_ov_mode(s)); -} - -static void ot_entropy_src_dj_update_filler(OtEntropySrcDjState *s) -{ - /* fill granule is OT_ENTROPY_SRC_DJ_FILL_WORD_COUNT bits */ - bool input = - ot_fifo32_num_free(&s->input_fifo) >= OT_ENTROPY_SRC_DJ_FILL_WORD_COUNT; - bool output = ot_fifo32_num_free(&s->final_fifo) >= ES_WORD_COUNT; - bool process = ot_entropy_src_dj_can_consume_entropy(s); - - bool accept_entropy = input && output && process; - trace_ot_entropy_src_update_filler(input, output, process, accept_entropy); - - if (!accept_entropy) { - /* if cannot accept entropy, stop the entropy scheduler */ - if (timer_pending(s->scheduler)) { - trace_ot_entropy_src_info("stop scheduler"); - timer_del(s->scheduler); - } - } else { - /* - * if entropy can be handled, start the entropy scheduler if - * it is not already active - */ - if (!timer_pending(s->scheduler)) { - trace_ot_entropy_src_info("reschedule"); - uint64_t now = qemu_clock_get_ns(OT_VIRTUAL_CLOCK); - timer_mod(s->scheduler, (int64_t)(now + (uint64_t)ES_FILL_RATE_NS)); - } - } -} - -static bool -ot_entropy_src_dj_can_condition_entropy(const OtEntropySrcDjState *s) -{ - if (!ot_fifo32_is_full(&s->precon_fifo)) { - /* room in preconditioner packer */ - return true; - } - if (ot_entropy_src_dj_is_final_fifo_slot_available(s)) { - /* room in output FIFO */ - return true; - } - - return false; -} - -static bool ot_entropy_src_dj_can_bypass_entropy(const OtEntropySrcDjState *s) -{ - if (!ot_fifo32_is_full(&s->bypass_fifo)) { - /* room in bypass packer */ - return true; - } - if (ot_entropy_src_dj_is_final_fifo_slot_available(s)) { - /* room in output FIFO */ - return true; - } - - return false; -} - -static bool ot_entropy_src_dj_push_entropy_to_conditioner( - OtEntropySrcDjState *s, uint32_t word) -{ - int res; - if (s->cond_word == 0) { - res = sha3_384_init(&s->sha3_state); - ot_entropy_src_dj_change_state(s, ENTROPY_SRC_DJ_SHA3_PREP); - g_assert(res == CRYPT_OK); - } - - g_assert(!ot_fifo32_is_full(&s->precon_fifo)); - - ot_fifo32_push(&s->precon_fifo, word); - - if (!ot_fifo32_is_full(&s->precon_fifo)) { - return false; - } - - ot_entropy_src_dj_change_state(s, ENTROPY_SRC_DJ_SHA3_PROCESS); - - uint32_t size; - const uint32_t *buf; - buf = ot_fifo32_peek_buf(&s->precon_fifo, s->precon_fifo.num, &size); - g_assert(size == s->precon_fifo.num); - xtrace_ot_entropy_src_dj_show_buffer("sha3 in", buf, - size * sizeof(uint32_t)); - res = sha3_process(&s->sha3_state, (const uint8_t *)buf, - size * sizeof(uint32_t)); - g_assert(res == CRYPT_OK); - s->cond_word += size; - ot_fifo32_reset(&s->precon_fifo); - - return true; -} - -static bool ot_entropy_src_dj_can_hash(const OtEntropySrcDjState *s) -{ - return ot_fifo32_is_empty(&s->precon_fifo) && - (s->cond_word >= (2048 / (8u * sizeof(uint32_t)))); -} - -static void ot_entropy_src_dj_perform_hash(OtEntropySrcDjState *s) -{ - uint32_t hash[OT_RANDOM_SRC_WORD_COUNT]; - int res; - res = sha3_done(&s->sha3_state, (uint8_t *)hash); - g_assert(res == CRYPT_OK); - s->cond_word = 0; - - xtrace_ot_entropy_src_dj_show_buffer("sha3 md", hash, - OT_RANDOM_SRC_WORD_COUNT * - sizeof(uint32_t)); - - ot_entropy_src_dj_change_state(s, ENTROPY_SRC_DJ_SHA3_MSGDONE); - - for (unsigned ix = 0; ix < OT_RANDOM_SRC_WORD_COUNT; ix++) { - g_assert(!ot_fifo32_is_full(&s->final_fifo)); - ot_fifo32_push(&s->final_fifo, hash[ix]); - } - s->packet_count += 1u; - - ot_entropy_src_dj_change_state(s, REG_MB4_IS_TRUE(s, FW_OV_SHA3_START, - FW_OV_INSERT_START) ? - ENTROPY_SRC_DJ_IDLE : - ENTROPY_SRC_DJ_CONT_HT_START); -} - -static bool -ot_entropy_src_dj_push_bypass_entropy(OtEntropySrcDjState *s, uint32_t word) -{ - g_assert(!ot_fifo32_is_full(&s->bypass_fifo)); - - ot_fifo32_push(&s->bypass_fifo, word); - if (!ot_fifo32_is_full(&s->bypass_fifo)) { - /* need a whole OT_ENTROPY_SRC_DJ_PACKET_SIZE_BITS packet to move on */ - return false; - } - - /* bypass conditioner full/ready, empty it into the final FIFO */ - while (!ot_fifo32_is_empty(&s->bypass_fifo)) { - g_assert(!ot_fifo32_is_full(&s->final_fifo)); - ot_fifo32_push(&s->final_fifo, ot_fifo32_pop(&s->bypass_fifo)); - } - s->packet_count += 1u; - - trace_ot_entropy_src_push_bypass_entropy( - ot_fifo32_num_used(&s->final_fifo) / OT_RANDOM_SRC_WORD_COUNT); - - return true; -} - -static void ot_entropy_src_dj_update_fw_route(OtEntropySrcDjState *s) -{ - if (ot_fifo32_num_used(&s->final_fifo) >= ES_WORD_COUNT) { - trace_ot_entropy_src_info("FW ROUTE"); - if (ot_fifo32_is_empty(&s->swread_fifo)) { - /* refill swread FIFO */ - unsigned count = ES_WORD_COUNT; - while (count--) { - ot_fifo32_push(&s->swread_fifo, ot_fifo32_pop(&s->final_fifo)); - } - s->regs[R_INTR_STATE] |= INTR_ES_ENTROPY_VALID_MASK; - trace_ot_entropy_src_available(STATE_NAME(s->state), s->state); - ot_entropy_src_dj_update_filler(s); - } - } -} - -static bool -ot_entropy_src_dj_consume_entropy(OtEntropySrcDjState *s, uint32_t word) -{ - bool fill_obs_fifo = ot_entropy_src_dj_is_fw_ov_mode(s); - bool hw_path = !ot_entropy_src_dj_is_fw_ov_entropy_insert(s); - bool bypass = ot_entropy_src_dj_is_bypass_mode(s); - - if (hw_path) { - /* check that HW accept data */ - hw_path = bypass ? ot_entropy_src_dj_can_bypass_entropy(s) : - ot_entropy_src_dj_can_condition_entropy(s); - } - - if (!(fill_obs_fifo || hw_path)) { - /* no way to consume noise, stop here */ - trace_ot_entropy_src_info("cannot consume noise for now"); - return false; - } - - s->noise_count += 1u; - trace_ot_entropy_src_consume_entropy(fill_obs_fifo, bypass, hw_path, - s->noise_count); - - if (fill_obs_fifo) { - if (ot_fifo32_is_full(&s->observe_fifo)) { - trace_ot_entropy_src_error("observe FIFO overflow", - STATE_NAME(s->state), s->state); - s->regs[R_FW_OV_RD_FIFO_OVERFLOW] |= - R_FW_OV_RD_FIFO_OVERFLOW_VAL_MASK; - } else { - if (s->obs_fifo_en) { - unsigned threshold = s->regs[R_OBSERVE_FIFO_THRESH]; - ot_fifo32_push(&s->observe_fifo, word); - trace_ot_entropy_src_obs_fifo(ot_fifo32_num_used( - &s->observe_fifo), - threshold); - if (ot_fifo32_is_full(&s->observe_fifo)) { - /* can only be enabled back once the FIFO is emptied */ - trace_ot_entropy_src_info("observe FIFO is full"); - s->obs_fifo_en = false; - } - /* is it > or >= ? */ - if (ot_fifo32_num_used(&s->observe_fifo) >= threshold) { - s->regs[R_INTR_STATE] |= INTR_ES_OBSERVE_FIFO_READY_MASK; - } - } else { - trace_ot_entropy_src_info("observe FIFO not enabled"); - } - } - } - - if (hw_path) { - if (ot_entropy_src_dj_is_bypass_mode(s)) { - ot_entropy_src_dj_push_bypass_entropy(s, word); - } else { - if (ot_entropy_src_dj_push_entropy_to_conditioner(s, word)) { - if (ot_entropy_src_dj_can_hash(s)) { - trace_ot_entropy_src_info("can hash"); - ot_entropy_src_dj_perform_hash(s); - } - } - } - } - - if (ot_entropy_src_dj_is_fw_route(s)) { - ot_entropy_src_dj_update_fw_route(s); - } - - return true; -} - -static bool ot_entropy_src_dj_fill_noise(OtEntropySrcDjState *s) -{ - unsigned count = ot_fifo32_num_free(&s->input_fifo); - if (count < OT_ENTROPY_SRC_DJ_FILL_WORD_COUNT) { - /* no room left, should be resheduled */ - return false; - } - - uint32_t buffer[OT_ENTROPY_SRC_DJ_FILL_WORD_COUNT]; - /* synchronous read */ - ot_ast_eg_getrandom(buffer, sizeof(buffer)); - - /* push the whole entropy buffer into the input FIFO */ - unsigned pos = 0; - while (!ot_fifo32_is_full(&s->input_fifo) && pos < ARRAY_SIZE(buffer)) { - ot_fifo32_push(&s->input_fifo, buffer[pos++]); - } - - trace_ot_entropy_src_fill_noise(count, ot_fifo32_num_used(&s->input_fifo)); - - for (unsigned ix = 0; - ix < ES_WORD_COUNT && !ot_fifo32_is_empty(&s->input_fifo); ix++) { - if (!ot_entropy_src_dj_consume_entropy(s, - ot_fifo32_pop(&s->input_fifo))) { - break; - } - } - - ot_entropy_src_dj_update_irqs(s); - - return true; -} - -static void ot_entropy_src_dj_noise_refill(void *opaque) -{ - OtEntropySrcDjState *s = opaque; - - if (!ot_entropy_src_dj_fill_noise(s)) { - trace_ot_entropy_src_info("FIFO already filled up"); - return; - } - - switch (s->state) { - case ENTROPY_SRC_DJ_BOOT_HT_RUNNING: - if (s->packet_count > 0) { - ot_entropy_src_dj_change_state(s, ENTROPY_SRC_DJ_BOOT_PHASE_DONE); - } - break; - case ENTROPY_SRC_DJ_STARTUP_HT_START: - ot_entropy_src_dj_change_state(s, ENTROPY_SRC_DJ_CONT_HT_RUNNING); - break; - case ENTROPY_SRC_DJ_CONT_HT_RUNNING: - case ENTROPY_SRC_DJ_CONT_HT_START: - case ENTROPY_SRC_DJ_BOOT_PHASE_DONE: - case ENTROPY_SRC_DJ_SHA3_PREP: - case ENTROPY_SRC_DJ_SHA3_VALID: - case ENTROPY_SRC_DJ_SHA3_PROCESS: - case ENTROPY_SRC_DJ_SHA3_DONE: - case ENTROPY_SRC_DJ_SHA3_MSGDONE: - break; - default: - trace_ot_entropy_src_error("unexpected state", STATE_NAME(s->state), - s->state); - break; - } - - ot_entropy_src_dj_update_filler(s); -} - -static void ot_entropy_src_dj_scheduler(void *opaque) -{ - OtEntropySrcDjState *s = opaque; - - switch (s->state) { - case ENTROPY_SRC_DJ_BOOT_HT_RUNNING: - case ENTROPY_SRC_DJ_BOOT_PHASE_DONE: - case ENTROPY_SRC_DJ_STARTUP_HT_START: - case ENTROPY_SRC_DJ_CONT_HT_START: - case ENTROPY_SRC_DJ_CONT_HT_RUNNING: - case ENTROPY_SRC_DJ_SHA3_PREP: - case ENTROPY_SRC_DJ_SHA3_VALID: - case ENTROPY_SRC_DJ_SHA3_PROCESS: - case ENTROPY_SRC_DJ_SHA3_DONE: - case ENTROPY_SRC_DJ_SHA3_MSGDONE: - ot_entropy_src_dj_noise_refill(s); - break; - case ENTROPY_SRC_DJ_IDLE: - break; - case ENTROPY_SRC_DJ_BOOT_POST_HT_CHK: - case ENTROPY_SRC_DJ_STARTUP_PHASE1: - case ENTROPY_SRC_DJ_STARTUP_PASS1: - case ENTROPY_SRC_DJ_STARTUP_FAIL1: - case ENTROPY_SRC_DJ_FW_INSERT_START: - case ENTROPY_SRC_DJ_FW_INSERT_MSG: - case ENTROPY_SRC_DJ_SHA3_QUIESCE: - case ENTROPY_SRC_DJ_ALERT_STATE: - case ENTROPY_SRC_DJ_ALERT_HANG: - case ENTROPY_SRC_DJ_ERROR: - default: - qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid state: [%s:%d]\n", __func__, - STATE_NAME(s->state), s->state); - } - - ot_entropy_src_dj_update_alerts(s); - ot_entropy_src_dj_update_irqs(s); -} - -static uint64_t -ot_entropy_src_dj_regs_read(void *opaque, hwaddr addr, unsigned size) -{ - OtEntropySrcDjState *s = opaque; - (void)size; - uint32_t val32; - - hwaddr reg = R32_OFF(addr); - - switch (reg) { - case R_INTR_STATE: - case R_INTR_ENABLE: - case R_ME_REGWEN: - case R_SW_REGUPD: - case R_MODULE_ENABLE: - case R_CONF: - case R_ENTROPY_CONTROL: - case R_HEALTH_TEST_WINDOWS: - case R_REPCNT_THRESHOLDS: - case R_REPCNTS_THRESHOLDS: - case R_ADAPTP_HI_THRESHOLDS: - case R_ADAPTP_LO_THRESHOLDS: - case R_BUCKET_THRESHOLDS: - case R_MARKOV_HI_THRESHOLDS: - case R_MARKOV_LO_THRESHOLDS: - case R_EXTHT_HI_THRESHOLDS: - case R_EXTHT_LO_THRESHOLDS: - case R_REPCNT_HI_WATERMARKS: - case R_REPCNTS_HI_WATERMARKS: - case R_ADAPTP_HI_WATERMARKS: - case R_ADAPTP_LO_WATERMARKS: - case R_EXTHT_HI_WATERMARKS: - case R_EXTHT_LO_WATERMARKS: - case R_BUCKET_HI_WATERMARKS: - case R_MARKOV_HI_WATERMARKS: - case R_MARKOV_LO_WATERMARKS: - case R_REPCNT_TOTAL_FAILS: - case R_REPCNTS_TOTAL_FAILS: - case R_ADAPTP_HI_TOTAL_FAILS: - case R_ADAPTP_LO_TOTAL_FAILS: - case R_BUCKET_TOTAL_FAILS: - case R_MARKOV_HI_TOTAL_FAILS: - case R_MARKOV_LO_TOTAL_FAILS: - case R_EXTHT_HI_TOTAL_FAILS: - case R_EXTHT_LO_TOTAL_FAILS: - case R_ALERT_THRESHOLD: - case R_ALERT_FAIL_COUNTS: - case R_EXTHT_FAIL_COUNTS: - case R_FW_OV_CONTROL: - case R_FW_OV_SHA3_START: - case R_FW_OV_RD_FIFO_OVERFLOW: - case R_OBSERVE_FIFO_THRESH: - case R_RECOV_ALERT_STS: - case R_ERR_CODE: - case R_ERR_CODE_TEST: - val32 = s->regs[reg]; - break; - case R_DEBUG_STATUS: - /* SHA3 block reporting is not supported */ - val32 = FIELD_DP32(0, DEBUG_STATUS, ENTROPY_FIFO_DEPTH, - ot_fifo32_num_used(&s->final_fifo)); - val32 = FIELD_DP32(val32, DEBUG_STATUS, MAIN_SM_IDLE, - (uint32_t)(s->state == ENTROPY_SRC_DJ_IDLE)); - val32 = - FIELD_DP32(val32, DEBUG_STATUS, MAIN_SM_BOOT_DONE, - (uint32_t)(s->state == ENTROPY_SRC_DJ_BOOT_PHASE_DONE)); - break; - case R_MAIN_SM_STATE: - if (s->state < ARRAY_SIZE(OtEDNFsmStateCode)) { - val32 = OtEDNFsmStateCode[s->state]; - } else { - val32 = OtEDNFsmStateCode[ENTROPY_SRC_DJ_ERROR]; - } - break; - case R_REGWEN: - val32 = (uint32_t)(s->regs[R_SW_REGUPD] == R_SW_REGUPD_UPD_MASK && - ot_entropy_src_dj_is_module_disabled(s)); - break; - case R_ALERT_SUMMARY_FAIL_COUNTS: - val32 = (uint32_t)ot_alert_get_alert_fail_count(s); - break; - case R_ENTROPY_DATA: - if (ot_entropy_src_dj_is_module_enabled(s) && - REG_MB4_IS_TRUE(s, CONF, ENTROPY_DATA_REG_ENABLE) && - ot_entropy_src_dj_is_fw_route(s)) { - if (!ot_fifo32_is_empty(&s->swread_fifo)) { - val32 = ot_fifo32_pop(&s->swread_fifo); - } else { - qemu_log_mask(LOG_GUEST_ERROR, - "%s: Entropy data not available\n", __func__); - val32 = 0; - } - } else { - qemu_log_mask(LOG_GUEST_ERROR, "%s: Entropy data not configured\n", - __func__); - val32 = 0; - } - break; - case R_FW_OV_WR_FIFO_FULL: { - bool can_write; - if (ot_entropy_src_dj_is_fw_ov_mode(s) && - ot_entropy_src_dj_is_fw_ov_entropy_insert(s)) { - if (ot_entropy_src_dj_is_bypass_mode(s)) { - can_write = ot_entropy_src_dj_can_bypass_entropy(s); - } else { - can_write = ot_entropy_src_dj_can_condition_entropy(s); - } - } else { - can_write = false; - } - val32 = can_write ? 0u : R_FW_OV_WR_FIFO_FULL_VAL_MASK; - } break; - case R_FW_OV_RD_DATA: - if (ot_entropy_src_dj_is_fw_ov_mode(s)) { - if (!ot_fifo32_is_empty(&s->observe_fifo)) { - val32 = ot_fifo32_pop(&s->observe_fifo); - } else { - qemu_log_mask(LOG_GUEST_ERROR, - "%s: Read from empty observe FIFO\n", __func__); - val32 = 0; - } - } else { - qemu_log_mask(LOG_GUEST_ERROR, "%s: FW override mode not active\n", - __func__); - val32 = 0; - } - break; - case R_OBSERVE_FIFO_DEPTH: - val32 = ot_fifo32_num_used(&s->observe_fifo); - break; - case R_INTR_TEST: - case R_ALERT_TEST: - case R_FW_OV_WR_DATA: - qemu_log_mask(LOG_GUEST_ERROR, - "%s: W/O register 0x%02" HWADDR_PRIx " (%s)\n", __func__, - addr, REG_NAME(reg)); - val32 = 0; - break; - default: - qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n", - __func__, addr); - val32 = 0; - break; - } - - uint32_t pc = ibex_get_current_pc(); - trace_ot_entropy_src_io_read_out((uint32_t)addr, REG_NAME(reg), val32, pc); - - return (uint64_t)val32; -}; - -#define CHECK_MULTIBOOT(_s_, _r_, _b_) \ - do { \ - if (!ot_entropy_src_dj_check_multibitboot((_s_), \ - FIELD_EX32(s->regs[R_##_r_], \ - _r_, _b_), \ - ALERT_STATUS_BIT(_b_))) { \ - qemu_log_mask(LOG_GUEST_ERROR, \ - "%s: invalid multiboot value 0x%1x\n", __func__, \ - FIELD_EX32(s->regs[R_##_r_], _r_, _b_)); \ - } \ - } while (0) - -static void ot_entropy_src_dj_regs_write(void *opaque, hwaddr addr, - uint64_t val64, unsigned size) -{ - OtEntropySrcDjState *s = opaque; - (void)size; - uint32_t val32 = (uint32_t)val64; - - hwaddr reg = R32_OFF(addr); - - uint32_t pc = ibex_get_current_pc(); - trace_ot_entropy_src_io_write((uint32_t)addr, REG_NAME(reg), val32, pc); - - switch (reg) { - case R_INTR_STATE: - val32 &= INTR_MASK; - s->regs[reg] &= ~val32; /* RW1C */ - /* not sure about this behavior, seems to be what the tests expect... */ - if (!ot_fifo32_is_empty(&s->swread_fifo)) { - s->regs[R_INTR_STATE] |= INTR_ES_ENTROPY_VALID_MASK; - } - if (!ot_fifo32_is_empty(&s->observe_fifo)) { - s->regs[R_INTR_STATE] |= INTR_ES_OBSERVE_FIFO_READY_MASK; - } - ot_entropy_src_dj_update_irqs(s); - break; - case R_INTR_ENABLE: - val32 &= INTR_MASK; - s->regs[reg] = val32; - ot_entropy_src_dj_update_irqs(s); - break; - case R_INTR_TEST: - val32 &= INTR_MASK; - s->regs[R_INTR_STATE] |= val32; - ot_entropy_src_dj_update_irqs(s); - break; - case R_ALERT_TEST: - val32 &= ALERT_TEST_MASK; - s->regs[reg] = val32; - ot_entropy_src_dj_update_alerts(s); - break; - case R_ME_REGWEN: - val32 &= R_ME_REGWEN_EN_MASK; - s->regs[reg] &= val32; /* RW0C */ - break; - case R_SW_REGUPD: - val32 &= R_SW_REGUPD_UPD_MASK; - s->regs[reg] &= val32; /* RW0C */ - break; - case R_MODULE_ENABLE: - if (s->regs[R_ME_REGWEN]) { - uint32_t old = s->regs[reg]; - val32 &= R_MODULE_ENABLE_MODULE_ENABLE_MASK; - s->regs[reg] = val32; - CHECK_MULTIBOOT(s, MODULE_ENABLE, MODULE_ENABLE); - if (ot_entropy_src_dj_is_module_disabled(s)) { - /* reset takes care of cancelling the scheduler timer */ - resettable_reset(OBJECT(s), RESET_TYPE_COLD); - break; - } - if ((old ^ s->regs[reg]) && - ot_entropy_src_dj_is_module_enabled(s)) { - if (ot_entropy_src_dj_is_fips_enabled(s)) { - /* start up phase */ - ot_entropy_src_dj_change_state( - s, ENTROPY_SRC_DJ_STARTUP_HT_START); - } else { - /* boot phase */ - ot_entropy_src_dj_change_state( - s, ENTROPY_SRC_DJ_BOOT_HT_RUNNING); - } - uint64_t now = qemu_clock_get_ns(OT_VIRTUAL_CLOCK); - timer_mod(s->scheduler, - (int64_t)(now + - (uint64_t)OT_ENTROPY_SRC_DJ_BOOT_DELAY_NS)); - } - break; - } - qemu_log_mask(LOG_GUEST_ERROR, "%s: ME_REGWEN not enabled\n", __func__); - break; - case R_CONF: - if (s->regs[R_REGWEN]) { - val32 &= CONF_MASK; - s->regs[reg] = val32; - CHECK_MULTIBOOT(s, CONF, FIPS_ENABLE); - CHECK_MULTIBOOT(s, CONF, ENTROPY_DATA_REG_ENABLE); - CHECK_MULTIBOOT(s, CONF, THRESHOLD_SCOPE); - CHECK_MULTIBOOT(s, CONF, RNG_BIT_ENABLE); - } - break; - case R_ENTROPY_CONTROL: - if (s->regs[R_REGWEN]) { - val32 &= ENTROPY_CONTROL_MASK; - s->regs[reg] = val32; - CHECK_MULTIBOOT(s, ENTROPY_CONTROL, ES_ROUTE); - CHECK_MULTIBOOT(s, ENTROPY_CONTROL, ES_TYPE); - } - break; - case R_HEALTH_TEST_WINDOWS: - if (s->regs[R_REGWEN]) { - s->regs[reg] = val32; - } - break; - case R_REPCNT_THRESHOLDS: - case R_REPCNTS_THRESHOLDS: - case R_ADAPTP_HI_THRESHOLDS: - case R_ADAPTP_LO_THRESHOLDS: - case R_BUCKET_THRESHOLDS: - case R_MARKOV_HI_THRESHOLDS: - case R_MARKOV_LO_THRESHOLDS: - case R_EXTHT_HI_THRESHOLDS: - case R_EXTHT_LO_THRESHOLDS: - if (s->regs[R_REGWEN]) { - s->regs[reg] = val32; - ot_entropy_src_dj_update_alerts(s); - } - break; - case R_ALERT_THRESHOLD: - if (s->regs[R_REGWEN]) { - if ((uint16_t)(val32) != (uint16_t)(~(val32 >> 16u))) { - s->regs[R_RECOV_ALERT_STS] |= - R_RECOV_ALERT_STS_ES_THRESH_CFG_ALERT_MASK; - } else { - s->regs[reg] = val32; - } - ot_entropy_src_dj_update_alerts(s); - } - break; - case R_FW_OV_CONTROL: - if (s->regs[R_REGWEN]) { - val32 &= FW_OV_CONTROL_MASK; - s->regs[reg] = val32; - CHECK_MULTIBOOT(s, FW_OV_CONTROL, FW_OV_MODE); - CHECK_MULTIBOOT(s, FW_OV_CONTROL, FW_OV_ENTROPY_INSERT); - s->obs_fifo_en = ot_entropy_src_dj_is_fw_ov_mode(s); - } - break; - case R_FW_OV_SHA3_START: - if (!ot_entropy_src_dj_is_module_enabled(s)) { - qemu_log_mask(LOG_GUEST_ERROR, "%s: module not enabled\n", - __func__); - break; - } - val32 &= R_FW_OV_SHA3_START_FW_OV_INSERT_START_MASK; - s->regs[reg] = val32; - CHECK_MULTIBOOT(s, FW_OV_SHA3_START, FW_OV_INSERT_START); - if (REG_MB4_IS_TRUE(s, FW_OV_SHA3_START, FW_OV_INSERT_START)) { - OtEntropySrcDjFsmState new_state; - new_state = ot_entropy_src_dj_is_bypass_mode(s) ? - ENTROPY_SRC_DJ_IDLE : - ENTROPY_SRC_DJ_FW_INSERT_START; - ot_entropy_src_dj_change_state(s, new_state); - } else { /* default to false */ - if (s->state == ENTROPY_SRC_DJ_SHA3_PROCESS) { - /* handle SHA3 processing */ - if (ot_fifo32_is_empty(&s->precon_fifo)) { - ot_entropy_src_dj_perform_hash(s); - if (ot_entropy_src_dj_is_fw_route(s)) { - ot_entropy_src_dj_update_fw_route(s); - } - } else { - qemu_log_mask(LOG_GUEST_ERROR, "%s: need 1 more word\n", - __func__); - } - } else { - OtEntropySrcDjFsmState new_state; - new_state = ot_entropy_src_dj_is_bypass_mode(s) ? - ENTROPY_SRC_DJ_BOOT_HT_RUNNING : - ENTROPY_SRC_DJ_STARTUP_HT_START; - ot_entropy_src_dj_change_state(s, new_state); - } - } - break; - case R_FW_OV_RD_FIFO_OVERFLOW: - val32 &= R_FW_OV_RD_FIFO_OVERFLOW_VAL_MASK; - s->regs[reg] &= val32; /* RW0C */ - break; - case R_FW_OV_WR_DATA: - if (!ot_entropy_src_dj_is_module_enabled(s)) { - qemu_log_mask(LOG_GUEST_ERROR, "%s: module not enabled\n", - __func__); - break; - } - if (ot_entropy_src_dj_is_fw_ov_mode(s) && - ot_entropy_src_dj_is_fw_ov_entropy_insert(s)) { - bool can_write; - if (ot_entropy_src_dj_is_bypass_mode(s)) { - can_write = ot_entropy_src_dj_can_bypass_entropy(s); - if (can_write) { - ot_entropy_src_dj_push_bypass_entropy(s, val32); - } - } else { - can_write = ot_entropy_src_dj_can_condition_entropy(s); - if (can_write) { - ot_entropy_src_dj_push_entropy_to_conditioner(s, val32); - } - } - if (!can_write) { - qemu_log_mask(LOG_GUEST_ERROR, "%s: FW override: FIFO full\n", - __func__); - } - } else { - qemu_log_mask(LOG_GUEST_ERROR, "%s: FW override mode not active\n", - __func__); - } - break; - case R_OBSERVE_FIFO_THRESH: - if (s->regs[R_REGWEN]) { - val32 &= R_OBSERVE_FIFO_THRESH_VAL_MASK; - s->regs[reg] = val32; - ot_entropy_src_dj_update_irqs(s); - } - break; - case R_RECOV_ALERT_STS: - val32 &= RECOV_ALERT_STS_MASK; - s->regs[reg] &= val32; /* RW0C */ - break; - case R_ERR_CODE_TEST: - val32 &= R_ERR_CODE_TEST_VAL_MASK; - s->regs[R_ERR_CODE_TEST] = val32; - ot_entropy_src_dj_update_irqs(s); - ot_entropy_src_dj_update_alerts(s); - break; - case R_REGWEN: - case R_ENTROPY_DATA: - case R_REPCNT_HI_WATERMARKS: - case R_REPCNTS_HI_WATERMARKS: - case R_ADAPTP_HI_WATERMARKS: - case R_ADAPTP_LO_WATERMARKS: - case R_EXTHT_HI_WATERMARKS: - case R_EXTHT_LO_WATERMARKS: - case R_BUCKET_HI_WATERMARKS: - case R_MARKOV_HI_WATERMARKS: - case R_MARKOV_LO_WATERMARKS: - case R_REPCNT_TOTAL_FAILS: - case R_REPCNTS_TOTAL_FAILS: - case R_ADAPTP_HI_TOTAL_FAILS: - case R_ADAPTP_LO_TOTAL_FAILS: - case R_BUCKET_TOTAL_FAILS: - case R_MARKOV_HI_TOTAL_FAILS: - case R_MARKOV_LO_TOTAL_FAILS: - case R_EXTHT_HI_TOTAL_FAILS: - case R_EXTHT_LO_TOTAL_FAILS: - case R_ALERT_SUMMARY_FAIL_COUNTS: - case R_ALERT_FAIL_COUNTS: - case R_EXTHT_FAIL_COUNTS: - case R_FW_OV_WR_FIFO_FULL: - case R_FW_OV_RD_DATA: - case R_OBSERVE_FIFO_DEPTH: - case R_DEBUG_STATUS: - case R_ERR_CODE: - case R_MAIN_SM_STATE: - qemu_log_mask(LOG_GUEST_ERROR, - "%s: R/O register 0x%02" HWADDR_PRIx " (%s)\n", __func__, - addr, REG_NAME(reg)); - break; - default: - qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n", - __func__, addr); - break; - } -}; - -static Property ot_entropy_src_dj_properties[] = { - DEFINE_PROP_LINK("ast", OtEntropySrcDjState, ast, TYPE_OT_AST_EG, - OtASTEgState *), - DEFINE_PROP_LINK("otp_ctrl", OtEntropySrcDjState, otp_ctrl, TYPE_OT_OTP, - OtOTPState *), - DEFINE_PROP_END_OF_LIST(), -}; - -static const MemoryRegionOps ot_entropy_src_dj_regs_ops = { - .read = &ot_entropy_src_dj_regs_read, - .write = &ot_entropy_src_dj_regs_write, - .endianness = DEVICE_NATIVE_ENDIAN, - .impl.min_access_size = 4u, - .impl.max_access_size = 4u, -}; - -static void ot_entropy_src_dj_reset_enter(Object *obj, ResetType type) -{ - OtEntropySrcDjClass *c = OT_ENTROPY_SRC_DJ_GET_CLASS(obj); - OtEntropySrcDjState *s = OT_ENTROPY_SRC_DJ(obj); - - trace_ot_entropy_src_reset(); - - if (c->parent_phases.enter) { - c->parent_phases.enter(obj, type); - } - - timer_del(s->scheduler); - - memset(s->regs, 0, REGS_SIZE); - - s->regs[R_ME_REGWEN] = 0x1u; - s->regs[R_SW_REGUPD] = 0x1u; - s->regs[R_REGWEN] = 0x1u; - s->regs[R_MODULE_ENABLE] = 0x9u; - s->regs[R_CONF] = 0x2649999u; - s->regs[R_ENTROPY_CONTROL] = 0x99u; - s->regs[R_HEALTH_TEST_WINDOWS] = 0x600200u; - s->regs[R_REPCNT_THRESHOLDS] = 0xffffffffu; - s->regs[R_REPCNTS_THRESHOLDS] = 0xffffffffu; - s->regs[R_ADAPTP_HI_THRESHOLDS] = 0xffffffffu; - s->regs[R_BUCKET_THRESHOLDS] = 0xffffffffu; - s->regs[R_MARKOV_HI_THRESHOLDS] = 0xffffffffu; - s->regs[R_EXTHT_HI_THRESHOLDS] = 0xffffffffu; - s->regs[R_ADAPTP_LO_WATERMARKS] = 0xffffffffu; - s->regs[R_EXTHT_LO_WATERMARKS] = 0xffffffffu; - s->regs[R_MARKOV_LO_WATERMARKS] = 0xffffffffu; - s->regs[R_ALERT_THRESHOLD] = 0xfffd0002u; - s->regs[R_FW_OV_CONTROL] = 0x99u; - s->regs[R_FW_OV_SHA3_START] = 0x9u; - s->regs[R_OBSERVE_FIFO_THRESH] = 0x10u; - s->regs[R_DEBUG_STATUS] = 0x10000u; - - ot_fifo32_reset(&s->input_fifo); - ot_fifo32_reset(&s->precon_fifo); - ot_fifo32_reset(&s->bypass_fifo); - ot_fifo32_reset(&s->observe_fifo); - ot_fifo32_reset(&s->swread_fifo); - ot_fifo32_reset(&s->final_fifo); - - s->cond_word = 0u; - s->noise_count = 0u; - s->packet_count = 0u; - s->obs_fifo_en = false; - - ot_entropy_src_dj_update_irqs(s); - for (unsigned ix = 0; ix < PARAM_NUM_ALERTS; ix++) { - ibex_irq_set(&s->alerts[ix], 0); - } - - OtOTPClass *oc = OBJECT_GET_CLASS(OtOTPClass, s->otp_ctrl, TYPE_OT_OTP); - const OtOTPEntropyCfg *entropy_cfg = oc->get_entropy_cfg(s->otp_ctrl); - g_assert(entropy_cfg); - - ot_entropy_src_dj_change_state(s, ENTROPY_SRC_DJ_IDLE); -} - -static void ot_entropy_src_dj_realize(DeviceState *dev, Error **errp) -{ - (void)errp; - - OtEntropySrcDjState *s = OT_ENTROPY_SRC_DJ(dev); - - g_assert(s->ast); - g_assert(s->otp_ctrl); -} - -static void ot_entropy_src_dj_init(Object *obj) -{ - OtEntropySrcDjState *s = OT_ENTROPY_SRC_DJ(obj); - - memory_region_init_io(&s->mmio, obj, &ot_entropy_src_dj_regs_ops, s, - TYPE_OT_ENTROPY_SRC_DJ, REGS_SIZE); - sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->mmio); - - s->regs = g_new0(uint32_t, REGS_COUNT); - for (unsigned ix = 0; ix < PARAM_NUM_IRQS; ix++) { - ibex_sysbus_init_irq(obj, &s->irqs[ix]); - } - for (unsigned ix = 0; ix < PARAM_NUM_ALERTS; ix++) { - ibex_qdev_init_irq(obj, &s->alerts[ix], OT_DEVICE_ALERT); - } - - ot_fifo32_create(&s->input_fifo, OT_ENTROPY_SRC_DJ_FILL_WORD_COUNT * 2u); - ot_fifo32_create(&s->precon_fifo, sizeof(uint64_t) / sizeof(uint32_t)); - ot_fifo32_create(&s->bypass_fifo, ES_WORD_COUNT); - ot_fifo32_create(&s->observe_fifo, PARAM_OBSERVE_FIFO_DEPTH); - ot_fifo32_create(&s->swread_fifo, ES_SWREAD_FIFO_WORD_COUNT); - ot_fifo32_create(&s->final_fifo, ES_FINAL_FIFO_WORD_COUNT); - - s->scheduler = - timer_new_ns(OT_VIRTUAL_CLOCK, &ot_entropy_src_dj_scheduler, s); -} - -static void ot_entropy_src_dj_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - (void)data; - - dc->realize = &ot_entropy_src_dj_realize; - device_class_set_props(dc, ot_entropy_src_dj_properties); - set_bit(DEVICE_CATEGORY_MISC, dc->categories); - - ResettableClass *rc = RESETTABLE_CLASS(klass); - OtEntropySrcDjClass *ec = OT_ENTROPY_SRC_DJ_CLASS(klass); - resettable_class_set_parent_phases(rc, &ot_entropy_src_dj_reset_enter, NULL, - NULL, &ec->parent_phases); - - OtRandomSrcIfClass *rdc = OT_RANDOM_SRC_IF_CLASS(klass); - rdc->get_random_values = &ot_entropy_src_dj_get_random; -} - -static const TypeInfo ot_entropy_src_dj_info = { - .name = TYPE_OT_ENTROPY_SRC_DJ, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(OtEntropySrcDjState), - .instance_init = &ot_entropy_src_dj_init, - .class_size = sizeof(OtEntropySrcDjClass), - .class_init = &ot_entropy_src_dj_class_init, - .interfaces = - (InterfaceInfo[]){ - { TYPE_OT_RANDOM_SRC_IF }, - {}, - }, -}; - -static void ot_entropy_src_dj_register_types(void) -{ - type_register_static(&ot_entropy_src_dj_info); -} - -type_init(ot_entropy_src_dj_register_types); diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig index 76e503af08d7..18ea1b3ce6cc 100644 --- a/hw/riscv/Kconfig +++ b/hw/riscv/Kconfig @@ -33,7 +33,7 @@ config OT_DARJEELING select OT_DEV_PROXY select OT_DM_TL select OT_DMA - select OT_ENTROPY_SRC_DJ + select OT_ENTROPY_SRC select OT_EDN select OT_GPIO_DJ select OT_HMAC @@ -78,7 +78,7 @@ config OT_EARLGREY select OT_CLKMGR select OT_CSRNG select OT_EDN - select OT_ENTROPY_SRC_EG + select OT_ENTROPY_SRC select OT_FLASH select OT_GPIO_EG select OT_HMAC diff --git a/hw/riscv/ot_darjeeling.c b/hw/riscv/ot_darjeeling.c index d4d92f0495c7..5d646ded929d 100644 --- a/hw/riscv/ot_darjeeling.c +++ b/hw/riscv/ot_darjeeling.c @@ -44,7 +44,7 @@ #include "hw/opentitan/ot_dm_tl.h" #include "hw/opentitan/ot_dma.h" #include "hw/opentitan/ot_edn.h" -#include "hw/opentitan/ot_entropy_src_dj.h" +#include "hw/opentitan/ot_entropy_src.h" #include "hw/opentitan/ot_gpio_dj.h" #include "hw/opentitan/ot_hmac.h" #include "hw/opentitan/ot_i2c.h" @@ -745,45 +745,23 @@ static const IbexDeviceDef ot_dj_soc_devices[] = { ), }, [OT_DJ_SOC_DEV_ENTROPY_SRC] = { - .type = TYPE_OT_UNIMP, - .cfg = &ibex_unimp_configure, + .type = TYPE_OT_ENTROPY_SRC, .memmap = MEMMAPENTRIES( - { .base = 0x21160000u } - ), - .prop = IBEXDEVICEPROPDEFS( - IBEX_DEV_STRING_PROP(OT_COMMON_DEV_ID, "entropy_src"), - IBEX_DEV_UINT_PROP("size", 0x100u), - IBEX_DEV_UINT_PROP("alert-count", 2u), - IBEX_DEV_BOOL_PROP("warn-once", true) + { .base = 0x21160000u } ), .gpio = IBEXGPIOCONNDEFS( - OT_DJ_SOC_GPIO_ALERT(0, 35), - OT_DJ_SOC_GPIO_ALERT(1, 36) + OT_DJ_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 89), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 90), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(2, PLIC, 91), + OT_DJ_SOC_GPIO_SYSBUS_IRQ(3, PLIC, 92), + OT_DJ_SOC_GPIO_ALERT(0, 35), + OT_DJ_SOC_GPIO_ALERT(1, 36) + ), + .link = IBEXDEVICELINKDEFS( + OT_DJ_SOC_DEVLINK("ast", AST), + OT_DJ_SOC_DEVLINK("otp_ctrl", OTP_CTRL) ), }, - /* - * @todo enable DJ entropy source once implemented, replacing the above - * unimplemented fake device - * - * [OT_DJ_SOC_DEV_ENTROPY_SRC] = { - * .type = TYPE_OT_ENTROPY_SRC, - * .memmap = MEMMAPENTRIES( - * { .base = 0x21160000u } - * ), - * .gpio = IBEXGPIOCONNDEFS( - * OT_DJ_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 89), - * OT_DJ_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 90), - * OT_DJ_SOC_GPIO_SYSBUS_IRQ(2, PLIC, 91), - * OT_DJ_SOC_GPIO_SYSBUS_IRQ(3, PLIC, 92), - * OT_DJ_SOC_GPIO_ALERT(0, 35), - * OT_DJ_SOC_GPIO_ALERT(1, 36) - * ), - * .link = IBEXDEVICELINKDEFS( - * OT_DJ_SOC_DEVLINK("ast", AST), - * OT_DJ_SOC_DEVLINK("otp_ctrl", OTP_CTRL) - * ), - * }, - */ [OT_DJ_SOC_DEV_EDN0] = { .type = TYPE_OT_EDN, .memmap = MEMMAPENTRIES( diff --git a/hw/riscv/ot_earlgrey.c b/hw/riscv/ot_earlgrey.c index 0bb082af3e0f..ddd3fdd47c5f 100644 --- a/hw/riscv/ot_earlgrey.c +++ b/hw/riscv/ot_earlgrey.c @@ -46,7 +46,7 @@ #include "hw/opentitan/ot_common.h" #include "hw/opentitan/ot_csrng.h" #include "hw/opentitan/ot_edn.h" -#include "hw/opentitan/ot_entropy_src_eg.h" +#include "hw/opentitan/ot_entropy_src.h" #include "hw/opentitan/ot_flash.h" #include "hw/opentitan/ot_gpio_eg.h" #include "hw/opentitan/ot_hmac.h" @@ -1233,7 +1233,7 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { ), }, [OT_EG_SOC_DEV_ENTROPY_SRC] = { - .type = TYPE_OT_ENTROPY_SRC_EG, + .type = TYPE_OT_ENTROPY_SRC, .memmap = MEMMAPENTRIES( { .base = 0x41160000u } ), diff --git a/include/hw/opentitan/ot_entropy_src_dj.h b/include/hw/opentitan/ot_entropy_src.h similarity index 80% rename from include/hw/opentitan/ot_entropy_src_dj.h rename to include/hw/opentitan/ot_entropy_src.h index 7aa1ea225287..3d981f14b64d 100644 --- a/include/hw/opentitan/ot_entropy_src_dj.h +++ b/include/hw/opentitan/ot_entropy_src.h @@ -1,5 +1,5 @@ /* - * QEMU OpenTitan Darjeeling Entropy Source device + * QEMU OpenTitan Entropy Source device * * Copyright (c) 2023-2025 Rivos, Inc. * Copyright (c) 2025 lowRISC contributors. @@ -26,12 +26,12 @@ * THE SOFTWARE. */ -#ifndef HW_OPENTITAN_OT_ENTROPY_SRC_DJ_H -#define HW_OPENTITAN_OT_ENTROPY_SRC_DJ_H +#ifndef HW_OPENTITAN_OT_ENTROPY_SRC_H +#define HW_OPENTITAN_OT_ENTROPY_SRC_H #include "qom/object.h" -#define TYPE_OT_ENTROPY_SRC_DJ "ot-entropy_src-dj" -OBJECT_DECLARE_TYPE(OtEntropySrcDjState, OtEntropySrcDjClass, OT_ENTROPY_SRC_DJ) +#define TYPE_OT_ENTROPY_SRC "ot-entropy_src" +OBJECT_DECLARE_TYPE(OtEntropySrcState, OtEntropySrcClass, OT_ENTROPY_SRC) -#endif /* HW_OPENTITAN_OT_ENTROPY_SRC_DJ_H */ +#endif /* HW_OPENTITAN_OT_ENTROPY_SRC_H */ diff --git a/include/hw/opentitan/ot_entropy_src_eg.h b/include/hw/opentitan/ot_entropy_src_eg.h deleted file mode 100644 index cd76e8303bbe..000000000000 --- a/include/hw/opentitan/ot_entropy_src_eg.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * QEMU OpenTitan Earlgrey 1.0.0 Entropy Source device - * - * Copyright (c) 2023-2025 Rivos, Inc. - * Copyright (c) 2025 lowRISC contributors. - * - * Author(s): - * Emmanuel Blot - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef HW_OPENTITAN_OT_ENTROPY_SRC_EG_H -#define HW_OPENTITAN_OT_ENTROPY_SRC_EG_H - -#include "qom/object.h" - -#define TYPE_OT_ENTROPY_SRC_EG "ot-entropy_src-eg" -OBJECT_DECLARE_TYPE(OtEntropySrcEgState, OtEntropySrcEgClass, OT_ENTROPY_SRC_EG) - -#endif /* HW_OPENTITAN_OT_ENTROPY_SRC_EG_H */ From 0002e8c4155b8ab7329c3ef3c61d429c3b86c342 Mon Sep 17 00:00:00 2001 From: Emmanuel Blot Date: Wed, 29 Oct 2025 13:43:22 +0100 Subject: [PATCH 02/18] [ot] hw/opentitan: ot_entropy_src: add support for multiple versions Support either version 2 or 3. Both versions are mostly similar, however a "REV" register has been added in v2 then removed in v3. This register stands at the 8th register slot. This causes most of the register map to shift down on v3 compared to v2. The version upgrade also introduces a couple of bitfield permutations and width changes in other registers. Add a new property to select the version to use. To address the register map shifting, split the register map in 3 segments: * lo: for registers before the REV register, whose base address is the same for both versions * rev: for the register which has been introduced in v2 and removed in v3 * hi: for the registers located after the REV register, whose base address depends on the presence of the REV register, i.e. whether emulutating v2 or v3 Use QEMU sub memory regions to map each register segment to the proper location based on the selected version. The addresses of each segment defined with REG32 macros are made relative to the start location of the matching segment. Traces reporting addresses are updated with the base address of each segment to preserve the "natural" address of each register. In order to avoid many offset computations and degrade code readability, also split the register array to support on array for each segment. Update macros to use the select the proper segment while addressing the register content. To address the register bitfield permutations/widening, as the scope of these changes is limited, simply dispatch handling based on the selected version. Signed-off-by: Emmanuel Blot --- hw/opentitan/ot_entropy_src.c | 1161 +++++++++++++++++++++------------ hw/opentitan/trace-events | 32 +- 2 files changed, 751 insertions(+), 442 deletions(-) diff --git a/hw/opentitan/ot_entropy_src.c b/hw/opentitan/ot_entropy_src.c index 8ea0006a079a..109309b44901 100644 --- a/hw/opentitan/ot_entropy_src.c +++ b/hw/opentitan/ot_entropy_src.c @@ -29,6 +29,9 @@ * - missing correct handling of ALERT_FAIL_COUNTS, currently never incremented. * - missing some error handling? ES_MAIN_SM_ERR is the only error that can be * triggered. + * + * v2: based on OpenTitan 011b6ea1fe + * v3: based on OpenTitan 5fe6fe8605 */ #include "qemu/osdep.h" @@ -51,85 +54,121 @@ #include "trace.h" -#define PARAM_NUM_IRQS 4u -#define PARAM_NUM_ALERTS 2u -#define PARAM_OBSERVE_FIFO_DEPTH 64u /* 2048 bits */ +#define NUM_ALERTS 2u +#define NUM_IRQS 4u +#define DISTR_FIFO_V2_DEPTH 2u +#define DISTR_FIFO_V3_DEPTH 3u +#define ES_FIFO_DEPTH 3u +#define OBSERVE_FIFO_DEPTH 32u +/* only in v3 */ +#define RNG_BUS_WIDTH 4u +#define RNG_BUS_BIT_SEL_WIDTH 2u +#define HEALTH_TEST_WINDOW_WIDTH 18u + +/* + * Note about the register split into different groups: + * ENTROPY_SRC module is supported in two variants, v2 and v3 + * There are very similar, but unfortunately v2 introduces a "version register" + * which has been subsequently removed in v3, and this register is inserted + * between other registers. This cause the address of all the subsequent + * registers that follow to shift down 4 bytes. In order for QEMU to support + * both versions with the same implementation, registers are therefore split + * into two groups, called "lo" and "hi", which are located on each side of + * the deprecated REV register. The register groups are mapped using two + * different memory regions, in order to simplify support for both versions. + * + * There are a couple of register bitfields that also differ between versions, + * namely the CONF and RECOV_ALERT_STS register, whose handling is specific + * to the instantiated module version. + */ /* clang-format off */ -REG32(INTR_STATE, 0x0u) + +/* first group of registers, "lo" */ +REG32(INTR_STATE, 0x00u) SHARED_FIELD(INTR_ES_ENTROPY_VALID, 0u, 1u) SHARED_FIELD(INTR_ES_HEALTH_TEST_FAILED, 1u, 1u) SHARED_FIELD(INTR_ES_OBSERVE_FIFO_READY, 2u, 1u) SHARED_FIELD(INTR_ES_FATAL_ERR, 3u, 1u) -REG32(INTR_ENABLE, 0x4u) -REG32(INTR_TEST, 0x8u) -REG32(ALERT_TEST, 0xcu) +REG32(INTR_ENABLE, 0x04u) +REG32(INTR_TEST, 0x08u) +REG32(ALERT_TEST, 0x0cu) FIELD(ALERT_TEST, RECOV_ALERT, 0u, 1u) FIELD(ALERT_TEST, FATAL_ALERT, 1u, 1u) REG32(ME_REGWEN, 0x10u) FIELD(ME_REGWEN, EN, 0u, 1u) REG32(SW_REGUPD, 0x14u) - FIELD(SW_REGUPD, UPD, 0u, 1u) + FIELD(SW_REGUPD, VAL, 0u, 1u) REG32(REGWEN, 0x18u) FIELD(REGWEN, EN, 0u, 1u) -REG32(REV, 0x1cu) + +/* second group of registers, "rev", only used with v2 */ +REG32(REV, 0x00u) FIELD(REV, ABI_REVISION, 0u, 8u) FIELD(REV, HW_REVISION, 8u, 8u) FIELD(REV, CHIP_TYPE, 16u, 8u) -REG32(MODULE_ENABLE, 0x20u) + +/* third group of registers, "hi" */ +REG32(MODULE_ENABLE, 0x00u) FIELD(MODULE_ENABLE, MODULE_ENABLE, 0u, 4u) -REG32(CONF, 0x24u) +REG32(CONF, 0x04u) + /* common bitfields for all versions */ FIELD(CONF, FIPS_ENABLE, 0u, 4u) FIELD(CONF, FIPS_FLAG, 4u, 4u) FIELD(CONF, RNG_FIPS, 8u, 4u) FIELD(CONF, RNG_BIT_ENABLE, 12u, 4u) - FIELD(CONF, RNG_BIT_SEL, 16u, 2u) - FIELD(CONF, THRESHOLD_SCOPE, 18u, 4u) - FIELD(CONF, ENTROPY_DATA_REG_ENABLE, 22u, 4u) -REG32(ENTROPY_CONTROL, 0x28u) + /* bitfields only defined on version 2 */ + FIELD(CONF, V2_RNG_BIT_SEL, 16u, 2u) + FIELD(CONF, V2_THRESHOLD_SCOPE, 18u, 4u) + FIELD(CONF, V2_ENTROPY_DATA_REG_ENABLE, 22u, 4u) + /* bitfields only defined on for version 3 */ + FIELD(CONF, V3_THRESHOLD_SCOPE, 16u, 4u) + FIELD(CONF, V3_ENTROPY_DATA_REG_ENABLE, 20u, 4u) + FIELD(CONF, V3_RNG_BIT_SEL, 24u, 8u) +REG32(ENTROPY_CONTROL, 0x08u) FIELD(ENTROPY_CONTROL, ES_ROUTE, 0u, 4u) FIELD(ENTROPY_CONTROL, ES_TYPE, 4u, 4u) -REG32(ENTROPY_DATA, 0x2cu) -REG32(HEALTH_TEST_WINDOWS, 0x30u) +REG32(ENTROPY_DATA, 0x0cu) +REG32(HEALTH_TEST_WINDOWS, 0x10u) FIELD(HEALTH_TEST_WINDOWS, FIPS_WINDOW, 0u, 16u) FIELD(HEALTH_TEST_WINDOWS, BYPASS_WINDOW, 16u, 16u) -REG32(REPCNT_THRESHOLDS, 0x34u) +REG32(REPCNT_THRESHOLDS, 0x14u) SHARED_FIELD(THRESHOLDS_FIPS, 0u, 16u) SHARED_FIELD(THRESHOLDS_BYPASS, 16u, 16u) -REG32(REPCNTS_THRESHOLDS, 0x38u) -REG32(ADAPTP_HI_THRESHOLDS, 0x3cu) -REG32(ADAPTP_LO_THRESHOLDS, 0x40u) -REG32(BUCKET_THRESHOLDS, 0x44u) -REG32(MARKOV_HI_THRESHOLDS, 0x48u) -REG32(MARKOV_LO_THRESHOLDS, 0x4cu) -REG32(EXTHT_HI_THRESHOLDS, 0x50u) -REG32(EXTHT_LO_THRESHOLDS, 0x54u) -REG32(REPCNT_HI_WATERMARKS, 0x58u) +REG32(REPCNTS_THRESHOLDS, 0x18u) +REG32(ADAPTP_HI_THRESHOLDS, 0x1cu) +REG32(ADAPTP_LO_THRESHOLDS, 0x20u) +REG32(BUCKET_THRESHOLDS, 0x24u) +REG32(MARKOV_HI_THRESHOLDS, 0x28u) +REG32(MARKOV_LO_THRESHOLDS, 0x2cu) +REG32(EXTHT_HI_THRESHOLDS, 0x30u) +REG32(EXTHT_LO_THRESHOLDS, 0x34u) +REG32(REPCNT_HI_WATERMARKS, 0x38u) SHARED_FIELD(WATERMARK_FIPS, 0u, 16u) SHARED_FIELD(WATERMARK_BYPASS, 16u, 16u) -REG32(REPCNTS_HI_WATERMARKS, 0x5cu) -REG32(ADAPTP_HI_WATERMARKS, 0x60u) -REG32(ADAPTP_LO_WATERMARKS, 0x64u) -REG32(EXTHT_HI_WATERMARKS, 0x68u) -REG32(EXTHT_LO_WATERMARKS, 0x6cu) -REG32(BUCKET_HI_WATERMARKS, 0x70u) -REG32(MARKOV_HI_WATERMARKS, 0x74u) -REG32(MARKOV_LO_WATERMARKS, 0x78u) -REG32(REPCNT_TOTAL_FAILS, 0x7cu) -REG32(REPCNTS_TOTAL_FAILS, 0x80u) -REG32(ADAPTP_HI_TOTAL_FAILS, 0x84u) -REG32(ADAPTP_LO_TOTAL_FAILS, 0x88u) -REG32(BUCKET_TOTAL_FAILS, 0x8cu) -REG32(MARKOV_HI_TOTAL_FAILS, 0x90u) -REG32(MARKOV_LO_TOTAL_FAILS, 0x94u) -REG32(EXTHT_HI_TOTAL_FAILS, 0x98u) -REG32(EXTHT_LO_TOTAL_FAILS, 0x9cu) -REG32(ALERT_THRESHOLD, 0xa0u) - FIELD(ALERT_THRESHOLD, ALERT_THRESHOLD, 0u, 16u) - FIELD(ALERT_THRESHOLD, ALERT_THRESHOLD_INV, 16u, 16u) -REG32(ALERT_SUMMARY_FAIL_COUNTS, 0xa4u) +REG32(REPCNTS_HI_WATERMARKS, 0x3cu) +REG32(ADAPTP_HI_WATERMARKS, 0x40u) +REG32(ADAPTP_LO_WATERMARKS, 0x44u) +REG32(EXTHT_HI_WATERMARKS, 0x48u) +REG32(EXTHT_LO_WATERMARKS, 0x4cu) +REG32(BUCKET_HI_WATERMARKS, 0x50u) +REG32(MARKOV_HI_WATERMARKS, 0x54u) +REG32(MARKOV_LO_WATERMARKS, 0x58u) +REG32(REPCNT_TOTAL_FAILS, 0x5cu) +REG32(REPCNTS_TOTAL_FAILS, 0x60u) +REG32(ADAPTP_HI_TOTAL_FAILS, 0x64u) +REG32(ADAPTP_LO_TOTAL_FAILS, 0x68u) +REG32(BUCKET_TOTAL_FAILS, 0x6cu) +REG32(MARKOV_HI_TOTAL_FAILS, 0x70u) +REG32(MARKOV_LO_TOTAL_FAILS, 0x74u) +REG32(EXTHT_HI_TOTAL_FAILS, 0x78u) +REG32(EXTHT_LO_TOTAL_FAILS, 0x7cu) +REG32(ALERT_THRESHOLD, 0x80u) + FIELD(ALERT_THRESHOLD, VAL, 0u, 16u) + FIELD(ALERT_THRESHOLD, INV, 16u, 16u) +REG32(ALERT_SUMMARY_FAIL_COUNTS, 0x84u) FIELD(ALERT_SUMMARY_FAIL_COUNTS, ANY_FAIL_COUNT, 0u, 16u) -REG32(ALERT_FAIL_COUNTS, 0xa8u) +REG32(ALERT_FAIL_COUNTS, 0x88u) FIELD(ALERT_FAIL_COUNTS, REPCNT_FAIL_COUNT, 4u, 4u) FIELD(ALERT_FAIL_COUNTS, ADAPTP_HI_FAIL_COUNT, 8u, 4u) FIELD(ALERT_FAIL_COUNTS, ADAPTP_LO_FAIL_COUNT, 12u, 4u) @@ -137,25 +176,25 @@ REG32(ALERT_FAIL_COUNTS, 0xa8u) FIELD(ALERT_FAIL_COUNTS, MARKOV_HI_FAIL_COUNT, 20u, 4u) FIELD(ALERT_FAIL_COUNTS, MARKOV_LO_FAIL_COUNT, 24u, 4u) FIELD(ALERT_FAIL_COUNTS, REPCNTS_FAIL_COUNT, 28u, 4u) -REG32(EXTHT_FAIL_COUNTS, 0xacu) +REG32(EXTHT_FAIL_COUNTS, 0x8cu) FIELD(EXTHT_FAIL_COUNTS, EXTHT_HI_FAIL_COUNT, 0u, 4u) FIELD(EXTHT_FAIL_COUNTS, EXTHT_LO_FAIL_COUNT, 4u, 4u) -REG32(FW_OV_CONTROL, 0xb0u) +REG32(FW_OV_CONTROL, 0x90u) FIELD(FW_OV_CONTROL, FW_OV_MODE, 0u, 4u) FIELD(FW_OV_CONTROL, FW_OV_ENTROPY_INSERT, 4u, 4u) -REG32(FW_OV_SHA3_START, 0xb4u) +REG32(FW_OV_SHA3_START, 0x94u) FIELD(FW_OV_SHA3_START, FW_OV_INSERT_START, 0u, 4u) -REG32(FW_OV_WR_FIFO_FULL, 0xb8u) +REG32(FW_OV_WR_FIFO_FULL, 0x98u) FIELD(FW_OV_WR_FIFO_FULL, VAL, 0u, 1u) -REG32(FW_OV_RD_FIFO_OVERFLOW, 0xbcu) +REG32(FW_OV_RD_FIFO_OVERFLOW, 0x9cu) FIELD(FW_OV_RD_FIFO_OVERFLOW, VAL, 0u, 1u) -REG32(FW_OV_RD_DATA, 0xc0u) -REG32(FW_OV_WR_DATA, 0xc4u) -REG32(OBSERVE_FIFO_THRESH, 0xc8u) +REG32(FW_OV_RD_DATA, 0xa0u) +REG32(FW_OV_WR_DATA, 0xa4u) +REG32(OBSERVE_FIFO_THRESH, 0xa8u) FIELD(OBSERVE_FIFO_THRESH, VAL, 0u, 6u) -REG32(OBSERVE_FIFO_DEPTH, 0xccu) +REG32(OBSERVE_FIFO_DEPTH, 0xacu) FIELD(OBSERVE_FIFO_DEPTH, VAL, 0u, 6u) -REG32(DEBUG_STATUS, 0xd0u) +REG32(DEBUG_STATUS, 0xb0u) FIELD(DEBUG_STATUS, ENTROPY_FIFO_DEPTH, 0u, 2u) FIELD(DEBUG_STATUS, SHA3_FSM, 3u, 3u) FIELD(DEBUG_STATUS, SHA3_BLOCK_PR, 6u, 1u) @@ -164,13 +203,13 @@ REG32(DEBUG_STATUS, 0xd0u) FIELD(DEBUG_STATUS, SHA3_ERR, 9u, 1u) FIELD(DEBUG_STATUS, MAIN_SM_IDLE, 16u, 1u) FIELD(DEBUG_STATUS, MAIN_SM_BOOT_DONE, 17u, 1u) -REG32(RECOV_ALERT_STS, 0xd4u) +REG32(RECOV_ALERT_STS, 0xb4u) FIELD(RECOV_ALERT_STS, FIPS_ENABLE_FIELD_ALERT, 0u, 1u) FIELD(RECOV_ALERT_STS, ENTROPY_DATA_REG_ENABLE_FIELD_ALERT, 1u, 1u) FIELD(RECOV_ALERT_STS, MODULE_ENABLE_FIELD_ALERT, 2u, 1u) FIELD(RECOV_ALERT_STS, THRESHOLD_SCOPE_FIELD_ALERT, 3u, 1u) FIELD(RECOV_ALERT_STS, RNG_BIT_ENABLE_FIELD_ALERT, 5u, 1u) - FIELD(RECOV_ALERT_STS, FW_OV_INSERT_START_FIELD_ALERT, 7u, 1u) + FIELD(RECOV_ALERT_STS, FW_OV_SHA3_START_FIELD_ALERT, 7u, 1u) FIELD(RECOV_ALERT_STS, FW_OV_MODE_FIELD_ALERT, 8u, 1u) FIELD(RECOV_ALERT_STS, FW_OV_ENTROPY_INSERT_FIELD_ALERT, 9u, 1u) FIELD(RECOV_ALERT_STS, ES_ROUTE_FIELD_ALERT, 10u, 1u) @@ -183,7 +222,7 @@ REG32(RECOV_ALERT_STS, 0xd4u) FIELD(RECOV_ALERT_STS, FIPS_FLAG_FIELD_ALERT, 17u, 1u) FIELD(RECOV_ALERT_STS, RNG_FIPS_FIELD_ALERT, 18u, 1u) FIELD(RECOV_ALERT_STS, POSTHT_ENTROPY_DROP_ALERT, 31u, 1u) -REG32(ERR_CODE, 0xd8u) +REG32(ERR_CODE, 0xb8u) FIELD(ERR_CODE, SFIFO_ESRNG_ERR, 0u, 1u) FIELD(ERR_CODE, SFIFO_DISTR_ERR, 1u, 1u) FIELD(ERR_CODE, SFIFO_OBSERVE_ERR, 2u, 1u) @@ -196,41 +235,34 @@ REG32(ERR_CODE, 0xd8u) FIELD(ERR_CODE, FIFO_WRITE_ERR, 28u, 1u) FIELD(ERR_CODE, FIFO_READ_ERR, 29u, 1u) FIELD(ERR_CODE, FIFO_STATE_ERR, 30u, 1u) -REG32(ERR_CODE_TEST, 0xdcu) +REG32(ERR_CODE_TEST, 0xbcu) FIELD(ERR_CODE_TEST, VAL, 0u, 5u) -REG32(MAIN_SM_STATE, 0xe0u) +REG32(MAIN_SM_STATE, 0xc0u) FIELD(MAIN_SM_STATE, VAL, 0u, 9u) /* clang-format on */ -#define R32_OFF(_r_) ((_r_) / sizeof(uint32_t)) - -#define R_LAST_REG (R_MAIN_SM_STATE) -#define REGS_COUNT (R_LAST_REG + 1u) -#define REGS_SIZE (REGS_COUNT * sizeof(uint32_t)) -#define REG_NAME(_reg_) \ - ((((_reg_) <= REGS_COUNT) && REG_NAMES[_reg_]) ? REG_NAMES[_reg_] : "?") - -#define INTR_MASK \ +#define INTR_WMASK \ (INTR_ES_ENTROPY_VALID_MASK | INTR_ES_HEALTH_TEST_FAILED_MASK | \ INTR_ES_OBSERVE_FIFO_READY_MASK | INTR_ES_FATAL_ERR_MASK) -#define ALERT_TEST_MASK \ +#define ALERT_TEST_WMASK \ (R_ALERT_TEST_RECOV_ALERT_MASK | R_ALERT_TEST_FATAL_ALERT_MASK) -#define CONF_MASK \ +#define CONF_V2_WMASK \ (R_CONF_FIPS_ENABLE_MASK | R_CONF_FIPS_FLAG_MASK | R_CONF_RNG_FIPS_MASK | \ - R_CONF_RNG_BIT_ENABLE_MASK | R_CONF_RNG_BIT_SEL_MASK | \ - R_CONF_THRESHOLD_SCOPE_MASK | R_CONF_ENTROPY_DATA_REG_ENABLE_MASK) -#define ENTROPY_CONTROL_MASK \ + R_CONF_RNG_BIT_ENABLE_MASK | R_CONF_V2_RNG_BIT_SEL_MASK | \ + R_CONF_V2_THRESHOLD_SCOPE_MASK | R_CONF_V2_ENTROPY_DATA_REG_ENABLE_MASK) +#define CONF_V3_WMASK UINT32_MAX +#define ENTROPY_CONTROL_WMASK \ (R_ENTROPY_CONTROL_ES_ROUTE_MASK | R_ENTROPY_CONTROL_ES_TYPE_MASK) -#define FW_OV_CONTROL_MASK \ +#define FW_OV_CONTROL_WMASK \ (R_FW_OV_CONTROL_FW_OV_MODE_MASK | \ R_FW_OV_CONTROL_FW_OV_ENTROPY_INSERT_MASK) -#define RECOV_ALERT_STS_MASK \ +#define RECOV_ALERT_STS_WMASK \ (R_RECOV_ALERT_STS_FIPS_ENABLE_FIELD_ALERT_MASK | \ R_RECOV_ALERT_STS_ENTROPY_DATA_REG_ENABLE_FIELD_ALERT_MASK | \ R_RECOV_ALERT_STS_MODULE_ENABLE_FIELD_ALERT_MASK | \ R_RECOV_ALERT_STS_THRESHOLD_SCOPE_FIELD_ALERT_MASK | \ R_RECOV_ALERT_STS_RNG_BIT_ENABLE_FIELD_ALERT_MASK | \ - R_RECOV_ALERT_STS_FW_OV_INSERT_START_FIELD_ALERT_MASK | \ + R_RECOV_ALERT_STS_FW_OV_SHA3_START_FIELD_ALERT_MASK | \ R_RECOV_ALERT_STS_FW_OV_MODE_FIELD_ALERT_MASK | \ R_RECOV_ALERT_STS_FW_OV_ENTROPY_INSERT_FIELD_ALERT_MASK | \ R_RECOV_ALERT_STS_ES_ROUTE_FIELD_ALERT_MASK | \ @@ -255,10 +287,50 @@ REG32(MAIN_SM_STATE, 0xe0u) R_ERR_CODE_ES_CNTR_ERR_MASK | R_ERR_CODE_SHA3_STATE_ERR_MASK | \ R_ERR_CODE_SHA3_RST_STORAGE_ERR_MASK) +/* + * this is an alias for the CHECK_MULTIBOOT macro, as the RECOV_ALERT_STS + * bit for the FW_OV_SHA3_START register is the only register bit that does + * not follow the same naming as its relative register + * */ +#define R_RECOV_ALERT_STS_FW_OV_INSERT_START_FIELD_ALERT_SHIFT \ + R_RECOV_ALERT_STS_FW_OV_SHA3_START_FIELD_ALERT_SHIFT + #define ALERT_STATUS_BIT(_x_) R_RECOV_ALERT_STS_##_x_##_FIELD_ALERT_SHIFT +#define R32_OFF(_r_) ((_r_) / sizeof(uint32_t)) + +#define R_LAST_LO_REG (R_REGWEN) +#define REGS_LO_COUNT (R_LAST_LO_REG + 1u) +#define REGS_LO_SIZE (REGS_LO_COUNT * sizeof(uint32_t)) +#define REGS_LO_BASE 0x00u +#define REG_LO_NAME(_reg_) \ + ((((_reg_) <= REGS_LO_COUNT) && REG_LO_NAMES[_reg_]) ? \ + REG_LO_NAMES[_reg_] : \ + "?") + +/* only used in version 2 */ +#define R_LAST_REV_REG (R_REV) +#define REGS_REV_COUNT (R_LAST_REV_REG + 1u) +#define REGS_REV_SIZE (REGS_REV_COUNT * sizeof(uint32_t)) +#define REGS_REV_BASE 0x1cu +#define REG_REV_NAME(_reg_) \ + ((((_reg_) <= REGS_REV_COUNT) && REG_REV_NAMES[_reg_]) ? \ + REG_REV_NAMES[_reg_] : \ + "?") + +#define R_LAST_HI_REG (R_MAIN_SM_STATE) +#define REGS_HI_COUNT (R_LAST_HI_REG + 1u) +#define REGS_HI_SIZE (REGS_HI_COUNT * sizeof(uint32_t)) +#define REGS_HI_V2_BASE 0x20u +#define REGS_HI_V3_BASE 0x1cu +#define REG_HI_NAME(_reg_) \ + ((((_reg_) <= REGS_HI_COUNT) && REG_HI_NAMES[_reg_]) ? \ + REG_HI_NAMES[_reg_] : \ + "?") + #define REG_NAME_ENTRY(_reg_) [R_##_reg_] = stringify(_reg_) -static const char *REG_NAMES[REGS_COUNT] = { +static const char *REG_LO_NAMES[REGS_LO_COUNT] = { + /* clang-format off */ REG_NAME_ENTRY(INTR_STATE), REG_NAME_ENTRY(INTR_ENABLE), REG_NAME_ENTRY(INTR_TEST), @@ -266,7 +338,18 @@ static const char *REG_NAMES[REGS_COUNT] = { REG_NAME_ENTRY(ME_REGWEN), REG_NAME_ENTRY(SW_REGUPD), REG_NAME_ENTRY(REGWEN), + /* clang-format on */ +}; + +/* only used in version 2 */ +static const char *REG_REV_NAMES[REGS_REV_COUNT] = { + /* clang-format off */ REG_NAME_ENTRY(REV), + /* clang-format on */ +}; + +static const char *REG_HI_NAMES[REGS_HI_COUNT] = { + /* clang-format off */ REG_NAME_ENTRY(MODULE_ENABLE), REG_NAME_ENTRY(CONF), REG_NAME_ENTRY(ENTROPY_CONTROL), @@ -316,6 +399,7 @@ static const char *REG_NAMES[REGS_COUNT] = { REG_NAME_ENTRY(ERR_CODE), REG_NAME_ENTRY(ERR_CODE_TEST), REG_NAME_ENTRY(MAIN_SM_STATE), + /* clang-format on */ }; #undef REG_NAME_ENTRY @@ -353,41 +437,47 @@ enum { ALERT_COUNT, }; -static_assert(ALERT_COUNT == PARAM_NUM_ALERTS, "Invalid alert count"); +static_assert(ALERT_COUNT == NUM_ALERTS, "Invalid alert count"); typedef enum { - ENTROPY_SRC_EG_IDLE, - ENTROPY_SRC_EG_BOOT_HT_RUNNING, - ENTROPY_SRC_EG_BOOT_POST_HT_CHK, - ENTROPY_SRC_EG_BOOT_PHASE_DONE, - ENTROPY_SRC_EG_STARTUP_HT_START, - ENTROPY_SRC_EG_STARTUP_PHASE1, - ENTROPY_SRC_EG_STARTUP_PASS1, - ENTROPY_SRC_EG_STARTUP_FAIL1, - ENTROPY_SRC_EG_CONT_HT_START, - ENTROPY_SRC_EG_CONT_HT_RUNNING, - ENTROPY_SRC_EG_FW_INSERT_START, - ENTROPY_SRC_EG_FW_INSERT_MSG, - ENTROPY_SRC_EG_SHA3_MSGDONE, - ENTROPY_SRC_EG_SHA3_PREP, - ENTROPY_SRC_EG_SHA3_PROCESS, - ENTROPY_SRC_EG_SHA3_VALID, - ENTROPY_SRC_EG_SHA3_DONE, - ENTROPY_SRC_EG_SHA3_QUIESCE, - ENTROPY_SRC_EG_ALERT_STATE, - ENTROPY_SRC_EG_ALERT_HANG, - ENTROPY_SRC_EG_ERROR, + ENTROPY_SRC_IDLE, + ENTROPY_SRC_BOOT_HT_RUNNING, + ENTROPY_SRC_BOOT_POST_HT_CHK, + ENTROPY_SRC_BOOT_PHASE_DONE, + ENTROPY_SRC_STARTUP_HT_START, + ENTROPY_SRC_STARTUP_PHASE1, + ENTROPY_SRC_STARTUP_PASS1, + ENTROPY_SRC_STARTUP_FAIL1, + ENTROPY_SRC_CONT_HT_START, + ENTROPY_SRC_CONT_HT_RUNNING, + ENTROPY_SRC_FW_INSERT_START, + ENTROPY_SRC_FW_INSERT_MSG, + ENTROPY_SRC_SHA3_MSGDONE, + ENTROPY_SRC_SHA3_PREP, + ENTROPY_SRC_SHA3_PROCESS, + ENTROPY_SRC_SHA3_VALID, + ENTROPY_SRC_SHA3_DONE, + ENTROPY_SRC_SHA3_QUIESCE, + ENTROPY_SRC_ALERT_STATE, + ENTROPY_SRC_ALERT_HANG, + ENTROPY_SRC_ERROR, } OtEntropySrcFsmState; struct OtEntropySrcState { SysBusDevice parent_obj; MemoryRegion mmio; - IbexIRQ irqs[PARAM_NUM_IRQS]; - IbexIRQ alerts[PARAM_NUM_ALERTS]; + MemoryRegion mmio_lo; + MemoryRegion mmio_rev; /* only in v2 */ + MemoryRegion mmio_hi; + IbexIRQ irqs[NUM_IRQS]; + IbexIRQ alerts[NUM_ALERTS]; QEMUTimer *scheduler; - uint32_t *regs; + uint32_t *regs_lo; + uint32_t *regs_rev; /* only on v2 */ + uint32_t *regs_hi; + OtFifo32 input_fifo; /* not in real HW, used to reduce feed rate */ OtFifo32 precon_fifo; /* 32-to-64 SHA3 input packer */ OtFifo32 bypass_fifo; /* 32-to-384 packer */ @@ -401,6 +491,8 @@ struct OtEntropySrcState { unsigned packet_count; /* count of output packets since enabled */ bool obs_fifo_en; /* observe FIFO accept incoming data */ + char *ot_id; + unsigned version; /* emulated version */ OtASTEgState *ast; OtOTPState *otp_ctrl; }; @@ -410,31 +502,32 @@ struct OtEntropySrcClass { ResettablePhases parent_phases; }; +/* @todo: need to check the FSM code are identical on v2 and v3... */ static const uint16_t OtEDNFsmStateCode[] = { - [ENTROPY_SRC_EG_IDLE] = 0b011110101, - [ENTROPY_SRC_EG_BOOT_HT_RUNNING] = 0b111010010, - [ENTROPY_SRC_EG_BOOT_POST_HT_CHK] = 0b101101110, - [ENTROPY_SRC_EG_BOOT_PHASE_DONE] = 0b010001110, - [ENTROPY_SRC_EG_STARTUP_HT_START] = 0b000101100, - [ENTROPY_SRC_EG_STARTUP_PHASE1] = 0b100000001, - [ENTROPY_SRC_EG_STARTUP_PASS1] = 0b110100101, - [ENTROPY_SRC_EG_STARTUP_FAIL1] = 0b000010111, - [ENTROPY_SRC_EG_CONT_HT_START] = 0b001000000, - [ENTROPY_SRC_EG_CONT_HT_RUNNING] = 0b110100010, - [ENTROPY_SRC_EG_FW_INSERT_START] = 0b011000011, - [ENTROPY_SRC_EG_FW_INSERT_MSG] = 0b001011001, - [ENTROPY_SRC_EG_SHA3_MSGDONE] = 0b100001111, - [ENTROPY_SRC_EG_SHA3_PREP] = 0b011111000, - [ENTROPY_SRC_EG_SHA3_PROCESS] = 0b010111111, - [ENTROPY_SRC_EG_SHA3_VALID] = 0b101110001, - [ENTROPY_SRC_EG_SHA3_DONE] = 0b110011000, - [ENTROPY_SRC_EG_SHA3_QUIESCE] = 0b111001101, - [ENTROPY_SRC_EG_ALERT_STATE] = 0b111111011, - [ENTROPY_SRC_EG_ALERT_HANG] = 0b101011100, - [ENTROPY_SRC_EG_ERROR] = 0b100111101, + [ENTROPY_SRC_IDLE] = 0b011110101, + [ENTROPY_SRC_BOOT_HT_RUNNING] = 0b111010010, + [ENTROPY_SRC_BOOT_POST_HT_CHK] = 0b101101110, + [ENTROPY_SRC_BOOT_PHASE_DONE] = 0b010001110, + [ENTROPY_SRC_STARTUP_HT_START] = 0b000101100, + [ENTROPY_SRC_STARTUP_PHASE1] = 0b100000001, + [ENTROPY_SRC_STARTUP_PASS1] = 0b110100101, + [ENTROPY_SRC_STARTUP_FAIL1] = 0b000010111, + [ENTROPY_SRC_CONT_HT_START] = 0b001000000, + [ENTROPY_SRC_CONT_HT_RUNNING] = 0b110100010, + [ENTROPY_SRC_FW_INSERT_START] = 0b011000011, + [ENTROPY_SRC_FW_INSERT_MSG] = 0b001011001, + [ENTROPY_SRC_SHA3_MSGDONE] = 0b100001111, + [ENTROPY_SRC_SHA3_PREP] = 0b011111000, + [ENTROPY_SRC_SHA3_PROCESS] = 0b010111111, + [ENTROPY_SRC_SHA3_VALID] = 0b101110001, + [ENTROPY_SRC_SHA3_DONE] = 0b110011000, + [ENTROPY_SRC_SHA3_QUIESCE] = 0b111001101, + [ENTROPY_SRC_ALERT_STATE] = 0b111111011, + [ENTROPY_SRC_ALERT_HANG] = 0b101011100, + [ENTROPY_SRC_ERROR] = 0b100111101, }; -#define STATE_NAME_ENTRY(_st_) [ENTROPY_SRC_EG_##_st_] = stringify(_st_) +#define STATE_NAME_ENTRY(_st_) [ENTROPY_SRC_##_st_] = stringify(_st_) static const char *STATE_NAMES[] = { STATE_NAME_ENTRY(IDLE), STATE_NAME_ENTRY(BOOT_HT_RUNNING), @@ -462,13 +555,15 @@ static const char *STATE_NAMES[] = { #define STATE_NAME(_st_) \ ((_st_) >= 0 && (_st_) < ARRAY_SIZE(STATE_NAMES) ? STATE_NAMES[(_st_)] : \ "?") -#define REG_MB4_IS_TRUE(_s_, _reg_, _fld_) \ - (FIELD_EX32((_s_)->regs[R_##_reg_], _reg_, _fld_) == OT_MULTIBITBOOL4_TRUE) -#define REG_MB4_IS_FALSE(_s_, _reg_, _fld_) \ - (FIELD_EX32((_s_)->regs[R_##_reg_], _reg_, _fld_) == OT_MULTIBITBOOL4_FALSE) +#define REG_MB4_IS_TRUE(_s_, _g_, _reg_, _fld_) \ + (FIELD_EX32((_s_)->regs##_##_g_[R_##_reg_], _reg_, _fld_) == \ + OT_MULTIBITBOOL4_TRUE) +#define REG_MB4_IS_FALSE(_s_, _g_, _reg_, _fld_) \ + (FIELD_EX32((_s_)->regs##_##_g_[R_##_reg_], _reg_, _fld_) == \ + OT_MULTIBITBOOL4_FALSE) -#define xtrace_ot_entropy_src_show_buffer(_msg_, _buf_, _len_) \ - ot_entropy_src_show_buffer(__func__, __LINE__, _msg_, _buf_, _len_) +#define xtrace_ot_entropy_src_show_buffer(_s_, _msg_, _buf_, _len_) \ + ot_entropy_src_show_buffer(_s_, __func__, __LINE__, _msg_, _buf_, _len_) static bool ot_entropy_src_is_module_enabled(const OtEntropySrcState *s); static bool ot_entropy_src_is_fips_enabled(const OtEntropySrcState *s); @@ -490,24 +585,24 @@ static int ot_entropy_src_get_random( bool fips_compliant; switch (s->state) { - case ENTROPY_SRC_EG_BOOT_PHASE_DONE: + case ENTROPY_SRC_BOOT_PHASE_DONE: fips_compliant = false; break; - case ENTROPY_SRC_EG_CONT_HT_RUNNING: - case ENTROPY_SRC_EG_CONT_HT_START: - case ENTROPY_SRC_EG_SHA3_MSGDONE: - case ENTROPY_SRC_EG_SHA3_PREP: - case ENTROPY_SRC_EG_SHA3_PROCESS: - case ENTROPY_SRC_EG_SHA3_VALID: - case ENTROPY_SRC_EG_SHA3_DONE: + case ENTROPY_SRC_CONT_HT_RUNNING: + case ENTROPY_SRC_CONT_HT_START: + case ENTROPY_SRC_SHA3_MSGDONE: + case ENTROPY_SRC_SHA3_PREP: + case ENTROPY_SRC_SHA3_PROCESS: + case ENTROPY_SRC_SHA3_VALID: + case ENTROPY_SRC_SHA3_DONE: fips_compliant = true; break; - case ENTROPY_SRC_EG_BOOT_HT_RUNNING: - case ENTROPY_SRC_EG_BOOT_POST_HT_CHK: - case ENTROPY_SRC_EG_STARTUP_HT_START: - case ENTROPY_SRC_EG_STARTUP_PHASE1: - case ENTROPY_SRC_EG_STARTUP_PASS1: - case ENTROPY_SRC_EG_STARTUP_FAIL1: { + case ENTROPY_SRC_BOOT_HT_RUNNING: + case ENTROPY_SRC_BOOT_POST_HT_CHK: + case ENTROPY_SRC_STARTUP_HT_START: + case ENTROPY_SRC_STARTUP_PHASE1: + case ENTROPY_SRC_STARTUP_PASS1: + case ENTROPY_SRC_STARTUP_FAIL1: { int64_t wait_ns; if (timer_pending(s->scheduler)) { /* computed delay fits into a 31-bit value */ @@ -517,20 +612,20 @@ static int ot_entropy_src_get_random( } else { wait_ns = OT_ENTROPY_SRC_WAIT_DELAY_NS; } - trace_ot_entropy_src_init_ongoing(STATE_NAME(s->state), s->state, - (int)wait_ns); + trace_ot_entropy_src_init_ongoing(s->ot_id, STATE_NAME(s->state), + s->state, (int)wait_ns); /* not ready */ return (int)wait_ns; } - case ENTROPY_SRC_EG_IDLE: + case ENTROPY_SRC_IDLE: qemu_log_mask(LOG_GUEST_ERROR, "%s: module is not enabled\n", __func__); return -1; - case ENTROPY_SRC_EG_FW_INSERT_START: - case ENTROPY_SRC_EG_FW_INSERT_MSG: - case ENTROPY_SRC_EG_SHA3_QUIESCE: /* this state is never emulated */ - case ENTROPY_SRC_EG_ALERT_STATE: - case ENTROPY_SRC_EG_ALERT_HANG: - case ENTROPY_SRC_EG_ERROR: + case ENTROPY_SRC_FW_INSERT_START: + case ENTROPY_SRC_FW_INSERT_MSG: + case ENTROPY_SRC_SHA3_QUIESCE: /* this state is never emulated */ + case ENTROPY_SRC_ALERT_STATE: + case ENTROPY_SRC_ALERT_HANG: + case ENTROPY_SRC_ERROR: default: qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid state: [%s:%d]\n", __func__, STATE_NAME(s->state), s->state); @@ -543,7 +638,8 @@ static int ot_entropy_src_get_random( } if (ot_fifo32_num_used(&s->final_fifo) < ES_WORD_COUNT) { - trace_ot_entropy_src_no_entropy(ot_fifo32_num_used(&s->final_fifo)); + trace_ot_entropy_src_no_entropy(s->ot_id, + ot_fifo32_num_used(&s->final_fifo)); return OT_ENTROPY_SRC_WAIT_DELAY_NS; } @@ -560,11 +656,11 @@ static int ot_entropy_src_get_random( *fips = fips_compliant && fips_capable; trace_ot_entropy_src_get_random_fips( - STATE_NAME(s->state), ot_entropy_src_is_fips_enabled(s), - REG_MB4_IS_TRUE(s, ENTROPY_CONTROL, ES_ROUTE), - REG_MB4_IS_TRUE(s, ENTROPY_CONTROL, ES_TYPE), - REG_MB4_IS_FALSE(s, CONF, RNG_BIT_ENABLE), fips_capable, fips_compliant, - *fips); + s->ot_id, STATE_NAME(s->state), ot_entropy_src_is_fips_enabled(s), + REG_MB4_IS_TRUE(s, hi, ENTROPY_CONTROL, ES_ROUTE), + REG_MB4_IS_TRUE(s, hi, ENTROPY_CONTROL, ES_TYPE), + REG_MB4_IS_FALSE(s, hi, CONF, RNG_BIT_ENABLE), fips_capable, + fips_compliant, *fips); if (ot_fifo32_num_used(&s->final_fifo) < ES_WORD_COUNT) { ot_entropy_src_update_filler(s); @@ -573,12 +669,9 @@ static int ot_entropy_src_get_random( return 0; } -/* -------------------------------------------------------------------------- */ -/* Private implementation */ -/* -------------------------------------------------------------------------- */ - static void ot_entropy_src_show_buffer( - const char *func, int line, const char *msg, const void *buf, unsigned size) + const OtEntropySrcState *s, const char *func, int line, const char *msg, + const void *buf, unsigned size) { if (trace_event_get_state(TRACE_OT_ENTROPY_SRC_SHOW_BUFFER) && qemu_loglevel_mask(LOG_TRACE)) { @@ -601,29 +694,40 @@ static void ot_entropy_src_show_buffer( hexstr[hix++] = '.'; } - trace_ot_entropy_src_show_buffer(func, line, msg, hexstr); + trace_ot_entropy_src_show_buffer(s->ot_id, func, line, msg, hexstr); } } +static inline uint32_t ot_entropy_src_hi_reg_base(const OtEntropySrcState *s) +{ + return (s->version < 3) ? REGS_HI_V2_BASE : REGS_HI_V3_BASE; +} + +static inline uint32_t +ot_entropy_src_hi_reg_addr(const OtEntropySrcState *s, uint32_t addr) +{ + return ot_entropy_src_hi_reg_base(s) + addr; +} + static bool ot_entropy_src_is_module_enabled(const OtEntropySrcState *s) { - return REG_MB4_IS_TRUE(s, MODULE_ENABLE, MODULE_ENABLE); + return REG_MB4_IS_TRUE(s, hi, MODULE_ENABLE, MODULE_ENABLE); } static bool ot_entropy_src_is_module_disabled(const OtEntropySrcState *s) { - return REG_MB4_IS_FALSE(s, MODULE_ENABLE, MODULE_ENABLE); + return REG_MB4_IS_FALSE(s, hi, MODULE_ENABLE, MODULE_ENABLE); } static bool ot_entropy_src_is_fips_enabled(const OtEntropySrcState *s) { - return REG_MB4_IS_TRUE(s, CONF, FIPS_ENABLE); + return REG_MB4_IS_TRUE(s, hi, CONF, FIPS_ENABLE); } static void ot_entropy_src_update_irqs(OtEntropySrcState *s) { - uint32_t levels = s->regs[R_INTR_STATE] & s->regs[R_INTR_ENABLE]; - for (unsigned ix = 0; ix < PARAM_NUM_IRQS; ix++) { + uint32_t levels = s->regs_lo[R_INTR_STATE] & s->regs_lo[R_INTR_ENABLE]; + for (unsigned ix = 0; ix < NUM_IRQS; ix++) { ibex_irq_set(&s->irqs[ix], (int)((levels >> ix) & 0x1u)); } } @@ -636,56 +740,56 @@ ot_entropy_src_is_final_fifo_slot_available(const OtEntropySrcState *s) static bool ot_entropy_src_is_hw_route(const OtEntropySrcState *s) { - return REG_MB4_IS_FALSE(s, ENTROPY_CONTROL, ES_ROUTE); + return REG_MB4_IS_FALSE(s, hi, ENTROPY_CONTROL, ES_ROUTE); } static bool ot_entropy_src_is_fw_route(const OtEntropySrcState *s) { - return REG_MB4_IS_TRUE(s, ENTROPY_CONTROL, ES_ROUTE); + return REG_MB4_IS_TRUE(s, hi, ENTROPY_CONTROL, ES_ROUTE); } static bool ot_entropy_src_is_bypass_mode(const OtEntropySrcState *s) { return !ot_entropy_src_is_fips_enabled(s) || (ot_entropy_src_is_fw_route(s) && - REG_MB4_IS_TRUE(s, ENTROPY_CONTROL, ES_TYPE)); + REG_MB4_IS_TRUE(s, hi, ENTROPY_CONTROL, ES_TYPE)); } static bool ot_entropy_src_is_fw_ov_mode(const OtEntropySrcState *s) { - return REG_MB4_IS_TRUE(s, FW_OV_CONTROL, FW_OV_MODE); + return REG_MB4_IS_TRUE(s, hi, FW_OV_CONTROL, FW_OV_MODE); } static bool ot_entropy_src_is_fw_ov_entropy_insert(const OtEntropySrcState *s) { - return REG_MB4_IS_TRUE(s, FW_OV_CONTROL, FW_OV_ENTROPY_INSERT); + return REG_MB4_IS_TRUE(s, hi, FW_OV_CONTROL, FW_OV_ENTROPY_INSERT); } static bool ot_entropy_src_is_fips_capable(const OtEntropySrcState *s) { return ot_entropy_src_is_fips_enabled(s) && - !(REG_MB4_IS_TRUE(s, ENTROPY_CONTROL, ES_ROUTE) && - REG_MB4_IS_TRUE(s, ENTROPY_CONTROL, ES_TYPE)) && - REG_MB4_IS_FALSE(s, CONF, RNG_BIT_ENABLE); + !(REG_MB4_IS_TRUE(s, hi, ENTROPY_CONTROL, ES_ROUTE) && + REG_MB4_IS_TRUE(s, hi, ENTROPY_CONTROL, ES_TYPE)) && + REG_MB4_IS_FALSE(s, hi, CONF, RNG_BIT_ENABLE); } static unsigned ot_alert_get_alert_fail_count(const OtEntropySrcState *s) { unsigned count; - count = FIELD_EX32(s->regs[R_ALERT_FAIL_COUNTS], ALERT_FAIL_COUNTS, + count = FIELD_EX32(s->regs_hi[R_ALERT_FAIL_COUNTS], ALERT_FAIL_COUNTS, REPCNT_FAIL_COUNT); - count += FIELD_EX32(s->regs[R_ALERT_FAIL_COUNTS], ALERT_FAIL_COUNTS, + count += FIELD_EX32(s->regs_hi[R_ALERT_FAIL_COUNTS], ALERT_FAIL_COUNTS, ADAPTP_HI_FAIL_COUNT); - count += FIELD_EX32(s->regs[R_ALERT_FAIL_COUNTS], ALERT_FAIL_COUNTS, + count += FIELD_EX32(s->regs_hi[R_ALERT_FAIL_COUNTS], ALERT_FAIL_COUNTS, ADAPTP_LO_FAIL_COUNT); - count += FIELD_EX32(s->regs[R_ALERT_FAIL_COUNTS], ALERT_FAIL_COUNTS, + count += FIELD_EX32(s->regs_hi[R_ALERT_FAIL_COUNTS], ALERT_FAIL_COUNTS, BUCKET_FAIL_COUNT); - count += FIELD_EX32(s->regs[R_ALERT_FAIL_COUNTS], ALERT_FAIL_COUNTS, + count += FIELD_EX32(s->regs_hi[R_ALERT_FAIL_COUNTS], ALERT_FAIL_COUNTS, MARKOV_HI_FAIL_COUNT); - count += FIELD_EX32(s->regs[R_ALERT_FAIL_COUNTS], ALERT_FAIL_COUNTS, + count += FIELD_EX32(s->regs_hi[R_ALERT_FAIL_COUNTS], ALERT_FAIL_COUNTS, MARKOV_LO_FAIL_COUNT); - count += FIELD_EX32(s->regs[R_ALERT_FAIL_COUNTS], ALERT_FAIL_COUNTS, + count += FIELD_EX32(s->regs_hi[R_ALERT_FAIL_COUNTS], ALERT_FAIL_COUNTS, REPCNTS_FAIL_COUNT); return count; @@ -697,11 +801,11 @@ static void ot_entropy_src_change_state_line( OtEntropySrcFsmState old_state = s->state; switch (s->state) { - case ENTROPY_SRC_EG_ALERT_STATE: - s->state = ENTROPY_SRC_EG_ALERT_HANG; + case ENTROPY_SRC_ALERT_STATE: + s->state = ENTROPY_SRC_ALERT_HANG; break; - case ENTROPY_SRC_EG_ALERT_HANG: - if ((state == ENTROPY_SRC_EG_IDLE) && + case ENTROPY_SRC_ALERT_HANG: + if ((state == ENTROPY_SRC_IDLE) && ot_entropy_src_is_module_disabled(s)) { s->state = state; } @@ -712,13 +816,13 @@ static void ot_entropy_src_change_state_line( } if (old_state != s->state) { - trace_ot_entropy_src_change_state(line, STATE_NAME(old_state), + trace_ot_entropy_src_change_state(s->ot_id, line, STATE_NAME(old_state), old_state, STATE_NAME(s->state), s->state); } - if (s->state == ENTROPY_SRC_EG_ERROR) { - s->regs[R_ERR_CODE] |= R_ERR_CODE_ES_MAIN_SM_ERR_MASK; + if (s->state == ENTROPY_SRC_ERROR) { + s->regs_hi[R_ERR_CODE] |= R_ERR_CODE_ES_MAIN_SM_ERR_MASK; ot_entropy_src_update_alerts(s); } } @@ -728,21 +832,22 @@ static void ot_entropy_src_change_state_line( static void ot_entropy_src_update_alerts(OtEntropySrcState *s) { - unsigned alert_threshold = FIELD_EX32(s->regs[R_ALERT_THRESHOLD], - ALERT_THRESHOLD, ALERT_THRESHOLD); + unsigned alert_threshold = + FIELD_EX32(s->regs_hi[R_ALERT_THRESHOLD], ALERT_THRESHOLD, VAL); unsigned alert_count = ot_alert_get_alert_fail_count(s); - bool recoverable = (bool)s->regs[R_RECOV_ALERT_STS]; - uint32_t level = s->regs[R_ALERT_TEST]; + bool recoverable = (bool)s->regs_hi[R_RECOV_ALERT_STS]; + uint32_t level = s->regs_lo[R_ALERT_TEST]; if (alert_count >= alert_threshold || recoverable) { level |= 1u << ALERT_RECOVERABLE; } - uint32_t fatal_alert = s->regs[R_ERR_CODE] & ERR_CODE_FATAL_ERROR_MASK; - fatal_alert |= (1u << s->regs[R_ERR_CODE_TEST]) & ERR_CODE_FATAL_ERROR_MASK; + uint32_t fatal_alert = s->regs_hi[R_ERR_CODE] & ERR_CODE_FATAL_ERROR_MASK; + fatal_alert |= + (1u << s->regs_hi[R_ERR_CODE_TEST]) & ERR_CODE_FATAL_ERROR_MASK; if (fatal_alert) { level |= 1u << ALERT_FATAL; } - for (unsigned ix = 0; ix < PARAM_NUM_ALERTS; ix++) { + for (unsigned ix = 0; ix < NUM_ALERTS; ix++) { ibex_irq_set(&s->alerts[ix], (int)((level >> ix) & 0x1u)); } } @@ -758,7 +863,7 @@ static bool ot_entropy_src_check_multibitboot( break; } - s->regs[R_RECOV_ALERT_STS] |= 1u << alert_bit; + s->regs_hi[R_RECOV_ALERT_STS] |= 1u << alert_bit; ot_entropy_src_update_alerts(s); return false; } @@ -779,12 +884,13 @@ static void ot_entropy_src_update_filler(OtEntropySrcState *s) bool process = ot_entropy_src_can_consume_entropy(s); bool accept_entropy = input && output && process; - trace_ot_entropy_src_update_filler(input, output, process, accept_entropy); + trace_ot_entropy_src_update_filler(s->ot_id, input, output, process, + accept_entropy); if (!accept_entropy) { /* if cannot accept entropy, stop the entropy scheduler */ if (timer_pending(s->scheduler)) { - trace_ot_entropy_src_info("stop scheduler"); + trace_ot_entropy_src_info(s->ot_id, "stop scheduler"); timer_del(s->scheduler); } } else { @@ -793,7 +899,7 @@ static void ot_entropy_src_update_filler(OtEntropySrcState *s) * it is not already active */ if (!timer_pending(s->scheduler)) { - trace_ot_entropy_src_info("reschedule"); + trace_ot_entropy_src_info(s->ot_id, "reschedule"); uint64_t now = qemu_clock_get_ns(OT_VIRTUAL_CLOCK); timer_mod(s->scheduler, (int64_t)(now + (uint64_t)ES_FILL_RATE_NS)); } @@ -834,7 +940,7 @@ ot_entropy_src_push_entropy_to_conditioner(OtEntropySrcState *s, uint32_t word) int res; if (s->cond_word == 0) { res = sha3_384_init(&s->sha3_state); - ot_entropy_src_change_state(s, ENTROPY_SRC_EG_SHA3_PREP); + ot_entropy_src_change_state(s, ENTROPY_SRC_SHA3_PREP); g_assert(res == CRYPT_OK); } @@ -846,13 +952,14 @@ ot_entropy_src_push_entropy_to_conditioner(OtEntropySrcState *s, uint32_t word) return false; } - ot_entropy_src_change_state(s, ENTROPY_SRC_EG_SHA3_PROCESS); + ot_entropy_src_change_state(s, ENTROPY_SRC_SHA3_PROCESS); uint32_t size; const uint32_t *buf; buf = ot_fifo32_peek_buf(&s->precon_fifo, s->precon_fifo.num, &size); g_assert(size == s->precon_fifo.num); - xtrace_ot_entropy_src_show_buffer("sha3 in", buf, size * sizeof(uint32_t)); + xtrace_ot_entropy_src_show_buffer(s, "sha3 in", buf, + size * sizeof(uint32_t)); res = sha3_process(&s->sha3_state, (const uint8_t *)buf, size * sizeof(uint32_t)); g_assert(res == CRYPT_OK); @@ -876,11 +983,11 @@ static void ot_entropy_src_perform_hash(OtEntropySrcState *s) g_assert(res == CRYPT_OK); s->cond_word = 0; - xtrace_ot_entropy_src_show_buffer("sha3 md", hash, + xtrace_ot_entropy_src_show_buffer(s, "sha3 md", hash, OT_RANDOM_SRC_WORD_COUNT * sizeof(uint32_t)); - ot_entropy_src_change_state(s, ENTROPY_SRC_EG_SHA3_MSGDONE); + ot_entropy_src_change_state(s, ENTROPY_SRC_SHA3_MSGDONE); for (unsigned ix = 0; ix < OT_RANDOM_SRC_WORD_COUNT; ix++) { g_assert(!ot_fifo32_is_full(&s->final_fifo)); @@ -888,10 +995,10 @@ static void ot_entropy_src_perform_hash(OtEntropySrcState *s) } s->packet_count += 1u; - ot_entropy_src_change_state(s, REG_MB4_IS_TRUE(s, FW_OV_SHA3_START, + ot_entropy_src_change_state(s, REG_MB4_IS_TRUE(s, hi, FW_OV_SHA3_START, FW_OV_INSERT_START) ? - ENTROPY_SRC_EG_IDLE : - ENTROPY_SRC_EG_CONT_HT_START); + ENTROPY_SRC_IDLE : + ENTROPY_SRC_CONT_HT_START); } static bool @@ -912,8 +1019,10 @@ ot_entropy_src_push_bypass_entropy(OtEntropySrcState *s, uint32_t word) } s->packet_count += 1u; - trace_ot_entropy_src_push_bypass_entropy( - ot_fifo32_num_used(&s->final_fifo) / OT_RANDOM_SRC_WORD_COUNT); + trace_ot_entropy_src_push_bypass_entropy(s->ot_id, + ot_fifo32_num_used( + &s->final_fifo) / + OT_RANDOM_SRC_WORD_COUNT); return true; } @@ -921,15 +1030,16 @@ ot_entropy_src_push_bypass_entropy(OtEntropySrcState *s, uint32_t word) static void ot_entropy_src_update_fw_route(OtEntropySrcState *s) { if (ot_fifo32_num_used(&s->final_fifo) >= ES_WORD_COUNT) { - trace_ot_entropy_src_info("FW ROUTE"); + trace_ot_entropy_src_info(s->ot_id, "FW ROUTE"); if (ot_fifo32_is_empty(&s->swread_fifo)) { /* refill swread FIFO */ unsigned count = ES_WORD_COUNT; while (count--) { ot_fifo32_push(&s->swread_fifo, ot_fifo32_pop(&s->final_fifo)); } - s->regs[R_INTR_STATE] |= INTR_ES_ENTROPY_VALID_MASK; - trace_ot_entropy_src_available(STATE_NAME(s->state), s->state); + s->regs_lo[R_INTR_STATE] |= INTR_ES_ENTROPY_VALID_MASK; + trace_ot_entropy_src_available(s->ot_id, STATE_NAME(s->state), + s->state); ot_entropy_src_update_filler(s); } } @@ -949,38 +1059,39 @@ static bool ot_entropy_src_consume_entropy(OtEntropySrcState *s, uint32_t word) if (!(fill_obs_fifo || hw_path)) { /* no way to consume noise, stop here */ - trace_ot_entropy_src_info("cannot consume noise for now"); + trace_ot_entropy_src_info(s->ot_id, "cannot consume noise for now"); return false; } s->noise_count += 1u; - trace_ot_entropy_src_consume_entropy(fill_obs_fifo, bypass, hw_path, - s->noise_count); + trace_ot_entropy_src_consume_entropy(s->ot_id, fill_obs_fifo, bypass, + hw_path, s->noise_count); if (fill_obs_fifo) { if (ot_fifo32_is_full(&s->observe_fifo)) { - trace_ot_entropy_src_error("observe FIFO overflow", + trace_ot_entropy_src_error(s->ot_id, "observe FIFO overflow", STATE_NAME(s->state), s->state); - s->regs[R_FW_OV_RD_FIFO_OVERFLOW] |= + s->regs_hi[R_FW_OV_RD_FIFO_OVERFLOW] |= R_FW_OV_RD_FIFO_OVERFLOW_VAL_MASK; } else { if (s->obs_fifo_en) { - unsigned threshold = s->regs[R_OBSERVE_FIFO_THRESH]; + unsigned threshold = s->regs_hi[R_OBSERVE_FIFO_THRESH]; ot_fifo32_push(&s->observe_fifo, word); - trace_ot_entropy_src_obs_fifo(ot_fifo32_num_used( + trace_ot_entropy_src_obs_fifo(s->ot_id, + ot_fifo32_num_used( &s->observe_fifo), threshold); if (ot_fifo32_is_full(&s->observe_fifo)) { /* can only be enabled back once the FIFO is emptied */ - trace_ot_entropy_src_info("observe FIFO is full"); + trace_ot_entropy_src_info(s->ot_id, "observe FIFO is full"); s->obs_fifo_en = false; } /* is it > or >= ? */ if (ot_fifo32_num_used(&s->observe_fifo) >= threshold) { - s->regs[R_INTR_STATE] |= INTR_ES_OBSERVE_FIFO_READY_MASK; + s->regs_lo[R_INTR_STATE] |= INTR_ES_OBSERVE_FIFO_READY_MASK; } } else { - trace_ot_entropy_src_info("observe FIFO not enabled"); + trace_ot_entropy_src_info(s->ot_id, "observe FIFO not enabled"); } } } @@ -991,7 +1102,7 @@ static bool ot_entropy_src_consume_entropy(OtEntropySrcState *s, uint32_t word) } else { if (ot_entropy_src_push_entropy_to_conditioner(s, word)) { if (ot_entropy_src_can_hash(s)) { - trace_ot_entropy_src_info("can hash"); + trace_ot_entropy_src_info(s->ot_id, "can hash"); ot_entropy_src_perform_hash(s); } } @@ -1005,6 +1116,28 @@ static bool ot_entropy_src_consume_entropy(OtEntropySrcState *s, uint32_t word) return true; } +static uint32_t ot_entropy_src_get_entropy_data(OtEntropySrcState *s) +{ + bool is_entropy_data_enabled = + (s->version < 3) ? + REG_MB4_IS_TRUE(s, hi, CONF, V2_ENTROPY_DATA_REG_ENABLE) : + REG_MB4_IS_TRUE(s, hi, CONF, V3_ENTROPY_DATA_REG_ENABLE); + + if (ot_entropy_src_is_module_enabled(s) && is_entropy_data_enabled && + ot_entropy_src_is_fw_route(s)) { + if (!ot_fifo32_is_empty(&s->swread_fifo)) { + return ot_fifo32_pop(&s->swread_fifo); + } + qemu_log_mask(LOG_GUEST_ERROR, "%s: Entropy data not available\n", + __func__); + } else { + qemu_log_mask(LOG_GUEST_ERROR, "%s: Entropy data not configured\n", + __func__); + } + + return 0u; +} + static bool ot_entropy_src_fill_noise(OtEntropySrcState *s) { unsigned count = ot_fifo32_num_free(&s->input_fifo); @@ -1023,7 +1156,8 @@ static bool ot_entropy_src_fill_noise(OtEntropySrcState *s) ot_fifo32_push(&s->input_fifo, buffer[pos++]); } - trace_ot_entropy_src_fill_noise(count, ot_fifo32_num_used(&s->input_fifo)); + trace_ot_entropy_src_fill_noise(s->ot_id, count, + ot_fifo32_num_used(&s->input_fifo)); for (unsigned ix = 0; ix < ES_WORD_COUNT && !ot_fifo32_is_empty(&s->input_fifo); ix++) { @@ -1042,31 +1176,31 @@ static void ot_entropy_src_noise_refill(void *opaque) OtEntropySrcState *s = opaque; if (!ot_entropy_src_fill_noise(s)) { - trace_ot_entropy_src_info("FIFO already filled up"); + trace_ot_entropy_src_info(s->ot_id, "FIFO already filled up"); return; } switch (s->state) { - case ENTROPY_SRC_EG_BOOT_HT_RUNNING: + case ENTROPY_SRC_BOOT_HT_RUNNING: if (s->packet_count > 0) { - ot_entropy_src_change_state(s, ENTROPY_SRC_EG_BOOT_PHASE_DONE); + ot_entropy_src_change_state(s, ENTROPY_SRC_BOOT_PHASE_DONE); } break; - case ENTROPY_SRC_EG_STARTUP_HT_START: - ot_entropy_src_change_state(s, ENTROPY_SRC_EG_CONT_HT_RUNNING); + case ENTROPY_SRC_STARTUP_HT_START: + ot_entropy_src_change_state(s, ENTROPY_SRC_CONT_HT_RUNNING); break; - case ENTROPY_SRC_EG_CONT_HT_RUNNING: - case ENTROPY_SRC_EG_CONT_HT_START: - case ENTROPY_SRC_EG_BOOT_PHASE_DONE: - case ENTROPY_SRC_EG_SHA3_PREP: - case ENTROPY_SRC_EG_SHA3_VALID: - case ENTROPY_SRC_EG_SHA3_PROCESS: - case ENTROPY_SRC_EG_SHA3_DONE: - case ENTROPY_SRC_EG_SHA3_MSGDONE: + case ENTROPY_SRC_CONT_HT_RUNNING: + case ENTROPY_SRC_CONT_HT_START: + case ENTROPY_SRC_BOOT_PHASE_DONE: + case ENTROPY_SRC_SHA3_PREP: + case ENTROPY_SRC_SHA3_VALID: + case ENTROPY_SRC_SHA3_PROCESS: + case ENTROPY_SRC_SHA3_DONE: + case ENTROPY_SRC_SHA3_MSGDONE: break; default: - trace_ot_entropy_src_error("unexpected state", STATE_NAME(s->state), - s->state); + trace_ot_entropy_src_error(s->ot_id, "unexpected state", + STATE_NAME(s->state), s->state); break; } @@ -1078,30 +1212,30 @@ static void ot_entropy_src_scheduler(void *opaque) OtEntropySrcState *s = opaque; switch (s->state) { - case ENTROPY_SRC_EG_BOOT_HT_RUNNING: - case ENTROPY_SRC_EG_BOOT_PHASE_DONE: - case ENTROPY_SRC_EG_STARTUP_HT_START: - case ENTROPY_SRC_EG_CONT_HT_START: - case ENTROPY_SRC_EG_CONT_HT_RUNNING: - case ENTROPY_SRC_EG_SHA3_PREP: - case ENTROPY_SRC_EG_SHA3_VALID: - case ENTROPY_SRC_EG_SHA3_PROCESS: - case ENTROPY_SRC_EG_SHA3_DONE: - case ENTROPY_SRC_EG_SHA3_MSGDONE: + case ENTROPY_SRC_BOOT_HT_RUNNING: + case ENTROPY_SRC_BOOT_PHASE_DONE: + case ENTROPY_SRC_STARTUP_HT_START: + case ENTROPY_SRC_CONT_HT_START: + case ENTROPY_SRC_CONT_HT_RUNNING: + case ENTROPY_SRC_SHA3_PREP: + case ENTROPY_SRC_SHA3_VALID: + case ENTROPY_SRC_SHA3_PROCESS: + case ENTROPY_SRC_SHA3_DONE: + case ENTROPY_SRC_SHA3_MSGDONE: ot_entropy_src_noise_refill(s); break; - case ENTROPY_SRC_EG_IDLE: + case ENTROPY_SRC_IDLE: break; - case ENTROPY_SRC_EG_BOOT_POST_HT_CHK: - case ENTROPY_SRC_EG_STARTUP_PHASE1: - case ENTROPY_SRC_EG_STARTUP_PASS1: - case ENTROPY_SRC_EG_STARTUP_FAIL1: - case ENTROPY_SRC_EG_FW_INSERT_START: - case ENTROPY_SRC_EG_FW_INSERT_MSG: - case ENTROPY_SRC_EG_SHA3_QUIESCE: - case ENTROPY_SRC_EG_ALERT_STATE: - case ENTROPY_SRC_EG_ALERT_HANG: - case ENTROPY_SRC_EG_ERROR: + case ENTROPY_SRC_BOOT_POST_HT_CHK: + case ENTROPY_SRC_STARTUP_PHASE1: + case ENTROPY_SRC_STARTUP_PASS1: + case ENTROPY_SRC_STARTUP_FAIL1: + case ENTROPY_SRC_FW_INSERT_START: + case ENTROPY_SRC_FW_INSERT_MSG: + case ENTROPY_SRC_SHA3_QUIESCE: + case ENTROPY_SRC_ALERT_STATE: + case ENTROPY_SRC_ALERT_HANG: + case ENTROPY_SRC_ERROR: default: qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid state: [%s:%d]\n", __func__, STATE_NAME(s->state), s->state); @@ -1112,7 +1246,7 @@ static void ot_entropy_src_scheduler(void *opaque) } static uint64_t -ot_entropy_src_regs_read(void *opaque, hwaddr addr, unsigned size) +ot_entropy_src_lo_regs_read(void *opaque, hwaddr addr, unsigned size) { OtEntropySrcState *s = opaque; (void)size; @@ -1125,7 +1259,73 @@ ot_entropy_src_regs_read(void *opaque, hwaddr addr, unsigned size) case R_INTR_ENABLE: case R_ME_REGWEN: case R_SW_REGUPD: + val32 = s->regs_lo[reg]; + break; + case R_REGWEN: + val32 = (uint32_t)(s->regs_lo[R_SW_REGUPD] == R_SW_REGUPD_VAL_MASK && + ot_entropy_src_is_module_disabled(s)); + break; + case R_INTR_TEST: + case R_ALERT_TEST: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: %s: W/O register 0x%02" HWADDR_PRIx " (%s)\n", + __func__, s->ot_id, addr, REG_LO_NAME(reg)); + val32 = 0; + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: %s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, + s->ot_id, addr); + val32 = 0; + break; + } + uint32_t pc = ibex_get_current_pc(); + trace_ot_entropy_src_io_read_out(s->ot_id, (uint32_t)addr, REG_LO_NAME(reg), + val32, pc); + + return (uint64_t)val32; +} + +static uint64_t +ot_entropy_src_rev_regs_read(void *opaque, hwaddr addr, unsigned size) +{ + OtEntropySrcState *s = opaque; + (void)size; + uint32_t val32; + + g_assert(s->version < 3 && s->regs_rev); + + hwaddr reg = R32_OFF(addr); + + /* NOLINTNEXTLINE(hicpp-multiway-paths-covered) */ + switch (reg) { case R_REV: + val32 = s->regs_rev[reg]; + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: %s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, + s->ot_id, addr + REGS_REV_BASE); + val32 = 0; + break; + } + uint32_t pc = ibex_get_current_pc(); + trace_ot_entropy_src_io_read_out(s->ot_id, (uint32_t)addr + REGS_REV_BASE, + REG_REV_NAME(reg), val32, pc); + + return (uint64_t)val32; +} + +static uint64_t +ot_entropy_src_hi_regs_read(void *opaque, hwaddr addr, unsigned size) +{ + OtEntropySrcState *s = opaque; + (void)size; + uint32_t val32; + + hwaddr reg = R32_OFF(addr); + + switch (reg) { case R_MODULE_ENABLE: case R_CONF: case R_ENTROPY_CONTROL: @@ -1167,48 +1367,29 @@ ot_entropy_src_regs_read(void *opaque, hwaddr addr, unsigned size) case R_RECOV_ALERT_STS: case R_ERR_CODE: case R_ERR_CODE_TEST: - val32 = s->regs[reg]; + val32 = s->regs_hi[reg]; break; case R_DEBUG_STATUS: /* SHA3 block reporting is not supported */ val32 = FIELD_DP32(0, DEBUG_STATUS, ENTROPY_FIFO_DEPTH, ot_fifo32_num_used(&s->final_fifo)); val32 = FIELD_DP32(val32, DEBUG_STATUS, MAIN_SM_IDLE, - (uint32_t)(s->state == ENTROPY_SRC_EG_IDLE)); - val32 = - FIELD_DP32(val32, DEBUG_STATUS, MAIN_SM_BOOT_DONE, - (uint32_t)(s->state == ENTROPY_SRC_EG_BOOT_PHASE_DONE)); + (uint32_t)(s->state == ENTROPY_SRC_IDLE)); + val32 = FIELD_DP32(val32, DEBUG_STATUS, MAIN_SM_BOOT_DONE, + (uint32_t)(s->state == ENTROPY_SRC_BOOT_PHASE_DONE)); break; case R_MAIN_SM_STATE: if (s->state < ARRAY_SIZE(OtEDNFsmStateCode)) { val32 = OtEDNFsmStateCode[s->state]; } else { - val32 = OtEDNFsmStateCode[ENTROPY_SRC_EG_ERROR]; + val32 = OtEDNFsmStateCode[ENTROPY_SRC_ERROR]; } break; - case R_REGWEN: - val32 = (uint32_t)(s->regs[R_SW_REGUPD] == R_SW_REGUPD_UPD_MASK && - ot_entropy_src_is_module_disabled(s)); - break; case R_ALERT_SUMMARY_FAIL_COUNTS: val32 = (uint32_t)ot_alert_get_alert_fail_count(s); break; case R_ENTROPY_DATA: - if (ot_entropy_src_is_module_enabled(s) && - REG_MB4_IS_TRUE(s, CONF, ENTROPY_DATA_REG_ENABLE) && - ot_entropy_src_is_fw_route(s)) { - if (!ot_fifo32_is_empty(&s->swread_fifo)) { - val32 = ot_fifo32_pop(&s->swread_fifo); - } else { - qemu_log_mask(LOG_GUEST_ERROR, - "%s: Entropy data not available\n", __func__); - val32 = 0; - } - } else { - qemu_log_mask(LOG_GUEST_ERROR, "%s: Entropy data not configured\n", - __func__); - val32 = 0; - } + val32 = ot_entropy_src_get_entropy_data(s); break; case R_FW_OV_WR_FIFO_FULL: { bool can_write; @@ -1242,107 +1423,174 @@ ot_entropy_src_regs_read(void *opaque, hwaddr addr, unsigned size) case R_OBSERVE_FIFO_DEPTH: val32 = ot_fifo32_num_used(&s->observe_fifo); break; - case R_INTR_TEST: - case R_ALERT_TEST: case R_FW_OV_WR_DATA: - qemu_log_mask(LOG_GUEST_ERROR, - "%s: W/O register 0x%02" HWADDR_PRIx " (%s)\n", __func__, - addr, REG_NAME(reg)); + qemu_log_mask(LOG_GUEST_ERROR, "%s: %s: W/O register 0x%02x (%s)\n", + __func__, s->ot_id, ot_entropy_src_hi_reg_addr(s, addr), + REG_HI_NAME(reg)); val32 = 0; break; default: - qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n", - __func__, addr); + qemu_log_mask(LOG_GUEST_ERROR, "%s: %s: Bad offset 0x%x\n", __func__, + s->ot_id, ot_entropy_src_hi_reg_addr(s, addr)); val32 = 0; break; } - uint32_t pc = ibex_get_current_pc(); - trace_ot_entropy_src_io_read_out((uint32_t)addr, REG_NAME(reg), val32, pc); + trace_ot_entropy_src_io_read_out(s->ot_id, + ot_entropy_src_hi_reg_addr(s, addr), + REG_HI_NAME(reg), val32, pc); return (uint64_t)val32; -}; +} -#define CHECK_MULTIBOOT(_s_, _r_, _b_) \ +#define CHECK_MULTIBOOT(_s_, _g_, _r_, _b_) \ do { \ - if (!ot_entropy_src_check_multibitboot((_s_), \ - FIELD_EX32(s->regs[R_##_r_], \ - _r_, _b_), \ - ALERT_STATUS_BIT(_b_))) { \ + if (!ot_entropy_src_check_multibitboot( \ + (_s_), FIELD_EX32(s->regs##_##_g_[R_##_r_], _r_, _b_), \ + ALERT_STATUS_BIT(_b_))) { \ qemu_log_mask(LOG_GUEST_ERROR, \ - "%s: invalid multiboot value 0x%1x\n", __func__, \ - FIELD_EX32(s->regs[R_##_r_], _r_, _b_)); \ + "%s: %s: invalid multiboot value 0x%1x\n", __func__, \ + (_s_)->ot_id, \ + FIELD_EX32((_s_)->regs##_##_g_[R_##_r_], _r_, _b_)); \ } \ } while (0) -static void ot_entropy_src_regs_write(void *opaque, hwaddr addr, uint64_t val64, - unsigned size) +#define CHECK_MULTIBOOT_VER(_s_, _g_, _r_, _v_, _b_) \ + do { \ + if (!ot_entropy_src_check_multibitboot( \ + (_s_), FIELD_EX32(s->regs##_##_g_[R_##_r_], _r_, _v_##_##_b_), \ + ALERT_STATUS_BIT(_b_))) { \ + qemu_log_mask(LOG_GUEST_ERROR, \ + "%s: %s: invalid multiboot value 0x%1x\n", __func__, \ + (_s_)->ot_id, \ + FIELD_EX32((_s_)->regs##_##_g_[R_##_r_], _r_, \ + _v_##_##_b_)); \ + } \ + } while (0) + +static void ot_entropy_src_lo_regs_write(void *opaque, hwaddr addr, + uint64_t val64, unsigned size) { OtEntropySrcState *s = opaque; (void)size; uint32_t val32 = (uint32_t)val64; - hwaddr reg = R32_OFF(addr); uint32_t pc = ibex_get_current_pc(); - trace_ot_entropy_src_io_write((uint32_t)addr, REG_NAME(reg), val32, pc); + trace_ot_entropy_src_io_write(s->ot_id, (uint32_t)addr, REG_LO_NAME(reg), + val32, pc); switch (reg) { case R_INTR_STATE: - val32 &= INTR_MASK; - s->regs[reg] &= ~val32; /* RW1C */ + val32 &= INTR_WMASK; + s->regs_lo[reg] &= ~val32; /* RW1C */ /* not sure about this behavior, seems to be what the tests expect... */ if (!ot_fifo32_is_empty(&s->swread_fifo)) { - s->regs[R_INTR_STATE] |= INTR_ES_ENTROPY_VALID_MASK; + s->regs_lo[R_INTR_STATE] |= INTR_ES_ENTROPY_VALID_MASK; } if (!ot_fifo32_is_empty(&s->observe_fifo)) { - s->regs[R_INTR_STATE] |= INTR_ES_OBSERVE_FIFO_READY_MASK; + s->regs_lo[R_INTR_STATE] |= INTR_ES_OBSERVE_FIFO_READY_MASK; } ot_entropy_src_update_irqs(s); break; case R_INTR_ENABLE: - val32 &= INTR_MASK; - s->regs[reg] = val32; + val32 &= INTR_WMASK; + s->regs_lo[reg] = val32; ot_entropy_src_update_irqs(s); break; case R_INTR_TEST: - val32 &= INTR_MASK; - s->regs[R_INTR_STATE] |= val32; + val32 &= INTR_WMASK; + s->regs_lo[R_INTR_STATE] |= val32; ot_entropy_src_update_irqs(s); break; case R_ALERT_TEST: - val32 &= ALERT_TEST_MASK; - s->regs[reg] = val32; + val32 &= ALERT_TEST_WMASK; + s->regs_lo[reg] = val32; ot_entropy_src_update_alerts(s); break; case R_ME_REGWEN: val32 &= R_ME_REGWEN_EN_MASK; - s->regs[reg] &= val32; /* RW0C */ + s->regs_lo[reg] &= val32; /* RW0C */ break; case R_SW_REGUPD: - val32 &= R_SW_REGUPD_UPD_MASK; - s->regs[reg] &= val32; /* RW0C */ + val32 &= R_SW_REGUPD_VAL_MASK; + s->regs_lo[reg] &= val32; /* RW0C */ + break; + case R_REGWEN: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: %s: R/O register 0x%02" HWADDR_PRIx " (%s)\n", + __func__, s->ot_id, addr, REG_LO_NAME(reg)); + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: %s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, + s->ot_id, addr); + break; + } +}; + +static void ot_entropy_src_rev_regs_write(void *opaque, hwaddr addr, + uint64_t val64, unsigned size) +{ + OtEntropySrcState *s = opaque; + (void)size; + uint32_t val32 = (uint32_t)val64; + hwaddr reg = R32_OFF(addr); + + uint32_t pc = ibex_get_current_pc(); + trace_ot_entropy_src_io_write(s->ot_id, (uint32_t)addr + REGS_REV_BASE, + REG_REV_NAME(reg), val32, pc); + + /* NOLINTNEXTLINE(hicpp-multiway-paths-covered) */ + switch (reg) { + case R_REV: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: %s: R/O register 0x%02" HWADDR_PRIx " (%s)\n", + __func__, s->ot_id, addr + REGS_REV_BASE, + REG_REV_NAME(reg)); break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: %s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, + s->ot_id, addr + REGS_REV_BASE); + break; + } +}; + +static void ot_entropy_src_hi_regs_write(void *opaque, hwaddr addr, + uint64_t val64, unsigned size) +{ + OtEntropySrcState *s = opaque; + (void)size; + uint32_t val32 = (uint32_t)val64; + + hwaddr reg = R32_OFF(addr); + + uint32_t pc = ibex_get_current_pc(); + trace_ot_entropy_src_io_write(s->ot_id, ot_entropy_src_hi_reg_addr(s, addr), + REG_HI_NAME(reg), val32, pc); + + switch (reg) { case R_MODULE_ENABLE: - if (s->regs[R_ME_REGWEN]) { - uint32_t old = s->regs[reg]; + if (s->regs_lo[R_ME_REGWEN]) { + uint32_t old = s->regs_hi[reg]; val32 &= R_MODULE_ENABLE_MODULE_ENABLE_MASK; - s->regs[reg] = val32; - CHECK_MULTIBOOT(s, MODULE_ENABLE, MODULE_ENABLE); + s->regs_hi[reg] = val32; + CHECK_MULTIBOOT(s, hi, MODULE_ENABLE, MODULE_ENABLE); if (ot_entropy_src_is_module_disabled(s)) { /* reset takes care of cancelling the scheduler timer */ resettable_reset(OBJECT(s), RESET_TYPE_COLD); break; } - if ((old ^ s->regs[reg]) && ot_entropy_src_is_module_enabled(s)) { + if ((old ^ s->regs_hi[reg]) && + ot_entropy_src_is_module_enabled(s)) { if (ot_entropy_src_is_fips_enabled(s)) { /* start up phase */ - ot_entropy_src_change_state( - s, ENTROPY_SRC_EG_STARTUP_HT_START); + ot_entropy_src_change_state(s, + ENTROPY_SRC_STARTUP_HT_START); } else { /* boot phase */ - ot_entropy_src_change_state(s, - ENTROPY_SRC_EG_BOOT_HT_RUNNING); + ot_entropy_src_change_state(s, ENTROPY_SRC_BOOT_HT_RUNNING); } uint64_t now = qemu_clock_get_ns(OT_VIRTUAL_CLOCK); timer_mod(s->scheduler, @@ -1354,26 +1602,31 @@ static void ot_entropy_src_regs_write(void *opaque, hwaddr addr, uint64_t val64, qemu_log_mask(LOG_GUEST_ERROR, "%s: ME_REGWEN not enabled\n", __func__); break; case R_CONF: - if (s->regs[R_REGWEN]) { - val32 &= CONF_MASK; - s->regs[reg] = val32; - CHECK_MULTIBOOT(s, CONF, FIPS_ENABLE); - CHECK_MULTIBOOT(s, CONF, ENTROPY_DATA_REG_ENABLE); - CHECK_MULTIBOOT(s, CONF, THRESHOLD_SCOPE); - CHECK_MULTIBOOT(s, CONF, RNG_BIT_ENABLE); + if (s->regs_lo[R_REGWEN]) { + val32 &= (s->version < 3) ? CONF_V2_WMASK : CONF_V3_WMASK; + s->regs_hi[reg] = val32; + CHECK_MULTIBOOT(s, hi, CONF, FIPS_ENABLE); + CHECK_MULTIBOOT(s, hi, CONF, RNG_BIT_ENABLE); + if (s->version < 3) { + CHECK_MULTIBOOT_VER(s, hi, CONF, V2, ENTROPY_DATA_REG_ENABLE); + CHECK_MULTIBOOT_VER(s, hi, CONF, V2, THRESHOLD_SCOPE); + } else { + CHECK_MULTIBOOT_VER(s, hi, CONF, V3, ENTROPY_DATA_REG_ENABLE); + CHECK_MULTIBOOT_VER(s, hi, CONF, V3, THRESHOLD_SCOPE); + } } break; case R_ENTROPY_CONTROL: - if (s->regs[R_REGWEN]) { - val32 &= ENTROPY_CONTROL_MASK; - s->regs[reg] = val32; - CHECK_MULTIBOOT(s, ENTROPY_CONTROL, ES_ROUTE); - CHECK_MULTIBOOT(s, ENTROPY_CONTROL, ES_TYPE); + if (s->regs_lo[R_REGWEN]) { + val32 &= ENTROPY_CONTROL_WMASK; + s->regs_hi[reg] = val32; + CHECK_MULTIBOOT(s, hi, ENTROPY_CONTROL, ES_ROUTE); + CHECK_MULTIBOOT(s, hi, ENTROPY_CONTROL, ES_TYPE); } break; case R_HEALTH_TEST_WINDOWS: - if (s->regs[R_REGWEN]) { - s->regs[reg] = val32; + if (s->regs_lo[R_REGWEN]) { + s->regs_hi[reg] = val32; } break; case R_REPCNT_THRESHOLDS: @@ -1385,28 +1638,28 @@ static void ot_entropy_src_regs_write(void *opaque, hwaddr addr, uint64_t val64, case R_MARKOV_LO_THRESHOLDS: case R_EXTHT_HI_THRESHOLDS: case R_EXTHT_LO_THRESHOLDS: - if (s->regs[R_REGWEN]) { - s->regs[reg] = val32; + if (s->regs_lo[R_REGWEN]) { + s->regs_hi[reg] = val32; ot_entropy_src_update_alerts(s); } break; case R_ALERT_THRESHOLD: - if (s->regs[R_REGWEN]) { + if (s->regs_lo[R_REGWEN]) { if ((uint16_t)(val32) != (uint16_t)(~(val32 >> 16u))) { - s->regs[R_RECOV_ALERT_STS] |= + s->regs_hi[R_RECOV_ALERT_STS] |= R_RECOV_ALERT_STS_ES_THRESH_CFG_ALERT_MASK; } else { - s->regs[reg] = val32; + s->regs_hi[reg] = val32; } ot_entropy_src_update_alerts(s); } break; case R_FW_OV_CONTROL: - if (s->regs[R_REGWEN]) { - val32 &= FW_OV_CONTROL_MASK; - s->regs[reg] = val32; - CHECK_MULTIBOOT(s, FW_OV_CONTROL, FW_OV_MODE); - CHECK_MULTIBOOT(s, FW_OV_CONTROL, FW_OV_ENTROPY_INSERT); + if (s->regs_lo[R_REGWEN]) { + val32 &= FW_OV_CONTROL_WMASK; + s->regs_hi[reg] = val32; + CHECK_MULTIBOOT(s, hi, FW_OV_CONTROL, FW_OV_MODE); + CHECK_MULTIBOOT(s, hi, FW_OV_CONTROL, FW_OV_ENTROPY_INSERT); s->obs_fifo_en = ot_entropy_src_is_fw_ov_mode(s); } break; @@ -1417,16 +1670,16 @@ static void ot_entropy_src_regs_write(void *opaque, hwaddr addr, uint64_t val64, break; } val32 &= R_FW_OV_SHA3_START_FW_OV_INSERT_START_MASK; - s->regs[reg] = val32; - CHECK_MULTIBOOT(s, FW_OV_SHA3_START, FW_OV_INSERT_START); - if (REG_MB4_IS_TRUE(s, FW_OV_SHA3_START, FW_OV_INSERT_START)) { + s->regs_hi[reg] = val32; + CHECK_MULTIBOOT(s, hi, FW_OV_SHA3_START, FW_OV_INSERT_START); + if (REG_MB4_IS_TRUE(s, hi, FW_OV_SHA3_START, FW_OV_INSERT_START)) { OtEntropySrcFsmState new_state; new_state = ot_entropy_src_is_bypass_mode(s) ? - ENTROPY_SRC_EG_IDLE : - ENTROPY_SRC_EG_FW_INSERT_START; + ENTROPY_SRC_IDLE : + ENTROPY_SRC_FW_INSERT_START; ot_entropy_src_change_state(s, new_state); } else { /* default to false */ - if (s->state == ENTROPY_SRC_EG_SHA3_PROCESS) { + if (s->state == ENTROPY_SRC_SHA3_PROCESS) { /* handle SHA3 processing */ if (ot_fifo32_is_empty(&s->precon_fifo)) { ot_entropy_src_perform_hash(s); @@ -1440,15 +1693,15 @@ static void ot_entropy_src_regs_write(void *opaque, hwaddr addr, uint64_t val64, } else { OtEntropySrcFsmState new_state; new_state = ot_entropy_src_is_bypass_mode(s) ? - ENTROPY_SRC_EG_BOOT_HT_RUNNING : - ENTROPY_SRC_EG_STARTUP_HT_START; + ENTROPY_SRC_BOOT_HT_RUNNING : + ENTROPY_SRC_STARTUP_HT_START; ot_entropy_src_change_state(s, new_state); } } break; case R_FW_OV_RD_FIFO_OVERFLOW: val32 &= R_FW_OV_RD_FIFO_OVERFLOW_VAL_MASK; - s->regs[reg] &= val32; /* RW0C */ + s->regs_hi[reg] &= val32; /* RW0C */ break; case R_FW_OV_WR_DATA: if (!ot_entropy_src_is_module_enabled(s)) { @@ -1480,24 +1733,22 @@ static void ot_entropy_src_regs_write(void *opaque, hwaddr addr, uint64_t val64, } break; case R_OBSERVE_FIFO_THRESH: - if (s->regs[R_REGWEN]) { + if (s->regs_lo[R_REGWEN]) { val32 &= R_OBSERVE_FIFO_THRESH_VAL_MASK; - s->regs[reg] = val32; + s->regs_hi[reg] = val32; ot_entropy_src_update_irqs(s); } break; case R_RECOV_ALERT_STS: - val32 &= RECOV_ALERT_STS_MASK; - s->regs[reg] &= val32; /* RW0C */ + val32 &= RECOV_ALERT_STS_WMASK; + s->regs_hi[reg] &= val32; /* RW0C */ break; case R_ERR_CODE_TEST: val32 &= R_ERR_CODE_TEST_VAL_MASK; - s->regs[R_ERR_CODE_TEST] = val32; + s->regs_hi[R_ERR_CODE_TEST] = val32; ot_entropy_src_update_irqs(s); ot_entropy_src_update_alerts(s); break; - case R_REGWEN: - case R_REV: case R_ENTROPY_DATA: case R_REPCNT_HI_WATERMARKS: case R_REPCNTS_HI_WATERMARKS: @@ -1526,18 +1777,51 @@ static void ot_entropy_src_regs_write(void *opaque, hwaddr addr, uint64_t val64, case R_DEBUG_STATUS: case R_ERR_CODE: case R_MAIN_SM_STATE: - qemu_log_mask(LOG_GUEST_ERROR, - "%s: R/O register 0x%02" HWADDR_PRIx " (%s)\n", __func__, - addr, REG_NAME(reg)); + qemu_log_mask(LOG_GUEST_ERROR, "%s: R/O register 0x%02x (%s)\n", + __func__, ot_entropy_src_hi_reg_addr(s, addr), + REG_HI_NAME(reg)); break; default: - qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n", - __func__, addr); + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%02x\n", __func__, + ot_entropy_src_hi_reg_addr(s, addr)); break; } }; +static const MemoryRegionOps ot_entropy_src_lo_ops = { + .read = &ot_entropy_src_lo_regs_read, + .write = &ot_entropy_src_lo_regs_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .impl = { + .min_access_size = 4u, + .max_access_size = 4u, + }, +}; + +static const MemoryRegionOps ot_entropy_src_rev_ops = { + .read = &ot_entropy_src_rev_regs_read, + .write = &ot_entropy_src_rev_regs_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .impl = { + .min_access_size = 4u, + .max_access_size = 4u, + }, +}; + +static const MemoryRegionOps ot_entropy_src_hi_ops = { + .read = &ot_entropy_src_hi_regs_read, + .write = &ot_entropy_src_hi_regs_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .impl = { + .min_access_size = 4u, + .max_access_size = 4u, + }, +}; + static Property ot_entropy_src_properties[] = { + DEFINE_PROP_STRING(OT_COMMON_DEV_ID, OtEntropySrcState, ot_id), + DEFINE_PROP_UINT32("version", OtEntropySrcState, version, 0), + DEFINE_PROP_LINK("ast", OtEntropySrcState, ast, TYPE_OT_AST_EG, OtASTEgState *), DEFINE_PROP_LINK("otp_ctrl", OtEntropySrcState, otp_ctrl, TYPE_OT_OTP, @@ -1545,52 +1829,52 @@ static Property ot_entropy_src_properties[] = { DEFINE_PROP_END_OF_LIST(), }; -static const MemoryRegionOps ot_entropy_src_regs_ops = { - .read = &ot_entropy_src_regs_read, - .write = &ot_entropy_src_regs_write, - .endianness = DEVICE_NATIVE_ENDIAN, - .impl.min_access_size = 4u, - .impl.max_access_size = 4u, -}; - static void ot_entropy_src_reset_enter(Object *obj, ResetType type) { OtEntropySrcClass *c = OT_ENTROPY_SRC_GET_CLASS(obj); OtEntropySrcState *s = OT_ENTROPY_SRC(obj); - trace_ot_entropy_src_reset(); + trace_ot_entropy_src_reset(s->ot_id); if (c->parent_phases.enter) { c->parent_phases.enter(obj, type); } - timer_del(s->scheduler); - - memset(s->regs, 0, REGS_SIZE); - - s->regs[R_ME_REGWEN] = 0x1u; - s->regs[R_SW_REGUPD] = 0x1u; - s->regs[R_REGWEN] = 0x1u; - s->regs[R_REV] = 0x10303u; - s->regs[R_MODULE_ENABLE] = 0x9u; - s->regs[R_CONF] = 0x2649999u; - s->regs[R_ENTROPY_CONTROL] = 0x99u; - s->regs[R_HEALTH_TEST_WINDOWS] = 0x600200u; - s->regs[R_REPCNT_THRESHOLDS] = 0xffffffffu; - s->regs[R_REPCNTS_THRESHOLDS] = 0xffffffffu; - s->regs[R_ADAPTP_HI_THRESHOLDS] = 0xffffffffu; - s->regs[R_BUCKET_THRESHOLDS] = 0xffffffffu; - s->regs[R_MARKOV_HI_THRESHOLDS] = 0xffffffffu; - s->regs[R_EXTHT_HI_THRESHOLDS] = 0xffffffffu; - s->regs[R_ADAPTP_LO_WATERMARKS] = 0xffffffffu; - s->regs[R_EXTHT_LO_WATERMARKS] = 0xffffffffu; - s->regs[R_MARKOV_LO_WATERMARKS] = 0xffffffffu; - s->regs[R_ALERT_THRESHOLD] = 0xfffd0002u; - s->regs[R_FW_OV_CONTROL] = 0x99u; - s->regs[R_FW_OV_SHA3_START] = 0x9u; - s->regs[R_OBSERVE_FIFO_THRESH] = 0x10u; - s->regs[R_DEBUG_STATUS] = 0x10000u; + memset(s->regs_lo, 0, REGS_LO_SIZE); + if (s->version < 3) { + memset(s->regs_rev, 0, REGS_REV_SIZE); + } + memset(s->regs_hi, 0, REGS_HI_SIZE); + + s->regs_lo[R_ME_REGWEN] = 0x00000001u; + s->regs_lo[R_SW_REGUPD] = 0x00000001u; + s->regs_lo[R_REGWEN] = 0x00000001u; + if (s->version < 3) { + s->regs_rev[R_REV] = 0x10303u; + s->regs_hi[R_CONF] = 0x2649999u; + s->regs_hi[R_HEALTH_TEST_WINDOWS] = 0x600200u; + } else { + s->regs_hi[R_CONF] = 0x999999u; + s->regs_hi[R_HEALTH_TEST_WINDOWS] = 0x1800200u; + } + s->regs_hi[R_MODULE_ENABLE] = 0x9u; + s->regs_hi[R_ENTROPY_CONTROL] = 0x99u; + s->regs_hi[R_REPCNT_THRESHOLDS] = 0xffffffffu; + s->regs_hi[R_REPCNTS_THRESHOLDS] = 0xffffffffu; + s->regs_hi[R_ADAPTP_HI_THRESHOLDS] = 0xffffffffu; + s->regs_hi[R_BUCKET_THRESHOLDS] = 0xffffffffu; + s->regs_hi[R_MARKOV_HI_THRESHOLDS] = 0xffffffffu; + s->regs_hi[R_EXTHT_HI_THRESHOLDS] = 0xffffffffu; + s->regs_hi[R_ADAPTP_LO_WATERMARKS] = 0xffffffffu; + s->regs_hi[R_EXTHT_LO_WATERMARKS] = 0xffffffffu; + s->regs_hi[R_MARKOV_LO_WATERMARKS] = 0xffffffffu; + s->regs_hi[R_ALERT_THRESHOLD] = 0xfffd0002u; + s->regs_hi[R_FW_OV_CONTROL] = 0x99u; + s->regs_hi[R_FW_OV_SHA3_START] = 0x9u; + s->regs_hi[R_OBSERVE_FIFO_THRESH] = 0x10u; + s->regs_hi[R_DEBUG_STATUS] = 0x10000u; + s->regs_hi[R_MAIN_SM_STATE] = 0xf5u; ot_fifo32_reset(&s->input_fifo); ot_fifo32_reset(&s->precon_fifo); ot_fifo32_reset(&s->bypass_fifo); @@ -1604,7 +1888,7 @@ static void ot_entropy_src_reset_enter(Object *obj, ResetType type) s->obs_fifo_en = false; ot_entropy_src_update_irqs(s); - for (unsigned ix = 0; ix < PARAM_NUM_ALERTS; ix++) { + for (unsigned ix = 0; ix < NUM_ALERTS; ix++) { ibex_irq_set(&s->alerts[ix], 0); } @@ -1612,7 +1896,7 @@ static void ot_entropy_src_reset_enter(Object *obj, ResetType type) const OtOTPEntropyCfg *entropy_cfg = oc->get_entropy_cfg(s->otp_ctrl); g_assert(entropy_cfg); - ot_entropy_src_change_state(s, ENTROPY_SRC_EG_IDLE); + ot_entropy_src_change_state(s, ENTROPY_SRC_IDLE); } static void ot_entropy_src_realize(DeviceState *dev, Error **errp) @@ -1621,6 +1905,8 @@ static void ot_entropy_src_realize(DeviceState *dev, Error **errp) OtEntropySrcState *s = OT_ENTROPY_SRC(dev); + /* emulated version should be specified */ + g_assert(s->version > 0); g_assert(s->ast); g_assert(s->otp_ctrl); } @@ -1629,22 +1915,45 @@ static void ot_entropy_src_init(Object *obj) { OtEntropySrcState *s = OT_ENTROPY_SRC(obj); - memory_region_init_io(&s->mmio, obj, &ot_entropy_src_regs_ops, s, - TYPE_OT_ENTROPY_SRC, REGS_SIZE); +#define OT_ENTROPY_SRC_APERTURE 0x100u + + memory_region_init(&s->mmio, obj, TYPE_OT_ENTROPY_SRC "-regs", + OT_ENTROPY_SRC_APERTURE); sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->mmio); - s->regs = g_new0(uint32_t, REGS_COUNT); - for (unsigned ix = 0; ix < PARAM_NUM_IRQS; ix++) { + memory_region_init_io(&s->mmio_lo, obj, &ot_entropy_src_lo_ops, s, + TYPE_OT_ENTROPY_SRC "-regs-lo", REGS_LO_SIZE); + memory_region_add_subregion(&s->mmio, REGS_LO_BASE, &s->mmio_lo); + + if (s->version < 3) { + memory_region_init_io(&s->mmio_rev, obj, &ot_entropy_src_rev_ops, s, + TYPE_OT_ENTROPY_SRC "-regs-rev", REGS_REV_SIZE); + memory_region_add_subregion(&s->mmio, REGS_REV_BASE, &s->mmio_rev); + } + + memory_region_init_io(&s->mmio_hi, obj, &ot_entropy_src_hi_ops, s, + TYPE_OT_ENTROPY_SRC "-regs-hi", REGS_HI_SIZE); + memory_region_add_subregion(&s->mmio, ot_entropy_src_hi_reg_base(s), + &s->mmio_hi); + + s->regs_lo = g_new0(uint32_t, REGS_LO_COUNT); + if (s->version < 3) { + s->regs_rev = g_new0(uint32_t, REGS_REV_COUNT); + } + s->regs_hi = g_new0(uint32_t, REGS_HI_COUNT); + + for (unsigned ix = 0; ix < NUM_IRQS; ix++) { ibex_sysbus_init_irq(obj, &s->irqs[ix]); } - for (unsigned ix = 0; ix < PARAM_NUM_ALERTS; ix++) { + + for (unsigned ix = 0; ix < NUM_ALERTS; ix++) { ibex_qdev_init_irq(obj, &s->alerts[ix], OT_DEVICE_ALERT); } ot_fifo32_create(&s->input_fifo, OT_ENTROPY_SRC_FILL_WORD_COUNT * 2u); ot_fifo32_create(&s->precon_fifo, sizeof(uint64_t) / sizeof(uint32_t)); ot_fifo32_create(&s->bypass_fifo, ES_WORD_COUNT); - ot_fifo32_create(&s->observe_fifo, PARAM_OBSERVE_FIFO_DEPTH); + ot_fifo32_create(&s->observe_fifo, OBSERVE_FIFO_DEPTH); ot_fifo32_create(&s->swread_fifo, ES_SWREAD_FIFO_WORD_COUNT); ot_fifo32_create(&s->final_fifo, ES_FINAL_FIFO_WORD_COUNT); diff --git a/hw/opentitan/trace-events b/hw/opentitan/trace-events index 76ce0226c7a9..b235bd00660c 100644 --- a/hw/opentitan/trace-events +++ b/hw/opentitan/trace-events @@ -178,22 +178,22 @@ ot_edn_xinfo(unsigned appid, const char *func, int line, const char *msg, uint32 # ot_entropy_src.c -ot_entropy_src_available(const char *state, int st) "entropy source is ready in [%s:%u]" -ot_entropy_src_change_state(int line, const char *old, int nold, const char *new, int nnew) "@ %d [%s:%d] -> [%s:%d]" -ot_entropy_src_consume_entropy(bool obs_fifo, bool bypass, bool hw_path, unsigned ncount) "obs_fifo %u, bypass %u, hw_path %u ncount %u" -ot_entropy_src_error(const char *msg, const char *state, int st) "%s [%s:%u]" -ot_entropy_src_fill_noise(unsigned count, unsigned infifo) "up to %u, input fifo %u" -ot_entropy_src_get_random_fips(const char *state, bool en, bool es_route, bool es_type, bool rng_bit_en, bool cap, bool comp, bool fips) "st:%s en:%u rt:%u tp:%u !rb:%u cap:%u comp:%u => %u" -ot_entropy_src_info(const char *msg) "%s" -ot_entropy_src_init_ongoing(const char *state, int st, int ns) "ES still initializing in [%s:%u] %d ns to go" -ot_entropy_src_io_read_out(uint32_t addr, const char * regname, uint32_t val, uint32_t pc) "addr=0x%02x (%s), val=0x%x, pc=0x%x" -ot_entropy_src_io_write(uint32_t addr, const char * regname, uint32_t val, uint32_t pc) "addr=0x%02x (%s), val=0x%x, pc=0x%x" -ot_entropy_src_no_entropy(unsigned count) "only %u words available" -ot_entropy_src_obs_fifo(unsigned level, unsigned thold) "level %u, threshold %u" -ot_entropy_src_push_bypass_entropy(unsigned slot) "final FIFO depth: %u" -ot_entropy_src_reset(void) "" -ot_entropy_src_show_buffer(const char *func, int line, const char *msg, const char *hexstr) "%s:%u %s: %s" -ot_entropy_src_update_filler(bool iok, bool ook, bool pok, bool all) "in %u, out %u, proc %u -> %u" +ot_entropy_src_available(const char *id, const char *state, int st) "%s: entropy source is ready in [%s:%u]" +ot_entropy_src_change_state(const char *id, int line, const char *old, int nold, const char *new, int nnew) "%s: @ %d [%s:%d] -> [%s:%d]" +ot_entropy_src_consume_entropy(const char *id, bool obs_fifo, bool bypass, bool hw_path, unsigned ncount) "%s: obs_fifo %u, bypass %u, hw_path %u ncount %u" +ot_entropy_src_error(const char *id, const char *msg, const char *state, int st) "%s: %s [%s:%u]" +ot_entropy_src_fill_noise(const char *id, unsigned count, unsigned infifo) "%s: up to %u, input fifo %u" +ot_entropy_src_get_random_fips(const char *id, const char *state, bool en, bool es_route, bool es_type, bool rng_bit_en, bool cap, bool comp, bool fips) "%s: st:%s en:%u rt:%u tp:%u !rb:%u cap:%u comp:%u => %u" +ot_entropy_src_info(const char *id, const char *msg) "%s: %s" +ot_entropy_src_init_ongoing(const char *id, const char *state, int st, int ns) "%s: ES still initializing in [%s:%u] %d ns to go" +ot_entropy_src_io_read_out(const char *id, uint32_t addr, const char * regname, uint32_t val, uint32_t pc) "%s: addr=0x%02x (%s), val=0x%x, pc=0x%x" +ot_entropy_src_io_write(const char *id, uint32_t addr, const char * regname, uint32_t val, uint32_t pc) "%s: addr=0x%02x (%s), val=0x%x, pc=0x%x" +ot_entropy_src_no_entropy(const char *id, unsigned count) "%s: only %u words available" +ot_entropy_src_obs_fifo(const char *id, unsigned level, unsigned thold) "%s: level %u, threshold %u" +ot_entropy_src_push_bypass_entropy(const char *id, unsigned slot) "%s: final FIFO depth: %u" +ot_entropy_src_reset(const char *id, void) "%s: " +ot_entropy_src_show_buffer(const char *id, const char *func, int line, const char *msg, const char *hexstr) "%s: %s:%u %s: %s" +ot_entropy_src_update_filler(const char *id, bool iok, bool ook, bool pok, bool all) "%s: in %u, out %u, proc %u -> %u" # ot_flash.c From 8a1b00e613d88f65f5986fd5420d5f0fb011ddd6 Mon Sep 17 00:00:00 2001 From: Emmanuel Blot Date: Thu, 23 Oct 2025 11:44:47 +0200 Subject: [PATCH 03/18] [ot] hw/opentitan: ot_entropy_src: remove random interface abstraction. Both EarlGrey and Darjeeling now use the EntropySrc to obtain entropy, whereas previous Darjeeling implementation was collecting entropy from the AST. Rework the EntropySrc class to expose a method to provide entropy to the CSRNG, and update CSRNG to use this "unique" entropy source. Signed-off-by: Emmanuel Blot --- hw/opentitan/Kconfig | 1 - hw/opentitan/ot_entropy_src.c | 72 +++++++++++---------------- include/hw/opentitan/ot_entropy_src.h | 30 +++++++++++ 3 files changed, 59 insertions(+), 44 deletions(-) diff --git a/hw/opentitan/Kconfig b/hw/opentitan/Kconfig index 154a7cf49f65..f8b26fc800b5 100644 --- a/hw/opentitan/Kconfig +++ b/hw/opentitan/Kconfig @@ -53,7 +53,6 @@ config OT_EDN bool config OT_ENTROPY_SRC - select OT_RANDOM_SRC bool config OT_FLASH diff --git a/hw/opentitan/ot_entropy_src.c b/hw/opentitan/ot_entropy_src.c index 109309b44901..58a9f5757992 100644 --- a/hw/opentitan/ot_entropy_src.c +++ b/hw/opentitan/ot_entropy_src.c @@ -44,7 +44,6 @@ #include "hw/opentitan/ot_entropy_src.h" #include "hw/opentitan/ot_fifo32.h" #include "hw/opentitan/ot_otp.h" -#include "hw/opentitan/ot_random_src.h" #include "hw/qdev-properties.h" #include "hw/registerfields.h" #include "hw/riscv/ibex_common.h" @@ -414,7 +413,7 @@ static const char *REG_HI_NAMES[REGS_HI_COUNT] = { ((NANOSECONDS_PER_SECOND * ES_FILL_BITS) / \ ((uint64_t)OT_AST_EG_RANDOM_4BIT_RATE * 4u)) #define OT_ENTROPY_SRC_FILL_WORD_COUNT (ES_FILL_BITS / (8u * sizeof(uint32_t))) -#define ES_WORD_COUNT (OT_RANDOM_SRC_WORD_COUNT) +#define ES_WORD_COUNT (OT_ENTROPY_SRC_WORD_COUNT) #define ES_SWREAD_FIFO_WORD_COUNT ES_WORD_COUNT #define ES_FINAL_FIFO_WORD_COUNT (ES_WORD_COUNT * ES_FINAL_FIFO_DEPTH) #define ES_HEXBUF_SIZE ((8U * 2u + 1u) * ES_WORD_COUNT + 4u) @@ -497,11 +496,6 @@ struct OtEntropySrcState { OtOTPState *otp_ctrl; }; -struct OtEntropySrcClass { - SysBusDeviceClass parent_class; - ResettablePhases parent_phases; -}; - /* @todo: need to check the FSM code are identical on v2 and v3... */ static const uint16_t OtEDNFsmStateCode[] = { [ENTROPY_SRC_IDLE] = 0b011110101, @@ -572,19 +566,18 @@ static bool ot_entropy_src_is_fips_capable(const OtEntropySrcState *s); static void ot_entropy_src_update_alerts(OtEntropySrcState *s); static void ot_entropy_src_update_filler(OtEntropySrcState *s); -static int ot_entropy_src_get_random( - OtRandomSrcIf *dev, uint64_t random[OT_RANDOM_SRC_DWORD_COUNT], bool *fips) +static int ot_entropy_src_get_entropy( + OtEntropySrcState *ess, uint64_t random[OT_ENTROPY_SRC_DWORD_COUNT], + bool *fips) { - OtEntropySrcState *s = OT_ENTROPY_SRC(dev); - - if (!ot_entropy_src_is_module_enabled(s)) { + if (!ot_entropy_src_is_module_enabled(ess)) { qemu_log_mask(LOG_GUEST_ERROR, "%s: entropy_src is down\n", __func__); return -1; } bool fips_compliant; - switch (s->state) { + switch (ess->state) { case ENTROPY_SRC_BOOT_PHASE_DONE: fips_compliant = false; break; @@ -604,16 +597,16 @@ static int ot_entropy_src_get_random( case ENTROPY_SRC_STARTUP_PASS1: case ENTROPY_SRC_STARTUP_FAIL1: { int64_t wait_ns; - if (timer_pending(s->scheduler)) { + if (timer_pending(ess->scheduler)) { /* computed delay fits into a 31-bit value */ - wait_ns = ((int64_t)timer_expire_time_ns(s->scheduler)) - + wait_ns = ((int64_t)timer_expire_time_ns(ess->scheduler)) - qemu_clock_get_ns(OT_VIRTUAL_CLOCK); wait_ns = MAX(wait_ns, OT_ENTROPY_SRC_WAIT_DELAY_NS); } else { wait_ns = OT_ENTROPY_SRC_WAIT_DELAY_NS; } - trace_ot_entropy_src_init_ongoing(s->ot_id, STATE_NAME(s->state), - s->state, (int)wait_ns); + trace_ot_entropy_src_init_ongoing(ess->ot_id, STATE_NAME(ess->state), + ess->state, (int)wait_ns); /* not ready */ return (int)wait_ns; } @@ -628,42 +621,42 @@ static int ot_entropy_src_get_random( case ENTROPY_SRC_ERROR: default: qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid state: [%s:%d]\n", __func__, - STATE_NAME(s->state), s->state); + STATE_NAME(ess->state), ess->state); return -1; } - if (!ot_entropy_src_is_hw_route(s)) { + if (!ot_entropy_src_is_hw_route(ess)) { qemu_log_mask(LOG_GUEST_ERROR, "%s: HW route not selected\n", __func__); return -1; } - if (ot_fifo32_num_used(&s->final_fifo) < ES_WORD_COUNT) { - trace_ot_entropy_src_no_entropy(s->ot_id, - ot_fifo32_num_used(&s->final_fifo)); + if (ot_fifo32_num_used(&ess->final_fifo) < ES_WORD_COUNT) { + trace_ot_entropy_src_no_entropy(ess->ot_id, + ot_fifo32_num_used(&ess->final_fifo)); return OT_ENTROPY_SRC_WAIT_DELAY_NS; } uint32_t *randu32 = (uint32_t *)random; size_t pos = 0; while (pos < ES_WORD_COUNT) { - g_assert(!ot_fifo32_is_empty(&s->final_fifo)); - randu32[pos++] = ot_fifo32_pop(&s->final_fifo); + g_assert(!ot_fifo32_is_empty(&ess->final_fifo)); + randu32[pos++] = ot_fifo32_pop(&ess->final_fifo); } - bool fips_capable = ot_entropy_src_is_fips_capable(s); + bool fips_capable = ot_entropy_src_is_fips_capable(ess); /* note: fips compliancy is only simulated here for now */ *fips = fips_compliant && fips_capable; trace_ot_entropy_src_get_random_fips( - s->ot_id, STATE_NAME(s->state), ot_entropy_src_is_fips_enabled(s), - REG_MB4_IS_TRUE(s, hi, ENTROPY_CONTROL, ES_ROUTE), - REG_MB4_IS_TRUE(s, hi, ENTROPY_CONTROL, ES_TYPE), - REG_MB4_IS_FALSE(s, hi, CONF, RNG_BIT_ENABLE), fips_capable, + ess->ot_id, STATE_NAME(ess->state), ot_entropy_src_is_fips_enabled(ess), + REG_MB4_IS_TRUE(ess, hi, ENTROPY_CONTROL, ES_ROUTE), + REG_MB4_IS_TRUE(ess, hi, ENTROPY_CONTROL, ES_TYPE), + REG_MB4_IS_FALSE(ess, hi, CONF, RNG_BIT_ENABLE), fips_capable, fips_compliant, *fips); - if (ot_fifo32_num_used(&s->final_fifo) < ES_WORD_COUNT) { - ot_entropy_src_update_filler(s); + if (ot_fifo32_num_used(&ess->final_fifo) < ES_WORD_COUNT) { + ot_entropy_src_update_filler(ess); } return 0; @@ -977,19 +970,19 @@ static bool ot_entropy_src_can_hash(const OtEntropySrcState *s) static void ot_entropy_src_perform_hash(OtEntropySrcState *s) { - uint32_t hash[OT_RANDOM_SRC_WORD_COUNT]; + uint32_t hash[OT_ENTROPY_SRC_WORD_COUNT]; int res; res = sha3_done(&s->sha3_state, (uint8_t *)hash); g_assert(res == CRYPT_OK); s->cond_word = 0; xtrace_ot_entropy_src_show_buffer(s, "sha3 md", hash, - OT_RANDOM_SRC_WORD_COUNT * + OT_ENTROPY_SRC_WORD_COUNT * sizeof(uint32_t)); ot_entropy_src_change_state(s, ENTROPY_SRC_SHA3_MSGDONE); - for (unsigned ix = 0; ix < OT_RANDOM_SRC_WORD_COUNT; ix++) { + for (unsigned ix = 0; ix < OT_ENTROPY_SRC_WORD_COUNT; ix++) { g_assert(!ot_fifo32_is_full(&s->final_fifo)); ot_fifo32_push(&s->final_fifo, hash[ix]); } @@ -1022,7 +1015,7 @@ ot_entropy_src_push_bypass_entropy(OtEntropySrcState *s, uint32_t word) trace_ot_entropy_src_push_bypass_entropy(s->ot_id, ot_fifo32_num_used( &s->final_fifo) / - OT_RANDOM_SRC_WORD_COUNT); + OT_ENTROPY_SRC_WORD_COUNT); return true; } @@ -1971,11 +1964,9 @@ static void ot_entropy_src_class_init(ObjectClass *klass, void *data) ResettableClass *rc = RESETTABLE_CLASS(klass); OtEntropySrcClass *ec = OT_ENTROPY_SRC_CLASS(klass); + ec->get_entropy = &ot_entropy_src_get_entropy; resettable_class_set_parent_phases(rc, &ot_entropy_src_reset_enter, NULL, NULL, &ec->parent_phases); - - OtRandomSrcIfClass *rdc = OT_RANDOM_SRC_IF_CLASS(klass); - rdc->get_random_values = &ot_entropy_src_get_random; } static const TypeInfo ot_entropy_src_info = { @@ -1985,11 +1976,6 @@ static const TypeInfo ot_entropy_src_info = { .instance_init = &ot_entropy_src_init, .class_size = sizeof(OtEntropySrcClass), .class_init = &ot_entropy_src_class_init, - .interfaces = - (InterfaceInfo[]){ - { TYPE_OT_RANDOM_SRC_IF }, - {}, - }, }; static void ot_entropy_src_register_types(void) diff --git a/include/hw/opentitan/ot_entropy_src.h b/include/hw/opentitan/ot_entropy_src.h index 3d981f14b64d..dc4b2ca53f26 100644 --- a/include/hw/opentitan/ot_entropy_src.h +++ b/include/hw/opentitan/ot_entropy_src.h @@ -34,4 +34,34 @@ #define TYPE_OT_ENTROPY_SRC "ot-entropy_src" OBJECT_DECLARE_TYPE(OtEntropySrcState, OtEntropySrcClass, OT_ENTROPY_SRC) +#define OT_ENTROPY_SRC_PACKET_SIZE_BITS 384u + +#define OT_ENTROPY_SRC_BYTE_COUNT (OT_ENTROPY_SRC_PACKET_SIZE_BITS / 8u) +#define OT_ENTROPY_SRC_WORD_COUNT \ + (OT_ENTROPY_SRC_BYTE_COUNT / sizeof(uint32_t)) +#define OT_ENTROPY_SRC_DWORD_COUNT \ + (OT_ENTROPY_SRC_BYTE_COUNT / sizeof(uint64_t)) + +struct OtEntropySrcClass { + SysBusDeviceClass parent_class; + ResettablePhases parent_phases; + + /* + * Fill up a buffer with random values + * + * @ess the entropy source instance + * @random the buffer to fill in with random data + * @fips on success, updated to @true if random data are FIPS-compliant + * @return 0 on success, + * >=1 if the random source is still initializing or not enough + * entropy is available to fill the output buffer; + * if >1, indicates a hint on how many ns to wait before retrying, + * -1 if the random source is not available, i.e. if the module is + * not enabled or if the selected route is not the HW one, + */ + int (*get_entropy)(OtEntropySrcState *ess, + uint64_t random[OT_ENTROPY_SRC_DWORD_COUNT], + bool *fips); +}; + #endif /* HW_OPENTITAN_OT_ENTROPY_SRC_H */ From f51139b8971233310b402a8e0c54087aa924e8f5 Mon Sep 17 00:00:00 2001 From: Emmanuel Blot Date: Wed, 29 Oct 2025 10:56:33 +0100 Subject: [PATCH 04/18] [ot] hw/opentitan: ot_entropy_src: update FSM Remove deprecated states, update state magic values Signed-off-by: Emmanuel Blot --- hw/opentitan/ot_entropy_src.c | 37 ++++++++++++----------------------- 1 file changed, 12 insertions(+), 25 deletions(-) diff --git a/hw/opentitan/ot_entropy_src.c b/hw/opentitan/ot_entropy_src.c index 58a9f5757992..37f70df54128 100644 --- a/hw/opentitan/ot_entropy_src.c +++ b/hw/opentitan/ot_entropy_src.c @@ -451,12 +451,10 @@ typedef enum { ENTROPY_SRC_CONT_HT_RUNNING, ENTROPY_SRC_FW_INSERT_START, ENTROPY_SRC_FW_INSERT_MSG, - ENTROPY_SRC_SHA3_MSGDONE, - ENTROPY_SRC_SHA3_PREP, + ENTROPY_SRC_SHA3_MSG_DONE, ENTROPY_SRC_SHA3_PROCESS, ENTROPY_SRC_SHA3_VALID, ENTROPY_SRC_SHA3_DONE, - ENTROPY_SRC_SHA3_QUIESCE, ENTROPY_SRC_ALERT_STATE, ENTROPY_SRC_ALERT_HANG, ENTROPY_SRC_ERROR, @@ -496,7 +494,6 @@ struct OtEntropySrcState { OtOTPState *otp_ctrl; }; -/* @todo: need to check the FSM code are identical on v2 and v3... */ static const uint16_t OtEDNFsmStateCode[] = { [ENTROPY_SRC_IDLE] = 0b011110101, [ENTROPY_SRC_BOOT_HT_RUNNING] = 0b111010010, @@ -510,15 +507,13 @@ static const uint16_t OtEDNFsmStateCode[] = { [ENTROPY_SRC_CONT_HT_RUNNING] = 0b110100010, [ENTROPY_SRC_FW_INSERT_START] = 0b011000011, [ENTROPY_SRC_FW_INSERT_MSG] = 0b001011001, - [ENTROPY_SRC_SHA3_MSGDONE] = 0b100001111, - [ENTROPY_SRC_SHA3_PREP] = 0b011111000, - [ENTROPY_SRC_SHA3_PROCESS] = 0b010111111, - [ENTROPY_SRC_SHA3_VALID] = 0b101110001, + [ENTROPY_SRC_SHA3_MSG_DONE] = 0b100001111, + [ENTROPY_SRC_SHA3_PROCESS] = 0b011111000, + [ENTROPY_SRC_SHA3_VALID] = 0b010111111, [ENTROPY_SRC_SHA3_DONE] = 0b110011000, - [ENTROPY_SRC_SHA3_QUIESCE] = 0b111001101, - [ENTROPY_SRC_ALERT_STATE] = 0b111111011, - [ENTROPY_SRC_ALERT_HANG] = 0b101011100, - [ENTROPY_SRC_ERROR] = 0b100111101, + [ENTROPY_SRC_ALERT_STATE] = 0b111001101, + [ENTROPY_SRC_ALERT_HANG] = 0b111111011, + [ENTROPY_SRC_ERROR] = 0b001110011, }; #define STATE_NAME_ENTRY(_st_) [ENTROPY_SRC_##_st_] = stringify(_st_) @@ -535,12 +530,10 @@ static const char *STATE_NAMES[] = { STATE_NAME_ENTRY(CONT_HT_RUNNING), STATE_NAME_ENTRY(FW_INSERT_START), STATE_NAME_ENTRY(FW_INSERT_MSG), - STATE_NAME_ENTRY(SHA3_MSGDONE), - STATE_NAME_ENTRY(SHA3_PREP), + STATE_NAME_ENTRY(SHA3_MSG_DONE), STATE_NAME_ENTRY(SHA3_PROCESS), STATE_NAME_ENTRY(SHA3_VALID), STATE_NAME_ENTRY(SHA3_DONE), - STATE_NAME_ENTRY(SHA3_QUIESCE), STATE_NAME_ENTRY(ALERT_STATE), STATE_NAME_ENTRY(ALERT_HANG), STATE_NAME_ENTRY(ERROR), @@ -583,8 +576,7 @@ static int ot_entropy_src_get_entropy( break; case ENTROPY_SRC_CONT_HT_RUNNING: case ENTROPY_SRC_CONT_HT_START: - case ENTROPY_SRC_SHA3_MSGDONE: - case ENTROPY_SRC_SHA3_PREP: + case ENTROPY_SRC_SHA3_MSG_DONE: case ENTROPY_SRC_SHA3_PROCESS: case ENTROPY_SRC_SHA3_VALID: case ENTROPY_SRC_SHA3_DONE: @@ -615,7 +607,6 @@ static int ot_entropy_src_get_entropy( return -1; case ENTROPY_SRC_FW_INSERT_START: case ENTROPY_SRC_FW_INSERT_MSG: - case ENTROPY_SRC_SHA3_QUIESCE: /* this state is never emulated */ case ENTROPY_SRC_ALERT_STATE: case ENTROPY_SRC_ALERT_HANG: case ENTROPY_SRC_ERROR: @@ -933,7 +924,6 @@ ot_entropy_src_push_entropy_to_conditioner(OtEntropySrcState *s, uint32_t word) int res; if (s->cond_word == 0) { res = sha3_384_init(&s->sha3_state); - ot_entropy_src_change_state(s, ENTROPY_SRC_SHA3_PREP); g_assert(res == CRYPT_OK); } @@ -980,7 +970,7 @@ static void ot_entropy_src_perform_hash(OtEntropySrcState *s) OT_ENTROPY_SRC_WORD_COUNT * sizeof(uint32_t)); - ot_entropy_src_change_state(s, ENTROPY_SRC_SHA3_MSGDONE); + ot_entropy_src_change_state(s, ENTROPY_SRC_SHA3_MSG_DONE); for (unsigned ix = 0; ix < OT_ENTROPY_SRC_WORD_COUNT; ix++) { g_assert(!ot_fifo32_is_full(&s->final_fifo)); @@ -1185,11 +1175,10 @@ static void ot_entropy_src_noise_refill(void *opaque) case ENTROPY_SRC_CONT_HT_RUNNING: case ENTROPY_SRC_CONT_HT_START: case ENTROPY_SRC_BOOT_PHASE_DONE: - case ENTROPY_SRC_SHA3_PREP: case ENTROPY_SRC_SHA3_VALID: case ENTROPY_SRC_SHA3_PROCESS: case ENTROPY_SRC_SHA3_DONE: - case ENTROPY_SRC_SHA3_MSGDONE: + case ENTROPY_SRC_SHA3_MSG_DONE: break; default: trace_ot_entropy_src_error(s->ot_id, "unexpected state", @@ -1210,11 +1199,10 @@ static void ot_entropy_src_scheduler(void *opaque) case ENTROPY_SRC_STARTUP_HT_START: case ENTROPY_SRC_CONT_HT_START: case ENTROPY_SRC_CONT_HT_RUNNING: - case ENTROPY_SRC_SHA3_PREP: case ENTROPY_SRC_SHA3_VALID: case ENTROPY_SRC_SHA3_PROCESS: case ENTROPY_SRC_SHA3_DONE: - case ENTROPY_SRC_SHA3_MSGDONE: + case ENTROPY_SRC_SHA3_MSG_DONE: ot_entropy_src_noise_refill(s); break; case ENTROPY_SRC_IDLE: @@ -1225,7 +1213,6 @@ static void ot_entropy_src_scheduler(void *opaque) case ENTROPY_SRC_STARTUP_FAIL1: case ENTROPY_SRC_FW_INSERT_START: case ENTROPY_SRC_FW_INSERT_MSG: - case ENTROPY_SRC_SHA3_QUIESCE: case ENTROPY_SRC_ALERT_STATE: case ENTROPY_SRC_ALERT_HANG: case ENTROPY_SRC_ERROR: From f7de31e02a228f4b317cc89972cd4d5d37db622a Mon Sep 17 00:00:00 2001 From: Emmanuel Blot Date: Thu, 23 Oct 2025 11:45:46 +0200 Subject: [PATCH 05/18] [ot] hw/opentitan: ot_csrng: replace ot_random_src_if calls with direct ot_entropy_src calls Signed-off-by: Emmanuel Blot --- hw/opentitan/ot_csrng.c | 43 +++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/hw/opentitan/ot_csrng.c b/hw/opentitan/ot_csrng.c index 2f320e8381df..1a67d614f453 100644 --- a/hw/opentitan/ot_csrng.c +++ b/hw/opentitan/ot_csrng.c @@ -37,9 +37,9 @@ #include "hw/opentitan/ot_alert.h" #include "hw/opentitan/ot_common.h" #include "hw/opentitan/ot_csrng.h" +#include "hw/opentitan/ot_entropy_src.h" #include "hw/opentitan/ot_fifo32.h" #include "hw/opentitan/ot_otp.h" -#include "hw/opentitan/ot_random_src.h" #include "hw/qdev-properties.h" #include "hw/registerfields.h" #include "hw/riscv/ibex_common.h" @@ -227,9 +227,9 @@ static const char *CMD_NAMES[] = { #define CMD_NAME(_cmd_) \ (((size_t)(_cmd_)) < ARRAY_SIZE(CMD_NAMES) ? CMD_NAMES[(_cmd_)] : "?") -static_assert(OT_CSRNG_PACKET_WORD_COUNT <= OT_RANDOM_SRC_WORD_COUNT, +static_assert(OT_CSRNG_PACKET_WORD_COUNT <= OT_ENTROPY_SRC_WORD_COUNT, "CSRNG packet cannot be larger than entropy_src packet"); -static_assert((OT_RANDOM_SRC_WORD_COUNT % OT_CSRNG_PACKET_WORD_COUNT) == 0, +static_assert((OT_ENTROPY_SRC_WORD_COUNT % OT_CSRNG_PACKET_WORD_COUNT) == 0, "CSRNG packet should be a multiple of entropy_src packet"); static_assert(OT_CSRNG_AES_BLOCK_SIZE + OT_CSRNG_AES_KEY_SIZE == OT_CSRNG_SEED_BYTE_COUNT, @@ -352,7 +352,7 @@ struct OtCSRNGState { OtCSRNGInstance *instances; OtCSRNGQueue cmd_requests; - DeviceState *random_src; + OtEntropySrcState *entropy_src; OtOTPState *otp_ctrl; }; @@ -421,8 +421,7 @@ static void ot_csrng_release_hw_app(OtCSRNGInstance *inst); static void ot_csrng_update_irqs(OtCSRNGState *s); static void ot_csrng_update_alerts(OtCSRNGState *s); -static OtCSRNDCmdResult -ot_csrng_drng_reseed(OtCSRNGInstance *inst, DeviceState *rand_dev, bool flag0); +static OtCSRNDCmdResult ot_csrng_drng_reseed(OtCSRNGInstance *inst, bool flag0); /* -------------------------------------------------------------------------- */ /* Client API */ @@ -658,8 +657,8 @@ static void ot_csrng_drng_increment(OtCSRNGDrng *drng) } } -static OtCSRNDCmdResult ot_csrng_drng_instantiate( - OtCSRNGInstance *inst, DeviceState *rand_dev, bool flag0) +static OtCSRNDCmdResult +ot_csrng_drng_instantiate(OtCSRNGInstance *inst, bool flag0) { OtCSRNGDrng *drng = &inst->drng; if (drng->instantiated) { @@ -680,7 +679,7 @@ static OtCSRNDCmdResult ot_csrng_drng_instantiate( memcpy(drng->key, key, OT_CSRNG_AES_KEY_SIZE); drng->instantiated = true; - res = ot_csrng_drng_reseed(inst, rand_dev, flag0); + res = ot_csrng_drng_reseed(inst, flag0); if (res) { drng->instantiated = false; return res; @@ -764,8 +763,7 @@ static void ot_csrng_drng_update(OtCSRNGInstance *inst) OT_CSRNG_AES_BLOCK_SIZE); } -static OtCSRNDCmdResult -ot_csrng_drng_reseed(OtCSRNGInstance *inst, DeviceState *rand_dev, bool flag0) +static OtCSRNDCmdResult ot_csrng_drng_reseed(OtCSRNGInstance *inst, bool flag0) { OtCSRNGState *s = inst->parent; OtCSRNGDrng *drng = &inst->drng; @@ -775,19 +773,19 @@ ot_csrng_drng_reseed(OtCSRNGInstance *inst, DeviceState *rand_dev, bool flag0) drng->seeded = false; if (!flag0) { - uint64_t buffer[OT_RANDOM_SRC_DWORD_COUNT]; + uint64_t buffer[OT_ENTROPY_SRC_DWORD_COUNT]; memset(buffer, 0, sizeof(buffer)); unsigned len = drng->material_len * sizeof(uint32_t); memcpy(buffer, drng->material, MIN(len, sizeof(buffer))); - uint64_t entropy[OT_RANDOM_SRC_DWORD_COUNT]; + uint64_t entropy[OT_ENTROPY_SRC_DWORD_COUNT]; int res; bool fips; trace_ot_csrng_request_entropy(slot); - OtRandomSrcIfClass *cls = OT_RANDOM_SRC_IF_GET_CLASS(rand_dev); - OtRandomSrcIf *randif = OT_RANDOM_SRC_IF(rand_dev); - res = cls->get_random_values(randif, entropy, &fips); + OtEntropySrcState *ess = inst->parent->entropy_src; + OtEntropySrcClass *esc = OT_ENTROPY_SRC_GET_CLASS(ess); + res = esc->get_entropy(ess, entropy, &fips); if (res < 0) { s->entropy_delay = 0; @@ -802,7 +800,7 @@ ot_csrng_drng_reseed(OtCSRNGInstance *inst, DeviceState *rand_dev, bool flag0) } /* always perform XOR which is a no-op if material_len is zero */ - for (unsigned ix = 0; ix < OT_RANDOM_SRC_DWORD_COUNT; ix++) { + for (unsigned ix = 0; ix < OT_ENTROPY_SRC_DWORD_COUNT; ix++) { buffer[ix] ^= entropy[ix]; } memcpy(drng->material, buffer, sizeof(entropy)); @@ -1136,7 +1134,7 @@ ot_csrng_handle_instantiate(OtCSRNGState *s, unsigned slot) int res; - res = ot_csrng_drng_instantiate(inst, s->random_src, flag0); + res = ot_csrng_drng_instantiate(inst, flag0); if ((res == CSRNG_CMD_OK) && !flag0) { /* if flag0 is set, entropy source is not used for reseeding */ s->regs[R_INTR_STATE] |= INTR_CS_ENTROPY_REQ_MASK; @@ -1237,7 +1235,7 @@ static OtCSRNDCmdResult ot_csrng_handle_reseed(OtCSRNGState *s, unsigned slot) } int res; - res = ot_csrng_drng_reseed(inst, s->random_src, flag0); + res = ot_csrng_drng_reseed(inst, flag0); if ((res == CSRNG_CMD_OK) && !flag0) { /* if flag0 is set, entropy source is not used for reseeding */ s->regs[R_INTR_STATE] |= INTR_CS_ENTROPY_REQ_MASK; @@ -1944,8 +1942,8 @@ static void ot_csrng_regs_write(void *opaque, hwaddr addr, uint64_t val64, }; static Property ot_csrng_properties[] = { - DEFINE_PROP_LINK("random_src", OtCSRNGState, random_src, TYPE_DEVICE, - DeviceState *), + DEFINE_PROP_LINK("entropy-src", OtCSRNGState, entropy_src, + TYPE_OT_ENTROPY_SRC, OtEntropySrcState *), DEFINE_PROP_LINK("otp_ctrl", OtCSRNGState, otp_ctrl, TYPE_OT_OTP, OtOTPState *), DEFINE_PROP_END_OF_LIST(), @@ -2019,8 +2017,7 @@ static void ot_csrng_realize(DeviceState *dev, Error **errp) OtCSRNGState *s = OT_CSRNG(dev); (void)errp; - g_assert(s->random_src); - OBJECT_CHECK(OtRandomSrcIf, s->random_src, TYPE_OT_RANDOM_SRC_IF); + g_assert(s->entropy_src); g_assert(s->otp_ctrl); } From d0b5b17806fac20cc7b154937993959da8714526 Mon Sep 17 00:00:00 2001 From: Emmanuel Blot Date: Thu, 23 Oct 2025 11:10:35 +0200 Subject: [PATCH 06/18] [ot] hw/opentitan: ot_noise_src: define a new interface for noise provider Signed-off-by: Emmanuel Blot --- hw/opentitan/Kconfig | 3 ++ hw/opentitan/meson.build | 1 + hw/riscv/ot_noise_src.c | 42 ++++++++++++++++++++ include/hw/opentitan/ot_noise_src.h | 61 +++++++++++++++++++++++++++++ 4 files changed, 107 insertions(+) create mode 100644 hw/riscv/ot_noise_src.c create mode 100644 include/hw/opentitan/ot_noise_src.h diff --git a/hw/opentitan/Kconfig b/hw/opentitan/Kconfig index f8b26fc800b5..dbd2b94cd26c 100644 --- a/hw/opentitan/Kconfig +++ b/hw/opentitan/Kconfig @@ -107,6 +107,9 @@ config OT_MBX select OT_COMMON bool +config OT_NOISE_SRC + bool + config OT_OTBN select OT_KEY_SINK select OT_BIGNUMBER diff --git a/hw/opentitan/meson.build b/hw/opentitan/meson.build index 75945c30c6a6..e564a20309e1 100644 --- a/hw/opentitan/meson.build +++ b/hw/opentitan/meson.build @@ -32,6 +32,7 @@ system_ss.add(when: 'CONFIG_OT_KEYMGR_DPE', if_true: files('ot_keymgr_dpe.c')) system_ss.add(when: 'CONFIG_OT_KMAC', if_true: [files('ot_kmac.c'), libtomcrypt_dep]) system_ss.add(when: 'CONFIG_OT_LC_CTRL', if_true: files('ot_lc_ctrl.c')) system_ss.add(when: 'CONFIG_OT_MBX', if_true: files('ot_mbx.c')) +system_ss.add(when: 'CONFIG_OT_NOISE_SRC', if_true: files('ot_noise_src.c')) system_ss.add(when: 'CONFIG_OT_OTBN', if_true: files('ot_otbn.c')) system_ss.add(when: 'CONFIG_OT_OTP', if_true: files('ot_otp.c')) system_ss.add(when: 'CONFIG_OT_OTP_BE_IF', if_true: files('ot_otp_be_if.c')) diff --git a/hw/riscv/ot_noise_src.c b/hw/riscv/ot_noise_src.c new file mode 100644 index 000000000000..6564a3a56071 --- /dev/null +++ b/hw/riscv/ot_noise_src.c @@ -0,0 +1,42 @@ +/* + * QEMU OpenTitan Noise Source interface + * + * Copyright (c) 2025 Rivos, Inc. + * + * Author(s): + * Emmanuel Blot + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "hw/opentitan/ot_noise_src.h" + +static const TypeInfo ot_noise_src_info = { + .name = TYPE_OT_NOISE_SRC_IF, + .parent = TYPE_INTERFACE, + .class_size = sizeof(OtNoiseSrcIfClass), +}; + +static void ot_noise_src_register_types(void) +{ + type_register_static(&ot_noise_src_info); +} + +type_init(ot_noise_src_register_types); diff --git a/include/hw/opentitan/ot_noise_src.h b/include/hw/opentitan/ot_noise_src.h new file mode 100644 index 000000000000..c88b869110d6 --- /dev/null +++ b/include/hw/opentitan/ot_noise_src.h @@ -0,0 +1,61 @@ +/* + * QEMU OpenTitan Noise Source interface + * + * Copyright (c) 2025 Rivos, Inc. + * Copyright (c) 2025 lowRISC contributors. + * + * Author(s): + * Emmanuel Blot + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef HW_OPENTITAN_OT_NOISE_SRC_H +#define HW_OPENTITAN_OT_NOISE_SRC_H + +#include "qom/object.h" + +#define TYPE_OT_NOISE_SRC_IF "ot-noise_src_if" +typedef struct OtNoiseSrcIfClass OtNoiseSrcIfClass; +DECLARE_CLASS_CHECKERS(OtNoiseSrcIfClass, OT_NOISE_SRC_IF, TYPE_OT_NOISE_SRC_IF) +#define OT_NOISE_SRC_IF(_obj_) \ + INTERFACE_CHECK(OtNoiseSrcIf, (_obj_), TYPE_OT_NOISE_SRC_IF) + +typedef struct OtNoiseSrcIf OtNoiseSrcIf; + +struct OtNoiseSrcIfClass { + InterfaceClass parent_class; + + /* + * Report the fill rate of this source. + * + * @return the fill rate, in bytes per second + */ + unsigned (*get_fill_rate)(OtNoiseSrcIf *dev); + + /* + * Fill up a buffer with noise data + * + * @buffer destination buffer + * @length number of bytes to fill in + */ + void (*get_noise)(OtNoiseSrcIf *dev, uint8_t *buffer, size_t length); +}; + +#endif /* HW_OPENTITAN_OT_NOISE_SRC_H */ From 081b593b6831a482fcadf237d1ea80ed0387fd9f Mon Sep 17 00:00:00 2001 From: Emmanuel Blot Date: Thu, 23 Oct 2025 11:10:39 +0200 Subject: [PATCH 07/18] [ot] hw/opentitan: ot_entropy_src: use the new noise provider interface replace the direct ot_ast_eg calls with the new abstract interface Signed-off-by: Emmanuel Blot --- hw/opentitan/Kconfig | 1 + hw/opentitan/ot_entropy_src.c | 53 +++++++++++++++++++-------- include/hw/opentitan/ot_entropy_src.h | 8 ++-- 3 files changed, 41 insertions(+), 21 deletions(-) diff --git a/hw/opentitan/Kconfig b/hw/opentitan/Kconfig index dbd2b94cd26c..f89d8155cd4f 100644 --- a/hw/opentitan/Kconfig +++ b/hw/opentitan/Kconfig @@ -53,6 +53,7 @@ config OT_EDN bool config OT_ENTROPY_SRC + select OT_NOISE_SRC bool config OT_FLASH diff --git a/hw/opentitan/ot_entropy_src.c b/hw/opentitan/ot_entropy_src.c index 37f70df54128..5a4f571922c5 100644 --- a/hw/opentitan/ot_entropy_src.c +++ b/hw/opentitan/ot_entropy_src.c @@ -39,10 +39,10 @@ #include "qemu/timer.h" #include "qemu/typedefs.h" #include "hw/opentitan/ot_alert.h" -#include "hw/opentitan/ot_ast_eg.h" #include "hw/opentitan/ot_common.h" #include "hw/opentitan/ot_entropy_src.h" #include "hw/opentitan/ot_fifo32.h" +#include "hw/opentitan/ot_noise_src.h" #include "hw/opentitan/ot_otp.h" #include "hw/qdev-properties.h" #include "hw/registerfields.h" @@ -407,11 +407,8 @@ static const char *REG_HI_NAMES[REGS_HI_COUNT] = { * feed rate to ~0.7 ms max. 128-bit packet can be divided down to 32-bit * FIFO packets. They are assembled into either 384-bit or 2048-bit packets. */ -#define ES_FILL_BITS 128u -#define ES_FINAL_FIFO_DEPTH 4u -#define ES_FILL_RATE_NS \ - ((NANOSECONDS_PER_SECOND * ES_FILL_BITS) / \ - ((uint64_t)OT_AST_EG_RANDOM_4BIT_RATE * 4u)) +#define ES_FILL_BITS 128u +#define ES_FINAL_FIFO_DEPTH 4u #define OT_ENTROPY_SRC_FILL_WORD_COUNT (ES_FILL_BITS / (8u * sizeof(uint32_t))) #define ES_WORD_COUNT (OT_ENTROPY_SRC_WORD_COUNT) #define ES_SWREAD_FIFO_WORD_COUNT ES_WORD_COUNT @@ -483,6 +480,7 @@ struct OtEntropySrcState { OtFifo32 final_fifo; /* output FIFO */ hash_state sha3_state; /* libtomcrypt hash state */ OtEntropySrcFsmState state; + uint64_t noise_fill_pace_ns; unsigned cond_word; /* count of words processed with SHA3 till hash */ unsigned noise_count; /* count of consumed noise words since enabled */ unsigned packet_count; /* count of output packets since enabled */ @@ -490,7 +488,7 @@ struct OtEntropySrcState { char *ot_id; unsigned version; /* emulated version */ - OtASTEgState *ast; + DeviceState *noise_src; OtOTPState *otp_ctrl; }; @@ -885,7 +883,7 @@ static void ot_entropy_src_update_filler(OtEntropySrcState *s) if (!timer_pending(s->scheduler)) { trace_ot_entropy_src_info(s->ot_id, "reschedule"); uint64_t now = qemu_clock_get_ns(OT_VIRTUAL_CLOCK); - timer_mod(s->scheduler, (int64_t)(now + (uint64_t)ES_FILL_RATE_NS)); + timer_mod(s->scheduler, (int64_t)(now + s->noise_fill_pace_ns)); } } } @@ -1131,7 +1129,9 @@ static bool ot_entropy_src_fill_noise(OtEntropySrcState *s) uint32_t buffer[OT_ENTROPY_SRC_FILL_WORD_COUNT]; /* synchronous read */ - ot_ast_eg_getrandom(buffer, sizeof(buffer)); + OtNoiseSrcIfClass *nsc = OT_NOISE_SRC_IF_GET_CLASS(s->noise_src); + OtNoiseSrcIf *nsi = OT_NOISE_SRC_IF(s->noise_src); + nsc->get_noise(nsi, (uint8_t *)buffer, sizeof(buffer)); /* push the whole entropy buffer into the input FIFO */ unsigned pos = 0; @@ -1801,9 +1801,8 @@ static const MemoryRegionOps ot_entropy_src_hi_ops = { static Property ot_entropy_src_properties[] = { DEFINE_PROP_STRING(OT_COMMON_DEV_ID, OtEntropySrcState, ot_id), DEFINE_PROP_UINT32("version", OtEntropySrcState, version, 0), - - DEFINE_PROP_LINK("ast", OtEntropySrcState, ast, TYPE_OT_AST_EG, - OtASTEgState *), + DEFINE_PROP_LINK("noise-src", OtEntropySrcState, noise_src, TYPE_DEVICE, + DeviceState *), DEFINE_PROP_LINK("otp_ctrl", OtEntropySrcState, otp_ctrl, TYPE_OT_OTP, OtOTPState *), DEFINE_PROP_END_OF_LIST(), @@ -1814,7 +1813,7 @@ static void ot_entropy_src_reset_enter(Object *obj, ResetType type) OtEntropySrcClass *c = OT_ENTROPY_SRC_GET_CLASS(obj); OtEntropySrcState *s = OT_ENTROPY_SRC(obj); - trace_ot_entropy_src_reset(s->ot_id); + trace_ot_entropy_src_reset(s->ot_id, "enter"); if (c->parent_phases.enter) { c->parent_phases.enter(obj, type); @@ -1879,6 +1878,24 @@ static void ot_entropy_src_reset_enter(Object *obj, ResetType type) ot_entropy_src_change_state(s, ENTROPY_SRC_IDLE); } +static void ot_entropy_src_reset_exit(Object *obj, ResetType type) +{ + OtEntropySrcClass *c = OT_ENTROPY_SRC_GET_CLASS(obj); + OtEntropySrcState *s = OT_ENTROPY_SRC(obj); + + trace_ot_entropy_src_reset(s->ot_id, "exit"); + + if (c->parent_phases.enter) { + c->parent_phases.enter(obj, type); + } + + OtNoiseSrcIfClass *nsc = OT_NOISE_SRC_IF_GET_CLASS(s->noise_src); + OtNoiseSrcIf *nsi = OT_NOISE_SRC_IF(s->noise_src); + uint64_t noise_file_rate = nsc->get_fill_rate(nsi); + s->noise_fill_pace_ns = + (NANOSECONDS_PER_SECOND * ES_FILL_BITS) / (noise_file_rate * 8ull); +} + static void ot_entropy_src_realize(DeviceState *dev, Error **errp) { (void)errp; @@ -1887,8 +1904,10 @@ static void ot_entropy_src_realize(DeviceState *dev, Error **errp) /* emulated version should be specified */ g_assert(s->version > 0); - g_assert(s->ast); + g_assert(s->noise_src); g_assert(s->otp_ctrl); + + (void)OBJECT_CHECK(OtNoiseSrcIf, s->noise_src, TYPE_OT_NOISE_SRC_IF); } static void ot_entropy_src_init(Object *obj) @@ -1949,11 +1968,13 @@ static void ot_entropy_src_class_init(ObjectClass *klass, void *data) device_class_set_props(dc, ot_entropy_src_properties); set_bit(DEVICE_CATEGORY_MISC, dc->categories); - ResettableClass *rc = RESETTABLE_CLASS(klass); OtEntropySrcClass *ec = OT_ENTROPY_SRC_CLASS(klass); ec->get_entropy = &ot_entropy_src_get_entropy; + + ResettableClass *rc = RESETTABLE_CLASS(klass); resettable_class_set_parent_phases(rc, &ot_entropy_src_reset_enter, NULL, - NULL, &ec->parent_phases); + &ot_entropy_src_reset_exit, + &ec->parent_phases); } static const TypeInfo ot_entropy_src_info = { diff --git a/include/hw/opentitan/ot_entropy_src.h b/include/hw/opentitan/ot_entropy_src.h index dc4b2ca53f26..85971db981c1 100644 --- a/include/hw/opentitan/ot_entropy_src.h +++ b/include/hw/opentitan/ot_entropy_src.h @@ -36,9 +36,8 @@ OBJECT_DECLARE_TYPE(OtEntropySrcState, OtEntropySrcClass, OT_ENTROPY_SRC) #define OT_ENTROPY_SRC_PACKET_SIZE_BITS 384u -#define OT_ENTROPY_SRC_BYTE_COUNT (OT_ENTROPY_SRC_PACKET_SIZE_BITS / 8u) -#define OT_ENTROPY_SRC_WORD_COUNT \ - (OT_ENTROPY_SRC_BYTE_COUNT / sizeof(uint32_t)) +#define OT_ENTROPY_SRC_BYTE_COUNT (OT_ENTROPY_SRC_PACKET_SIZE_BITS / 8u) +#define OT_ENTROPY_SRC_WORD_COUNT (OT_ENTROPY_SRC_BYTE_COUNT / sizeof(uint32_t)) #define OT_ENTROPY_SRC_DWORD_COUNT \ (OT_ENTROPY_SRC_BYTE_COUNT / sizeof(uint64_t)) @@ -60,8 +59,7 @@ struct OtEntropySrcClass { * not enabled or if the selected route is not the HW one, */ int (*get_entropy)(OtEntropySrcState *ess, - uint64_t random[OT_ENTROPY_SRC_DWORD_COUNT], - bool *fips); + uint64_t random[OT_ENTROPY_SRC_DWORD_COUNT], bool *fips); }; #endif /* HW_OPENTITAN_OT_ENTROPY_SRC_H */ From 88ed98e3242edb0ee420f42d2f039e075dffd875 Mon Sep 17 00:00:00 2001 From: Emmanuel Blot Date: Thu, 23 Oct 2025 11:09:58 +0200 Subject: [PATCH 08/18] [ot] hw/opentitan: ot_ast_eg: implement the noise provider interface Signed-off-by: Emmanuel Blot --- hw/opentitan/Kconfig | 1 + hw/opentitan/ot_ast_eg.c | 33 ++++++++++++++++++-------- hw/{riscv => opentitan}/ot_noise_src.c | 0 hw/opentitan/trace-events | 2 +- include/hw/opentitan/ot_ast_eg.h | 4 ---- 5 files changed, 25 insertions(+), 15 deletions(-) rename hw/{riscv => opentitan}/ot_noise_src.c (100%) diff --git a/hw/opentitan/Kconfig b/hw/opentitan/Kconfig index f89d8155cd4f..3e349512a4b3 100644 --- a/hw/opentitan/Kconfig +++ b/hw/opentitan/Kconfig @@ -23,6 +23,7 @@ config OT_AST_DJ config OT_AST_EG select IBEX_CLOCK_SRC select OT_CLOCK_CTRL + select OT_NOISE_SRC bool config OT_CLKMGR diff --git a/hw/opentitan/ot_ast_eg.c b/hw/opentitan/ot_ast_eg.c index 08d2b1102848..ecbf99ce941f 100644 --- a/hw/opentitan/ot_ast_eg.c +++ b/hw/opentitan/ot_ast_eg.c @@ -36,6 +36,7 @@ #include "hw/opentitan/ot_ast_eg.h" #include "hw/opentitan/ot_clock_ctrl.h" #include "hw/opentitan/ot_common.h" +#include "hw/opentitan/ot_noise_src.h" #include "hw/qdev-properties.h" #include "hw/registerfields.h" #include "hw/riscv/ibex_clock_src.h" @@ -132,6 +133,8 @@ static const char REGB_NAMES[REGSB_COUNT][6U] = { }; #undef REG_NAME_ENTRY +#define OT_AST_EG_NOISE_4BIT_RATE 50000u /* 50 kHz */ + typedef struct { char *name; unsigned frequency; @@ -161,16 +164,6 @@ struct OtASTEgClass { ResettablePhases parent_phases; }; -/* -------------------------------------------------------------------------- */ -/* Public API */ -/* -------------------------------------------------------------------------- */ - -void ot_ast_eg_getrandom(void *buf, size_t len) -{ - qemu_guest_getrandom_nofail(buf, len); -} - - static const char *CFGSEP = ","; static gint ot_ast_eg_match_clock_by_name(gconstpointer a, gconstpointer b) @@ -260,6 +253,21 @@ static void ot_ast_eg_clock_ext_freq_select(OtClockCtrlIf *dev, bool enable) qemu_log_mask(LOG_UNIMP, "%s: not implemented: %u\n", __func__, enable); } +static unsigned ot_ast_eg_get_fill_rate(OtNoiseSrcIf *dev) +{ + (void)dev; + + return OT_AST_EG_NOISE_4BIT_RATE / 2u; /* 4 bits to byte */ +} + +static void ot_ast_eg_get_noise(OtNoiseSrcIf *dev, uint8_t *buffer, + size_t length) +{ + (void)dev; + + qemu_guest_getrandom_nofail((void *)buffer, length); +} + static void ot_ast_eg_parse_clocks(OtASTEgState *s, Error **errp) { if (!s->cfg_topclocks) { @@ -580,6 +588,10 @@ static void ot_ast_eg_class_init(ObjectClass *klass, void *data) OtClockCtrlIfClass *cc = OT_CLOCK_CTRL_IF_CLASS(klass); cc->clock_enable = &ot_ast_eg_clock_enable; cc->clock_ext_freq_select = &ot_ast_eg_clock_ext_freq_select; + + OtNoiseSrcIfClass *nc = OT_NOISE_SRC_IF_CLASS(klass); + nc->get_fill_rate = &ot_ast_eg_get_fill_rate; + nc->get_noise = &ot_ast_eg_get_noise; } static const TypeInfo ot_ast_eg_info = { @@ -593,6 +605,7 @@ static const TypeInfo ot_ast_eg_info = { (InterfaceInfo[]){ { TYPE_IBEX_CLOCK_SRC_IF }, { TYPE_OT_CLOCK_CTRL_IF }, + { TYPE_OT_NOISE_SRC_IF }, {}, }, }; diff --git a/hw/riscv/ot_noise_src.c b/hw/opentitan/ot_noise_src.c similarity index 100% rename from hw/riscv/ot_noise_src.c rename to hw/opentitan/ot_noise_src.c diff --git a/hw/opentitan/trace-events b/hw/opentitan/trace-events index b235bd00660c..c3764ccebda1 100644 --- a/hw/opentitan/trace-events +++ b/hw/opentitan/trace-events @@ -191,7 +191,7 @@ ot_entropy_src_io_write(const char *id, uint32_t addr, const char * regname, uin ot_entropy_src_no_entropy(const char *id, unsigned count) "%s: only %u words available" ot_entropy_src_obs_fifo(const char *id, unsigned level, unsigned thold) "%s: level %u, threshold %u" ot_entropy_src_push_bypass_entropy(const char *id, unsigned slot) "%s: final FIFO depth: %u" -ot_entropy_src_reset(const char *id, void) "%s: " +ot_entropy_src_reset(const char *id, const char *phase) "%s: %s" ot_entropy_src_show_buffer(const char *id, const char *func, int line, const char *msg, const char *hexstr) "%s: %s:%u %s: %s" ot_entropy_src_update_filler(const char *id, bool iok, bool ook, bool pok, bool all) "%s: in %u, out %u, proc %u -> %u" diff --git a/include/hw/opentitan/ot_ast_eg.h b/include/hw/opentitan/ot_ast_eg.h index 04e297a60bd7..fc55015c84f8 100644 --- a/include/hw/opentitan/ot_ast_eg.h +++ b/include/hw/opentitan/ot_ast_eg.h @@ -33,8 +33,4 @@ #define TYPE_OT_AST_EG "ot-ast-eg" OBJECT_DECLARE_TYPE(OtASTEgState, OtASTEgClass, OT_AST_EG) -#define OT_AST_EG_RANDOM_4BIT_RATE 50000u /* 50 kHz */ - -void ot_ast_eg_getrandom(void *buf, size_t len); - #endif /* HW_OPENTITAN_OT_AST_EG_H */ From 166eab0cfbae2c37f0c22a36c7601e2b37e3c178 Mon Sep 17 00:00:00 2001 From: Emmanuel Blot Date: Thu, 23 Oct 2025 11:56:22 +0200 Subject: [PATCH 09/18] [ot] hw/opentitan: ot_ast_dj: remove ot_random_src interface implementation Signed-off-by: Emmanuel Blot --- hw/opentitan/Kconfig | 1 - hw/opentitan/ot_ast_dj.c | 72 ---------------------------------------- 2 files changed, 73 deletions(-) diff --git a/hw/opentitan/Kconfig b/hw/opentitan/Kconfig index 3e349512a4b3..bda1aaf623c7 100644 --- a/hw/opentitan/Kconfig +++ b/hw/opentitan/Kconfig @@ -16,7 +16,6 @@ config OT_AON_TIMER config OT_AST_DJ select IBEX_CLOCK_SRC - select OT_RANDOM_SRC select OT_CLOCK_CTRL bool diff --git a/hw/opentitan/ot_ast_dj.c b/hw/opentitan/ot_ast_dj.c index 2a0b97fd62ca..c6c69fd6383d 100644 --- a/hw/opentitan/ot_ast_dj.c +++ b/hw/opentitan/ot_ast_dj.c @@ -37,7 +37,6 @@ #include "hw/opentitan/ot_ast_dj.h" #include "hw/opentitan/ot_clock_ctrl.h" #include "hw/opentitan/ot_common.h" -#include "hw/opentitan/ot_random_src.h" #include "hw/qdev-properties.h" #include "hw/registerfields.h" #include "hw/riscv/ibex_clock_src.h" @@ -134,12 +133,6 @@ static const char REGB_NAMES[REGSB_COUNT][6U] = { }; #undef REG_NAME_ENTRY -typedef struct { - QEMUTimer *timer; - uint64_t *buffer; - bool avail; -} OtASTDjRandom; - typedef struct { char *name; unsigned frequency; @@ -154,7 +147,6 @@ struct OtASTDjState { SysBusDevice parent_obj; MemoryRegion mmio; - OtASTDjRandom random; GList *clocks; /* OtASTDjClock */ @@ -170,56 +162,10 @@ struct OtASTDjClass { ResettablePhases parent_phases; }; -#define OT_AST_DJ_RANDOM_FILL_RATE_NS 1000000ull /* arbitrary: 1 ms */ - /* -------------------------------------------------------------------------- */ /* Private implementation */ /* -------------------------------------------------------------------------- */ -static int ot_ast_dj_get_random( - OtRandomSrcIf *dev, uint64_t random[OT_RANDOM_SRC_DWORD_COUNT], bool *fips) -{ - OtASTDjState *s = OT_AST_DJ(dev); - OtASTDjRandom *rnd = &s->random; - - if (!rnd->avail) { - /* not ready */ - trace_ot_ast_no_entropy(0); - int wait_ns; - if (timer_pending(s->random.timer)) { - wait_ns = 1; - } else { - /* computed delay fits into a 31-bit value */ - wait_ns = (int)(timer_expire_time_ns(s->random.timer) - - qemu_clock_get_ns(OT_VIRTUAL_CLOCK)); - } - return wait_ns; - } - - memcpy(random, rnd->buffer, OT_RANDOM_SRC_DWORD_COUNT * sizeof(uint64_t)); - rnd->avail = false; - - /* note: fips compliancy is only simulated here for now */ - *fips = true; - - uint64_t now = qemu_clock_get_ns(OT_VIRTUAL_CLOCK); - timer_mod(rnd->timer, (int64_t)(now + OT_AST_DJ_RANDOM_FILL_RATE_NS)); - - return 0; -} - -static void ot_ast_dj_random_scheduler(void *opaque) -{ - OtASTDjState *s = opaque; - OtASTDjRandom *rnd = &s->random; - - qemu_guest_getrandom_nofail(rnd->buffer, - OT_RANDOM_SRC_DWORD_COUNT * sizeof(uint64_t)); - - rnd->avail = true; -} - - static const char *CFGSEP = ","; static gint ot_ast_dj_match_clock_by_name(gconstpointer a, gconstpointer b) @@ -525,16 +471,11 @@ static void ot_ast_dj_reset_enter(Object *obj, ResetType type) { OtASTDjClass *c = OT_AST_DJ_GET_CLASS(obj); OtASTDjState *s = OT_AST_DJ(obj); - OtASTDjRandom *rnd = &s->random; if (c->parent_phases.enter) { c->parent_phases.enter(obj, type); } - timer_del(rnd->timer); - memset(rnd->buffer, 0, OT_RANDOM_SRC_DWORD_COUNT * sizeof(uint64_t)); - rnd->avail = false; - memset(s->regsa, 0, REGSA_SIZE); memset(s->regsb, 0, REGSB_SIZE); @@ -584,15 +525,11 @@ static void ot_ast_dj_reset_exit(Object *obj, ResetType type) { OtASTDjClass *c = OT_AST_DJ_GET_CLASS(obj); OtASTDjState *s = OT_AST_DJ(obj); - OtASTDjRandom *rnd = &s->random; if (c->parent_phases.exit) { c->parent_phases.exit(obj, type); } - uint64_t now = qemu_clock_get_ns(OT_VIRTUAL_CLOCK); - timer_mod(rnd->timer, (int64_t)(now + OT_AST_DJ_RANDOM_FILL_RATE_NS)); - g_list_foreach(s->clocks, ot_ast_dj_update_clock, s); } @@ -614,11 +551,6 @@ static void ot_ast_dj_init(Object *obj) s->regsa = g_new0(uint32_t, REGSA_COUNT); s->regsb = g_new0(uint32_t, REGSB_COUNT); - - OtASTDjRandom *rnd = &s->random; - - rnd->timer = timer_new_ns(OT_VIRTUAL_CLOCK, &ot_ast_dj_random_scheduler, s); - rnd->buffer = g_new0(uint64_t, OT_RANDOM_SRC_DWORD_COUNT); } static void ot_ast_dj_class_init(ObjectClass *klass, void *data) @@ -636,9 +568,6 @@ static void ot_ast_dj_class_init(ObjectClass *klass, void *data) &ot_ast_dj_reset_exit, &ac->parent_phases); - OtRandomSrcIfClass *rdc = OT_RANDOM_SRC_IF_CLASS(klass); - rdc->get_random_values = &ot_ast_dj_get_random; - IbexClockSrcIfClass *ic = IBEX_CLOCK_SRC_IF_CLASS(klass); ic->get_clock_source = &ot_ast_dj_get_clock_source; @@ -656,7 +585,6 @@ static const TypeInfo ot_ast_dj_info = { .class_init = &ot_ast_dj_class_init, .interfaces = (InterfaceInfo[]){ - { TYPE_OT_RANDOM_SRC_IF }, { TYPE_IBEX_CLOCK_SRC_IF }, { TYPE_OT_CLOCK_CTRL_IF }, {}, From 98e0dc510676c81beaaf2c2cfa1a5bc4ae6c9dc5 Mon Sep 17 00:00:00 2001 From: Emmanuel Blot Date: Thu, 23 Oct 2025 12:18:54 +0200 Subject: [PATCH 10/18] [ot] hw/opentitan: ot_ast_dj: implement the noise provider interface Signed-off-by: Emmanuel Blot --- hw/opentitan/Kconfig | 1 + hw/opentitan/ot_ast_dj.c | 31 +++++++++++++++++++++++++++---- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/hw/opentitan/Kconfig b/hw/opentitan/Kconfig index bda1aaf623c7..9b37047f4f0f 100644 --- a/hw/opentitan/Kconfig +++ b/hw/opentitan/Kconfig @@ -17,6 +17,7 @@ config OT_AON_TIMER config OT_AST_DJ select IBEX_CLOCK_SRC select OT_CLOCK_CTRL + select OT_NOISE_SRC bool config OT_AST_EG diff --git a/hw/opentitan/ot_ast_dj.c b/hw/opentitan/ot_ast_dj.c index c6c69fd6383d..39a62d6752dc 100644 --- a/hw/opentitan/ot_ast_dj.c +++ b/hw/opentitan/ot_ast_dj.c @@ -37,6 +37,7 @@ #include "hw/opentitan/ot_ast_dj.h" #include "hw/opentitan/ot_clock_ctrl.h" #include "hw/opentitan/ot_common.h" +#include "hw/opentitan/ot_noise_src.h" #include "hw/qdev-properties.h" #include "hw/registerfields.h" #include "hw/riscv/ibex_clock_src.h" @@ -133,6 +134,9 @@ static const char REGB_NAMES[REGSB_COUNT][6U] = { }; #undef REG_NAME_ENTRY +/* @todo check with HW what is the best default value */ +#define OT_AST_DJ_NOISE_BITRATE_DEFAULT 1000000u /* 1 MHz */ + typedef struct { char *name; unsigned frequency; @@ -155,6 +159,7 @@ struct OtASTDjState { char *cfg_topclocks; char *cfg_aonclocks; + uint32_t noise_bitrate; }; struct OtASTDjClass { @@ -162,10 +167,6 @@ struct OtASTDjClass { ResettablePhases parent_phases; }; -/* -------------------------------------------------------------------------- */ -/* Private implementation */ -/* -------------------------------------------------------------------------- */ - static const char *CFGSEP = ","; static gint ot_ast_dj_match_clock_by_name(gconstpointer a, gconstpointer b) @@ -255,6 +256,21 @@ static void ot_ast_dj_clock_ext_freq_select(OtClockCtrlIf *dev, bool enable) qemu_log_mask(LOG_UNIMP, "%s: not implemented: %u\n", __func__, enable); } +static unsigned ot_ast_dj_get_fill_rate(OtNoiseSrcIf *dev) +{ + OtASTDjState *s = OT_AST_DJ(dev); + + return s->noise_bitrate / 8u; /* bit to byte */ +} + +static void ot_ast_dj_get_noise(OtNoiseSrcIf *dev, uint8_t *buffer, + size_t length) +{ + (void)dev; + + qemu_guest_getrandom_nofail((void *)buffer, length); +} + static void ot_ast_dj_parse_clocks(OtASTDjState *s, Error **errp) { if (!s->cfg_topclocks) { @@ -456,6 +472,8 @@ static void ot_ast_dj_regs_write(void *opaque, hwaddr addr, uint64_t val64, static Property ot_ast_dj_properties[] = { DEFINE_PROP_STRING("topclocks", OtASTDjState, cfg_topclocks), DEFINE_PROP_STRING("aonclocks", OtASTDjState, cfg_aonclocks), + DEFINE_PROP_UINT32("noise-bitrate", OtASTDjState, noise_bitrate, + OT_AST_DJ_NOISE_BITRATE_DEFAULT), DEFINE_PROP_END_OF_LIST(), }; @@ -574,6 +592,10 @@ static void ot_ast_dj_class_init(ObjectClass *klass, void *data) OtClockCtrlIfClass *cc = OT_CLOCK_CTRL_IF_CLASS(klass); cc->clock_enable = &ot_ast_dj_clock_enable; cc->clock_ext_freq_select = &ot_ast_dj_clock_ext_freq_select; + + OtNoiseSrcIfClass *nc = OT_NOISE_SRC_IF_CLASS(klass); + nc->get_fill_rate = &ot_ast_dj_get_fill_rate; + nc->get_noise = &ot_ast_dj_get_noise; } static const TypeInfo ot_ast_dj_info = { @@ -587,6 +609,7 @@ static const TypeInfo ot_ast_dj_info = { (InterfaceInfo[]){ { TYPE_IBEX_CLOCK_SRC_IF }, { TYPE_OT_CLOCK_CTRL_IF }, + { TYPE_OT_NOISE_SRC_IF }, {}, }, }; From 42437b3718da1f4afd2ff9720b91da8950dd2342 Mon Sep 17 00:00:00 2001 From: Emmanuel Blot Date: Thu, 23 Oct 2025 12:21:36 +0200 Subject: [PATCH 11/18] [ot] hw/opentitan: ot_random_src: remove ot_random_src implementation it is no longer useful Signed-off-by: Emmanuel Blot --- hw/opentitan/Kconfig | 3 -- hw/opentitan/meson.build | 1 - hw/opentitan/ot_random_src.c | 42 ---------------- include/hw/opentitan/ot_random_src.h | 71 ---------------------------- 4 files changed, 117 deletions(-) delete mode 100644 hw/opentitan/ot_random_src.c delete mode 100644 include/hw/opentitan/ot_random_src.h diff --git a/hw/opentitan/Kconfig b/hw/opentitan/Kconfig index 9b37047f4f0f..ad2b5dd61001 100644 --- a/hw/opentitan/Kconfig +++ b/hw/opentitan/Kconfig @@ -158,9 +158,6 @@ config OT_PWRMGR select OT_CLOCK_CTRL bool -config OT_RANDOM_SRC - bool - config OT_ROM_CTRL bool select OT_COMMON diff --git a/hw/opentitan/meson.build b/hw/opentitan/meson.build index e564a20309e1..2049687268bc 100644 --- a/hw/opentitan/meson.build +++ b/hw/opentitan/meson.build @@ -46,7 +46,6 @@ system_ss.add(when: 'CONFIG_OT_PRESENT', if_true: files('ot_present.c')) system_ss.add(when: 'CONFIG_OT_PRINCE', if_true: files('ot_prince.c')) system_ss.add(when: 'CONFIG_OT_PRNG', if_true: files('ot_prng.c')) system_ss.add(when: 'CONFIG_OT_PWRMGR', if_true: files('ot_pwrmgr.c')) -system_ss.add(when: 'CONFIG_OT_RANDOM_SRC', if_true: files('ot_random_src.c')) system_ss.add(when: 'CONFIG_OT_ROM_CTRL', if_true: files('ot_rom_ctrl.c', 'ot_rom_ctrl_img.c')) system_ss.add(when: 'CONFIG_OT_RSTMGR', if_true: files('ot_rstmgr.c')) system_ss.add(when: 'CONFIG_OT_SENSOR_EG', if_true: files('ot_sensor_eg.c')) diff --git a/hw/opentitan/ot_random_src.c b/hw/opentitan/ot_random_src.c deleted file mode 100644 index c637a86085ac..000000000000 --- a/hw/opentitan/ot_random_src.c +++ /dev/null @@ -1,42 +0,0 @@ -/* - * QEMU OpenTitan Random Source interface - * - * Copyright (c) 2023 Rivos, Inc. - * - * Author(s): - * Emmanuel Blot - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "qemu/osdep.h" -#include "hw/opentitan/ot_random_src.h" - -static const TypeInfo ot_random_src_info = { - .name = TYPE_OT_RANDOM_SRC_IF, - .parent = TYPE_INTERFACE, - .class_size = sizeof(OtRandomSrcIfClass), -}; - -static void ot_random_src_register_types(void) -{ - type_register_static(&ot_random_src_info); -} - -type_init(ot_random_src_register_types); diff --git a/include/hw/opentitan/ot_random_src.h b/include/hw/opentitan/ot_random_src.h deleted file mode 100644 index 606ef74091de..000000000000 --- a/include/hw/opentitan/ot_random_src.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * QEMU OpenTitan Random Source interface - * - * Copyright (c) 2023-2024 Rivos, Inc. - * Copyright (c) 2025 lowRISC contributors. - * - * - * Author(s): - * Emmanuel Blot - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef HW_OPENTITAN_OT_RANDOM_SRC_H -#define HW_OPENTITAN_OT_RANDOM_SRC_H - -#include "qom/object.h" - -#define TYPE_OT_RANDOM_SRC_IF "ot-random_src_if" -typedef struct OtRandomSrcIfClass OtRandomSrcIfClass; -DECLARE_CLASS_CHECKERS(OtRandomSrcIfClass, OT_RANDOM_SRC_IF, - TYPE_OT_RANDOM_SRC_IF) -#define OT_RANDOM_SRC_IF(_obj_) \ - INTERFACE_CHECK(OtRandomSrcIf, (_obj_), TYPE_OT_RANDOM_SRC_IF) - -#define OT_RANDOM_SRC_PACKET_SIZE_BITS 384u - -#define OT_RANDOM_SRC_BYTE_COUNT (OT_RANDOM_SRC_PACKET_SIZE_BITS / 8u) -#define OT_RANDOM_SRC_WORD_COUNT (OT_RANDOM_SRC_BYTE_COUNT / sizeof(uint32_t)) -#define OT_RANDOM_SRC_DWORD_COUNT (OT_RANDOM_SRC_BYTE_COUNT / sizeof(uint64_t)) - -typedef struct OtRandomSrcIf OtRandomSrcIf; - -struct OtRandomSrcIfClass { - InterfaceClass parent_class; - - /* - * Fill up a buffer with random values - * - * @dev the random source instance - * @random the buffer to fill in with random data - * @fips on success, updated to @true if random data are FIPS-compliant - * @return 0 on success, - * >=1 if the random source is still initializing or not enough - * entropy is available to fill the output buffer; - * if >1, indicates a hint on how many ns to wait before retrying, - * -1 if the random source is not available, i.e. if the module is - * not enabled or if the selected route is not the HW one, - */ - int (*get_random_values)(OtRandomSrcIf *dev, - uint64_t random[OT_RANDOM_SRC_DWORD_COUNT], - bool *fips); -}; - -#endif /* HW_OPENTITAN_OT_RANDOM_SRC_H */ From 63bf2e06a88dc624e139cb3655d8d2c51395496f Mon Sep 17 00:00:00 2001 From: Emmanuel Blot Date: Thu, 23 Oct 2025 12:26:48 +0200 Subject: [PATCH 12/18] [ot] hw/riscv: ot_darjeeling: update entropy stack configuration - configure entropy src version - replace random src interface with entropy src - replace entropy src noise source Signed-off-by: Emmanuel Blot --- hw/riscv/ot_darjeeling.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/hw/riscv/ot_darjeeling.c b/hw/riscv/ot_darjeeling.c index 5d646ded929d..b50117dec83a 100644 --- a/hw/riscv/ot_darjeeling.c +++ b/hw/riscv/ot_darjeeling.c @@ -740,7 +740,7 @@ static const IbexDeviceDef ot_dj_soc_devices[] = { OT_DJ_SOC_GPIO_ALERT(1, 34) ), .link = IBEXDEVICELINKDEFS( - OT_DJ_SOC_DEVLINK("random_src", AST), + OT_DJ_SOC_DEVLINK("entropy-src", ENTROPY_SRC), OT_DJ_SOC_DEVLINK("otp_ctrl", OTP_CTRL) ), }, @@ -758,9 +758,12 @@ static const IbexDeviceDef ot_dj_soc_devices[] = { OT_DJ_SOC_GPIO_ALERT(1, 36) ), .link = IBEXDEVICELINKDEFS( - OT_DJ_SOC_DEVLINK("ast", AST), + OT_DJ_SOC_DEVLINK("noise-src", AST), OT_DJ_SOC_DEVLINK("otp_ctrl", OTP_CTRL) ), + .prop = IBEXDEVICEPROPDEFS( + IBEX_DEV_UINT_PROP("version", 3) + ), }, [OT_DJ_SOC_DEV_EDN0] = { .type = TYPE_OT_EDN, From dccd8bdb8ff47582c05f5d8a503c0ea301ca6b06 Mon Sep 17 00:00:00 2001 From: Emmanuel Blot Date: Thu, 23 Oct 2025 12:27:29 +0200 Subject: [PATCH 13/18] [ot] hw/riscv: ot_earlgrey: update entropy stack configuration - configure entropy src version - replace random src interface with entropy src - replace entropy src noise source Signed-off-by: Emmanuel Blot --- hw/riscv/ot_earlgrey.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/hw/riscv/ot_earlgrey.c b/hw/riscv/ot_earlgrey.c index ddd3fdd47c5f..bc1f3b309889 100644 --- a/hw/riscv/ot_earlgrey.c +++ b/hw/riscv/ot_earlgrey.c @@ -1228,7 +1228,7 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { OT_EG_SOC_GPIO_ALERT(1, 52) ), .link = IBEXDEVICELINKDEFS( - OT_EG_SOC_DEVLINK("random_src", ENTROPY_SRC), + OT_EG_SOC_DEVLINK("entropy-src", ENTROPY_SRC), OT_EG_SOC_DEVLINK("otp_ctrl", OTP_CTRL) ), }, @@ -1246,9 +1246,12 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { OT_EG_SOC_GPIO_ALERT(1, 54) ), .link = IBEXDEVICELINKDEFS( - OT_EG_SOC_DEVLINK("ast", AST), + OT_EG_SOC_DEVLINK("noise-src", AST), OT_EG_SOC_DEVLINK("otp_ctrl", OTP_CTRL) ), + .prop = IBEXDEVICEPROPDEFS( + IBEX_DEV_UINT_PROP("version", 2) + ), }, [OT_EG_SOC_DEV_EDN0] = { .type = TYPE_OT_EDN, From 87553eb16e82e043edcbf9d16ac88652f04dcbc0 Mon Sep 17 00:00:00 2001 From: Emmanuel Blot Date: Thu, 23 Oct 2025 14:10:07 +0200 Subject: [PATCH 14/18] [ot] hw/opentitan: ot_otp: remove useless entropy API Move the en_csrng_sw_app_read field to where it belongs: OtOTPHWCfg Signed-off-by: Emmanuel Blot --- hw/opentitan/ot_csrng.c | 16 +++++----------- hw/opentitan/ot_entropy_src.c | 4 ---- hw/opentitan/ot_otp_dj.c | 19 ++++++++----------- hw/opentitan/ot_otp_eg.c | 20 +++++--------------- include/hw/opentitan/ot_otp.h | 16 ++-------------- 5 files changed, 20 insertions(+), 55 deletions(-) diff --git a/hw/opentitan/ot_csrng.c b/hw/opentitan/ot_csrng.c index 1a67d614f453..bfb4de3cafa8 100644 --- a/hw/opentitan/ot_csrng.c +++ b/hw/opentitan/ot_csrng.c @@ -1822,24 +1822,18 @@ static void ot_csrng_regs_write(void *opaque, hwaddr addr, uint64_t val64, if (change) { xtrace_ot_csrng_info("handling CTRL change", val32); ot_csrng_handle_enable(s); - bool granted; OtOTPClass *oc = OBJECT_GET_CLASS(OtOTPClass, s->otp_ctrl, TYPE_OT_OTP); - const OtOTPEntropyCfg *entropy_cfg = - oc->get_entropy_cfg(s->otp_ctrl); - if (entropy_cfg) { - granted = - entropy_cfg->en_csrng_sw_app_read == OT_MULTIBITBOOL8_TRUE; - } else { - /* defaults to granted if no entropy config in OTP */ - granted = true; - } - if (granted) { + const OtOTPHWCfg *hw_cfg = oc->get_hw_cfg(s->otp_ctrl); + g_assert(hw_cfg); + if (hw_cfg->en_csrng_sw_app_read == OT_MULTIBITBOOL8_TRUE) { uint32_t sw_app_en = FIELD_EX32(val32, CTRL, SW_APP_ENABLE); s->sw_app_granted = sw_app_en == OT_MULTIBITBOOL4_TRUE; uint32_t read_int = FIELD_EX32(val32, CTRL, READ_INT_STATE); s->read_int_granted = read_int == OT_MULTIBITBOOL4_TRUE; } else { + qemu_log_mask(LOG_GUEST_ERROR, "%s: SW APP disabled in OTP\n", + __func__); s->sw_app_granted = false; s->read_int_granted = false; } diff --git a/hw/opentitan/ot_entropy_src.c b/hw/opentitan/ot_entropy_src.c index 5a4f571922c5..bcafff5fb5d9 100644 --- a/hw/opentitan/ot_entropy_src.c +++ b/hw/opentitan/ot_entropy_src.c @@ -1871,10 +1871,6 @@ static void ot_entropy_src_reset_enter(Object *obj, ResetType type) ibex_irq_set(&s->alerts[ix], 0); } - OtOTPClass *oc = OBJECT_GET_CLASS(OtOTPClass, s->otp_ctrl, TYPE_OT_OTP); - const OtOTPEntropyCfg *entropy_cfg = oc->get_entropy_cfg(s->otp_ctrl); - g_assert(entropy_cfg); - ot_entropy_src_change_state(s, ENTROPY_SRC_IDLE); } diff --git a/hw/opentitan/ot_otp_dj.c b/hw/opentitan/ot_otp_dj.c index 7f2759cc2bf0..ecf3af451ccc 100644 --- a/hw/opentitan/ot_otp_dj.c +++ b/hw/opentitan/ot_otp_dj.c @@ -2926,14 +2926,7 @@ static const OtOTPHWCfg *ot_otp_dj_get_hw_cfg(const OtOTPState *s) { const OtOTPDjState *ds = OT_OTP_DJ(s); - return ds->hw_cfg; -} - -static const OtOTPEntropyCfg *ot_otp_dj_get_entropy_cfg(const OtOTPState *s) -{ - (void)s; - /* not present Darjeeling OTP */ - return NULL; + return (const OtOTPHWCfg *)ds->hw_cfg; } static void ot_otp_dj_request_entropy_bh(void *opaque) @@ -3550,6 +3543,10 @@ static void ot_otp_dj_pwr_load_hw_cfg(OtOTPDjState *s) hw_cfg->en_sram_ifetch = s->blk ? (uint8_t)otp->data[R_HW_CFG1_EN_SRAM_IFETCH] : OT_MULTIBITBOOL8_TRUE; + /* do not prevent CSRNG app reads if no OTP configuration is loaded */ + hw_cfg->en_csrng_sw_app_read = + s->blk ? (uint8_t)otp->data[R_HW_CFG1_EN_CSRNG_SW_APP_READ] : + OT_MULTIBITBOOL8_TRUE; } static void ot_otp_dj_pwr_load_tokens(OtOTPDjState *s) @@ -3960,7 +3957,7 @@ static void ot_otp_dj_reset_enter(Object *obj, ResetType type) * * File back-end storage (loading) is processed from * the ot_otp_dj_pwr_otp_bh handler, to ensure data is reloaded from the - * backend on each reset, prior to this very reset fuction. This reset + * backend on each reset, prior to this very reset function. This reset * function should not alter the storage content. * * Ideally the OTP reset functions should be decoupled from the regular @@ -3988,6 +3985,7 @@ static void ot_otp_dj_reset_enter(Object *obj, ResetType type) s->keygen->edn_sched = false; memset(s->regs, 0, REGS_COUNT * sizeof(uint32_t)); + memset(s->hw_cfg, 0, sizeof(*s->hw_cfg)); s->regs[R_DIRECT_ACCESS_REGWEN] = 0x00000001u; s->regs[R_CHECK_TRIGGER_REGWEN] = 0x00000001u; @@ -4070,7 +4068,7 @@ static void ot_otp_dj_realize(DeviceState *dev, Error **errp) /* * Set the OTP drive's permissions now during realization. We can't leave it - * until reset because QEMU might have `-deamonize`d and changed directory, + * until reset because QEMU might have `-daemonize`d and changed directory, * invalidating the filesystem path to the OTP image. */ if (s->blk) { @@ -4187,7 +4185,6 @@ static void ot_otp_dj_class_init(ObjectClass *klass, void *data) oc->get_lc_info = &ot_otp_dj_get_lc_info; oc->get_hw_cfg = &ot_otp_dj_get_hw_cfg; - oc->get_entropy_cfg = &ot_otp_dj_get_entropy_cfg; oc->get_otp_key = &ot_otp_dj_get_otp_key; oc->get_keymgr_secret = &ot_otp_dj_get_keymgr_secret; oc->program_req = &ot_otp_dj_program_req; diff --git a/hw/opentitan/ot_otp_eg.c b/hw/opentitan/ot_otp_eg.c index e33913d80da0..4ab2c7fe7a3d 100644 --- a/hw/opentitan/ot_otp_eg.c +++ b/hw/opentitan/ot_otp_eg.c @@ -699,7 +699,6 @@ struct OtOTPEgState { OtOTPStorage *otp; OtOTPHWCfg *hw_cfg; - OtOTPEntropyCfg *entropy_cfg; OtOTPTokens *tokens; char *hexstr; @@ -2803,14 +2802,7 @@ static const OtOTPHWCfg *ot_otp_eg_get_hw_cfg(const OtOTPState *s) { const OtOTPEgState *es = OT_OTP_EG(s); - return es->hw_cfg; -} - -static const OtOTPEntropyCfg *ot_otp_eg_get_entropy_cfg(const OtOTPState *s) -{ - const OtOTPEgState *es = OT_OTP_EG(s); - - return es->entropy_cfg; + return (const OtOTPHWCfg *)es->hw_cfg; } static void ot_otp_eg_request_entropy_bh(void *opaque) @@ -3425,7 +3417,6 @@ static void ot_otp_eg_pwr_load_hw_cfg(OtOTPEgState *s) { OtOTPStorage *otp = s->otp; OtOTPHWCfg *hw_cfg = s->hw_cfg; - OtOTPEntropyCfg *entropy_cfg = s->entropy_cfg; memcpy(hw_cfg->device_id, &otp->data[R_HW_CFG0_DEVICE_ID], sizeof(hw_cfg->device_id)); @@ -3436,7 +3427,7 @@ static void ot_otp_eg_pwr_load_hw_cfg(OtOTPEgState *s) s->blk ? (uint8_t)otp->data[R_HW_CFG1_EN_SRAM_IFETCH] : OT_MULTIBITBOOL8_TRUE; /* do not prevent CSRNG app reads if no OTP configuration is loaded */ - entropy_cfg->en_csrng_sw_app_read = + hw_cfg->en_csrng_sw_app_read = s->blk ? (uint8_t)otp->data[R_HW_CFG1_EN_CSRNG_SW_APP_READ] : OT_MULTIBITBOOL8_TRUE; } @@ -3944,7 +3935,7 @@ static void ot_otp_eg_reset_enter(Object *obj, ResetType type) * * File back-end storage (loading) is processed from * the ot_otp_eg_pwr_otp_bh handler, to ensure data is reloaded from the - * backend on each reset, prior to this very reset fuction. This reset + * backend on each reset, prior to this very reset function. This reset * function should not alter the storage content. * * Ideally the OTP reset functions should be decoupled from the regular @@ -3972,6 +3963,7 @@ static void ot_otp_eg_reset_enter(Object *obj, ResetType type) s->keygen->edn_sched = false; memset(s->regs, 0, REGS_COUNT * sizeof(uint32_t)); + memset(s->hw_cfg, 0, sizeof(*s->hw_cfg)); s->regs[R_DIRECT_ACCESS_REGWEN] = 0x1u; s->regs[R_CHECK_TRIGGER_REGWEN] = 0x1u; @@ -4044,7 +4036,7 @@ static void ot_otp_eg_realize(DeviceState *dev, Error **errp) /* * Set the OTP drive's permissions now during realization. We can't leave it - * until reset because QEMU might have `-deamonize`d and changed directory, + * until reset because QEMU might have `-daemonize`d and changed directory, * invalidating the filesystem path to the OTP image. */ if (s->blk) { @@ -4104,7 +4096,6 @@ static void ot_otp_eg_init(Object *obj) OT_LC_BROADCAST, OT_OTP_LC_BROADCAST_COUNT); s->hw_cfg = g_new0(OtOTPHWCfg, 1u); - s->entropy_cfg = g_new0(OtOTPEntropyCfg, 1u); s->tokens = g_new0(OtOTPTokens, 1u); s->regs = g_new0(uint32_t, REGS_COUNT); s->dai = g_new0(OtOTPDAIController, 1u); @@ -4163,7 +4154,6 @@ static void ot_otp_eg_class_init(ObjectClass *klass, void *data) oc->get_lc_info = &ot_otp_eg_get_lc_info; oc->get_hw_cfg = &ot_otp_eg_get_hw_cfg; - oc->get_entropy_cfg = &ot_otp_eg_get_entropy_cfg; oc->get_otp_key = &ot_otp_eg_get_otp_key; oc->get_keymgr_secret = &ot_otp_eg_get_keymgr_secret; oc->program_req = &ot_otp_eg_program_req; diff --git a/include/hw/opentitan/ot_otp.h b/include/hw/opentitan/ot_otp.h index 7378376f72cc..2093baffc72c 100644 --- a/include/hw/opentitan/ot_otp.h +++ b/include/hw/opentitan/ot_otp.h @@ -57,7 +57,7 @@ typedef enum { #define OT_OTP_HWCFG_SOC_DBG_STATE_BYTES 4u /* - * Hardware configuration (for HW_CFG partition) + * Hardware configuration (for HW_CFG partitions) */ typedef struct { uint8_t device_id[OT_OTP_HWCFG_DEVICE_ID_BYTES]; @@ -66,12 +66,8 @@ typedef struct { uint8_t soc_dbg_state[OT_OTP_HWCFG_SOC_DBG_STATE_BYTES]; /* the following value is stored as OT_MULTIBITBOOL8 */ uint8_t en_sram_ifetch; -} OtOTPHWCfg; - -typedef struct { - /* the following values are stored as OT_MULTIBITBOOL8 */ uint8_t en_csrng_sw_app_read; -} OtOTPEntropyCfg; +} OtOTPHWCfg; typedef enum { OTP_TOKEN_TEST_UNLOCK, @@ -158,14 +154,6 @@ struct OtOTPClass { */ const OtOTPHWCfg *(*get_hw_cfg)(const OtOTPState *s); - /* - * Retrieve entropy configuration. - * - * @s the OTP device - * @return the entropy config data (may be NULL if not present in OTP) - */ - const OtOTPEntropyCfg *(*get_entropy_cfg)(const OtOTPState *s); - /* * Retrieve SRAM scrambling key. * From 9aec3d99c7e9c6bc3b95cc4bfdca49ace20a6ba1 Mon Sep 17 00:00:00 2001 From: Emmanuel Blot Date: Thu, 23 Oct 2025 16:07:35 +0200 Subject: [PATCH 15/18] [ot] hw/opentitan: ot_common: define type aliases for OpenTitan multibit booleans Signed-off-by: Emmanuel Blot --- include/hw/opentitan/ot_common.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/hw/opentitan/ot_common.h b/include/hw/opentitan/ot_common.h index b53a5f937edc..8e9824935ada 100644 --- a/include/hw/opentitan/ot_common.h +++ b/include/hw/opentitan/ot_common.h @@ -71,6 +71,12 @@ #define OT_MULTIBITBOOL_LC4_TRUE 0xau #define OT_MULTIBITBOOL_LC4_FALSE 0x5u +typedef uint8_t ot_mb4_t; +typedef uint8_t ot_mb8_t; +typedef uint16_t ot_mb12_t; +typedef uint16_t ot_mb16_t; +typedef uint8_t ot_mb_lc4_t; + /* * Performs a logical OR operation between two multibit values. * This treats "act" as logical 1, and all other values are treated as 0. From 016820d256b1796421841f84827e5447aed7f348 Mon Sep 17 00:00:00 2001 From: Emmanuel Blot Date: Thu, 23 Oct 2025 15:56:14 +0200 Subject: [PATCH 16/18] [ot] hw/opentitan: ot_otp: make multibool bit type more visible Signed-off-by: Emmanuel Blot --- hw/opentitan/ot_csrng.c | 2 +- hw/opentitan/ot_otp_dj.c | 4 ++-- hw/opentitan/ot_otp_eg.c | 4 ++-- hw/opentitan/ot_sram_ctrl.c | 2 +- include/hw/opentitan/ot_otp.h | 15 ++++++++++----- 5 files changed, 16 insertions(+), 11 deletions(-) diff --git a/hw/opentitan/ot_csrng.c b/hw/opentitan/ot_csrng.c index bfb4de3cafa8..c275ab1002f2 100644 --- a/hw/opentitan/ot_csrng.c +++ b/hw/opentitan/ot_csrng.c @@ -1826,7 +1826,7 @@ static void ot_csrng_regs_write(void *opaque, hwaddr addr, uint64_t val64, OBJECT_GET_CLASS(OtOTPClass, s->otp_ctrl, TYPE_OT_OTP); const OtOTPHWCfg *hw_cfg = oc->get_hw_cfg(s->otp_ctrl); g_assert(hw_cfg); - if (hw_cfg->en_csrng_sw_app_read == OT_MULTIBITBOOL8_TRUE) { + if (hw_cfg->en_csrng_sw_app_read_mb8 == OT_MULTIBITBOOL8_TRUE) { uint32_t sw_app_en = FIELD_EX32(val32, CTRL, SW_APP_ENABLE); s->sw_app_granted = sw_app_en == OT_MULTIBITBOOL4_TRUE; uint32_t read_int = FIELD_EX32(val32, CTRL, READ_INT_STATE); diff --git a/hw/opentitan/ot_otp_dj.c b/hw/opentitan/ot_otp_dj.c index ecf3af451ccc..1b11fff5700a 100644 --- a/hw/opentitan/ot_otp_dj.c +++ b/hw/opentitan/ot_otp_dj.c @@ -3540,11 +3540,11 @@ static void ot_otp_dj_pwr_load_hw_cfg(OtOTPDjState *s) memcpy(hw_cfg->soc_dbg_state, &otp->data[R_HW_CFG1_SOC_DBG_STATE], sizeof(hw_cfg->soc_dbg_state)); /* do not prevent execution from SRAM if no OTP configuration is loaded */ - hw_cfg->en_sram_ifetch = + hw_cfg->en_sram_ifetch_mb8 = s->blk ? (uint8_t)otp->data[R_HW_CFG1_EN_SRAM_IFETCH] : OT_MULTIBITBOOL8_TRUE; /* do not prevent CSRNG app reads if no OTP configuration is loaded */ - hw_cfg->en_csrng_sw_app_read = + hw_cfg->en_csrng_sw_app_read_mb8 = s->blk ? (uint8_t)otp->data[R_HW_CFG1_EN_CSRNG_SW_APP_READ] : OT_MULTIBITBOOL8_TRUE; } diff --git a/hw/opentitan/ot_otp_eg.c b/hw/opentitan/ot_otp_eg.c index 4ab2c7fe7a3d..62841414aa00 100644 --- a/hw/opentitan/ot_otp_eg.c +++ b/hw/opentitan/ot_otp_eg.c @@ -3423,11 +3423,11 @@ static void ot_otp_eg_pwr_load_hw_cfg(OtOTPEgState *s) memcpy(hw_cfg->manuf_state, &otp->data[R_HW_CFG0_MANUF_STATE], sizeof(hw_cfg->manuf_state)); /* do not prevent execution from SRAM if no OTP configuration is loaded */ - hw_cfg->en_sram_ifetch = + hw_cfg->en_sram_ifetch_mb8 = s->blk ? (uint8_t)otp->data[R_HW_CFG1_EN_SRAM_IFETCH] : OT_MULTIBITBOOL8_TRUE; /* do not prevent CSRNG app reads if no OTP configuration is loaded */ - hw_cfg->en_csrng_sw_app_read = + hw_cfg->en_csrng_sw_app_read_mb8 = s->blk ? (uint8_t)otp->data[R_HW_CFG1_EN_CSRNG_SW_APP_READ] : OT_MULTIBITBOOL8_TRUE; } diff --git a/hw/opentitan/ot_sram_ctrl.c b/hw/opentitan/ot_sram_ctrl.c index 0b3e4b5f2e02..185cc31aad6b 100644 --- a/hw/opentitan/ot_sram_ctrl.c +++ b/hw/opentitan/ot_sram_ctrl.c @@ -356,7 +356,7 @@ static void ot_sram_ctrl_update_exec(OtSramCtrlState *s) */ if (s->otp_ctrl) { OtOTPClass *oc = OBJECT_GET_CLASS(OtOTPClass, s->otp_ctrl, TYPE_OT_OTP); - s->otp_ifetch = oc->get_hw_cfg(s->otp_ctrl)->en_sram_ifetch == + s->otp_ifetch = oc->get_hw_cfg(s->otp_ctrl)->en_sram_ifetch_mb8 == OT_MULTIBITBOOL8_TRUE; } diff --git a/include/hw/opentitan/ot_otp.h b/include/hw/opentitan/ot_otp.h index 2093baffc72c..12a9fdc56016 100644 --- a/include/hw/opentitan/ot_otp.h +++ b/include/hw/opentitan/ot_otp.h @@ -30,6 +30,7 @@ #define HW_OPENTITAN_OT_OTP_H #include "qom/object.h" +#include "hw/opentitan/ot_common.h" #include "hw/sysbus.h" #define TYPE_OT_OTP "ot-otp" @@ -57,16 +58,20 @@ typedef enum { #define OT_OTP_HWCFG_SOC_DBG_STATE_BYTES 4u /* - * Hardware configuration (for HW_CFG partitions) + * Hardware configuration (for HW_CFG partitions). + * + * Digests are not added to this structure since real HW does not use them + * + * Note that some fields may be meaningless / not initialized depending on the + * actual OpenTitan top. */ typedef struct { uint8_t device_id[OT_OTP_HWCFG_DEVICE_ID_BYTES]; uint8_t manuf_state[OT_OTP_HWCFG_MANUF_STATE_BYTES]; - /* soc_dbg_state may be meaningless, dep. on the platform */ uint8_t soc_dbg_state[OT_OTP_HWCFG_SOC_DBG_STATE_BYTES]; - /* the following value is stored as OT_MULTIBITBOOL8 */ - uint8_t en_sram_ifetch; - uint8_t en_csrng_sw_app_read; + ot_mb8_t en_sram_ifetch_mb8; + ot_mb8_t en_csrng_sw_app_read_mb8; + ot_mb_lc4_t valid_lc4; /* seems generated but no used on real HW */ } OtOTPHWCfg; typedef enum { From a97bfa9569218e502c69c9b50e10b8dfbbc930a8 Mon Sep 17 00:00:00 2001 From: Emmanuel Blot Date: Thu, 23 Oct 2025 16:18:45 +0200 Subject: [PATCH 17/18] [ot] hw/riscv, hw/opentitan: all: fix dash vs. underscore link names Signed-off-by: Emmanuel Blot --- hw/opentitan/ot_csrng.c | 2 +- hw/opentitan/ot_entropy_src.c | 2 +- hw/opentitan/ot_keymgr.c | 4 ++-- hw/opentitan/ot_keymgr_dpe.c | 4 ++-- hw/opentitan/ot_lc_ctrl.c | 2 +- hw/opentitan/ot_pwrmgr.c | 2 +- hw/opentitan/ot_sram_ctrl.c | 2 +- hw/riscv/dtm.c | 2 +- hw/riscv/ibexdemo.c | 2 +- hw/riscv/ot_darjeeling.c | 20 ++++++++++---------- hw/riscv/ot_earlgrey.c | 18 +++++++++--------- 11 files changed, 30 insertions(+), 30 deletions(-) diff --git a/hw/opentitan/ot_csrng.c b/hw/opentitan/ot_csrng.c index c275ab1002f2..f21cf113f3d8 100644 --- a/hw/opentitan/ot_csrng.c +++ b/hw/opentitan/ot_csrng.c @@ -1938,7 +1938,7 @@ static void ot_csrng_regs_write(void *opaque, hwaddr addr, uint64_t val64, static Property ot_csrng_properties[] = { DEFINE_PROP_LINK("entropy-src", OtCSRNGState, entropy_src, TYPE_OT_ENTROPY_SRC, OtEntropySrcState *), - DEFINE_PROP_LINK("otp_ctrl", OtCSRNGState, otp_ctrl, TYPE_OT_OTP, + DEFINE_PROP_LINK("otp-ctrl", OtCSRNGState, otp_ctrl, TYPE_OT_OTP, OtOTPState *), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/opentitan/ot_entropy_src.c b/hw/opentitan/ot_entropy_src.c index bcafff5fb5d9..2bfee3f802c8 100644 --- a/hw/opentitan/ot_entropy_src.c +++ b/hw/opentitan/ot_entropy_src.c @@ -1803,7 +1803,7 @@ static Property ot_entropy_src_properties[] = { DEFINE_PROP_UINT32("version", OtEntropySrcState, version, 0), DEFINE_PROP_LINK("noise-src", OtEntropySrcState, noise_src, TYPE_DEVICE, DeviceState *), - DEFINE_PROP_LINK("otp_ctrl", OtEntropySrcState, otp_ctrl, TYPE_OT_OTP, + DEFINE_PROP_LINK("otp-ctrl", OtEntropySrcState, otp_ctrl, TYPE_OT_OTP, OtOTPState *), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/opentitan/ot_keymgr.c b/hw/opentitan/ot_keymgr.c index b8b430e4c350..a4b59f803b42 100644 --- a/hw/opentitan/ot_keymgr.c +++ b/hw/opentitan/ot_keymgr.c @@ -2330,9 +2330,9 @@ static Property ot_keymgr_properties[] = { OtFlashState *), DEFINE_PROP_LINK("kmac", OtKeyMgrState, kmac, TYPE_OT_KMAC, OtKMACState *), DEFINE_PROP_UINT8("kmac-app", OtKeyMgrState, kmac_app, UINT8_MAX), - DEFINE_PROP_LINK("lc_ctrl", OtKeyMgrState, lc_ctrl, TYPE_OT_LC_CTRL, + DEFINE_PROP_LINK("lc-ctrl", OtKeyMgrState, lc_ctrl, TYPE_OT_LC_CTRL, OtLcCtrlState *), - DEFINE_PROP_LINK("otp_ctrl", OtKeyMgrState, otp_ctrl, TYPE_OT_OTP, + DEFINE_PROP_LINK("otp-ctrl", OtKeyMgrState, otp_ctrl, TYPE_OT_OTP, OtOTPState *), DEFINE_PROP_LINK("rom_ctrl", OtKeyMgrState, rom_ctrl, TYPE_OT_ROM_CTRL, OtRomCtrlState *), diff --git a/hw/opentitan/ot_keymgr_dpe.c b/hw/opentitan/ot_keymgr_dpe.c index e6d08f4241e3..422607e2df22 100644 --- a/hw/opentitan/ot_keymgr_dpe.c +++ b/hw/opentitan/ot_keymgr_dpe.c @@ -2002,9 +2002,9 @@ static Property ot_keymgr_dpe_properties[] = { DEFINE_PROP_LINK("kmac", OtKeyMgrDpeState, kmac, TYPE_OT_KMAC, OtKMACState *), DEFINE_PROP_UINT8("kmac-app", OtKeyMgrDpeState, kmac_app, UINT8_MAX), - DEFINE_PROP_LINK("lc_ctrl", OtKeyMgrDpeState, lc_ctrl, TYPE_OT_LC_CTRL, + DEFINE_PROP_LINK("lc-ctrl", OtKeyMgrDpeState, lc_ctrl, TYPE_OT_LC_CTRL, OtLcCtrlState *), - DEFINE_PROP_LINK("otp_ctrl", OtKeyMgrDpeState, otp, TYPE_OT_OTP, + DEFINE_PROP_LINK("otp-ctrl", OtKeyMgrDpeState, otp, TYPE_OT_OTP, OtOTPState *), DEFINE_PROP_LINK("rom0", OtKeyMgrDpeState, rom_ctrl[0], TYPE_OT_ROM_CTRL, OtRomCtrlState *), diff --git a/hw/opentitan/ot_lc_ctrl.c b/hw/opentitan/ot_lc_ctrl.c index cba7905e304b..25be5342bd50 100644 --- a/hw/opentitan/ot_lc_ctrl.c +++ b/hw/opentitan/ot_lc_ctrl.c @@ -2137,7 +2137,7 @@ static void ot_lc_ctrl_get_keymgr_div(const OtLcCtrlState *s, static Property ot_lc_ctrl_properties[] = { DEFINE_PROP_STRING(OT_COMMON_DEV_ID, OtLcCtrlState, ot_id), - DEFINE_PROP_LINK("otp_ctrl", OtLcCtrlState, otp_ctrl, TYPE_OT_OTP, + DEFINE_PROP_LINK("otp-ctrl", OtLcCtrlState, otp_ctrl, TYPE_OT_OTP, OtOTPState *), DEFINE_PROP_LINK("kmac", OtLcCtrlState, kmac, TYPE_OT_KMAC, OtKMACState *), DEFINE_PROP_STRING("raw_unlock_token", OtLcCtrlState, diff --git a/hw/opentitan/ot_pwrmgr.c b/hw/opentitan/ot_pwrmgr.c index a65e1b4fe875..9e74a4a66e79 100644 --- a/hw/opentitan/ot_pwrmgr.c +++ b/hw/opentitan/ot_pwrmgr.c @@ -984,7 +984,7 @@ static void ot_pwrmgr_regs_write(void *opaque, hwaddr addr, uint64_t val64, static Property ot_pwrmgr_properties[] = { DEFINE_PROP_STRING(OT_COMMON_DEV_ID, OtPwrMgrState, ot_id), DEFINE_PROP_STRING("clocks", OtPwrMgrState, cfg_clocks), - DEFINE_PROP_LINK("clock_ctrl", OtPwrMgrState, clock_ctrl, TYPE_DEVICE, + DEFINE_PROP_LINK("clock-ctrl", OtPwrMgrState, clock_ctrl, TYPE_DEVICE, DeviceState *), DEFINE_PROP_UINT8("num-rom", OtPwrMgrState, num_rom, 0), DEFINE_PROP_UINT8("version", OtPwrMgrState, version, UINT8_MAX), diff --git a/hw/opentitan/ot_sram_ctrl.c b/hw/opentitan/ot_sram_ctrl.c index 185cc31aad6b..99c689e85c07 100644 --- a/hw/opentitan/ot_sram_ctrl.c +++ b/hw/opentitan/ot_sram_ctrl.c @@ -668,7 +668,7 @@ static MemTxResult ot_sram_ctrl_mem_init_write_with_attrs( static Property ot_sram_ctrl_properties[] = { DEFINE_PROP_STRING(OT_COMMON_DEV_ID, OtSramCtrlState, ot_id), - DEFINE_PROP_LINK("otp_ctrl", OtSramCtrlState, otp_ctrl, TYPE_OT_OTP, + DEFINE_PROP_LINK("otp-ctrl", OtSramCtrlState, otp_ctrl, TYPE_OT_OTP, OtOTPState *), DEFINE_PROP_LINK("vmapper", OtSramCtrlState, vmapper, TYPE_OT_VMAPPER, OtVMapperState *), diff --git a/hw/riscv/dtm.c b/hw/riscv/dtm.c index 121e93346543..cfaa2c4ca2d1 100644 --- a/hw/riscv/dtm.c +++ b/hw/riscv/dtm.c @@ -516,7 +516,7 @@ static void riscv_dtm_activate_dms(RISCVDTMState *s) static Property riscv_dtm_properties[] = { DEFINE_PROP_UINT32("abits", RISCVDTMState, abits, 0x7u), - DEFINE_PROP_LINK("tap_ctrl", RISCVDTMState, tap_ctrl, TYPE_DEVICE, + DEFINE_PROP_LINK("tap-ctrl", RISCVDTMState, tap_ctrl, TYPE_DEVICE, DeviceState *), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/riscv/ibexdemo.c b/hw/riscv/ibexdemo.c index e8a468cce749..97affe33a150 100644 --- a/hw/riscv/ibexdemo.c +++ b/hw/riscv/ibexdemo.c @@ -152,7 +152,7 @@ static const IbexDeviceDef ibexdemo_soc_devices[] = { [IBEXDEMO_SOC_DEV_DTM] = { .type = TYPE_RISCV_DTM, .link = IBEXDEVICELINKDEFS( - IBEXDEMO_SOC_DEVLINK("tap_ctrl", TAP_CTRL) + IBEXDEMO_SOC_DEVLINK("tap-ctrl", TAP_CTRL) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_UINT_PROP("abits", 7u) diff --git a/hw/riscv/ot_darjeeling.c b/hw/riscv/ot_darjeeling.c index b50117dec83a..b267500cb050 100644 --- a/hw/riscv/ot_darjeeling.c +++ b/hw/riscv/ot_darjeeling.c @@ -523,7 +523,7 @@ static const IbexDeviceDef ot_dj_soc_devices[] = { [OT_DJ_SOC_DEV_DTM] = { .type = TYPE_RISCV_DTM, .link = IBEXDEVICELINKDEFS( - OT_DJ_SOC_DEVLINK("tap_ctrl", TAP_CTRL) + OT_DJ_SOC_DEVLINK("tap-ctrl", TAP_CTRL) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_UINT_PROP("abits", 12u) @@ -716,8 +716,8 @@ static const IbexDeviceDef ot_dj_soc_devices[] = { OT_DJ_SOC_DEVLINK("edn", EDN0), OT_DJ_SOC_DEVLINK("kmac", KMAC), OT_DJ_SOC_DEVLINK("otbn", OTBN), - OT_DJ_SOC_DEVLINK("lc_ctrl", LC_CTRL), - OT_DJ_SOC_DEVLINK("otp_ctrl", OTP_CTRL), + OT_DJ_SOC_DEVLINK("lc-ctrl", LC_CTRL), + OT_DJ_SOC_DEVLINK("otp-ctrl", OTP_CTRL), OT_DJ_SOC_DEVLINK("rom0", ROM_CTRL0), OT_DJ_SOC_DEVLINK("rom1", ROM_CTRL1) ), @@ -741,7 +741,7 @@ static const IbexDeviceDef ot_dj_soc_devices[] = { ), .link = IBEXDEVICELINKDEFS( OT_DJ_SOC_DEVLINK("entropy-src", ENTROPY_SRC), - OT_DJ_SOC_DEVLINK("otp_ctrl", OTP_CTRL) + OT_DJ_SOC_DEVLINK("otp-ctrl", OTP_CTRL) ), }, [OT_DJ_SOC_DEV_ENTROPY_SRC] = { @@ -759,7 +759,7 @@ static const IbexDeviceDef ot_dj_soc_devices[] = { ), .link = IBEXDEVICELINKDEFS( OT_DJ_SOC_DEVLINK("noise-src", AST), - OT_DJ_SOC_DEVLINK("otp_ctrl", OTP_CTRL) + OT_DJ_SOC_DEVLINK("otp-ctrl", OTP_CTRL) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_UINT_PROP("version", 3) @@ -811,7 +811,7 @@ static const IbexDeviceDef ot_dj_soc_devices[] = { OT_DJ_SOC_GPIO_ALERT(0, 41) ), .link = IBEXDEVICELINKDEFS( - OT_DJ_SOC_DEVLINK("otp_ctrl", OTP_CTRL), + OT_DJ_SOC_DEVLINK("otp-ctrl", OTP_CTRL), OT_DJ_SOC_DEVLINK("vmapper", VMAPPER) ), .prop = IBEXDEVICEPROPDEFS( @@ -830,7 +830,7 @@ static const IbexDeviceDef ot_dj_soc_devices[] = { OT_DJ_SOC_GPIO_ALERT(0, 42) ), .link = IBEXDEVICELINKDEFS( - OT_DJ_SOC_DEVLINK("otp_ctrl", OTP_CTRL), + OT_DJ_SOC_DEVLINK("otp-ctrl", OTP_CTRL), OT_DJ_SOC_DEVLINK("vmapper", VMAPPER) ), .prop = IBEXDEVICEPROPDEFS( @@ -1175,7 +1175,7 @@ static const IbexDeviceDef ot_dj_soc_devices[] = { OT_DJ_SOC_RSP(OT_PWRMGR_LC, PWRMGR) ), .link = IBEXDEVICELINKDEFS( - OT_DJ_SOC_DEVLINK("otp_ctrl", OTP_CTRL), + OT_DJ_SOC_DEVLINK("otp-ctrl", OTP_CTRL), OT_DJ_SOC_DEVLINK("kmac", KMAC) ), .prop = IBEXDEVICEPROPDEFS( @@ -1285,7 +1285,7 @@ static const IbexDeviceDef ot_dj_soc_devices[] = { OT_RSTMGR_RST_REQ, 0) ), .link = IBEXDEVICELINKDEFS( - OT_DJ_SOC_DEVLINK("clock_ctrl", AST) + OT_DJ_SOC_DEVLINK("clock-ctrl", AST) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_STRING_PROP("clocks", "main,io"), @@ -1421,7 +1421,7 @@ static const IbexDeviceDef ot_dj_soc_devices[] = { OT_DJ_SOC_GPIO_ALERT(0, 21) ), .link = IBEXDEVICELINKDEFS( - OT_DJ_SOC_DEVLINK("otp_ctrl", OTP_CTRL), + OT_DJ_SOC_DEVLINK("otp-ctrl", OTP_CTRL), OT_DJ_SOC_DEVLINK("vmapper", VMAPPER) ), .prop = IBEXDEVICEPROPDEFS( diff --git a/hw/riscv/ot_earlgrey.c b/hw/riscv/ot_earlgrey.c index bc1f3b309889..0fdfc591cefb 100644 --- a/hw/riscv/ot_earlgrey.c +++ b/hw/riscv/ot_earlgrey.c @@ -363,7 +363,7 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { [OT_EG_SOC_DEV_DTM] = { .type = TYPE_RISCV_DTM, .link = IBEXDEVICELINKDEFS( - OT_EG_SOC_DEVLINK("tap_ctrl", TAP_CTRL) + OT_EG_SOC_DEVLINK("tap-ctrl", TAP_CTRL) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_UINT_PROP("abits", 7u) @@ -776,7 +776,7 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { OT_LC_BROADCAST, OT_OTP_LC_CHECK_BYP_EN) ), .link = IBEXDEVICELINKDEFS( - OT_EG_SOC_DEVLINK("otp_ctrl", OTP_CTRL), + OT_EG_SOC_DEVLINK("otp-ctrl", OTP_CTRL), OT_EG_SOC_DEVLINK("kmac", KMAC) ), .prop = IBEXDEVICEPROPDEFS( @@ -912,7 +912,7 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { OT_RSTMGR_RST_REQ, 0) ), .link = IBEXDEVICELINKDEFS( - OT_EG_SOC_DEVLINK("clock_ctrl", AST) + OT_EG_SOC_DEVLINK("clock-ctrl", AST) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_STRING_PROP("clocks", "main,io,usb"), @@ -1076,7 +1076,7 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { OT_EG_SOC_GPIO_ALERT(0, 34) ), .link = IBEXDEVICELINKDEFS( - OT_EG_SOC_DEVLINK("otp_ctrl", OTP_CTRL), + OT_EG_SOC_DEVLINK("otp-ctrl", OTP_CTRL), OT_EG_SOC_DEVLINK("vmapper", VMAPPER) ), .prop = IBEXDEVICEPROPDEFS( @@ -1204,9 +1204,9 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { OT_EG_SOC_DEVLINK("edn", EDN0), OT_EG_SOC_DEVLINK("flash_ctrl", FLASH_CTRL), OT_EG_SOC_DEVLINK("kmac", KMAC), - OT_EG_SOC_DEVLINK("lc_ctrl", LC_CTRL), + OT_EG_SOC_DEVLINK("lc-ctrl", LC_CTRL), OT_EG_SOC_DEVLINK("otbn", OTBN), - OT_EG_SOC_DEVLINK("otp_ctrl", OTP_CTRL), + OT_EG_SOC_DEVLINK("otp-ctrl", OTP_CTRL), OT_EG_SOC_DEVLINK("rom_ctrl", ROM_CTRL) ), .prop = IBEXDEVICEPROPDEFS( @@ -1229,7 +1229,7 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { ), .link = IBEXDEVICELINKDEFS( OT_EG_SOC_DEVLINK("entropy-src", ENTROPY_SRC), - OT_EG_SOC_DEVLINK("otp_ctrl", OTP_CTRL) + OT_EG_SOC_DEVLINK("otp-ctrl", OTP_CTRL) ), }, [OT_EG_SOC_DEV_ENTROPY_SRC] = { @@ -1247,7 +1247,7 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { ), .link = IBEXDEVICELINKDEFS( OT_EG_SOC_DEVLINK("noise-src", AST), - OT_EG_SOC_DEVLINK("otp_ctrl", OTP_CTRL) + OT_EG_SOC_DEVLINK("otp-ctrl", OTP_CTRL) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_UINT_PROP("version", 2) @@ -1299,7 +1299,7 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { OT_EG_SOC_GPIO_ALERT(0, 59) ), .link = IBEXDEVICELINKDEFS( - OT_EG_SOC_DEVLINK("otp_ctrl", OTP_CTRL), + OT_EG_SOC_DEVLINK("otp-ctrl", OTP_CTRL), OT_EG_SOC_DEVLINK("vmapper", VMAPPER) ), .prop = IBEXDEVICEPROPDEFS( From cf90a32e9e64d44da34503ca91ec812dad49dafb Mon Sep 17 00:00:00 2001 From: Emmanuel Blot Date: Wed, 29 Oct 2025 12:16:08 +0100 Subject: [PATCH 18/18] [ot] .gitlab-ci.d/opentitan: ot-smoke.yml: fix typo for Darjeeling smoke test Introduced in 5d9dfd633 Signed-off-by: Emmanuel Blot --- .gitlab-ci.d/opentitan/ot-smoke.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.d/opentitan/ot-smoke.yml b/.gitlab-ci.d/opentitan/ot-smoke.yml index da4ac2751cf0..21fd36878bf0 100644 --- a/.gitlab-ci.d/opentitan/ot-smoke.yml +++ b/.gitlab-ci.d/opentitan/ot-smoke.yml @@ -11,5 +11,5 @@ smoke-tests-ot: - timeout -s KILL 4 build/qemu-system-riscv32 -M ot-earlgrey,no_epmp_cfg=true -nographic -object ot-rom_img,id=rom,file=build/exit_eg.bin -d in_asm,int - timeout -s KILL 4 build/qemu-system-riscv32 -M ot-darjeeling,no_epmp_cfg=true - -object ot-rom_img,id=rom,file=build/exit_eg.bin -d in_asm,int + -object ot-rom_img,id=rom,file=build/exit_dj.bin -d in_asm,int -nographic -global ot-ibex_wrapper.lc-ignore=on