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