1#![expect(missing_docs)]
7#![forbid(unsafe_code)]
8#![no_std]
9
10pub mod gic;
11pub mod rsi;
12pub mod smccc;
13
14use bitfield_struct::bitfield;
15use core::fmt::Display;
16use open_enum::open_enum;
17use zerocopy::FromBytes;
18use zerocopy::Immutable;
19use zerocopy::IntoBytes;
20use zerocopy::KnownLayout;
21
22#[bitfield(u64)]
25pub struct Cpsr64 {
26 pub sp: bool,
28 _rsvd0: bool,
29 #[bits(2)]
31 pub el: u8,
32 pub aa32: bool,
35 _rsvd1: bool,
36 pub f: bool,
37 pub i: bool,
38 pub a: bool,
39 pub d: bool,
40 #[bits(2)]
41 pub btype: u8,
42 pub ssbs: bool,
43 #[bits(7)]
44 _rsvd2: u8,
45 pub il: bool,
46 pub ss: bool,
47 pub pan: bool,
48 pub uao: bool,
49 pub dit: bool,
50 pub tco: bool,
51 #[bits(2)]
52 _rsvd3: u8,
53 pub v: bool,
54 pub c: bool,
55 pub z: bool,
56 pub n: bool,
57 pub res0: u32,
58}
59
60#[bitfield(u64)]
62#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
63pub struct EsrEl2 {
64 #[bits(6)]
65 pub lower_iss: u8,
66 pub wnr: bool,
67 #[bits(9)]
68 pub mid_iss: u16,
69 #[bits(5)]
70 pub b_srt: u8,
71 pub a: bool,
72 pub b: bool,
73 pub c: bool,
74 pub d: bool,
75 pub il: bool,
76 #[bits(6)]
77 pub ec: u8,
78 #[bits(5)]
79 pub iss2: u8,
80 #[bits(27)]
81 _rsvd: u32,
82}
83
84impl EsrEl2 {
85 pub fn is_write(&self) -> bool {
86 self.wnr()
88 }
89
90 pub fn is_read(&self) -> bool {
91 !self.wnr()
93 }
94
95 pub fn iss(&self) -> u32 {
96 u32::from(self.lower_iss())
97 | ((self.wnr() as u32) << 6)
98 | (u32::from(self.mid_iss()) << 7)
99 | (u32::from(self.b_srt()) << 16)
100 | ((self.a() as u32) << 21)
101 | ((self.b() as u32) << 22)
102 | ((self.c() as u32) << 23)
103 | ((self.d() as u32) << 24)
104 }
105
106 pub fn srt(&self) -> Option<u8> {
107 if (ExceptionClass::DATA_ABORT_LOWER.0..ExceptionClass::DATA_ABORT.0).contains(&self.ec()) {
109 Some(self.b_srt())
110 } else {
111 None
112 }
113 }
114}
115
116#[bitfield(u64)]
118#[derive(PartialEq, Eq)]
119pub struct SctlrEl1 {
120 pub m: bool,
121 pub a: bool,
122 pub c: bool,
123 pub sa: bool,
124 pub sa0: bool,
125 pub cp15ben: bool,
126 pub n_aa: bool,
127 pub itd: bool,
128 pub sed: bool,
129 pub uma: bool,
130 pub en_rctx: bool,
131 pub eos: bool,
132 pub i: bool,
133 pub en_db: bool,
134 pub dze: bool,
135 pub uct: bool,
136 pub n_twi: bool,
137 _mbz0: bool,
138 pub n_twe: bool,
139 pub wxn: bool,
140 pub tscxt: bool,
141 pub iesb: bool,
142 pub eis: bool,
143 pub span: bool,
144 pub e0e: bool,
145 pub ee: bool,
146 pub uci: bool,
147 pub en_da: bool,
148 pub n_tlsmd: bool,
149 pub lsmaoe: bool,
150 pub en_ib: bool,
151 pub en_ia: bool,
152 pub cmow: bool,
153 pub msc_en: bool,
154 _mbz1: bool,
155 pub bt0: bool,
156 pub bt1: bool,
157 pub itfsb: bool,
158 #[bits(2)]
159 pub tcf0: u64,
160 #[bits(2)]
161 pub tcf: u64,
162 pub ata0: bool,
163 pub ata: bool,
164 pub dssbs: bool,
165 pub twed_en: bool,
166 #[bits(4)]
167 pub twedel: u64,
168 pub tmt0: bool,
169 pub tmt: bool,
170 pub tme0: bool,
171 pub tme: bool,
172 pub en_asr: bool,
173 pub en_as0: bool,
174 pub en_als: bool,
175 pub epan: bool,
176 pub tcso0: bool,
177 pub tcso: bool,
178 pub en_tp2: bool,
179 pub nmi: bool,
180 pub spintmask: bool,
181 pub tidcp: bool,
182}
183
184open_enum! {
185 pub enum ExceptionClass: u8 {
186 UNKNOWN = 0b000000,
187 WFI = 0b000001,
188 MCR_MRC_COPROC_15 = 0b000011,
189 MCRR_MRRC_COPROC_15 = 0b000100,
190 MCR_MRC_COPROC_14 = 0b000101,
191 LDC_STC = 0b000110,
192 FP_OR_SIMD = 0b000111,
193 VMRS = 0b001000,
194 POINTER_AUTH_HCR_OR_SCR = 0b001001,
195 LS64 = 0b001010,
196 MRRC_COPROC_14 = 0b001100,
197 BRANCH_TARGET = 0b001101,
198 ILLEGAL_STATE = 0b001110,
199 SVC32 = 0b010001,
200 HVC32 = 0b010010,
201 SMC32 = 0b010011,
202 SVC = 0b010101,
203 HVC = 0b010110,
204 SMC = 0b010111,
205 SYSTEM = 0b011000,
206 SVE = 0b011001,
207 ERET = 0b011010,
208 TSTART = 0b011011,
209 POINTER_AUTH = 0b011100,
210 SME = 0b011101,
211 INSTRUCTION_ABORT_LOWER = 0b100000,
212 INSTRUCTION_ABORT = 0b100001,
213 PC_ALIGNMENT = 0b100010,
214 DATA_ABORT_LOWER = 0b100100,
215 DATA_ABORT = 0b100101,
216 SP_ALIGNMENT_FAULT = 0b100110,
217 MEMORY_OP = 0b100111,
218 FP_EXCEPTION_32 = 0b101000,
219 FP_EXCEPTION_64 = 0b101100,
220 SERROR = 0b101111,
221 BREAKPOINT_LOWER = 0b110000,
222 BREAKPOINT = 0b110001,
223 STEP_LOWER = 0b110010,
224 STEP = 0b110011,
225 WATCHPOINT_LOWER = 0b110100,
226 WATCHPOINT = 0b110101,
227 BRK32 = 0b111000,
228 VECTOR_CATCH_32 = 0b111010,
229 BRK = 0b111100,
230 }
231}
232
233#[bitfield(u32)]
234pub struct IssDataAbort {
235 #[bits(6)]
236 pub dfsc: FaultStatusCode,
237 pub wnr: bool,
239 pub s1ptw: bool,
240 pub cm: bool,
241 pub ea: bool,
242 pub fnv: bool,
244 #[bits(2)]
245 pub set: u8,
246 pub vncr: bool,
247 pub ar: bool,
249 pub sf: bool,
251 #[bits(5)]
252 pub srt: u8,
254 pub sse: bool,
256 #[bits(2)]
257 pub sas: u8,
259 pub isv: bool,
261 #[bits(7)]
262 _unused: u8,
263}
264
265impl From<IssDataAbort> for EsrEl2 {
266 fn from(abort_code: IssDataAbort) -> Self {
267 let val: u32 = abort_code.into();
268 let iss = val & 0x07ff_ffff;
269 EsrEl2::new()
270 .with_ec(ExceptionClass::DATA_ABORT.0)
271 .with_lower_iss((iss & 0x3f) as u8)
272 .with_wnr(((iss >> 6) & 1) != 0)
273 .with_mid_iss(((iss >> 7) & 0x1ff) as u16)
274 .with_b_srt(((iss >> 16) & 0x1F) as u8)
275 .with_a(((iss >> 21) & 0x1) != 0)
276 .with_b(((iss >> 22) & 0x1) != 0)
277 .with_c(((iss >> 23) & 0x1) != 0)
278 .with_d(((iss >> 24) & 0x1) != 0)
279 .with_iss2((val >> 27) as u8)
280 }
281}
282
283open_enum! {
284 pub enum FaultStatusCode: u8 {
285 ADDRESS_SIZE_FAULT_LEVEL0 = 0b000000,
286 ADDRESS_SIZE_FAULT_LEVEL1 = 0b000001,
287 ADDRESS_SIZE_FAULT_LEVEL2 = 0b000010,
288 ADDRESS_SIZE_FAULT_LEVEL3 = 0b000011,
289 TRANSLATION_FAULT_LEVEL0 = 0b000100,
290 TRANSLATION_FAULT_LEVEL1 = 0b000101,
291 TRANSLATION_FAULT_LEVEL2 = 0b000110,
292 TRANSLATION_FAULT_LEVEL3 = 0b000111,
293 ACCESS_FLAG_FAULT_LEVEL0 = 0b001000,
294 ACCESS_FLAG_FAULT_LEVEL1 = 0b001001,
295 ACCESS_FLAG_FAULT_LEVEL2 = 0b001010,
296 ACCESS_FLAG_FAULT_LEVEL3 = 0b001011,
297 PERMISSION_FAULT_LEVEL0 = 0b001100,
298 PERMISSION_FAULT_LEVEL1 = 0b001101,
299 PERMISSION_FAULT_LEVEL2 = 0b001110,
300 PERMISSION_FAULT_LEVEL3 = 0b001111,
301 SYNCHRONOUS_EXTERNAL_ABORT = 0b010000,
302 SYNC_TAG_CHECK_FAULT = 0b010001,
303 SEA_TTW_LEVEL_NEG1 = 0b010011,
304 SEA_TTW_LEVEL0 = 0b010100,
305 SEA_TTW_LEVEL1 = 0b010101,
306 SEA_TTW_LEVEL2 = 0b010110,
307 SEA_TTW_LEVEL3 = 0b010111,
308 ECC_PARITY = 0b011000,
309 ECC_PARITY_TTW_LEVEL_NEG1 = 0b011011,
310 ECC_PARITY_TTW_LEVEL0 = 0b011100,
311 ECC_PARITY_TTW_LEVEL1 = 0b011101,
312 ECC_PARITY_TTW_LEVEL2 = 0b011110,
313 ECC_PARITY_TTW_LEVEL3 = 0b011111,
314 ALIGNMENT_FAULT = 0b100001,
316 GRANULE_PROTECTION_FAULT_LEVEL_NEG = 0b100011,
318 GRANULE_PROTECTION_FAULT_LEVEL0 = 0b100100,
320 GRANULE_PROTECTION_FAULT_LEVEL1 = 0b100101,
322 GRANULE_PROTECTION_FAULT_LEVEL2 = 0b100110,
324 GRANULE_PROTECTION_FAULT_LEVE3 = 0b100111,
326 ADDRESS_SIZE_FAULT_LEVEL_NEG1 = 0b101001,
327 TRANSLATION_FAULT_LEVEL_NEG1 = 0b101011,
328 TLB_CONFLICT_ABORT = 0b110000,
329 UNSUPPORTED_HW_UPDATE_FAULT = 0b110001,
330 }
331}
332
333impl FaultStatusCode {
335 const fn from_bits(bits: u32) -> Self {
336 FaultStatusCode((bits & 0x3f) as u8)
337 }
338
339 const fn into_bits(self) -> u32 {
340 self.0 as u32
341 }
342}
343
344#[bitfield(u32)]
345pub struct IssInstructionAbort {
346 #[bits(6)]
347 pub ifsc: FaultStatusCode,
348 #[bits(1)]
349 _rsvd: u8,
350 pub s1ptw: bool,
352 #[bits(1)]
353 _rsvd2: u8,
354 pub ea: bool,
356 pub fnv: bool,
358 #[bits(2)]
359 pub set: SynchronousErrorType,
360 #[bits(11)]
361 _rsvd3: u16,
362 #[bits(8)]
363 _unused: u8,
364}
365
366impl From<IssInstructionAbort> for EsrEl2 {
367 fn from(instruction_code: IssInstructionAbort) -> Self {
368 let val: u32 = instruction_code.into();
369 let iss = val & 0x07ff_ffff;
370
371 EsrEl2::new()
372 .with_ec(ExceptionClass::INSTRUCTION_ABORT.0)
373 .with_lower_iss((iss & 0x3f) as u8)
374 .with_wnr(((iss >> 6) & 1) != 0)
375 .with_mid_iss(((iss >> 7) & 0x1ff) as u16)
376 .with_b_srt(((iss >> 16) & 0x1F) as u8)
377 .with_a(((iss >> 21) & 0x1) != 0)
378 .with_b(((iss >> 22) & 0x1) != 0)
379 .with_c(((iss >> 23) & 0x1) != 0)
380 .with_d(((iss >> 24) & 0x1) != 0)
381 .with_iss2((val >> 27) as u8)
382 }
383}
384
385open_enum! {
386 pub enum SynchronousErrorType: u8 {
387 RECOVERABLE = 0,
388 UNCONTAINABLE = 2,
389 RESTARTABLE = 3,
390 }
391}
392
393impl SynchronousErrorType {
395 const fn from_bits(bits: u32) -> Self {
396 SynchronousErrorType((bits & 0x1800) as u8)
397 }
398
399 const fn into_bits(self) -> u32 {
400 (self.0 as u32) << 11
401 }
402}
403
404#[bitfield(u32)]
405pub struct IssSystem {
406 pub direction: bool,
407 #[bits(4)]
408 pub crm: u8,
409 #[bits(5)]
410 pub rt: u8,
411 #[bits(4)]
412 pub crn: u8,
413 #[bits(3)]
414 pub op1: u8,
415 #[bits(3)]
416 pub op2: u8,
417 #[bits(2)]
418 pub op0: u8,
419 #[bits(10)]
420 _unused: u32,
421}
422
423impl IssSystem {
424 pub const fn system_reg(&self) -> SystemReg {
425 SystemReg(
426 SystemRegEncoding::new()
427 .with_op0(self.op0())
428 .with_op1(self.op1())
429 .with_crn(self.crn())
430 .with_crm(self.crm())
431 .with_op2(self.op2()),
432 )
433 }
434}
435
436#[bitfield(u32)]
437#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
438pub struct SystemRegEncoding {
439 #[bits(5)]
440 _rsvd: u32,
441 #[bits(3)]
442 pub op2: u8,
443 #[bits(4)]
444 pub crm: u8,
445 #[bits(4)]
446 pub crn: u8,
447 #[bits(3)]
448 pub op1: u8,
449 #[bits(2)]
450 pub op0: u8,
451 #[bits(11)]
452 _rsvd2: u32,
453}
454
455open_enum! {
456 pub enum SystemReg: SystemRegEncoding {
457 SPSR_EL1 = SystemRegEncoding::make(3, 0, 4, 0, 0),
458 SPSR_EL2 = SystemRegEncoding::make(3, 4, 4, 0, 0),
459 SPSR_EL3 = SystemRegEncoding::make(3, 6, 4, 0, 0),
460 ELR_EL1 = SystemRegEncoding::make(3, 0, 4, 0, 1),
461 ELR_EL2 = SystemRegEncoding::make(3, 4, 4, 0, 1),
462 ELR_EL3 = SystemRegEncoding::make(3, 6, 4, 0, 1),
463 SP_EL0 = SystemRegEncoding::make(3, 0, 4, 1, 0),
464 SP_EL1 = SystemRegEncoding::make(3, 4, 4, 1, 0),
465 SP_EL2 = SystemRegEncoding::make(3, 6, 4, 1, 0),
466 FPSR = SystemRegEncoding::make(3, 3, 4, 4, 1),
467 FPCR = SystemRegEncoding::make(3, 3, 4, 4, 0),
468 SPSR_ABT = SystemRegEncoding::make(3, 4, 4, 3, 1),
469 IFSR32_EL2 = SystemRegEncoding::make(3, 4, 5, 0, 1),
470
471 VPIDR_EL2 = SystemRegEncoding::make(3, 4, 0, 0, 0),
472 ARM64_REVIDR_EL1 = SystemRegEncoding::make(3, 0, 0, 0, 6),
473 CTR_EL0 = SystemRegEncoding::make(3, 3, 0, 0, 1),
474 ARM64_VMPIDR_EL2 = SystemRegEncoding::make(3, 4, 0, 0, 5),
475 ID_AA64PFR0_EL1 = SystemRegEncoding::make(3, 0, 0, 4, 0),
476 ID_AA64PFR1_EL1 = SystemRegEncoding::make(3, 0, 0, 4, 1),
477 ID_AA64DFR0_EL1 = SystemRegEncoding::make(3, 0, 0, 5, 0),
478 ID_AA64DFR1_EL1 = SystemRegEncoding::make(3, 0, 0, 5, 1),
479 ID_AA64AFR0_EL1 = SystemRegEncoding::make(3, 0, 0, 5, 4),
480 ID_AA64AFR1_EL1 = SystemRegEncoding::make(3, 0, 0, 5, 5),
481 ID_AA64ISAR0_EL1 = SystemRegEncoding::make(3, 0, 0, 6, 0),
482 ID_AA64ISAR1_EL1 = SystemRegEncoding::make(3, 0, 0, 6, 1),
483 ID_AA64MMFR0_EL1 = SystemRegEncoding::make(3, 0, 0, 7, 0),
484 ID_AA64MMFR1_EL1 = SystemRegEncoding::make(3, 0, 0, 7, 1),
485 ID_AA64MMFR2_EL1 = SystemRegEncoding::make(3, 0, 0, 7, 2),
486
487 ID_MMFR0 = SystemRegEncoding::make(3, 0, 0, 1, 4),
488 ID_MMFR1 = SystemRegEncoding::make(3, 0, 0, 1, 5),
489 ID_MMFR2 = SystemRegEncoding::make(3, 0, 0, 1, 6),
490 ID_MMFR3 = SystemRegEncoding::make(3, 0, 0, 1, 7),
491 ID_MMFR4 = SystemRegEncoding::make(3, 0, 0, 2, 6),
492 ID_ISAR0 = SystemRegEncoding::make(3, 0, 0, 2, 0),
493 ID_ISAR1 = SystemRegEncoding::make(3, 0, 0, 2, 1),
494 ID_ISAR2 = SystemRegEncoding::make(3, 0, 0, 2, 2),
495 ID_ISAR3 = SystemRegEncoding::make(3, 0, 0, 2, 3),
496 ID_ISAR4 = SystemRegEncoding::make(3, 0, 0, 2, 4),
497 ID_ISAR5 = SystemRegEncoding::make(3, 0, 0, 2, 5),
498 ID_ISAR6 = SystemRegEncoding::make(3, 0, 0, 2, 7),
499 MVFR0_EL1 = SystemRegEncoding::make(3, 0, 0, 3, 0),
500 MVFR1_EL1 = SystemRegEncoding::make(3, 3, 0, 0, 1),
501 MVFR2_EL1 = SystemRegEncoding::make(3, 3, 0, 0, 2),
502 ID_AA64ZFR0_EL1 = SystemRegEncoding::make(3, 0, 0, 4, 4),
503 DACR32_EL2 = SystemRegEncoding::make(3, 4, 3, 0, 0),
504 FPEXC32_EL2 = SystemRegEncoding::make(3, 4, 5, 3, 0),
505 VMPIDR_EL2 = SystemRegEncoding::make(3, 4, 0, 0, 5),
506
507 SCTLR = SystemRegEncoding::make(3, 0, 1, 0, 0),
508 SCTLR_EL2 = SystemRegEncoding::make(3, 4, 1, 0, 0),
509 HCR_EL2 = SystemRegEncoding::make(3, 4, 1, 1, 0),
510 HSTR_EL2 = SystemRegEncoding::make(3, 4, 1, 1, 3),
511 HACR_EL2 = SystemRegEncoding::make(3, 4, 1, 1, 7),
512 ACTLR_EL1 = SystemRegEncoding::make(3, 0, 1, 0, 1),
513 ACTLR_EL2 = SystemRegEncoding::make(3, 4, 1, 0, 1),
514 CPACR = SystemRegEncoding::make(3, 0, 1, 0, 2),
515 CPTR_EL2 = SystemRegEncoding::make(3, 4, 1, 1, 2),
516 CPUECTLR_EL1 = SystemRegEncoding::make(3, 0, 15, 1, 4),
517 CNTPS_CTL_EL1 = SystemRegEncoding::make(3, 7, 14, 2, 1),
518 CPUMERRSR_EL1 = SystemRegEncoding::make(3, 1, 15, 2, 2),
519 CNTPS_CVAL_EL1 = SystemRegEncoding::make(3, 7, 14, 2, 2),
520 L2MERRSR_EL1 = SystemRegEncoding::make(3, 1, 15, 2, 3),
521
522 TTBR0_EL1 = SystemRegEncoding::make(3, 0, 2, 0, 0),
523 TTBR0_EL2 = SystemRegEncoding::make(3, 4, 2, 0, 0),
524 TTBR1_EL1 = SystemRegEncoding::make(3, 0, 2, 0, 1),
525 VTTBR_EL2 = SystemRegEncoding::make(3, 4, 2, 1, 0),
526 TCR_EL1 = SystemRegEncoding::make(3, 0, 2, 0, 2),
527 TCR_EL2 = SystemRegEncoding::make(3, 4, 2, 0, 2),
528 VTCR_EL2 = SystemRegEncoding::make(3, 4, 2, 1, 2),
529 ESR_EL1 = SystemRegEncoding::make(3, 0, 5, 2, 0),
530 ESR_EL2 = SystemRegEncoding::make(3, 4, 5, 2, 0),
531 ESR_EL3 = SystemRegEncoding::make(3, 6, 5, 2, 0),
532 FAR_EL1 = SystemRegEncoding::make(3, 0, 6, 0, 0),
533 FAR_EL2 = SystemRegEncoding::make(3, 4, 6, 0, 0),
534 HPFAR_EL2 = SystemRegEncoding::make(3, 4, 6, 0, 4),
535 AFSR0_EL1 = SystemRegEncoding::make(3, 0, 5, 1, 0),
536 AFSR0_EL2 = SystemRegEncoding::make(3, 4, 5, 1, 0),
537 AFSR1_EL1 = SystemRegEncoding::make(3, 0, 5, 1, 1),
538 AFSR1_EL2 = SystemRegEncoding::make(3, 4, 5, 1, 1),
539
540 PAR_EL1 = SystemRegEncoding::make(3, 0, 7, 4, 0),
541 CNTFRQ_EL0 = SystemRegEncoding::make(3, 3, 14, 0, 0),
542 CNTP_CTL_EL0 = SystemRegEncoding::make(3, 3, 14, 2, 1),
543 CNTP_CVAL_EL0 = SystemRegEncoding::make(3, 3, 14, 2, 2),
544 CNTV_CTL_EL0 = SystemRegEncoding::make(3, 3, 14, 3, 1),
545 CNTV_CVAL_EL0 = SystemRegEncoding::make(3, 3, 14, 3, 2),
546 CNTHCTL_EL2 = SystemRegEncoding::make(3, 4, 14, 1, 0),
547 CNTHP_CTL_EL2 = SystemRegEncoding::make(3, 4, 14, 2, 1),
548 CNTHP_CVAL_EL2 = SystemRegEncoding::make(3, 4, 14, 2, 2),
549 PMCCFILTR_EL0 = SystemRegEncoding::make(3, 3, 14, 15, 7),
550 MDCR_EL2 = SystemRegEncoding::make(3, 4, 1, 1, 1),
551 PMCR_EL0 = SystemRegEncoding::make(3, 3, 9, 12, 0),
552 PMCNTENSET_EL0 = SystemRegEncoding::make(3, 3, 9, 12, 1),
553 PMCNTENCLR_EL0 = SystemRegEncoding::make(3, 3, 9, 12, 2),
554 PMOVSSET_EL0 = SystemRegEncoding::make(3, 3, 9, 14, 3),
555 PMOVSCLR_EL0 = SystemRegEncoding::make(3, 3, 9, 12, 3),
556 PMSELR_EL0 = SystemRegEncoding::make(3, 3, 9, 12, 5),
557 PMCEID0_EL0 = SystemRegEncoding::make(3, 3, 9, 12, 6),
558 PMCEID1_EL0 = SystemRegEncoding::make(3, 3, 9, 12, 7),
559 PMCCNTR_EL0 = SystemRegEncoding::make(3, 3, 9, 13, 0),
560 PMUSERENR_EL0 = SystemRegEncoding::make(3, 3, 9, 14, 0),
561 PMINTENSET_EL1 = SystemRegEncoding::make(3, 0, 9, 14, 1),
562 PMINTENCLR_EL1 = SystemRegEncoding::make(3, 0, 9, 14, 2),
563
564 MAIR_EL1 = SystemRegEncoding::make(3, 0, 10, 2, 0),
565 AMAIR0 = SystemRegEncoding::make(3, 0, 10, 3, 0),
566 MAIR_EL2 = SystemRegEncoding::make(3, 4, 10, 2, 0),
567 AMAIR_EL2 = SystemRegEncoding::make(3, 4, 10, 3, 0),
568 MAIR_EL3 = SystemRegEncoding::make(3, 6, 10, 2, 0),
569
570 VBAR = SystemRegEncoding::make(3, 0, 12, 0, 0),
571 VBAR_EL2 = SystemRegEncoding::make(3, 4, 12, 0, 0),
572 RVBAR_EL2 = SystemRegEncoding::make(3, 4, 12, 0, 1),
573
574 TPIDR_EL0 = SystemRegEncoding::make(3, 3, 13, 0, 2),
575 TPIDRRO_EL0 = SystemRegEncoding::make(3, 3, 13, 0, 3),
576 TPIDR_EL1 = SystemRegEncoding::make(3, 0, 13, 0, 4),
577 TPIDR_EL2 = SystemRegEncoding::make(3, 4, 13, 0, 2),
578 CONTEXTIDR_EL1 = SystemRegEncoding::make(3, 0, 13, 0, 1),
579
580 CLIDR = SystemRegEncoding::make(3, 1, 0, 0, 1),
581 AIDR = SystemRegEncoding::make(3, 1, 0, 0, 7),
582 CSSELR = SystemRegEncoding::make(3, 2, 0, 0, 0),
583
584 CNTKCTL = SystemRegEncoding::make(3, 0, 14, 1, 0),
585 CNTVOFF_EL2 = SystemRegEncoding::make(3, 4, 14, 0, 3),
586
587 MDCCSR_EL0 = SystemRegEncoding::make(2, 3, 0, 1, 0),
588 MDSCR_EL1 = SystemRegEncoding::make(2, 0, 0, 2, 2),
589 MDRAR_EL1 = SystemRegEncoding::make(2, 0, 1, 0, 0),
590 OSLSR_EL1 = SystemRegEncoding::make(2, 0, 1, 1, 4),
591 DBGBVR0 = SystemRegEncoding::make(2, 0, 0, 0, 4),
592 DBGBVR1 = SystemRegEncoding::make(2, 0, 0, 1, 4),
593 DBGBVR2 = SystemRegEncoding::make(2, 0, 0, 2, 4),
594 DBGBVR3 = SystemRegEncoding::make(2, 0, 0, 3, 4),
595 DBGBVR4 = SystemRegEncoding::make(2, 0, 0, 4, 4),
596 DBGBVR5 = SystemRegEncoding::make(2, 0, 0, 5, 4),
597 DBGBCR0 = SystemRegEncoding::make(2, 0, 0, 0, 5),
598 DBGBCR1 = SystemRegEncoding::make(2, 0, 0, 1, 5),
599 DBGBCR2 = SystemRegEncoding::make(2, 0, 0, 2, 5),
600 DBGBCR3 = SystemRegEncoding::make(2, 0, 0, 3, 5),
601 DBGBCR4 = SystemRegEncoding::make(2, 0, 0, 4, 5),
602 DBGBCR5 = SystemRegEncoding::make(2, 0, 0, 5, 5),
603 DBGWVR0 = SystemRegEncoding::make(2, 0, 0, 0, 6),
604 DBGWVR1 = SystemRegEncoding::make(2, 0, 0, 1, 6),
605 DBGWVR2 = SystemRegEncoding::make(2, 0, 0, 2, 6),
606 DBGWVR3 = SystemRegEncoding::make(2, 0, 0, 3, 6),
607 DBGWCR0 = SystemRegEncoding::make(2, 0, 0, 0, 7),
608 DBGWCR1 = SystemRegEncoding::make(2, 0, 0, 1, 7),
609 DBGWCR2 = SystemRegEncoding::make(2, 0, 0, 2, 7),
610 DBGWCR3 = SystemRegEncoding::make(2, 0, 0, 3, 7),
611
612 ICC_AP0R0_EL1 = SystemRegEncoding::make(3, 0, 12, 8, 4),
613 ICC_AP0R1_EL1 = SystemRegEncoding::make(3, 0, 12, 8, 5),
614 ICC_AP0R2_EL1 = SystemRegEncoding::make(3, 0, 12, 8, 6),
615 ICC_AP0R3_EL1 = SystemRegEncoding::make(3, 0, 12, 8, 7),
616 ICC_AP1R0_EL1 = SystemRegEncoding::make(3, 0, 12, 9, 0),
617 ICC_AP1R1_EL1 = SystemRegEncoding::make(3, 0, 12, 9, 1),
618 ICC_AP1R2_EL1 = SystemRegEncoding::make(3, 0, 12, 9, 2),
619 ICC_AP1R3_EL1 = SystemRegEncoding::make(3, 0, 12, 9, 3),
620 ICC_ASGI1R_EL1 = SystemRegEncoding::make(3, 0, 12, 11, 6),
621 ICC_BPR0_EL1 = SystemRegEncoding::make(3, 0, 12, 8, 3),
622 ICC_BPR1_EL1 = SystemRegEncoding::make(3, 0, 12, 12, 3),
623 ICC_CTLR_EL1 = SystemRegEncoding::make(3, 0, 12, 12, 4),
624 ICC_CTLR_EL3 = SystemRegEncoding::make(3, 6, 12, 12, 4),
625 ICC_DIR_EL1 = SystemRegEncoding::make(3, 0, 12, 11, 1),
626 ICC_EOIR0_EL1 = SystemRegEncoding::make(3, 0, 12, 8, 1),
627 ICC_EOIR1_EL1 = SystemRegEncoding::make(3, 0, 12, 12, 1),
628 ICC_HPPIR0_EL1 = SystemRegEncoding::make(3, 0, 12, 8, 2),
629 ICC_HPPIR1_EL1 = SystemRegEncoding::make(3, 0, 12, 12, 2),
630 ICC_IAR0_EL1 = SystemRegEncoding::make(3, 0, 12, 8, 0),
631 ICC_IAR1_EL1 = SystemRegEncoding::make(3, 0, 12, 12, 0),
632 ICC_IGRPEN0_EL1 = SystemRegEncoding::make(3, 0, 12, 12, 6),
633 ICC_IGRPEN1_EL1 = SystemRegEncoding::make(3, 0, 12, 12, 7),
634 ICC_IGRPEN1_EL3 = SystemRegEncoding::make(3, 6, 12, 12, 7),
635 ICC_PMR_EL1 = SystemRegEncoding::make(3, 0, 4, 6, 0),
636 ICC_RPR_EL1 = SystemRegEncoding::make(3, 0, 12, 11, 3),
637 ICC_SGI0R_EL1 = SystemRegEncoding::make(3, 0, 12, 11, 7),
638 ICC_SGI1R_EL1 = SystemRegEncoding::make(3, 0, 12, 11, 5),
639 ICC_SRE_EL1 = SystemRegEncoding::make(3, 0, 12, 12, 5),
640 ICC_SRE_EL2 = SystemRegEncoding::make(3, 4, 12, 9, 5),
641 ICC_SRE_EL3 = SystemRegEncoding::make(3, 6, 12, 12, 5),
642 }
643}
644
645impl SystemRegEncoding {
646 pub const fn make(op0: u8, op1: u8, crn: u8, crm: u8, op2: u8) -> Self {
647 Self::new()
648 .with_op0(op0)
649 .with_op1(op1)
650 .with_crn(crn)
651 .with_crm(crm)
652 .with_op2(op2)
653 }
654}
655
656#[bitfield(u64)]
658pub struct MpidrEl1 {
659 pub aff0: u8,
660 pub aff1: u8,
661 pub aff2: u8,
662 pub mt: bool,
663 #[bits(5)]
664 pub res0_25_29: u8,
665 pub u: bool,
666 pub res1_31: bool,
667 pub aff3: u8,
668 #[bits(24)]
669 pub res0_40_63: u32,
670}
671
672impl MpidrEl1 {
673 pub const AFFINITY_MASK: Self = Self::new()
674 .with_aff0(0xff)
675 .with_aff1(0xff)
676 .with_aff2(0xff)
677 .with_aff3(0xff);
678}
679
680open_enum! {
681 pub enum TranslationGranule0: u64 {
683 TG_4KB = 0b00,
684 TG_64KB = 0b01,
685 TG_16KB = 0b10,
686 }
687}
688
689impl TranslationGranule0 {
690 const fn into_bits(self) -> u64 {
691 self.0
692 }
693
694 const fn from_bits(bits: u64) -> Self {
695 Self(bits)
696 }
697}
698
699open_enum! {
700 pub enum TranslationGranule1: u64 {
702 TG_INVALID = 0b00,
703 TG_16KB = 0b01,
704 TG_4KB = 0b10,
705 TG_64KB = 0b11,
706 }
707}
708
709impl TranslationGranule1 {
710 const fn into_bits(self) -> u64 {
711 self.0
712 }
713
714 const fn from_bits(bits: u64) -> Self {
715 Self(bits)
716 }
717}
718
719open_enum! {
720 pub enum IntermPhysAddrSize: u64{
722 IPA_32_BITS_4_GB = 0b000,
723 IPA_36_BITS_64_GB = 0b001,
724 IPA_40_BITS_1_TB = 0b010,
725 IPA_42_BITS_4_TB = 0b011,
726 IPA_44_BITS_16_TB = 0b100,
727 IPA_48_BITS_256_TB = 0b101,
728 IPA_52_BITS_4_PB = 0b110,
729 IPA_56_BITS_64_PB = 0b111,
730 }
731}
732
733impl IntermPhysAddrSize {
734 const fn into_bits(self) -> u64 {
735 self.0
736 }
737
738 const fn from_bits(bits: u64) -> Self {
739 Self(bits)
740 }
741}
742
743#[bitfield(u64)]
745#[derive(PartialEq, Eq)]
746pub struct TranslationControlEl1 {
747 #[bits(6)]
748 pub t0sz: u64,
749 #[bits(1)]
750 _mbz0: u64,
751 #[bits(1)]
752 pub epd0: u64,
753 #[bits(2)]
754 pub irgn0: u64,
755 #[bits(2)]
756 pub orgn0: u64,
757 #[bits(2)]
758 pub sh0: u64,
759 #[bits(2)]
760 pub tg0: TranslationGranule0,
761 #[bits(6)]
762 pub t1sz: u64,
763 #[bits(1)]
764 pub a1: u64,
765 #[bits(1)]
766 pub epd1: u64,
767 #[bits(2)]
768 pub irgn1: u64,
769 #[bits(2)]
770 pub orgn1: u64,
771 #[bits(2)]
772 pub sh1: u64,
773 #[bits(2)]
774 pub tg1: TranslationGranule1,
775 #[bits(3)]
776 pub ips: IntermPhysAddrSize,
777 #[bits(1)]
778 _mbz1: u64,
779 #[bits(1)]
780 pub a_s: u64,
781 #[bits(1)]
782 pub tbi0: u64,
783 #[bits(1)]
784 pub tbi1: u64,
785 #[bits(1)]
786 pub ha: u64,
787 #[bits(1)]
788 pub hd: u64,
789 #[bits(1)]
790 pub hpd0: u64,
791 #[bits(1)]
792 pub hpd1: u64,
793 #[bits(1)]
794 pub hwu059: u64,
795 #[bits(1)]
796 pub hwu060: u64,
797 #[bits(1)]
798 pub hwu061: u64,
799 #[bits(1)]
800 pub hwu062: u64,
801 #[bits(1)]
802 pub hwu159: u64,
803 #[bits(1)]
804 pub hwu160: u64,
805 #[bits(1)]
806 pub hwu161: u64,
807 #[bits(1)]
808 pub hwu162: u64,
809 #[bits(1)]
810 pub tbid0: u64,
811 #[bits(1)]
812 pub tbid1: u64,
813 #[bits(1)]
814 pub nfd0: u64,
815 #[bits(1)]
816 pub nfd1: u64,
817 #[bits(1)]
818 pub e0pd0: u64,
819 #[bits(1)]
820 pub e0pd1: u64,
821 #[bits(1)]
822 pub tcma0: u64,
823 #[bits(1)]
824 pub tcma1: u64,
825 #[bits(1)]
826 pub ds: u64,
827 #[bits(1)]
828 pub mtx0: u64,
829 #[bits(1)]
830 pub mtx1: u64,
831 #[bits(2)]
832 _mbz2: u64,
833}
834
835impl TranslationControlEl1 {
836 pub fn ttbr0_valid_address_bits(&self) -> u64 {
837 64 - self.t0sz()
838 }
839
840 pub fn ttbr1_valid_address_bits(&self) -> u64 {
841 64 - self.t1sz()
842 }
843}
844
845#[bitfield(u64)]
847#[derive(PartialEq, Eq)]
848pub struct TranslationBaseEl1 {
849 #[bits(48)]
853 pub baddr: u64,
854 #[bits(16)]
855 pub asid: u64,
856}
857
858#[bitfield(u64)]
859#[derive(PartialEq, Eq, IntoBytes, Immutable, KnownLayout, FromBytes)]
860pub struct Pte {
861 pub valid: bool,
862 pub not_large_page: bool,
863 #[bits(3)]
864 pub attribute_index: u64,
865 pub non_secure: bool,
866 pub ap_unprivileged: bool,
867 pub ap_read_only: bool,
868 #[bits(2)]
869 pub shareability: u64,
870 pub access_flag: bool,
871 pub not_global: bool,
872 #[bits(36)]
873 pub pfn: u64,
874 #[bits(3)]
875 pub reserved_must_be_zero: u64,
876 pub dbm: bool,
877 pub contiguous_hint: bool,
878 pub privilege_no_execute: bool,
879 pub user_no_execute: bool,
880 #[bits(4)]
881 pub _reserved2: u64,
882 pub pxn_table: bool,
883 pub uxn_table: bool,
884 pub ap_table_privileged_only: bool,
885 pub ap_table_read_only: bool,
886 pub ns_table: bool,
887}
888
889#[bitfield(u64)]
891pub struct MmFeatures0El1 {
892 #[bits(4)]
893 pub pa_range: IntermPhysAddrSize,
894 #[bits(60)]
895 _rest: u64,
896}
897
898pub const GIC_DISTRIBUTOR_SIZE: u64 = 0x1_0000;
899pub const GIC_REDISTRIBUTOR_FRAME_SIZE: u64 = 0x1_0000;
900pub const GIC_SGI_FRAME_SIZE: u64 = 0x1_0000;
901pub const GIC_REDISTRIBUTOR_SIZE: u64 = GIC_REDISTRIBUTOR_FRAME_SIZE + GIC_SGI_FRAME_SIZE;
902
903pub const GIC_V2_DISTRIBUTOR_SIZE: u64 = 0x1000;
905pub const GIC_V2_CPU_INTERFACE_SIZE: u64 = 0x2000;
906
907open_enum! {
908 pub enum SystemReset2Code: u32 {
909 WARM_RESET = 0,
910 }
911}
912
913open_enum! {
914 pub enum SystemOff2Code: u32 {
915 DEFAULT = 0,
916 HIBERNATE_OFF = 1,
917 }
918}
919
920#[derive(Debug, PartialEq, Eq, Copy, Clone)]
921pub struct Vendor(pub u32);
922
923impl Vendor {
924 pub const ARM: Self = Self(0x0010);
925
926 pub fn is_arm_compatible(&self) -> bool {
927 *self == Self::ARM
928 }
929
930 pub fn is_intel_compatible(&self) -> bool {
933 false
934 }
935
936 pub fn is_amd_compatible(&self) -> bool {
938 false
939 }
940}
941
942impl Display for Vendor {
943 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
944 if self.is_arm_compatible() {
945 f.pad("Arm")
946 } else {
947 write!(f, "{:#x}", self.0)
948 }
949 }
950}