CHERIoT RTOS
A compartmentalised RTOS for CHERIoT hardware
Loading...
Searching...
No Matches
interrupt.h
Go to the documentation of this file.
1// Copyright Microsoft and CHERIoT Contributors.
2// SPDX-License-Identifier: MIT
3
4#pragma once
5/**
6 * \file
7 *
8 * This file describes the interfaces for compartments to wait for interrupts.
9 * Interrupts are exposed to compartments as futexes that contain the count of
10 * the number of times that an interrupt has fired. This count can wrap but
11 * that should not be visible in practice (if will be observable only if one
12 * thread handles a specific interrupt 2^32 times in between another thread
13 * finishing handling that interrupt and waiting again).
14 *
15 * The flow for waiting for an interrupt involves the following steps:
16 *
17 * 1. Request the futex word for a particular from the scheduler.
18 * 2. Wait on the futex.
19 * 3. Read the value of the futex word.
20 * 4. Handle whatever the interrupt was raised for.
21 * 5. Mark the interrupt as completed.
22 * 6. Loop from step 2, using the value read from step 3.
23 *
24 * If the interrupt fires between steps 5 and 6 then the futex word will not
25 * match the value read in step 3 and the futex wait will return immediately.
26 *
27 * The first time that step 2 is reached, the expected value for the futex
28 * should be 0. This ensures that you acknowledge any interrupt that happened
29 * in between the system starting and your registering interest in the
30 * interrupt.
31 *
32 * Note that step 2 may use a multiwaiter, rather than a single futex_wait
33 * call, if you wish to wait for one of multiple event sources.
34 *
35 * Both step 1 and 5 require an authorising capability, as described below.
36 */
37
38#include <compartment.h>
39#include <stdbool.h>
40
41#ifndef CLANG_TIDY
42# if !__has_include("board-interrupts.h")
43# error Including <interrupt.h> w/o cheriot.board.interrupts dependency
44# endif
45# include "board-interrupts.h"
46#else
47
48enum InterruptName : uint16_t
49{
50 FakeInterrupt = 4,
51 RevokerInterrupt = 5,
52 EthernetReceiveInterrupt = 3,
53 EthernetInterrupt = 47
54};
55
56#endif
57
58/**
59 * Structure for authorising access to a specific interrupt.
60 */
62{
63 /**
64 * The interrupt number that this refers to.
65 */
66 enum InterruptName interruptNumber;
67 /**
68 * Does this authorise accessing the futex for monitoring the interrupt?
69 */
70 bool mayWait;
71 /**
72 * Does this authorise acknowledging the interrupt?
73 */
75};
76
77/**
78 * Type for sealed capabilities that authorise access to interrupts.
79 */
80typedef CHERI_SEALED(struct InterruptCapabilityState *) InterruptCapability;
81
82/**
83 * Helper macro to forward declare an interrupt capability.
84 */
85#define DECLARE_INTERRUPT_CAPABILITY(name) \
86 DECLARE_STATIC_SEALED_VALUE( \
87 struct InterruptCapabilityState, scheduler, InterruptKey, name);
88
89/**
90 * Helper macro to define an interrupt capability. The three arguments after
91 * the name are the interrupt number and two boolean values indicating whether
92 * it may be used with `interrupt_futex_get` and with `interrupt_complete`,
93 * respectively.
94 */
95#define DEFINE_INTERRUPT_CAPABILITY(name, number, mayWait, mayComplete) \
96 DEFINE_STATIC_SEALED_VALUE(struct InterruptCapabilityState, \
97 scheduler, \
98 InterruptKey, \
99 name, \
100 number, \
101 mayWait, \
102 mayComplete);
103
104/**
105 * Helper macro to define an interrupt capability without a separate
106 * declaration. The arguments are the same as those for
107 * `DEFINE_INTERRUPT_CAPABILITY`.
108 */
109#define DECLARE_AND_DEFINE_INTERRUPT_CAPABILITY( \
110 name, number, mayWait, mayComplete) \
111 DECLARE_INTERRUPT_CAPABILITY(name); \
112 DEFINE_INTERRUPT_CAPABILITY(name, number, mayWait, mayComplete)
113
114/**
115 * Request the futex associated with an interrupt. The argument is a sealed
116 * capability to an `InterruptCapabilityState` structure that must have
117 * `mayWait` flag set to true. This is sealed with the `InterruptKey` type
118 * exposed from the scheduler compartment.
119 *
120 * Returns `nullptr` on failure.
121 */
122__cheri_compartment("scheduler") const uint32_t *interrupt_futex_get(
123 InterruptCapability interruptcapability);
124
125/**
126 * Acknowledge the end of handling an interrupt. The argument is a sealed
127 * capability to an `InterruptCapabilityState` structure that must have
128 * `mayWait` flag set to true. This is sealed with the `InterruptKey` type
129 * exposed from the scheduler compartment.
130 *
131 * Returns 0 on success or `-EPERM` if the argument does not authorise this
132 * operation.
133 */
134__cheri_compartment("scheduler") int interrupt_complete(
135 InterruptCapability interruptcapability);
int interrupt_complete(InterruptCapability interruptcapability)
Acknowledge the end of handling an interrupt.
typedef CHERI_SEALED(struct InterruptCapabilityState *) InterruptCapability
Type for sealed capabilities that authorise access to interrupts.
const uint32_t * interrupt_futex_get(InterruptCapability interruptcapability)
Request the futex associated with an interrupt.
Structure for authorising access to a specific interrupt.
Definition interrupt.h:62
bool mayComplete
Does this authorise acknowledging the interrupt?
Definition interrupt.h:74
bool mayWait
Does this authorise accessing the futex for monitoring the interrupt?
Definition interrupt.h:70
enum InterruptName interruptNumber
The interrupt number that this refers to.
Definition interrupt.h:66