1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
//! Event queue types for ARM SMMU v3
//!
//! Event queue management per ARM SMMU v3 specification Section 6.3.
use crate::types::SecurityState;
/// Event type enumeration
///
/// Defines the types of events that can be queued in the event queue.
///
/// Discriminant values are the exact event numbers from ARM IHI0070G.b §7.3.
/// Variants in the 0xE0–0xEF range are IMPLEMENTATION DEFINED per §7.3.21 and
/// are used by this software model for internal completion signalling that has
/// no direct equivalent in the hardware event queue.
#[repr(u8)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum EventType {
// ── Spec-defined events (§7.3) ──────────────────────────────────────────
/// §7.3.2 F_UUT — Unsupported Upstream Transaction (0x01)
FUut = 0x01,
/// §7.3.3 C_BAD_STREAMID — StreamID out of range (0x02)
CBadStreamid = 0x02,
/// §7.3.4 F_STE_FETCH — STE fetch caused external abort (0x03)
FSteFetch = 0x03,
/// §7.3.5 C_BAD_STE — Used STE invalid (0x04)
CBadSte = 0x04,
/// §7.3.6 F_BAD_ATS_TREQ — ATS Translation Request disallowed (0x05)
FBadAtsTreq = 0x05,
/// §7.3.7 F_STREAM_DISABLED — Non-substream transaction with stream disabled (0x06)
FStreamDisabled = 0x06,
/// §7.3.8 F_TRANSL_FORBIDDEN — ATS Translated transaction disallowed (0x07)
FTranslForbidden = 0x07,
/// §7.3.9 C_BAD_SUBSTREAMID — SubstreamID present but invalid (0x08)
CBadSubstreamid = 0x08,
/// §7.3.10 F_CD_FETCH — CD fetch caused external abort (0x09)
FCdFetch = 0x09,
/// §7.3.11 C_BAD_CD — Fetched CD invalid (0x0A)
CBadCd = 0x0A,
/// §7.3.12 F_WALK_EABT — External abort during translation table walk (0x0B)
FWalkEabt = 0x0B,
/// §7.3.13 F_TRANSLATION — Translation fault (0x10)
FTranslation = 0x10,
/// §7.3.14 F_ADDR_SIZE — Address size fault (0x11)
FAddrSize = 0x11,
/// §7.3.15 F_ACCESS — Access flag fault (0x12)
FAccess = 0x12,
/// §7.3.16 F_PERMISSION — Permission fault (0x13)
FPermission = 0x13,
/// §7.3.17 F_TLB_CONFLICT — TLB conflict (0x20)
FTlbConflict = 0x20,
/// §7.3.18 F_CFG_CONFLICT — Configuration cache conflict (0x21)
FCfgConflict = 0x21,
/// §7.3.19 E_PAGE_REQUEST — Page request hint (0x24)
EPageRequest = 0x24,
/// §7.3.20 F_VMS_FETCH — VMS fetch caused external abort (0x25)
FVmsFetch = 0x25,
// ── Implementation-defined events (§7.3.21, 0xE0–0xEF range) ───────────
/// IMPDEF: Command SYNC completion — internal SW model signalling
CommandSyncCompletion = 0xE0,
/// IMPDEF: ATC invalidation completion — internal SW model signalling
AtcInvalidateCompletion = 0xE1,
}
impl Default for EventType {
fn default() -> Self {
Self::FTranslation
}
}
/// Event entry structure
///
/// Contains all information about a single event in the event queue.
/// Follows ARM SMMU v3 event record format.
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct EventEntry {
/// Type of event
pub event_type: EventType,
/// Source stream identifier (raw u32 for simpler access)
pub stream_id: u32,
/// Process Address Space ID (raw u32 for simpler access)
pub pasid: u32,
/// Faulting or relevant address (raw u64 for simpler access)
pub address: u64,
/// Security state context
pub security_state: SecurityState,
/// Event-specific error code
pub error_code: u32,
/// Event timestamp
pub timestamp: u64,
/// Whether this event corresponds to a stalled transaction (ARM IHI0070G.b §7.3)
/// Must be true for events generated by stall-mode faults (§3.5.3).
pub stall: bool,
/// §3.12.2: Stall Tag — identifies the stalled transaction group for CMD_RESUME matching.
/// Non-zero only when `stall == true`; zero for all non-stall events.
pub stag: u16,
// ── CONF-GAP-20: §7.3 event record wire format fields ───────────────────
/// Intermediate Physical Address — for two-stage faults (§7.3).
/// Zero for single-stage faults.
pub ipa: u64,
/// CLASS: 2-bit event class field per ARM IHI0070G.b §7.3.
///
/// Defined only for translation-related F_* events:
/// - `0b00` (0) = CD — fault during CD fetch
/// - `0b01` (1) = TTD — fault during translation table descriptor fetch
/// - `0b10` (2) = IN — fault on the input address itself (default for SW model F_* events)
/// - `0b11` = Reserved
///
/// C_* configuration events (C_BAD_STREAMID, C_BAD_STE, C_BAD_SUBSTREAMID, C_BAD_CD,
/// F_CFG_CONFLICT) must leave this field at 0 — CLASS is not defined for them.
pub event_class: u8,
/// S2 flag — true if the fault occurred during Stage-2 translation (§7.3).
pub s2: bool,
/// RnW — true=read, false=write (ARM §7.3: RnW=1 means Read not Write).
pub rnw: bool,
/// InD — true=instruction fetch, false=data access (§7.3).
pub ind: bool,
/// PnU — true=privileged, false=unprivileged (§7.3).
pub pnu: bool,
/// NSIPA — true if the IPA is in the Non-Secure physical address space (§7.3).
pub nsipa: bool,
/// SSV — SubstreamID Valid; true when the transaction carried a non-zero PASID (§7.3).
pub ssv: bool,
// ── Item 1 (Moderate): §7.3.6 F_BAD_ATS_TREQ ATS permission bits [95:92] ─
/// §7.3.6: ATS TR requested Read permission (bit 95).
///
/// True when the original ATS Translation Request was not a pure write
/// (i.e. the access includes read or execute). RES0 for all other event types.
pub ats_r: bool,
/// §7.3.6: ATS TR requested Write permission (bit 94, = !NW).
///
/// True when the original ATS Translation Request requested write permission.
/// RES0 for all other event types.
pub ats_w: bool,
/// §7.3.6: ATS TR requested Execute permission (bit 93).
///
/// True when the original ATS Translation Request was an instruction fetch.
/// RES0 for all other event types.
pub ats_x: bool,
/// §7.3.6: ATS TR requested Privileged access (bit 92).
///
/// True when the original ATS Translation Request was a privileged access
/// (AxPROT\[1\]=1). RES0 for all other event types.
pub ats_p: bool,
// ── Item 2 (Low): §7.3.2 F_UUT Reason field bits [79:64] ───────────────
/// §7.3.2: F_UUT IMPLEMENTATION DEFINED Reason field (bits [79:64]).
///
/// Always 0 for this software model; 0 is a valid IMPDEF choice per §7.3.2.
pub reason: u16,
// ── BUG-NEW-9: §7.3.19 E_PAGE_REQUEST permission and span fields ────────
/// §7.3.19: Unprivileged Read permission requested (RES0 for non-E_PAGE_REQUEST events).
pub ur: bool,
/// §7.3.19: Unprivileged Write permission requested (RES0 for non-E_PAGE_REQUEST events).
pub uw: bool,
/// §7.3.19: Unprivileged Execute permission requested (RES0 for non-E_PAGE_REQUEST events).
pub ux: bool,
/// §7.3.19: Privileged Read permission requested (RES0 for non-E_PAGE_REQUEST events).
pub pr: bool,
/// §7.3.19: Privileged Write permission requested (RES0 for non-E_PAGE_REQUEST events).
pub pw: bool,
/// §7.3.19: Privileged Execute permission requested (RES0 for non-E_PAGE_REQUEST events).
pub px: bool,
/// §7.3.19: Access span in units of 4096 bytes. 0 = single page (RES0 for non-E_PAGE_REQUEST events).
pub span: u8,
}
impl EventEntry {
/// Return a zeroed/defaulted `EventEntry`.
///
/// Provided as a `const fn` so it can be used as a struct-update base in
/// both `const` and non-`const` contexts:
///
/// ```rust
/// use smmu::types::{EventEntry, EventType};
/// let ev = EventEntry { event_type: EventType::FTranslation, stream_id: 1,
/// ..EventEntry::zeroed() };
/// ```
#[must_use]
pub const fn zeroed() -> Self {
Self {
event_type: EventType::FTranslation,
stream_id: 0,
pasid: 0,
address: 0,
security_state: SecurityState::NonSecure,
error_code: 0,
timestamp: 0,
stall: false,
stag: 0,
ipa: 0,
event_class: 0,
s2: false,
rnw: false,
ind: false,
pnu: false,
nsipa: false,
ssv: false,
ats_r: false,
ats_w: false,
ats_x: false,
ats_p: false,
reason: 0,
// BUG-NEW-9: §7.3.19 E_PAGE_REQUEST permission/span fields default to 0/false.
ur: false,
uw: false,
ux: false,
pr: false,
pw: false,
px: false,
span: 0,
}
}
/// Create a new event entry
#[must_use]
pub const fn new(event_type: EventType, stream_id: u32, pasid: u32, address: u64) -> Self {
Self {
event_type,
stream_id,
pasid,
address,
security_state: SecurityState::NonSecure,
error_code: 0,
timestamp: 0,
stall: false,
stag: 0,
// CONF-GAP-20: wire-format fields default to zero/false.
ipa: 0,
event_class: 0,
s2: false,
rnw: false,
ind: false,
pnu: false,
nsipa: false,
ssv: false,
ats_r: false,
ats_w: false,
ats_x: false,
ats_p: false,
reason: 0,
// BUG-NEW-9: §7.3.19 E_PAGE_REQUEST permission/span fields default to 0/false.
ur: false,
uw: false,
ux: false,
pr: false,
pw: false,
px: false,
span: 0,
}
}
}
impl Default for EventEntry {
fn default() -> Self {
Self::zeroed()
}
}