blob: 4f4ec89edb621c5f4818433ab0ac2e92e1c90024 [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 * Hardware instantiation parameters for the alert handler.
28 *
29 * This struct describes information about the underlying hardware that is
30 * not determined until the hardware design is used as part of a top-level
31 * design.
32 */
33typedef struct dif_alert_handler_params {
34 /**
Miguel Young de la Sota475887f2020-08-10 16:40:09 -040035 * The configured number of alerts.
36 *
37 * This value is fixed by the hardware, but not known to this library.
38 */
39 uint32_t alert_count;
40 /**
41 * The configured number of escalation signals.
42 *
43 * This value is fixed by the hardware, but not known to this library.
44 */
45 // It's actually fixed at 4 right now but this is likely to become
46 // configurable too.
47 uint32_t escalation_signal_count;
48} dif_alert_handler_params_t;
49
50/**
Miguel Young de la Sota475887f2020-08-10 16:40:09 -040051 * An alert class.
52 *
53 * An alert class roughly specifies how to deal with an alert. The class
54 * determines which interrupt handler is fired for an alert, as well as the
55 * fine-grained details of the escalation policy, for when the processor
56 * fails to respond to an alert quickly enough.
57 *
58 * Alert classes serve as the alert handler's IRQ types. There is one IRQ for
59 * each class. Whenever an alert fires, the corresponding class's IRQ is
60 * serviced by the processor (if enabled).
61 */
62typedef enum dif_alert_handler_class {
63 /**
64 * Alert class "A".
65 */
66 kDifAlertHandlerClassA = 0,
67 /**
68 * Alert class "B".
69 */
70 kDifAlertHandlerClassB = 1,
71 /**
72 * Alert class "C".
73 */
74 kDifAlertHandlerClassC = 2,
75 /**
76 * Alert class "D".
77 */
78 kDifAlertHandlerClassD = 3,
79} dif_alert_handler_class_t;
80
81/**
Miguel Young de la Sota475887f2020-08-10 16:40:09 -040082 * An alert, identified by a numeric id.
83 *
84 * Alerts are hardware-level events indicating that something catastrophic
85 * has happened. An alert handler handle.consumes alerts, classifies them to a
86 * particular `dif_alert_handler_class_t`, and uses policy information attached
87 * to that class to handle it.
88 *
89 * The number of alerts is configurable at hardware-synthesis time, and is
90 * specified by the software when initializing a `dif_alert_handler_t`.
91 */
92typedef uint32_t dif_alert_handler_alert_t;
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 */
101typedef enum dif_alert_handler_local_alert {
102 kDifAlertHandlerLocalAlertAlertPingFail,
103 kDifAlertHandlerLocalAlertEscalationPingFail,
104 kDifAlertHandlerLocalAlertAlertIntegrityFail,
105 kDifAlertHandlerLocalAlertEscalationIntegrityFail,
Timothy Trippelbcca3302021-08-04 20:18:16 +0000106 kDifAlertHandlerLocalAlertBusIntegrityFail,
Michael Schaffner1a5d53a2021-06-03 17:44:17 -0700107 kDifAlertHandlerLocalAlertShadowedUpdateError,
108 kDifAlertHandlerLocalAlertShadowedStorageError,
Miguel Young de la Sota475887f2020-08-10 16:40:09 -0400109} dif_alert_handler_local_alert_t;
110
111/**
112 * An escalation signal, identified by a numeric id.
113 *
114 * An escalation signal is a generic "response" to failing to handle a
115 * catastrophic event. What each signal means is determined by the chip.
116 *
117 * A `dif_alert_handler_class_t` can be configured to raise escalation signals
118 * as part of its policy.
119 */
120typedef uint32_t dif_alert_handler_signal_t;
121
122/**
123 * An alert class state.
124 *
125 * This enum describes the sequence of states in the *escalation protocol*,
126 * which triggers under two different conditions:
Timothy Trippel3d578e52021-08-05 00:37:34 +0000127 * - If too many alerts of a particular class accumulate.
Miguel Young de la Sota475887f2020-08-10 16:40:09 -0400128 * - If the software IRQ handler for that class times out.
129 *
130 * When either of these conditions is reached, phase 0 begins. This may trigger
131 * an escalation signal, and after a configured duration, proceed to phase 1.
132 * This process repeats until phase 3 ends, at which point the class enters a
133 * "bricked" terminal state, which cannot be exited except by reset.
134 *
135 * At any point, software may end the escalation protocol by calling
136 * `dif_alert_handler_escalation_clear()` (unless clearing is disabled).
137 * Successfully calling this function, or clearing the IRQ on time, will reset
138 * back to the idle state. Note that this function cannot clear the terminal
139 * state; that state can only be cleared by resetting the chip.
140 */
141typedef enum dif_alert_handler_class_state {
142 /**
143 * The initial, idle state.
144 */
145 kDifAlertHandlerClassStateIdle,
146 /**
147 * The "timeout" state, that is, the IRQ has been fired and the clock is
148 * ticking for the processor to handle the alert.
149 */
150 kDifAlertHandlerClassStateTimeout,
151
152 /**
153 * The zeroth escalation phase.
154 */
155 kDifAlertHandlerClassStatePhase0,
156 /**
157 * The first escalation phase.
158 */
159 kDifAlertHandlerClassStatePhase1,
160 /**
161 * The second escalation phase.
162 */
163 kDifAlertHandlerClassStatePhase2,
164 /**
165 * The third escalation phase.
166 */
167 kDifAlertHandlerClassStatePhase3,
168
169 /**
170 * The terminal state. Most configurations will never reach this state, since
171 * one of the previous phases will use an escalation signal to reset the
172 * device.
173 */
174 kDifAlertHandlerClassStateTerminal,
175} dif_alert_handler_class_state_t;
176
177/**
178 * Runtime configuration for responding to a given escalation phase.
179 *
Miguel Young de la Sotadd71d982020-09-17 15:40:16 -0400180 * See `dif_alert_handler_class_config_t`.
Miguel Young de la Sota475887f2020-08-10 16:40:09 -0400181 */
182typedef struct dif_alert_handler_class_phase_signal {
183 /**
184 * The phase this configuration describes.
185 *
186 * It is an error for this to not be one of the `Phase` constants in
187 * `dif_alert_handler_class_state_t`.
188 */
189 dif_alert_handler_class_state_t phase;
190 /**
191 * The signal that should be triggered when this phase begins.
192 */
193 dif_alert_handler_signal_t signal;
194} dif_alert_handler_class_phase_signal_t;
195
196/**
197 * Runtime configuration for the duration of an escalation phase.
198 *
Miguel Young de la Sotadd71d982020-09-17 15:40:16 -0400199 * See `dif_alert_handler_class_config_t`.
Miguel Young de la Sota475887f2020-08-10 16:40:09 -0400200 */
201typedef struct dif_alert_handler_class_phase_duration {
202 /**
203 * The phase this configuration describes.
204 *
205 * It is an error for this to not be one of the `Phase` constants in
206 * `dif_alert_handler_class_state_t`.
207 */
208 dif_alert_handler_class_state_t phase;
209 /**
210 * The duration of this phase, in cycles.
211 */
212 uint32_t cycles;
213} dif_alert_handler_class_phase_duration_t;
214
215/**
216 * Runtime configuration for a particular alert class.
217 *
218 * This struct describes how a particular alert class should be configured,
219 * such as which signals are associated with it, and what options are turned
220 * on for the escalation protocol.
221 *
222 * For each of the pointer/length field pairs below, if the length is zero, the
223 * pointer may be `NULL`.
224 */
225typedef struct dif_alert_handler_class_config {
226 /**
227 * The class this configuration describes.
228 */
229 dif_alert_handler_class_t alert_class;
230
231 /**
232 * A list of alerts that should be classified as having this class.
233 *
234 * Each alert in this list will additionally be set as enabled.
235 */
236 const dif_alert_handler_alert_t *alerts;
237 /**
238 * The length of the array `alerts`.
239 */
240 size_t alerts_len;
241
242 /**
243 * A list of local that should be classified as having this class.
244 *
245 * Each local alert in this list will additionally be set as enabled.
246 */
247 const dif_alert_handler_local_alert_t *local_alerts;
248 /**
249 * The length of the array `local_alerts`.
250 */
251 size_t local_alerts_len;
252
253 /**
254 * Whether the escalation protocol should be used for this class
255 * (i.e., accumulator and timeout based escalation).
256 *
257 * Class IRQs will still fire regardless of this setting.
258 */
Timothy Trippel915ba132021-09-24 01:23:38 +0000259 dif_toggle_t use_escalation_protocol;
Miguel Young de la Sota475887f2020-08-10 16:40:09 -0400260
261 /**
262 * Whether automatic escalation locking should be used for this class.
263 *
264 * When enabled, upon beginning the escalation protocol, the hardware will
265 * lock
266 * the escalation clear bit, so that software cannot stop escalation once it
267 * has begun.
268 */
Timothy Trippel915ba132021-09-24 01:23:38 +0000269 dif_toggle_t automatic_locking;
Miguel Young de la Sota475887f2020-08-10 16:40:09 -0400270
271 /**
272 * The threshold for the class accmulator which, when reached, will
Miguel Young de la Sotadf5994c2020-10-22 13:29:46 -0400273 * automatically trigger escalation.
Miguel Young de la Sota475887f2020-08-10 16:40:09 -0400274 */
275 uint16_t accumulator_threshold;
276
277 /**
278 * The number of cycles this class's associated IRQ handler has to acknowledge
279 * the IRQ before escalation is triggered.
280 *
281 * A value of zero disables the timeout.
282 */
283 uint32_t irq_deadline_cycles;
284
285 /**
286 * Signals to associate to each escalation phase.
287 *
288 * Each escalation phase signal in this list will additionally be set as
289 * enabled; phases not listed will have their escalation signals disabled.
290 */
291 const dif_alert_handler_class_phase_signal_t *phase_signals;
292 /**
293 * The length of the array `phase_signals`.
294 */
295 size_t phase_signals_len;
296
297 /**
298 * Durations, in cycles, of each escalation phase.
299 */
300 const dif_alert_handler_class_phase_duration_t *phase_durations;
301 /**
302 * The length of the array `phase_durations`.
303 */
304 size_t phase_durations_len;
305} dif_alert_handler_class_config_t;
306
307/**
308 * Runtime configuration for alert handler.
309 *
310 * This struct describes runtime information for one-time configuration of the
311 * hardware.
312 */
313typedef struct dif_alert_handler_config {
314 /**
315 * The alert ping timeout, in cycles.
316 *
Miguel Young de la Sotadd71d982020-09-17 15:40:16 -0400317 * The alert handler will regularly, at random intervals, ping alert
318 * sources. If a source fails to respond, a local alert will be raised.
Miguel Young de la Sota475887f2020-08-10 16:40:09 -0400319 *
320 * The appropriate value will be dependent on all of the clocks involved on
321 * a chip.
322 *
323 * Note that the ping timer won't start until `dif_alert_handler_lock()` is
324 * successfully called.
Miguel Young de la Sotadd71d982020-09-17 15:40:16 -0400325 *
326 * This value must fit in 24 bits.
Miguel Young de la Sota475887f2020-08-10 16:40:09 -0400327 */
328 uint32_t ping_timeout;
329
330 /**
331 * A list of alert classes to configure.
332 */
333 const dif_alert_handler_class_config_t *classes;
334 /**
335 * The length of the array `classes`.
336 */
337 size_t classes_len;
338} dif_alert_handler_config_t;
339
340/**
341 * Creates a new handle for alert handler.
342 *
343 * This function does not actuate the hardware.
344 *
Timothy Trippel915ba132021-09-24 01:23:38 +0000345 * @param base_addr Hardware instantiation base address.
Miguel Young de la Sota475887f2020-08-10 16:40:09 -0400346 * @param params Hardware instantiation parameters.
347 * @param handler Out param for the initialized handle.
348 * @return The result of the operation.
349 */
Timothy Trippele3f8a822021-09-17 06:09:28 +0000350OT_WARN_UNUSED_RESULT
Timothy Trippel915ba132021-09-24 01:23:38 +0000351dif_result_t dif_alert_handler_init(mmio_region_t base_addr,
352 dif_alert_handler_params_t params,
353 dif_alert_handler_t *alert_handler);
Miguel Young de la Sota475887f2020-08-10 16:40:09 -0400354
355/**
356 * Configures alert handler with runtime information.
357 *
358 * This function should need to be called once for the lifetime of `handle`.
359 *
360 * This operation is lock-protected.
361 *
362 * @param handler An alert handler handle.
363 * @param config Runtime configuration parameters.
364 * @return The result of the operation.
365 */
Timothy Trippele3f8a822021-09-17 06:09:28 +0000366OT_WARN_UNUSED_RESULT
Timothy Trippel915ba132021-09-24 01:23:38 +0000367dif_result_t dif_alert_handler_configure(
368 const dif_alert_handler_t *alert_handler, dif_alert_handler_params_t params,
369 dif_alert_handler_config_t config);
Miguel Young de la Sota475887f2020-08-10 16:40:09 -0400370/**
371 * Locks out alert handler configuration functionality.
372 *
373 * Once locked, `dif_alert_handler_configure()` will return
374 * `kDifAlertHandlerConfigLocked`.
375 *
376 * This operation cannot be undone, and should be performed at the end of
377 * configuring the alert handler in early boot.
378 *
379 * This function is reentrant: calling it while functionality is locked will
380 * have no effect and return `kDifAlertHandlerOk`.
381 *
382 * @param handler An alert handler handle.
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_lock(const dif_alert_handler_t *alert_handler);
Miguel Young de la Sota475887f2020-08-10 16:40:09 -0400387
388/**
389 * Checks whether this alert handler is locked.
390 *
391 * See `dif_alert_handler_lock()`.
392 *
393 * @param handler An alert handler handle.
394 * @param is_locked Out-param for the locked state.
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_is_locked(
399 const dif_alert_handler_t *alert_handler, bool *is_locked);
Miguel Young de la Sota475887f2020-08-10 16:40:09 -0400400
401/**
402 * Checks whether an alert is one of the causes for an alert IRQ.
403 *
Miguel Young de la Sotadd71d982020-09-17 15:40:16 -0400404 * Note that multiple alerts may be causes at the same time.
405 *
Miguel Young de la Sota475887f2020-08-10 16:40:09 -0400406 * @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_alert_is_cause(
413 const dif_alert_handler_t *alert_handler, dif_alert_handler_params_t params,
414 dif_alert_handler_alert_t alert, bool *is_cause);
Miguel Young de la Sota475887f2020-08-10 16:40:09 -0400415
416/**
417 * Clears an alert from the cause vector, similar to an IRQ acknowledgement.
418 *
419 * @param handler An alert handler handle.
420 * @param alert The alert to acknowledge.
421 * @return The result of the operation.
422 */
Timothy Trippele3f8a822021-09-17 06:09:28 +0000423OT_WARN_UNUSED_RESULT
Timothy Trippel915ba132021-09-24 01:23:38 +0000424dif_result_t dif_alert_handler_alert_acknowledge(
425 const dif_alert_handler_t *alert_handler, dif_alert_handler_params_t params,
426 dif_alert_handler_alert_t alert);
Miguel Young de la Sota475887f2020-08-10 16:40:09 -0400427
428/**
Miguel Young de la Sotadd71d982020-09-17 15:40:16 -0400429 * Checks whether a local alert is one of the causes for an alert IRQ.
430 *
431 * Note that multiple alerts may be causes at the same time.
432 *
433 * @param handler An alert handler handle.
434 * @param alert The alert to check.
435 * @param is_cause Out-param for whether this alert is a cause.
436 * @return The result of the operation.
437 */
Timothy Trippele3f8a822021-09-17 06:09:28 +0000438OT_WARN_UNUSED_RESULT
Timothy Trippel915ba132021-09-24 01:23:38 +0000439dif_result_t dif_alert_handler_local_alert_is_cause(
440 const dif_alert_handler_t *alert_handler,
441 dif_alert_handler_local_alert_t alert, bool *is_cause);
Miguel Young de la Sotadd71d982020-09-17 15:40:16 -0400442
443/**
444 * Clears a local alert from the cause vector, similar to an IRQ
445 * acknowledgement.
446 *
447 * @param handler An alert handler handle.
448 * @param alert The alert to acknowledge.
449 * @return The result of the operation.
450 */
Timothy Trippele3f8a822021-09-17 06:09:28 +0000451OT_WARN_UNUSED_RESULT
Timothy Trippel915ba132021-09-24 01:23:38 +0000452dif_result_t dif_alert_handler_local_alert_acknowledge(
453 const dif_alert_handler_t *alert_handler,
454 dif_alert_handler_local_alert_t alert);
Miguel Young de la Sotadd71d982020-09-17 15:40:16 -0400455
456/**
Miguel Young de la Sota475887f2020-08-10 16:40:09 -0400457 * Checks whether software can clear escalations for this class.
458 *
459 * If `automatic_locking` has been set in a class's configuration, this
460 * function may suddenly begin returning `false` instead of `true` without
461 * software invervention, if escalation has been triggered.
462 *
463 * @param handler An alert handler handle.
464 * @param alert_class The class to check.
465 * @param can_clear Out-param for the clear enablement state.
466 * @return The result of the operation.
467 */
Timothy Trippele3f8a822021-09-17 06:09:28 +0000468OT_WARN_UNUSED_RESULT
Timothy Trippel915ba132021-09-24 01:23:38 +0000469dif_result_t dif_alert_handler_escalation_can_clear(
470 const dif_alert_handler_t *alert_handler,
471 dif_alert_handler_class_t alert_class, bool *can_clear);
Miguel Young de la Sota475887f2020-08-10 16:40:09 -0400472
473/**
474 * Disables escalation clearing for this class.
475 *
476 * This operation is similar to locking in that it cannot be undone.
477 *
478 * @param handler An alert handler handle.
479 * @param alert_class The class to disable clearing for.
480 * @return The result of the operation.
481 */
Timothy Trippele3f8a822021-09-17 06:09:28 +0000482OT_WARN_UNUSED_RESULT
Timothy Trippel915ba132021-09-24 01:23:38 +0000483dif_result_t dif_alert_handler_escalation_disable_clearing(
484 const dif_alert_handler_t *alert_handler,
485 dif_alert_handler_class_t alert_class);
Miguel Young de la Sota475887f2020-08-10 16:40:09 -0400486
487/**
488 * Clears an on-going escalation, as well as the class accumulator.
489 *
490 * This operation can be disabled with
491 * `dif_alert_handler_escalation_disable_clearing()`.
492 *
493 * @param handler An alert handler handle.
494 * @param alert_class The class to clear an escalation for.
495 * @return The result of the operation.
496 */
Timothy Trippele3f8a822021-09-17 06:09:28 +0000497OT_WARN_UNUSED_RESULT
Timothy Trippel915ba132021-09-24 01:23:38 +0000498dif_result_t dif_alert_handler_escalation_clear(
499 const dif_alert_handler_t *alert_handler,
500 dif_alert_handler_class_t alert_class);
Miguel Young de la Sota475887f2020-08-10 16:40:09 -0400501
502/**
503 * Gets the accumulator value for this class.
504 *
505 * This value is the number of alerts of this class that have been logged so
506 * far (more or less, since multiple alerts on the same cycle will be merged
507 * into one). Once this value equals the configured threshold, any followup
508 * alerts will immediately trigger the escalation protocol.
509 *
510 * This value is cleared as a side-effect of
511 * `dif_alert_handler_escalation_clear()`.
512 *
513 * @param handler An alert handler handle.
514 * @param alert_class The class to get the accumulator for.
515 * @param alerts Out-param for the accumulator.
516 * @return The result of the operation.
517 */
Timothy Trippele3f8a822021-09-17 06:09:28 +0000518OT_WARN_UNUSED_RESULT
Timothy Trippel915ba132021-09-24 01:23:38 +0000519dif_result_t dif_alert_handler_get_accumulator(
520 const dif_alert_handler_t *alert_handler,
521 dif_alert_handler_class_t alert_class, uint16_t *alerts);
Miguel Young de la Sota475887f2020-08-10 16:40:09 -0400522
523/**
524 * Gets the current value of the "escalation counter".
525 *
526 * The interpretation of this value depends on the value returned by
527 * `dif_alert_handler_class_state_get()`. If it is in the timeout state,
528 * it returns the number of cycles counted towards that cycle so far.
529 * If in an escalation phase, it returns the number of cycles that phase
530 * has been active for.
531 *
532 * @param handler An alert handler handle.
533 * @param alert_class The class to set the counter for.
534 * @param cycles Out-param for the counter.
535 * @return The result of the operation.
536 */
Timothy Trippele3f8a822021-09-17 06:09:28 +0000537OT_WARN_UNUSED_RESULT
Timothy Trippel915ba132021-09-24 01:23:38 +0000538dif_result_t dif_alert_handler_get_escalation_counter(
539 const dif_alert_handler_t *alert_handler,
540 dif_alert_handler_class_t alert_class, uint32_t *cycles);
Miguel Young de la Sota475887f2020-08-10 16:40:09 -0400541
542/**
543 * Gets the current state of this class.
544 *
545 * See `dif_alert_handler_class_state_t` for potential states.
546 *
547 * @param handler An alert handler handle.
548 * @param alert_class The class to get the state of
549 * @param state Out-param for the class state.
550 * @return The result of the operation.
551 */
Timothy Trippele3f8a822021-09-17 06:09:28 +0000552OT_WARN_UNUSED_RESULT
Timothy Trippel915ba132021-09-24 01:23:38 +0000553dif_result_t dif_alert_handler_get_class_state(
554 const dif_alert_handler_t *alert_handler,
555 dif_alert_handler_class_t alert_class,
Miguel Young de la Sota475887f2020-08-10 16:40:09 -0400556 dif_alert_handler_class_state_t *state);
557
558#ifdef __cplusplus
559} // extern "C"
560#endif // __cplusplus
561
562#endif // OPENTITAN_SW_DEVICE_LIB_DIF_DIF_ALERT_HANDLER_H_