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_AA64PFR0_EL1 = SystemRegEncoding::make(3, 0, 0, 4, 0),
416        ID_AA64PFR1_EL1 = SystemRegEncoding::make(3, 0, 0, 4, 1),
417        ID_AA64DFR0_EL1 = SystemRegEncoding::make(3, 0, 0, 5, 0),
418        ID_AA64DFR1_EL1 = SystemRegEncoding::make(3, 0, 0, 5, 1),
419        ID_AA64AFR0_EL1 = SystemRegEncoding::make(3, 0, 0, 5, 4),
420        ID_AA64AFR1_EL1 = SystemRegEncoding::make(3, 0, 0, 5, 5),
421        ID_AA64ISAR0_EL1 = SystemRegEncoding::make(3, 0, 0, 6, 0),
422        ID_AA64ISAR1_EL1 = SystemRegEncoding::make(3, 0, 0, 6, 1),
423        ID_AA64MMFR0_EL1 = SystemRegEncoding::make(3, 0, 0, 7, 0),
424        ID_AA64MMFR1_EL1 = SystemRegEncoding::make(3, 0, 0, 7, 1),
425        ID_AA64MMFR2_EL1 = SystemRegEncoding::make(3, 0, 0, 7, 2),
426
427        ID_MMFR0 = SystemRegEncoding::make(3, 0, 0, 1, 4),
428        ID_MMFR1 = SystemRegEncoding::make(3, 0, 0, 1, 5),
429        ID_MMFR2 = SystemRegEncoding::make(3, 0, 0, 1, 6),
430        ID_MMFR3 = SystemRegEncoding::make(3, 0, 0, 1, 7),
431        ID_MMFR4 = SystemRegEncoding::make(3, 0, 0, 2, 6),
432        ID_ISAR0 = SystemRegEncoding::make(3, 0, 0, 2, 0),
433        ID_ISAR1 = SystemRegEncoding::make(3, 0, 0, 2, 1),
434        ID_ISAR2 = SystemRegEncoding::make(3, 0, 0, 2, 2),
435        ID_ISAR3 = SystemRegEncoding::make(3, 0, 0, 2, 3),
436        ID_ISAR4 = SystemRegEncoding::make(3, 0, 0, 2, 4),
437        ID_ISAR5 = SystemRegEncoding::make(3, 0, 0, 2, 5),
438        ID_ISAR6 = SystemRegEncoding::make(3, 0, 0, 2, 7),
439        MVFR0_EL1 = SystemRegEncoding::make(3, 0, 0, 3, 0),
440        MVFR1_EL1 = SystemRegEncoding::make(3, 3, 0, 0, 1),
441        MVFR2_EL1 = SystemRegEncoding::make(3, 3, 0, 0, 2),
442        ID_AA64ZFR0_EL1 = SystemRegEncoding::make(3, 0, 0, 4, 4),
443        DACR32_EL2 = SystemRegEncoding::make(3, 4, 3, 0, 0),
444        FPEXC32_EL2 = SystemRegEncoding::make(3, 4, 5, 3, 0),
445        VMPIDR_EL2 = SystemRegEncoding::make(3, 4, 0, 0, 5),
446
447        SCTLR = SystemRegEncoding::make(3, 0, 1, 0, 0),
448        SCTLR_EL2 = SystemRegEncoding::make(3, 4, 1, 0, 0),
449        HCR_EL2 = SystemRegEncoding::make(3, 4, 1, 1, 0),
450        HSTR_EL2 = SystemRegEncoding::make(3, 4, 1, 1, 3),
451        HACR_EL2 = SystemRegEncoding::make(3, 4, 1, 1, 7),
452        ACTLR_EL1 = SystemRegEncoding::make(3, 0, 1, 0, 1),
453        ACTLR_EL2 = SystemRegEncoding::make(3, 4, 1, 0, 1),
454        CPACR = SystemRegEncoding::make(3, 0, 1, 0, 2),
455        CPTR_EL2 = SystemRegEncoding::make(3, 4, 1, 1, 2),
456        CPUECTLR_EL1 = SystemRegEncoding::make(3, 0, 15, 1, 4),
457        CNTPS_CTL_EL1 = SystemRegEncoding::make(3, 7, 14, 2, 1),
458        CPUMERRSR_EL1 = SystemRegEncoding::make(3, 1, 15, 2, 2),
459        CNTPS_CVAL_EL1 = SystemRegEncoding::make(3, 7, 14, 2, 2),
460        L2MERRSR_EL1 = SystemRegEncoding::make(3, 1, 15, 2, 3),
461
462        TTBR0_EL1 = SystemRegEncoding::make(3, 0, 2, 0, 0),
463        TTBR0_EL2 = SystemRegEncoding::make(3, 4, 2, 0, 0),
464        TTBR1_EL1 = SystemRegEncoding::make(3, 0, 2, 0, 1),
465        VTTBR_EL2 = SystemRegEncoding::make(3, 4, 2, 1, 0),
466        TCR_EL1 = SystemRegEncoding::make(3, 0, 2, 0, 2),
467        TCR_EL2 = SystemRegEncoding::make(3, 4, 2, 0, 2),
468        VTCR_EL2 = SystemRegEncoding::make(3, 4, 2, 1, 2),
469        ESR_EL1 = SystemRegEncoding::make(3, 0, 5, 2, 0),
470        ESR_EL2 = SystemRegEncoding::make(3, 4, 5, 2, 0),
471        ESR_EL3 = SystemRegEncoding::make(3, 6, 5, 2, 0),
472        FAR_EL1 = SystemRegEncoding::make(3, 0, 6, 0, 0),
473        FAR_EL2 = SystemRegEncoding::make(3, 4, 6, 0, 0),
474        HPFAR_EL2 = SystemRegEncoding::make(3, 4, 6, 0, 4),
475        AFSR0_EL1 = SystemRegEncoding::make(3, 0, 5, 1, 0),
476        AFSR0_EL2 = SystemRegEncoding::make(3, 4, 5, 1, 0),
477        AFSR1_EL1 = SystemRegEncoding::make(3, 0, 5, 1, 1),
478        AFSR1_EL2 = SystemRegEncoding::make(3, 4, 5, 1, 1),
479
480        PAR_EL1 = SystemRegEncoding::make(3, 0, 7, 4, 0),
481        CNTFRQ_EL0 = SystemRegEncoding::make(3, 3, 14, 0, 0),
482        CNTP_CTL_EL0 = SystemRegEncoding::make(3, 3, 14, 2, 1),
483        CNTP_CVAL_EL0 = SystemRegEncoding::make(3, 3, 14, 2, 2),
484        CNTV_CTL_EL0 = SystemRegEncoding::make(3, 3, 14, 3, 1),
485        CNTV_CVAL_EL0 = SystemRegEncoding::make(3, 3, 14, 3, 2),
486        CNTHCTL_EL2 = SystemRegEncoding::make(3, 4, 14, 1, 0),
487        CNTHP_CTL_EL2 = SystemRegEncoding::make(3, 4, 14, 2, 1),
488        CNTHP_CVAL_EL2 = SystemRegEncoding::make(3, 4, 14, 2, 2),
489        PMCCFILTR_EL0 = SystemRegEncoding::make(3, 3, 14, 15, 7),
490        MDCR_EL2 = SystemRegEncoding::make(3, 4, 1, 1, 1),
491        PMCR_EL0 = SystemRegEncoding::make(3, 3, 9, 12, 0),
492        PMCNTENSET_EL0 = SystemRegEncoding::make(3, 3, 9, 12, 1),
493        PMCNTENCLR_EL0 = SystemRegEncoding::make(3, 3, 9, 12, 2),
494        PMOVSSET_EL0 = SystemRegEncoding::make(3, 3, 9, 14, 3),
495        PMOVSCLR_EL0 = SystemRegEncoding::make(3, 3, 9, 12, 3),
496        PMSELR_EL0 = SystemRegEncoding::make(3, 3, 9, 12, 5),
497        PMCEID0_EL0 = SystemRegEncoding::make(3, 3, 9, 12, 6),
498        PMCEID1_EL0 = SystemRegEncoding::make(3, 3, 9, 12, 7),
499        PMCCNTR_EL0 = SystemRegEncoding::make(3, 3, 9, 13, 0),
500        PMUSERENR_EL0 = SystemRegEncoding::make(3, 3, 9, 14, 0),
501        PMINTENSET_EL1 = SystemRegEncoding::make(3, 0, 9, 14, 1),
502        PMINTENCLR_EL1 = SystemRegEncoding::make(3, 0, 9, 14, 2),
503
504        MAIR_EL1 = SystemRegEncoding::make(3, 0, 10, 2, 0),
505        AMAIR0 = SystemRegEncoding::make(3, 0, 10, 3, 0),
506        MAIR_EL2 = SystemRegEncoding::make(3, 4, 10, 2, 0),
507        AMAIR_EL2 = SystemRegEncoding::make(3, 4, 10, 3, 0),
508        MAIR_EL3 = SystemRegEncoding::make(3, 6, 10, 2, 0),
509
510        VBAR = SystemRegEncoding::make(3, 0, 12, 0, 0),
511        VBAR_EL2 = SystemRegEncoding::make(3, 4, 12, 0, 0),
512        RVBAR_EL2 = SystemRegEncoding::make(3, 4, 12, 0, 1),
513
514        TPIDR_EL0 = SystemRegEncoding::make(3, 3, 13, 0, 2),
515        TPIDRRO_EL0 = SystemRegEncoding::make(3, 3, 13, 0, 3),
516        TPIDR_EL1 = SystemRegEncoding::make(3, 0, 13, 0, 4),
517        TPIDR_EL2 = SystemRegEncoding::make(3, 4, 13, 0, 2),
518        CONTEXTIDR_EL1 = SystemRegEncoding::make(3, 0, 13, 0, 1),
519
520        CLIDR = SystemRegEncoding::make(3, 1, 0, 0, 1),
521        AIDR = SystemRegEncoding::make(3, 1, 0, 0, 7),
522        CSSELR = SystemRegEncoding::make(3, 2, 0, 0, 0),
523
524        CNTKCTL = SystemRegEncoding::make(3, 0, 14, 1, 0),
525        CNTVOFF_EL2 = SystemRegEncoding::make(3, 4, 14, 0, 3),
526
527        MDCCSR_EL0 = SystemRegEncoding::make(2, 3, 0, 1, 0),
528        MDSCR_EL1 = SystemRegEncoding::make(2, 0, 0, 2, 2),
529        MDRAR_EL1 = SystemRegEncoding::make(2, 0, 1, 0, 0),
530        OSLSR_EL1 = SystemRegEncoding::make(2, 0, 1, 1, 4),
531        DBGBVR0 = SystemRegEncoding::make(2, 0, 0, 0, 4),
532        DBGBVR1 = SystemRegEncoding::make(2, 0, 0, 1, 4),
533        DBGBVR2 = SystemRegEncoding::make(2, 0, 0, 2, 4),
534        DBGBVR3 = SystemRegEncoding::make(2, 0, 0, 3, 4),
535        DBGBVR4 = SystemRegEncoding::make(2, 0, 0, 4, 4),
536        DBGBVR5 = SystemRegEncoding::make(2, 0, 0, 5, 4),
537        DBGBCR0 = SystemRegEncoding::make(2, 0, 0, 0, 5),
538        DBGBCR1 = SystemRegEncoding::make(2, 0, 0, 1, 5),
539        DBGBCR2 = SystemRegEncoding::make(2, 0, 0, 2, 5),
540        DBGBCR3 = SystemRegEncoding::make(2, 0, 0, 3, 5),
541        DBGBCR4 = SystemRegEncoding::make(2, 0, 0, 4, 5),
542        DBGBCR5 = SystemRegEncoding::make(2, 0, 0, 5, 5),
543        DBGWVR0 = SystemRegEncoding::make(2, 0, 0, 0, 6),
544        DBGWVR1 = SystemRegEncoding::make(2, 0, 0, 1, 6),
545        DBGWVR2 = SystemRegEncoding::make(2, 0, 0, 2, 6),
546        DBGWVR3 = SystemRegEncoding::make(2, 0, 0, 3, 6),
547        DBGWCR0 = SystemRegEncoding::make(2, 0, 0, 0, 7),
548        DBGWCR1 = SystemRegEncoding::make(2, 0, 0, 1, 7),
549        DBGWCR2 = SystemRegEncoding::make(2, 0, 0, 2, 7),
550        DBGWCR3 = SystemRegEncoding::make(2, 0, 0, 3, 7),
551
552        ICC_AP0R0_EL1 = SystemRegEncoding::make(3, 0, 12, 8, 4),
553        ICC_AP0R1_EL1 = SystemRegEncoding::make(3, 0, 12, 8, 5),
554        ICC_AP0R2_EL1 = SystemRegEncoding::make(3, 0, 12, 8, 6),
555        ICC_AP0R3_EL1 = SystemRegEncoding::make(3, 0, 12, 8, 7),
556        ICC_AP1R0_EL1 = SystemRegEncoding::make(3, 0, 12, 9, 0),
557        ICC_AP1R1_EL1 = SystemRegEncoding::make(3, 0, 12, 9, 1),
558        ICC_AP1R2_EL1 = SystemRegEncoding::make(3, 0, 12, 9, 2),
559        ICC_AP1R3_EL1 = SystemRegEncoding::make(3, 0, 12, 9, 3),
560        ICC_ASGI1R_EL1 = SystemRegEncoding::make(3, 0, 12, 11, 6),
561        ICC_BPR0_EL1 = SystemRegEncoding::make(3, 0, 12, 8, 3),
562        ICC_BPR1_EL1 = SystemRegEncoding::make(3, 0, 12, 12, 3),
563        ICC_CTLR_EL1 = SystemRegEncoding::make(3, 0, 12, 12, 4),
564        ICC_CTLR_EL3 = SystemRegEncoding::make(3, 6, 12, 12, 4),
565        ICC_DIR_EL1 = SystemRegEncoding::make(3, 0, 12, 11, 1),
566        ICC_EOIR0_EL1 = SystemRegEncoding::make(3, 0, 12, 8, 1),
567        ICC_EOIR1_EL1 = SystemRegEncoding::make(3, 0, 12, 12, 1),
568        ICC_HPPIR0_EL1 = SystemRegEncoding::make(3, 0, 12, 8, 2),
569        ICC_HPPIR1_EL1 = SystemRegEncoding::make(3, 0, 12, 12, 2),
570        ICC_IAR0_EL1 = SystemRegEncoding::make(3, 0, 12, 8, 0),
571        ICC_IAR1_EL1 = SystemRegEncoding::make(3, 0, 12, 12, 0),
572        ICC_IGRPEN0_EL1 = SystemRegEncoding::make(3, 0, 12, 12, 6),
573        ICC_IGRPEN1_EL1 = SystemRegEncoding::make(3, 0, 12, 12, 7),
574        ICC_IGRPEN1_EL3 = SystemRegEncoding::make(3, 6, 12, 12, 7),
575        ICC_PMR_EL1 = SystemRegEncoding::make(3, 0, 4, 6, 0),
576        ICC_RPR_EL1 = SystemRegEncoding::make(3, 0, 12, 11, 3),
577        ICC_SGI0R_EL1 = SystemRegEncoding::make(3, 0, 12, 11, 7),
578        ICC_SGI1R_EL1 = SystemRegEncoding::make(3, 0, 12, 11, 5),
579        ICC_SRE_EL1 = SystemRegEncoding::make(3, 0, 12, 12, 5),
580        ICC_SRE_EL2 = SystemRegEncoding::make(3, 4, 12, 9, 5),
581        ICC_SRE_EL3 = SystemRegEncoding::make(3, 6, 12, 12, 5),
582    }
583}
584
585impl SystemRegEncoding {
586    pub const fn make(op0: u8, op1: u8, crn: u8, crm: u8, op2: u8) -> Self {
587        Self::new()
588            .with_op0(op0)
589            .with_op1(op1)
590            .with_crn(crn)
591            .with_crm(crm)
592            .with_op2(op2)
593    }
594}
595
596/// MPIDR_EL1
597#[bitfield(u64)]
598pub struct MpidrEl1 {
599    pub aff0: u8,
600    pub aff1: u8,
601    pub aff2: u8,
602    pub mt: bool,
603    #[bits(5)]
604    pub res0_25_29: u8,
605    pub u: bool,
606    pub res1_31: bool,
607    pub aff3: u8,
608    #[bits(24)]
609    pub res0_40_63: u32,
610}
611
612impl MpidrEl1 {
613    pub const AFFINITY_MASK: Self = Self::new()
614        .with_aff0(0xff)
615        .with_aff1(0xff)
616        .with_aff2(0xff)
617        .with_aff3(0xff);
618}
619
620open_enum! {
621    /// aarch64 translation granule size for TTBR0_EL1
622    pub enum TranslationGranule0: u64 {
623        TG_4KB = 0b00,
624        TG_64KB = 0b01,
625        TG_16KB = 0b10,
626    }
627}
628
629impl TranslationGranule0 {
630    const fn into_bits(self) -> u64 {
631        self.0
632    }
633
634    const fn from_bits(bits: u64) -> Self {
635        Self(bits)
636    }
637}
638
639open_enum! {
640    /// aarch64 translation granule size for TTBR1_EL1
641    pub enum TranslationGranule1: u64 {
642        TG_INVALID = 0b00,
643        TG_16KB = 0b01,
644        TG_4KB = 0b10,
645        TG_64KB = 0b11,
646    }
647}
648
649impl TranslationGranule1 {
650    const fn into_bits(self) -> u64 {
651        self.0
652    }
653
654    const fn from_bits(bits: u64) -> Self {
655        Self(bits)
656    }
657}
658
659open_enum! {
660    /// aarch64 intermediate physical address size
661    pub enum IntermPhysAddrSize: u64{
662        IPA_32_BITS_4_GB = 0b000,
663        IPA_36_BITS_64_GB = 0b001,
664        IPA_40_BITS_1_TB = 0b010,
665        IPA_42_BITS_4_TB = 0b011,
666        IPA_44_BITS_16_TB = 0b100,
667        IPA_48_BITS_256_TB = 0b101,
668        IPA_52_BITS_4_PB = 0b110,
669        IPA_56_BITS_64_PB = 0b111,
670    }
671}
672
673impl IntermPhysAddrSize {
674    const fn into_bits(self) -> u64 {
675        self.0
676    }
677
678    const fn from_bits(bits: u64) -> Self {
679        Self(bits)
680    }
681}
682
683/// aarch64 TCR_EL1 register
684#[bitfield(u64)]
685#[derive(PartialEq, Eq)]
686pub struct TranslationControlEl1 {
687    #[bits(6)]
688    pub t0sz: u64,
689    #[bits(1)]
690    _mbz0: u64,
691    #[bits(1)]
692    pub epd0: u64,
693    #[bits(2)]
694    pub irgn0: u64,
695    #[bits(2)]
696    pub orgn0: u64,
697    #[bits(2)]
698    pub sh0: u64,
699    #[bits(2)]
700    pub tg0: TranslationGranule0,
701    #[bits(6)]
702    pub t1sz: u64,
703    #[bits(1)]
704    pub a1: u64,
705    #[bits(1)]
706    pub epd1: u64,
707    #[bits(2)]
708    pub irgn1: u64,
709    #[bits(2)]
710    pub orgn1: u64,
711    #[bits(2)]
712    pub sh1: u64,
713    #[bits(2)]
714    pub tg1: TranslationGranule1,
715    #[bits(3)]
716    pub ips: IntermPhysAddrSize,
717    #[bits(1)]
718    _mbz1: u64,
719    #[bits(1)]
720    pub a_s: u64,
721    #[bits(1)]
722    pub tbi0: u64,
723    #[bits(1)]
724    pub tbi1: u64,
725    #[bits(1)]
726    pub ha: u64,
727    #[bits(1)]
728    pub hd: u64,
729    #[bits(1)]
730    pub hpd0: u64,
731    #[bits(1)]
732    pub hpd1: u64,
733    #[bits(1)]
734    pub hwu059: u64,
735    #[bits(1)]
736    pub hwu060: u64,
737    #[bits(1)]
738    pub hwu061: u64,
739    #[bits(1)]
740    pub hwu062: u64,
741    #[bits(1)]
742    pub hwu159: u64,
743    #[bits(1)]
744    pub hwu160: u64,
745    #[bits(1)]
746    pub hwu161: u64,
747    #[bits(1)]
748    pub hwu162: u64,
749    #[bits(1)]
750    pub tbid0: u64,
751    #[bits(1)]
752    pub tbid1: u64,
753    #[bits(1)]
754    pub nfd0: u64,
755    #[bits(1)]
756    pub nfd1: u64,
757    #[bits(1)]
758    pub e0pd0: u64,
759    #[bits(1)]
760    pub e0pd1: u64,
761    #[bits(1)]
762    pub tcma0: u64,
763    #[bits(1)]
764    pub tcma1: u64,
765    #[bits(1)]
766    pub ds: u64,
767    #[bits(1)]
768    pub mtx0: u64,
769    #[bits(1)]
770    pub mtx1: u64,
771    #[bits(2)]
772    _mbz2: u64,
773}
774
775impl TranslationControlEl1 {
776    pub fn ttbr0_valid_address_bits(&self) -> u64 {
777        64 - self.t0sz()
778    }
779
780    pub fn ttbr1_valid_address_bits(&self) -> u64 {
781        64 - self.t1sz()
782    }
783}
784
785/// aarch64 TTBRx_EL1 content
786#[bitfield(u64)]
787#[derive(PartialEq, Eq)]
788pub struct TranslationBaseEl1 {
789    // Hardcoding CnP to be `0` for simplicity.
790    // #[bits(1)]
791    // pub cnp: u64,
792    #[bits(48)]
793    pub baddr: u64,
794    #[bits(16)]
795    pub asid: u64,
796}
797
798#[bitfield(u64)]
799#[derive(PartialEq, Eq, IntoBytes, Immutable, KnownLayout, FromBytes)]
800pub struct Pte {
801    pub valid: bool,
802    pub not_large_page: bool,
803    #[bits(3)]
804    pub attribute_index: u64,
805    pub non_secure: bool,
806    pub ap_unprivileged: bool,
807    pub ap_read_only: bool,
808    #[bits(2)]
809    pub shareability: u64,
810    pub access_flag: bool,
811    pub not_global: bool,
812    #[bits(36)]
813    pub pfn: u64,
814    #[bits(3)]
815    pub reserved_must_be_zero: u64,
816    pub dbm: bool,
817    pub contiguous_hint: bool,
818    pub privilege_no_execute: bool,
819    pub user_no_execute: bool,
820    #[bits(4)]
821    pub _reserved2: u64,
822    pub pxn_table: bool,
823    pub uxn_table: bool,
824    pub ap_table_privileged_only: bool,
825    pub ap_table_read_only: bool,
826    pub ns_table: bool,
827}
828
829/// The contents of ID_MMFR0_EL1
830#[bitfield(u64)]
831pub struct MmFeatures0El1 {
832    #[bits(4)]
833    pub pa_range: IntermPhysAddrSize,
834    #[bits(60)]
835    _rest: u64,
836}
837
838pub const GIC_DISTRIBUTOR_SIZE: u64 = 0x1_0000;
839pub const GIC_REDISTRIBUTOR_FRAME_SIZE: u64 = 0x1_0000;
840pub const GIC_SGI_FRAME_SIZE: u64 = 0x1_0000;
841pub const GIC_REDISTRIBUTOR_SIZE: u64 = GIC_REDISTRIBUTOR_FRAME_SIZE + GIC_SGI_FRAME_SIZE;
842
843open_enum! {
844    pub enum SystemReset2Code: u32 {
845        WARM_RESET = 0,
846    }
847}
848
849open_enum! {
850    pub enum SystemOff2Code: u32 {
851        DEFAULT = 0,
852        HIBERNATE_OFF = 1,
853    }
854}