blob: aba1cb805a6f24602614205ec1a0b0fc9fa89db1 [file] [log] [blame]
Miguel Young de la Sota475887f2020-08-10 16:40:09 -04001// Copyright lowRISC contributors.
2// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3// SPDX-License-Identifier: Apache-2.0
4
5#ifndef OPENTITAN_SW_DEVICE_LIB_DIF_DIF_ALERT_HANDLER_H_
6#define OPENTITAN_SW_DEVICE_LIB_DIF_DIF_ALERT_HANDLER_H_
7
8/**
9 * @file
10 * @brief <a href="/hw/ip/alert_handler/doc/">Alert handler</a> Device Interface
11 * Functions
12 */
13
14#include <stdint.h>
15
Timothy Trippele3f8a822021-09-17 06:09:28 +000016#include "sw/device/lib/base/macros.h"
Miguel Young de la Sota475887f2020-08-10 16:40:09 -040017#include "sw/device/lib/base/mmio.h"
Timothy Trippel915ba132021-09-24 01:23:38 +000018#include "sw/device/lib/dif/dif_base.h"
19
20#include "sw/device/lib/dif/autogen/dif_alert_handler_autogen.h"
Miguel Young de la Sota475887f2020-08-10 16:40:09 -040021
Miguel Young de la Sota475887f2020-08-10 16:40:09 -040022#ifdef __cplusplus
23extern "C" {
24#endif // __cplusplus
25
26/**
Miguel Young de la Sota475887f2020-08-10 16:40:09 -040027 * An alert class.
28 *
29 * An alert class roughly specifies how to deal with an alert. The class
30 * determines which interrupt handler is fired for an alert, as well as the
31 * fine-grained details of the escalation policy, for when the processor
32 * fails to respond to an alert quickly enough.
33 *
34 * Alert classes serve as the alert handler's IRQ types. There is one IRQ for
35 * each class. Whenever an alert fires, the corresponding class's IRQ is
36 * serviced by the processor (if enabled).
37 */
38typedef enum dif_alert_handler_class {
39 /**
40 * Alert class "A".
41 */
42 kDifAlertHandlerClassA = 0,
43 /**
44 * Alert class "B".
45 */
46 kDifAlertHandlerClassB = 1,
47 /**
48 * Alert class "C".
49 */
50 kDifAlertHandlerClassC = 2,
51 /**
52 * Alert class "D".
53 */
54 kDifAlertHandlerClassD = 3,
55} dif_alert_handler_class_t;
56
57/**
Miguel Young de la Sota475887f2020-08-10 16:40:09 -040058 * An alert, identified by a numeric id.
59 *
60 * Alerts are hardware-level events indicating that something catastrophic
61 * has happened. An alert handler handle.consumes alerts, classifies them to a
62 * particular `dif_alert_handler_class_t`, and uses policy information attached
63 * to that class to handle it.
64 *
65 * The number of alerts is configurable at hardware-synthesis time, and is
66 * specified by the software when initializing a `dif_alert_handler_t`.
67 */
68typedef uint32_t dif_alert_handler_alert_t;
69
70/**
71 * A local alert originating from within the alert handler itself.
72 *
73 * A local alert is exactly the same as a normal `dif_alert_handler_alert_t`,
74 * except that they use different functions for setting up classification and
75 * for getting causes.
76 */
77typedef enum dif_alert_handler_local_alert {
78 kDifAlertHandlerLocalAlertAlertPingFail,
79 kDifAlertHandlerLocalAlertEscalationPingFail,
80 kDifAlertHandlerLocalAlertAlertIntegrityFail,
81 kDifAlertHandlerLocalAlertEscalationIntegrityFail,
Timothy Trippelbcca3302021-08-04 20:18:16 +000082 kDifAlertHandlerLocalAlertBusIntegrityFail,
Michael Schaffner1a5d53a2021-06-03 17:44:17 -070083 kDifAlertHandlerLocalAlertShadowedUpdateError,
84 kDifAlertHandlerLocalAlertShadowedStorageError,
Miguel Young de la Sota475887f2020-08-10 16:40:09 -040085} dif_alert_handler_local_alert_t;
86
87/**
88 * An escalation signal, identified by a numeric id.
89 *
90 * An escalation signal is a generic "response" to failing to handle a
91 * catastrophic event. What each signal means is determined by the chip.
92 *
93 * A `dif_alert_handler_class_t` can be configured to raise escalation signals
94 * as part of its policy.
95 */
96typedef uint32_t dif_alert_handler_signal_t;
97
98/**
99 * An alert class state.
100 *
101 * This enum describes the sequence of states in the *escalation protocol*,
102 * which triggers under two different conditions:
Timothy Trippel3d578e52021-08-05 00:37:34 +0000103 * - If too many alerts of a particular class accumulate.
Miguel Young de la Sota475887f2020-08-10 16:40:09 -0400104 * - If the software IRQ handler for that class times out.
105 *
106 * When either of these conditions is reached, phase 0 begins. This may trigger
107 * an escalation signal, and after a configured duration, proceed to phase 1.
108 * This process repeats until phase 3 ends, at which point the class enters a
109 * "bricked" terminal state, which cannot be exited except by reset.
110 *
111 * At any point, software may end the escalation protocol by calling
112 * `dif_alert_handler_escalation_clear()` (unless clearing is disabled).
113 * Successfully calling this function, or clearing the IRQ on time, will reset
114 * back to the idle state. Note that this function cannot clear the terminal
115 * state; that state can only be cleared by resetting the chip.
116 */
117typedef enum dif_alert_handler_class_state {
118 /**
119 * The initial, idle state.
120 */
121 kDifAlertHandlerClassStateIdle,
122 /**
123 * The "timeout" state, that is, the IRQ has been fired and the clock is
124 * ticking for the processor to handle the alert.
125 */
126 kDifAlertHandlerClassStateTimeout,
127
128 /**
129 * The zeroth escalation phase.
130 */
131 kDifAlertHandlerClassStatePhase0,
132 /**
133 * The first escalation phase.
134 */
135 kDifAlertHandlerClassStatePhase1,
136 /**
137 * The second escalation phase.
138 */
139 kDifAlertHandlerClassStatePhase2,
140 /**
141 * The third escalation phase.
142 */
143 kDifAlertHandlerClassStatePhase3,
144
145 /**
146 * The terminal state. Most configurations will never reach this state, since
147 * one of the previous phases will use an escalation signal to reset the
148 * device.
149 */
150 kDifAlertHandlerClassStateTerminal,
151} dif_alert_handler_class_state_t;
152
153/**
154 * Runtime configuration for responding to a given escalation phase.
155 *
Miguel Young de la Sotadd71d982020-09-17 15:40:16 -0400156 * See `dif_alert_handler_class_config_t`.
Miguel Young de la Sota475887f2020-08-10 16:40:09 -0400157 */
158typedef struct dif_alert_handler_class_phase_signal {
159 /**
160 * The phase this configuration describes.
161 *
162 * It is an error for this to not be one of the `Phase` constants in
163 * `dif_alert_handler_class_state_t`.
164 */
165 dif_alert_handler_class_state_t phase;
166 /**
167 * The signal that should be triggered when this phase begins.
168 */
169 dif_alert_handler_signal_t signal;
170} dif_alert_handler_class_phase_signal_t;
171
172/**
173 * Runtime configuration for the duration of an escalation phase.
174 *
Miguel Young de la Sotadd71d982020-09-17 15:40:16 -0400175 * See `dif_alert_handler_class_config_t`.
Miguel Young de la Sota475887f2020-08-10 16:40:09 -0400176 */
177typedef struct dif_alert_handler_class_phase_duration {
178 /**
179 * The phase this configuration describes.
180 *
181 * It is an error for this to not be one of the `Phase` constants in
182 * `dif_alert_handler_class_state_t`.
183 */
184 dif_alert_handler_class_state_t phase;
185 /**
186 * The duration of this phase, in cycles.
187 */
188 uint32_t cycles;
189} dif_alert_handler_class_phase_duration_t;
190
191/**
192 * Runtime configuration for a particular alert class.
193 *
194 * This struct describes how a particular alert class should be configured,
195 * such as which signals are associated with it, and what options are turned
196 * on for the escalation protocol.
197 *
198 * For each of the pointer/length field pairs below, if the length is zero, the
199 * pointer may be `NULL`.
200 */
201typedef struct dif_alert_handler_class_config {
202 /**
203 * The class this configuration describes.
204 */
205 dif_alert_handler_class_t alert_class;
206
207 /**
208 * A list of alerts that should be classified as having this class.
209 *
210 * Each alert in this list will additionally be set as enabled.
211 */
212 const dif_alert_handler_alert_t *alerts;
213 /**
214 * The length of the array `alerts`.
215 */
216 size_t alerts_len;
217
218 /**
219 * A list of local that should be classified as having this class.
220 *
221 * Each local alert in this list will additionally be set as enabled.
222 */
223 const dif_alert_handler_local_alert_t *local_alerts;
224 /**
225 * The length of the array `local_alerts`.
226 */
227 size_t local_alerts_len;
228
229 /**
230 * Whether the escalation protocol should be used for this class
231 * (i.e., accumulator and timeout based escalation).
232 *
233 * Class IRQs will still fire regardless of this setting.
234 */
Timothy Trippel915ba132021-09-24 01:23:38 +0000235 dif_toggle_t use_escalation_protocol;
Miguel Young de la Sota475887f2020-08-10 16:40:09 -0400236
237 /**
238 * Whether automatic escalation locking should be used for this class.
239 *
240 * When enabled, upon beginning the escalation protocol, the hardware will
241 * lock
242 * the escalation clear bit, so that software cannot stop escalation once it
243 * has begun.
244 */
Timothy Trippel915ba132021-09-24 01:23:38 +0000245 dif_toggle_t automatic_locking;
Miguel Young de la Sota475887f2020-08-10 16:40:09 -0400246
247 /**
248 * The threshold for the class accmulator which, when reached, will
Miguel Young de la Sotadf5994c2020-10-22 13:29:46 -0400249 * automatically trigger escalation.
Miguel Young de la Sota475887f2020-08-10 16:40:09 -0400250 */
251 uint16_t accumulator_threshold;
252
253 /**
254 * The number of cycles this class's associated IRQ handler has to acknowledge
255 * the IRQ before escalation is triggered.
256 *
257 * A value of zero disables the timeout.
258 */
259 uint32_t irq_deadline_cycles;
260
261 /**
262 * Signals to associate to each escalation phase.
263 *
264 * Each escalation phase signal in this list will additionally be set as
265 * enabled; phases not listed will have their escalation signals disabled.
266 */
267 const dif_alert_handler_class_phase_signal_t *phase_signals;
268 /**
269 * The length of the array `phase_signals`.
270 */
271 size_t phase_signals_len;
272
273 /**
274 * Durations, in cycles, of each escalation phase.
275 */
276 const dif_alert_handler_class_phase_duration_t *phase_durations;
277 /**
278 * The length of the array `phase_durations`.
279 */
280 size_t phase_durations_len;
281} dif_alert_handler_class_config_t;
282
283/**
284 * Runtime configuration for alert handler.
285 *
286 * This struct describes runtime information for one-time configuration of the
287 * hardware.
288 */
289typedef struct dif_alert_handler_config {
290 /**
291 * The alert ping timeout, in cycles.
292 *
Miguel Young de la Sotadd71d982020-09-17 15:40:16 -0400293 * The alert handler will regularly, at random intervals, ping alert
294 * sources. If a source fails to respond, a local alert will be raised.
Miguel Young de la Sota475887f2020-08-10 16:40:09 -0400295 *
296 * The appropriate value will be dependent on all of the clocks involved on
297 * a chip.
298 *
299 * Note that the ping timer won't start until `dif_alert_handler_lock()` is
300 * successfully called.
Miguel Young de la Sotadd71d982020-09-17 15:40:16 -0400301 *
302 * This value must fit in 24 bits.
Miguel Young de la Sota475887f2020-08-10 16:40:09 -0400303 */
304 uint32_t ping_timeout;
305
306 /**
307 * A list of alert classes to configure.
308 */
309 const dif_alert_handler_class_config_t *classes;
310 /**
311 * The length of the array `classes`.
312 */
313 size_t classes_len;
314} dif_alert_handler_config_t;
315
316/**
317 * Creates a new handle for alert handler.
318 *
319 * This function does not actuate the hardware.
320 *
Timothy Trippel915ba132021-09-24 01:23:38 +0000321 * @param base_addr Hardware instantiation base address.
Miguel Young de la Sota475887f2020-08-10 16:40:09 -0400322 * @param handler Out param for the initialized handle.
323 * @return The result of the operation.
324 */
Timothy Trippele3f8a822021-09-17 06:09:28 +0000325OT_WARN_UNUSED_RESULT
Timothy Trippel915ba132021-09-24 01:23:38 +0000326dif_result_t dif_alert_handler_init(mmio_region_t base_addr,
Timothy Trippel915ba132021-09-24 01:23:38 +0000327 dif_alert_handler_t *alert_handler);
Miguel Young de la Sota475887f2020-08-10 16:40:09 -0400328
329/**
330 * Configures alert handler with runtime information.
331 *
332 * This function should need to be called once for the lifetime of `handle`.
333 *
334 * This operation is lock-protected.
335 *
336 * @param handler An alert handler handle.
337 * @param config Runtime configuration parameters.
338 * @return The result of the operation.
339 */
Timothy Trippele3f8a822021-09-17 06:09:28 +0000340OT_WARN_UNUSED_RESULT
Timothy Trippel915ba132021-09-24 01:23:38 +0000341dif_result_t dif_alert_handler_configure(
Timothy Trippel936db9a2021-10-13 19:55:11 +0000342 const dif_alert_handler_t *alert_handler,
Timothy Trippel915ba132021-09-24 01:23:38 +0000343 dif_alert_handler_config_t config);
Miguel Young de la Sota475887f2020-08-10 16:40:09 -0400344/**
345 * Locks out alert handler configuration functionality.
346 *
347 * Once locked, `dif_alert_handler_configure()` will return
348 * `kDifAlertHandlerConfigLocked`.
349 *
350 * This operation cannot be undone, and should be performed at the end of
351 * configuring the alert handler in early boot.
352 *
353 * This function is reentrant: calling it while functionality is locked will
354 * have no effect and return `kDifAlertHandlerOk`.
355 *
356 * @param handler An alert handler handle.
357 * @return The result of the operation.
358 */
Timothy Trippele3f8a822021-09-17 06:09:28 +0000359OT_WARN_UNUSED_RESULT
Timothy Trippel915ba132021-09-24 01:23:38 +0000360dif_result_t dif_alert_handler_lock(const dif_alert_handler_t *alert_handler);
Miguel Young de la Sota475887f2020-08-10 16:40:09 -0400361
362/**
363 * Checks whether this alert handler is locked.
364 *
365 * See `dif_alert_handler_lock()`.
366 *
367 * @param handler An alert handler handle.
368 * @param is_locked Out-param for the locked state.
369 * @return The result of the operation.
370 */
Timothy Trippele3f8a822021-09-17 06:09:28 +0000371OT_WARN_UNUSED_RESULT
Timothy Trippel915ba132021-09-24 01:23:38 +0000372dif_result_t dif_alert_handler_is_locked(
373 const dif_alert_handler_t *alert_handler, bool *is_locked);
Miguel Young de la Sota475887f2020-08-10 16:40:09 -0400374
375/**
376 * Checks whether an alert is one of the causes for an alert IRQ.
377 *
Miguel Young de la Sotadd71d982020-09-17 15:40:16 -0400378 * Note that multiple alerts may be causes at the same time.
379 *
Miguel Young de la Sota475887f2020-08-10 16:40:09 -0400380 * @param handler An alert handler handle.
381 * @param alert The alert to check.
382 * @param is_cause Out-param for whether this alert is a cause.
383 * @return The result of the operation.
384 */
Timothy Trippele3f8a822021-09-17 06:09:28 +0000385OT_WARN_UNUSED_RESULT
Timothy Trippel915ba132021-09-24 01:23:38 +0000386dif_result_t dif_alert_handler_alert_is_cause(
Timothy Trippel936db9a2021-10-13 19:55:11 +0000387 const dif_alert_handler_t *alert_handler, dif_alert_handler_alert_t alert,
388 bool *is_cause);
Miguel Young de la Sota475887f2020-08-10 16:40:09 -0400389
390/**
391 * Clears an alert from the cause vector, similar to an IRQ acknowledgement.
392 *
393 * @param handler An alert handler handle.
394 * @param alert The alert to acknowledge.
395 * @return The result of the operation.
396 */
Timothy Trippele3f8a822021-09-17 06:09:28 +0000397OT_WARN_UNUSED_RESULT
Timothy Trippel915ba132021-09-24 01:23:38 +0000398dif_result_t dif_alert_handler_alert_acknowledge(
Timothy Trippel936db9a2021-10-13 19:55:11 +0000399 const dif_alert_handler_t *alert_handler, dif_alert_handler_alert_t alert);
Miguel Young de la Sota475887f2020-08-10 16:40:09 -0400400
401/**
Miguel Young de la Sotadd71d982020-09-17 15:40:16 -0400402 * Checks whether a local alert is one of the causes for an alert IRQ.
403 *
404 * Note that multiple alerts may be causes at the same time.
405 *
406 * @param handler An alert handler handle.
407 * @param alert The alert to check.
408 * @param is_cause Out-param for whether this alert is a cause.
409 * @return The result of the operation.
410 */
Timothy Trippele3f8a822021-09-17 06:09:28 +0000411OT_WARN_UNUSED_RESULT
Timothy Trippel915ba132021-09-24 01:23:38 +0000412dif_result_t dif_alert_handler_local_alert_is_cause(
413 const dif_alert_handler_t *alert_handler,
414 dif_alert_handler_local_alert_t alert, bool *is_cause);
Miguel Young de la Sotadd71d982020-09-17 15:40:16 -0400415
416/**
417 * Clears a local alert from the cause vector, similar to an IRQ
418 * acknowledgement.
419 *
420 * @param handler An alert handler handle.
421 * @param alert The alert to acknowledge.
422 * @return The result of the operation.
423 */
Timothy Trippele3f8a822021-09-17 06:09:28 +0000424OT_WARN_UNUSED_RESULT
Timothy Trippel915ba132021-09-24 01:23:38 +0000425dif_result_t dif_alert_handler_local_alert_acknowledge(
426 const dif_alert_handler_t *alert_handler,
427 dif_alert_handler_local_alert_t alert);
Miguel Young de la Sotadd71d982020-09-17 15:40:16 -0400428
429/**
Miguel Young de la Sota475887f2020-08-10 16:40:09 -0400430 * Checks whether software can clear escalations for this class.
431 *
432 * If `automatic_locking` has been set in a class's configuration, this
433 * function may suddenly begin returning `false` instead of `true` without
434 * software invervention, if escalation has been triggered.
435 *
436 * @param handler An alert handler handle.
437 * @param alert_class The class to check.
438 * @param can_clear Out-param for the clear enablement state.
439 * @return The result of the operation.
440 */
Timothy Trippele3f8a822021-09-17 06:09:28 +0000441OT_WARN_UNUSED_RESULT
Timothy Trippel915ba132021-09-24 01:23:38 +0000442dif_result_t dif_alert_handler_escalation_can_clear(
443 const dif_alert_handler_t *alert_handler,
444 dif_alert_handler_class_t alert_class, bool *can_clear);
Miguel Young de la Sota475887f2020-08-10 16:40:09 -0400445
446/**
447 * Disables escalation clearing for this class.
448 *
449 * This operation is similar to locking in that it cannot be undone.
450 *
451 * @param handler An alert handler handle.
452 * @param alert_class The class to disable clearing for.
453 * @return The result of the operation.
454 */
Timothy Trippele3f8a822021-09-17 06:09:28 +0000455OT_WARN_UNUSED_RESULT
Timothy Trippel915ba132021-09-24 01:23:38 +0000456dif_result_t dif_alert_handler_escalation_disable_clearing(
457 const dif_alert_handler_t *alert_handler,
458 dif_alert_handler_class_t alert_class);
Miguel Young de la Sota475887f2020-08-10 16:40:09 -0400459
460/**
461 * Clears an on-going escalation, as well as the class accumulator.
462 *
463 * This operation can be disabled with
464 * `dif_alert_handler_escalation_disable_clearing()`.
465 *
466 * @param handler An alert handler handle.
467 * @param alert_class The class to clear an escalation for.
468 * @return The result of the operation.
469 */
Timothy Trippele3f8a822021-09-17 06:09:28 +0000470OT_WARN_UNUSED_RESULT
Timothy Trippel915ba132021-09-24 01:23:38 +0000471dif_result_t dif_alert_handler_escalation_clear(
472 const dif_alert_handler_t *alert_handler,
473 dif_alert_handler_class_t alert_class);
Miguel Young de la Sota475887f2020-08-10 16:40:09 -0400474
475/**
476 * Gets the accumulator value for this class.
477 *
478 * This value is the number of alerts of this class that have been logged so
479 * far (more or less, since multiple alerts on the same cycle will be merged
480 * into one). Once this value equals the configured threshold, any followup
481 * alerts will immediately trigger the escalation protocol.
482 *
483 * This value is cleared as a side-effect of
484 * `dif_alert_handler_escalation_clear()`.
485 *
486 * @param handler An alert handler handle.
487 * @param alert_class The class to get the accumulator for.
488 * @param alerts Out-param for the accumulator.
489 * @return The result of the operation.
490 */
Timothy Trippele3f8a822021-09-17 06:09:28 +0000491OT_WARN_UNUSED_RESULT
Timothy Trippel915ba132021-09-24 01:23:38 +0000492dif_result_t dif_alert_handler_get_accumulator(
493 const dif_alert_handler_t *alert_handler,
494 dif_alert_handler_class_t alert_class, uint16_t *alerts);
Miguel Young de la Sota475887f2020-08-10 16:40:09 -0400495
496/**
497 * Gets the current value of the "escalation counter".
498 *
499 * The interpretation of this value depends on the value returned by
500 * `dif_alert_handler_class_state_get()`. If it is in the timeout state,
501 * it returns the number of cycles counted towards that cycle so far.
502 * If in an escalation phase, it returns the number of cycles that phase
503 * has been active for.
504 *
505 * @param handler An alert handler handle.
506 * @param alert_class The class to set the counter for.
507 * @param cycles Out-param for the counter.
508 * @return The result of the operation.
509 */
Timothy Trippele3f8a822021-09-17 06:09:28 +0000510OT_WARN_UNUSED_RESULT
Timothy Trippel915ba132021-09-24 01:23:38 +0000511dif_result_t dif_alert_handler_get_escalation_counter(
512 const dif_alert_handler_t *alert_handler,
513 dif_alert_handler_class_t alert_class, uint32_t *cycles);
Miguel Young de la Sota475887f2020-08-10 16:40:09 -0400514
515/**
516 * Gets the current state of this class.
517 *
518 * See `dif_alert_handler_class_state_t` for potential states.
519 *
520 * @param handler An alert handler handle.
521 * @param alert_class The class to get the state of
522 * @param state Out-param for the class state.
523 * @return The result of the operation.
524 */
Timothy Trippele3f8a822021-09-17 06:09:28 +0000525OT_WARN_UNUSED_RESULT
Timothy Trippel915ba132021-09-24 01:23:38 +0000526dif_result_t dif_alert_handler_get_class_state(
527 const dif_alert_handler_t *alert_handler,
528 dif_alert_handler_class_t alert_class,
Miguel Young de la Sota475887f2020-08-10 16:40:09 -0400529 dif_alert_handler_class_state_t *state);
530
531#ifdef __cplusplus
532} // extern "C"
533#endif // __cplusplus
534
535#endif // OPENTITAN_SW_DEVICE_LIB_DIF_DIF_ALERT_HANDLER_H_