CHERIoT RTOS
A compartmentalised RTOS for CHERIoT hardware
Toggle main menu visibility
Loading...
Searching...
No Matches
sdk
include
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
48
enum
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
*/
61
struct
InterruptCapabilityState
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
*/
74
bool
mayComplete
;
75
};
76
77
/**
78
* Type for sealed capabilities that authorise access to interrupts.
79
*/
80
typedef
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);
interrupt_complete
int interrupt_complete(InterruptCapability interruptcapability)
Acknowledge the end of handling an interrupt.
CHERI_SEALED
typedef CHERI_SEALED(struct InterruptCapabilityState *) InterruptCapability
Type for sealed capabilities that authorise access to interrupts.
interrupt_futex_get
const uint32_t * interrupt_futex_get(InterruptCapability interruptcapability)
Request the futex associated with an interrupt.
InterruptCapabilityState
Structure for authorising access to a specific interrupt.
Definition
interrupt.h:62
InterruptCapabilityState::mayComplete
bool mayComplete
Does this authorise acknowledging the interrupt?
Definition
interrupt.h:74
InterruptCapabilityState::mayWait
bool mayWait
Does this authorise accessing the futex for monitoring the interrupt?
Definition
interrupt.h:70
InterruptCapabilityState::interruptNumber
enum InterruptName interruptNumber
The interrupt number that this refers to.
Definition
interrupt.h:66
Generated by
1.18.0