Skip to main content

libarch/arm64/
system.rs

1// Copyright 2026 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use bitrs::{bitfield_repr, layout, multilayout};
6use regio::arm64::{SysReg, spec};
7
8use super::PhysicalAddressSize;
9
10/// [arm/sysreg]/currentel: CurrentEL, Current Exception Level
11pub const CURRENT_EL: SysReg<spec::CurrentEL, CurrentEl> = SysReg::new();
12
13layout!({
14    /// The layout of [`CURRENT_EL`].
15    pub struct CurrentEl(u64);
16    {
17        let __ @ 63..4;
18        let el @ 3..2;
19        let __ @ 1..0;
20    }
21});
22
23/// [arm/sysreg]/midr_el1: Main ID Register
24pub const MIDR_EL1: SysReg<spec::MIDR_EL1, MainIdRegister> = SysReg::new();
25
26layout!({
27    /// The layout of [`MIDR_EL1`].
28    pub struct MainIdRegister(u64);
29    {
30        let __ @ 63..32;
31        let implementer @ 31..24; // Implementer code, e.g. 0x41 ('A') for Arm
32        let variant @ 23..20; // Major revision
33        let architecture @ 19..16; // Architecture; 0b1111 defers to the ID registers
34        let part_num @ 15..4; // Primary part number
35        let revision @ 3..0; // Minor revision
36    }
37});
38
39/// [arm/sysreg]/mpidr_el1: Multiprocessor Affinity Register (EL1)
40pub const MPIDR_EL1: SysReg<spec::MPIDR_EL1, MultiprocessorAffinityRegister> = SysReg::new();
41
42layout!({
43    /// The layout of [`MPIDR_EL1`] and `VMPIDR_EL2`.
44    pub struct MultiprocessorAffinityRegister(u64);
45    {
46        let __ @ 63..40;
47        let aff3 @ 39..32; // Affinity level 3
48        let __ @ 31 = 1;
49        let u @ 30; // Uniprocessor system
50        let __ @ 29..25;
51        let mt @ 24; // Multithreading
52        let aff2 @ 23..16; // Affinity level 2
53        let aff1 @ 15..8; // Affinity level 1
54        let aff0 @ 7..0; // Affinity level 0
55    }
56});
57
58impl MultiprocessorAffinityRegister {
59    const AFFINITY_MASK: u64 = MultiprocessorAffinityRegister::AFF3_MASK
60        | MultiprocessorAffinityRegister::AFF2_MASK
61        | MultiprocessorAffinityRegister::AFF1_MASK
62        | MultiprocessorAffinityRegister::AFF0_MASK;
63
64    /// Returns the full affinity value (bits [39:32], [23:16], [15:8], and [7:0]).
65    pub fn affinity(&self) -> u64 {
66        self.bits() & Self::AFFINITY_MASK
67    }
68}
69
70/// [arm/sysreg]/sctlr_el1: System Control Register (EL1)
71pub const SCTLR_EL1: SysReg<spec::SCTLR_EL1, SystemControlRegisterEl1> = SysReg::new();
72
73/// [arm/sysreg]/sctlr_el2: System Control Register (EL2)
74pub const SCTLR_EL2: SysReg<spec::SCTLR_EL2, SystemControlRegisterEl2> = SysReg::new();
75
76/// [arm/sysreg]/sctlr_el3: System Control Register (EL3)
77pub const SCTLR_EL3: SysReg<spec::SCTLR_EL3, SystemControlRegisterEl3> = SysReg::new();
78
79#[bitfield_repr(u8)]
80#[derive(Clone, Copy)]
81pub enum TagCheckFault {
82    None = 0b00,            // Faults have no effect.
83    Synchronous = 0b01,     // All faults cause a synchronous exception.
84    Asynchronous = 0b10,    // All faults accumulate asynchronously.
85    SynchronousRead = 0b11, // Synchronous for read, asynchronous for write.
86}
87
88multilayout!({
89    /// The layout of [`SCTLR_EL1`].
90    #[bitrs(el1)]
91    pub struct SystemControlRegisterEl1(u64);
92
93    /// The layout of [`SCTLR_EL2`].
94    #[bitrs(el2)]
95    pub struct SystemControlRegisterEl2(u64);
96
97    /// The layout of [`SCTLR_EL3`].
98    #[bitrs(el3)]
99    pub struct SystemControlRegisterEl3(u64);
100
101    // EL1, EL2, EL3
102    {
103        let spintmask @ 62;
104        let nmi @ 61;
105        let tsco @ 59;
106        let tme @ 53;
107        let tmt @ 51;
108        let dsbss @ 44;
109        let ata @ 43;
110        let tcf @ 41..40: TagCheckFault;
111        let itfsb @ 37;
112        let bt @ 36;
113        let __ @ 34;
114        let enia @ 31;
115        let enib @ 30;
116        let enda @ 27;
117        let ee @ 25;
118        let eis @ 22;
119        let iesb @ 21;
120        let wxn @ 19;
121        let __ @ 17;
122        let dze @ 14;
123        let endb @ 13;
124        let i @ 12;
125        let eos @ 11;
126        let naa @ 6;
127        let sa @ 3;
128        let c @ 2;
129        let a @ 1;
130        let m @ 0;
131    }
132
133    // EL1, EL2
134    #[any(el1, el2)]
135    {
136        let tidcp @ 63;
137        let entp2 @ 60;
138        let tsco0 @ 58;
139        let epan @ 57;
140        let enals @ 56;
141        let enas0 @ 55;
142        let enasr @ 54;
143        let tme0 @ 52;
144        let tmt0 @ 50;
145        let mscen @ 33;
146        let cmow @ 32;
147    }
148
149    // EL1
150    #[el1]
151    {
152        let twedel @ 49..46;
153        let tweden @ 45;
154        let ata0 @ 42;
155        let tcf0 @ 39..38: TagCheckFault;
156        let bt0 @ 35;
157        let lsmaoe @ 29;
158        let ntlsmd @ 28;
159        let uci @ 26;
160        let e0e @ 24;
161        let span @ 23;
162        let tscxt @ 20;
163        let ntwe @ 18;
164        let ntwi @ 16;
165        let uct @ 15;
166        let enrctx @ 10;
167        let uma @ 9;
168        let sed @ 8;
169        let itd @ 7;
170        let cp15ben @ 5;
171        let sa0 @ 4;
172    }
173});
174
175impl SystemControlRegisterEl1 {
176    /// Returns the minimum delay in cycles if TWEDEn is enabled.
177    pub fn twedel_cycles(&self) -> Option<u64> {
178        if self.tweden() { Some(1u64 << self.twedel() << 8) } else { None }
179    }
180}
181
182/// [arm/sysreg]/sctlr2_el1: System Control Register 2 (EL1)
183pub const SCTLR2_EL1: SysReg<spec::SCTLR2_EL1, SystemControlRegister2El1> = SysReg::new();
184
185/// [arm/sysreg]/sctlr2_el2: System Control Register 2 (EL2)
186pub const SCTLR2_EL2: SysReg<spec::SCTLR2_EL2, SystemControlRegister2El2> = SysReg::new();
187
188/// [arm/sysreg]/sctlr2_el3: System Control Register 2 (EL3)
189pub const SCTLR2_EL3: SysReg<spec::SCTLR2_EL3, SystemControlRegister2El3> = SysReg::new();
190
191multilayout!({
192    /// The layout of [`SCTLR2_EL1`].
193    #[bitrs(el1)]
194    pub struct SystemControlRegister2El1(u64);
195
196    /// The layout of [`SCTLR2_EL2`].
197    #[bitrs(el2)]
198    pub struct SystemControlRegister2El2(u64);
199
200    /// The layout of [`SCTLR2_EL3`].
201    #[bitrs(el3)]
202    pub struct SystemControlRegister2El3(u64);
203
204    // EL1, EL2, EL3
205    {
206        let __ @ 63..7;
207        let enanerr @ 4;
208        let enaderr @ 3;
209        let __ @ 0;
210    }
211
212    // EL1, EL2
213    #[any(el1, el2)]
214    {
215        let enidcp128 @ 6;
216        let ease @ 5;
217        let nmea @ 2;
218    }
219
220    // EL2, EL3
221    #[any(el2, el3)]
222    {
223        let emec @ 1;
224    }
225});
226
227/// [arm/sysreg]/scr_el3: Secure Configuration Register
228pub const SCR_EL3: SysReg<spec::SCR_EL3, SecureConfigurationRegister> = SysReg::new();
229
230layout!({
231    /// The layout of [`SCR_EL3`].
232    pub struct SecureConfigurationRegister(u64);
233    {
234        let __ @ 63..39;
235        let hxen @ 38;
236        let aden @ 37;
237        let enas0 @ 36;
238        let amvoffen @ 35;
239        let __ @ 34;
240        let twedel @ 33..30;
241        let tweden @ 29;
242        let ecven @ 28;
243        let fgten @ 27;
244        let ata @ 26;
245        let enscxt @ 25;
246        let __ @ 24..22;
247        let fien @ 21;
248        let nmea @ 20;
249        let ease @ 19;
250        let eel2 @ 18;
251        let api @ 17;
252        let apk @ 16;
253        let terr @ 15;
254        let tlor @ 14;
255        let twe @ 13;
256        let twi @ 12;
257        let st @ 11;
258        let rw @ 10;
259        let sif @ 9;
260        let hce @ 8;
261        let smd @ 7;
262        let __ @ 6;
263        let __ @ 5..4 = 0b11;
264        let ea @ 3;
265        let fiq @ 2;
266        let irq @ 1;
267        let ns @ 0;
268    }
269});
270
271/// The cache shareability attribute for memory regions, as defined by the
272/// TCR_ELx.SHn fields.
273///
274/// [arm/v8]: D13.2.120 TCR_EL1, Translation Control Register (EL1)
275/// [arm/v8]: D13.2.121 TCR_EL2, Translation Control Register (EL2)
276#[bitfield_repr(u8)]
277#[derive(Clone, Copy)]
278pub enum ShareabilityAttribute {
279    None = 0b00,
280    // 0b01 is reserved.
281    Outer = 0b10,
282    Inner = 0b11,
283}
284
285/// The cacheability attribute of a normal memory regions, as defined by the
286/// TCR_ELx.IRGNn and TCR_ELx.ORGNn fields.
287///
288/// [arm/v8]: D13.2.120 TCR_EL1, Translation Control Register (EL1)
289/// [arm/v8]: D13.2.121 TCR_EL2, Translation Control Register (EL2)
290#[bitfield_repr(u8)]
291#[derive(Clone, Copy)]
292pub enum CacheabilityAttribute {
293    NonCacheable = 0b00,
294    WriteBackReadWriteAllocate = 0b01,
295    WriteThroughReadAllocate = 0b10,
296    WriteBackReadAllocate = 0b11,
297}
298
299/// Granule size values for the TCR_EL1 and TCR_EL2 fields.
300///
301/// WARNING: The encodings for the TG0 field and TG1 field are different.
302///
303/// [arm/v8]: D13.2.120 TCR_EL1, Translation Control Register (EL1)
304#[bitfield_repr(u8)]
305#[derive(Clone, Copy)]
306pub enum TcrTg0Value {
307    Tg4KiB = 0b00,
308    Tg16KiB = 0b10,
309    Tg64KiB = 0b01,
310}
311
312/// Granule size values for the TCR_EL1.TG1 field.
313///
314/// WARNING: The encodings for the TG0 field and TG1 field are different.
315///
316/// [arm/v8]: D13.2.120 TCR_EL1, Translation Control Register (EL1)
317#[bitfield_repr(u8)]
318#[derive(Clone, Copy)]
319pub enum TcrTg1Value {
320    Tg16KiB = 0b01,
321    Tg4KiB = 0b10,
322    Tg64KiB = 0b11,
323}
324
325/// [arm/v8]: D13.2.120 TCR_EL1, Translation Control Register (EL1)
326pub const TCR_EL1: SysReg<spec::TCR_EL1, TranslationControlRegisterEl1> = SysReg::new();
327
328/// [arm/v8]: D13.2.121 TCR_EL2, Translation Control Register (EL2)
329pub const TCR_EL2: SysReg<spec::TCR_EL2, TranslationControlRegisterEl2> = SysReg::new();
330
331multilayout!({
332    /// The layout of [`TCR_EL1`].
333    #[bitrs(el1)]
334    pub struct TranslationControlRegisterEl1(u64);
335
336    /// The layout of [`TCR_EL2`].
337    #[bitrs(el2)]
338    pub struct TranslationControlRegisterEl2(u64);
339
340    // EL1, EL2.
341    {
342        let __ @ 63..62;
343        let tg0 @ 15..14: TcrTg0Value;
344        let sh0 @ 13..12: ShareabilityAttribute;
345        let orgn0 @ 11..10: CacheabilityAttribute;
346        let irgn0 @ 9..8: CacheabilityAttribute;
347        let t0sz @ 5..0;
348    }
349
350    #[el1]
351    {
352        let mtx1 @ 61;
353        let mtx0 @ 60;
354        let ds @ 59;
355        let tcma1 @ 58;
356        let tcma0 @ 57;
357        let e0pd1 @ 56;
358        let e0pd0 @ 55;
359        let nfd1 @ 54;
360        let nfd0 @ 53;
361        let tbid1 @ 52;
362        let tbid0 @ 51;
363        let hwu162 @ 50;
364        let hwu161 @ 49;
365        let hwu160 @ 48;
366        let hwu159 @ 47;
367        let hwu062 @ 46;
368        let hwu061 @ 45;
369        let hwu060 @ 44;
370        let hwu059 @ 43;
371        let hpd1 @ 42;
372        let hpd0 @ 41;
373        let hd @ 40;
374        let ha @ 39;
375        let tbi1 @ 38;
376        let tbi0 @ 37;
377        let asid_size @ 36; // `as` is reserved
378        let __ @ 35;
379        let ips @ 34..32: PhysicalAddressSize;
380        let tg1 @ 31..30: TcrTg1Value;
381        let sh1 @ 29..28: ShareabilityAttribute;
382        let orgn1 @ 27..26: CacheabilityAttribute;
383        let irgn1 @ 25..24: CacheabilityAttribute;
384        let epd1 @ 23;
385        let a1 @ 22;
386        let t1sz @ 21..16;
387        let epd0 @ 7;
388        let __ @ 6;
389    }
390
391    #[el2]
392    {
393        let mtx @ 33;
394        let ds @ 32;
395        let __ @ 31 = 1;
396        let tcma @ 30;
397        let tbid @ 29;
398        let hwu62 @ 28;
399        let hwu61 @ 27;
400        let hwu60 @ 26;
401        let hwu59 @ 25;
402        let hpd @ 24;
403        let __ @ 23 = 1;
404        let hd @ 22;
405        let ha @ 21;
406        let tbi @ 20;
407        let ps @ 18..16: PhysicalAddressSize;
408        let __ @ 7..6;
409    }
410});
411
412/// [arm/v8]: VTCR_EL2, Virtualization Translation Control Register
413pub const VTCR_EL2: SysReg<spec::VTCR_EL2, VirtualizationTranslationControlRegister> =
414    SysReg::new();
415
416layout!({
417    /// The layout of [`VTCR_EL2`].
418    pub struct VirtualizationTranslationControlRegister(u64);
419    {
420        let __ @ 63..46;
421        let hdbss @ 45;
422        let haft @ 44;
423        let __ @ 43..42;
424        let tl0 @ 41;
425        let gcsh @ 40;
426        let __ @ 39;
427        let d128 @ 38;
428        let s2poe @ 37;
429        let s2pie @ 36;
430        let tl1 @ 35;
431        let assured_only @ 34;
432        let sl2 @ 33;
433        let ds @ 32;
434        let __ @ 31 = 1;
435        let nsa @ 30;
436        let nsw @ 29;
437        let hwu62 @ 28;
438        let hwu61 @ 27;
439        let hwu60 @ 26;
440        let hwu59 @ 25;
441        let __ @ 24;
442        let __ @ 23 = 1;
443        let hd @ 22;
444        let ha @ 21;
445        let __ @ 20;
446        let vs @ 19;
447        let ps @ 18..16: PhysicalAddressSize;
448        let tg0 @ 15..14: TcrTg0Value;
449        let sh0 @ 13..12: ShareabilityAttribute;
450        let orgn0 @ 11..10: CacheabilityAttribute;
451        let irgn0 @ 9..8: CacheabilityAttribute;
452        let sl0 @ 7..6;
453        let t0sz @ 5..0;
454    }
455});
456
457/// [arm/v9]: D23.2.172 TCR2_EL1, Translation Control Register (EL1)
458pub const TCR2_EL1: SysReg<spec::TCR2_EL1, ExtendedTranslationControlRegister> = SysReg::new();
459
460layout!({
461    /// The layout of [`TCR2_EL1`].
462    pub struct ExtendedTranslationControlRegister(u64);
463    {
464        let __ @ 63..22;
465        let fngna1 @ 21; // Force non-global for unassured using TTBR1. (FEAT_THE)
466        let fngna0 @ 20; // Force non-global for unassured using TTBR0. (FEAT_THE)
467        let __ @ 19;
468        let fng1 @ 18; // Force non-global translations for TTBR1. (FEAT_ASID2)
469        let fng0 @ 17; // Force non-global translations for TTBR0. (FEAT_ASID2)
470        let a2 @ 16; // Enable use of two ASIDs. (FEAT_ASID2)
471        let disch1 @ 15; // Disable contiguous bit for start table for TTBR1. (FEAT_D128)
472        let disch0 @ 14; // Disable contiguous bit for start table for TTBR0. (FEAT_D128)
473        let __ @ 13..12;
474        let haft @ 11; // Hardware managed access flag for table descriptors. (FEAT_HAFT)
475        let pttwi @ 10; // Permit translation table walk incoherence. (FEAT_THE)
476        let __ @ 9..6;
477        let d128 @ 5; // Enable 128 bit translation tables. (FEAT_D128)
478        let aie @ 4; // Enable attribute indexing extension. (FEAT_AIE)
479        let poe @ 3; // Enable permission overlays for privileged accesses. (FEAT_S1POE)
480        let e0poe @ 2; // Enable permission overlays for unprivileged accesses. (FEAT_S1POE)
481        let pie @ 1; // Enable indirect permission scheme. (FEAT_S1PIE)
482        let pnch @ 0; // Enable protected attribute enable. (FEAT_THE)
483    }
484});
485
486/// [arm/v8]: D13.2.132 TTBR0_EL1, Translation Table Base Register 0 (EL1)
487pub const TTBR0_EL1: SysReg<spec::TTBR0_EL1, TranslationTableBaseRegister> = SysReg::new();
488
489/// [arm/v8]: D13.2.133 TTBR0_EL2, Translation Table Base Register 0 (EL2)
490pub const TTBR0_EL2: SysReg<spec::TTBR0_EL2, TranslationTableBaseRegister> = SysReg::new();
491
492/// [arm/v8]: D13.2.134 TTBR0_EL3, Translation Table Base Register 0 (EL3)
493pub const TTBR0_EL3: SysReg<spec::TTBR0_EL3, TranslationTableBaseRegister> = SysReg::new();
494
495/// [arm/v8]: D13.2.135 TTBR1_EL1, Translation Table Base Register 1 (EL1)
496pub const TTBR1_EL1: SysReg<spec::TTBR1_EL1, TranslationTableBaseRegister> = SysReg::new();
497
498/// [arm/v8]: D13.2.136 TTBR1_EL2, Translation Table Base Register 1 (EL2)
499pub const TTBR1_EL2: SysReg<spec::TTBR1_EL2, TranslationTableBaseRegister> = SysReg::new();
500
501/// [arm/v8]: VTTBR_EL2, Virtualization Translation Table Base Register (EL2)
502pub const VTTBR_EL2: SysReg<spec::VTTBR_EL2, TranslationTableBaseRegister> = SysReg::new();
503
504layout!({
505    /// The layout of [`TTBR0_EL1`], [`TTBR0_EL2`], [`TTBR0_EL3`],
506    /// [`TTBR1_EL1`], [`TTBR1_EL2`], [`TTBR1_EL3`], and [`VTTBR_EL2`].
507    pub struct TranslationTableBaseRegister(u64);
508    {
509        let asid @ 63..48;
510        #[unshifted]
511        let addr @ 47..1; // Bits [47:1] of the root table physical address.
512        let cnp @ 0; // Common not private.
513    }
514});
515
516impl TranslationTableBaseRegister {
517    /// VMID field (same bit position as ASID when used for VTTBR_EL2).
518    ///
519    /// The layout is the same as TTBR0_ELx, but the ASID field is called VMID.
520    pub fn vmid(&self) -> u16 {
521        self.asid()
522    }
523
524    /// Sets VMID field.
525    pub fn set_vmid(&mut self, vmid: u16) -> &mut Self {
526        self.set_asid(vmid)
527    }
528}
529
530/// [arm/sysreg]/currentel: DAIF, Interrupt Mask Bits
531pub const DAIF: SysReg<spec::DAIF, Daif> = SysReg::new();
532
533layout!({
534    /// The layout of [`DAIF`].
535    pub struct Daif(u64);
536    {
537        let __ @ 63..10;
538        let d @ 9;
539        let a @ 8;
540        let i @ 7;
541        let f @ 6;
542        let __ @ 5..0;
543    }
544});
545
546/// [arm/sysreg]/vbar_el1: Vector Base Address Register (EL1)
547pub const VBAR_EL1: SysReg<spec::VBAR_EL1, VectorBaseAddressRegister> = SysReg::new();
548
549/// [arm/sysreg]/vbar_el2: Vector Base Address Register (EL2)
550pub const VBAR_EL2: SysReg<spec::VBAR_EL2, VectorBaseAddressRegister> = SysReg::new();
551
552/// [arm/sysreg]/vbar_el3: Vector Base Address Register (EL3)
553pub const VBAR_EL3: SysReg<spec::VBAR_EL3, VectorBaseAddressRegister> = SysReg::new();
554
555layout!({
556    /// The layout of [`VBAR_EL1`], [`VBAR_EL2`], and [`VBAR_EL3`].
557    pub struct VectorBaseAddressRegister(u64);
558    {
559        #[unshifted]
560        let addr @ 63..11;
561        let __ @ 10..0;
562    }
563});
564
565/// [arm/sysreg]/elr_el1: Exception Link Register (EL1)
566pub const ELR_EL1: SysReg<spec::ELR_EL1, ExceptionLinkRegister> = SysReg::new();
567
568/// [arm/sysreg]/elr_el2: Exception Link Register (EL2)
569pub const ELR_EL2: SysReg<spec::ELR_EL2, ExceptionLinkRegister> = SysReg::new();
570
571/// [arm/sysreg]/elr_el3: Exception Link Register (EL3)
572pub const ELR_EL3: SysReg<spec::ELR_EL3, ExceptionLinkRegister> = SysReg::new();
573
574layout!({
575    /// The layout of [`ELR_EL1`], [`ELR_EL2`], and [`ELR_EL3`].
576    pub struct ExceptionLinkRegister(u64);
577    {
578        let pc @ 63..0;
579    }
580});
581
582/// [arm/sysreg]/sp_el0: Stack Pointer (EL0)
583pub const SP_EL0: SysReg<spec::SP_EL0, StackPointerRegister> = SysReg::new();
584
585/// [arm/sysreg]/sp_el1: Stack Pointer (EL1)
586pub const SP_EL1: SysReg<spec::SP_EL1, StackPointerRegister> = SysReg::new();
587
588/// [arm/sysreg]/sp_el2: Stack Pointer (EL2)
589pub const SP_EL2: SysReg<spec::SP_EL2, StackPointerRegister> = SysReg::new();
590
591layout!({
592    /// The layout of [`SP_EL1`], [`SP_EL2`], and [`SP_EL3`].
593    pub struct StackPointerRegister(u64);
594    {
595        let sp @ 63..0;
596    }
597});
598
599/// [arm/sysreg]/spsr_el1: Saved Program Status Register (El1)
600pub const SPSR_EL1: SysReg<spec::SPSR_EL1, SavedProgramStatusRegister> = SysReg::new();
601
602/// [arm/sysreg]/spsr_el2: Saved Program Status Register (El2)
603pub const SPSR_EL2: SysReg<spec::SPSR_EL2, SavedProgramStatusRegister> = SysReg::new();
604
605/// [arm/sysreg]/spsr_el3: Saved Program Status Register (El3)
606pub const SPSR_EL3: SysReg<spec::SPSR_EL3, SavedProgramStatusRegister> = SysReg::new();
607
608#[bitfield_repr(u8)]
609#[derive(Clone, Copy)]
610pub enum SpsrExceptionLevel {
611    El0t = 0b0000, // EL0 using SP_EL0
612    El1t = 0b0100, // EL1 using SP_EL0
613    El1h = 0b0101, // EL1 using SP_EL1
614    El2t = 0b1000, // EL2 using SP_EL0
615    El2h = 0b1001, // EL2 using SP_EL2
616    El3t = 0b1100, // EL3 using SP_EL0
617    El3h = 0b1101, // EL3 using SP_EL3
618}
619
620layout!({
621    /// The layout of [`SPSR_EL1`], [`SPSR_EL2`], and [`SPSR_EL3`].
622    ///
623    /// These are the assignments when an exception is taken from AArch64 state.
624    pub struct SavedProgramStatusRegister(u64);
625    {
626        let __ @ 63..32;
627        let n @ 31;
628        let z @ 30;
629        let c @ 29;
630        let v @ 28;
631        let __ @ 27..26;
632        let tco @ 25;
633        let dit @ 24;
634        let uao @ 23;
635        let pan @ 22;
636        let ss @ 21;
637        let il @ 20;
638        let __ @ 19..13;
639        let ssbs @ 12;
640        let btype @ 11..10;
641        let d @ 9;
642        let a @ 8;
643        let i @ 7;
644        let f @ 6;
645        let __ @ 5;
646        let a32 @ 4; // Always zero in this format.
647        let m @ 3..0: SpsrExceptionLevel;
648    }
649});
650
651impl SavedProgramStatusRegister {
652    /// EL this exception was taken from.
653    pub fn el(self) -> CurrentEl {
654        CurrentEl::from((self.m() as u64) & CurrentEl::EL_MASK)
655    }
656
657    /// SPSel state at the exception (true if it used SP_ELx).
658    pub fn spsel(self) -> bool {
659        (self.m() as u8) & 1 != 0
660    }
661}
662
663/// [arm/sysreg]/nzcv: Condition Flags
664pub const NZCV: SysReg<spec::NZCV, Nzcv> = SysReg::new();
665
666layout!({
667    /// The layout of [`NZCV`].
668    ///
669    /// This is a subset of SPSR_ELx that is accessible R/W to everyone.
670    pub struct Nzcv(u64);
671    {
672        let __ @ 63..32;
673        let n @ 31;
674        let z @ 30;
675        let c @ 29;
676        let v @ 28;
677        let __ @ 27..0;
678    }
679});
680
681/// [arm/sysreg]/esr_el1: Exception Syndrome Register (El1)
682pub const ESR_EL1: SysReg<spec::ESR_EL1, ExceptionSyndromeRegister> = SysReg::new();
683
684/// [arm/sysreg]/esr_el2: Exception Syndrome Register (El2)
685pub const ESR_EL2: SysReg<spec::ESR_EL2, ExceptionSyndromeRegister> = SysReg::new();
686
687/// [arm/sysreg]/esr_el3: Exception Syndrome Register (El3)
688pub const ESR_EL3: SysReg<spec::ESR_EL3, ExceptionSyndromeRegister> = SysReg::new();
689
690/// Some values are only possible in ESR_EL2 and/or ESR_EL3.
691#[bitfield_repr(u8)]
692#[derive(Clone, Copy)]
693pub enum ExceptionClass {
694    Unknown = 0b000000,
695    Wf = 0b000001,         // WF
696    Mcr = 0b000011,        // MCR or MRC
697    Mcrr = 0b000100,       // MCRR or MRRC
698    McrCoproc = 0b000101,  // MCR or MRC (coproc=0b1110)
699    Ldc = 0b000110,        // LDC or STC
700    Fp = 0b000111,         // SVE or SIMD
701    Ld64b = 0b001010,      // LD64B, ST64B, ST64BV, or ST64BVO
702    McrrCoproc = 0b001100, // MRRC (coproc==0b1110)
703    Bti = 0b001101,        // Branch target exception
704    IllegalExecution = 0b001110,
705    Svc32 = 0b010001,
706    Hvc32 = 0b010010, // EL2, EL3
707    Smc32 = 0b010011, // EL2, EL3
708    TrappedSysreg128 = 0b010100,
709    Svc64 = 0b010101,
710    Hvc64 = 0b010110, // EL2, EL3
711    Smc64 = 0b010111, // EL2, EL3
712    Msr = 0b011000,   // MSR, MRS, or System Instruction
713    Sve = 0b011001,
714    Eret = 0b011010, // EL2, EL3
715    Tstart = 0b011011,
716    Pac = 0b011100,
717    Sme = 0b011101,
718    ImplementationDefined = 0b011111, // EL3
719    InstructionAbortLowerEl = 0b100000,
720    InstructionAbortSameEl = 0b100001,
721    PcAlignment = 0b100010,
722    DataAbortLowerEl = 0b100100,
723    DataAbortSameEl = 0b100101,
724    SpAlignment = 0b100110,
725    Mops = 0b100111,
726    Fpe32 = 0b101000,
727    Fpe64 = 0b101100,
728    Gcs = 0b101101,
729    Serror = 0b101111,
730    BreakpointLowerEl = 0b110000,
731    BreakpointSameEl = 0b110001,
732    StepLowerEl = 0b110010,
733    StepSameEl = 0b110011,
734    WatchpointLowerEl = 0b110100,
735    WatchpointSameEl = 0b110101,
736    Bkpt = 0b111000,        // AArch32 BKPT #<n>
737    VectorCatch = 0b111010, // EL2, EL3
738    Brk = 0b111100,         // AArch64 BRK #<n>
739    Profiling = 0b111101,
740}
741
742layout!({
743    /// The layout of [`ESR_EL1`], [`ESR_EL2`], and [`ESR_EL3`].
744    ///
745    /// These are the assignments when an exception is taken from AArch64 state.
746    pub struct ExceptionSyndromeRegister(u64);
747    {
748        let __ @ 63..56;
749        let iss2 @ 55..32;
750        let ec @ 31..26: ExceptionClass;
751        let il @ 25;
752        let iss @ 24..0;
753    }
754});
755
756/// [arm/sysreg]/cptr_el2: Architectural Feature Trap Register (EL2) when `HCR_EL2.E2H == 0`
757pub const CPTR_EL2_NO_VHE: SysReg<spec::CPTR_EL2, ArchitecturalFeatureTrapRegisterNoVhe> =
758    SysReg::new();
759
760/// [arm/sysreg]/cptr_el2: Architectural Feature Trap Register (EL2) when `HCR_EL2.E2H == 1` (FEAT_VHE)
761pub const CPTR_EL2_VHE: SysReg<spec::CPTR_EL2, ArchitecturalFeatureTrapRegisterVhe> = SysReg::new();
762
763/// [arm/sysreg]/cptr_el3: Architectural Feature Trap Register (EL3) when `HCR_EL2.E2H == 0`
764pub const CPTR_EL3_NO_VHE: SysReg<spec::CPTR_EL3, ArchitecturalFeatureTrapRegisterNoVhe> =
765    SysReg::new();
766
767/// [arm/sysreg]/cptr_el3: Architectural Feature Trap Register (EL3) when `HCR_EL2.E2H == 1` (FEAT_VHE)
768pub const CPTR_EL3_VHE: SysReg<spec::CPTR_EL3, ArchitecturalFeatureTrapRegisterVhe> = SysReg::new();
769
770multilayout!({
771    /// The layout of [`CPTR_EL2`] and [`CPTR_EL3`] when `HCR_EL2.E2H == 0`.
772    #[bitrs(no_e2h)]
773    pub struct ArchitecturalFeatureTrapRegisterNoVhe(u64);
774
775    /// The layout of [`CPTR_EL2`] and [`CPTR_EL3`] when `HCR_EL2.E2H == 1` (FEAT_VHE).
776    #[bitrs(e2h)]
777    pub struct ArchitecturalFeatureTrapRegisterVhe(u64);
778
779    {
780        let __ @ 63..32;
781        let tcpac @ 31;
782        let tam @ 30;
783        let __ @ 29;
784        let __ @ 27..26;
785        let __ @ 23..22;
786        let __ @ 19..18;
787    }
788
789    #[e2h]
790    {
791        let tta @ 28;
792        let smen @ 25..24;
793        let fpen @ 21..20;
794        let zen @ 17..16;
795        let __ @ 15..0;
796    }
797
798    #[no_e2h]
799    {
800        let __ @ 28;
801        let __ @ 25..24;
802        let __ @ 21;
803        let tta @ 20;
804        let __ @ 17..14;
805        let __ @ 13 = 1;
806        let tsm @ 12;
807        let __ @ 11;
808        let tfp @ 10;
809        let __ @ 9 = 1;
810        let tz @ 8;
811        let __ @ 7..0;
812    }
813});
814
815/// [arm/sysreg]/hcr_el2: Hypervisor Configuration register (EL2)
816pub const HCR_EL2: SysReg<spec::HCR_EL2, HypervisorConfigurationRegister> = SysReg::new();
817
818layout!({
819    /// The layout of [`HCR_EL2`].
820    pub struct HypervisorConfigurationRegister(u64);
821    {
822        let twedel @ 63..60;
823        let tweden @ 59;
824        let tid5 @ 58;
825        let dct @ 57;
826        let ata @ 56;
827        let ttlbos @ 55;
828        let ttlbis @ 54;
829        let enscxt @ 53;
830        let tocu @ 52;
831        let amvoffen @ 51;
832        let ticab @ 50;
833        let tid4 @ 49;
834        let gpf @ 48;
835        let fien @ 47;
836        let fwb @ 46;
837        let nv2 @ 45;
838        let at @ 44;
839        let nv1 @ 43;
840        let nv @ 42;
841        let api @ 41;
842        let apk @ 40;
843        let tme @ 39;
844        let miocnce @ 38;
845        let tea @ 37;
846        let terr @ 36;
847        let tlor @ 35;
848        let e2h @ 34;
849        let id @ 33;
850        let cd @ 32;
851        let rw @ 31;
852        let trvm @ 30;
853        let hcd @ 29;
854        let tdz @ 28;
855        let tge @ 27;
856        let tvm @ 26;
857        let ttlb @ 25;
858        let tpu @ 24;
859        let tcpc @ 23;
860        let tsw @ 22;
861        let tacr @ 21;
862        let tidcp @ 20;
863        let tsc @ 19;
864        let tid3 @ 18;
865        let tid2 @ 17;
866        let tid1 @ 16;
867        let tid0 @ 15;
868        let twe @ 14;
869        let twi @ 13;
870        let dc @ 12;
871        let bsu @ 11..10;
872        let fb @ 9;
873        let vse @ 8;
874        let vi @ 7;
875        let vf @ 6;
876        let amo @ 5;
877        let imo @ 4;
878        let fmo @ 3;
879        let ptw @ 2;
880        let swio @ 1;
881        let vm @ 0;
882    }
883});
884
885/// [arm/sysreg]/hcrx_el2: Extended Hypervisor Configuration register (EL2)
886pub const HCRX_EL2: SysReg<spec::HCRX_EL2, ExtendedHypervisorConfigurationRegister> = SysReg::new();
887
888layout!({
889    /// The layout of [`HCRX_EL2`].
890    pub struct ExtendedHypervisorConfigurationRegister(u64);
891    {
892        let __ @ 63..27; // Safe "pass-through" value for no-op EL2.
893        let srmasken @ 26; // if FEAT_SRMASK
894        let __ @ 25;
895        let pacmen @ 24; // if FEAT_PAuth_LR
896        let enfpm @ 23; // if FEAT_FPMR
897        let gcsen @ 22; // if FEAT_GCS
898        let enidcp128 @ 21; // if FEAT_SYSREG128
899        let ensderr @ 20; // if FEAT_ADERR
900        let tmea @ 19; // if FEAT_DoubleFault2
901        let ensnerr @ 18; // if FEAT_ANERR
902        let d128en @ 17; // if FEAT_D128
903        let pttwi @ 16; // if FEAT_THE
904        let sctlr2en @ 15; // if FEAT_SCTLR2
905        let tcr2en @ 14; // if FEAT_TCR2
906        let __ @ 13..12;
907        let mscen @ 11; // if FEAT_MOPS
908        let mce2 @ 10; // if FEAT_MOPS
909        let cmow @ 9; // if CEAT_CMOW
910        let vfnmi @ 8; // if FEAT_NMI
911        let vinmi @ 7; // if FEAT_NMI
912        let tallint @ 6; // if FEAT_NMI
913        let smpme @ 5; // if FEAT_SME
914        let fgtnxs @ 4; // if FEAT_XS
915        let fnxs @ 3; // if FEAT_XS
916        let enasr @ 2; // if FEAT_LS64_V
917        let enals @ 1; // if FEAT_LS64
918        let enas0 @ 0; // if FEAT_LS64_ACCDATA
919    }
920});
921
922/// [arm/sysreg]/cnthctl_el2: Counter-timer Hypervisor Control register (EL2) when `HCR_EL2.E2H == 0`
923pub const CNTHCTL_EL2_NO_VHE: SysReg<
924    spec::CNTHCTL_EL2,
925    CounterTimerHypervisorControlRegisterNoVhe,
926> = SysReg::new();
927
928/// [arm/sysreg]/cnthctl_el2: Counter-timer Hypervisor Control register (EL2) when `HCR_EL2.E2H == 1` (FEAT_VHE)
929pub const CNTHCTL_EL2_VHE: SysReg<spec::CNTHCTL_EL2, CounterTimerHypervisorControlRegisterVhe> =
930    SysReg::new();
931
932multilayout!({
933    /// The layout of [`CNTHCTL_EL2`] when `HCR_EL2.E2H == 0`.
934    #[bitrs(no_e2h)]
935    pub struct CounterTimerHypervisorControlRegisterNoVhe(u64);
936
937    /// The layout of [`CNTHCTL_EL2`] when `HCR_EL2.E2H == 1` (FEAT_VHE).
938    #[bitrs(e2h)]
939    pub struct CounterTimerHypervisorControlRegisterVhe(u64);
940
941    {
942        let __ @ 63..20;
943        let cntpmask @ 19;
944        let cntvmask @ 18;
945        let evntis @ 17;
946        let el1nvvct @ 16;
947        let el1nvpct @ 15;
948        let el1tvct @ 14;
949        let el1tvt @ 13;
950        let ecv @ 12;
951        let evnti @ 7..4;
952        let evntdir @ 3;
953        let evnten @ 2;
954    }
955
956    #[e2h]
957    {
958        let el1pten @ 11;
959        let el1pcten @ 10;
960        let el0pten @ 9;
961        let el0vten @ 8;
962        let el0vcten @ 1;
963        let el0pcten @ 0;
964    }
965
966    #[no_e2h]
967    {
968        let __ @ 11..8;
969        let el1pcen @ 1;
970        let el1pcten @ 0;
971    }
972});
973
974/// [arm/sysreg]/icc_sre_el1: Interrupt Controller System Register Enable Register (EL1)
975pub const ICC_SRE_EL1: SysReg<spec::ICC_SRE_EL1, InterruptControllerSystemRegisterEnableRegister> =
976    SysReg::new();
977
978/// [arm/sysreg]/icc_sre_el2: Interrupt Controller System Register Enable Register (EL2)
979pub const ICC_SRE_EL2: SysReg<spec::ICC_SRE_EL2, InterruptControllerSystemRegisterEnableRegister> =
980    SysReg::new();
981
982/// [arm/sysreg]/icc_sre_el3: Interrupt Controller System Register Enable Register (EL3)
983pub const ICC_SRE_EL3: SysReg<spec::ICC_SRE_EL3, InterruptControllerSystemRegisterEnableRegister> =
984    SysReg::new();
985
986layout!({
987    /// The layout of [`ICC_SRE_EL1`], [`ICC_SRE_EL2`], and [`ICC_SRE_EL3`].
988    pub struct InterruptControllerSystemRegisterEnableRegister(u64);
989    {
990        let __ @ 63..4;
991        let enable @ 3;
992        let dib @ 2;
993        let dfb @ 1;
994        let sre @ 0;
995    }
996});
997
998#[cfg(test)]
999mod tests {
1000    use super::*;
1001
1002    #[test]
1003    fn multiprocessor_affinity() {
1004        let mpidr =
1005            *MultiprocessorAffinityRegister::new().set_aff0(1).set_aff1(2).set_aff2(3).set_aff3(4);
1006        assert_eq!(mpidr.affinity(), 0x04_0003_0201);
1007    }
1008}