Software APIs
dif_alert_handler.h
Go to the documentation of this file.
1 // 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 
18 
19 #ifdef __cplusplus
20 extern "C" {
21 #endif // __cplusplus
22 
23 /**
24  * A toggle state: enabled, or disabled.
25  *
26  * This enum may be used instead of a `bool` when describing an enabled/disabled
27  * state.
28  */
30  /**
31  * The "enabled" state.
32  */
34  /**
35  * The "disabled" state.
36  */
39 
40 /**
41  * Hardware instantiation parameters for the alert handler.
42  *
43  * This struct describes information about the underlying hardware that is
44  * not determined until the hardware design is used as part of a top-level
45  * design.
46  */
47 typedef struct dif_alert_handler_params {
48  /**
49  * The base address for the alert handler hardware registers.
50  */
52  /**
53  * The configured number of alerts.
54  *
55  * This value is fixed by the hardware, but not known to this library.
56  */
57  uint32_t alert_count;
58  /**
59  * The configured number of escalation signals.
60  *
61  * This value is fixed by the hardware, but not known to this library.
62  */
63  // It's actually fixed at 4 right now but this is likely to become
64  // configurable too.
67 
68 /**
69  * A handle to alert handler.
70  *
71  * This type should be treated as opaque by users.
72  */
73 typedef struct dif_alert_handler {
76 
77 /**
78  * The result of an alert handler operation.
79  */
81  /**
82  * Indicates that the operation succeeded.
83  */
85  /**
86  * Indicates some unspecified failure.
87  */
89  /**
90  * Indicates that some parameter passed into a function failed a
91  * precondition.
92  *
93  * When this value is returned, no hardware operations occurred.
94  */
97 
98 /**
99  * The result of an alert handler configuration operation.
100  */
102  /**
103  * Indicates that the operation succeeded.
104  */
106  /**
107  * Indicates some unspecified failure.
108  */
110  /**
111  * Indicates that some parameter passed into a function failed a
112  * precondition.
113  *
114  * When this value is returned, no hardware operations occurred.
115  */
117  /**
118  * Indicates that this operation has been locked out, and can never
119  * succeed until hardware reset.
120  */
123 
124 /**
125  * An alert class.
126  *
127  * An alert class roughly specifies how to deal with an alert. The class
128  * determines which interrupt handler is fired for an alert, as well as the
129  * fine-grained details of the escalation policy, for when the processor
130  * fails to respond to an alert quickly enough.
131  *
132  * Alert classes serve as the alert handler's IRQ types. There is one IRQ for
133  * each class. Whenever an alert fires, the corresponding class's IRQ is
134  * serviced by the processor (if enabled).
135  */
137  /**
138  * Alert class "A".
139  */
141  /**
142  * Alert class "B".
143  */
145  /**
146  * Alert class "C".
147  */
149  /**
150  * Alert class "D".
151  */
154 
155 /**
156  * A snapshot of the enablement state of the interrupts for alert handler.
157  *
158  * This is an opaque type, to be used with the
159  * `dif_alert_handler_irq_disable_all()` and
160  * `dif_alert_handler_irq_restore_all()` functions.
161  */
163 
164 /**
165  * An alert, identified by a numeric id.
166  *
167  * Alerts are hardware-level events indicating that something catastrophic
168  * has happened. An alert handler handle.consumes alerts, classifies them to a
169  * particular `dif_alert_handler_class_t`, and uses policy information attached
170  * to that class to handle it.
171  *
172  * The number of alerts is configurable at hardware-synthesis time, and is
173  * specified by the software when initializing a `dif_alert_handler_t`.
174  */
175 typedef uint32_t dif_alert_handler_alert_t;
176 
177 /**
178  * A local alert originating from within the alert handler itself.
179  *
180  * A local alert is exactly the same as a normal `dif_alert_handler_alert_t`,
181  * except that they use different functions for setting up classification and
182  * for getting causes.
183  */
185  kDifAlertHandlerLocalAlertAlertPingFail,
186  kDifAlertHandlerLocalAlertEscalationPingFail,
187  kDifAlertHandlerLocalAlertAlertIntegrityFail,
188  kDifAlertHandlerLocalAlertEscalationIntegrityFail,
190 
191 /**
192  * An escalation signal, identified by a numeric id.
193  *
194  * An escalation signal is a generic "response" to failing to handle a
195  * catastrophic event. What each signal means is determined by the chip.
196  *
197  * A `dif_alert_handler_class_t` can be configured to raise escalation signals
198  * as part of its policy.
199  */
200 typedef uint32_t dif_alert_handler_signal_t;
201 
202 /**
203  * An alert class state.
204  *
205  * This enum describes the sequence of states in the *escalation protocol*,
206  * which triggers under two different conditions:
207  * - If too many alerts of a particular class accumualte.
208  * - If the software IRQ handler for that class times out.
209  *
210  * When either of these conditions is reached, phase 0 begins. This may trigger
211  * an escalation signal, and after a configured duration, proceed to phase 1.
212  * This process repeats until phase 3 ends, at which point the class enters a
213  * "bricked" terminal state, which cannot be exited except by reset.
214  *
215  * At any point, software may end the escalation protocol by calling
216  * `dif_alert_handler_escalation_clear()` (unless clearing is disabled).
217  * Successfully calling this function, or clearing the IRQ on time, will reset
218  * back to the idle state. Note that this function cannot clear the terminal
219  * state; that state can only be cleared by resetting the chip.
220  */
222  /**
223  * The initial, idle state.
224  */
226  /**
227  * The "timeout" state, that is, the IRQ has been fired and the clock is
228  * ticking for the processor to handle the alert.
229  */
231 
232  /**
233  * The zeroth escalation phase.
234  */
236  /**
237  * The first escalation phase.
238  */
240  /**
241  * The second escalation phase.
242  */
244  /**
245  * The third escalation phase.
246  */
248 
249  /**
250  * The terminal state. Most configurations will never reach this state, since
251  * one of the previous phases will use an escalation signal to reset the
252  * device.
253  */
256 
257 /**
258  * Runtime configuration for responding to a given escalation phase.
259  *
260  * See `dif_alert_handler_class_config_t`.
261  */
263  /**
264  * The phase this configuration describes.
265  *
266  * It is an error for this to not be one of the `Phase` constants in
267  * `dif_alert_handler_class_state_t`.
268  */
269  dif_alert_handler_class_state_t phase;
270  /**
271  * The signal that should be triggered when this phase begins.
272  */
273  dif_alert_handler_signal_t signal;
275 
276 /**
277  * Runtime configuration for the duration of an escalation phase.
278  *
279  * See `dif_alert_handler_class_config_t`.
280  */
282  /**
283  * The phase this configuration describes.
284  *
285  * It is an error for this to not be one of the `Phase` constants in
286  * `dif_alert_handler_class_state_t`.
287  */
288  dif_alert_handler_class_state_t phase;
289  /**
290  * The duration of this phase, in cycles.
291  */
292  uint32_t cycles;
294 
295 /**
296  * Runtime configuration for a particular alert class.
297  *
298  * This struct describes how a particular alert class should be configured,
299  * such as which signals are associated with it, and what options are turned
300  * on for the escalation protocol.
301  *
302  * For each of the pointer/length field pairs below, if the length is zero, the
303  * pointer may be `NULL`.
304  */
306  /**
307  * The class this configuration describes.
308  */
310 
311  /**
312  * A list of alerts that should be classified as having this class.
313  *
314  * Each alert in this list will additionally be set as enabled.
315  */
316  const dif_alert_handler_alert_t *alerts;
317  /**
318  * The length of the array `alerts`.
319  */
320  size_t alerts_len;
321 
322  /**
323  * A list of local that should be classified as having this class.
324  *
325  * Each local alert in this list will additionally be set as enabled.
326  */
327  const dif_alert_handler_local_alert_t *local_alerts;
328  /**
329  * The length of the array `local_alerts`.
330  */
332 
333  /**
334  * Whether the escalation protocol should be used for this class
335  * (i.e., accumulator and timeout based escalation).
336  *
337  * Class IRQs will still fire regardless of this setting.
338  */
339  dif_alert_handler_toggle_t use_escalation_protocol;
340 
341  /**
342  * Whether automatic escalation locking should be used for this class.
343  *
344  * When enabled, upon beginning the escalation protocol, the hardware will
345  * lock
346  * the escalation clear bit, so that software cannot stop escalation once it
347  * has begun.
348  */
349  dif_alert_handler_toggle_t automatic_locking;
350 
351  /**
352  * The threshold for the class accmulator which, when reached, will
353  * automatically trigger escalation.
354  */
356 
357  /**
358  * The number of cycles this class's associated IRQ handler has to acknowledge
359  * the IRQ before escalation is triggered.
360  *
361  * A value of zero disables the timeout.
362  */
364 
365  /**
366  * Signals to associate to each escalation phase.
367  *
368  * Each escalation phase signal in this list will additionally be set as
369  * enabled; phases not listed will have their escalation signals disabled.
370  */
372  /**
373  * The length of the array `phase_signals`.
374  */
376 
377  /**
378  * Durations, in cycles, of each escalation phase.
379  */
381  /**
382  * The length of the array `phase_durations`.
383  */
386 
387 /**
388  * Runtime configuration for alert handler.
389  *
390  * This struct describes runtime information for one-time configuration of the
391  * hardware.
392  */
393 typedef struct dif_alert_handler_config {
394  /**
395  * The alert ping timeout, in cycles.
396  *
397  * The alert handler will regularly, at random intervals, ping alert
398  * sources. If a source fails to respond, a local alert will be raised.
399  *
400  * The appropriate value will be dependent on all of the clocks involved on
401  * a chip.
402  *
403  * Note that the ping timer won't start until `dif_alert_handler_lock()` is
404  * successfully called.
405  *
406  * This value must fit in 24 bits.
407  */
408  uint32_t ping_timeout;
409 
410  /**
411  * A list of alert classes to configure.
412  */
414  /**
415  * The length of the array `classes`.
416  */
417  size_t classes_len;
419 
420 /**
421  * Creates a new handle for alert handler.
422  *
423  * This function does not actuate the hardware.
424  *
425  * @param params Hardware instantiation parameters.
426  * @param handler Out param for the initialized handle.
427  * @return The result of the operation.
428  */
432 
433 /**
434  * Configures alert handler with runtime information.
435  *
436  * This function should need to be called once for the lifetime of `handle`.
437  *
438  * This operation is lock-protected.
439  *
440  * @param handler An alert handler handle.
441  * @param config Runtime configuration parameters.
442  * @return The result of the operation.
443  */
446  const dif_alert_handler_t *handler, dif_alert_handler_config_t config);
447 /**
448  * Locks out alert handler configuration functionality.
449  *
450  * Once locked, `dif_alert_handler_configure()` will return
451  * `kDifAlertHandlerConfigLocked`.
452  *
453  * This operation cannot be undone, and should be performed at the end of
454  * configuring the alert handler in early boot.
455  *
456  * This function is reentrant: calling it while functionality is locked will
457  * have no effect and return `kDifAlertHandlerOk`.
458  *
459  * @param handler An alert handler handle.
460  * @return The result of the operation.
461  */
464  const dif_alert_handler_t *handler);
465 
466 /**
467  * Checks whether this alert handler is locked.
468  *
469  * See `dif_alert_handler_lock()`.
470  *
471  * @param handler An alert handler handle.
472  * @param is_locked Out-param for the locked state.
473  * @return The result of the operation.
474  */
477  const dif_alert_handler_t *handler, bool *is_locked);
478 
479 /**
480  * Returns whether a particular interrupt is currently pending.
481  *
482  * @param handler An alert handler handle.
483  * @param alert_class An alert class.
484  * @param is_pending Out-param for whether the interrupt is pending.
485  * @return The result of the operation.
486  */
489  const dif_alert_handler_t *handler, dif_alert_handler_class_t alert_class,
490  bool *is_pending);
491 
492 /**
493  * Acknowledges a particular interrupt, indicating to the hardware that it has
494  * been successfully serviced.
495  *
496  * @param handler An alert handler handle.
497  * @param alert_class An alert class.
498  * @return The result of the operation.
499  */
502  const dif_alert_handler_t *handler, dif_alert_handler_class_t alert_class);
503 
504 /**
505  * Checks whether a particular interrupt is currently enabled or disabled.
506  *
507  * @param handler An alert handler handle.
508  * @param alert_class An alert class.
509  * @param state Out-param toggle state of the interrupt.
510  * @return The result of the operation.
511  */
514  const dif_alert_handler_t *handler, dif_alert_handler_class_t alert_class,
515  dif_alert_handler_toggle_t *state);
516 
517 /**
518  * Sets whether a particular interrupt is currently enabled or disabled.
519  *
520  * @param handler An alert handler handle.
521  * @param alert_class An alert class.
522  * @param state The new toggle state for the interrupt.
523  * @return The result of the operation.
524  */
527  const dif_alert_handler_t *handler, dif_alert_handler_class_t alert_class,
528  dif_alert_handler_toggle_t state);
529 
530 /**
531  * Forces a particular interrupt, causing it to be serviced as if hardware had
532  * asserted it.
533  *
534  * @param handler An alert handler handle.
535  * @param alert_class An alert class.
536  * @return The result of the operation.
537  */
540  const dif_alert_handler_t *handler, dif_alert_handler_class_t alert_class);
541 
542 /**
543  * Disables all interrupts, optionally snapshotting all toggle state for later
544  * restoration.
545  *
546  * @param handler An alert handler handle.
547  * @param snapshot Out-param for the snapshot; may be `NULL`.
548  * @return The result of the operation.
549  */
552  const dif_alert_handler_t *handler,
553  dif_alert_handler_irq_snapshot_t *snapshot);
554 
555 /**
556  * Restores interrupts from the given snapshot.
557  *
558  * This function can be used with `dif_alert_handler_irq_disable_all()` to
559  * temporary
560  * interrupt save-and-restore.
561  *
562  * @param handler An alert handler handle.
563  * @param snapshot A snapshot to restore from.
564  * @return The result of the operation.
565  */
568  const dif_alert_handler_t *handler,
569  const dif_alert_handler_irq_snapshot_t *snapshot);
570 
571 /**
572  * Checks whether an alert is one of the causes for an alert IRQ.
573  *
574  * Note that multiple alerts may be causes at the same time.
575  *
576  * @param handler An alert handler handle.
577  * @param alert The alert to check.
578  * @param is_cause Out-param for whether this alert is a cause.
579  * @return The result of the operation.
580  */
583  const dif_alert_handler_t *handler, dif_alert_handler_alert_t alert,
584  bool *is_cause);
585 
586 /**
587  * Clears an alert from the cause vector, similar to an IRQ acknowledgement.
588  *
589  * @param handler An alert handler handle.
590  * @param alert The alert to acknowledge.
591  * @return The result of the operation.
592  */
595  const dif_alert_handler_t *handler, dif_alert_handler_alert_t alert);
596 
597 /**
598  * Checks whether a local alert is one of the causes for an alert IRQ.
599  *
600  * Note that multiple alerts may be causes at the same time.
601  *
602  * @param handler An alert handler handle.
603  * @param alert The alert to check.
604  * @param is_cause Out-param for whether this alert is a cause.
605  * @return The result of the operation.
606  */
609  const dif_alert_handler_t *handler, dif_alert_handler_local_alert_t alert,
610  bool *is_cause);
611 
612 /**
613  * Clears a local alert from the cause vector, similar to an IRQ
614  * acknowledgement.
615  *
616  * @param handler An alert handler handle.
617  * @param alert The alert to acknowledge.
618  * @return The result of the operation.
619  */
622  const dif_alert_handler_t *handler, dif_alert_handler_local_alert_t alert);
623 
624 /**
625  * Checks whether software can clear escalations for this class.
626  *
627  * If `automatic_locking` has been set in a class's configuration, this
628  * function may suddenly begin returning `false` instead of `true` without
629  * software invervention, if escalation has been triggered.
630  *
631  * @param handler An alert handler handle.
632  * @param alert_class The class to check.
633  * @param can_clear Out-param for the clear enablement state.
634  * @return The result of the operation.
635  */
638  const dif_alert_handler_t *handler, dif_alert_handler_class_t alert_class,
639  bool *can_clear);
640 
641 /**
642  * Disables escalation clearing for this class.
643  *
644  * This operation is similar to locking in that it cannot be undone.
645  *
646  * @param handler An alert handler handle.
647  * @param alert_class The class to disable clearing for.
648  * @return The result of the operation.
649  */
652  const dif_alert_handler_t *handler, dif_alert_handler_class_t alert_class);
653 
654 /**
655  * Clears an on-going escalation, as well as the class accumulator.
656  *
657  * This operation can be disabled with
658  * `dif_alert_handler_escalation_disable_clearing()`.
659  *
660  * @param handler An alert handler handle.
661  * @param alert_class The class to clear an escalation for.
662  * @return The result of the operation.
663  */
666  const dif_alert_handler_t *handler, dif_alert_handler_class_t alert_class);
667 
668 /**
669  * Gets the accumulator value for this class.
670  *
671  * This value is the number of alerts of this class that have been logged so
672  * far (more or less, since multiple alerts on the same cycle will be merged
673  * into one). Once this value equals the configured threshold, any followup
674  * alerts will immediately trigger the escalation protocol.
675  *
676  * This value is cleared as a side-effect of
677  * `dif_alert_handler_escalation_clear()`.
678  *
679  * @param handler An alert handler handle.
680  * @param alert_class The class to get the accumulator for.
681  * @param alerts Out-param for the accumulator.
682  * @return The result of the operation.
683  */
686  const dif_alert_handler_t *handler, dif_alert_handler_class_t alert_class,
687  uint16_t *alerts);
688 
689 /**
690  * Gets the current value of the "escalation counter".
691  *
692  * The interpretation of this value depends on the value returned by
693  * `dif_alert_handler_class_state_get()`. If it is in the timeout state,
694  * it returns the number of cycles counted towards that cycle so far.
695  * If in an escalation phase, it returns the number of cycles that phase
696  * has been active for.
697  *
698  * @param handler An alert handler handle.
699  * @param alert_class The class to set the counter for.
700  * @param cycles Out-param for the counter.
701  * @return The result of the operation.
702  */
705  const dif_alert_handler_t *handler, dif_alert_handler_class_t alert_class,
706  uint32_t *cycles);
707 
708 /**
709  * Gets the current state of this class.
710  *
711  * See `dif_alert_handler_class_state_t` for potential states.
712  *
713  * @param handler An alert handler handle.
714  * @param alert_class The class to get the state of
715  * @param state Out-param for the class state.
716  * @return The result of the operation.
717  */
720  const dif_alert_handler_t *handler, dif_alert_handler_class_t alert_class,
721  dif_alert_handler_class_state_t *state);
722 
723 #ifdef __cplusplus
724 } // extern "C"
725 #endif // __cplusplus
726 
727 #endif // OPENTITAN_SW_DEVICE_LIB_DIF_DIF_ALERT_HANDLER_H_