aarch64_rt/
pagetable.rs

1// Copyright 2025 The aarch64-rt Authors.
2// This project is dual-licensed under Apache 2.0 and MIT terms.
3// See LICENSE-APACHE and LICENSE-MIT for details.
4
5//! Code to set up an initial pagetable.
6
7use core::arch::global_asm;
8
9const MAIR_DEV_NGNRE: u64 = 0x04;
10const MAIR_MEM_WBWA: u64 = 0xff;
11const MAIR_VALUE: u64 = MAIR_DEV_NGNRE | MAIR_MEM_WBWA << 8;
12
13/// 4 KiB granule size for TTBR0_ELx.
14const TCR_TG0_4KB: u64 = 0x0 << 14;
15/// 4 KiB granule size for TTBR1_ELx.
16#[cfg(not(feature = "el3"))]
17const TCR_TG1_4KB: u64 = 0x2 << 30;
18/// Disable translation table walk for TTBR1_ELx, generating a translation fault instead.
19#[cfg(not(feature = "el3"))]
20const TCR_EPD1: u64 = 0x1 << 23;
21/// Translation table walks for TTBR0_ELx are inner sharable.
22const TCR_SH_INNER: u64 = 0x3 << 12;
23/// Translation table walks for TTBR0_ELx are outer write-back read-allocate write-allocate
24/// cacheable.
25const TCR_RGN_OWB: u64 = 0x1 << 10;
26/// Translation table walks for TTBR0_ELx are inner write-back read-allocate write-allocate
27/// cacheable.
28const TCR_RGN_IWB: u64 = 0x1 << 8;
29/// Size offset for TTBR0_ELx is 2**39 bytes (512 GiB).
30const TCR_T0SZ_512: u64 = 64 - 39;
31#[cfg(not(feature = "el3"))]
32const TCR_VALUE: u64 =
33    TCR_TG0_4KB | TCR_TG1_4KB | TCR_EPD1 | TCR_RGN_OWB | TCR_RGN_IWB | TCR_SH_INNER | TCR_T0SZ_512;
34#[cfg(feature = "el3")]
35const TCR_VALUE_EL3: u64 = TCR_TG0_4KB | TCR_RGN_OWB | TCR_RGN_IWB | TCR_SH_INNER | TCR_T0SZ_512;
36
37/// Stage 1 instruction access cacheability is unaffected.
38const SCTLR_ELX_I: u64 = 0x1 << 12;
39/// SP alignment fault if SP is not aligned to a 16 byte boundary.
40const SCTLR_ELX_SA: u64 = 0x1 << 3;
41/// Stage 1 data access cacheability is unaffected.
42const SCTLR_ELX_C: u64 = 0x1 << 2;
43/// EL0 and EL1 stage 1 MMU enabled.
44const SCTLR_ELX_M: u64 = 0x1 << 0;
45/// Privileged Access Never is unchanged on taking an exception to ELx.
46const SCTLR_ELX_SPAN: u64 = 0x1 << 23;
47/// SETEND instruction disabled at EL0 in aarch32 mode.
48const SCTLR_ELX_SED: u64 = 0x1 << 8;
49/// Various IT instructions are disabled at EL0 in aarch32 mode.
50const SCTLR_ELX_ITD: u64 = 0x1 << 7;
51const SCTLR_ELX_RES1: u64 = (0x1 << 11) | (0x1 << 20) | (0x1 << 22) | (0x1 << 28) | (0x1 << 29);
52const SCTLR_VALUE: u64 = SCTLR_ELX_M
53    | SCTLR_ELX_C
54    | SCTLR_ELX_SA
55    | SCTLR_ELX_ITD
56    | SCTLR_ELX_SED
57    | SCTLR_ELX_I
58    | SCTLR_ELX_SPAN
59    | SCTLR_ELX_RES1;
60
61#[cfg(feature = "el1")]
62global_asm!(
63    include_str!("el1_enable_mmu.S"),
64    MAIR_VALUE = const MAIR_VALUE,
65    TCR_VALUE = const TCR_VALUE,
66    SCTLR_VALUE = const SCTLR_VALUE,
67);
68#[cfg(feature = "el2")]
69global_asm!(
70    include_str!("el2_enable_mmu.S"),
71    MAIR_VALUE = const MAIR_VALUE,
72    TCR_VALUE = const TCR_VALUE,
73    SCTLR_VALUE = const SCTLR_VALUE,
74);
75#[cfg(feature = "el3")]
76global_asm!(
77    include_str!("el3_enable_mmu.S"),
78    MAIR_VALUE = const MAIR_VALUE,
79    TCR_VALUE = const TCR_VALUE_EL3,
80    SCTLR_VALUE = const SCTLR_VALUE,
81);
82
83/// Provides an initial pagetable which can be used before any Rust code is run.
84///
85/// The `initial-pagetable` feature must be enabled for this to be used.
86#[macro_export]
87macro_rules! initial_pagetable {
88    ($value:expr) => {
89        #[unsafe(export_name = "initial_pagetable")]
90        #[unsafe(link_section = ".rodata.initial_pagetable")]
91        static INITIAL_PAGETABLE: $crate::InitialPagetable = $value;
92    };
93}
94
95/// A hardcoded pagetable.
96#[repr(C, align(4096))]
97pub struct InitialPagetable(pub [usize; 512]);