1use core::arch::naked_asm;
8
9const MAIR_DEV_NGNRE: u64 = 0x04;
10const MAIR_MEM_WBWA: u64 = 0xff;
11pub const DEFAULT_MAIR: u64 = MAIR_DEV_NGNRE | MAIR_MEM_WBWA << 8;
13
14const TCR_TG1_4KB: u64 = 0x2 << 30;
16const TCR_EPD1: u64 = 0x1 << 23;
18const TCR_EL1_IPS_1TB: u64 = 0x2 << 32;
20const TCR_EL2_PS_1TB: u64 = 0x2 << 16;
22const TCR_TG0_4KB: u64 = 0x0 << 14;
24const TCR_SH_INNER: u64 = 0x3 << 12;
26const TCR_RGN_OWB: u64 = 0x1 << 10;
29const TCR_RGN_IWB: u64 = 0x1 << 8;
32const TCR_T0SZ_512: u64 = 64 - 39;
34pub const DEFAULT_TCR_EL1: u64 = TCR_EL1_IPS_1TB
36 | TCR_TG1_4KB
37 | TCR_EPD1
38 | TCR_TG0_4KB
39 | TCR_SH_INNER
40 | TCR_RGN_OWB
41 | TCR_RGN_IWB
42 | TCR_T0SZ_512;
43pub const DEFAULT_TCR_EL2: u64 =
45 TCR_EL2_PS_1TB | TCR_TG0_4KB | TCR_SH_INNER | TCR_RGN_OWB | TCR_RGN_IWB | TCR_T0SZ_512;
46pub const DEFAULT_TCR_EL3: u64 =
48 TCR_TG0_4KB | TCR_RGN_OWB | TCR_RGN_IWB | TCR_SH_INNER | TCR_T0SZ_512;
49
50const SCTLR_ELX_I: u64 = 0x1 << 12;
52const SCTLR_ELX_SA: u64 = 0x1 << 3;
54const SCTLR_ELX_C: u64 = 0x1 << 2;
56const SCTLR_ELX_M: u64 = 0x1 << 0;
58const SCTLR_ELX_SPAN: u64 = 0x1 << 23;
60const SCTLR_ELX_SED: u64 = 0x1 << 8;
62const SCTLR_ELX_ITD: u64 = 0x1 << 7;
64const SCTLR_ELX_RES1: u64 = (0x1 << 11) | (0x1 << 20) | (0x1 << 22) | (0x1 << 28) | (0x1 << 29);
65pub const DEFAULT_SCTLR: u64 = SCTLR_ELX_M
67 | SCTLR_ELX_C
68 | SCTLR_ELX_SA
69 | SCTLR_ELX_ITD
70 | SCTLR_ELX_SED
71 | SCTLR_ELX_I
72 | SCTLR_ELX_SPAN
73 | SCTLR_ELX_RES1;
74
75#[cfg(any(feature = "el1", feature = "el2", feature = "el3"))]
79#[macro_export]
80macro_rules! initial_pagetable {
81 ($value:expr, $mair:expr, $sctlr:expr, $tcr:expr) => {
82 static INITIAL_PAGETABLE: $crate::InitialPagetable = $value;
83
84 $crate::enable_mmu!(INITIAL_PAGETABLE, $mair, $sctlr, $tcr);
85 };
86 ($value:expr, $mair:expr) => {
87 $crate::initial_pagetable!($value, $mair, $crate::DEFAULT_SCTLR, $crate::DEFAULT_TCR);
88 };
89 ($value:expr) => {
90 $crate::initial_pagetable!(
91 $value,
92 $crate::DEFAULT_MAIR,
93 $crate::DEFAULT_SCTLR,
94 $crate::DEFAULT_TCR
95 );
96 };
97}
98
99#[cfg(not(any(feature = "el1", feature = "el2", feature = "el3")))]
103#[macro_export]
104macro_rules! initial_pagetable {
105 ($value:expr, $mair:expr, $sctlr:expr, $tcr_el1:expr, $tcr_el2:expr, $tcr_el3:expr) => {
106 static INITIAL_PAGETABLE: $crate::InitialPagetable = $value;
107
108 $crate::enable_mmu!(
109 INITIAL_PAGETABLE,
110 $mair,
111 $sctlr,
112 $tcr_el1,
113 $tcr_el2,
114 $tcr_el3
115 );
116 };
117 ($value:expr, $mair:expr) => {
118 initial_pagetable!(
119 $value,
120 $mair,
121 $crate::DEFAULT_SCTLR,
122 $crate::DEFAULT_TCR_EL1,
123 $crate::DEFAULT_TCR_EL2,
124 $crate::DEFAULT_TCR_EL3
125 );
126 };
127 ($value:expr) => {
128 initial_pagetable!(
129 $value,
130 $crate::DEFAULT_MAIR,
131 $crate::DEFAULT_SCTLR,
132 $crate::DEFAULT_TCR_EL1,
133 $crate::DEFAULT_TCR_EL2,
134 $crate::DEFAULT_TCR_EL3
135 );
136 };
137}
138
139#[doc(hidden)]
151#[unsafe(naked)]
152pub unsafe extern "C" fn __enable_mmu_el1() {
153 naked_asm!(
154 "msr mair_el1, x8",
157 "msr ttbr0_el1, x11",
158 "mrs x8, id_aa64mmfr0_el1",
160 "bfi x10, x8, #32, #4",
161 "msr tcr_el1, x10",
162 "isb",
165 "tlbi vmalle1",
166 "ic iallu",
167 "dsb nsh",
168 "isb",
169 "msr sctlr_el1, x9",
172 "isb",
173 "ret"
174 );
175}
176
177#[doc(hidden)]
189#[unsafe(naked)]
190pub unsafe extern "C" fn __enable_mmu_el2() {
191 naked_asm!(
192 "msr mair_el2, x8",
195 "msr ttbr0_el2, x11",
196 "mrs x8, id_aa64mmfr0_el1",
198 "bfi x10, x8, #32, #4",
199 "msr tcr_el2, x10",
200 "isb",
203 "tlbi vmalle1",
204 "ic iallu",
205 "dsb nsh",
206 "isb",
207 "msr sctlr_el2, x9",
210 "isb",
211 "ret"
212 );
213}
214
215#[doc(hidden)]
227#[unsafe(naked)]
228pub unsafe extern "C" fn __enable_mmu_el3() {
229 naked_asm!(
230 "msr mair_el3, x8",
233 "msr ttbr0_el3, x11",
234 "mrs x8, id_aa64mmfr0_el1",
236 "bfi x10, x8, #32, #4",
237 "msr tcr_el3, x10",
238 "isb",
241 "tlbi vmalle1",
242 "ic iallu",
243 "dsb nsh",
244 "isb",
245 "msr sctlr_el3, x9",
248 "isb",
249 "ret"
250 );
251}
252
253#[cfg(feature = "el1")]
258#[macro_export]
259macro_rules! enable_mmu {
260 ($pagetable:path, $mair:expr, $sctlr:expr, $tcr:expr) => {
261 core::arch::global_asm!(
262 r".macro mov_i, reg:req, imm:req",
263 r"movz \reg, :abs_g3:\imm",
264 r"movk \reg, :abs_g2_nc:\imm",
265 r"movk \reg, :abs_g1_nc:\imm",
266 r"movk \reg, :abs_g0_nc:\imm",
267 r".endm",
268
269 ".section .init, \"ax\"",
270 ".global enable_mmu",
271 "enable_mmu:",
272 "mov_i x8, {MAIR_VALUE}",
273 "mov_i x9 {SCTLR_VALUE}",
274 "mov_i x10, {TCR_VALUE}",
275 "adrp x11, {pagetable}",
276
277 "b {enable_mmu_el1}",
278
279 ".purgem mov_i",
280 MAIR_VALUE = const $mair,
281 SCTLR_VALUE = const $sctlr,
282 TCR_VALUE = const $tcr,
283 pagetable = sym $pagetable,
284 enable_mmu_el1 = sym $crate::__private::__enable_mmu_el1,
285 );
286 };
287 ($pagetable:path) => {
288 $crate::enable_mmu!($pagetable, $crate::DEFAULT_MAIR, $crate::DEFAULT_SCTLR, $crate::DEFAULT_TCR_EL1);
289 };
290}
291
292#[cfg(feature = "el2")]
297#[macro_export]
298macro_rules! enable_mmu {
299 ($pagetable:path, $mair:expr, $sctlr:expr, $tcr:expr) => {
300 core::arch::global_asm!(
301 r".macro mov_i, reg:req, imm:req",
302 r"movz \reg, :abs_g3:\imm",
303 r"movk \reg, :abs_g2_nc:\imm",
304 r"movk \reg, :abs_g1_nc:\imm",
305 r"movk \reg, :abs_g0_nc:\imm",
306 r".endm",
307
308 ".section .init, \"ax\"",
309 ".global enable_mmu",
310 "enable_mmu:",
311 "mov_i x8, {MAIR_VALUE}",
312 "mov_i x9, {SCTLR_VALUE}",
313 "mov_i x10, {TCR_VALUE}",
314 "adrp x11, {pagetable}",
315
316 "b {enable_mmu_el2}",
317
318 ".purgem mov_i",
319 MAIR_VALUE = const $mair,
320 SCTLR_VALUE = const $sctlr,
321 TCR_VALUE = const $tcr,
322 pagetable = sym $pagetable,
323 enable_mmu_el2 = sym $crate::__private::__enable_mmu_el2,
324 );
325 };
326 ($pagetable:path) => {
327 $crate::enable_mmu!($pagetable, $crate::DEFAULT_MAIR, $crate::DEFAULT_SCTLR, $crate::DEFAULT_TCR_EL2);
328 };
329}
330
331#[cfg(feature = "el3")]
336#[macro_export]
337macro_rules! enable_mmu {
338 ($pagetable:path, $mair:expr, $sctlr:expr, $tcr:expr) => {
339 core::arch::global_asm!(
340 r".macro mov_i, reg:req, imm:req",
341 r"movz \reg, :abs_g3:\imm",
342 r"movk \reg, :abs_g2_nc:\imm",
343 r"movk \reg, :abs_g1_nc:\imm",
344 r"movk \reg, :abs_g0_nc:\imm",
345 r".endm",
346
347 ".section .init, \"ax\"",
348 ".global enable_mmu",
349 "enable_mmu:",
350 "mov_i x8, {MAIR_VALUE}",
351 "mov_i x9, {SCTLR_VALUE}",
352 "mov_i x10, {TCR_VALUE}",
353 "adrp x11, {pagetable}",
354
355 "b {enable_mmu_el3}",
356
357 ".purgem mov_i",
358 MAIR_VALUE = const $mair,
359 SCTLR_VALUE = const $sctlr,
360 TCR_VALUE = const $tcr,
361 pagetable = sym $pagetable,
362 enable_mmu_el3 = sym $crate::__private::__enable_mmu_el3,
363 );
364 };
365 ($pagetable:path) => {
366 $crate::enable_mmu!($pagetable, $crate::DEFAULT_MAIR, $crate::DEFAULT_SCTLR, $crate::DEFAULT_TCR_EL3);
367 };
368}
369
370#[cfg(not(any(feature = "el1", feature = "el2", feature = "el3")))]
375#[macro_export]
376macro_rules! enable_mmu {
377 ($pagetable:path, $mair:expr, $sctlr:expr, $tcr_el1:expr, $tcr_el2:expr, $tcr_el3:expr) => {
378 core::arch::global_asm!(
379 r".macro mov_i, reg:req, imm:req",
380 r"movz \reg, :abs_g3:\imm",
381 r"movk \reg, :abs_g2_nc:\imm",
382 r"movk \reg, :abs_g1_nc:\imm",
383 r"movk \reg, :abs_g0_nc:\imm",
384 r".endm",
385
386 ".section .init, \"ax\"",
387 ".global enable_mmu",
388 "enable_mmu:",
389 "mov_i x8, {MAIR_VALUE}",
390 "mov_i x9, {SCTLR_VALUE}",
391 "adrp x11, {pagetable}",
392
393 "mrs x12, CurrentEL",
394 "ubfx x12, x12, #2, #2",
395
396 "cmp x12, #3",
397 "b.ne 0f",
398 "mov_i x10, {TCR_EL3_VALUE}",
399 "b {enable_mmu_el3}",
400 "0:",
401 "cmp x12, #2",
402 "b.ne 1f",
403 "mov_i x10, {TCR_EL2_VALUE}",
404 "b {enable_mmu_el2}",
405 "1:",
406 "mov_i x10, {TCR_EL1_VALUE}",
407 "b {enable_mmu_el1}",
408
409 ".purgem mov_i",
410 MAIR_VALUE = const $mair,
411 SCTLR_VALUE = const $sctlr,
412 TCR_EL1_VALUE = const $tcr_el1,
413 TCR_EL2_VALUE = const $tcr_el2,
414 TCR_EL3_VALUE = const $tcr_el3,
415 pagetable = sym $pagetable,
416 enable_mmu_el1 = sym $crate::__private::__enable_mmu_el1,
417 enable_mmu_el2 = sym $crate::__private::__enable_mmu_el2,
418 enable_mmu_el3 = sym $crate::__private::__enable_mmu_el3,
419 );
420 };
421 ($pagetable:path) => {
422 $crate::enable_mmu!(
423 $pagetable,
424 $crate::DEFAULT_MAIR,
425 $crate::DEFAULT_SCTLR,
426 $crate::DEFAULT_TCR_EL1,
427 $crate::DEFAULT_TCR_EL2,
428 $crate::DEFAULT_TCR_EL3
429 );
430 };
431}
432
433#[repr(C, align(4096))]
435pub struct InitialPagetable(pub [usize; 512]);