From a722da1f5c759ba686edd334496a3c89d69543d9 Mon Sep 17 00:00:00 2001 From: Emmanuel Blot Date: Tue, 4 Nov 2025 12:02:57 +0100 Subject: [PATCH 01/24] [ot] hw/opentitan: ot_lc_ctrl: add RMA broadcast signal Note: this signal is not available on EG 1.0.0 and should not be used with this Top. Also add missing ot_id in qemu_log messages. Signed-off-by: Emmanuel Blot --- hw/opentitan/ot_lc_ctrl.c | 98 ++++++++++++++++--------------- include/hw/opentitan/ot_lc_ctrl.h | 1 + 2 files changed, 53 insertions(+), 46 deletions(-) diff --git a/hw/opentitan/ot_lc_ctrl.c b/hw/opentitan/ot_lc_ctrl.c index d6810c4e03351..a8ef6bedea5c7 100644 --- a/hw/opentitan/ot_lc_ctrl.c +++ b/hw/opentitan/ot_lc_ctrl.c @@ -25,8 +25,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * - * Note: for now, only a minimalist subset of Life Cycle controller device is - * implemented in order to enable OpenTitan's ROM boot to progress + * Based on OpenTitan 0fc384d8a6 */ #include "qemu/osdep.h" @@ -58,11 +57,11 @@ #define REVISION_ID_WIDTH 8u /* clang-format off */ -REG32(ALERT_TEST, 0x0u) +REG32(ALERT_TEST, 0x00u) SHARED_FIELD(ALERT_FATAL_PROG_ERROR, 0u, 1u) SHARED_FIELD(ALERT_FATAL_STATE_ERROR, 1u, 1u) SHARED_FIELD(ALERT_FATAL_BUS_INTEG_ERROR, 2u, 1u) -REG32(STATUS, 0x4u) +REG32(STATUS, 0x04u) FIELD(STATUS, INITIALIZED, 0u, 1u) FIELD(STATUS, READY, 1u, 1u) FIELD(STATUS, EXT_CLOCK_SWITCHED, 2u, 1u) @@ -75,10 +74,10 @@ REG32(STATUS, 0x4u) FIELD(STATUS, STATE_ERROR, 9u, 1u) FIELD(STATUS, BUS_INTEG_ERROR, 10u, 1u) FIELD(STATUS, OTP_PARTITION_ERROR, 11u, 1u) -REG32(CLAIM_TRANSITION_IF_REGWEN, 0x8u) +REG32(CLAIM_TRANSITION_IF_REGWEN, 0x08u) FIELD(CLAIM_TRANSITION_IF_REGWEN, EN, 0u, 1u) -REG32(CLAIM_TRANSITION_IF, 0xcu) - FIELD(CLAIM_TRANSITION, IF_MUTEX, 0u, 8u) +REG32(CLAIM_TRANSITION_IF, 0x0cu) + FIELD(CLAIM_TRANSITION_IF, MUTEX, 0u, 8u) REG32(TRANSITION_REGWEN, 0x10u) FIELD(TRANSITION_REGWEN, EN, 0u, 1u) REG32(TRANSITION_CMD, 0x14u) @@ -125,6 +124,13 @@ REG32(MANUF_STATE_6, 0x84u) REG32(MANUF_STATE_7, 0x88u) /* clang-format on */ +#define ALERT_TEST_WMASK \ + (ALERT_FATAL_PROG_ERROR_MASK | ALERT_FATAL_STATE_ERROR_MASK | \ + ALERT_FATAL_BUS_INTEG_ERROR_MASK) +#define TRANSITION_CTRL_WMASK \ + (TRANSITION_CTRL_EXT_CLOCK_EN_MASK | \ + TRANSITION_CTRL_VOLATILE_RAW_UNLOCK_MASK) + #define R32_OFF(_r_) ((_r_) / sizeof(uint32_t)) #define R_LAST_REG (R_MANUF_STATE_7) @@ -138,10 +144,6 @@ REG32(MANUF_STATE_7, 0x88u) #define EXCLUSIVE_REGS_COUNT (R_LAST_EXCLUSIVE_REG - R_FIRST_EXCLUSIVE_REG + 1u) #define XREGS_OFFSET(_r_) ((_r_) - R_FIRST_EXCLUSIVE_REG) -#define ALERT_TEST_MASK \ - (ALERT_FATAL_PROG_ERROR_MASK | ALERT_FATAL_STATE_ERROR_MASK | \ - ALERT_FATAL_BUS_INTEG_ERROR_MASK) - #define LC_TRANSITION_COUNT_MAX 24u #define LC_TOKEN_WIDTH 16u /* 128 bits */ #define LC_TOKEN_DWORDS (LC_TOKEN_WIDTH / sizeof(uint64_t)) @@ -708,7 +710,7 @@ LC_STATES_TPL[NUM_LC_STATE][LC_STATE_WORDS] = { #ifdef OT_LC_CTRL_DEBUG #define OT_LC_CTRL_HEXSTR_SIZE 256u #define TRACE_LC_CTRL(msg, ...) \ - qemu_log("%s: " msg "\n", __func__, ##__VA_ARGS__); + qemu_log("%s: %s: " msg "\n", __func__, s->ot_id, ##__VA_ARGS__); #define ot_lc_ctrl_hexdump(_s_, _b_, _l_) \ ot_common_lhexdump((const uint8_t *)_b_, _l_, false, (_s_)->hexstr, \ OT_LC_CTRL_HEXSTR_SIZE) @@ -823,15 +825,16 @@ static void ot_lc_ctrl_update_broadcast(OtLcCtrlState *s) div_type = LC_DIV_DEV; break; case LC_STATE_RMA: - sigbm = - LC_BCAST_BIT(RAW_TEST_RMA) | LC_BCAST_BIT(DFT_EN) | - LC_BCAST_BIT(NVM_DEBUG_EN) | LC_BCAST_BIT(HW_DEBUG_EN) | - LC_BCAST_BIT(CPU_EN) | LC_BCAST_BIT(KEYMGR_EN) | - LC_BCAST_BIT(CHECK_BYP_EN) | - LC_BCAST_BIT(CREATOR_SEED_SW_RW_EN) | - LC_BCAST_BIT(OWNER_SEED_SW_RW_EN) | - LC_BCAST_BIT(ISO_PART_SW_RD_EN) | - LC_BCAST_BIT(ISO_PART_SW_WR_EN) | LC_BCAST_BIT(SEED_HW_RD_EN); + /* note: RMA signal not available on EG 1.0.0 */ + sigbm = LC_BCAST_BIT(RAW_TEST_RMA) | LC_BCAST_BIT(DFT_EN) | + LC_BCAST_BIT(NVM_DEBUG_EN) | LC_BCAST_BIT(HW_DEBUG_EN) | + LC_BCAST_BIT(CPU_EN) | LC_BCAST_BIT(KEYMGR_EN) | + LC_BCAST_BIT(CHECK_BYP_EN) | + LC_BCAST_BIT(CREATOR_SEED_SW_RW_EN) | + LC_BCAST_BIT(OWNER_SEED_SW_RW_EN) | + LC_BCAST_BIT(ISO_PART_SW_RD_EN) | + LC_BCAST_BIT(ISO_PART_SW_WR_EN) | + LC_BCAST_BIT(SEED_HW_RD_EN) | LC_BCAST_BIT(RMA); div_type = LC_DIV_RMA; break; case LC_STATE_SCRAP: @@ -1301,8 +1304,8 @@ static void ot_lc_ctrl_program_otp(OtLcCtrlState *s, unsigned lc_tcount, if (!oc->program_req) { qemu_log_mask(LOG_UNIMP, - "%s: OTP implementation does not support programming", - __func__); + "%s: %s: OTP implementation does not support programming", + __func__, s->ot_id); s->regs[R_STATUS] |= R_STATUS_OTP_ERROR_MASK; LC_FSM_CHANGE_STATE(s, ST_POST_TRANS); s->lc_state = LC_STATE_POST_TRANSITION; @@ -1765,13 +1768,14 @@ static uint32_t ot_lc_ctrl_regs_read(OtLcCtrlState *s, hwaddr addr, break; case R_ALERT_TEST: qemu_log_mask(LOG_GUEST_ERROR, - "%s: W/O register 0x%02" HWADDR_PRIx " (%s)\n", __func__, - addr, REG_NAME(reg)); + "%s: %s: W/O register 0x%02" HWADDR_PRIx " (%s)\n", + __func__, s->ot_id, addr, REG_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%" HWADDR_PRIx "\n", __func__, + s->ot_id, addr); val32 = 0; break; } @@ -1819,7 +1823,7 @@ static void ot_lc_ctrl_regs_write(OtLcCtrlState *s, hwaddr addr, uint32_t val32, switch (reg) { case R_ALERT_TEST: - val32 &= ALERT_TEST_MASK; + val32 &= ALERT_TEST_WMASK; s->regs[R_ALERT_TEST] = val32; ot_lc_ctrl_update_alerts(s); break; @@ -1830,8 +1834,9 @@ static void ot_lc_ctrl_regs_write(OtLcCtrlState *s, hwaddr addr, uint32_t val32, case R_CLAIM_TRANSITION_IF: if (!(s->regs[R_CLAIM_TRANSITION_IF_REGWEN] & R_CLAIM_TRANSITION_IF_REGWEN_EN_MASK)) { - qemu_log_mask(LOG_GUEST_ERROR, "%s: CLAIM_TRANSITION_IF disabled\n", - __func__); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: %s: CLAIM_TRANSITION_IF disabled\n", __func__, + s->ot_id); break; } val32 &= R_CLAIM_TRANSITION_IF_MUTEX_MASK; @@ -1845,8 +1850,8 @@ static void ot_lc_ctrl_regs_write(OtLcCtrlState *s, hwaddr addr, uint32_t val32, val32 &= R_TRANSITION_CMD_START_MASK; if (val32) { if (!ot_lc_ctrl_is_transition_en(s, ifreq)) { - qemu_log_mask(LOG_GUEST_ERROR, "%s: LC IF not available\n", - __func__); + qemu_log_mask(LOG_GUEST_ERROR, "%s: %s: LC IF not available\n", + __func__, s->ot_id); break; } ot_lc_ctrl_start_transition(s); @@ -1854,8 +1859,8 @@ static void ot_lc_ctrl_regs_write(OtLcCtrlState *s, hwaddr addr, uint32_t val32, break; case R_TRANSITION_CTRL: if (!ot_lc_ctrl_is_transition_en(s, ifreq)) { - qemu_log_mask(LOG_GUEST_ERROR, "%s: LC IF not available\n", - __func__); + qemu_log_mask(LOG_GUEST_ERROR, "%s: %s: LC IF not available\n", + __func__, s->ot_id); break; } if (val32 & R_TRANSITION_CTRL_EXT_CLOCK_EN_MASK) { @@ -1874,8 +1879,8 @@ static void ot_lc_ctrl_regs_write(OtLcCtrlState *s, hwaddr addr, uint32_t val32, case R_TRANSITION_TOKEN_2: case R_TRANSITION_TOKEN_3: if (!ot_lc_ctrl_is_transition_en(s, ifreq)) { - qemu_log_mask(LOG_GUEST_ERROR, "%s: LC IF not available\n", - __func__); + qemu_log_mask(LOG_GUEST_ERROR, "%s: %s: LC IF not available\n", + __func__, s->ot_id); break; } g_assert(LC_XSLOT(ifreq) < EXCLUSIVE_SLOTS_COUNT); @@ -1883,8 +1888,8 @@ static void ot_lc_ctrl_regs_write(OtLcCtrlState *s, hwaddr addr, uint32_t val32, break; case R_TRANSITION_TARGET: if (!ot_lc_ctrl_is_transition_en(s, ifreq)) { - qemu_log_mask(LOG_GUEST_ERROR, "%s: LC IF not available\n", - __func__); + qemu_log_mask(LOG_GUEST_ERROR, "%s: %s: LC IF not available\n", + __func__, s->ot_id); break; } val32 &= R_TRANSITION_TARGET_STATE_MASK; @@ -1895,8 +1900,8 @@ static void ot_lc_ctrl_regs_write(OtLcCtrlState *s, hwaddr addr, uint32_t val32, break; case R_OTP_VENDOR_TEST_CTRL: if (!ot_lc_ctrl_is_transition_en(s, ifreq)) { - qemu_log_mask(LOG_GUEST_ERROR, "%s: LC IF not available\n", - __func__); + qemu_log_mask(LOG_GUEST_ERROR, "%s: %s: LC IF not available\n", + __func__, s->ot_id); break; } s->regs[reg] = val32; @@ -1926,12 +1931,13 @@ static void ot_lc_ctrl_regs_write(OtLcCtrlState *s, hwaddr addr, uint32_t val32, case R_MANUF_STATE_6: case R_MANUF_STATE_7: qemu_log_mask(LOG_GUEST_ERROR, - "%s: R/O register 0x%02" HWADDR_PRIx " (%s)\n", __func__, - addr, REG_NAME(reg)); + "%s: %s: R/O register 0x%02" HWADDR_PRIx " (%s)\n", + __func__, s->ot_id, addr, REG_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: %s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, + s->ot_id, addr); break; } }; @@ -1997,7 +2003,7 @@ static void ot_lc_ctrl_load_transitions(OtLcCtrlState *s, len = strlen(s->trans_cfg[trans].state[ix]); /* each byte is encoding with two ASCII nibbles */ if (len != tdesc->word_count * sizeof(uint16_t) * 2u) { - qemu_log("%s %s %s %zu %zu\n", __func__, tdesc->name, + qemu_log("%s: %s: %s %s %zu %zu\n", __func__, s->ot_id, tdesc->name, TSTATE_NAME(ix), len, tdesc->word_count * sizeof(uint16_t)); error_setg(&err, "%s: %s invalid %s %s length\n", __func__, @@ -2101,7 +2107,7 @@ static void ot_lc_ctrl_configure_transitions( /* dump the generated transition tables */ lcval = table; for (unsigned tix = 0; tix < tdesc->step_count; tix++) { - qemu_log("%s: %s[%2u]", __func__, tdesc->name, tix); + qemu_log("%s: %s: %s[%2u]", __func__, s->ot_id, tdesc->name, tix); for (unsigned wix = 0; wix < tdesc->word_count; wix++) { qemu_log(" %04hx", *lcval++); }; diff --git a/include/hw/opentitan/ot_lc_ctrl.h b/include/hw/opentitan/ot_lc_ctrl.h index c620ce787c2b8..c837cbe0d95a5 100644 --- a/include/hw/opentitan/ot_lc_ctrl.h +++ b/include/hw/opentitan/ot_lc_ctrl.h @@ -57,6 +57,7 @@ typedef enum { OT_LC_ISO_PART_SW_RD_EN, /* for embed. flash, not used in DJ */ OT_LC_ISO_PART_SW_WR_EN, /* for embed. flash, not used in DJ */ OT_LC_SEED_HW_RD_EN, /* for OTP and embed. flash */ + OT_LC_RMA, /* RMA state */ OT_LC_BROADCAST_COUNT, } OtLcCtrlBroadcast; From 58465ebcef33fe525efe4c9ece544672e6231b57 Mon Sep 17 00:00:00 2001 From: Emmanuel Blot Date: Fri, 7 Nov 2025 11:14:27 +0100 Subject: [PATCH 02/24] [ot] hw/opentitan: ot_lc_ctrl: rename SOCDBG as SOC_DBG to match new HW Signed-off-by: Emmanuel Blot --- hw/opentitan/ot_lc_ctrl.c | 62 +++++++++++++++---------------- hw/opentitan/trace-events | 2 +- include/hw/opentitan/ot_lc_ctrl.h | 6 ++- 3 files changed, 36 insertions(+), 34 deletions(-) diff --git a/hw/opentitan/ot_lc_ctrl.c b/hw/opentitan/ot_lc_ctrl.c index a8ef6bedea5c7..a2abfcbf9bd87 100644 --- a/hw/opentitan/ot_lc_ctrl.c +++ b/hw/opentitan/ot_lc_ctrl.c @@ -39,7 +39,6 @@ #include "hw/opentitan/ot_lc_ctrl.h" #include "hw/opentitan/ot_otp_if.h" #include "hw/opentitan/ot_pwrmgr.h" -#include "hw/opentitan/ot_socdbg_ctrl.h" #include "hw/qdev-properties.h" #include "hw/registerfields.h" #include "hw/riscv/ibex_common.h" @@ -194,18 +193,18 @@ static const char *REG_NAMES[REGS_COUNT] = { #define NUM_LC_STATE (LC_STATE_VALID_COUNT) #define NUM_LC_TRANSITION_COUNT 25u #define NUM_OWNERSHIP 9u -#define NUM_SOCDBG 3u +#define NUM_SOC_DBG 3u #define LC_TRANSITION_COUNT_WORDS 24u #define LC_STATE_WORDS 20u #define OWNERSHIP_WORDS 8u -#define SOCDBG_WORDS 2u +#define SOC_DBG_WORDS 2u #define LC_TRANSITION_COUNT_BYTES \ ((LC_TRANSITION_COUNT_WORDS) / sizeof(uint16_t)) #define LC_STATE_BYTES ((LC_STATE_WORDS) / sizeof(uint16_t)) #define OWNERSHIP_SIZE ((OWNERSHIP_WORDS) / sizeof(uint16_t)) -#define SOCDBG_SIZE ((SOCDBG_WORDS) / sizeof(uint16_t)) +#define SOC_DBG_SIZE ((SOC_DBG_WORDS) / sizeof(uint16_t)) #define LC_STATE_BIT_WIDTH 5u #define LC_ENCODE_STATE(_x_) \ @@ -281,7 +280,7 @@ typedef enum { typedef uint16_t OtLcCtrlStateValue[LC_STATE_WORDS]; typedef uint16_t OtLcCtrlTransitionCountValue[LC_TRANSITION_COUNT_WORDS]; typedef uint16_t OtLcCtrlOwnershipValue[OWNERSHIP_WORDS]; -typedef uint16_t OtLcCtrlSocDbgValue[SOCDBG_WORDS]; +typedef uint16_t OtLcCtrlSocDbgValue[SOC_DBG_WORDS]; typedef enum { LC_IF_NONE, @@ -355,7 +354,7 @@ typedef enum { LC_CTRL_TRANS_LC_STATE, LC_CTRL_TRANS_LC_TCOUNT, LC_CTRL_TRANS_OWNERSHIP, - LC_CTRL_TRANS_SOCDBG, + LC_CTRL_TRANS_SOC_DBG, LC_CTRL_TRANS_COUNT } OtLcCtrlTransition; @@ -380,7 +379,7 @@ struct OtLcCtrlState { IbexIRQ alerts[NUM_ALERTS]; IbexIRQ broadcasts[OT_LC_BROADCAST_COUNT]; IbexIRQ pwc_lc_rsp; - IbexIRQ socdbg_tx; + IbexIRQ soc_dbg_tx; uint32_t *regs; /* slots in xregs are not used in regs */ uint32_t xregs[EXCLUSIVE_SLOTS_COUNT][EXCLUSIVE_REGS_COUNT]; @@ -394,7 +393,7 @@ struct OtLcCtrlState { OtLcCtrlStateValue *lc_states; OtLcCtrlTransitionCountValue *lc_transitions; OtLcCtrlOwnershipValue *ownerships; - OtLcCtrlSocDbgValue *socdbgs; + OtLcCtrlSocDbgValue *soc_dbgs; OtOTPTokenValue *hashed_tokens; uint8_t km_divs[LC_DIV_COUNT][OT_LC_KEYMGR_DIV_BYTES]; @@ -422,7 +421,7 @@ struct OtLcCtrlState { uint8_t revision_id; uint8_t kmac_app; bool volatile_raw_unlock; - bool socdbg; /* whether this instance use SoCDbg state */ + bool soc_dbg; /* whether this instance use SoCDbg state */ }; /* try to cope with the many ways to encode a transition matrix */ @@ -556,11 +555,11 @@ static const OtLcCtrlTransitionDesc TRANSITION_DESC[LC_CTRL_TRANS_COUNT] = { .mode = LC_TR_MODE_FIRST_FULL, .name = "ownership", }, - [LC_CTRL_TRANS_SOCDBG] = { - .word_count = SOCDBG_WORDS, - .step_count = NUM_SOCDBG, + [LC_CTRL_TRANS_SOC_DBG] = { + .word_count = SOC_DBG_WORDS, + .step_count = NUM_SOC_DBG, .mode = LC_TR_MODE_FULL_CHANGE, - .name = "socdbg", + .name = "soc_dbg", }, }; @@ -1231,31 +1230,31 @@ static void ot_lc_ctrl_load_otp_hw_cfg(OtLcCtrlState *s) memcpy(&s->regs[R_MANUF_STATE_0], &hw_cfg->manuf_state[0], LC_MANUF_STATE_WIDTH); - if (!s->socdbg) { + if (!s->soc_dbg) { return; } /* default to lowest capabilities */ - int socdbg_ix = OT_SOCDBG_ST_PROD; + int soc_dbg_ix = OT_LC_SOC_DBG_STATE_COUNT - 1u; TRACE_LC_CTRL("soc_dbg_state: %s", ot_lc_ctrl_hexdump(s, hw_cfg->soc_dbg_state, sizeof(OtLcCtrlSocDbgValue))); - for (unsigned six = 0; six < OT_SOCDBG_ST_COUNT; six++) { - bool match = !memcmp(hw_cfg->soc_dbg_state, s->socdbgs[six], + for (unsigned six = 0; six < OT_LC_SOC_DBG_STATE_COUNT; six++) { + bool match = !memcmp(hw_cfg->soc_dbg_state, s->soc_dbgs[six], sizeof(OtLcCtrlSocDbgValue)); TRACE_LC_CTRL("soc_dbg ref[%u]: %s, match: %u", six, - ot_lc_ctrl_hexdump(s, s->socdbgs[six], + ot_lc_ctrl_hexdump(s, s->soc_dbgs[six], sizeof(OtLcCtrlSocDbgValue)), match); if (match) { - socdbg_ix = (int)six; + soc_dbg_ix = (int)six; break; } } - ibex_irq_set(&s->socdbg_tx, socdbg_ix); + ibex_irq_set(&s->soc_dbg_tx, soc_dbg_ix); } static void ot_lc_ctrl_handle_otp_ack(void *opaque, bool ack) @@ -2182,11 +2181,11 @@ static Property ot_lc_ctrl_properties[] = { DEFINE_PROP_STRING("ownership_last", OtLcCtrlState, trans_cfg[LC_CTRL_TRANS_OWNERSHIP] .state[LC_CTRL_TSTATE_LAST]), - DEFINE_PROP_STRING("socdbg_first", OtLcCtrlState, - trans_cfg[LC_CTRL_TRANS_SOCDBG] + DEFINE_PROP_STRING("soc_dbg_first", OtLcCtrlState, + trans_cfg[LC_CTRL_TRANS_SOC_DBG] .state[LC_CTRL_TSTATE_FIRST]), - DEFINE_PROP_STRING("socdbg_last", OtLcCtrlState, - trans_cfg[LC_CTRL_TRANS_SOCDBG] + DEFINE_PROP_STRING("soc_dbg_last", OtLcCtrlState, + trans_cfg[LC_CTRL_TRANS_SOC_DBG] .state[LC_CTRL_TSTATE_LAST]), DEFINE_PROP_UINT16("silicon_creator_id", OtLcCtrlState, silicon_creator_id, 0), @@ -2194,7 +2193,7 @@ static Property ot_lc_ctrl_properties[] = { DEFINE_PROP_UINT8("revision_id", OtLcCtrlState, revision_id, 0), DEFINE_PROP_BOOL("volatile_raw_unlock", OtLcCtrlState, volatile_raw_unlock, true), - DEFINE_PROP_BOOL("socdbg", OtLcCtrlState, socdbg, false), + DEFINE_PROP_BOOL("soc-dbg", OtLcCtrlState, soc_dbg, false), DEFINE_PROP_UINT8("kmac-app", OtLcCtrlState, kmac_app, UINT8_MAX), DEFINE_PROP_END_OF_LIST(), }; @@ -2315,9 +2314,9 @@ static void ot_lc_ctrl_realize(DeviceState *dev, Error **errp) (uint16_t *)s->lc_transitions); ot_lc_ctrl_configure_transitions(s, LC_CTRL_TRANS_OWNERSHIP, (uint16_t *)s->ownerships); - if (s->socdbg) { - ot_lc_ctrl_configure_transitions(s, LC_CTRL_TRANS_SOCDBG, - (uint16_t *)s->socdbgs); + if (s->soc_dbg) { + ot_lc_ctrl_configure_transitions(s, LC_CTRL_TRANS_SOC_DBG, + (uint16_t *)s->soc_dbgs); } ot_lc_ctrl_configure_km_div(s); ot_lc_ctrl_compute_predefined_tokens(s); @@ -2340,7 +2339,7 @@ static void ot_lc_ctrl_init(Object *obj) s->lc_transitions = g_new0(OtLcCtrlTransitionCountValue, NUM_LC_TRANSITION_COUNT); s->ownerships = g_new0(OtLcCtrlOwnershipValue, NUM_OWNERSHIP); - s->socdbgs = g_new0(OtLcCtrlSocDbgValue, NUM_SOCDBG); + s->soc_dbgs = g_new0(OtLcCtrlSocDbgValue, NUM_SOC_DBG); s->hashed_tokens = g_new0(OtOTPTokenValue, LC_TK_COUNT); for (unsigned ix = 0; ix < ARRAY_SIZE(s->alerts); ix++) { @@ -2352,8 +2351,9 @@ static void ot_lc_ctrl_init(Object *obj) } ibex_qdev_init_irq(obj, &s->pwc_lc_rsp, OT_PWRMGR_LC_RSP); - ibex_qdev_init_irq_default(obj, &s->socdbg_tx, OT_LC_CTRL_SOCDBG, - OT_SOCDBG_ST_COUNT); + ibex_qdev_init_irq_default(obj, &s->soc_dbg_tx, OT_LC_SOC_DBG, + /* initialize with an invalid level */ + OT_LC_SOC_DBG_STATE_COUNT); qdev_init_gpio_in_named(DEVICE(obj), &ot_lc_ctrl_pwr_lc_req, OT_PWRMGR_LC_REQ, 1); diff --git a/hw/opentitan/trace-events b/hw/opentitan/trace-events index 0a9fdb940a248..5c4c524915417 100644 --- a/hw/opentitan/trace-events +++ b/hw/opentitan/trace-events @@ -367,7 +367,7 @@ ot_lc_ctrl_io_read_out_repeat(const char * id, uint32_t addr, const char * regna ot_lc_ctrl_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_lc_ctrl_km_div_missing(const char * id, unsigned ix) "%s: #%u" ot_lc_ctrl_load_lc_info_force_raw(const char * id) "%s: force_raw enabled" -ot_lc_ctrl_load_otp_hw_cfg(const char * id, const char *socdbg) "%s: socdbg_state: %s" +ot_lc_ctrl_load_otp_hw_cfg(const char * id, const char *soc_dbg) "%s: soc_dbg_state: %s" ot_lc_ctrl_load_otp_token(const char * id, const char *tk, unsigned tkix, const char *inv, uint64_t hi, uint64_t lo) "%s: token %s (%u) %svalid: 0x%016" PRIx64 "%016" PRIx64 ot_lc_ctrl_mismatch_token(const char * id, const char *tkkind, const char *tkname, unsigned tok, uint64_t htkhi, uint64_t htklo, uint64_t rtkhi, uint64_t rtklo) "%s: %s token %s (%u): 0x%016" PRIx64 "%016" PRIx64 ", ref 0x%016" PRIx64 "%016" PRIx64 ot_lc_ctrl_pwr_lc_req(const char * id, const char *where) "%s: %s" diff --git a/include/hw/opentitan/ot_lc_ctrl.h b/include/hw/opentitan/ot_lc_ctrl.h index c837cbe0d95a5..8b8ec6ad1993c 100644 --- a/include/hw/opentitan/ot_lc_ctrl.h +++ b/include/hw/opentitan/ot_lc_ctrl.h @@ -39,8 +39,8 @@ OBJECT_DECLARE_TYPE(OtLcCtrlState, OtLcCtrlClass, OT_LC_CTRL) #define OT_LC_A0_FORCE_RAW TYPE_OT_LC_CTRL "-a0-force-raw" /* output lines */ -#define OT_LC_BROADCAST TYPE_OT_LC_CTRL "-broadcast" -#define OT_LC_CTRL_SOCDBG TYPE_OT_LC_CTRL "-socdbg" +#define OT_LC_BROADCAST TYPE_OT_LC_CTRL "-broadcast" +#define OT_LC_SOC_DBG TYPE_OT_LC_CTRL "-soc-dbg" /* Life cycle broadcast signals (booleans) */ typedef enum { @@ -63,6 +63,8 @@ typedef enum { #define OT_LC_KEYMGR_DIV_BYTES 16u /* 128 bits */ +#define OT_LC_SOC_DBG_STATE_COUNT 3u + typedef struct { uint8_t data[OT_LC_KEYMGR_DIV_BYTES]; } OtLcCtrlKeyMgrDiv; From 37e44a6a2c89bdaa744f86b25e2463ee7e0fe8ac Mon Sep 17 00:00:00 2001 From: Emmanuel Blot Date: Fri, 7 Nov 2025 11:18:31 +0100 Subject: [PATCH 03/24] [ot] hw/opentitan: ot_lc_ctrl: rename soc_dbg property Signed-off-by: Emmanuel Blot --- hw/opentitan/ot_lc_ctrl.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/opentitan/ot_lc_ctrl.c b/hw/opentitan/ot_lc_ctrl.c index a2abfcbf9bd87..92a2aa122fe06 100644 --- a/hw/opentitan/ot_lc_ctrl.c +++ b/hw/opentitan/ot_lc_ctrl.c @@ -421,7 +421,7 @@ struct OtLcCtrlState { uint8_t revision_id; uint8_t kmac_app; bool volatile_raw_unlock; - bool soc_dbg; /* whether this instance use SoCDbg state */ + bool decode_soc_dbg; /* whether to handle SoCDbg state */ }; /* try to cope with the many ways to encode a transition matrix */ @@ -1230,7 +1230,7 @@ static void ot_lc_ctrl_load_otp_hw_cfg(OtLcCtrlState *s) memcpy(&s->regs[R_MANUF_STATE_0], &hw_cfg->manuf_state[0], LC_MANUF_STATE_WIDTH); - if (!s->soc_dbg) { + if (!s->decode_soc_dbg) { return; } @@ -2193,7 +2193,7 @@ static Property ot_lc_ctrl_properties[] = { DEFINE_PROP_UINT8("revision_id", OtLcCtrlState, revision_id, 0), DEFINE_PROP_BOOL("volatile_raw_unlock", OtLcCtrlState, volatile_raw_unlock, true), - DEFINE_PROP_BOOL("soc-dbg", OtLcCtrlState, soc_dbg, false), + DEFINE_PROP_BOOL("decode_soc_dbg", OtLcCtrlState, decode_soc_dbg, false), DEFINE_PROP_UINT8("kmac-app", OtLcCtrlState, kmac_app, UINT8_MAX), DEFINE_PROP_END_OF_LIST(), }; @@ -2314,7 +2314,7 @@ static void ot_lc_ctrl_realize(DeviceState *dev, Error **errp) (uint16_t *)s->lc_transitions); ot_lc_ctrl_configure_transitions(s, LC_CTRL_TRANS_OWNERSHIP, (uint16_t *)s->ownerships); - if (s->soc_dbg) { + if (s->decode_soc_dbg) { ot_lc_ctrl_configure_transitions(s, LC_CTRL_TRANS_SOC_DBG, (uint16_t *)s->soc_dbgs); } From 4d21a402f0bfbdf9c57f5e58fb17d8466a840037 Mon Sep 17 00:00:00 2001 From: Emmanuel Blot Date: Fri, 7 Nov 2025 10:52:46 +0100 Subject: [PATCH 04/24] [ot] hw/opentitan: ot_lc_ctrl: add new API to retrieve soc debug state code Signed-off-by: Emmanuel Blot --- hw/opentitan/ot_lc_ctrl.c | 36 +++++++++++++++++++++++++++++++ include/hw/opentitan/ot_lc_ctrl.h | 11 ++++++++++ 2 files changed, 47 insertions(+) diff --git a/hw/opentitan/ot_lc_ctrl.c b/hw/opentitan/ot_lc_ctrl.c index 92a2aa122fe06..04b5208c171f1 100644 --- a/hw/opentitan/ot_lc_ctrl.c +++ b/hw/opentitan/ot_lc_ctrl.c @@ -2150,6 +2150,41 @@ static void ot_lc_ctrl_get_keymgr_div(const OtLcCtrlState *s, memcpy(&div->data[0], s->km_divs[s->km_div_type], OT_LC_KEYMGR_DIV_BYTES); } +static uint32_t +ot_lc_ctrl_get_soc_dbg_state(const OtLcCtrlState *s, unsigned state) +{ + g_assert(s->decode_soc_dbg); + + /* + * SoC debug controller is signalled with the OT_LC_CTRL_SOC_DBG interrupt + * line, with the decoded SoC debug state (OtSoCDbgState). In C code, this + * is defined as an enumeration. Valid constant values are initialized with + * the "soc_dbg_first" and "soc_dbg_last" properties and generated in + * #ot_lc_ctrl_configure_transitions. The encoded OTP values are loaded in + * #ot_lc_ctrl_load_otp_hw_cfg and decoded, if valid, into a OtSoCDbgState + * enumerated value. This feature is not deeply related to LC controller + * which only handles the Top-dependent SoC debug state value matrix and + * forward them to the Soc Debug Controller. + * However, the Soc Debug Controller now needs to expose the actual OTP + * encoded values onbly for debug purposes. + * This function converts back a OtSoCDbgState value into its actual + * top-specific encoding. + */ + uint32_t code; + + if (state < OT_LC_SOC_DBG_STATE_COUNT) { + code = (uint32_t)s->soc_dbgs[state][0u] | + ((uint32_t)s->soc_dbgs[state][1u]) << 16u; + } else { + error_report("%s: %s: unsupported Soc Dbg state %u", __func__, s->ot_id, + state); + code = UINT32_MAX; + } + + return code; +} + + 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_IF, @@ -2385,6 +2420,7 @@ static void ot_lc_ctrl_class_init(ObjectClass *klass, void *data) &lc->parent_phases); lc->get_keymgr_div = &ot_lc_ctrl_get_keymgr_div; + lc->get_soc_dbg_state = &ot_lc_ctrl_get_soc_dbg_state; } static const TypeInfo ot_lc_ctrl_info = { diff --git a/include/hw/opentitan/ot_lc_ctrl.h b/include/hw/opentitan/ot_lc_ctrl.h index 8b8ec6ad1993c..6b733cd2c67f5 100644 --- a/include/hw/opentitan/ot_lc_ctrl.h +++ b/include/hw/opentitan/ot_lc_ctrl.h @@ -76,10 +76,21 @@ struct OtLcCtrlClass { /* * Retrieve key manager diversification value. * + * @s the LC controller instance * @div a pointer to a structure that will be filled with the key manager * diversification data. */ void (*get_keymgr_div)(const OtLcCtrlState *s, OtLcCtrlKeyMgrDiv *div); + + /* + * Expose SoC debug state value + * + * @s the LC controller instance + * @state the soc debug state index to obtain the code for + * @return LC soc debug state value or UINT32_MAX if the value of the state + * is unknown + */ + uint32_t (*get_soc_dbg_state)(const OtLcCtrlState *s, unsigned state); }; #endif /* HW_OPENTITAN_OT_LC_CTRL_H */ From d36f37f16a31590c725b62cb1efcbd05d3f04166 Mon Sep 17 00:00:00 2001 From: Emmanuel Blot Date: Fri, 7 Nov 2025 11:25:47 +0100 Subject: [PATCH 05/24] [ot] hw/opentitan: ot_pwrmgr: rename `irq` in ROM handlers Avoid using single var name and match other handlers. Signed-off-by: Emmanuel Blot --- hw/opentitan/ot_pwrmgr.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/hw/opentitan/ot_pwrmgr.c b/hw/opentitan/ot_pwrmgr.c index 9e74a4a66e790..a8dc79763209c 100644 --- a/hw/opentitan/ot_pwrmgr.c +++ b/hw/opentitan/ot_pwrmgr.c @@ -472,30 +472,30 @@ static void ot_pwrmgr_cdc_sync(void *opaque) s->regs[R_CFG_CDC_SYNC] &= ~R_CFG_CDC_SYNC_SYNC_MASK; } -static void ot_pwrmgr_rom_good(void *opaque, int n, int level) +static void ot_pwrmgr_rom_good(void *opaque, int irq, int level) { OtPwrMgrState *s = opaque; - g_assert((unsigned)n < s->num_rom); + g_assert((unsigned)irq < s->num_rom); - trace_ot_pwrmgr_rom(s->ot_id, n, "good", level); + trace_ot_pwrmgr_rom(s->ot_id, irq, "good", level); if (level) { - s->fsm_events.rom_good |= 1u << n; + s->fsm_events.rom_good |= 1u << irq; ot_pwrmgr_schedule_fsm(s); } } -static void ot_pwrmgr_rom_done(void *opaque, int n, int level) +static void ot_pwrmgr_rom_done(void *opaque, int irq, int level) { OtPwrMgrState *s = opaque; - g_assert((unsigned)n < s->num_rom); + g_assert((unsigned)irq < s->num_rom); - trace_ot_pwrmgr_rom(s->ot_id, n, "done", level); + trace_ot_pwrmgr_rom(s->ot_id, irq, "done", level); if (level) { - s->fsm_events.rom_done |= 1u << n; + s->fsm_events.rom_done |= 1u << irq; ot_pwrmgr_schedule_fsm(s); } } From c92365d7c9e42da9725540a0dafa3c6e04de3b62 Mon Sep 17 00:00:00 2001 From: Emmanuel Blot Date: Fri, 7 Nov 2025 11:28:01 +0100 Subject: [PATCH 06/24] [ot] hw/opentitan: ot_pwrmgr: rename boot status signals to match new HW Signed-off-by: Emmanuel Blot --- hw/opentitan/ot_pwrmgr.c | 8 ++++---- hw/opentitan/ot_socdbg_ctrl.c | 9 ++++----- include/hw/opentitan/ot_pwrmgr.h | 5 ++--- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/hw/opentitan/ot_pwrmgr.c b/hw/opentitan/ot_pwrmgr.c index a8dc79763209c..645e081ddf2b3 100644 --- a/hw/opentitan/ot_pwrmgr.c +++ b/hw/opentitan/ot_pwrmgr.c @@ -644,8 +644,8 @@ static void ot_pwrmgr_fast_fsm_tick(OtPwrMgrState *s) ot_pwrmgr_clock_enable_all(s, true); break; case OT_PWR_FAST_ST_ENABLE_CLOCKS: - s->boot_status.main_ip_clk_en = 1u; - s->boot_status.io_ip_clk_en = 1u; + s->boot_status.main_clk_status = 1u; + s->boot_status.io_clk_status = 1u; ibex_irq_set(&s->boot_st, s->boot_status.i32); PWR_CHANGE_FAST_STATE(s, RELEASE_LC_RST); /* @@ -714,8 +714,8 @@ static void ot_pwrmgr_fast_fsm_tick(OtPwrMgrState *s) } break; case OT_PWR_FAST_ST_DIS_CLKS: - s->boot_status.main_ip_clk_en = 0u; - s->boot_status.io_ip_clk_en = 0u; + s->boot_status.main_clk_status = 0u; + s->boot_status.io_clk_status = 0u; ibex_irq_set(&s->boot_st, s->boot_status.i32); PWR_CHANGE_FAST_STATE(s, RESET_PREP); break; diff --git a/hw/opentitan/ot_socdbg_ctrl.c b/hw/opentitan/ot_socdbg_ctrl.c index bd4feeae7bf8b..6dab39fc4db83 100644 --- a/hw/opentitan/ot_socdbg_ctrl.c +++ b/hw/opentitan/ot_socdbg_ctrl.c @@ -502,15 +502,14 @@ static void ot_socdbg_ctrl_boot_status(void *opaque, int n, int level) g_assert(n == 0); OtPwrMgrBootStatus bs = { .i32 = level }; - trace_ot_socdbg_ctrl_boot_status(s->ot_id, (bool)bs.main_ip_clk_en, - (bool)bs.io_ip_clk_en, (bool)bs.otp_done, + trace_ot_socdbg_ctrl_boot_status(s->ot_id, (bool)bs.main_clk_status, + (bool)bs.io_clk_status, (bool)bs.otp_done, (bool)bs.lc_done, (bool)bs.cpu_fetch_en, bs.rom_done & ROM_MASK, bs.rom_good & ROM_MASK); uint16_t bs_bm = 0; - bs_bm = FIELD_DP16(bs_bm, BOOT_STATUS, MAIN_CLK_STATUS, bs.main_ip_clk_en); - bs_bm = FIELD_DP16(bs_bm, BOOT_STATUS, IO_CLK_STATUS, bs.io_ip_clk_en); - bs_bm = FIELD_DP16(bs_bm, BOOT_STATUS, USB_CLK_STATUS, bs.usb_ip_clk_en); + bs_bm = FIELD_DP16(bs_bm, BOOT_STATUS, MAIN_CLK_STATUS, bs.main_clk_status); + bs_bm = FIELD_DP16(bs_bm, BOOT_STATUS, IO_CLK_STATUS, bs.io_clk_status); bs_bm = FIELD_DP16(bs_bm, BOOT_STATUS, OTP_DONE, bs.otp_done); bs_bm = FIELD_DP16(bs_bm, BOOT_STATUS, LC_DONE, bs.lc_done); bs_bm = diff --git a/include/hw/opentitan/ot_pwrmgr.h b/include/hw/opentitan/ot_pwrmgr.h index beeaa220c45a1..c644777cfa481 100644 --- a/include/hw/opentitan/ot_pwrmgr.h +++ b/include/hw/opentitan/ot_pwrmgr.h @@ -55,9 +55,8 @@ typedef enum { /* Boot status packed as an IRQ */ typedef union { struct { - unsigned main_ip_clk_en:1; - unsigned io_ip_clk_en:1; - unsigned usb_ip_clk_en:1; /* ignored for now */ + unsigned main_clk_status:1u; /* in pwr_clk_rsp_t */ + unsigned io_clk_status:1u; /* in pwr_clk_rsp_t */ unsigned otp_done:1; unsigned lc_done:1; unsigned cpu_fetch_en:1; From a13fe863eea710e47d150d2d9a7e10957db11ddf Mon Sep 17 00:00:00 2001 From: Emmanuel Blot Date: Fri, 7 Nov 2025 13:18:38 +0100 Subject: [PATCH 07/24] [ot] hw/opentitan: ot_pwrmgr: use ROM constants for bitfield widths also remove USB device clock from boot status to follow HW changes Signed-off-by: Emmanuel Blot --- hw/opentitan/ot_pwrmgr.c | 11 ++++++++--- include/hw/opentitan/ot_pwrmgr.h | 20 +++++++++++++------- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/hw/opentitan/ot_pwrmgr.c b/hw/opentitan/ot_pwrmgr.c index 645e081ddf2b3..6ad9dfa972192 100644 --- a/hw/opentitan/ot_pwrmgr.c +++ b/hw/opentitan/ot_pwrmgr.c @@ -211,13 +211,17 @@ typedef union { uint8_t lc_done:1; uint8_t escalate:1; /* escalation from alert handler */ uint8_t holdon_fetch:1; /* custom extension */ - uint8_t rom_good; /* up to 8 ROMs */ - uint8_t rom_done; /* up to 8 ROMs */ + /* clang-format off */ + uint8_t rom_good:OT_PWRMGR_MAX_ROM_COUNT; + uint8_t rom_done:OT_PWRMGR_MAX_ROM_COUNT; + /* clang-format on */ }; } OtPwrMgrEvents; static_assert(sizeof(OtPwrMgrEvents) == sizeof(uint32_t), "Invalid OtPwrMgrEvents definition"); +static_assert(sizeof(OtPwrMgrBootStatus) == sizeof(int), + "Invalid OtPwrMgrBootStatus size"); struct OtPwrMgrState { SysBusDevice parent_obj; @@ -1028,6 +1032,7 @@ static void ot_pwrmgr_reset_enter(Object *obj, ResetType type) s->fsm_events.bitmap = 0; s->fsm_events.holdon_fetch = s->fetch_ctrl; s->boot_status.i32 = 0; + s->boot_status.rom_mask = (1u << s->num_rom) - 1u; ot_pwrmgr_sync_slow_regs(s); PWR_CHANGE_FAST_STATE(s, LOW_POWER); @@ -1073,7 +1078,7 @@ static void ot_pwrmgr_realize(DeviceState *dev, Error **errp) (int)PWRMGR_CONFIG[s->version].reset_count); if (s->num_rom) { - if (s->num_rom > 8u * sizeof(uint8_t)) { + if (s->num_rom > OT_PWRMGR_MAX_ROM_COUNT) { error_setg(&error_fatal, "%s: %s: too many ROMs\n", __func__, s->ot_id); g_assert_not_reached(); diff --git a/include/hw/opentitan/ot_pwrmgr.h b/include/hw/opentitan/ot_pwrmgr.h index c644777cfa481..ec41e2ac0d058 100644 --- a/include/hw/opentitan/ot_pwrmgr.h +++ b/include/hw/opentitan/ot_pwrmgr.h @@ -52,18 +52,24 @@ typedef enum { OT_PWRMGR_WAKEUP_COUNT, } OtPwrMgrWakeup; +#define OT_PWRMGR_MAX_ROM_CTRL_COUNT 3u +#define OT_PWRMGR_MAX_ROM_COUNT (OT_PWRMGR_MAX_ROM_CTRL_COUNT + 1u) + /* Boot status packed as an IRQ */ typedef union { struct { unsigned main_clk_status:1u; /* in pwr_clk_rsp_t */ unsigned io_clk_status:1u; /* in pwr_clk_rsp_t */ - unsigned otp_done:1; - unsigned lc_done:1; - unsigned cpu_fetch_en:1; - unsigned strap_sampled:1; - unsigned light_reset:1; - unsigned rom_done:4; - unsigned rom_good:4; + unsigned otp_done:1u; + unsigned lc_done:1u; + unsigned cpu_fetch_en:1u; + unsigned strap_sampled:1u; + unsigned light_reset:1u; + /* clang-format off */ + unsigned rom_done:OT_PWRMGR_MAX_ROM_COUNT; + unsigned rom_good:OT_PWRMGR_MAX_ROM_COUNT; + unsigned rom_mask:OT_PWRMGR_MAX_ROM_COUNT; + /* clang-format on */ }; int i32; } OtPwrMgrBootStatus; From 14e55cd5a1a3970eb2e205561ac51f8f49a04cf4 Mon Sep 17 00:00:00 2001 From: Emmanuel Blot Date: Fri, 7 Nov 2025 10:34:35 +0100 Subject: [PATCH 08/24] [ot] hw/opentitan: ot_common: add multibit bool bitmask and width definitions Signed-off-by: Emmanuel Blot --- include/hw/opentitan/ot_common.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/include/hw/opentitan/ot_common.h b/include/hw/opentitan/ot_common.h index 8e9824935ada1..3970600f2f1f3 100644 --- a/include/hw/opentitan/ot_common.h +++ b/include/hw/opentitan/ot_common.h @@ -58,18 +58,28 @@ #define OT_MULTIBITBOOL4_TRUE 0x6u #define OT_MULTIBITBOOL4_FALSE 0x9u +#define OT_MULTIBITBOOL4_WIDTH 4u +#define OT_MULTIBITBOOL4_MASK ((1u << OT_MULTIBITBOOL4_WIDTH) - 1u) #define OT_MULTIBITBOOL8_TRUE 0x96u #define OT_MULTIBITBOOL8_FALSE 0x69u +#define OT_MULTIBITBOOL8_WIDTH 8u +#define OT_MULTIBITBOOL8_MASK ((1u << OT_MULTIBITBOOL8_WIDTH) - 1u) #define OT_MULTIBITBOOL12_TRUE 0x696u #define OT_MULTIBITBOOL12_FALSE 0x969u +#define OT_MULTIBITBOOL12_WIDTH 12u +#define OT_MULTIBITBOOL12_MASK ((1u << OT_MULTIBITBOOL12_WIDTH) - 1u) #define OT_MULTIBITBOOL16_TRUE 0x9696u #define OT_MULTIBITBOOL16_FALSE 0x6969u +#define OT_MULTIBITBOOL16_WIDTH 16u +#define OT_MULTIBITBOOL16_MASK ((1u << OT_MULTIBITBOOL16_WIDTH) - 1u) #define OT_MULTIBITBOOL_LC4_TRUE 0xau #define OT_MULTIBITBOOL_LC4_FALSE 0x5u +#define OT_MULTIBITBOOL_LC4_WIDTH 4u +#define OT_MULTIBITBOOL_LC4_MASK ((1u << OT_MULTIBITBOOL_LC4_WIDTH) - 1u) typedef uint8_t ot_mb4_t; typedef uint8_t ot_mb8_t; From 9b79401a0347bdfe60987a48c5565802d9b60764 Mon Sep 17 00:00:00 2001 From: Emmanuel Blot Date: Fri, 7 Nov 2025 10:35:32 +0100 Subject: [PATCH 09/24] [ot] hw/opentitan: ot_soc_dbg_ctrl: rename files from `ot_socdbg_ctrl` to match new HW Signed-off-by: Emmanuel Blot --- docs/opentitan/ot_darjeeling.md | 2 +- docs/opentitan/{ot_socdbg_ctrl.md => ot_soc_dbg_ctrl.md} | 0 hw/opentitan/Kconfig | 2 +- hw/opentitan/meson.build | 2 +- hw/opentitan/{ot_socdbg_ctrl.c => ot_soc_dbg_ctrl.c} | 4 +--- hw/riscv/Kconfig | 2 +- hw/riscv/ot_darjeeling.c | 2 +- .../hw/opentitan/{ot_socdbg_ctrl.h => ot_soc_dbg_ctrl.h} | 6 +++--- 8 files changed, 9 insertions(+), 11 deletions(-) rename docs/opentitan/{ot_socdbg_ctrl.md => ot_soc_dbg_ctrl.md} (100%) rename hw/opentitan/{ot_socdbg_ctrl.c => ot_soc_dbg_ctrl.c} (99%) rename include/hw/opentitan/{ot_socdbg_ctrl.h => ot_soc_dbg_ctrl.h} (94%) diff --git a/docs/opentitan/ot_darjeeling.md b/docs/opentitan/ot_darjeeling.md index 783ce9cdc229e..23b95dc23cc77 100644 --- a/docs/opentitan/ot_darjeeling.md +++ b/docs/opentitan/ot_darjeeling.md @@ -30,7 +30,7 @@ Please check out `hw/opentitan/ot_ref.log` * zero-ization is not yet supported * [RISC-V Debug Module](jtag-dm.md) and Pulp Debug Module * [ROM controller](ot_rom_ctrl.md) -* [SoC debug controller documentation](ot_socdbg_ctrl.md) +* [SoC debug controller documentation](ot_soc_dbg_ctrl.md) * SPI data flash (from QEMU upstream w/ fixes) * [SPI Host controller](ot_spi_host.md) * HW bus config is ignored (SPI mode, speed, ...) diff --git a/docs/opentitan/ot_socdbg_ctrl.md b/docs/opentitan/ot_soc_dbg_ctrl.md similarity index 100% rename from docs/opentitan/ot_socdbg_ctrl.md rename to docs/opentitan/ot_soc_dbg_ctrl.md diff --git a/hw/opentitan/Kconfig b/hw/opentitan/Kconfig index d5bd6b5dc068a..8c1f5c6ae25eb 100644 --- a/hw/opentitan/Kconfig +++ b/hw/opentitan/Kconfig @@ -191,7 +191,7 @@ config OT_SENSOR_EG config OT_SOC_PROXY bool -config OT_SOCDBG_CTRL +config OT_SOC_DBG_CTRL bool config OT_SPI_DEVICE diff --git a/hw/opentitan/meson.build b/hw/opentitan/meson.build index 3acdfbc2ae9ba..48fb5d9e4cccf 100644 --- a/hw/opentitan/meson.build +++ b/hw/opentitan/meson.build @@ -52,7 +52,7 @@ system_ss.add(when: 'CONFIG_OT_ROM_CTRL', if_true: files('ot_rom_ctrl.c', 'ot_ro 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')) system_ss.add(when: 'CONFIG_OT_SOC_PROXY', if_true: files('ot_soc_proxy.c')) -system_ss.add(when: 'CONFIG_OT_SOCDBG_CTRL', if_true: files('ot_socdbg_ctrl.c')) +system_ss.add(when: 'CONFIG_OT_SOC_DBG_CTRL', if_true: files('ot_soc_dbg_ctrl.c')) system_ss.add(when: 'CONFIG_OT_SPI_DEVICE', if_true: files('ot_spi_device.c')) system_ss.add(when: 'CONFIG_OT_SPI_HOST', if_true: files('ot_spi_host.c')) system_ss.add(when: 'CONFIG_OT_SRAM_CTRL', if_true: files('ot_sram_ctrl.c')) diff --git a/hw/opentitan/ot_socdbg_ctrl.c b/hw/opentitan/ot_soc_dbg_ctrl.c similarity index 99% rename from hw/opentitan/ot_socdbg_ctrl.c rename to hw/opentitan/ot_soc_dbg_ctrl.c index 6dab39fc4db83..0d208acd0f70e 100644 --- a/hw/opentitan/ot_socdbg_ctrl.c +++ b/hw/opentitan/ot_soc_dbg_ctrl.c @@ -33,15 +33,13 @@ #include "hw/opentitan/ot_common.h" #include "hw/opentitan/ot_lc_ctrl.h" #include "hw/opentitan/ot_pwrmgr.h" -#include "hw/opentitan/ot_socdbg_ctrl.h" +#include "hw/opentitan/ot_soc_dbg_ctrl.h" #include "hw/qdev-properties.h" #include "hw/registerfields.h" #include "hw/riscv/ibex_common.h" #include "hw/riscv/ibex_gpio.h" #include "hw/riscv/ibex_irq.h" #include "trace.h" -#include "trace/trace-hw_opentitan.h" - /* clang-format off */ diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig index 35722c0a338e7..4eb7e6b76b07c 100644 --- a/hw/riscv/Kconfig +++ b/hw/riscv/Kconfig @@ -53,7 +53,7 @@ config OT_DARJEELING select OT_PWRMGR select OT_RSTMGR select OT_ROM_CTRL - select OT_SOCDBG_CTRL + select OT_SOC_DBG_CTRL select OT_SOC_PROXY select OT_SPI_DEVICE select OT_SPI_HOST diff --git a/hw/riscv/ot_darjeeling.c b/hw/riscv/ot_darjeeling.c index 35458c5eac23c..f54a569aced41 100644 --- a/hw/riscv/ot_darjeeling.c +++ b/hw/riscv/ot_darjeeling.c @@ -64,8 +64,8 @@ #include "hw/opentitan/ot_pwrmgr.h" #include "hw/opentitan/ot_rom_ctrl.h" #include "hw/opentitan/ot_rstmgr.h" +#include "hw/opentitan/ot_soc_dbg_ctrl.h" #include "hw/opentitan/ot_soc_proxy.h" -#include "hw/opentitan/ot_socdbg_ctrl.h" #include "hw/opentitan/ot_spi_device.h" #include "hw/opentitan/ot_spi_host.h" #include "hw/opentitan/ot_sram_ctrl.h" diff --git a/include/hw/opentitan/ot_socdbg_ctrl.h b/include/hw/opentitan/ot_soc_dbg_ctrl.h similarity index 94% rename from include/hw/opentitan/ot_socdbg_ctrl.h rename to include/hw/opentitan/ot_soc_dbg_ctrl.h index 3976dc57327eb..4baca85cd1729 100644 --- a/include/hw/opentitan/ot_socdbg_ctrl.h +++ b/include/hw/opentitan/ot_soc_dbg_ctrl.h @@ -25,8 +25,8 @@ * THE SOFTWARE. */ -#ifndef HW_OPENTITAN_OT_SOCDBG_CTRL_H -#define HW_OPENTITAN_OT_SOCDBG_CTRL_H +#ifndef HW_OPENTITAN_OT_SOC_DBG_CTRL_H +#define HW_OPENTITAN_OT_SOC_DBG_CTRL_H #include "qom/object.h" @@ -56,4 +56,4 @@ typedef enum { #define OT_SOCDBG_DEBUG_POLICY_MASK 0x0fu #define OT_SOCDBG_DEBUG_VALID_MASK 0x80u -#endif /* HW_OPENTITAN_OT_SOCDBG_CTRL_H */ +#endif /* HW_OPENTITAN_OT_SOC_DBG_CTRL_H */ From addf916f176b3b251fd352a076da95e5c8afe189 Mon Sep 17 00:00:00 2001 From: Emmanuel Blot Date: Fri, 7 Nov 2025 11:45:32 +0100 Subject: [PATCH 10/24] [ot] hw/opentitan: ot_soc_dbg_ctrl: rename variable and constants from `ot_socdbg_ctrl` to match new HW Signed-off-by: Emmanuel Blot --- hw/opentitan/ot_soc_dbg_ctrl.c | 303 +++++++++++++------------ hw/opentitan/trace-events | 30 +-- hw/riscv/ot_darjeeling.c | 2 +- include/hw/opentitan/ot_soc_dbg_ctrl.h | 32 +-- 4 files changed, 185 insertions(+), 182 deletions(-) diff --git a/hw/opentitan/ot_soc_dbg_ctrl.c b/hw/opentitan/ot_soc_dbg_ctrl.c index 0d208acd0f70e..c6a6ffe472115 100644 --- a/hw/opentitan/ot_soc_dbg_ctrl.c +++ b/hw/opentitan/ot_soc_dbg_ctrl.c @@ -83,11 +83,11 @@ REG16(BOOT_STATUS, 0x0) FIELD(BOOT_STATUS, ROM_CTRL_GOOD, 8u, 3u) FIELD(BOOT_STATUS, CPU_FETCH_EN, 11u, 1u) -/* socdbg_bm fields */ -REG16(SOCDBG, 0x0) - FIELD(SOCDBG, A0_DEBUG, 0u, 1u) - FIELD(SOCDBG, A0_FORCE_RAW, 1u, 1u) - FIELD(SOCDBG, HALT_CPU_BOOT, 2u, 1u) +/* soc_dbg_bm fields */ +REG16(SOC_DBG, 0x0) + FIELD(SOC_DBG, A0_DEBUG, 0u, 1u) + FIELD(SOC_DBG, A0_FORCE_RAW, 1u, 1u) + FIELD(SOC_DBG, HALT_CPU_BOOT, 2u, 1u) /* debug_policy, dbg_locked, dbg_unlocked fields */ SHARED_FIELD(POLICY_CAT, 0u, 2u) @@ -144,11 +144,11 @@ struct OtSoCDbgCtrlState { uint32_t regs[REGS_CORE_COUNT]; OtSoCDbgCtrlFsmState fsm_state; - OtSoCDbgState socdbg_state; + OtSoCDbgState soc_dbg_state; unsigned debug_policy; unsigned fsm_tick_count; uint16_t boot_status_bm; /* BOOT_STATUS fields */ - uint16_t socdbg_bm; /* SOCDBG fields */ + uint16_t soc_dbg_bm; /* SOC_DBG fields */ uint16_t lc_broadcast_bm; /* OtLcCtrlBroadcast fields */ bool boot_continue; bool debug_valid; @@ -220,18 +220,19 @@ static const char *LC_BROADCAST_NAMES[] = { LC_BROADCAST_NAMES[(_bit_)] : \ "?") -#define SOCDBG_NAME_ENTRY(_st_) [OT_SOCDBG_ST_##_st_] = stringify(_st_) -static const char *SOCDBG_NAMES[] = { +#define SOC_DBG_NAME_ENTRY(_st_) [OT_SOC_DBG_ST_##_st_] = stringify(_st_) +static const char *SOC_DBG_NAMES[] = { /* clang-format off */ - SOCDBG_NAME_ENTRY(RAW), - SOCDBG_NAME_ENTRY(PRE_PROD), - SOCDBG_NAME_ENTRY(PROD), + SOC_DBG_NAME_ENTRY(RAW), + SOC_DBG_NAME_ENTRY(PRE_PROD), + SOC_DBG_NAME_ENTRY(PROD), /* clang-format on */ }; -#undef SOCDBG_NAME_ENTRY +#undef SOC_DBG_NAME_ENTRY -#define SOCDBG_NAME(_st_) \ - (((unsigned)(_st_)) < ARRAY_SIZE(SOCDBG_NAMES) ? SOCDBG_NAMES[(_st_)] : "?") +#define SOC_DBG_NAME(_st_) \ + (((unsigned)(_st_)) < ARRAY_SIZE(SOC_DBG_NAMES) ? SOC_DBG_NAMES[(_st_)] : \ + "?") #define STATE_NAME_ENTRY(_st_) [ST_##_st_] = stringify(_st_) static const char *STATE_NAMES[] = { @@ -250,46 +251,46 @@ static const char *STATE_NAMES[] = { ((_st_) >= 0 && (_st_) < ARRAY_SIZE(STATE_NAMES) ? STATE_NAMES[(_st_)] : \ "?") #define CHANGE_STATE(_s_, _st_) \ - ot_socdbg_ctrl_change_state_line(_s_, ST_##_st_, __LINE__) -#define SCHEDULE_FSM(_s_) ot_socdbg_ctrl_schedule_fsm(_s_, __func__, __LINE__) + ot_soc_dbg_ctrl_change_state_line(_s_, ST_##_st_, __LINE__) +#define SCHEDULE_FSM(_s_) ot_soc_dbg_ctrl_schedule_fsm(_s_, __func__, __LINE__) -static void ot_socdbg_ctrl_core_update_irq(OtSoCDbgCtrlState *s) +static void ot_soc_dbg_ctrl_core_update_irq(OtSoCDbgCtrlState *s) { uint32_t levels = s->regs[R_CORE_INTR_STATE] & s->regs[R_CORE_INTR_ENABLE]; int level = (int)(bool)(levels & INTR_DEBUG_ATTENTION_MASK); if (level != ibex_irq_get_level(&s->irq)) { - trace_ot_socdbg_ctrl_core_update_irq(s->ot_id, level); + trace_ot_soc_dbg_ctrl_core_update_irq(s->ot_id, level); } ibex_irq_set(&s->irq, level); } -static void ot_socdbg_ctrl_change_state_line( +static void ot_soc_dbg_ctrl_change_state_line( OtSoCDbgCtrlState *s, OtSoCDbgCtrlFsmState state, int line) { - trace_ot_socdbg_ctrl_change_state(s->ot_id, line, STATE_NAME(s->fsm_state), - s->fsm_state, STATE_NAME(state), state); + trace_ot_soc_dbg_ctrl_change_state(s->ot_id, line, STATE_NAME(s->fsm_state), + s->fsm_state, STATE_NAME(state), state); s->fsm_state = state; } static void -ot_socdbg_ctrl_schedule_fsm(OtSoCDbgCtrlState *s, const char *func, int line) +ot_soc_dbg_ctrl_schedule_fsm(OtSoCDbgCtrlState *s, const char *func, int line) { s->fsm_tick_count += 1u; - trace_ot_socdbg_ctrl_schedule_fsm(s->ot_id, func, line, s->fsm_tick_count); + trace_ot_soc_dbg_ctrl_schedule_fsm(s->ot_id, func, line, s->fsm_tick_count); qemu_bh_schedule(s->fsm_tick_bh); } -static void ot_socdbg_ctrl_tick_fsm(OtSoCDbgCtrlState *s) +static void ot_soc_dbg_ctrl_tick_fsm(OtSoCDbgCtrlState *s) { bool cpu_boot_done = false; - trace_ot_socdbg_ctrl_tick_fsm(s->ot_id, STATE_NAME(s->fsm_state), - s->boot_status_bm, s->lc_broadcast_bm, - s->socdbg_bm, s->dft_ignore, - s->boot_continue); + trace_ot_soc_dbg_ctrl_tick_fsm(s->ot_id, STATE_NAME(s->fsm_state), + s->boot_status_bm, s->lc_broadcast_bm, + s->soc_dbg_bm, s->dft_ignore, + s->boot_continue); switch (s->fsm_state) { case ST_IDLE: @@ -311,7 +312,7 @@ static void ot_socdbg_ctrl_tick_fsm(OtSoCDbgCtrlState *s) } break; case ST_CHECK_HALT_PIN: - if (s->socdbg_bm & R_SOCDBG_HALT_CPU_BOOT_MASK) { + if (s->soc_dbg_bm & R_SOC_DBG_HALT_CPU_BOOT_MASK) { CHANGE_STATE(s, CHECK_JTAG_GO); } else { CHANGE_STATE(s, CONTINUE_BOOT); @@ -337,36 +338,36 @@ static void ot_socdbg_ctrl_tick_fsm(OtSoCDbgCtrlState *s) /* as with PwrMgr, use simple boolean value, not MuBi4 */ int cpu_boot_done_i = (int)cpu_boot_done; if (ibex_irq_get_level(&s->cpu_boot[CPU_BOOT_DONE]) != cpu_boot_done_i) { - trace_ot_socdbg_ctrl_cpu_boot_done(s->ot_id, cpu_boot_done_i); + trace_ot_soc_dbg_ctrl_cpu_boot_done(s->ot_id, cpu_boot_done_i); } ibex_irq_set(&s->cpu_boot[CPU_BOOT_DONE], cpu_boot_done_i); } -static void ot_socdbg_ctrl_update(OtSoCDbgCtrlState *s) +static void ot_soc_dbg_ctrl_update(OtSoCDbgCtrlState *s) { - OtSoCDbgState socdbg_state = - ((s->socdbg_bm & R_SOCDBG_A0_DEBUG_MASK) && - (s->socdbg_bm & R_SOCDBG_A0_FORCE_RAW_MASK)) ? - OT_SOCDBG_ST_RAW : - s->socdbg_state; - - switch (socdbg_state) { - case OT_SOCDBG_ST_RAW: + OtSoCDbgState soc_dbg_state = + ((s->soc_dbg_bm & R_SOC_DBG_A0_DEBUG_MASK) && + (s->soc_dbg_bm & R_SOC_DBG_A0_FORCE_RAW_MASK)) ? + OT_SOC_DBG_ST_RAW : + s->soc_dbg_state; + + switch (soc_dbg_state) { + case OT_SOC_DBG_ST_RAW: s->debug_policy = s->lc_broadcast_bm & (1u << OT_LC_DFT_EN) || s->lc_broadcast_bm & (1u << OT_LC_HW_DEBUG_EN) || - (s->socdbg_bm & R_SOCDBG_A0_DEBUG_MASK) ? + (s->soc_dbg_bm & R_SOC_DBG_A0_DEBUG_MASK) ? s->dbg_unlocked : s->dbg_locked; s->debug_valid = (bool)((s->boot_status_bm & R_BOOT_STATUS_LC_DONE_MASK) || - (s->socdbg_bm & R_SOCDBG_A0_DEBUG_MASK)); + (s->soc_dbg_bm & R_SOC_DBG_A0_DEBUG_MASK)); break; - case OT_SOCDBG_ST_PRE_PROD: + case OT_SOC_DBG_ST_PRE_PROD: s->debug_policy = s->dbg_unlocked; s->debug_valid = (bool)(s->boot_status_bm & R_BOOT_STATUS_LC_DONE_MASK); break; - case OT_SOCDBG_ST_PROD: + case OT_SOC_DBG_ST_PROD: s->debug_policy = s->regs[R_CORE_DEBUG_POLICY_CTRL] & (POLICY_CAT_MASK | POLICY_RELOCK_MASK); s->debug_valid = (bool)s->regs[R_CORE_DEBUG_POLICY_VALID]; @@ -376,28 +377,28 @@ static void ot_socdbg_ctrl_update(OtSoCDbgCtrlState *s) s->debug_valid = false; } - int policy = (int)((s->debug_policy & OT_SOCDBG_DEBUG_POLICY_MASK) | - (s->debug_valid ? OT_SOCDBG_DEBUG_VALID_MASK : 0)); + int policy = (int)((s->debug_policy & OT_SOC_DBG_DEBUG_POLICY_MASK) | + (s->debug_valid ? OT_SOC_DBG_DEBUG_VALID_MASK : 0)); int prev_policy = ibex_irq_get_level(&s->policy); if (prev_policy != policy) { - trace_ot_socdbg_ctrl_update(s->ot_id, SOCDBG_NAME(socdbg_state), - STATE_NAME(s->fsm_state), s->debug_policy, - s->debug_valid); + trace_ot_soc_dbg_ctrl_update(s->ot_id, SOC_DBG_NAME(soc_dbg_state), + STATE_NAME(s->fsm_state), s->debug_policy, + s->debug_valid); } ibex_irq_set(&s->policy, policy); } -static void ot_socdbg_ctrl_fsm_tick(void *opaque) +static void ot_soc_dbg_ctrl_fsm_tick(void *opaque) { OtSoCDbgCtrlState *s = opaque; OtSoCDbgCtrlFsmState fsm_state = s->fsm_state; g_assert(s->fsm_tick_count); while (s->fsm_tick_count) { - ot_socdbg_ctrl_update(s); + ot_soc_dbg_ctrl_update(s); s->fsm_tick_count--; - ot_socdbg_ctrl_tick_fsm(s); + ot_soc_dbg_ctrl_tick_fsm(s); } if (fsm_state != s->fsm_state) { /* schedule FSM update once more if its state has changed */ @@ -405,49 +406,49 @@ static void ot_socdbg_ctrl_fsm_tick(void *opaque) } } -static void ot_socdbg_ctrl_a0_debug(void *opaque, int n, int level) +static void ot_soc_dbg_ctrl_a0_debug(void *opaque, int n, int level) { OtSoCDbgCtrlState *s = opaque; g_assert(n == 0); - trace_ot_socdbg_ctrl_rcv(s->ot_id, "A0_DEBUG", 0, ibex_gpio_repr(level)); + trace_ot_soc_dbg_ctrl_rcv(s->ot_id, "A0_DEBUG", 0, ibex_gpio_repr(level)); /* expect an Ibex GPIO signal */ g_assert(ibex_gpio_check(level)); if (ibex_gpio_level(level)) { - s->socdbg_bm |= R_SOCDBG_A0_DEBUG_MASK; + s->soc_dbg_bm |= R_SOC_DBG_A0_DEBUG_MASK; } else { - s->socdbg_bm &= ~R_SOCDBG_A0_DEBUG_MASK; + s->soc_dbg_bm &= ~R_SOC_DBG_A0_DEBUG_MASK; } SCHEDULE_FSM(s); } -static void ot_socdbg_ctrl_halt_cpu_boot(void *opaque, int n, int level) +static void ot_soc_dbg_ctrl_halt_cpu_boot(void *opaque, int n, int level) { OtSoCDbgCtrlState *s = opaque; g_assert(n == 0); - trace_ot_socdbg_ctrl_rcv(s->ot_id, "HALT_CPU_BOOT", 0, - ibex_gpio_repr(level)); + trace_ot_soc_dbg_ctrl_rcv(s->ot_id, "HALT_CPU_BOOT", 0, + ibex_gpio_repr(level)); /* expect an Ibex GPIO signal */ g_assert(ibex_gpio_check(level)); /* active low */ if (!ibex_gpio_level(level)) { - s->socdbg_bm |= R_SOCDBG_HALT_CPU_BOOT_MASK; + s->soc_dbg_bm |= R_SOC_DBG_HALT_CPU_BOOT_MASK; } else { - s->socdbg_bm &= ~R_SOCDBG_HALT_CPU_BOOT_MASK; + s->soc_dbg_bm &= ~R_SOC_DBG_HALT_CPU_BOOT_MASK; } SCHEDULE_FSM(s); } -static void ot_socdbg_ctrl_lc_broadcast(void *opaque, int n, int level) +static void ot_soc_dbg_ctrl_lc_broadcast(void *opaque, int n, int level) { OtSoCDbgCtrlState *s = opaque; @@ -455,8 +456,8 @@ static void ot_socdbg_ctrl_lc_broadcast(void *opaque, int n, int level) g_assert(bcast < OT_LC_BROADCAST_COUNT); g_assert(!ibex_gpio_check(level)); - trace_ot_socdbg_ctrl_rcv(s->ot_id, LC_BCAST_NAME(bcast), bcast, - level ? '1' : '0'); + trace_ot_soc_dbg_ctrl_rcv(s->ot_id, LC_BCAST_NAME(bcast), bcast, + level ? '1' : '0'); switch (n) { case OT_LC_RAW_TEST_RMA: @@ -493,18 +494,18 @@ static void ot_socdbg_ctrl_lc_broadcast(void *opaque, int n, int level) SCHEDULE_FSM(s); } -static void ot_socdbg_ctrl_boot_status(void *opaque, int n, int level) +static void ot_soc_dbg_ctrl_boot_status(void *opaque, int n, int level) { OtSoCDbgCtrlState *s = opaque; g_assert(n == 0); OtPwrMgrBootStatus bs = { .i32 = level }; - trace_ot_socdbg_ctrl_boot_status(s->ot_id, (bool)bs.main_clk_status, - (bool)bs.io_clk_status, (bool)bs.otp_done, - (bool)bs.lc_done, (bool)bs.cpu_fetch_en, - bs.rom_done & ROM_MASK, - bs.rom_good & ROM_MASK); + trace_ot_soc_dbg_ctrl_boot_status(s->ot_id, (bool)bs.main_clk_status, + (bool)bs.io_clk_status, (bool)bs.otp_done, + (bool)bs.lc_done, (bool)bs.cpu_fetch_en, + bs.rom_done & ROM_MASK, + bs.rom_good & ROM_MASK); uint16_t bs_bm = 0; bs_bm = FIELD_DP16(bs_bm, BOOT_STATUS, MAIN_CLK_STATUS, bs.main_clk_status); bs_bm = FIELD_DP16(bs_bm, BOOT_STATUS, IO_CLK_STATUS, bs.io_clk_status); @@ -520,25 +521,25 @@ static void ot_socdbg_ctrl_boot_status(void *opaque, int n, int level) SCHEDULE_FSM(s); } -static void ot_socdbg_ctrl_a0_force_raw(void *opaque, int n, int level) +static void ot_soc_dbg_ctrl_a0_force_raw(void *opaque, int n, int level) { OtSoCDbgCtrlState *s = opaque; g_assert(n == 0); g_assert(!ibex_gpio_check(level)); - trace_ot_socdbg_ctrl_rcv(s->ot_id, "FORCE_RAW", 0, level ? '1' : '0'); + trace_ot_soc_dbg_ctrl_rcv(s->ot_id, "FORCE_RAW", 0, level ? '1' : '0'); if (level) { - s->socdbg_bm |= R_SOCDBG_A0_FORCE_RAW_MASK; + s->soc_dbg_bm |= R_SOC_DBG_A0_FORCE_RAW_MASK; } else { - s->socdbg_bm &= ~R_SOCDBG_A0_FORCE_RAW_MASK; + s->soc_dbg_bm &= ~R_SOC_DBG_A0_FORCE_RAW_MASK; } SCHEDULE_FSM(s); } -static void ot_socdbg_ctrl_socdbg_state(void *opaque, int n, int level) +static void ot_soc_dbg_ctrl_soc_dbg_state(void *opaque, int n, int level) { OtSoCDbgCtrlState *s = opaque; @@ -547,27 +548,29 @@ static void ot_socdbg_ctrl_socdbg_state(void *opaque, int n, int level) switch (level) { case 0: - s->socdbg_state = OT_SOCDBG_ST_RAW; + s->soc_dbg_state = OT_SOC_DBG_ST_RAW; break; case 1: - s->socdbg_state = OT_SOCDBG_ST_PRE_PROD; + s->soc_dbg_state = OT_SOC_DBG_ST_PRE_PROD; break; case 2: - s->socdbg_state = OT_SOCDBG_ST_PROD; + s->soc_dbg_state = OT_SOC_DBG_ST_PROD; break; default: g_assert_not_reached(); } - trace_ot_socdbg_ctrl_rcv(s->ot_id, "SOCDBG_STATE", 0, (char)('0' + level)); + trace_ot_soc_dbg_ctrl_rcv(s->ot_id, "SOC_DBG_STATE", 0, + (char)('0' + level)); - trace_ot_socdbg_ctrl_socdbg_state(s->ot_id, SOCDBG_NAME(s->socdbg_state)); + trace_ot_soc_dbg_ctrl_soc_dbg_state(s->ot_id, + SOC_DBG_NAME(s->soc_dbg_state)); SCHEDULE_FSM(s); } static uint64_t -ot_socdbg_ctrl_core_read(void *opaque, hwaddr addr, unsigned size) +ot_soc_dbg_ctrl_core_read(void *opaque, hwaddr addr, unsigned size) { OtSoCDbgCtrlState *s = opaque; (void)size; @@ -599,14 +602,14 @@ ot_socdbg_ctrl_core_read(void *opaque, hwaddr addr, unsigned size) } uint32_t pc = ibex_get_current_pc(); - trace_ot_socdbg_ctrl_core_io_read_out(s->ot_id, (uint32_t)addr, - REG_NAME(CORE, reg), val32, pc); + trace_ot_soc_dbg_ctrl_core_io_read_out(s->ot_id, (uint32_t)addr, + REG_NAME(CORE, reg), val32, pc); return (uint32_t)val32; } -static void ot_socdbg_ctrl_core_write(void *opaque, hwaddr addr, uint64_t value, - unsigned size) +static void ot_soc_dbg_ctrl_core_write(void *opaque, hwaddr addr, + uint64_t value, unsigned size) { OtSoCDbgCtrlState *s = opaque; (void)size; @@ -615,24 +618,24 @@ static void ot_socdbg_ctrl_core_write(void *opaque, hwaddr addr, uint64_t value, hwaddr reg = R32_OFF(addr); uint32_t pc = ibex_get_current_pc(); - trace_ot_socdbg_ctrl_core_io_write(s->ot_id, (uint32_t)addr, - REG_NAME(CORE, reg), val32, pc); + trace_ot_soc_dbg_ctrl_core_io_write(s->ot_id, (uint32_t)addr, + REG_NAME(CORE, reg), val32, pc); switch (reg) { case R_CORE_INTR_STATE: val32 &= INTR_DEBUG_ATTENTION_MASK; s->regs[reg] &= ~val32; /* RW1C */ - ot_socdbg_ctrl_core_update_irq(s); + ot_soc_dbg_ctrl_core_update_irq(s); break; case R_CORE_INTR_ENABLE: val32 &= INTR_DEBUG_ATTENTION_MASK; s->regs[reg] = val32; - ot_socdbg_ctrl_core_update_irq(s); + ot_soc_dbg_ctrl_core_update_irq(s); break; case R_CORE_INTR_TEST: val32 &= INTR_DEBUG_ATTENTION_MASK; s->regs[reg] |= val32; /* RW1S */ - ot_socdbg_ctrl_core_update_irq(s); + ot_soc_dbg_ctrl_core_update_irq(s); break; case R_CORE_ALERT_TEST: val32 &= CORE_ALERT_TEST_MASK; @@ -660,7 +663,7 @@ static void ot_socdbg_ctrl_core_write(void *opaque, hwaddr addr, uint64_t value, } static uint64_t -ot_socdbg_ctrl_dmi_read(void *opaque, hwaddr addr, unsigned size) +ot_soc_dbg_ctrl_dmi_read(void *opaque, hwaddr addr, unsigned size) { OtSoCDbgCtrlState *s = opaque; (void)size; @@ -692,14 +695,14 @@ ot_socdbg_ctrl_dmi_read(void *opaque, hwaddr addr, unsigned size) break; } - trace_ot_socdbg_ctrl_dmi_io_read_out(s->ot_id, (uint32_t)addr, - REG_NAME(DMI, reg), val32); + trace_ot_soc_dbg_ctrl_dmi_io_read_out(s->ot_id, (uint32_t)addr, + REG_NAME(DMI, reg), val32); return (uint32_t)val32; } -static void ot_socdbg_ctrl_dmi_write(void *opaque, hwaddr addr, uint64_t value, - unsigned size) +static void ot_soc_dbg_ctrl_dmi_write(void *opaque, hwaddr addr, uint64_t value, + unsigned size) { OtSoCDbgCtrlState *s = opaque; (void)size; @@ -707,8 +710,8 @@ static void ot_socdbg_ctrl_dmi_write(void *opaque, hwaddr addr, uint64_t value, hwaddr reg = R32_OFF(addr); - trace_ot_socdbg_ctrl_dmi_io_write(s->ot_id, (uint32_t)addr, - REG_NAME(DMI, reg), val32); + trace_ot_soc_dbg_ctrl_dmi_io_write(s->ot_id, (uint32_t)addr, + REG_NAME(DMI, reg), val32); switch (reg) { case R_DMI_CONTROL: @@ -728,7 +731,7 @@ static void ot_socdbg_ctrl_dmi_write(void *opaque, hwaddr addr, uint64_t value, } } -static Property ot_socdbg_ctrl_properties[] = { +static Property ot_soc_dbg_ctrl_properties[] = { DEFINE_PROP_STRING(OT_COMMON_DEV_ID, OtSoCDbgCtrlState, ot_id), DEFINE_PROP_UINT8("dbg_unlocked", OtSoCDbgCtrlState, dbg_unlocked, DEFAULT_DBG_UNLOCKED), @@ -739,26 +742,26 @@ static Property ot_socdbg_ctrl_properties[] = { DEFINE_PROP_END_OF_LIST(), }; -static const MemoryRegionOps ot_socdbg_ctrl_core_ops = { - .read = &ot_socdbg_ctrl_core_read, - .write = &ot_socdbg_ctrl_core_write, +static const MemoryRegionOps ot_soc_dbg_ctrl_core_ops = { + .read = &ot_soc_dbg_ctrl_core_read, + .write = &ot_soc_dbg_ctrl_core_write, .endianness = DEVICE_NATIVE_ENDIAN, .impl.min_access_size = 4u, .impl.max_access_size = 4u, }; -static const MemoryRegionOps ot_socdbg_ctrl_dmi_ops = { - .read = &ot_socdbg_ctrl_dmi_read, - .write = &ot_socdbg_ctrl_dmi_write, +static const MemoryRegionOps ot_soc_dbg_ctrl_dmi_ops = { + .read = &ot_soc_dbg_ctrl_dmi_read, + .write = &ot_soc_dbg_ctrl_dmi_write, .endianness = DEVICE_NATIVE_ENDIAN, .impl.min_access_size = 4u, .impl.max_access_size = 4u, }; -static void ot_socdbg_ctrl_reset_enter(Object *obj, ResetType type) +static void ot_soc_dbg_ctrl_reset_enter(Object *obj, ResetType type) { - OtSoCDbgCtrlClass *c = OT_SOCDBG_CTRL_GET_CLASS(obj); - OtSoCDbgCtrlState *s = OT_SOCDBG_CTRL(obj); + OtSoCDbgCtrlClass *c = OT_SOC_DBG_CTRL_GET_CLASS(obj); + OtSoCDbgCtrlState *s = OT_SOC_DBG_CTRL(obj); if (c->parent_phases.enter) { c->parent_phases.enter(obj, type); @@ -766,26 +769,26 @@ static void ot_socdbg_ctrl_reset_enter(Object *obj, ResetType type) memset(s->regs, 0, sizeof(s->regs)); - ot_socdbg_ctrl_core_update_irq(s); + ot_soc_dbg_ctrl_core_update_irq(s); ibex_irq_set(&s->alert, 0); ibex_irq_set(&s->cpu_boot[CPU_BOOT_GOOD], (int)false); ibex_irq_set(&s->cpu_boot[CPU_BOOT_DONE], (int)false); CHANGE_STATE(s, IDLE); s->fsm_tick_count = 0u; - s->socdbg_bm = 0u; + s->soc_dbg_bm = 0u; s->boot_status_bm = 0u; s->lc_broadcast_bm = 0u; - s->socdbg_state = OT_SOCDBG_ST_PROD; + s->soc_dbg_state = OT_SOC_DBG_ST_PROD; s->debug_policy = s->dbg_locked; s->debug_valid = false; s->boot_continue = false; } -static void ot_socdbg_ctrl_reset_exit(Object *obj, ResetType type) +static void ot_soc_dbg_ctrl_reset_exit(Object *obj, ResetType type) { - OtSoCDbgCtrlClass *c = OT_SOCDBG_CTRL_GET_CLASS(obj); - OtSoCDbgCtrlState *s = OT_SOCDBG_CTRL(obj); + OtSoCDbgCtrlClass *c = OT_SOC_DBG_CTRL_GET_CLASS(obj); + OtSoCDbgCtrlState *s = OT_SOC_DBG_CTRL(obj); if (c->parent_phases.exit) { c->parent_phases.exit(obj, type); @@ -805,9 +808,9 @@ static void ot_socdbg_ctrl_reset_exit(Object *obj, ResetType type) SCHEDULE_FSM(s); } -static void ot_socdbg_ctrl_realize(DeviceState *dev, Error **errp) +static void ot_soc_dbg_ctrl_realize(DeviceState *dev, Error **errp) { - OtSoCDbgCtrlState *s = OT_SOCDBG_CTRL(dev); + OtSoCDbgCtrlState *s = OT_SOC_DBG_CTRL(dev); (void)errp; g_assert(s->ot_id); @@ -816,68 +819,68 @@ static void ot_socdbg_ctrl_realize(DeviceState *dev, Error **errp) s->dbg_unlocked &= POLICY_CAT_MASK | POLICY_RELOCK_MASK; } -static void ot_socdbg_ctrl_init(Object *obj) +static void ot_soc_dbg_ctrl_init(Object *obj) { - OtSoCDbgCtrlState *s = OT_SOCDBG_CTRL(obj); + OtSoCDbgCtrlState *s = OT_SOC_DBG_CTRL(obj); - memory_region_init_io(&s->core, obj, &ot_socdbg_ctrl_core_ops, s, - TYPE_OT_SOCDBG_CTRL, REGS_CORE_SIZE); + memory_region_init_io(&s->core, obj, &ot_soc_dbg_ctrl_core_ops, s, + TYPE_OT_SOC_DBG_CTRL, REGS_CORE_SIZE); sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->core); - memory_region_init_io(&s->dmi, obj, &ot_socdbg_ctrl_dmi_ops, s, - TYPE_OT_SOCDBG_CTRL, REGS_DMI_SIZE); + memory_region_init_io(&s->dmi, obj, &ot_soc_dbg_ctrl_dmi_ops, s, + TYPE_OT_SOC_DBG_CTRL, REGS_DMI_SIZE); sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->dmi); ibex_sysbus_init_irq(obj, &s->irq); ibex_qdev_init_irq(obj, &s->alert, OT_DEVICE_ALERT); - ibex_qdev_init_irq(obj, &s->policy, OT_SOCDBG_DEBUG_POLICY); - ibex_qdev_init_irqs(obj, s->cpu_boot, OT_SOCDBG_CPU_BOOT, + ibex_qdev_init_irq(obj, &s->policy, OT_SOC_DBG_DEBUG_POLICY); + ibex_qdev_init_irqs(obj, s->cpu_boot, OT_SOC_DBG_CPU_BOOT, ARRAY_SIZE(s->cpu_boot)); - qdev_init_gpio_in_named(DEVICE(obj), &ot_socdbg_ctrl_halt_cpu_boot, - OT_SOCDBG_HALT_CPU_BOOT, 1); - qdev_init_gpio_in_named(DEVICE(obj), &ot_socdbg_ctrl_lc_broadcast, - OT_SOCDBG_LC_BCAST, OT_LC_BROADCAST_COUNT); - qdev_init_gpio_in_named(DEVICE(obj), &ot_socdbg_ctrl_socdbg_state, - OT_SOCDBG_STATE, 1); - qdev_init_gpio_in_named(DEVICE(obj), &ot_socdbg_ctrl_boot_status, - OT_SOCDBG_BOOT_STATUS, 1u); - qdev_init_gpio_in_named(DEVICE(obj), &ot_socdbg_ctrl_a0_debug, - OT_SOCDBG_A0_DEBUG_EN, 1); - qdev_init_gpio_in_named(DEVICE(obj), &ot_socdbg_ctrl_a0_force_raw, - OT_SOCDBG_A0_FORCE_RAW, 1u); - - s->fsm_tick_bh = qemu_bh_new(&ot_socdbg_ctrl_fsm_tick, s); + qdev_init_gpio_in_named(DEVICE(obj), &ot_soc_dbg_ctrl_halt_cpu_boot, + OT_SOC_DBG_HALT_CPU_BOOT, 1); + qdev_init_gpio_in_named(DEVICE(obj), &ot_soc_dbg_ctrl_lc_broadcast, + OT_SOC_DBG_LC_BCAST, OT_LC_BROADCAST_COUNT); + qdev_init_gpio_in_named(DEVICE(obj), &ot_soc_dbg_ctrl_soc_dbg_state, + OT_SOC_DBG_STATE, 1); + qdev_init_gpio_in_named(DEVICE(obj), &ot_soc_dbg_ctrl_boot_status, + OT_SOC_DBG_BOOT_STATUS, 1u); + qdev_init_gpio_in_named(DEVICE(obj), &ot_soc_dbg_ctrl_a0_debug, + OT_SOC_DBG_A0_DEBUG_EN, 1); + qdev_init_gpio_in_named(DEVICE(obj), &ot_soc_dbg_ctrl_a0_force_raw, + OT_SOC_DBG_A0_FORCE_RAW, 1u); + + s->fsm_tick_bh = qemu_bh_new(&ot_soc_dbg_ctrl_fsm_tick, s); } -static void ot_socdbg_ctrl_class_init(ObjectClass *klass, void *data) +static void ot_soc_dbg_ctrl_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); (void)data; - dc->realize = &ot_socdbg_ctrl_realize; - device_class_set_props(dc, ot_socdbg_ctrl_properties); + dc->realize = &ot_soc_dbg_ctrl_realize; + device_class_set_props(dc, ot_soc_dbg_ctrl_properties); set_bit(DEVICE_CATEGORY_MISC, dc->categories); ResettableClass *rc = RESETTABLE_CLASS(klass); - OtSoCDbgCtrlClass *sc = OT_SOCDBG_CTRL_CLASS(klass); - resettable_class_set_parent_phases(rc, &ot_socdbg_ctrl_reset_enter, NULL, - &ot_socdbg_ctrl_reset_exit, + OtSoCDbgCtrlClass *sc = OT_SOC_DBG_CTRL_CLASS(klass); + resettable_class_set_parent_phases(rc, &ot_soc_dbg_ctrl_reset_enter, NULL, + &ot_soc_dbg_ctrl_reset_exit, &sc->parent_phases); } -static const TypeInfo ot_socdbg_ctrl_info = { - .name = TYPE_OT_SOCDBG_CTRL, +static const TypeInfo ot_soc_dbg_ctrl_info = { + .name = TYPE_OT_SOC_DBG_CTRL, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(OtSoCDbgCtrlState), - .instance_init = &ot_socdbg_ctrl_init, + .instance_init = &ot_soc_dbg_ctrl_init, .class_size = sizeof(OtSoCDbgCtrlClass), - .class_init = &ot_socdbg_ctrl_class_init, + .class_init = &ot_soc_dbg_ctrl_class_init, }; -static void ot_socdbg_ctrl_register_types(void) +static void ot_soc_dbg_ctrl_register_types(void) { - type_register_static(&ot_socdbg_ctrl_info); + type_register_static(&ot_soc_dbg_ctrl_info); } -type_init(ot_socdbg_ctrl_register_types); +type_init(ot_soc_dbg_ctrl_register_types); diff --git a/hw/opentitan/trace-events b/hw/opentitan/trace-events index 5c4c524915417..4a604f8e61387 100644 --- a/hw/opentitan/trace-events +++ b/hw/opentitan/trace-events @@ -520,21 +520,21 @@ ot_soc_proxy_io_read_out(const char * id, uint32_t addr, const char * regname, u ot_soc_proxy_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_soc_proxy_update_irq(const char * id, unsigned n, int prev, int next) "%s: #%u %d -> %d" -# ot_socdbg_ctrl.c - -ot_socdbg_ctrl_boot_status(const char *id, bool mclk, bool ioclk, bool otp, bool lc, bool cpu, unsigned rdone, unsigned rgood) "%s: mclk:%u ioclk:%u otp:%u lc:%u cpu_en:%u rom_done:0x%x rom_good:0x%x" -ot_socdbg_ctrl_change_state(const char *id, int line, const char *old, int nold, const char *new, int nnew) "%s: @ %d [%s:%d] -> [%s:%d]" -ot_socdbg_ctrl_cpu_boot_done(const char *id, int level) "%s: %d" -ot_socdbg_ctrl_core_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_socdbg_ctrl_core_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_socdbg_ctrl_core_update_irq(const char *id, int new) "%s: %u" -ot_socdbg_ctrl_dmi_io_read_out(const char *id, uint32_t addr, const char * regname, uint32_t val) "%s: addr=0x%02x (%s), val=0x%x" -ot_socdbg_ctrl_dmi_io_write(const char *id, uint32_t addr, const char * regname, uint32_t val) "%s: addr=0x%02x (%s), val=0x%x" -ot_socdbg_ctrl_rcv(const char *id, const char *src, unsigned n, char sig) "%s: %s #%d: lvl %c" -ot_socdbg_ctrl_schedule_fsm(const char *id, const char *func, int line, unsigned tc) "%s: @ %s:%d (%u)" -ot_socdbg_ctrl_socdbg_state(const char *id, const char *st) "%s: %s" -ot_socdbg_ctrl_tick_fsm(const char *id, const char *st, uint32_t bs, uint32_t lc, uint32_t dbg, bool dfti, bool bc) "%s: %s bs:0x%03x lc:0x%02x dbg:0x%01x dfti:%u bc:%u" -ot_socdbg_ctrl_update(const char *id, const char *socdbgst, const char *fsmst, unsigned policy, bool valid) "%s: [%s] fsm:%s policy:0x%1x valid:%u" +# ot_soc_dbg_ctrl.c + +ot_soc_dbg_ctrl_boot_status(const char *id, bool mclk, bool ioclk, bool otp, bool lc, bool cpu, unsigned rdone, unsigned rgood) "%s: mclk:%u ioclk:%u otp:%u lc:%u cpu_en:%u rom_done:0x%x rom_good:0x%x" +ot_soc_dbg_ctrl_change_state(const char *id, int line, const char *old, int nold, const char *new, int nnew) "%s: @ %d [%s:%d] -> [%s:%d]" +ot_soc_dbg_ctrl_cpu_boot_done(const char *id, int level) "%s: %d" +ot_soc_dbg_ctrl_core_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_soc_dbg_ctrl_core_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_soc_dbg_ctrl_core_update_irq(const char *id, int new) "%s: %u" +ot_soc_dbg_ctrl_dmi_io_read_out(const char *id, uint32_t addr, const char * regname, uint32_t val) "%s: addr=0x%02x (%s), val=0x%x" +ot_soc_dbg_ctrl_dmi_io_write(const char *id, uint32_t addr, const char * regname, uint32_t val) "%s: addr=0x%02x (%s), val=0x%x" +ot_soc_dbg_ctrl_rcv(const char *id, const char *src, unsigned n, char sig) "%s: %s #%d: lvl %c" +ot_soc_dbg_ctrl_schedule_fsm(const char *id, const char *func, int line, unsigned tc) "%s: @ %s:%d (%u)" +ot_soc_dbg_ctrl_soc_dbg_state(const char *id, const char *st) "%s: %s" +ot_soc_dbg_ctrl_tick_fsm(const char *id, const char *st, uint32_t bs, uint32_t lc, uint32_t dbg, bool dfti, bool bc) "%s: %s bs:0x%03x lc:0x%02x dbg:0x%01x dfti:%u bc:%u" +ot_soc_dbg_ctrl_update(const char *id, const char *soc_dbgst, const char *fsmst, unsigned policy, bool valid) "%s: [%s] fsm:%s policy:0x%1x valid:%u" # ot_spi_device.c diff --git a/hw/riscv/ot_darjeeling.c b/hw/riscv/ot_darjeeling.c index f54a569aced41..53b54aeda845c 100644 --- a/hw/riscv/ot_darjeeling.c +++ b/hw/riscv/ot_darjeeling.c @@ -1287,7 +1287,7 @@ static const IbexDeviceDef ot_dj_soc_devices[] = { }, [OT_DJ_SOC_DEV_SOC_DBG_CTRL] = { /* @todo: should be renamed TYPE_OT_SOC_DBG_CTRL */ - .type = TYPE_OT_SOCDBG_CTRL, + .type = TYPE_OT_SOC_DBG_CTRL, .memmap = MEMMAPENTRIES( { .base = 0x30170000u } ), diff --git a/include/hw/opentitan/ot_soc_dbg_ctrl.h b/include/hw/opentitan/ot_soc_dbg_ctrl.h index 4baca85cd1729..e2f8b263024e8 100644 --- a/include/hw/opentitan/ot_soc_dbg_ctrl.h +++ b/include/hw/opentitan/ot_soc_dbg_ctrl.h @@ -30,30 +30,30 @@ #include "qom/object.h" -#define TYPE_OT_SOCDBG_CTRL "ot-socdbg_ctrl" -OBJECT_DECLARE_TYPE(OtSoCDbgCtrlState, OtSoCDbgCtrlClass, OT_SOCDBG_CTRL) +#define TYPE_OT_SOC_DBG_CTRL "ot-soc_dbg_ctrl" +OBJECT_DECLARE_TYPE(OtSoCDbgCtrlState, OtSoCDbgCtrlClass, OT_SOC_DBG_CTRL) /* SocDbg controller states */ typedef enum { - OT_SOCDBG_ST_RAW, - OT_SOCDBG_ST_PRE_PROD, - OT_SOCDBG_ST_PROD, - OT_SOCDBG_ST_COUNT, + OT_SOC_DBG_ST_RAW, + OT_SOC_DBG_ST_PRE_PROD, + OT_SOC_DBG_ST_PROD, + OT_SOC_DBG_ST_COUNT, } OtSoCDbgState; /* input lines */ -#define OT_SOCDBG_HALT_CPU_BOOT TYPE_OT_SOCDBG_CTRL "-halt-cpu-boot" -#define OT_SOCDBG_LC_BCAST TYPE_OT_SOCDBG_CTRL "-lc-broacast" -#define OT_SOCDBG_STATE TYPE_OT_SOCDBG_CTRL "-socdbg" -#define OT_SOCDBG_BOOT_STATUS TYPE_OT_SOCDBG_CTRL "-boot-status" -#define OT_SOCDBG_A0_DEBUG_EN TYPE_OT_SOCDBG_CTRL "-a0-debug-en" -#define OT_SOCDBG_A0_FORCE_RAW TYPE_OT_SOCDBG_CTRL "-a0-force-raw" +#define OT_SOC_DBG_HALT_CPU_BOOT TYPE_OT_SOC_DBG_CTRL "-halt-cpu-boot" +#define OT_SOC_DBG_LC_BCAST TYPE_OT_SOC_DBG_CTRL "-lc-broacast" +#define OT_SOC_DBG_STATE TYPE_OT_SOC_DBG_CTRL "-soc-dbg" +#define OT_SOC_DBG_BOOT_STATUS TYPE_OT_SOC_DBG_CTRL "-boot-status" +#define OT_SOC_DBG_A0_DEBUG_EN TYPE_OT_SOC_DBG_CTRL "-a0-debug-en" +#define OT_SOC_DBG_A0_FORCE_RAW TYPE_OT_SOC_DBG_CTRL "-a0-force-raw" /* output lines */ -#define OT_SOCDBG_CPU_BOOT TYPE_OT_SOCDBG_CTRL "-cpu-boot" -#define OT_SOCDBG_DEBUG_POLICY TYPE_OT_SOCDBG_CTRL "-debug-policy" +#define OT_SOC_DBG_CPU_BOOT TYPE_OT_SOC_DBG_CTRL "-cpu-boot" +#define OT_SOC_DBG_DEBUG_POLICY TYPE_OT_SOC_DBG_CTRL "-debug-policy" -#define OT_SOCDBG_DEBUG_POLICY_MASK 0x0fu -#define OT_SOCDBG_DEBUG_VALID_MASK 0x80u +#define OT_SOC_DBG_DEBUG_POLICY_MASK 0x0fu +#define OT_SOC_DBG_DEBUG_VALID_MASK 0x80u #endif /* HW_OPENTITAN_OT_SOC_DBG_CTRL_H */ From 37986e4a1adfca77bfe858ea38bbee524e542db5 Mon Sep 17 00:00:00 2001 From: Emmanuel Blot Date: Fri, 7 Nov 2025 11:53:02 +0100 Subject: [PATCH 11/24] [ot] hw/opentitan: ot_soc_dbg_ctrl: rename deprecated signals A0 signals are no longer defined in new HW Signed-off-by: Emmanuel Blot --- hw/opentitan/ot_soc_dbg_ctrl.c | 60 +++----------------------- include/hw/opentitan/ot_soc_dbg_ctrl.h | 4 +- 2 files changed, 6 insertions(+), 58 deletions(-) diff --git a/hw/opentitan/ot_soc_dbg_ctrl.c b/hw/opentitan/ot_soc_dbg_ctrl.c index c6a6ffe472115..2aa8c2c976574 100644 --- a/hw/opentitan/ot_soc_dbg_ctrl.c +++ b/hw/opentitan/ot_soc_dbg_ctrl.c @@ -85,8 +85,6 @@ REG16(BOOT_STATUS, 0x0) /* soc_dbg_bm fields */ REG16(SOC_DBG, 0x0) - FIELD(SOC_DBG, A0_DEBUG, 0u, 1u) - FIELD(SOC_DBG, A0_FORCE_RAW, 1u, 1u) FIELD(SOC_DBG, HALT_CPU_BOOT, 2u, 1u) /* debug_policy, dbg_locked, dbg_unlocked fields */ @@ -345,23 +343,14 @@ static void ot_soc_dbg_ctrl_tick_fsm(OtSoCDbgCtrlState *s) static void ot_soc_dbg_ctrl_update(OtSoCDbgCtrlState *s) { - OtSoCDbgState soc_dbg_state = - ((s->soc_dbg_bm & R_SOC_DBG_A0_DEBUG_MASK) && - (s->soc_dbg_bm & R_SOC_DBG_A0_FORCE_RAW_MASK)) ? - OT_SOC_DBG_ST_RAW : - s->soc_dbg_state; - - switch (soc_dbg_state) { + switch (s->soc_dbg_state) { case OT_SOC_DBG_ST_RAW: s->debug_policy = s->lc_broadcast_bm & (1u << OT_LC_DFT_EN) || - s->lc_broadcast_bm & (1u << OT_LC_HW_DEBUG_EN) || - (s->soc_dbg_bm & R_SOC_DBG_A0_DEBUG_MASK) ? + s->lc_broadcast_bm & (1u << OT_LC_HW_DEBUG_EN) ? s->dbg_unlocked : s->dbg_locked; - s->debug_valid = - (bool)((s->boot_status_bm & R_BOOT_STATUS_LC_DONE_MASK) || - (s->soc_dbg_bm & R_SOC_DBG_A0_DEBUG_MASK)); + s->debug_valid = (bool)(s->boot_status_bm & R_BOOT_STATUS_LC_DONE_MASK); break; case OT_SOC_DBG_ST_PRE_PROD: s->debug_policy = s->dbg_unlocked; @@ -382,7 +371,7 @@ static void ot_soc_dbg_ctrl_update(OtSoCDbgCtrlState *s) int prev_policy = ibex_irq_get_level(&s->policy); if (prev_policy != policy) { - trace_ot_soc_dbg_ctrl_update(s->ot_id, SOC_DBG_NAME(soc_dbg_state), + trace_ot_soc_dbg_ctrl_update(s->ot_id, SOC_DBG_NAME(s->soc_dbg_state), STATE_NAME(s->fsm_state), s->debug_policy, s->debug_valid); } @@ -406,25 +395,6 @@ static void ot_soc_dbg_ctrl_fsm_tick(void *opaque) } } -static void ot_soc_dbg_ctrl_a0_debug(void *opaque, int n, int level) -{ - OtSoCDbgCtrlState *s = opaque; - - g_assert(n == 0); - - trace_ot_soc_dbg_ctrl_rcv(s->ot_id, "A0_DEBUG", 0, ibex_gpio_repr(level)); - - /* expect an Ibex GPIO signal */ - g_assert(ibex_gpio_check(level)); - - if (ibex_gpio_level(level)) { - s->soc_dbg_bm |= R_SOC_DBG_A0_DEBUG_MASK; - } else { - s->soc_dbg_bm &= ~R_SOC_DBG_A0_DEBUG_MASK; - } - - SCHEDULE_FSM(s); -} static void ot_soc_dbg_ctrl_halt_cpu_boot(void *opaque, int n, int level) { @@ -521,23 +491,6 @@ static void ot_soc_dbg_ctrl_boot_status(void *opaque, int n, int level) SCHEDULE_FSM(s); } -static void ot_soc_dbg_ctrl_a0_force_raw(void *opaque, int n, int level) -{ - OtSoCDbgCtrlState *s = opaque; - - g_assert(n == 0); - g_assert(!ibex_gpio_check(level)); - - trace_ot_soc_dbg_ctrl_rcv(s->ot_id, "FORCE_RAW", 0, level ? '1' : '0'); - - if (level) { - s->soc_dbg_bm |= R_SOC_DBG_A0_FORCE_RAW_MASK; - } else { - s->soc_dbg_bm &= ~R_SOC_DBG_A0_FORCE_RAW_MASK; - } - - SCHEDULE_FSM(s); -} static void ot_soc_dbg_ctrl_soc_dbg_state(void *opaque, int n, int level) { @@ -845,10 +798,7 @@ static void ot_soc_dbg_ctrl_init(Object *obj) OT_SOC_DBG_STATE, 1); qdev_init_gpio_in_named(DEVICE(obj), &ot_soc_dbg_ctrl_boot_status, OT_SOC_DBG_BOOT_STATUS, 1u); - qdev_init_gpio_in_named(DEVICE(obj), &ot_soc_dbg_ctrl_a0_debug, - OT_SOC_DBG_A0_DEBUG_EN, 1); - qdev_init_gpio_in_named(DEVICE(obj), &ot_soc_dbg_ctrl_a0_force_raw, - OT_SOC_DBG_A0_FORCE_RAW, 1u); + s->fsm_tick_bh = qemu_bh_new(&ot_soc_dbg_ctrl_fsm_tick, s); } diff --git a/include/hw/opentitan/ot_soc_dbg_ctrl.h b/include/hw/opentitan/ot_soc_dbg_ctrl.h index e2f8b263024e8..8565555bf3c90 100644 --- a/include/hw/opentitan/ot_soc_dbg_ctrl.h +++ b/include/hw/opentitan/ot_soc_dbg_ctrl.h @@ -43,11 +43,9 @@ typedef enum { /* input lines */ #define OT_SOC_DBG_HALT_CPU_BOOT TYPE_OT_SOC_DBG_CTRL "-halt-cpu-boot" -#define OT_SOC_DBG_LC_BCAST TYPE_OT_SOC_DBG_CTRL "-lc-broacast" +#define OT_SOC_DBG_LC_BCAST TYPE_OT_SOC_DBG_CTRL "-lc-broadcast" #define OT_SOC_DBG_STATE TYPE_OT_SOC_DBG_CTRL "-soc-dbg" #define OT_SOC_DBG_BOOT_STATUS TYPE_OT_SOC_DBG_CTRL "-boot-status" -#define OT_SOC_DBG_A0_DEBUG_EN TYPE_OT_SOC_DBG_CTRL "-a0-debug-en" -#define OT_SOC_DBG_A0_FORCE_RAW TYPE_OT_SOC_DBG_CTRL "-a0-force-raw" /* output lines */ #define OT_SOC_DBG_CPU_BOOT TYPE_OT_SOC_DBG_CTRL "-cpu-boot" From 26b1908d1aef0e4b6f062c6b829063da9fb51732 Mon Sep 17 00:00:00 2001 From: Emmanuel Blot Date: Fri, 7 Nov 2025 11:57:03 +0100 Subject: [PATCH 12/24] [ot] hw/opentitan: ot_soc_dbg_ctrl: rename `RAW` SoC debug state as `BLANK` to match new HW Signed-off-by: Emmanuel Blot --- hw/opentitan/ot_soc_dbg_ctrl.c | 6 +++--- include/hw/opentitan/ot_soc_dbg_ctrl.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/opentitan/ot_soc_dbg_ctrl.c b/hw/opentitan/ot_soc_dbg_ctrl.c index 2aa8c2c976574..df3dbf9b18f87 100644 --- a/hw/opentitan/ot_soc_dbg_ctrl.c +++ b/hw/opentitan/ot_soc_dbg_ctrl.c @@ -221,7 +221,7 @@ static const char *LC_BROADCAST_NAMES[] = { #define SOC_DBG_NAME_ENTRY(_st_) [OT_SOC_DBG_ST_##_st_] = stringify(_st_) static const char *SOC_DBG_NAMES[] = { /* clang-format off */ - SOC_DBG_NAME_ENTRY(RAW), + SOC_DBG_NAME_ENTRY(BLANK), SOC_DBG_NAME_ENTRY(PRE_PROD), SOC_DBG_NAME_ENTRY(PROD), /* clang-format on */ @@ -344,7 +344,7 @@ static void ot_soc_dbg_ctrl_tick_fsm(OtSoCDbgCtrlState *s) static void ot_soc_dbg_ctrl_update(OtSoCDbgCtrlState *s) { switch (s->soc_dbg_state) { - case OT_SOC_DBG_ST_RAW: + case OT_SOC_DBG_ST_BLANK: s->debug_policy = s->lc_broadcast_bm & (1u << OT_LC_DFT_EN) || s->lc_broadcast_bm & (1u << OT_LC_HW_DEBUG_EN) ? @@ -501,7 +501,7 @@ static void ot_soc_dbg_ctrl_soc_dbg_state(void *opaque, int n, int level) switch (level) { case 0: - s->soc_dbg_state = OT_SOC_DBG_ST_RAW; + s->soc_dbg_state = OT_SOC_DBG_ST_BLANK; break; case 1: s->soc_dbg_state = OT_SOC_DBG_ST_PRE_PROD; diff --git a/include/hw/opentitan/ot_soc_dbg_ctrl.h b/include/hw/opentitan/ot_soc_dbg_ctrl.h index 8565555bf3c90..197d85f47bb75 100644 --- a/include/hw/opentitan/ot_soc_dbg_ctrl.h +++ b/include/hw/opentitan/ot_soc_dbg_ctrl.h @@ -35,7 +35,7 @@ OBJECT_DECLARE_TYPE(OtSoCDbgCtrlState, OtSoCDbgCtrlClass, OT_SOC_DBG_CTRL) /* SocDbg controller states */ typedef enum { - OT_SOC_DBG_ST_RAW, + OT_SOC_DBG_ST_BLANK, OT_SOC_DBG_ST_PRE_PROD, OT_SOC_DBG_ST_PROD, OT_SOC_DBG_ST_COUNT, From af35a49fa4a6d0c997f8af489bbbd8dbe1c8b065 Mon Sep 17 00:00:00 2001 From: Emmanuel Blot Date: Fri, 7 Nov 2025 12:03:42 +0100 Subject: [PATCH 13/24] [ot] hw/opentitan: ot_soc_dbg_ctrl: remove lock/unlock properties Signed-off-by: Emmanuel Blot --- hw/opentitan/ot_soc_dbg_ctrl.c | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/hw/opentitan/ot_soc_dbg_ctrl.c b/hw/opentitan/ot_soc_dbg_ctrl.c index df3dbf9b18f87..24126bd1b8394 100644 --- a/hw/opentitan/ot_soc_dbg_ctrl.c +++ b/hw/opentitan/ot_soc_dbg_ctrl.c @@ -87,7 +87,7 @@ REG16(BOOT_STATUS, 0x0) REG16(SOC_DBG, 0x0) FIELD(SOC_DBG, HALT_CPU_BOOT, 2u, 1u) -/* debug_policy, dbg_locked, dbg_unlocked fields */ +/* debug_policy fields */ SHARED_FIELD(POLICY_CAT, 0u, 2u) SHARED_FIELD(POLICY_RELOCK, 2u, 1u) SHARED_FIELD(POLICY_UNUSED, 3u, 1u) @@ -152,8 +152,6 @@ struct OtSoCDbgCtrlState { bool debug_valid; char *ot_id; - uint8_t dbg_locked; - uint8_t dbg_unlocked; bool halt_function; bool dft_ignore; }; @@ -348,12 +346,12 @@ static void ot_soc_dbg_ctrl_update(OtSoCDbgCtrlState *s) s->debug_policy = s->lc_broadcast_bm & (1u << OT_LC_DFT_EN) || s->lc_broadcast_bm & (1u << OT_LC_HW_DEBUG_EN) ? - s->dbg_unlocked : - s->dbg_locked; + DEFAULT_DBG_UNLOCKED : + DEFAULT_DBG_LOCKED; s->debug_valid = (bool)(s->boot_status_bm & R_BOOT_STATUS_LC_DONE_MASK); break; case OT_SOC_DBG_ST_PRE_PROD: - s->debug_policy = s->dbg_unlocked; + s->debug_policy = DEFAULT_DBG_UNLOCKED; s->debug_valid = (bool)(s->boot_status_bm & R_BOOT_STATUS_LC_DONE_MASK); break; case OT_SOC_DBG_ST_PROD: @@ -362,7 +360,7 @@ static void ot_soc_dbg_ctrl_update(OtSoCDbgCtrlState *s) s->debug_valid = (bool)s->regs[R_CORE_DEBUG_POLICY_VALID]; break; default: - s->debug_policy = s->dbg_locked; + s->debug_policy = DEFAULT_DBG_LOCKED; s->debug_valid = false; } @@ -686,10 +684,6 @@ static void ot_soc_dbg_ctrl_dmi_write(void *opaque, hwaddr addr, uint64_t value, static Property ot_soc_dbg_ctrl_properties[] = { DEFINE_PROP_STRING(OT_COMMON_DEV_ID, OtSoCDbgCtrlState, ot_id), - DEFINE_PROP_UINT8("dbg_unlocked", OtSoCDbgCtrlState, dbg_unlocked, - DEFAULT_DBG_UNLOCKED), - DEFINE_PROP_UINT8("dbg_locked", OtSoCDbgCtrlState, dbg_locked, - DEFAULT_DBG_LOCKED), DEFINE_PROP_BOOL("halt_function", OtSoCDbgCtrlState, halt_function, true), DEFINE_PROP_BOOL("dft-ignore", OtSoCDbgCtrlState, dft_ignore, false), DEFINE_PROP_END_OF_LIST(), @@ -733,7 +727,7 @@ static void ot_soc_dbg_ctrl_reset_enter(Object *obj, ResetType type) s->boot_status_bm = 0u; s->lc_broadcast_bm = 0u; s->soc_dbg_state = OT_SOC_DBG_ST_PROD; - s->debug_policy = s->dbg_locked; + s->debug_policy = DEFAULT_DBG_LOCKED; s->debug_valid = false; s->boot_continue = false; } @@ -767,9 +761,6 @@ static void ot_soc_dbg_ctrl_realize(DeviceState *dev, Error **errp) (void)errp; g_assert(s->ot_id); - - s->dbg_locked &= POLICY_CAT_MASK | POLICY_RELOCK_MASK; - s->dbg_unlocked &= POLICY_CAT_MASK | POLICY_RELOCK_MASK; } static void ot_soc_dbg_ctrl_init(Object *obj) From 25eeb6a6e8e214ba35e38db5a7560d5e411a3870 Mon Sep 17 00:00:00 2001 From: Emmanuel Blot Date: Fri, 7 Nov 2025 12:06:55 +0100 Subject: [PATCH 14/24] [ot] hw/opentitan: ot_soc_dbg_ctrl: rename DMI as JTAG this matches the HW definitions, although the actual bus is still DMI. Signed-off-by: Emmanuel Blot --- hw/opentitan/ot_soc_dbg_ctrl.c | 72 +++++++++++++++++----------------- hw/opentitan/trace-events | 4 +- 2 files changed, 38 insertions(+), 38 deletions(-) diff --git a/hw/opentitan/ot_soc_dbg_ctrl.c b/hw/opentitan/ot_soc_dbg_ctrl.c index 24126bd1b8394..a00ddcf0fc091 100644 --- a/hw/opentitan/ot_soc_dbg_ctrl.c +++ b/hw/opentitan/ot_soc_dbg_ctrl.c @@ -56,7 +56,7 @@ REG32(CORE_DEBUG_POLICY_CTRL, 0x10u) REG32(CORE_DEBUG_POLICY_VALID, 0x14u) FIELD(CORE_DEBUG_POLICY_VALID, VALID, 0u, 1u) REG32(CORE_STATUS_MBX, 0x18u) - /* shared by CORE_STATUS_MBX and DMI_JTAG_STATUS */ + /* shared by CORE_STATUS_MBX and JTAG_STATUS */ SHARED_FIELD(AUTH_DEBUG_INTENT_SET, 0u, 1u) SHARED_FIELD(AUTH_WINDOW_OPEN, 4u, 1u) SHARED_FIELD(AUTH_WINDOW_CLOSED, 5u, 1u) @@ -66,11 +66,11 @@ REG32(CORE_STATUS_MBX, 0x18u) SHARED_FIELD(CURRENT_POLICY, 8u, 4u) SHARED_FIELD(REQUESTED_POLICY, 12u, 4u) -/* registers on DMI bus */ -REG32(DMI_CONTROL, 0x0) - FIELD(DMI_CONTROL, BOOT_CONTINUE, 0u, 1u) -REG32(DMI_JTAG_STATUS, 0x4) -REG32(DMI_JTAG_BOOT_STATUS, 0x8) +/* registers reachable from JTAG */ +REG32(JTAG_CONTROL, 0x0) + FIELD(JTAG_CONTROL, BOOT_CONTINUE, 0u, 1u) + REG32(JTAG_STATUS, 0x4) + REG32(JTAG_BOOT_STATUS, 0x8) /* boot_status_bm fields */ REG16(BOOT_STATUS, 0x0) @@ -100,9 +100,9 @@ SHARED_FIELD(POLICY_UNUSED, 3u, 1u) #define REGS_CORE_COUNT (R_CORE_LAST_REG + 1u) #define REGS_CORE_SIZE (REGS_CORE_COUNT * sizeof(uint32_t)) -#define R_DMI_LAST_REG (R_DMI_JTAG_BOOT_STATUS) -#define REGS_DMI_COUNT (R_DMI_LAST_REG + 1u) -#define REGS_DMI_SIZE (REGS_DMI_COUNT * sizeof(uint32_t)) +#define R_JTAG_LAST_REG (R_JTAG_BOOT_STATUS) +#define REGS_JTAG_COUNT (R_JTAG_LAST_REG + 1u) +#define REGS_JTAG_SIZE (REGS_JTAG_COUNT * sizeof(uint32_t)) #define CORE_ALERT_TEST_MASK (R_CORE_ALERT_TEST_FATAL_FAULT_MASK) #define STATUS_MASK \ @@ -133,7 +133,7 @@ struct OtSoCDbgCtrlState { SysBusDevice parent_obj; MemoryRegion core; - MemoryRegion dmi; + MemoryRegion jtag; IbexIRQ irq; IbexIRQ alert; IbexIRQ policy; @@ -182,11 +182,11 @@ static const char *REG_CORE_NAMES[REGS_CORE_COUNT] = { /* clang-format on */ }; -static const char *REG_DMI_NAMES[REGS_DMI_COUNT] = { +static const char *REG_JTAG_NAMES[REGS_JTAG_COUNT] = { /* clang-format off */ - REG_NAME_ENTRY(DMI_CONTROL), - REG_NAME_ENTRY(DMI_JTAG_STATUS), - REG_NAME_ENTRY(DMI_JTAG_BOOT_STATUS), + REG_NAME_ENTRY(JTAG_CONTROL), + REG_NAME_ENTRY(JTAG_STATUS), + REG_NAME_ENTRY(JTAG_BOOT_STATUS), /* clang-format on */ }; #undef REG_NAME_ENTRY @@ -614,7 +614,7 @@ static void ot_soc_dbg_ctrl_core_write(void *opaque, hwaddr addr, } static uint64_t -ot_soc_dbg_ctrl_dmi_read(void *opaque, hwaddr addr, unsigned size) +ot_soc_dbg_ctrl_jtag_read(void *opaque, hwaddr addr, unsigned size) { OtSoCDbgCtrlState *s = opaque; (void)size; @@ -622,13 +622,13 @@ ot_soc_dbg_ctrl_dmi_read(void *opaque, hwaddr addr, unsigned size) hwaddr reg = R32_OFF(addr); switch (reg) { - case R_DMI_CONTROL: - val32 = s->boot_continue ? R_DMI_CONTROL_BOOT_CONTINUE_MASK : 0u; + case R_JTAG_CONTROL: + val32 = s->boot_continue ? R_JTAG_CONTROL_BOOT_CONTINUE_MASK : 0u; break; - case R_DMI_JTAG_STATUS: + case R_JTAG_STATUS: val32 = s->regs[R_CORE_STATUS_MBX]; /* mirror of the core I/F */ break; - case R_DMI_JTAG_BOOT_STATUS: + case R_JTAG_BOOT_STATUS: if (s->lc_broadcast_bm & (1u << OT_LC_DFT_EN)) { val32 = (uint32_t)s->boot_status_bm; } else { @@ -646,14 +646,14 @@ ot_soc_dbg_ctrl_dmi_read(void *opaque, hwaddr addr, unsigned size) break; } - trace_ot_soc_dbg_ctrl_dmi_io_read_out(s->ot_id, (uint32_t)addr, - REG_NAME(DMI, reg), val32); + trace_ot_soc_dbg_ctrl_jtag_io_read_out(s->ot_id, (uint32_t)addr, + REG_NAME(JTAG, reg), val32); return (uint32_t)val32; } -static void ot_soc_dbg_ctrl_dmi_write(void *opaque, hwaddr addr, uint64_t value, - unsigned size) +static void ot_soc_dbg_ctrl_jtag_write(void *opaque, hwaddr addr, + uint64_t value, unsigned size) { OtSoCDbgCtrlState *s = opaque; (void)size; @@ -661,19 +661,19 @@ static void ot_soc_dbg_ctrl_dmi_write(void *opaque, hwaddr addr, uint64_t value, hwaddr reg = R32_OFF(addr); - trace_ot_soc_dbg_ctrl_dmi_io_write(s->ot_id, (uint32_t)addr, - REG_NAME(DMI, reg), val32); + trace_ot_soc_dbg_ctrl_jtag_io_write(s->ot_id, (uint32_t)addr, + REG_NAME(JTAG, reg), val32); switch (reg) { - case R_DMI_CONTROL: - s->boot_continue = (bool)(val32 & R_DMI_CONTROL_BOOT_CONTINUE_MASK); + case R_JTAG_CONTROL: + s->boot_continue = (bool)(val32 & R_JTAG_CONTROL_BOOT_CONTINUE_MASK); SCHEDULE_FSM(s); break; - case R_DMI_JTAG_STATUS: - case R_DMI_JTAG_BOOT_STATUS: + case R_JTAG_STATUS: + case R_JTAG_BOOT_STATUS: qemu_log_mask(LOG_GUEST_ERROR, "%s: %s: R/O register 0x%02" HWADDR_PRIx " (%s)\n", - __func__, s->ot_id, addr, REG_NAME(DMI, reg)); + __func__, s->ot_id, addr, REG_NAME(JTAG, reg)); break; default: qemu_log_mask(LOG_GUEST_ERROR, @@ -697,9 +697,9 @@ static const MemoryRegionOps ot_soc_dbg_ctrl_core_ops = { .impl.max_access_size = 4u, }; -static const MemoryRegionOps ot_soc_dbg_ctrl_dmi_ops = { - .read = &ot_soc_dbg_ctrl_dmi_read, - .write = &ot_soc_dbg_ctrl_dmi_write, +static const MemoryRegionOps ot_soc_dbg_ctrl_jtag_ops = { + .read = &ot_soc_dbg_ctrl_jtag_read, + .write = &ot_soc_dbg_ctrl_jtag_write, .endianness = DEVICE_NATIVE_ENDIAN, .impl.min_access_size = 4u, .impl.max_access_size = 4u, @@ -771,9 +771,9 @@ static void ot_soc_dbg_ctrl_init(Object *obj) TYPE_OT_SOC_DBG_CTRL, REGS_CORE_SIZE); sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->core); - memory_region_init_io(&s->dmi, obj, &ot_soc_dbg_ctrl_dmi_ops, s, - TYPE_OT_SOC_DBG_CTRL, REGS_DMI_SIZE); - sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->dmi); + memory_region_init_io(&s->jtag, obj, &ot_soc_dbg_ctrl_jtag_ops, s, + TYPE_OT_SOC_DBG_CTRL, REGS_JTAG_SIZE); + sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->jtag); ibex_sysbus_init_irq(obj, &s->irq); ibex_qdev_init_irq(obj, &s->alert, OT_DEVICE_ALERT); diff --git a/hw/opentitan/trace-events b/hw/opentitan/trace-events index 4a604f8e61387..cea375edb703d 100644 --- a/hw/opentitan/trace-events +++ b/hw/opentitan/trace-events @@ -528,8 +528,8 @@ ot_soc_dbg_ctrl_cpu_boot_done(const char *id, int level) "%s: %d" ot_soc_dbg_ctrl_core_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_soc_dbg_ctrl_core_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_soc_dbg_ctrl_core_update_irq(const char *id, int new) "%s: %u" -ot_soc_dbg_ctrl_dmi_io_read_out(const char *id, uint32_t addr, const char * regname, uint32_t val) "%s: addr=0x%02x (%s), val=0x%x" -ot_soc_dbg_ctrl_dmi_io_write(const char *id, uint32_t addr, const char * regname, uint32_t val) "%s: addr=0x%02x (%s), val=0x%x" +ot_soc_dbg_ctrl_jtag_io_read_out(const char *id, uint32_t addr, const char * regname, uint32_t val) "%s: addr=0x%02x (%s), val=0x%x" +ot_soc_dbg_ctrl_jtag_io_write(const char *id, uint32_t addr, const char * regname, uint32_t val) "%s: addr=0x%02x (%s), val=0x%x" ot_soc_dbg_ctrl_rcv(const char *id, const char *src, unsigned n, char sig) "%s: %s #%d: lvl %c" ot_soc_dbg_ctrl_schedule_fsm(const char *id, const char *func, int line, unsigned tc) "%s: @ %s:%d (%u)" ot_soc_dbg_ctrl_soc_dbg_state(const char *id, const char *st) "%s: %s" From 65038da3abc3da28c5ca74db1ed294a1ced0a0e6 Mon Sep 17 00:00:00 2001 From: Emmanuel Blot Date: Fri, 7 Nov 2025 13:07:23 +0100 Subject: [PATCH 15/24] [ot] hw/opentitan: ot_soc_dbg_ctrl: rename `cpu_boot` as `continue_cpu_boot` to match HW Signed-off-by: Emmanuel Blot --- hw/opentitan/ot_soc_dbg_ctrl.c | 26 ++++++++++++++------------ include/hw/opentitan/ot_soc_dbg_ctrl.h | 4 ++-- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/hw/opentitan/ot_soc_dbg_ctrl.c b/hw/opentitan/ot_soc_dbg_ctrl.c index a00ddcf0fc091..ab86f2d4cb927 100644 --- a/hw/opentitan/ot_soc_dbg_ctrl.c +++ b/hw/opentitan/ot_soc_dbg_ctrl.c @@ -114,10 +114,10 @@ SHARED_FIELD(POLICY_UNUSED, 3u, 1u) #define DEFAULT_DBG_LOCKED 7u enum { - CPU_BOOT_GOOD, - CPU_BOOT_DONE, - CPU_BOOT_COUNT, -} OtSoCDbgCpuBoot; + CONTINUE_CPU_BOOT_GOOD, + CONTINUE_CPU_BOOT_DONE, + CONTINUE_CPU_BOOT_COUNT, +} OtSoCDbgContinueCpuBoot; typedef enum { ST_IDLE, @@ -137,7 +137,7 @@ struct OtSoCDbgCtrlState { IbexIRQ irq; IbexIRQ alert; IbexIRQ policy; - IbexIRQ cpu_boot[CPU_BOOT_COUNT]; /* "continue_cpu_boot" */ + IbexIRQ continue_cpu_boot[CONTINUE_CPU_BOOT_COUNT]; QEMUBH *fsm_tick_bh; uint32_t regs[REGS_CORE_COUNT]; @@ -333,10 +333,12 @@ static void ot_soc_dbg_ctrl_tick_fsm(OtSoCDbgCtrlState *s) /* as with PwrMgr, use simple boolean value, not MuBi4 */ int cpu_boot_done_i = (int)cpu_boot_done; - if (ibex_irq_get_level(&s->cpu_boot[CPU_BOOT_DONE]) != cpu_boot_done_i) { + if (ibex_irq_get_level(&s->continue_cpu_boot[CONTINUE_CPU_BOOT_DONE]) != + cpu_boot_done_i) { trace_ot_soc_dbg_ctrl_cpu_boot_done(s->ot_id, cpu_boot_done_i); } - ibex_irq_set(&s->cpu_boot[CPU_BOOT_DONE], cpu_boot_done_i); + ibex_irq_set(&s->continue_cpu_boot[CONTINUE_CPU_BOOT_DONE], + cpu_boot_done_i); } static void ot_soc_dbg_ctrl_update(OtSoCDbgCtrlState *s) @@ -718,8 +720,8 @@ static void ot_soc_dbg_ctrl_reset_enter(Object *obj, ResetType type) ot_soc_dbg_ctrl_core_update_irq(s); ibex_irq_set(&s->alert, 0); - ibex_irq_set(&s->cpu_boot[CPU_BOOT_GOOD], (int)false); - ibex_irq_set(&s->cpu_boot[CPU_BOOT_DONE], (int)false); + ibex_irq_set(&s->continue_cpu_boot[CONTINUE_CPU_BOOT_GOOD], (int)false); + ibex_irq_set(&s->continue_cpu_boot[CONTINUE_CPU_BOOT_DONE], (int)false); CHANGE_STATE(s, IDLE); s->fsm_tick_count = 0u; @@ -750,7 +752,7 @@ static void ot_soc_dbg_ctrl_reset_exit(Object *obj, ResetType type) */ s->boot_status_bm |= ROM_MASK << R_BOOT_STATUS_ROM_CTRL_GOOD_SHIFT; - ibex_irq_set(&s->cpu_boot[CPU_BOOT_GOOD], (int)true); + ibex_irq_set(&s->continue_cpu_boot[CONTINUE_CPU_BOOT_GOOD], (int)true); SCHEDULE_FSM(s); } @@ -778,8 +780,8 @@ static void ot_soc_dbg_ctrl_init(Object *obj) ibex_sysbus_init_irq(obj, &s->irq); ibex_qdev_init_irq(obj, &s->alert, OT_DEVICE_ALERT); ibex_qdev_init_irq(obj, &s->policy, OT_SOC_DBG_DEBUG_POLICY); - ibex_qdev_init_irqs(obj, s->cpu_boot, OT_SOC_DBG_CPU_BOOT, - ARRAY_SIZE(s->cpu_boot)); + ibex_qdev_init_irqs(obj, s->continue_cpu_boot, OT_SOC_DBG_CONTINUE_CPU_BOOT, + ARRAY_SIZE(s->continue_cpu_boot)); qdev_init_gpio_in_named(DEVICE(obj), &ot_soc_dbg_ctrl_halt_cpu_boot, OT_SOC_DBG_HALT_CPU_BOOT, 1); diff --git a/include/hw/opentitan/ot_soc_dbg_ctrl.h b/include/hw/opentitan/ot_soc_dbg_ctrl.h index 197d85f47bb75..aab963cad5759 100644 --- a/include/hw/opentitan/ot_soc_dbg_ctrl.h +++ b/include/hw/opentitan/ot_soc_dbg_ctrl.h @@ -48,8 +48,8 @@ typedef enum { #define OT_SOC_DBG_BOOT_STATUS TYPE_OT_SOC_DBG_CTRL "-boot-status" /* output lines */ -#define OT_SOC_DBG_CPU_BOOT TYPE_OT_SOC_DBG_CTRL "-cpu-boot" -#define OT_SOC_DBG_DEBUG_POLICY TYPE_OT_SOC_DBG_CTRL "-debug-policy" +#define OT_SOC_DBG_CONTINUE_CPU_BOOT TYPE_OT_SOC_DBG_CTRL "-continue-cpu-boot" +#define OT_SOC_DBG_DEBUG_POLICY TYPE_OT_SOC_DBG_CTRL "-debug-policy" #define OT_SOC_DBG_DEBUG_POLICY_MASK 0x0fu #define OT_SOC_DBG_DEBUG_VALID_MASK 0x80u From daf37df3ad2b1bd0c3fa95dc64dd505ba9b16f0b Mon Sep 17 00:00:00 2001 From: Emmanuel Blot Date: Fri, 7 Nov 2025 13:25:01 +0100 Subject: [PATCH 16/24] [ot] hw/opentitan: ot_soc_dbg_ctrl: remove IRQ managemnt there is no IRQ in new HW Signed-off-by: Emmanuel Blot --- hw/opentitan/ot_soc_dbg_ctrl.c | 40 ---------------------------------- 1 file changed, 40 deletions(-) diff --git a/hw/opentitan/ot_soc_dbg_ctrl.c b/hw/opentitan/ot_soc_dbg_ctrl.c index ab86f2d4cb927..b47bbaa2117c9 100644 --- a/hw/opentitan/ot_soc_dbg_ctrl.c +++ b/hw/opentitan/ot_soc_dbg_ctrl.c @@ -44,10 +44,6 @@ /* clang-format off */ /* registers on core bus */ -REG32(CORE_INTR_STATE, 0x00) - SHARED_FIELD(INTR_DEBUG_ATTENTION, 0u, 1u) -REG32(CORE_INTR_ENABLE, 0x04u) -REG32(CORE_INTR_TEST, 0x08u) REG32(CORE_ALERT_TEST, 0x0cu) FIELD(CORE_ALERT_TEST, FATAL_FAULT, 0u, 1u) REG32(CORE_DEBUG_POLICY_CTRL, 0x10u) @@ -134,7 +130,6 @@ struct OtSoCDbgCtrlState { MemoryRegion core; MemoryRegion jtag; - IbexIRQ irq; IbexIRQ alert; IbexIRQ policy; IbexIRQ continue_cpu_boot[CONTINUE_CPU_BOOT_COUNT]; @@ -172,9 +167,6 @@ struct OtSoCDbgCtrlClass { static const char *REG_CORE_NAMES[REGS_CORE_COUNT] = { /* clang-format off */ - REG_NAME_ENTRY(CORE_INTR_STATE), - REG_NAME_ENTRY(CORE_INTR_ENABLE), - REG_NAME_ENTRY(CORE_INTR_TEST), REG_NAME_ENTRY(CORE_ALERT_TEST), REG_NAME_ENTRY(CORE_DEBUG_POLICY_CTRL), REG_NAME_ENTRY(CORE_DEBUG_POLICY_VALID), @@ -250,18 +242,6 @@ static const char *STATE_NAMES[] = { ot_soc_dbg_ctrl_change_state_line(_s_, ST_##_st_, __LINE__) #define SCHEDULE_FSM(_s_) ot_soc_dbg_ctrl_schedule_fsm(_s_, __func__, __LINE__) -static void ot_soc_dbg_ctrl_core_update_irq(OtSoCDbgCtrlState *s) -{ - uint32_t levels = s->regs[R_CORE_INTR_STATE] & s->regs[R_CORE_INTR_ENABLE]; - - int level = (int)(bool)(levels & INTR_DEBUG_ATTENTION_MASK); - if (level != ibex_irq_get_level(&s->irq)) { - trace_ot_soc_dbg_ctrl_core_update_irq(s->ot_id, level); - } - - ibex_irq_set(&s->irq, level); -} - static void ot_soc_dbg_ctrl_change_state_line( OtSoCDbgCtrlState *s, OtSoCDbgCtrlFsmState state, int line) { @@ -532,14 +512,11 @@ ot_soc_dbg_ctrl_core_read(void *opaque, hwaddr addr, unsigned size) hwaddr reg = R32_OFF(addr); switch (reg) { /* note: interrupt usage is not specified */ - case R_CORE_INTR_STATE: - case R_CORE_INTR_ENABLE: case R_CORE_DEBUG_POLICY_CTRL: case R_CORE_DEBUG_POLICY_VALID: case R_CORE_STATUS_MBX: val32 = s->regs[reg]; break; - case R_CORE_INTR_TEST: case R_CORE_ALERT_TEST: qemu_log_mask(LOG_GUEST_ERROR, "%s: %s: W/O register 0x%02" HWADDR_PRIx " (%s)\n", @@ -575,21 +552,6 @@ static void ot_soc_dbg_ctrl_core_write(void *opaque, hwaddr addr, REG_NAME(CORE, reg), val32, pc); switch (reg) { - case R_CORE_INTR_STATE: - val32 &= INTR_DEBUG_ATTENTION_MASK; - s->regs[reg] &= ~val32; /* RW1C */ - ot_soc_dbg_ctrl_core_update_irq(s); - break; - case R_CORE_INTR_ENABLE: - val32 &= INTR_DEBUG_ATTENTION_MASK; - s->regs[reg] = val32; - ot_soc_dbg_ctrl_core_update_irq(s); - break; - case R_CORE_INTR_TEST: - val32 &= INTR_DEBUG_ATTENTION_MASK; - s->regs[reg] |= val32; /* RW1S */ - ot_soc_dbg_ctrl_core_update_irq(s); - break; case R_CORE_ALERT_TEST: val32 &= CORE_ALERT_TEST_MASK; if (val32) { @@ -718,7 +680,6 @@ static void ot_soc_dbg_ctrl_reset_enter(Object *obj, ResetType type) memset(s->regs, 0, sizeof(s->regs)); - ot_soc_dbg_ctrl_core_update_irq(s); ibex_irq_set(&s->alert, 0); ibex_irq_set(&s->continue_cpu_boot[CONTINUE_CPU_BOOT_GOOD], (int)false); ibex_irq_set(&s->continue_cpu_boot[CONTINUE_CPU_BOOT_DONE], (int)false); @@ -777,7 +738,6 @@ static void ot_soc_dbg_ctrl_init(Object *obj) TYPE_OT_SOC_DBG_CTRL, REGS_JTAG_SIZE); sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->jtag); - ibex_sysbus_init_irq(obj, &s->irq); ibex_qdev_init_irq(obj, &s->alert, OT_DEVICE_ALERT); ibex_qdev_init_irq(obj, &s->policy, OT_SOC_DBG_DEBUG_POLICY); ibex_qdev_init_irqs(obj, s->continue_cpu_boot, OT_SOC_DBG_CONTINUE_CPU_BOOT, From c37d3de9e9a206c30151c42294935d249232ec1b Mon Sep 17 00:00:00 2001 From: Emmanuel Blot Date: Fri, 7 Nov 2025 13:35:20 +0100 Subject: [PATCH 17/24] [ot] hw/opentitan: ot_soc_dbg_ctrl: update ALERT management to match new HW: there are two alert channels (fatal and recoverable) Signed-off-by: Emmanuel Blot --- hw/opentitan/ot_soc_dbg_ctrl.c | 61 ++++++++++++++++++++++++++++------ 1 file changed, 51 insertions(+), 10 deletions(-) diff --git a/hw/opentitan/ot_soc_dbg_ctrl.c b/hw/opentitan/ot_soc_dbg_ctrl.c index b47bbaa2117c9..ef0b924f3c976 100644 --- a/hw/opentitan/ot_soc_dbg_ctrl.c +++ b/hw/opentitan/ot_soc_dbg_ctrl.c @@ -41,11 +41,14 @@ #include "hw/riscv/ibex_irq.h" #include "trace.h" +#define NUM_ALERTS 2u + /* clang-format off */ /* registers on core bus */ REG32(CORE_ALERT_TEST, 0x0cu) FIELD(CORE_ALERT_TEST, FATAL_FAULT, 0u, 1u) + FIELD(CORE_ALERT_TEST, RECOV_CTRL_UPDATE_ERR, 1u, 1u) REG32(CORE_DEBUG_POLICY_CTRL, 0x10u) /* 4 bits as it seems to be relock (1) + policy (3) */ FIELD(CORE_DEBUG_POLICY_CTRL, LEVEL, 0u, 4u) @@ -100,7 +103,9 @@ SHARED_FIELD(POLICY_UNUSED, 3u, 1u) #define REGS_JTAG_COUNT (R_JTAG_LAST_REG + 1u) #define REGS_JTAG_SIZE (REGS_JTAG_COUNT * sizeof(uint32_t)) -#define CORE_ALERT_TEST_MASK (R_CORE_ALERT_TEST_FATAL_FAULT_MASK) +#define CORE_ALERT_TEST_WMASK \ + (R_CORE_ALERT_TEST_FATAL_FAULT_MASK | \ + R_CORE_ALERT_TEST_RECOV_CTRL_UPDATE_ERR_MASK) #define STATUS_MASK \ (AUTH_DEBUG_INTENT_SET_MASK | AUTH_WINDOW_OPEN_MASK | \ AUTH_WINDOW_CLOSED_MASK | AUTH_UNLOCK_SUCCESS_MASK | \ @@ -125,12 +130,18 @@ typedef enum { ST_HALT_DONE, } OtSoCDbgCtrlFsmState; +typedef enum { + ALERT_FATAL, + ALERT_RECOV, + ALERT_COUNT, +} OtSoCDbgAlert; + struct OtSoCDbgCtrlState { SysBusDevice parent_obj; MemoryRegion core; MemoryRegion jtag; - IbexIRQ alert; + IbexIRQ alerts[ALERT_COUNT]; IbexIRQ policy; IbexIRQ continue_cpu_boot[CONTINUE_CPU_BOOT_COUNT]; QEMUBH *fsm_tick_bh; @@ -143,6 +154,8 @@ struct OtSoCDbgCtrlState { uint16_t boot_status_bm; /* BOOT_STATUS fields */ uint16_t soc_dbg_bm; /* SOC_DBG fields */ uint16_t lc_broadcast_bm; /* OtLcCtrlBroadcast fields */ + uint8_t fatal_alert_bm; + uint8_t recov_alert_bm; bool boot_continue; bool debug_valid; @@ -155,6 +168,7 @@ struct OtSoCDbgCtrlClass { SysBusDeviceClass parent_class; ResettablePhases parent_phases; }; +static_assert(ALERT_COUNT == NUM_ALERTS, "Invalid alert count"); #define ROM_MASK ((1u << (R_BOOT_STATUS_ROM_CTRL_DONE_LENGTH - 1u)) - 1u) @@ -251,6 +265,26 @@ static void ot_soc_dbg_ctrl_change_state_line( s->fsm_state = state; } +static void +ot_soc_dbg_ctrl_update_alerts(OtSoCDbgCtrlState *s, uint32_t test_bm) +{ + bool alert; + + alert = (bool)s->fatal_alert_bm | + (bool)(test_bm & R_CORE_ALERT_TEST_FATAL_FAULT_MASK); + ibex_irq_set(&s->alerts[ALERT_FATAL], (int)alert); + + alert = (bool)s->recov_alert_bm | + (bool)(test_bm & R_CORE_ALERT_TEST_RECOV_CTRL_UPDATE_ERR_MASK); + ibex_irq_set(&s->alerts[ALERT_RECOV], (int)alert); + + if (test_bm) { + /* alert test is transient */ + ibex_irq_set(&s->alerts[ALERT_FATAL], (int)(bool)s->fatal_alert_bm); + ibex_irq_set(&s->alerts[ALERT_RECOV], (int)(bool)s->recov_alert_bm); + } +} + static void ot_soc_dbg_ctrl_schedule_fsm(OtSoCDbgCtrlState *s, const char *func, int line) { @@ -306,8 +340,12 @@ static void ot_soc_dbg_ctrl_tick_fsm(OtSoCDbgCtrlState *s) cpu_boot_done = true; break; default: - /* it does not seem there is a special state for this case */ - ibex_irq_set(&s->alert, (int)true); + /* + * it does not seem there is a special state for this case, i.e. + * the FSM does not enter a special error state, it only raises + * an alert. + */ + ibex_irq_set(&s->alerts[ALERT_FATAL], (int)true); return; } @@ -553,10 +591,8 @@ static void ot_soc_dbg_ctrl_core_write(void *opaque, hwaddr addr, switch (reg) { case R_CORE_ALERT_TEST: - val32 &= CORE_ALERT_TEST_MASK; - if (val32) { - ibex_irq_set(&s->alert, 1); - } + val32 &= CORE_ALERT_TEST_WMASK; + ot_soc_dbg_ctrl_update_alerts(s, val32); break; case R_CORE_DEBUG_POLICY_CTRL: val32 &= R_CORE_DEBUG_POLICY_CTRL_LEVEL_MASK; @@ -680,7 +716,6 @@ static void ot_soc_dbg_ctrl_reset_enter(Object *obj, ResetType type) memset(s->regs, 0, sizeof(s->regs)); - ibex_irq_set(&s->alert, 0); ibex_irq_set(&s->continue_cpu_boot[CONTINUE_CPU_BOOT_GOOD], (int)false); ibex_irq_set(&s->continue_cpu_boot[CONTINUE_CPU_BOOT_DONE], (int)false); @@ -693,6 +728,10 @@ static void ot_soc_dbg_ctrl_reset_enter(Object *obj, ResetType type) s->debug_policy = DEFAULT_DBG_LOCKED; s->debug_valid = false; s->boot_continue = false; + s->fatal_alert_bm = 0u; + s->recov_alert_bm = 0u; + + ot_soc_dbg_ctrl_update_alerts(s, 0u); } static void ot_soc_dbg_ctrl_reset_exit(Object *obj, ResetType type) @@ -738,7 +777,9 @@ static void ot_soc_dbg_ctrl_init(Object *obj) TYPE_OT_SOC_DBG_CTRL, REGS_JTAG_SIZE); sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->jtag); - ibex_qdev_init_irq(obj, &s->alert, OT_DEVICE_ALERT); + for (unsigned ix = 0; ix < NUM_ALERTS; ix++) { + ibex_qdev_init_irq(obj, &s->alerts[ix], OT_DEVICE_ALERT); + } ibex_qdev_init_irq(obj, &s->policy, OT_SOC_DBG_DEBUG_POLICY); ibex_qdev_init_irqs(obj, s->continue_cpu_boot, OT_SOC_DBG_CONTINUE_CPU_BOOT, ARRAY_SIZE(s->continue_cpu_boot)); From 6a8da3986a19873b96637649e30f80abeb272e9a Mon Sep 17 00:00:00 2001 From: Emmanuel Blot Date: Wed, 12 Nov 2025 11:49:28 +0100 Subject: [PATCH 18/24] [ot] hw/opentitan: ot_soc_dbg_ctrl: redefine state machine and signal management to match new HW Signed-off-by: Emmanuel Blot --- hw/opentitan/ot_soc_dbg_ctrl.c | 474 +++++++++++++++++++++------------ hw/opentitan/trace-events | 7 +- 2 files changed, 307 insertions(+), 174 deletions(-) diff --git a/hw/opentitan/ot_soc_dbg_ctrl.c b/hw/opentitan/ot_soc_dbg_ctrl.c index ef0b924f3c976..a15d584b0d978 100644 --- a/hw/opentitan/ot_soc_dbg_ctrl.c +++ b/hw/opentitan/ot_soc_dbg_ctrl.c @@ -24,6 +24,8 @@ * 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. + * + * Based on OpenTitan c5507b4cdc */ #include "qemu/osdep.h" @@ -45,74 +47,71 @@ /* clang-format off */ -/* registers on core bus */ -REG32(CORE_ALERT_TEST, 0x0cu) +/* + * registers on core bus + * note: use shared register definition to avoid defining unreadable constants + */ +REG32(CORE_ALERT_TEST, 0x00u) FIELD(CORE_ALERT_TEST, FATAL_FAULT, 0u, 1u) FIELD(CORE_ALERT_TEST, RECOV_CTRL_UPDATE_ERR, 1u, 1u) -REG32(CORE_DEBUG_POLICY_CTRL, 0x10u) - /* 4 bits as it seems to be relock (1) + policy (3) */ - FIELD(CORE_DEBUG_POLICY_CTRL, LEVEL, 0u, 4u) -REG32(CORE_DEBUG_POLICY_VALID, 0x14u) - FIELD(CORE_DEBUG_POLICY_VALID, VALID, 0u, 1u) -REG32(CORE_STATUS_MBX, 0x18u) - /* shared by CORE_STATUS_MBX and JTAG_STATUS */ +REG32(CORE_DEBUG_POLICY_VALID_SHADOWED, 0x04u) + SHARED_FIELD(DEBUG_POLICY_VALID, 0u, OT_MULTIBITBOOL4_WIDTH) +REG32(CORE_DEBUG_POLICY_CATEGORY_SHADOWED, 0x08u) + SHARED_FIELD(DEBUG_POLICY_CATEGORY, 0u, 7u) +REG32(CORE_DEBUG_POLICY_RELOCKED, 0x0cu) + SHARED_FIELD(DEBUG_POLICY_RELOCKED, 0u, OT_MULTIBITBOOL4_WIDTH) +REG32(CORE_TRACE_DEBUG_POLICY_CATEGORY, 0x10u) + SHARED_FIELD(TRACE_DEBUG_POLICY_CATEGORY, 0u, 7u) +REG32(CORE_TRACE_DEBUG_POLICY_VALID_RELOCKED, 0x14u) + SHARED_FIELD(TRACE_DEBUG_POLICY_VALID_RELOCKED_VALID, 0u, + OT_MULTIBITBOOL4_WIDTH) + SHARED_FIELD(TRACE_DEBUG_POLICY_VALID_RELOCKED_RELOCKED, 4u, + OT_MULTIBITBOOL4_WIDTH) +REG32(CORE_STATUS, 0x18u) SHARED_FIELD(AUTH_DEBUG_INTENT_SET, 0u, 1u) SHARED_FIELD(AUTH_WINDOW_OPEN, 4u, 1u) SHARED_FIELD(AUTH_WINDOW_CLOSED, 5u, 1u) SHARED_FIELD(AUTH_UNLOCK_SUCCESS, 6u, 1u) SHARED_FIELD(AUTH_UNLOCK_FAILED, 7u, 1u) - /* this is not HW-connected to CORE_DEBUG_POLICY_CTRL */ - SHARED_FIELD(CURRENT_POLICY, 8u, 4u) - SHARED_FIELD(REQUESTED_POLICY, 12u, 4u) /* registers reachable from JTAG */ -REG32(JTAG_CONTROL, 0x0) +REG32(JTAG_TRACE_DEBUG_POLICY_CATEGORY, 0x00u) +REG32(JTAG_TRACE_DEBUG_POLICY_VALID_RELOCKED, 0x04u) +REG32(JTAG_CONTROL, 0x08u) FIELD(JTAG_CONTROL, BOOT_CONTINUE, 0u, 1u) - REG32(JTAG_STATUS, 0x4) - REG32(JTAG_BOOT_STATUS, 0x8) - -/* boot_status_bm fields */ -REG16(BOOT_STATUS, 0x0) - FIELD(BOOT_STATUS, MAIN_CLK_STATUS, 0u, 1u) - FIELD(BOOT_STATUS, IO_CLK_STATUS, 1u, 1u) - FIELD(BOOT_STATUS, USB_CLK_STATUS, 2u, 1u) - FIELD(BOOT_STATUS, OTP_DONE, 3u, 1u) - FIELD(BOOT_STATUS, LC_DONE, 4u, 1u) - FIELD(BOOT_STATUS, ROM_CTRL_DONE, 5u, 3u) - FIELD(BOOT_STATUS, ROM_CTRL_GOOD, 8u, 3u) - FIELD(BOOT_STATUS, CPU_FETCH_EN, 11u, 1u) - -/* soc_dbg_bm fields */ -REG16(SOC_DBG, 0x0) - FIELD(SOC_DBG, HALT_CPU_BOOT, 2u, 1u) - -/* debug_policy fields */ -SHARED_FIELD(POLICY_CAT, 0u, 2u) -SHARED_FIELD(POLICY_RELOCK, 2u, 1u) -SHARED_FIELD(POLICY_UNUSED, 3u, 1u) +REG32(JTAG_STATUS, 0x0cu) +REG32(JTAG_BOOT_STATUS, 0x10u) + FIELD(JTAG_BOOT_STATUS, MAIN_CLK_STATUS, 0u, 1u) + FIELD(JTAG_BOOT_STATUS, IO_CLK_STATUS, 1u, 1u) + FIELD(JTAG_BOOT_STATUS, OTP_DONE, 2u, 1u) + FIELD(JTAG_BOOT_STATUS, LC_DONE, 3u, 1u) + FIELD(JTAG_BOOT_STATUS, CPU_FETCH_EN, 4u, 1u) + FIELD(JTAG_BOOT_STATUS, HALT_FSM_STATE, 5u, 6u) + FIELD(JTAG_BOOT_STATUS, BOOT_GREENLIGHT_DONE, 11u, 3u) + FIELD(JTAG_BOOT_STATUS, BOOT_GREENLIGHT_GOOD, 14u, 3u) +REG32(JTAG_TRACE_SOC_DBG_STATE, 0x14u) /* clang-format on */ #define R32_OFF(_r_) ((_r_) / sizeof(uint32_t)) -#define R_CORE_LAST_REG (R_CORE_STATUS_MBX) +#define R_CORE_LAST_REG (R_CORE_STATUS) #define REGS_CORE_COUNT (R_CORE_LAST_REG + 1u) #define REGS_CORE_SIZE (REGS_CORE_COUNT * sizeof(uint32_t)) -#define R_JTAG_LAST_REG (R_JTAG_BOOT_STATUS) +#define R_JTAG_LAST_REG (R_JTAG_TRACE_SOC_DBG_STATE) #define REGS_JTAG_COUNT (R_JTAG_LAST_REG + 1u) #define REGS_JTAG_SIZE (REGS_JTAG_COUNT * sizeof(uint32_t)) #define CORE_ALERT_TEST_WMASK \ (R_CORE_ALERT_TEST_FATAL_FAULT_MASK | \ R_CORE_ALERT_TEST_RECOV_CTRL_UPDATE_ERR_MASK) -#define STATUS_MASK \ +#define CORE_STATUS_WMASK \ (AUTH_DEBUG_INTENT_SET_MASK | AUTH_WINDOW_OPEN_MASK | \ AUTH_WINDOW_CLOSED_MASK | AUTH_UNLOCK_SUCCESS_MASK | \ - AUTH_UNLOCK_FAILED_MASK | CURRENT_POLICY_MASK | REQUESTED_POLICY_MASK) - -#define DEFAULT_DBG_UNLOCKED 0u -#define DEFAULT_DBG_LOCKED 7u + AUTH_UNLOCK_FAILED_MASK) +#define BOOT_ROM_MASK \ + ((1u << (R_JTAG_BOOT_STATUS_BOOT_GREENLIGHT_DONE_LENGTH)) - 1u) enum { CONTINUE_CPU_BOOT_GOOD, @@ -122,12 +121,12 @@ enum { typedef enum { ST_IDLE, - ST_CHECK_LC_ST, - ST_WAIT4_DFT_EN, + ST_CHECK_LC_STATE, + ST_WAIT4DFT_EN, ST_CHECK_HALT_PIN, ST_CHECK_JTAG_GO, - ST_CONTINUE_BOOT, ST_HALT_DONE, + ST_COUNT, } OtSoCDbgCtrlFsmState; typedef enum { @@ -136,31 +135,60 @@ typedef enum { ALERT_COUNT, } OtSoCDbgAlert; +typedef enum { + ALERT_RECOV_POLICY_VALID, + ALERT_RECOV_POLICY_CATEGORY, + ALERT_RECOV_COUNT, +} OtSoCDbgRecovAlert; + +typedef enum { + OT_SOC_DBG_CATEGORY_LOCKED = 0b1010000, + OT_SOC_DBG_CATEGORY_2 = 0b1001101, + OT_SOC_DBG_CATEGORY_3 = 0b0001010, + OT_SOC_DBG_CATEGORY_4 = 0b1100011, +} OtSocDbgCategory; + +typedef struct { + /* can be any value, comes either from a register or local value */ + uint8_t cat; + /* can be any 4-bit value, from a register or local value */ + ot_mb4_t relocked; + /* only local, a regular bool is sufficient */ + bool valid; +} OtSocDbgPolicy; + +typedef struct { + struct { + OtShadowReg valid; + OtShadowReg category; + uint32_t relocked; + } debug_policy; + uint32_t status; +} OtSoCDbgCtrlRegs; + struct OtSoCDbgCtrlState { SysBusDevice parent_obj; MemoryRegion core; MemoryRegion jtag; IbexIRQ alerts[ALERT_COUNT]; - IbexIRQ policy; + IbexIRQ debug_policy; IbexIRQ continue_cpu_boot[CONTINUE_CPU_BOOT_COUNT]; QEMUBH *fsm_tick_bh; - uint32_t regs[REGS_CORE_COUNT]; + OtSoCDbgCtrlRegs regs; OtSoCDbgCtrlFsmState fsm_state; OtSoCDbgState soc_dbg_state; - unsigned debug_policy; + OtSocDbgPolicy soc_dbg_policy; /* calculated policy */ unsigned fsm_tick_count; - uint16_t boot_status_bm; /* BOOT_STATUS fields */ - uint16_t soc_dbg_bm; /* SOC_DBG fields */ + OtPwrMgrBootStatus pwr_boot_status; uint16_t lc_broadcast_bm; /* OtLcCtrlBroadcast fields */ uint8_t fatal_alert_bm; uint8_t recov_alert_bm; + bool halt_cpu_boot; bool boot_continue; - bool debug_valid; char *ot_id; - bool halt_function; bool dft_ignore; }; @@ -168,7 +196,21 @@ struct OtSoCDbgCtrlClass { SysBusDeviceClass parent_class; ResettablePhases parent_phases; }; + +/* clang-format off */ +static const uint8_t OT_SOC_DBG_FSM_STATE[ST_COUNT] = { + [ST_IDLE] = 0b101000u, + [ST_CHECK_LC_STATE] = 0b011101u, + [ST_WAIT4DFT_EN] = 0b000110u, + [ST_CHECK_HALT_PIN] = 0b110011u, + [ST_CHECK_JTAG_GO] = 0b111110u, + [ST_HALT_DONE] = 0b100101u, +}; +/* clang-format on */ + static_assert(ALERT_COUNT == NUM_ALERTS, "Invalid alert count"); +static_assert(OT_SOC_DBG_ST_COUNT == OT_LC_SOC_DBG_STATE_COUNT, + "Invalid SoC Debug state count"); #define ROM_MASK ((1u << (R_BOOT_STATUS_ROM_CTRL_DONE_LENGTH - 1u)) - 1u) @@ -182,17 +224,23 @@ static_assert(ALERT_COUNT == NUM_ALERTS, "Invalid alert count"); static const char *REG_CORE_NAMES[REGS_CORE_COUNT] = { /* clang-format off */ REG_NAME_ENTRY(CORE_ALERT_TEST), - REG_NAME_ENTRY(CORE_DEBUG_POLICY_CTRL), - REG_NAME_ENTRY(CORE_DEBUG_POLICY_VALID), - REG_NAME_ENTRY(CORE_STATUS_MBX), + REG_NAME_ENTRY(CORE_DEBUG_POLICY_VALID_SHADOWED), + REG_NAME_ENTRY(CORE_DEBUG_POLICY_CATEGORY_SHADOWED), + REG_NAME_ENTRY(CORE_DEBUG_POLICY_RELOCKED), + REG_NAME_ENTRY(CORE_TRACE_DEBUG_POLICY_CATEGORY), + REG_NAME_ENTRY(CORE_TRACE_DEBUG_POLICY_VALID_RELOCKED), + REG_NAME_ENTRY(CORE_STATUS), /* clang-format on */ }; static const char *REG_JTAG_NAMES[REGS_JTAG_COUNT] = { /* clang-format off */ + REG_NAME_ENTRY(JTAG_TRACE_DEBUG_POLICY_CATEGORY), + REG_NAME_ENTRY(JTAG_TRACE_DEBUG_POLICY_VALID_RELOCKED), REG_NAME_ENTRY(JTAG_CONTROL), REG_NAME_ENTRY(JTAG_STATUS), REG_NAME_ENTRY(JTAG_BOOT_STATUS), + REG_NAME_ENTRY(JTAG_TRACE_SOC_DBG_STATE), /* clang-format on */ }; #undef REG_NAME_ENTRY @@ -213,6 +261,7 @@ static const char *LC_BROADCAST_NAMES[] = { LC_NAME_ENTRY(OT_LC_ISO_PART_SW_RD_EN), LC_NAME_ENTRY(OT_LC_ISO_PART_SW_WR_EN), LC_NAME_ENTRY(OT_LC_SEED_HW_RD_EN), + LC_NAME_ENTRY(OT_LC_RMA), /* clang-format on */ }; #undef LC_NAME_ENTRY @@ -237,14 +286,13 @@ static const char *SOC_DBG_NAMES[] = { "?") #define STATE_NAME_ENTRY(_st_) [ST_##_st_] = stringify(_st_) -static const char *STATE_NAMES[] = { +static const char *STATE_NAMES[ST_COUNT] = { /* clang-format off */ STATE_NAME_ENTRY(IDLE), - STATE_NAME_ENTRY(CHECK_LC_ST), - STATE_NAME_ENTRY(WAIT4_DFT_EN), + STATE_NAME_ENTRY(CHECK_LC_STATE), + STATE_NAME_ENTRY(WAIT4DFT_EN), STATE_NAME_ENTRY(CHECK_HALT_PIN), STATE_NAME_ENTRY(CHECK_JTAG_GO), - STATE_NAME_ENTRY(CONTINUE_BOOT), STATE_NAME_ENTRY(HALT_DONE), /* clang-format on */ }; @@ -265,6 +313,12 @@ static void ot_soc_dbg_ctrl_change_state_line( s->fsm_state = state; } +static inline bool +ot_soc_dbg_ctrl_lc_test(const OtSoCDbgCtrlState *s, OtLcCtrlBroadcast lc_bc) +{ + return (bool)(s->lc_broadcast_bm & (1u << (unsigned)lc_bc)); +} + static void ot_soc_dbg_ctrl_update_alerts(OtSoCDbgCtrlState *s, uint32_t test_bm) { @@ -298,44 +352,41 @@ static void ot_soc_dbg_ctrl_tick_fsm(OtSoCDbgCtrlState *s) bool cpu_boot_done = false; trace_ot_soc_dbg_ctrl_tick_fsm(s->ot_id, STATE_NAME(s->fsm_state), - s->boot_status_bm, s->lc_broadcast_bm, - s->soc_dbg_bm, s->dft_ignore, + s->lc_broadcast_bm, s->dft_ignore, + s->pwr_boot_status.lc_done, s->halt_cpu_boot, s->boot_continue); switch (s->fsm_state) { case ST_IDLE: - if (s->boot_status_bm & R_BOOT_STATUS_LC_DONE_MASK) { - CHANGE_STATE(s, CHECK_LC_ST); + if (s->pwr_boot_status.lc_done) { + CHANGE_STATE(s, CHECK_LC_STATE); } break; - case ST_CHECK_LC_ST: + case ST_CHECK_LC_STATE: if ((s->lc_broadcast_bm & (1u << OT_LC_RAW_TEST_RMA)) && !s->dft_ignore) { - CHANGE_STATE(s, WAIT4_DFT_EN); + CHANGE_STATE(s, WAIT4DFT_EN); } else { - CHANGE_STATE(s, CONTINUE_BOOT); + CHANGE_STATE(s, HALT_DONE); } break; - case ST_WAIT4_DFT_EN: + case ST_WAIT4DFT_EN: if (s->lc_broadcast_bm & (1u << OT_LC_DFT_EN)) { CHANGE_STATE(s, CHECK_HALT_PIN); } break; case ST_CHECK_HALT_PIN: - if (s->soc_dbg_bm & R_SOC_DBG_HALT_CPU_BOOT_MASK) { + if (s->halt_cpu_boot) { CHANGE_STATE(s, CHECK_JTAG_GO); } else { - CHANGE_STATE(s, CONTINUE_BOOT); + CHANGE_STATE(s, HALT_DONE); } break; case ST_CHECK_JTAG_GO: if (s->boot_continue) { - CHANGE_STATE(s, CONTINUE_BOOT); + CHANGE_STATE(s, HALT_DONE); } break; - case ST_CONTINUE_BOOT: - CHANGE_STATE(s, HALT_DONE); - break; case ST_HALT_DONE: cpu_boot_done = true; break; @@ -351,7 +402,7 @@ static void ot_soc_dbg_ctrl_tick_fsm(OtSoCDbgCtrlState *s) /* as with PwrMgr, use simple boolean value, not MuBi4 */ int cpu_boot_done_i = (int)cpu_boot_done; - if (ibex_irq_get_level(&s->continue_cpu_boot[CONTINUE_CPU_BOOT_DONE]) != + if (ibex_irq_get_level(&s->continue_cpu_boot[CONTINUE_CPU_BOOT_COUNT]) != cpu_boot_done_i) { trace_ot_soc_dbg_ctrl_cpu_boot_done(s->ot_id, cpu_boot_done_i); } @@ -359,41 +410,54 @@ static void ot_soc_dbg_ctrl_tick_fsm(OtSoCDbgCtrlState *s) cpu_boot_done_i); } -static void ot_soc_dbg_ctrl_update(OtSoCDbgCtrlState *s) +static void ot_soc_dbg_ctrl_update_policy(OtSoCDbgCtrlState *s) { + OtSocDbgPolicy policy; + switch (s->soc_dbg_state) { case OT_SOC_DBG_ST_BLANK: - s->debug_policy = - s->lc_broadcast_bm & (1u << OT_LC_DFT_EN) || - s->lc_broadcast_bm & (1u << OT_LC_HW_DEBUG_EN) ? - DEFAULT_DBG_UNLOCKED : - DEFAULT_DBG_LOCKED; - s->debug_valid = (bool)(s->boot_status_bm & R_BOOT_STATUS_LC_DONE_MASK); + policy.cat = ot_soc_dbg_ctrl_lc_test(s, OT_LC_DFT_EN) || + ot_soc_dbg_ctrl_lc_test(s, OT_LC_HW_DEBUG_EN) ? + OT_SOC_DBG_CATEGORY_4 : + OT_SOC_DBG_CATEGORY_LOCKED; + policy.valid = (bool)s->pwr_boot_status.lc_done; + policy.relocked = OT_MULTIBITBOOL4_FALSE; break; case OT_SOC_DBG_ST_PRE_PROD: - s->debug_policy = DEFAULT_DBG_UNLOCKED; - s->debug_valid = (bool)(s->boot_status_bm & R_BOOT_STATUS_LC_DONE_MASK); + policy.cat = OT_SOC_DBG_CATEGORY_4; + policy.valid = (bool)s->pwr_boot_status.lc_done; + policy.relocked = OT_MULTIBITBOOL4_FALSE; break; case OT_SOC_DBG_ST_PROD: - s->debug_policy = s->regs[R_CORE_DEBUG_POLICY_CTRL] & - (POLICY_CAT_MASK | POLICY_RELOCK_MASK); - s->debug_valid = (bool)s->regs[R_CORE_DEBUG_POLICY_VALID]; + if (ot_soc_dbg_ctrl_lc_test(s, OT_LC_RMA)) { + policy.cat = OT_SOC_DBG_CATEGORY_4; + policy.valid = true; + policy.relocked = OT_MULTIBITBOOL4_FALSE; + } else if (ot_soc_dbg_ctrl_lc_test(s, OT_LC_CPU_EN)) { + policy.cat = ot_shadow_reg_peek(&s->regs.debug_policy.category); + policy.valid = true; + policy.relocked = s->regs.debug_policy.relocked; + } else { + policy.cat = OT_SOC_DBG_CATEGORY_LOCKED; + policy.valid = (bool)s->pwr_boot_status.lc_done; + policy.relocked = OT_MULTIBITBOOL4_FALSE; + } break; default: - s->debug_policy = DEFAULT_DBG_LOCKED; - s->debug_valid = false; + policy.cat = OT_SOC_DBG_CATEGORY_LOCKED; + policy.valid = false; + policy.relocked = OT_MULTIBITBOOL4_FALSE; + break; } - int policy = (int)((s->debug_policy & OT_SOC_DBG_DEBUG_POLICY_MASK) | - (s->debug_valid ? OT_SOC_DBG_DEBUG_VALID_MASK : 0)); - - int prev_policy = ibex_irq_get_level(&s->policy); - if (prev_policy != policy) { - trace_ot_soc_dbg_ctrl_update(s->ot_id, SOC_DBG_NAME(s->soc_dbg_state), - STATE_NAME(s->fsm_state), s->debug_policy, - s->debug_valid); + /* detect valid rising edge */ + if (policy.valid && !s->soc_dbg_policy.valid) { + /* store current policy for edge detection and trace registers */ + s->soc_dbg_policy = policy; + } else { + /* store only valid level for edge detection */ + s->soc_dbg_policy.valid = policy.valid; } - ibex_irq_set(&s->policy, policy); } static void ot_soc_dbg_ctrl_fsm_tick(void *opaque) @@ -403,7 +467,7 @@ static void ot_soc_dbg_ctrl_fsm_tick(void *opaque) OtSoCDbgCtrlFsmState fsm_state = s->fsm_state; g_assert(s->fsm_tick_count); while (s->fsm_tick_count) { - ot_soc_dbg_ctrl_update(s); + ot_soc_dbg_ctrl_update_policy(s); s->fsm_tick_count--; ot_soc_dbg_ctrl_tick_fsm(s); } @@ -427,11 +491,7 @@ static void ot_soc_dbg_ctrl_halt_cpu_boot(void *opaque, int n, int level) g_assert(ibex_gpio_check(level)); /* active low */ - if (!ibex_gpio_level(level)) { - s->soc_dbg_bm |= R_SOC_DBG_HALT_CPU_BOOT_MASK; - } else { - s->soc_dbg_bm &= ~R_SOC_DBG_HALT_CPU_BOOT_MASK; - } + s->halt_cpu_boot = !ibex_gpio_level(level); SCHEDULE_FSM(s); } @@ -470,9 +530,7 @@ static void ot_soc_dbg_ctrl_lc_broadcast(void *opaque, int n, int level) case OT_LC_SEED_HW_RD_EN: case OT_LC_ESCALATE_EN: case OT_LC_CHECK_BYP_EN: - /* verbatim from RTL: "Use unused singals to make lint clean" */ - - /* why do we explictly route signals that are then discarded? */ + /* verbatim from RTL: "Use unused signals to make lint clean" */ break; /* NOLINTEND(bugprone-branch-clone) */ default: @@ -489,26 +547,44 @@ static void ot_soc_dbg_ctrl_boot_status(void *opaque, int n, int level) g_assert(n == 0); OtPwrMgrBootStatus bs = { .i32 = level }; + + g_assert(bs.rom_mask != 0); + g_assert(!(bs.rom_mask & ~BOOT_ROM_MASK)); + trace_ot_soc_dbg_ctrl_boot_status(s->ot_id, (bool)bs.main_clk_status, (bool)bs.io_clk_status, (bool)bs.otp_done, (bool)bs.lc_done, (bool)bs.cpu_fetch_en, - bs.rom_done & ROM_MASK, - bs.rom_good & ROM_MASK); - uint16_t bs_bm = 0; - bs_bm = FIELD_DP16(bs_bm, BOOT_STATUS, MAIN_CLK_STATUS, bs.main_clk_status); - bs_bm = FIELD_DP16(bs_bm, BOOT_STATUS, IO_CLK_STATUS, bs.io_clk_status); - bs_bm = FIELD_DP16(bs_bm, BOOT_STATUS, OTP_DONE, bs.otp_done); - bs_bm = FIELD_DP16(bs_bm, BOOT_STATUS, LC_DONE, bs.lc_done); - bs_bm = - FIELD_DP16(bs_bm, BOOT_STATUS, ROM_CTRL_DONE, bs.rom_done & ROM_MASK); - bs_bm = - FIELD_DP16(bs_bm, BOOT_STATUS, ROM_CTRL_DONE, bs.rom_good & ROM_MASK); - bs_bm = FIELD_DP16(bs_bm, BOOT_STATUS, CPU_FETCH_EN, bs.cpu_fetch_en); - s->boot_status_bm = bs_bm; + bs.rom_done & bs.rom_mask, + bs.rom_good & bs.rom_mask); + s->pwr_boot_status = bs; SCHEDULE_FSM(s); } +static uint32_t ot_soc_dbg_ctrl_get_jtag_boot_status(const OtSoCDbgCtrlState *s) +{ + const OtPwrMgrBootStatus *bs = &s->pwr_boot_status; + + g_assert(s->fsm_state < ST_COUNT); + + uint32_t bs_bm = 0; + + bs_bm = FIELD_DP32(bs_bm, JTAG_BOOT_STATUS, MAIN_CLK_STATUS, + bs->main_clk_status); + bs_bm = + FIELD_DP32(bs_bm, JTAG_BOOT_STATUS, IO_CLK_STATUS, bs->io_clk_status); + bs_bm = FIELD_DP32(bs_bm, JTAG_BOOT_STATUS, OTP_DONE, bs->otp_done); + bs_bm = FIELD_DP32(bs_bm, JTAG_BOOT_STATUS, LC_DONE, bs->lc_done); + bs_bm = FIELD_DP32(bs_bm, JTAG_BOOT_STATUS, BOOT_GREENLIGHT_DONE, + bs->rom_done & bs->rom_mask); + bs_bm = FIELD_DP32(bs_bm, JTAG_BOOT_STATUS, BOOT_GREENLIGHT_GOOD, + bs->rom_good & bs->rom_mask); + bs_bm = FIELD_DP32(bs_bm, JTAG_BOOT_STATUS, CPU_FETCH_EN, bs->cpu_fetch_en); + bs_bm = FIELD_DP32(bs_bm, JTAG_BOOT_STATUS, HALT_FSM_STATE, + (uint32_t)OT_SOC_DBG_FSM_STATE[s->fsm_state]); + + return bs_bm; +} static void ot_soc_dbg_ctrl_soc_dbg_state(void *opaque, int n, int level) { @@ -549,22 +625,32 @@ ot_soc_dbg_ctrl_core_read(void *opaque, hwaddr addr, unsigned size) hwaddr reg = R32_OFF(addr); switch (reg) { - /* note: interrupt usage is not specified */ - case R_CORE_DEBUG_POLICY_CTRL: - case R_CORE_DEBUG_POLICY_VALID: - case R_CORE_STATUS_MBX: - val32 = s->regs[reg]; + case R_CORE_DEBUG_POLICY_VALID_SHADOWED: + val32 = ot_shadow_reg_read(&s->regs.debug_policy.valid); + break; + case R_CORE_DEBUG_POLICY_CATEGORY_SHADOWED: + val32 = ot_shadow_reg_read(&s->regs.debug_policy.category); + break; + case R_CORE_DEBUG_POLICY_RELOCKED: + val32 = s->regs.debug_policy.relocked; + break; + case R_CORE_TRACE_DEBUG_POLICY_CATEGORY: + val32 = (uint32_t)s->soc_dbg_policy.cat; + break; + case R_CORE_TRACE_DEBUG_POLICY_VALID_RELOCKED: + val32 = (uint32_t)s->soc_dbg_policy.relocked; + break; + case R_CORE_STATUS: + val32 = s->regs.status; break; case R_CORE_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_NAME(CORE, reg)); + qemu_log_mask(LOG_GUEST_ERROR, "%s: %s: W/O register 0x%02x (%s)\n", + __func__, s->ot_id, (uint32_t)addr, REG_NAME(CORE, reg)); val32 = 0; break; default: - qemu_log_mask(LOG_GUEST_ERROR, - "%s: %s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, - s->ot_id, addr); + qemu_log_mask(LOG_GUEST_ERROR, "%s: %s: Bad offset 0x%02x\n", __func__, + s->ot_id, (uint32_t)addr); val32 = 0; break; } @@ -594,22 +680,60 @@ static void ot_soc_dbg_ctrl_core_write(void *opaque, hwaddr addr, val32 &= CORE_ALERT_TEST_WMASK; ot_soc_dbg_ctrl_update_alerts(s, val32); break; - case R_CORE_DEBUG_POLICY_CTRL: - val32 &= R_CORE_DEBUG_POLICY_CTRL_LEVEL_MASK; - s->regs[reg] = val32; + case R_CORE_DEBUG_POLICY_VALID_SHADOWED: + val32 &= DEBUG_POLICY_VALID_MASK; + switch (ot_shadow_reg_write(&s->regs.debug_policy.valid, val32)) { + case OT_SHADOW_REG_STAGED: + case OT_SHADOW_REG_COMMITTED: + s->recov_alert_bm &= ~(1u << ALERT_RECOV_POLICY_VALID); + break; + case OT_SHADOW_REG_ERROR: + s->recov_alert_bm |= 1u << ALERT_RECOV_POLICY_VALID; + default: + break; + } + ot_soc_dbg_ctrl_update_alerts(s, 0u); + break; + case R_CORE_DEBUG_POLICY_CATEGORY_SHADOWED: + val32 &= DEBUG_POLICY_CATEGORY_MASK; + if (ot_shadow_reg_peek(&s->regs.debug_policy.valid) == + OT_MULTIBITBOOL4_FALSE) { + /* debug policy not yet validated, can still update it */ + switch ( + ot_shadow_reg_write(&s->regs.debug_policy.category, val32)) { + case OT_SHADOW_REG_STAGED: + case OT_SHADOW_REG_COMMITTED: + s->recov_alert_bm &= ~(1u << ALERT_RECOV_POLICY_CATEGORY); + break; + case OT_SHADOW_REG_ERROR: + s->recov_alert_bm |= 1u << ALERT_RECOV_POLICY_CATEGORY; + default: + break; + } + ot_soc_dbg_ctrl_update_alerts(s, 0u); + } + break; + case R_CORE_DEBUG_POLICY_RELOCKED: + val32 &= DEBUG_POLICY_RELOCKED_MASK; + s->regs.debug_policy.relocked = val32; break; - case R_CORE_DEBUG_POLICY_VALID: - val32 &= R_CORE_DEBUG_POLICY_VALID_VALID_MASK; - s->regs[reg] = val32; + case R_CORE_TRACE_DEBUG_POLICY_CATEGORY: + case R_CORE_TRACE_DEBUG_POLICY_VALID_RELOCKED: + qemu_log_mask(LOG_GUEST_ERROR, "%s: %s: R/O register 0x%02x (%s)\n", + __func__, s->ot_id, (uint32_t)addr, REG_NAME(CORE, reg)); break; - case R_CORE_STATUS_MBX: - val32 &= STATUS_MASK; - s->regs[reg] = val32; + case R_CORE_STATUS: + /* + * this register does nothing but masks some bits and make them + * readable from JTAG side. + */ + val32 &= CORE_STATUS_WMASK; + s->regs.status = val32; break; default: - qemu_log_mask(LOG_GUEST_ERROR, - "%s: %s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, - s->ot_id, addr); + qemu_log_mask(LOG_GUEST_ERROR, "%s: %s: Bad offset 0x%02x\n", __func__, + s->ot_id, (uint32_t)addr); + break; } } @@ -622,15 +746,21 @@ ot_soc_dbg_ctrl_jtag_read(void *opaque, hwaddr addr, unsigned size) hwaddr reg = R32_OFF(addr); switch (reg) { + case R_JTAG_TRACE_DEBUG_POLICY_CATEGORY: + val32 = (uint32_t)s->soc_dbg_policy.cat; + break; + case R_JTAG_TRACE_DEBUG_POLICY_VALID_RELOCKED: + val32 = (uint32_t)s->soc_dbg_policy.relocked; + break; case R_JTAG_CONTROL: val32 = s->boot_continue ? R_JTAG_CONTROL_BOOT_CONTINUE_MASK : 0u; break; case R_JTAG_STATUS: - val32 = s->regs[R_CORE_STATUS_MBX]; /* mirror of the core I/F */ + val32 = s->regs.status; break; case R_JTAG_BOOT_STATUS: - if (s->lc_broadcast_bm & (1u << OT_LC_DFT_EN)) { - val32 = (uint32_t)s->boot_status_bm; + if (ot_soc_dbg_ctrl_lc_test(s, OT_LC_DFT_EN)) { + val32 = ot_soc_dbg_ctrl_get_jtag_boot_status(s); } else { qemu_log_mask(LOG_GUEST_ERROR, "%s: %s: BootStatus disabled (no DFT)\n", __func__, @@ -638,10 +768,14 @@ ot_soc_dbg_ctrl_jtag_read(void *opaque, hwaddr addr, unsigned size) val32 = 0; } break; + case R_JTAG_TRACE_SOC_DBG_STATE: + qemu_log_mask(LOG_UNIMP, "%s: %s: not implemented %s\n", __func__, + s->ot_id, REG_NAME(JTAG, reg)); + val32 = 0u; + break; default: - qemu_log_mask(LOG_GUEST_ERROR, - "%s: %s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, - s->ot_id, addr); + qemu_log_mask(LOG_GUEST_ERROR, "%s: %s: Bad offset 0x%02x\n", __func__, + s->ot_id, (uint32_t)addr); val32 = 0; break; } @@ -669,22 +803,23 @@ static void ot_soc_dbg_ctrl_jtag_write(void *opaque, hwaddr addr, s->boot_continue = (bool)(val32 & R_JTAG_CONTROL_BOOT_CONTINUE_MASK); SCHEDULE_FSM(s); break; + case R_JTAG_TRACE_DEBUG_POLICY_CATEGORY: + case R_JTAG_TRACE_DEBUG_POLICY_VALID_RELOCKED: case R_JTAG_STATUS: case R_JTAG_BOOT_STATUS: - qemu_log_mask(LOG_GUEST_ERROR, - "%s: %s: R/O register 0x%02" HWADDR_PRIx " (%s)\n", - __func__, s->ot_id, addr, REG_NAME(JTAG, reg)); + case R_JTAG_TRACE_SOC_DBG_STATE: + qemu_log_mask(LOG_GUEST_ERROR, "%s: %s: R/O register 0x%02x (%s)\n", + __func__, s->ot_id, (uint32_t)addr, REG_NAME(JTAG, reg)); break; default: - qemu_log_mask(LOG_GUEST_ERROR, - "%s: %s, Bad offset 0x%" HWADDR_PRIx "\n", __func__, - s->ot_id, addr); + qemu_log_mask(LOG_GUEST_ERROR, "%s: %s, Bad offset 0x%02x\n", __func__, + s->ot_id, (uint32_t)addr); + break; } } static Property ot_soc_dbg_ctrl_properties[] = { DEFINE_PROP_STRING(OT_COMMON_DEV_ID, OtSoCDbgCtrlState, ot_id), - DEFINE_PROP_BOOL("halt_function", OtSoCDbgCtrlState, halt_function, true), DEFINE_PROP_BOOL("dft-ignore", OtSoCDbgCtrlState, dft_ignore, false), DEFINE_PROP_END_OF_LIST(), }; @@ -714,19 +849,23 @@ static void ot_soc_dbg_ctrl_reset_enter(Object *obj, ResetType type) c->parent_phases.enter(obj, type); } - memset(s->regs, 0, sizeof(s->regs)); + ot_shadow_reg_init(&s->regs.debug_policy.valid, OT_MULTIBITBOOL4_FALSE); + ot_shadow_reg_init(&s->regs.debug_policy.category, + OT_SOC_DBG_CATEGORY_LOCKED); + s->regs.debug_policy.relocked = OT_MULTIBITBOOL4_FALSE; - ibex_irq_set(&s->continue_cpu_boot[CONTINUE_CPU_BOOT_GOOD], (int)false); ibex_irq_set(&s->continue_cpu_boot[CONTINUE_CPU_BOOT_DONE], (int)false); + ibex_irq_set(&s->debug_policy, 0); + + memset(&s->soc_dbg_policy, 0, sizeof(s->soc_dbg_policy)); CHANGE_STATE(s, IDLE); + s->fsm_state = ST_IDLE; s->fsm_tick_count = 0u; - s->soc_dbg_bm = 0u; - s->boot_status_bm = 0u; + s->pwr_boot_status.i32 = 0; s->lc_broadcast_bm = 0u; s->soc_dbg_state = OT_SOC_DBG_ST_PROD; - s->debug_policy = DEFAULT_DBG_LOCKED; - s->debug_valid = false; + s->halt_cpu_boot = false; s->boot_continue = false; s->fatal_alert_bm = 0u; s->recov_alert_bm = 0u; @@ -745,15 +884,11 @@ static void ot_soc_dbg_ctrl_reset_exit(Object *obj, ResetType type) qemu_bh_cancel(s->fsm_tick_bh); - /* - * ROM signal which does not comes from a ROM but from this device to - * signal the status of the Ibex core, but used as a ROM in PwrMgr: - * always on.... - */ - s->boot_status_bm |= ROM_MASK << R_BOOT_STATUS_ROM_CTRL_GOOD_SHIFT; - + /* this fake ROM signal is hardcoded to true and never updated. */ ibex_irq_set(&s->continue_cpu_boot[CONTINUE_CPU_BOOT_GOOD], (int)true); + ot_soc_dbg_ctrl_update_policy(s); + SCHEDULE_FSM(s); } @@ -780,7 +915,7 @@ static void ot_soc_dbg_ctrl_init(Object *obj) for (unsigned ix = 0; ix < NUM_ALERTS; ix++) { ibex_qdev_init_irq(obj, &s->alerts[ix], OT_DEVICE_ALERT); } - ibex_qdev_init_irq(obj, &s->policy, OT_SOC_DBG_DEBUG_POLICY); + ibex_qdev_init_irq(obj, &s->debug_policy, OT_SOC_DBG_DEBUG_POLICY); ibex_qdev_init_irqs(obj, s->continue_cpu_boot, OT_SOC_DBG_CONTINUE_CPU_BOOT, ARRAY_SIZE(s->continue_cpu_boot)); @@ -793,7 +928,6 @@ static void ot_soc_dbg_ctrl_init(Object *obj) qdev_init_gpio_in_named(DEVICE(obj), &ot_soc_dbg_ctrl_boot_status, OT_SOC_DBG_BOOT_STATUS, 1u); - s->fsm_tick_bh = qemu_bh_new(&ot_soc_dbg_ctrl_fsm_tick, s); } diff --git a/hw/opentitan/trace-events b/hw/opentitan/trace-events index cea375edb703d..1425460dd3f26 100644 --- a/hw/opentitan/trace-events +++ b/hw/opentitan/trace-events @@ -367,7 +367,7 @@ ot_lc_ctrl_io_read_out_repeat(const char * id, uint32_t addr, const char * regna ot_lc_ctrl_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_lc_ctrl_km_div_missing(const char * id, unsigned ix) "%s: #%u" ot_lc_ctrl_load_lc_info_force_raw(const char * id) "%s: force_raw enabled" -ot_lc_ctrl_load_otp_hw_cfg(const char * id, const char *soc_dbg) "%s: soc_dbg_state: %s" +ot_lc_ctrl_load_otp_hw_cfg(const char * id, const char *socdbg) "%s: socdbg_state: %s" ot_lc_ctrl_load_otp_token(const char * id, const char *tk, unsigned tkix, const char *inv, uint64_t hi, uint64_t lo) "%s: token %s (%u) %svalid: 0x%016" PRIx64 "%016" PRIx64 ot_lc_ctrl_mismatch_token(const char * id, const char *tkkind, const char *tkname, unsigned tok, uint64_t htkhi, uint64_t htklo, uint64_t rtkhi, uint64_t rtklo) "%s: %s token %s (%u): 0x%016" PRIx64 "%016" PRIx64 ", ref 0x%016" PRIx64 "%016" PRIx64 ot_lc_ctrl_pwr_lc_req(const char * id, const char *where) "%s: %s" @@ -533,9 +533,8 @@ ot_soc_dbg_ctrl_jtag_io_write(const char *id, uint32_t addr, const char * regnam ot_soc_dbg_ctrl_rcv(const char *id, const char *src, unsigned n, char sig) "%s: %s #%d: lvl %c" ot_soc_dbg_ctrl_schedule_fsm(const char *id, const char *func, int line, unsigned tc) "%s: @ %s:%d (%u)" ot_soc_dbg_ctrl_soc_dbg_state(const char *id, const char *st) "%s: %s" -ot_soc_dbg_ctrl_tick_fsm(const char *id, const char *st, uint32_t bs, uint32_t lc, uint32_t dbg, bool dfti, bool bc) "%s: %s bs:0x%03x lc:0x%02x dbg:0x%01x dfti:%u bc:%u" -ot_soc_dbg_ctrl_update(const char *id, const char *soc_dbgst, const char *fsmst, unsigned policy, bool valid) "%s: [%s] fsm:%s policy:0x%1x valid:%u" - +ot_soc_dbg_ctrl_tick_fsm(const char *id, const char *st, uint16_t lc, bool dfti, bool lcd, bool hcb, bool bc) "%s: %s lc:0x%02x dfti:%u lcd:%u hcb:%u bc:%u" +ot_soc_dbg_ctrl_update_policy(const char *id, const char *socdbgst, const char *fsmst, uint8_t cat_bm, bool relocked) "%s: [%s] fsm:%s cat_bm:0x%1x relocked:%u" # ot_spi_device.c From dcf2c0b2ac663c04df1a28f2880e289560106bcd Mon Sep 17 00:00:00 2001 From: Emmanuel Blot Date: Wed, 12 Nov 2025 11:32:48 +0100 Subject: [PATCH 19/24] [ot] hw/opentitan: ot_soc_dbg_ctrl: retrieve SoC debug code from LC controller Signed-off-by: Emmanuel Blot --- hw/opentitan/ot_soc_dbg_ctrl.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/hw/opentitan/ot_soc_dbg_ctrl.c b/hw/opentitan/ot_soc_dbg_ctrl.c index a15d584b0d978..c7423b978eb23 100644 --- a/hw/opentitan/ot_soc_dbg_ctrl.c +++ b/hw/opentitan/ot_soc_dbg_ctrl.c @@ -189,6 +189,7 @@ struct OtSoCDbgCtrlState { bool boot_continue; char *ot_id; + OtLcCtrlState *lc_ctrl; bool dft_ignore; }; @@ -769,9 +770,16 @@ ot_soc_dbg_ctrl_jtag_read(void *opaque, hwaddr addr, unsigned size) } break; case R_JTAG_TRACE_SOC_DBG_STATE: - qemu_log_mask(LOG_UNIMP, "%s: %s: not implemented %s\n", __func__, - s->ot_id, REG_NAME(JTAG, reg)); - val32 = 0u; + if (ot_soc_dbg_ctrl_lc_test(s, OT_LC_DFT_EN)) { + OtLcCtrlClass *lc = OT_LC_CTRL_GET_CLASS(s->lc_ctrl); + val32 = + lc->get_soc_dbg_state(s->lc_ctrl, (unsigned)s->soc_dbg_state); + } else { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: %s: SocDbgState disabled (no DFT)\n", __func__, + s->ot_id); + val32 = 0u; + } break; default: qemu_log_mask(LOG_GUEST_ERROR, "%s: %s: Bad offset 0x%02x\n", __func__, @@ -820,6 +828,8 @@ static void ot_soc_dbg_ctrl_jtag_write(void *opaque, hwaddr addr, static Property ot_soc_dbg_ctrl_properties[] = { DEFINE_PROP_STRING(OT_COMMON_DEV_ID, OtSoCDbgCtrlState, ot_id), + DEFINE_PROP_LINK("lc-ctrl", OtSoCDbgCtrlState, lc_ctrl, TYPE_OT_LC_CTRL, + OtLcCtrlState *), DEFINE_PROP_BOOL("dft-ignore", OtSoCDbgCtrlState, dft_ignore, false), DEFINE_PROP_END_OF_LIST(), }; @@ -898,6 +908,7 @@ static void ot_soc_dbg_ctrl_realize(DeviceState *dev, Error **errp) (void)errp; g_assert(s->ot_id); + g_assert(s->lc_ctrl); } static void ot_soc_dbg_ctrl_init(Object *obj) From 090d4a5801d07d32f3cd06e8ce76c55f7ecc2652 Mon Sep 17 00:00:00 2001 From: Emmanuel Blot Date: Wed, 12 Nov 2025 11:48:52 +0100 Subject: [PATCH 20/24] [ot] hw/opentitan: ot_soc_dbg_ctrl: decode debug policy and update output signal for clients Signed-off-by: Emmanuel Blot --- hw/opentitan/ot_soc_dbg_ctrl.c | 37 +++++++++++++++++++++++++- include/hw/opentitan/ot_soc_dbg_ctrl.h | 17 ++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/hw/opentitan/ot_soc_dbg_ctrl.c b/hw/opentitan/ot_soc_dbg_ctrl.c index c7423b978eb23..f08c7b85e3509 100644 --- a/hw/opentitan/ot_soc_dbg_ctrl.c +++ b/hw/opentitan/ot_soc_dbg_ctrl.c @@ -210,6 +210,8 @@ static const uint8_t OT_SOC_DBG_FSM_STATE[ST_COUNT] = { /* clang-format on */ static_assert(ALERT_COUNT == NUM_ALERTS, "Invalid alert count"); +static_assert(sizeof(OtSocDbgDebugPolicy) == sizeof(int), + "Invalid OtSocDbgDebugPolicy size"); static_assert(OT_SOC_DBG_ST_COUNT == OT_LC_SOC_DBG_STATE_COUNT, "Invalid SoC Debug state count"); @@ -415,6 +417,10 @@ static void ot_soc_dbg_ctrl_update_policy(OtSoCDbgCtrlState *s) { OtSocDbgPolicy policy; + ot_mb4_t relocked = + (ot_mb4_t)SHARED_FIELD_EX32(s->regs.debug_policy.relocked, + DEBUG_POLICY_RELOCKED); + switch (s->soc_dbg_state) { case OT_SOC_DBG_ST_BLANK: policy.cat = ot_soc_dbg_ctrl_lc_test(s, OT_LC_DFT_EN) || @@ -437,7 +443,7 @@ static void ot_soc_dbg_ctrl_update_policy(OtSoCDbgCtrlState *s) } else if (ot_soc_dbg_ctrl_lc_test(s, OT_LC_CPU_EN)) { policy.cat = ot_shadow_reg_peek(&s->regs.debug_policy.category); policy.valid = true; - policy.relocked = s->regs.debug_policy.relocked; + policy.relocked = relocked; } else { policy.cat = OT_SOC_DBG_CATEGORY_LOCKED; policy.valid = (bool)s->pwr_boot_status.lc_done; @@ -453,6 +459,35 @@ static void ot_soc_dbg_ctrl_update_policy(OtSoCDbgCtrlState *s) /* detect valid rising edge */ if (policy.valid && !s->soc_dbg_policy.valid) { + /* decode the values into the combined output signal */ + OtSocDbgDebugPolicy debug_policy = { + .cat_bm = 0u, + .relocked = policy.relocked == OT_MULTIBITBOOL4_TRUE, + }; + + if (policy.cat == OT_SOC_DBG_CATEGORY_4) { + debug_policy.cat_bm |= 1u << 4u; + } + if (!relocked) { + if (policy.cat == OT_SOC_DBG_CATEGORY_3 || + (debug_policy.cat_bm & (1u << 4u))) { + debug_policy.cat_bm |= 1u << 3u; + } + if (policy.cat == OT_SOC_DBG_CATEGORY_2 || + (debug_policy.cat_bm & ((1u << 4u) | (1u << 3u)))) { + debug_policy.cat_bm |= 1u << 2u; + } + } + + int prev_policy = ibex_irq_get_level(&s->debug_policy); + if (prev_policy != debug_policy.i32) { + trace_ot_soc_dbg_ctrl_update_policy(s->ot_id, + SOC_DBG_NAME(s->soc_dbg_state), + STATE_NAME(s->fsm_state), + debug_policy.cat_bm, relocked); + } + ibex_irq_set(&s->debug_policy, debug_policy.i32); + /* store current policy for edge detection and trace registers */ s->soc_dbg_policy = policy; } else { diff --git a/include/hw/opentitan/ot_soc_dbg_ctrl.h b/include/hw/opentitan/ot_soc_dbg_ctrl.h index aab963cad5759..bb45b04a97b86 100644 --- a/include/hw/opentitan/ot_soc_dbg_ctrl.h +++ b/include/hw/opentitan/ot_soc_dbg_ctrl.h @@ -41,6 +41,23 @@ typedef enum { OT_SOC_DBG_ST_COUNT, } OtSoCDbgState; +/* Signal carried over OT_SOC_DBG_DEBUG_POLICY */ +typedef union { + struct { + /* + * Active categories: + * b0..b1: unused + * b2: CAT2 + * b3: CAT3 + * b4: CAT4 + * b5..b7: unused + */ + uint8_t cat_bm; + bool relocked; + }; + int i32; +} OtSocDbgDebugPolicy; + /* input lines */ #define OT_SOC_DBG_HALT_CPU_BOOT TYPE_OT_SOC_DBG_CTRL "-halt-cpu-boot" #define OT_SOC_DBG_LC_BCAST TYPE_OT_SOC_DBG_CTRL "-lc-broadcast" From 75b206b202c6cdb8166482a69da3d60a05218642 Mon Sep 17 00:00:00 2001 From: Emmanuel Blot Date: Fri, 7 Nov 2025 10:34:21 +0100 Subject: [PATCH 21/24] [ot] hw/riscv: ot_darjeeling: update Soc Debug controller configuration - connect SoC debug controller to LC controller - define alert signals - tell the LC controller to decode signals for the SoC debug controller Signed-off-by: Emmanuel Blot --- hw/riscv/ot_darjeeling.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/hw/riscv/ot_darjeeling.c b/hw/riscv/ot_darjeeling.c index 53b54aeda845c..42b4933ffd7ab 100644 --- a/hw/riscv/ot_darjeeling.c +++ b/hw/riscv/ot_darjeeling.c @@ -1253,8 +1253,9 @@ static const IbexDeviceDef ot_dj_soc_devices[] = { IBEX_DEV_UINT_PROP("silicon_creator_id", 0x4002u), IBEX_DEV_UINT_PROP("product_id", 0x4000u), IBEX_DEV_UINT_PROP("revision_id", 0x1u), + IBEX_DEV_UINT_PROP("kmac-app", 1u), IBEX_DEV_BOOL_PROP("volatile_raw_unlock", true), - IBEX_DEV_UINT_PROP("kmac-app", 1u) + IBEX_DEV_BOOL_PROP("decode_soc_dbg", true) ) }, [OT_DJ_SOC_DEV_ALERT_HANDLER] = { @@ -1286,19 +1287,17 @@ static const IbexDeviceDef ot_dj_soc_devices[] = { ), }, [OT_DJ_SOC_DEV_SOC_DBG_CTRL] = { - /* @todo: should be renamed TYPE_OT_SOC_DBG_CTRL */ .type = TYPE_OT_SOC_DBG_CTRL, .memmap = MEMMAPENTRIES( { .base = 0x30170000u } ), - /* - * @todo: add alert signals once OT_SOC_DBG_CTRL supports them - * - * .gpio = IBEXGPIOCONNDEFS( - * OT_DJ_SOC_GPIO_ALERT(0, 95), - * OT_DJ_SOC_GPIO_ALERT(1, 96) - * ), - */ + .gpio = IBEXGPIOCONNDEFS( + OT_DJ_SOC_GPIO_ALERT(0, 95), + OT_DJ_SOC_GPIO_ALERT(1, 96) + ), + .link = IBEXDEVICELINKDEFS( + OT_DJ_SOC_DEVLINK("lc-ctrl", LC_CTRL) + ), }, [OT_DJ_SOC_DEV_SPI_HOST0] = { .type = TYPE_OT_SPI_HOST, From 5f8ce57cfe41e3aece61d335615492c67123268e Mon Sep 17 00:00:00 2001 From: Emmanuel Blot Date: Fri, 7 Nov 2025 14:23:55 +0100 Subject: [PATCH 22/24] [ot] python/qemu: ot.lc_ctrl: rename 'socdbg' as 'soc_dbg' to match new HW Signed-off-by: Emmanuel Blot --- python/qemu/ot/lc_ctrl/const.py | 16 ++++++++-------- python/qemu/ot/otp/lifecycle.py | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/python/qemu/ot/lc_ctrl/const.py b/python/qemu/ot/lc_ctrl/const.py index 5310ade046c63..32d16be97f06a 100644 --- a/python/qemu/ot/lc_ctrl/const.py +++ b/python/qemu/ot/lc_ctrl/const.py @@ -21,7 +21,7 @@ def __init__(self): self._log = getLogger('lc.const') self._states: dict[str, tuple[str, str]] = {} self._tokens: dict[str, str] = {} - self._diversifiers: dict [str, str] = {} + self._diversifiers: dict[str, str] = {} def load_sv(self, svp: TextIO) -> None: """Decode LC information from a System Verilog file. @@ -50,14 +50,14 @@ def load_sv(self, svp: TextIO) -> None: int(trans[otrans[0]]), int(trans[otrans[1]])) self._tokens.update(lcext.get_tokens(False, False)) - socdbg = lcext.get_configuration('SOCDBG') - if socdbg: - for raw in {s for s in socdbg if int(s, 16) == 0}: - del socdbg[raw] - osoc = list(socdbg) - self._states['socdbg'] = osoc[0], osoc[-1] + soc_dbg = lcext.get_configuration('SOC_DBG') + if soc_dbg: + for raw in {s for s in soc_dbg if int(s, 16) == 0}: + del soc_dbg[raw] + osoc = list(soc_dbg) + self._states['soc_dbg'] = osoc[0], osoc[-1] self._log.info("Socdbg first: '%s', last '%s'", - socdbg[osoc[0]], socdbg[osoc[-1]]) + soc_dbg[osoc[0]], soc_dbg[osoc[-1]]) ownership = lcext.get_configuration('OWNERSHIP') if ownership: for raw in {s for s in ownership if int(s, 16) == 0}: diff --git a/python/qemu/ot/otp/lifecycle.py b/python/qemu/ot/otp/lifecycle.py index dff2a14a7e83a..3d33704f5f03a 100644 --- a/python/qemu/ot/otp/lifecycle.py +++ b/python/qemu/ot/otp/lifecycle.py @@ -92,7 +92,7 @@ def load(self, svp: TextIO): mkind, conv = {'lcst': ('LC_STATE', str), 'lccnt': ('LC_TRANSITION_CNT', int), 'ownershipst': ('OWNERSHIP', str), - 'socdbgst': ('SOCDBG', str)}[kind] + 'socdbgst': ('SOC_DBG', str)}[kind] self._tables[mkind] = {} for ref, seq in seqs.items(): seq = ''.join((f'{x:04x}'for x in map(codes.get, seq))) From bcc42aa3fdac48030d33136611745249a2d6f83d Mon Sep 17 00:00:00 2001 From: Emmanuel Blot Date: Fri, 7 Nov 2025 14:24:46 +0100 Subject: [PATCH 23/24] [ot] scripts/opentitan: darjeeling.cfg: update OpenOCD script to match HW naming Signed-off-by: Emmanuel Blot --- scripts/opentitan/darjeeling-ocd.cfg | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/opentitan/darjeeling-ocd.cfg b/scripts/opentitan/darjeeling-ocd.cfg index 0298ab34523db..c1d180e041f28 100644 --- a/scripts/opentitan/darjeeling-ocd.cfg +++ b/scripts/opentitan/darjeeling-ocd.cfg @@ -13,10 +13,10 @@ transport select jtag set _IRLENGTH 5 # DMI addresses -set _OT_DJ_DEBUG_RV_DM_ADDR 0x0 -set _OT_DJ_DEBUG_MBX_JTAG_ADDR 0x880 -set _OT_DJ_DEBUG_SOCDBG_CTRL_ADDR 0x8c0 -set _OT_DJ_DEBUG_LC_CTRL_ADDR 0xc00 +set _OT_DJ_DEBUG_RV_DM_ADDR 0x0 +set _OT_DJ_DEBUG_MBX_JTAG_ADDR 0x880 +set _OT_DJ_DEBUG_SOC_DBG_CTRL_ADDR 0x8c0 +set _OT_DJ_DEBUG_LC_CTRL_ADDR 0xc00 set _CHIPNAME riscv # part 1, ver 0, lowRISC From f32a873aea84b3ef613bdde7374a778cad573355 Mon Sep 17 00:00:00 2001 From: Emmanuel Blot Date: Fri, 7 Nov 2025 14:25:22 +0100 Subject: [PATCH 24/24] [ot] docs/config: opentitan: update Darjeeling configuration Signed-off-by: Emmanuel Blot --- docs/config/opentitan/darjeeling.cfg | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/config/opentitan/darjeeling.cfg b/docs/config/opentitan/darjeeling.cfg index 0c27f85672b8b..e7b9802d8b9e3 100644 --- a/docs/config/opentitan/darjeeling.cfg +++ b/docs/config/opentitan/darjeeling.cfg @@ -1,5 +1,4 @@ -# Generated from OpenTitan 'master' branch -# commit: fc2d73b432 +# Generated from OpenTitan commit: c5507b4cdc [ot_device "ot-rom_ctrl.rom0"] key = "30ae84156d37cc68063276f9e85faee1" @@ -39,8 +38,8 @@ production = "ffc2171a49199bb53d8e0daa8f0578db" raw_unlock_token = "e4225dc332ea1fda63b4c524556ed4d4" rma = "aa5f022791480b4e709e0f80976e0966" - socdbg_first = "6b36fc2c" - socdbg_last = "ebf6fc7f" + soc_dbg_first = "6b36fc2c" + soc_dbg_last = "ebf6fc7f" test_unlocked = "e4c72c47d9e15fa8ff9f82833e32c151" [ot_device "ot-keymgr_dpe"] @@ -67,3 +66,4 @@ [ot_device "ot-pwrmgr"] clocks = "main,io" +