Software APIs
dif_alert_handler.h
Go to the documentation of this file.
1// Copyright lowRISC contributors (OpenTitan project).
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="/book/hw/ip/alert_handler/">Alert handler</a> Device
11 * Interface Functions
12 */
13
14#include <stdint.h>
15
19
20#include "sw/device/lib/dif/autogen/dif_alert_handler_autogen.h"
21
22#ifdef __cplusplus
23extern "C" {
24#endif // __cplusplus
25
26/**
27 * Helper X macro for defining enums and case statements related to alert
28 * classes. If an additional class is ever added to the hardware, this list can
29 * be updated.
30 */
31#define LIST_OF_CLASSES(X) \
32 X(A, 0) \
33 X(B, 1) \
34 X(C, 2) \
35 X(D, 3)
36
37/**
38 * Helper macro for defining a `dif_alert_handler_class_t` enumeration constant.
39 * @class_ Alert class of the enumeration constant.
40 * @value_ Value of the enumeration constant.
41 */
42#define ALERT_CLASS_ENUM_INIT_(class_, value_) \
43 kDifAlertHandlerClass##class_ = value_,
44
45/**
46 * An alert class.
47 *
48 * An alert class roughly specifies how to deal with an alert. The class
49 * determines which interrupt handler is fired for an alert, as well as the
50 * fine-grained details of the escalation policy, for when the processor
51 * fails to respond to an alert quickly enough.
52 *
53 * Alert classes serve as the alert handler's IRQ types. There is one IRQ for
54 * each class. Whenever an alert fires, the corresponding class's IRQ is
55 * serviced by the processor (if enabled).
56 */
60
61/**
62 * An alert, identified by a numeric id.
63 *
64 * Alerts are hardware-level events indicating that something catastrophic
65 * has happened. The alert handler consumes alerts, classifies them into a
66 * particular `dif_alert_handler_class_t`, and uses policy information attached
67 * to that class to handle it.
68 *
69 * The number of alerts is configurable at hardware-synthesis time.
70 */
72
73/**
74 * Helper X macro for defining enums and case statements related to local
75 * alerts. If an additional class is ever added to the hardware, this list can
76 * be updated.
77 */
78#define LIST_OF_LOC_ALERTS(X) \
79 X(kDifAlertHandlerLocalAlertAlertPingFail, 0) \
80 X(kDifAlertHandlerLocalAlertEscalationPingFail, 1) \
81 X(kDifAlertHandlerLocalAlertAlertIntegrityFail, 2) \
82 X(kDifAlertHandlerLocalAlertEscalationIntegrityFail, 3) \
83 X(kDifAlertHandlerLocalAlertBusIntegrityFail, 4) \
84 X(kDifAlertHandlerLocalAlertShadowedUpdateError, 5) \
85 X(kDifAlertHandlerLocalAlertShadowedStorageError, 6)
86
87/**
88 * Helper macro for defining a `dif_alert_handler_local_alert_t` enumeration
89 * constant.
90 * @name_ Name of the enumeration constant.
91 */
92#define LOC_ALERT_ENUM_INIT_(name_, value_) name_ = value_,
93
94/**
95 * A local alert originating from within the alert handler itself.
96 *
97 * A local alert is exactly the same as a normal `dif_alert_handler_alert_t`,
98 * except that they use different functions for setting up classification and
99 * for getting causes.
100 */
104
105/**
106 * An alert class state.
107 *
108 * This enum describes the sequence of states in the *escalation protocol*,
109 * which triggers under two different conditions:
110 * - If too many alerts of a particular class accumulate.
111 * - If the software IRQ handler for that class times out.
112 *
113 * When either of these conditions is reached, phase 0 begins. This may trigger
114 * an escalation signal, and after a configured duration, proceed to phase 1.
115 * This process repeats until phase 3 ends, at which point the class enters a
116 * "bricked" terminal state, which cannot be exited except by reset.
117 *
118 * At any point, software may end the escalation protocol by calling
119 * `dif_alert_handler_escalation_clear()` (unless clearing is disabled).
120 * Successfully calling this function, or clearing the IRQ on time, will reset
121 * the state back to idle. Note that this function cannot clear the terminal
122 * state; that state can only be cleared by resetting the chip.
123 */
125 /**
126 * The initial, idle state.
127 */
129 /**
130 * The "timeout" state, that is, the IRQ has been fired and the clock is
131 * ticking for the processor to handle the alert.
132 */
134
135 /**
136 * The "fsm_error" state. This is a terminal state indicating the FSM
137 * has been glitched.
138 */
140 /**
141 * The terminal state. Most configurations will never reach this state, since
142 * one of the previous phases will use an escalation signal to reset the
143 * device.
144 */
146
147 /**
148 * The zeroth escalation phase.
149 */
151 /**
152 * The first escalation phase.
153 */
155 /**
156 * The second escalation phase.
157 */
159 /**
160 * The third escalation phase.
161 */
164
165/**
166 * An escalation signal, identified by a numeric ID.
167 *
168 * An escalation signal is a generic "response" to failing to handle alert(s).
169 * The meaning of each escalation signal is determined by the chip.
170 *
171 * An alert class can be configured to raise various escalation signal(s) during
172 * various escalation phases as part of its escalation policy.
173 */
175
176/**
177 * Runtime configuration for an escalation phase.
178 */
180 /**
181 * The phase this configuration describes.
182 *
183 * It is an error for this to not be one of the `Phase` constants in
184 * `dif_alert_handler_class_state_t`.
185 */
187 /**
188 * The escalation signal that should be triggered when this phase begins.
189 */
191 /**
192 * The duration of this phase, in cycles.
193 */
196
197/**
198 * Runtime configuration for a particular alert class.
199 *
200 * This struct describes the escalation protocol for an alert class.
201 */
203 /**
204 * Whether to automatically lock the accumulation counter.
205 *
206 * There are two ways to lock the accumulation counter (prevent it from being
207 * cleared once the class's escalation protocol has been triggered):
208 * 1. clear the write enable for the accumulation counter clear register, or
209 * 2. to set this configuration flag which will automatically clear the
210 * write enable for the accumulation counter clear register once the
211 * class's escalation protocol has been triggered.
212 */
214 /**
215 * The threshold for the class accmulator which indicates the number of alerts
216 * that must fire because the class's escalation protocol will trigger.
217 */
219 /**
220 * The number of cycles this class's associated IRQ handler has to acknowledge
221 * the IRQ before escalation is triggered.
222 *
223 * A value of zero disables the timeout.
224 */
226 /**
227 * Escalation phases to be configured for this class.
228 *
229 * Each escalation phase in this list will additionally be set as enabled for
230 * this class; phases not listed will have their escalation signals disabled.
231 */
233 /**
234 * The length of the array `escalation_phases`.
235 */
237 /**
238 * The escalation phase to capture the crashdump information in.
239 *
240 * It is an error for this to not be one of the `Phase` constants in
241 * `dif_alert_handler_class_state_t`.
242 *
243 * Note, it is recommended to capture the crashdump upon entering the first
244 * escalation phase that activates a countermeasure with many side-effects
245 * (e.g. life cycle state scrapping) in order to prevent spurious alert events
246 * from masking the original alert causes.
247 */
250
251/**
252 * Runtime configuration for the alert handler.
253 *
254 * This struct describes runtime information for a single-shot configuration of
255 * the alert handler hardware.
256 *
257 * Note, any of the array pointers may be NULL, in which case the associated
258 * length should be 0.
259 */
261 /**
262 * A list of alerts to configure.
263 */
265 /**
266 * A list of classes to assign each alert to.
267 */
269 /**
270 * The lengths of the arrays `alerts` and `alert_classes`.
271 */
273
274 /**
275 * A list of local alerts to configure.
276 */
278 /**
279 * A list of classes to assign each local alert to.
280 */
282 /**
283 * The lengths of the arrays `local_alerts` and `local_alert_classes`.
284 */
286
287 /**
288 * A list of alert classes to configure.
289 */
291 /**
292 * A list of alert class (escalation protocol) configurations.
293 */
295 /**
296 * The length of the arrays `classes` and `class_configs`.
297 */
299
300 /**
301 * The alert ping timeout, in cycles.
302 *
303 * The alert handler will regularly, at random intervals, ping alert
304 * sources. If a source fails to respond, a local alert will be raised.
305 *
306 * The appropriate value will be dependent on all of the clocks involved on
307 * a chip.
308 *
309 * Note that the ping timer won't start until `dif_alert_handler_lock()` is
310 * successfully called.
311 *
312 * Note while this value must fit into the timeout register which is smaller
313 * than the native word length.
314 */
315 uint32_t ping_timeout;
316
318
319/**
320 * Configures an alert in the alert handler.
321 *
322 * This operation is lock-protected, meaning once the configuration is locked,
323 * it cannot be reconfigured until after a system reset.
324 *
325 * @param alert_handler An alert handler handle.
326 * @param alert The alert to be configured.
327 * @param alert_class The class to assign the alert to.
328 * @param enabled The enablement state to configure the alert in.
329 * @param locked The locked state to configure the alert in.
330 * @return The result of the operation.
331 */
334 const dif_alert_handler_t *alert_handler, dif_alert_handler_alert_t alert,
335 dif_alert_handler_class_t alert_class, dif_toggle_t enabled,
336 dif_toggle_t locked);
337
338/**
339 * Configures a local alert in the alert handler.
340 *
341 * This operation is lock-protected, meaning once the configuration is locked,
342 * it cannot be reconfigured until after a system reset.
343 *
344 * @param alert_handler An alert handler handle.
345 * @param local_alert The local alert to be configured.
346 * @param alert_class The class to assign the alert to.
347 * @param enabled The enablement state to configure the alert in.
348 * @param locked The locked state to configure the alert in.
349 * @return The result of the operation.
350 */
353 const dif_alert_handler_t *alert_handler,
355 dif_alert_handler_class_t alert_class, dif_toggle_t enabled,
356 dif_toggle_t locked);
357
358/**
359 * Configures the escalation protocol of an alert class in the alert handler.
360 *
361 * This operation is lock-protected, meaning once the configuration is locked,
362 * it cannot be reconfigured until after a system reset.
363 *
364 * Note, regardless if the class is enabled or, IRQs will still fire based on
365 * the accumulation counter threshold configuration for the class, however, the
366 * escalation protocol will not trigger.
367 *
368 * @param alert_handler An alert handler handle.
369 * @param alert_class The class to be configured.
370 * @param config The escalation protocol configuration.
371 * @param enabled The enablement state of the class escalation protocol.
372 * @param locked The locked state to configure the class in.
373 * @return The result of the operation.
374 */
377 const dif_alert_handler_t *alert_handler,
378 dif_alert_handler_class_t alert_class,
380 dif_toggle_t locked);
381
382/**
383 * Configures the crash dump trigger for an alert class in the alert
384 * handler.
385 *
386 * @param alert_handler An alert handler handle.
387 * @param alert_class The class to be configured.
388 * @param crashdump_phase The crash dump trigger phase.
389 * @return The result of the operation.
390 */
393 const dif_alert_handler_t *alert_handler,
394 dif_alert_handler_class_t alert_class,
395 dif_alert_handler_class_state_t crashdump_phase);
396
397/**
398 * Configures the ping timer in the alert handler.
399 *
400 * This operation is lock-protected, meaning once the configuration is locked,
401 * it cannot be reconfigured until after a system reset.
402 *
403 * Note, the ping timer will only ping alerts that have been enabled AND locked.
404 * Therefore, this DIF should be invoked after configuring and enabling each
405 * (local) alert.
406 *
407 * @param alert_handler An alert handler handle.
408 * @param ping_timeout The alert ping timeout, in cycles.
409 * @param enabled The enablement state to configure the ping timer in.
410 * @param locked The locked state to configure ping timer in.
411 * @return The result of the operation.
412 */
415 const dif_alert_handler_t *alert_handler, uint32_t ping_timeout,
416 dif_toggle_t enabled, dif_toggle_t locked);
417
418/**
419 * Enables the ping timer in the alert handler.
420 *
421 * This operation is lock-protected, meaning once the configuration is locked,
422 * it cannot be reconfigured until after a system reset.
423 *
424 * Note, the ping timer will only ping alerts that have been enabled AND locked.
425 * Therefore, this DIF should be invoked after configuring and enabling each
426 * (local) alert.
427 *
428 * @param alert_handler An alert handler handle.
429 * @param locked The locked state to configure ping timer in after enabling it.
430 * @return The result of the operation.
431 */
434 const dif_alert_handler_t *alert_handler, dif_toggle_t locked);
435
436/**
437 * Locks out an alert handler alert configuration.
438 *
439 * This operation cannot be undone, and should be performed at the end of
440 * configuring the alert handler in early boot.
441 *
442 * This function is reentrant: calling it while functionality is locked will
443 * have no effect and return `kDifOk`.
444 *
445 * @param alert_handler An alert handler handle.
446 * @param alert The alert to lock.
447 * @return The result of the operation.
448 */
451 const dif_alert_handler_t *alert_handler, dif_alert_handler_alert_t alert);
452
453/**
454 * Checks whether an alert handler's alert is locked.
455 *
456 * @param alert_handler An alert handler handle.
457 * @param alert The alert to check is locked.
458 * @param[out] is_locked Out-param for the locked state.
459 * @return The result of the operation.
460 */
463 const dif_alert_handler_t *alert_handler, dif_alert_handler_alert_t alert,
464 bool *is_locked);
465
466/**
467 * Locks out an alert handler local alert configuration.
468 *
469 * This operation cannot be undone, and should be performed at the end of
470 * configuring the alert handler in early boot.
471 *
472 * This function is reentrant: calling it while functionality is locked will
473 * have no effect and return `kDifOk`.
474 *
475 * @param alert_handler An alert handler handle.
476 * @param local_alert The local alert to lock.
477 * @return The result of the operation.
478 */
481 const dif_alert_handler_t *alert_handler,
483
484/**
485 * Checks whether an alert handler's local alert is locked.
486 *
487 * @param alert_handler An alert handler handle.
488 * @param local_alert The local alert to check is locked.
489 * @param[out] is_locked Out-param for the locked state.
490 * @return The result of the operation.
491 */
494 const dif_alert_handler_t *alert_handler,
495 dif_alert_handler_local_alert_t local_alert, bool *is_locked);
496
497/**
498 * Locks out an alert handler class configuration.
499 *
500 * This operation cannot be undone, and should be performed at the end of
501 * configuring the alert handler in early boot.
502 *
503 * This function is reentrant: calling it while functionality is locked will
504 * have no effect and return `kDifOk`.
505 *
506 * @param alert_handler An alert handler handle.
507 * @param alert_class The alert class to lock.
508 * @return The result of the operation.
509 */
512 const dif_alert_handler_t *alert_handler,
513 dif_alert_handler_class_t alert_class);
514
515/**
516 * Checks whether an alert handler's class is locked.
517 *
518 * @param alert_handler An alert handler handle.
519 * @param alert_class The alert class to check is locked.
520 * @param[out] is_locked Out-param for the locked state.
521 * @return The result of the operation.
522 */
525 const dif_alert_handler_t *alert_handler,
526 dif_alert_handler_class_t alert_class, bool *is_locked);
527
528/**
529 * Locks out alert handler ping timer configuration.
530 *
531 * This operation cannot be undone, and should be performed at the end of
532 * configuring the alert handler in early boot.
533 *
534 * This function is reentrant: calling it while functionality is locked will
535 * have no effect and return `kDifOk`.
536 *
537 * @param alert_handler An alert handler handle.
538 * @return The result of the operation.
539 */
542 const dif_alert_handler_t *alert_handler);
543
544/**
545 * Checks whether alert handler's ping timer is locked.
546 *
547 * @param alert_handler An alert handler handle.
548 * @param[out] is_locked Out-param for the locked state.
549 * @return The result of the operation.
550 */
553 const dif_alert_handler_t *alert_handler, bool *is_locked);
554
555/**
556 * Checks whether an alert is one of the causes for an alert IRQ.
557 *
558 * Note that multiple alerts may be causes at the same time.
559 *
560 * @param alert_handler An alert handler handle.
561 * @param alert The alert to check.
562 * @param[out] is_cause Out-param for whether this alert is a cause.
563 * @return The result of the operation.
564 */
567 const dif_alert_handler_t *alert_handler, dif_alert_handler_alert_t alert,
568 bool *is_cause);
569
570/**
571 * Clears an alert from the cause vector, similar to an IRQ acknowledgement.
572 *
573 * @param alert_handler An alert handler handle.
574 * @param alert The alert to acknowledge.
575 * @return The result of the operation.
576 */
579 const dif_alert_handler_t *alert_handler, dif_alert_handler_alert_t alert);
580
581/**
582 * Checks whether a local alert is one of the causes for an alert IRQ.
583 *
584 * Note that multiple alerts may be causes at the same time.
585 *
586 * @param alert_handler An alert handler handle.
587 * @param local_alert The local alert to check.
588 * @param[out] is_cause Out-param for whether this alert is a cause.
589 * @return The result of the operation.
590 */
593 const dif_alert_handler_t *alert_handler,
594 dif_alert_handler_local_alert_t local_alert, bool *is_cause);
595
596/**
597 * Clears a local alert from the cause vector, similar to an IRQ
598 * acknowledgement.
599 *
600 * @param alert_handler An alert handler handle.
601 * @param local_alert The local alert to acknowledge.
602 * @return The result of the operation.
603 */
606 const dif_alert_handler_t *alert_handler,
608
609/**
610 * Checks whether software can clear escalations for this class.
611 *
612 * If `automatic_locking` has been set in a class's configuration, this
613 * function may suddenly begin returning `false` instead of `true` without
614 * software invervention, if escalation has been triggered.
615 *
616 * @param alert_handler An alert handler handle.
617 * @param alert_class The class to check.
618 * @param[out] can_clear Out-param for the clear enablement state.
619 * @return The result of the operation.
620 */
623 const dif_alert_handler_t *alert_handler,
624 dif_alert_handler_class_t alert_class, bool *can_clear);
625
626/**
627 * Disables escalation clearing for this class.
628 *
629 * This operation is similar to locking in that it cannot be undone.
630 *
631 * @param alert_handler An alert handler handle.
632 * @param alert_class The class to disable clearing for.
633 * @return The result of the operation.
634 */
637 const dif_alert_handler_t *alert_handler,
638 dif_alert_handler_class_t alert_class);
639
640/**
641 * Clears an on-going escalation, as well as the class accumulator.
642 *
643 * This operation can be disabled with
644 * `dif_alert_handler_escalation_disable_clearing()`.
645 *
646 * @param alert_handler An alert handler handle.
647 * @param alert_class The class to clear an escalation for.
648 * @return The result of the operation.
649 */
652 const dif_alert_handler_t *alert_handler,
653 dif_alert_handler_class_t alert_class);
654
655/**
656 * Gets the accumulator value for this class.
657 *
658 * This value is the number of alerts of this class that have been logged so
659 * far (more or less, since multiple alerts on the same cycle will be merged
660 * into one). Once this value equals the configured threshold, any followup
661 * alerts will immediately trigger the escalation protocol.
662 *
663 * This value is cleared as a side-effect of
664 * `dif_alert_handler_escalation_clear()`.
665 *
666 * @param alert_handler An alert handler handle.
667 * @param alert_class The class to get the accumulator for.
668 * @param[out] num_alerts Out-param for the number of alerts that have
669 * accumulated.
670 * @return The result of the operation.
671 */
674 const dif_alert_handler_t *alert_handler,
675 dif_alert_handler_class_t alert_class, uint16_t *num_alerts);
676
677/**
678 * Gets the current value of the "escalation counter".
679 *
680 * The interpretation of this value depends on the value returned by
681 * `dif_alert_handler_class_state_get()`. If it is in the timeout state,
682 * it returns the number of cycles counted towards that cycle so far.
683 * If in an escalation phase, it returns the number of cycles that phase
684 * has been active for.
685 *
686 * @param alert_handler An alert handler handle.
687 * @param alert_class The class to set the counter for.
688 * @param[out] cycles Out-param for the counter.
689 * @return The result of the operation.
690 */
693 const dif_alert_handler_t *alert_handler,
694 dif_alert_handler_class_t alert_class, uint32_t *cycles);
695
696/**
697 * Checks whether this class is enabled.
698 *
699 * @param alert_handler An alert handler handle.
700 * @param alert_class The class to check.
701 * @param[out] is_enabled Out-param for the enablement state.
702 * @return The result of the operation.
703 */
706 const dif_alert_handler_t *alert_handler,
707 dif_alert_handler_class_t alert_class, bool *is_enabled);
708
709/**
710 * Gets the current state of this class.
711 *
712 * See `dif_alert_handler_class_state_t` for potential states.
713 *
714 * @param alert_handler An alert handler handle.
715 * @param alert_class The class to get the state of
716 * @param[out] state Out-param for the class state.
717 * @return The result of the operation.
718 */
721 const dif_alert_handler_t *alert_handler,
722 dif_alert_handler_class_t alert_class,
724
725#ifdef __cplusplus
726} // extern "C"
727#endif // __cplusplus
728
729#endif // OPENTITAN_SW_DEVICE_LIB_DIF_DIF_ALERT_HANDLER_H_