[otbn] Introduce locked state
Introduce a new locked state, represented as LOCKED in the STATUS
register to indicate if OTBN has detected a fatal error and is now
"dead" until a reset.
With this new state, OTBN guarantees a certain value of the STATUS
register after a fatal error was detected, simplifying the documentation
and the verification.
Furthermore, operation handling from Ibex got easier even if fatal
alerts don't reach Ibex for whatever reason: an operation always returns
with a done interrupt, and reading the STATUS register clearly indicates
what happened to OTBN. (Before, software would have to read
FATAL_ALERT_CAUSE as well if STATUS was non-zero to check if an
operation can be restarted [in case of a recoverable error], or if
OTBN is locked.)
Signed-off-by: Philipp Wagner <phw@lowrisc.org>
diff --git a/hw/ip/otbn/data/otbn.hjson b/hw/ip/otbn/data/otbn.hjson
index 0a02f45..b5997f5 100644
--- a/hw/ip/otbn/data/otbn.hjson
+++ b/hw/ip/otbn/data/otbn.hjson
@@ -243,6 +243,15 @@
<td>BUSY_SEC_WIPE_IMEM</td>
<td>OTBN is securely wiping the instruction memory.</td>
</tr>
+ <tr>
+ <td>0xFF</td>
+ <td>LOCKED</td>
+ <td>
+ OTBN is locked as reaction to a fatal error, and must be
+ reset to unlock it again. See also the section on fatal
+ error handling.
+ </td>
+ </tr>
</tbody>
</table>
'''
diff --git a/hw/ip/otbn/doc/_index.md b/hw/ip/otbn/doc/_index.md
index f9aa1e2..e20876d 100644
--- a/hw/ip/otbn/doc/_index.md
+++ b/hw/ip/otbn/doc/_index.md
@@ -523,17 +523,21 @@
OTBN can be in different operational states.
OTBN is *busy* for as long it is performing an operation.
+OTBN is *locked* if a fatal error was observed.
Otherwise OTBN is *idle*.
The current operational state is reflected in the {{< regref "STATUS" >}} register.
- If OTBN is idle, the {{< regref "STATUS" >}} register is set to `IDLE`.
- If OTBN is busy, the {{< regref "STATUS" >}} register is set to one of the values starting with `BUSY_`.
+- If OTBN is locked, the {{< regref "STATUS" >}} register is set to `LOCKED`.
OTBN transitions into the busy state as result of host software [issuing a command](#design-details-commands); OTBN is then said to perform an operation.
OTBN transitions out of the busy state whenever the operation has completed.
In the {{< regref "STATUS" >}} register the different `BUSY_*` values represent the operation that is currently being performed.
-A transition from busy to idle is signaled by the `done` interrupt ({{< regref "INTR_STATE.done" >}}).
+A transition out of the busy state is signaled by the `done` interrupt ({{< regref "INTR_STATE.done" >}}).
+
+The locked state is a terminal state; transitioning out of it requires an OTBN reset.
### Operations and Commands {#design-details-commands}
@@ -557,7 +561,7 @@
- From this point on, all subsequent instructions are executed according to their semantics until either an {{< otbnInsnRef "ECALL" >}} instruction is executed, or an error is detected.
- A [secure wipe of internal state](#design-details-secure-wipe-internal) is performed.
- The {{< regref "ERR_BITS" >}} register is set to indicate either a successful execution (value `0`), or to indicate the error that was observed (a non-zero value).
-- OTBN transitions into the [idle state](#design-details-operational-states).
+- OTBN transitions into the [idle state](#design-details-operational-states) (in case of a successful execution, or a recoverable error) or the locked state (in case of a fatal error).
This transition is signaled by raising the `done` interrupt ({{< regref "INTR_STATE.done" >}}), and reflected in the {{< regref "STATUS" >}} register.
### Error Handling and Reporting {#design-details-error-handling-and-reporting}
@@ -603,6 +607,7 @@
- A [secure wipe of internal state](#design-details-secure-wipe-internal) is performed.
- The {{< regref "ERR_BITS" >}} register is set to a non-zero value that describes the error.
- The current operation is marked as complete by setting {{< regref "INTR_STATE.done" >}}.
+ - The {{< regref "STATUS" >}} register is set to `LOCKED`.
3. A [fatal alert]({{< relref "#alerts" >}}) is raised.
Note that OTBN can detect some errors even when it isn't running.
diff --git a/hw/ip/otbn/rtl/otbn_pkg.sv b/hw/ip/otbn/rtl/otbn_pkg.sv
index c17fc85..f90ea1f 100644
--- a/hw/ip/otbn/rtl/otbn_pkg.sv
+++ b/hw/ip/otbn/rtl/otbn_pkg.sv
@@ -62,7 +62,8 @@
StatusIdle = 8'h00,
StatusBusyExecute = 8'h01,
StatusBusySecWipeDmem = 8'h02,
- StatusBusySecWipeImem = 8'h03
+ StatusBusySecWipeImem = 8'h03,
+ StatusLocked = 8'hFF
} status_e;
// Error bits
diff --git a/sw/device/lib/dif/dif_otbn.h b/sw/device/lib/dif/dif_otbn.h
index 5868e8d..c7323be 100644
--- a/sw/device/lib/dif/dif_otbn.h
+++ b/sw/device/lib/dif/dif_otbn.h
@@ -82,6 +82,7 @@
kDifOtbnStatusBusyExecute = 0x01,
kDifOtbnStatusBusySecWipeDmem = 0x02,
kDifOtbnStatusBusySecWipeImem = 0x03,
+ kDifOtbnStatusLocked = 0xFF,
} dif_otbn_status_t;
/**
diff --git a/sw/device/silicon_creator/lib/drivers/otbn.h b/sw/device/silicon_creator/lib/drivers/otbn.h
index 0d24d49..fd1ed27 100644
--- a/sw/device/silicon_creator/lib/drivers/otbn.h
+++ b/sw/device/silicon_creator/lib/drivers/otbn.h
@@ -42,6 +42,7 @@
kOtbnStatusBusyExecute = 0x01,
kOtbnStatusBusySecWipeDmem = 0x02,
kOtbnStatusBusySecWipeImem = 0x03,
+ kOtbnStatusLocked = 0xFF,
} otbn_status_t;
/**