Skip to content

Commit 6f91842

Browse files
rivos-eblotloiclefort
authored andcommitted
[ot] hw/opentitan: ot_otp_dj: DAI WRITE data are now committed to the back-end
Also fix buffered partition digest computation with DAI DIGEST Signed-off-by: Emmanuel Blot <eblot@rivosinc.com>
1 parent 0b2125b commit 6f91842

File tree

2 files changed

+67
-27
lines changed

2 files changed

+67
-27
lines changed

hw/opentitan/ot_otp_dj.c

Lines changed: 66 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1032,6 +1032,8 @@ ot_otp_dj_lci_change_state_line(OtOTPDjState *s, OtOTPLCIState state, int line);
10321032
#define LCI_CHANGE_STATE(_s_, _st_) \
10331033
ot_otp_dj_lci_change_state_line(_s_, _st_, __LINE__)
10341034

1035+
#define OT_OTP_PART_DATA_OFFSET(_pix_) \
1036+
((unsigned)(OtOTPPartDescs[(_pix_)].offset))
10351037
#define OT_OTP_PART_DATA_BYTE_SIZE(_pix_) \
10361038
((unsigned)(OtOTPPartDescs[(_pix_)].size - \
10371039
sizeof(uint32_t) * NUM_DIGEST_WORDS))
@@ -1543,6 +1545,10 @@ static void ot_otp_dj_check_partition_integrity(OtOTPDjState *s, unsigned ix)
15431545
if (digest != pctrl->buffer.digest) {
15441546
trace_ot_otp_mismatch_digest(PART_NAME(ix), ix, digest,
15451547
pctrl->buffer.digest);
1548+
1549+
TRACE_OTP("%s: compute digest %016llx from %s\n", __func__, digest,
1550+
ot_otp_hexdump(pctrl->buffer.data, part_size));
1551+
15461552
pctrl->failed = true;
15471553
/* this is a fatal error */
15481554
ot_otp_dj_set_error(s, ix, OTP_CHECK_FAIL_ERROR);
@@ -1575,6 +1581,20 @@ static bool ot_otp_dj_is_backend_writable(OtOTPDjState *s)
15751581
return (s->blk != NULL) && blk_is_writable(s->blk);
15761582
}
15771583

1584+
static inline int ot_otp_dj_write_backend(OtOTPDjState *s, void *buffer,
1585+
unsigned offset, size_t size)
1586+
{
1587+
/*
1588+
* the blk_pwrite API is awful, isolate it so that linter exceptions are
1589+
* are not repeated over and over
1590+
*/
1591+
// NOLINTBEGIN(clang-analyzer-optin.core.EnumCastOutOfRange)
1592+
return blk_pwrite(s->blk, (int64_t)(intptr_t)offset, (int64_t)size, buffer,
1593+
/* a bitfield of enum is not an enum item */
1594+
(BdrvRequestFlags)0);
1595+
// NOLINTEND(clang-analyzer-optin.core.EnumCastOutOfRange)
1596+
}
1597+
15781598
static void ot_otp_dj_dai_init(OtOTPDjState *s)
15791599
{
15801600
DAI_CHANGE_STATE(s, OTP_DAI_IDLE);
@@ -1734,9 +1754,10 @@ static void ot_otp_dj_dai_write(OtOTPDjState *s)
17341754
}
17351755

17361756
unsigned waddr = address >> 2u;
1737-
1757+
unsigned size;
17381758
if (is_wide || is_digest) {
17391759
waddr &= ~0b1u;
1760+
size = sizeof(uint64_t);
17401761

17411762
uint32_t dst_lo = s->otp->data[waddr];
17421763
uint32_t dst_hi = s->otp->data[waddr + 1u];
@@ -1747,29 +1768,38 @@ static void ot_otp_dj_dai_write(OtOTPDjState *s)
17471768
if ((dst_lo & ~lo) || (dst_hi & ~hi)) {
17481769
qemu_log_mask(LOG_GUEST_ERROR, "%s: Cannot clear OTP bits\n",
17491770
__func__);
1750-
ot_otp_dj_dai_set_error(s, OTP_MACRO_WRITE_BLANK_ERROR);
1751-
return;
1771+
ot_otp_dj_set_error(s, OTP_ENTRY_DAI, OTP_MACRO_WRITE_BLANK_ERROR);
17521772
}
17531773

17541774
s->otp->data[waddr] = lo;
17551775
s->otp->data[waddr + 1u] = hi;
17561776
} else {
1777+
size = sizeof(uint32_t);
1778+
17571779
uint32_t dst = s->otp->data[waddr];
17581780
uint32_t data = s->regs[R_DIRECT_ACCESS_WDATA_0];
17591781

17601782
if (dst & ~data) {
17611783
qemu_log_mask(LOG_GUEST_ERROR, "%s: Cannot clear OTP bits\n",
17621784
__func__);
1763-
ot_otp_dj_dai_set_error(s, OTP_MACRO_WRITE_BLANK_ERROR);
1764-
return;
1785+
ot_otp_dj_set_error(s, OTP_ENTRY_DAI, OTP_MACRO_WRITE_BLANK_ERROR);
17651786
}
17661787

17671788
s->otp->data[waddr] = data;
17681789
}
17691790

1770-
/* fake slow access to OTP cell */
1791+
uintptr_t offset = (uintptr_t)s->otp->data - (uintptr_t)s->otp->storage;
1792+
if (ot_otp_dj_write_backend(s, &s->otp->data[waddr],
1793+
(unsigned)(offset + waddr * sizeof(uint32_t)),
1794+
size)) {
1795+
error_report("%s: cannot update OTP backend", __func__);
1796+
ot_otp_dj_dai_set_error(s, OTP_MACRO_ERROR);
1797+
return;
1798+
}
1799+
17711800
DAI_CHANGE_STATE(s, OTP_DAI_WRITE_WAIT);
17721801

1802+
/* fake slow access to OTP cell */
17731803
timer_mod(s->dai->delay,
17741804
qemu_clock_get_ns(OT_VIRTUAL_CLOCK) + DAI_WRITE_DELAY_NS);
17751805
}
@@ -1839,7 +1869,14 @@ static void ot_otp_dj_dai_digest(OtOTPDjState *s)
18391869

18401870
DAI_CHANGE_STATE(s, OTP_DAI_DIG_READ);
18411871

1842-
const uint8_t *data = (const uint8_t *)pctrl->buffer.data;
1872+
const uint8_t *data;
1873+
1874+
if (OtOTPPartDescs[partition].buffered) {
1875+
data = ((const uint8_t *)s->otp->data) +
1876+
OT_OTP_PART_DATA_OFFSET(partition);
1877+
} else {
1878+
data = (const uint8_t *)pctrl->buffer.data;
1879+
}
18431880
unsigned part_size = OT_OTP_PART_DATA_BYTE_SIZE(partition);
18441881

18451882
DAI_CHANGE_STATE(s, OTP_DAI_DIG);
@@ -1848,6 +1885,9 @@ static void ot_otp_dj_dai_digest(OtOTPDjState *s)
18481885
ot_otp_dj_compute_partition_digest(s, data, part_size);
18491886
s->dai->partition = partition;
18501887

1888+
TRACE_OTP("%s: next digest %016llx from %s\n", __func__,
1889+
pctrl->buffer.next_digest, ot_otp_hexdump(data, part_size));
1890+
18511891
DAI_CHANGE_STATE(s, OTP_DAI_DIG_WAIT);
18521892

18531893
/* fake slow access to OTP cell */
@@ -1865,29 +1905,31 @@ static void ot_otp_dj_dai_write_digest(void *opaque)
18651905

18661906
OtOTPPartController *pctrl = &s->partctrls[s->dai->partition];
18671907
unsigned address = OtOTPPartDescs[s->dai->partition].digest_offset;
1868-
address >>= 3u;
1869-
uint64_t *dst = &((uint64_t *)s->otp->data)[address];
1908+
unsigned dwaddr = address / sizeof(uint64_t);
1909+
uint64_t *dst = &((uint64_t *)s->otp->data)[dwaddr];
18701910
uint64_t data = pctrl->buffer.next_digest;
18711911
pctrl->buffer.next_digest = 0;
1872-
OtOTPError error;
1912+
18731913
if (*dst & ~data) {
18741914
qemu_log_mask(LOG_GUEST_ERROR, "%s: Cannot clear OTP bits\n", __func__);
1875-
error = OTP_MACRO_WRITE_BLANK_ERROR;
1915+
ot_otp_dj_set_error(s, OTP_ENTRY_DAI, OTP_MACRO_WRITE_BLANK_ERROR);
18761916
} else {
18771917
*dst |= data;
1878-
error = OTP_NO_ERROR;
18791918
}
18801919

1881-
if (error == OTP_NO_ERROR) {
1882-
/* fake slow access to OTP cell */
1883-
DAI_CHANGE_STATE(s, OTP_DAI_WRITE_WAIT);
1884-
1885-
timer_mod(s->dai->delay,
1886-
qemu_clock_get_ns(OT_VIRTUAL_CLOCK) + DAI_WRITE_DELAY_NS);
1887-
} else {
1888-
/* TODO: no idea on how to report the error since partition is undef */
1889-
ot_otp_dj_dai_set_error(s, error);
1920+
uintptr_t offset = (uintptr_t)s->otp->data - (uintptr_t)s->otp->storage;
1921+
if (ot_otp_dj_write_backend(s, dst, (unsigned)(offset + address),
1922+
sizeof(uint64_t))) {
1923+
error_report("%s: cannot update OTP backend", __func__);
1924+
ot_otp_dj_dai_set_error(s, OTP_MACRO_ERROR);
1925+
return;
18901926
}
1927+
1928+
DAI_CHANGE_STATE(s, OTP_DAI_WRITE_WAIT);
1929+
1930+
/* fake slow access to OTP cell */
1931+
timer_mod(s->dai->delay,
1932+
qemu_clock_get_ns(OT_VIRTUAL_CLOCK) + DAI_WRITE_DELAY_NS);
18911933
}
18921934

18931935
static void ot_otp_dj_dai_complete(void *opaque)
@@ -3029,11 +3071,9 @@ static void ot_otp_dj_lci_write_complete(OtOTPDjState *s, bool success)
30293071
const OtOTPPartDesc *lcdesc = &OtOTPPartDescs[OTP_PART_LIFE_CYCLE];
30303072
unsigned lc_data_off = lcdesc->offset / sizeof(uint32_t);
30313073
uintptr_t offset = (uintptr_t)s->otp->data - (uintptr_t)s->otp->storage;
3032-
// NOLINTBEGIN(clang-analyzer-optin.core.EnumCastOutOfRange)
3033-
if (blk_pwrite(s->blk, (int64_t)(intptr_t)(offset + lcdesc->offset),
3034-
lcdesc->size, &s->otp->data[lc_data_off],
3035-
(BdrvRequestFlags)0)) {
3036-
// NOLINTEND(clang-analyzer-optin.core.EnumCastOutOfRange)
3074+
if (ot_otp_dj_write_backend(s, &s->otp->data[lc_data_off],
3075+
(unsigned)(offset + lcdesc->offset),
3076+
lcdesc->size)) {
30373077
error_report("%s: cannot update OTP backend", __func__);
30383078
if (lci->error == OTP_NO_ERROR) {
30393079
lci->error = OTP_MACRO_ERROR;

hw/opentitan/trace-events

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ ot_otp_lci_change_state(int line, const char *old, int nold, const char *new, in
307307
ot_otp_lci_write(unsigned pos, uint16_t cval, uint16_t nval) "@ %u 0x%04x -> 0x%04x"
308308
ot_otp_load_backend(unsigned ver, const char *mode) "loading OTP image v%u in %s mode"
309309
ot_otp_load_token(const char *token, unsigned tkx, uint64_t hi, uint64_t lo, const char *valid) "%s (%u) 0x%016" PRIx64 "%016" PRIx64 ": %svalid"
310-
ot_otp_mismatch_digest(const char* part, unsigned pix, uint64_t sdig, uint64_t ldig) "Mismatch digest on %s (#%u), stored 0x%" PRIx64 " found 0x%" PRIx64
310+
ot_otp_mismatch_digest(const char* part, unsigned pix, uint64_t sdig, uint64_t ldig) "Mismatch digest on %s (#%u), computed 0x%" PRIx64 " stored 0x%" PRIx64
311311
ot_otp_pwr_otp_req(const char *where) "%s"
312312
ot_otp_reset(void) ""
313313
ot_otp_set_error(unsigned pix, const char* err, unsigned eix) "#%u: %s (%u)"

0 commit comments

Comments
 (0)