Skip to main content

aarch64defs/
lib.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! ARM64 type and constant definitions.
5
6#![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/// Aarch64 SPSR_EL2 register when in 64-bit mode. Usually called CPSR by
23/// hypervisors.
24#[bitfield(u64)]
25pub struct Cpsr64 {
26    /// PSTATE.SP
27    pub sp: bool,
28    _rsvd0: bool,
29    /// Exception Level
30    #[bits(2)]
31    pub el: u8,
32    /// Aarch32 mode. If set, this struct is the wrong one to interpret this
33    /// register.
34    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/// ESR_EL2, exception syndrome register.
61#[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        // The WNR bit is set for writes, not reads.
87        self.wnr()
88    }
89
90    pub fn is_read(&self) -> bool {
91        // The WNR bit is set for writes, not reads.
92        !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        // The SRT field is only valid for data aborts.
108        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/// aarch64 SCTRL_EL1
117#[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    // Write operation (write not read)
238    pub wnr: bool,
239    pub s1ptw: bool,
240    pub cm: bool,
241    pub ea: bool,
242    /// FAR not valid
243    pub fnv: bool,
244    #[bits(2)]
245    pub set: u8,
246    pub vncr: bool,
247    /// Acquire/release
248    pub ar: bool,
249    /// (ISV==1) 64-bit, (ISV==0) FAR is approximate
250    pub sf: bool,
251    #[bits(5)]
252    /// Register index.
253    pub srt: u8,
254    /// Sign extended.
255    pub sse: bool,
256    #[bits(2)]
257    /// access width log2
258    pub sas: u8,
259    /// Valid ESREL2 iss field.
260    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        /// Valid only for data fault.
315        ALIGNMENT_FAULT = 0b100001,
316        /// Valid only for instruction fault.
317        GRANULE_PROTECTION_FAULT_LEVEL_NEG = 0b100011,
318        /// Valid only for instruction fault.
319        GRANULE_PROTECTION_FAULT_LEVEL0 = 0b100100,
320        /// Valid only for instruction fault.
321        GRANULE_PROTECTION_FAULT_LEVEL1 = 0b100101,
322        /// Valid only for instruction fault.
323        GRANULE_PROTECTION_FAULT_LEVEL2 = 0b100110,
324        /// Valid only for instruction fault.
325        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
333/// Support for embedding within IssDataAbort/IssInstructionAbort
334impl 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    /// Stage 2 translation fault
351    pub s1ptw: bool,
352    #[bits(1)]
353    _rsvd2: u8,
354    /// External abort
355    pub ea: bool,
356    /// FAR not valid
357    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
393/// Support for embedding within IssInstructionAbort
394impl 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/// MPIDR_EL1
657#[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    /// aarch64 translation granule size for TTBR0_EL1
682    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    /// aarch64 translation granule size for TTBR1_EL1
701    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    /// aarch64 intermediate physical address size
721    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/// aarch64 TCR_EL1 register
744#[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/// aarch64 TTBRx_EL1 content
846#[bitfield(u64)]
847#[derive(PartialEq, Eq)]
848pub struct TranslationBaseEl1 {
849    // Hardcoding CnP to be `0` for simplicity.
850    // #[bits(1)]
851    // pub cnp: u64,
852    #[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/// The contents of ID_MMFR0_EL1
890#[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
903// GICv2 sizes.
904pub 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    // Intel and Amd compatible checkers are still implemented and return false.
931    // By this, some generic code do NOT diverge on AArch64.
932    pub fn is_intel_compatible(&self) -> bool {
933        false
934    }
935
936    // Likewise
937    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}