Skip to content

Commit 4dbb64a

Browse files
authored
Merge pull request #14 from google/pagetable
Move pagetable constants from assembly to Rust
2 parents 9ebbdc0 + fe9e78b commit 4dbb64a

File tree

6 files changed

+118
-164
lines changed

6 files changed

+118
-164
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## Unreleased
4+
5+
### Bugfixes
6+
7+
- Fixed build failure when `psci` feature was enabled without `exceptions` feature.
8+
39
## 0.2.0
410

511
### Breaking changes

src/el1_enable_mmu.S

Lines changed: 3 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -5,51 +5,6 @@
55
* See LICENSE-APACHE and LICENSE-MIT for details.
66
*/
77

8-
.set .L_MAIR_DEV_nGnRE, 0x04
9-
.set .L_MAIR_MEM_WBWA, 0xff
10-
.set .Lmairval, .L_MAIR_DEV_nGnRE | (.L_MAIR_MEM_WBWA << 8)
11-
12-
/* 4 KiB granule size for TTBR0_EL1. */
13-
.set .L_TCR_TG0_4KB, 0x0 << 14
14-
/* 4 KiB granule size for TTBR1_EL1. */
15-
.set .L_TCR_TG1_4KB, 0x2 << 30
16-
/* Disable translation table walk for TTBR1_EL1, generating a translation fault instead. */
17-
.set .L_TCR_EPD1, 0x1 << 23
18-
/* Translation table walks for TTBR0_EL1 are inner sharable. */
19-
.set .L_TCR_SH_INNER, 0x3 << 12
20-
/*
21-
* Translation table walks for TTBR0_EL1 are outer write-back read-allocate write-allocate
22-
* cacheable.
23-
*/
24-
.set .L_TCR_RGN_OWB, 0x1 << 10
25-
/*
26-
* Translation table walks for TTBR0_EL1 are inner write-back read-allocate write-allocate
27-
* cacheable.
28-
*/
29-
.set .L_TCR_RGN_IWB, 0x1 << 8
30-
/* Size offset for TTBR0_EL1 is 2**39 bytes (512 GiB). */
31-
.set .L_TCR_T0SZ_512, 64 - 39
32-
.set .Ltcrval, .L_TCR_TG0_4KB | .L_TCR_TG1_4KB | .L_TCR_EPD1 | .L_TCR_RGN_OWB
33-
.set .Ltcrval, .Ltcrval | .L_TCR_RGN_IWB | .L_TCR_SH_INNER | .L_TCR_T0SZ_512
34-
35-
/* Stage 1 instruction access cacheability is unaffected. */
36-
.set .L_SCTLR_ELx_I, 0x1 << 12
37-
/* SP alignment fault if SP is not aligned to a 16 byte boundary. */
38-
.set .L_SCTLR_ELx_SA, 0x1 << 3
39-
/* Stage 1 data access cacheability is unaffected. */
40-
.set .L_SCTLR_ELx_C, 0x1 << 2
41-
/* EL0 and EL1 stage 1 MMU enabled. */
42-
.set .L_SCTLR_ELx_M, 0x1 << 0
43-
/* Privileged Access Never is unchanged on taking an exception to EL1. */
44-
.set .L_SCTLR_EL1_SPAN, 0x1 << 23
45-
/* SETEND instruction disabled at EL0 in aarch32 mode. */
46-
.set .L_SCTLR_EL1_SED, 0x1 << 8
47-
/* Various IT instructions are disabled at EL0 in aarch32 mode. */
48-
.set .L_SCTLR_EL1_ITD, 0x1 << 7
49-
.set .L_SCTLR_EL1_RES1, (0x1 << 11) | (0x1 << 20) | (0x1 << 22) | (0x1 << 28) | (0x1 << 29)
50-
.set .Lsctlrval, .L_SCTLR_ELx_M | .L_SCTLR_ELx_C | .L_SCTLR_ELx_SA | .L_SCTLR_EL1_ITD | .L_SCTLR_EL1_SED
51-
.set .Lsctlrval, .Lsctlrval | .L_SCTLR_ELx_I | .L_SCTLR_EL1_SPAN | .L_SCTLR_EL1_RES1
52-
538
.macro mov_i, reg:req, imm:req
549
movz \reg, :abs_g3:\imm
5510
movk \reg, :abs_g2_nc:\imm
@@ -67,17 +22,17 @@ enable_mmu:
6722
adrp x28, initial_pagetable
6823
msr ttbr0_el1, x28
6924

70-
mov_i x28, .Lmairval
25+
mov_i x28, {MAIR_VALUE}
7126
msr mair_el1, x28
7227

73-
mov_i x28, .Ltcrval
28+
mov_i x28, {TCR_VALUE}
7429
/* Copy the supported PA range into TCR_EL1.IPS. */
7530
mrs x29, id_aa64mmfr0_el1
7631
bfi x28, x29, #32, #4
7732

7833
msr tcr_el1, x28
7934

80-
mov_i x28, .Lsctlrval
35+
mov_i x28, {SCTLR_VALUE}
8136

8237
/*
8338
* Ensure everything before this point has completed, then invalidate any

src/el2_enable_mmu.S

Lines changed: 3 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -5,51 +5,6 @@
55
* See LICENSE-APACHE and LICENSE-MIT for details.
66
*/
77

8-
.set .L_MAIR_DEV_nGnRE, 0x04
9-
.set .L_MAIR_MEM_WBWA, 0xff
10-
.set .Lmairval, .L_MAIR_DEV_nGnRE | (.L_MAIR_MEM_WBWA << 8)
11-
12-
/* 4 KiB granule size for TTBR0_EL2. */
13-
.set .L_TCR_TG0_4KB, 0x0 << 14
14-
/* 4 KiB granule size for TTBR1_EL2. */
15-
.set .L_TCR_TG1_4KB, 0x2 << 30
16-
/* Disable translation table walk for TTBR1_EL2, generating a translation fault instead. */
17-
.set .L_TCR_EPD1, 0x1 << 23
18-
/* Translation table walks for TTBR0_EL2 are inner sharable. */
19-
.set .L_TCR_SH_INNER, 0x3 << 12
20-
/*
21-
* Translation table walks for TTBR0_EL2 are outer write-back read-allocate write-allocate
22-
* cacheable.
23-
*/
24-
.set .L_TCR_RGN_OWB, 0x1 << 10
25-
/*
26-
* Translation table walks for TTBR0_EL2 are inner write-back read-allocate write-allocate
27-
* cacheable.
28-
*/
29-
.set .L_TCR_RGN_IWB, 0x1 << 8
30-
/* Size offset for TTBR0_EL2 is 2**39 bytes (512 GiB). */
31-
.set .L_TCR_T0SZ_512, 64 - 39
32-
.set .Ltcrval, .L_TCR_TG0_4KB | .L_TCR_TG1_4KB | .L_TCR_EPD1 | .L_TCR_RGN_OWB
33-
.set .Ltcrval, .Ltcrval | .L_TCR_RGN_IWB | .L_TCR_SH_INNER | .L_TCR_T0SZ_512
34-
35-
/* Stage 1 instruction access cacheability is unaffected. */
36-
.set .L_SCTLR_ELx_I, 0x1 << 12
37-
/* SP alignment fault if SP is not aligned to a 16 byte boundary. */
38-
.set .L_SCTLR_ELx_SA, 0x1 << 3
39-
/* Stage 1 data access cacheability is unaffected. */
40-
.set .L_SCTLR_ELx_C, 0x1 << 2
41-
/* EL0 and EL1 stage 1 MMU enabled. */
42-
.set .L_SCTLR_ELx_M, 0x1 << 0
43-
/* Privileged Access Never is unchanged on taking an exception to EL2. */
44-
.set .L_SCTLR_EL2_SPAN, 0x1 << 23
45-
/* SETEND instruction disabled at EL0 in aarch32 mode. */
46-
.set .L_SCTLR_EL2_SED, 0x1 << 8
47-
/* Various IT instructions are disabled at EL0 in aarch32 mode. */
48-
.set .L_SCTLR_EL2_ITD, 0x1 << 7
49-
.set .L_SCTLR_EL2_RES1, (0x1 << 11) | (0x1 << 20) | (0x1 << 22) | (0x1 << 28) | (0x1 << 29)
50-
.set .Lsctlrval, .L_SCTLR_ELx_M | .L_SCTLR_ELx_C | .L_SCTLR_ELx_SA | .L_SCTLR_EL2_ITD | .L_SCTLR_EL2_SED
51-
.set .Lsctlrval, .Lsctlrval | .L_SCTLR_ELx_I | .L_SCTLR_EL2_SPAN | .L_SCTLR_EL2_RES1
52-
538
.macro mov_i, reg:req, imm:req
549
movz \reg, :abs_g3:\imm
5510
movk \reg, :abs_g2_nc:\imm
@@ -67,17 +22,17 @@ enable_mmu:
6722
adrp x28, initial_pagetable
6823
msr ttbr0_el2, x28
6924

70-
mov_i x28, .Lmairval
25+
mov_i x28, {MAIR_VALUE}
7126
msr mair_el2, x28
7227

73-
mov_i x28, .Ltcrval
28+
mov_i x28, {TCR_VALUE}
7429
/* Copy the supported PA range into TCR_EL2.IPS. */
7530
mrs x29, id_aa64mmfr0_el1
7631
bfi x28, x29, #32, #4
7732

7833
msr tcr_el2, x28
7934

80-
mov_i x28, .Lsctlrval
35+
mov_i x28, {SCTLR_VALUE}
8136

8237
/*
8338
* Ensure everything before this point has completed, then invalidate any

src/el3_enable_mmu.S

Lines changed: 3 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -5,47 +5,6 @@
55
* See LICENSE-APACHE and LICENSE-MIT for details.
66
*/
77

8-
.set .L_MAIR_DEV_nGnRE, 0x04
9-
.set .L_MAIR_MEM_WBWA, 0xff
10-
.set .Lmairval, .L_MAIR_DEV_nGnRE | (.L_MAIR_MEM_WBWA << 8)
11-
12-
/* 4 KiB granule size for TTBR0_EL3. */
13-
.set .L_TCR_TG0_4KB, 0x0 << 14
14-
/* Translation table walks for TTBR0_EL3 are inner sharable. */
15-
.set .L_TCR_SH_INNER, 0x3 << 12
16-
/*
17-
* Translation table walks for TTBR0_EL3 are outer write-back read-allocate write-allocate
18-
* cacheable.
19-
*/
20-
.set .L_TCR_RGN_OWB, 0x1 << 10
21-
/*
22-
* Translation table walks for TTBR0_EL3 are inner write-back read-allocate write-allocate
23-
* cacheable.
24-
*/
25-
.set .L_TCR_RGN_IWB, 0x1 << 8
26-
/* Size offset for TTBR0_EL3 is 2**39 bytes (512 GiB). */
27-
.set .L_TCR_T0SZ_512, 64 - 39
28-
.set .Ltcrval, .L_TCR_TG0_4KB | .L_TCR_RGN_OWB
29-
.set .Ltcrval, .Ltcrval | .L_TCR_RGN_IWB | .L_TCR_SH_INNER | .L_TCR_T0SZ_512
30-
31-
/* Stage 1 instruction access cacheability is unaffected. */
32-
.set .L_SCTLR_ELx_I, 0x1 << 12
33-
/* SP alignment fault if SP is not aligned to a 16 byte boundary. */
34-
.set .L_SCTLR_ELx_SA, 0x1 << 3
35-
/* Stage 1 data access cacheability is unaffected. */
36-
.set .L_SCTLR_ELx_C, 0x1 << 2
37-
/* EL0 and EL1 stage 1 MMU enabled. */
38-
.set .L_SCTLR_ELx_M, 0x1 << 0
39-
/* Privileged Access Never is unchanged on taking an exception to EL3. */
40-
.set .L_SCTLR_EL3_SPAN, 0x1 << 23
41-
/* SETEND instruction disabled at EL0 in aarch32 mode. */
42-
.set .L_SCTLR_EL3_SED, 0x1 << 8
43-
/* Various IT instructions are disabled at EL0 in aarch32 mode. */
44-
.set .L_SCTLR_EL3_ITD, 0x1 << 7
45-
.set .L_SCTLR_EL3_RES1, (0x1 << 11) | (0x1 << 20) | (0x1 << 22) | (0x1 << 28) | (0x1 << 29)
46-
.set .Lsctlrval, .L_SCTLR_ELx_M | .L_SCTLR_ELx_C | .L_SCTLR_ELx_SA | .L_SCTLR_EL3_ITD | .L_SCTLR_EL3_SED
47-
.set .Lsctlrval, .Lsctlrval | .L_SCTLR_ELx_I | .L_SCTLR_EL3_SPAN | .L_SCTLR_EL3_RES1
48-
498
.macro mov_i, reg:req, imm:req
509
movz \reg, :abs_g3:\imm
5110
movk \reg, :abs_g2_nc:\imm
@@ -63,17 +22,17 @@ enable_mmu:
6322
adrp x28, initial_pagetable
6423
msr ttbr0_el3, x28
6524

66-
mov_i x28, .Lmairval
25+
mov_i x28, {MAIR_VALUE}
6726
msr mair_el3, x28
6827

69-
mov_i x28, .Ltcrval
28+
mov_i x28, {TCR_VALUE}
7029
/* Copy the supported PA range into TCR_EL3.IPS. */
7130
mrs x29, id_aa64mmfr0_el1
7231
bfi x28, x29, #32, #4
7332

7433
msr tcr_el3, x28
7534

76-
mov_i x28, .Lsctlrval
35+
mov_i x28, {SCTLR_VALUE}
7736

7837
/*
7938
* Ensure everything before this point has completed, then invalidate any

src/lib.rs

Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,19 @@
1515
))]
1616
compile_error!("Only one `el` feature may be enabled at once.");
1717

18-
#[cfg(feature = "exceptions")]
18+
#[cfg(feature = "initial-pagetable")]
19+
mod pagetable;
20+
21+
#[cfg(any(feature = "exceptions", feature = "psci"))]
1922
use core::arch::asm;
2023
use core::arch::global_asm;
24+
#[cfg(feature = "initial-pagetable")]
25+
pub use pagetable::InitialPagetable;
2126

2227
global_asm!(include_str!("entry.S"));
2328

2429
#[cfg(not(feature = "initial-pagetable"))]
2530
global_asm!(include_str!("dummy_enable_mmu.S"),);
26-
#[cfg(all(feature = "el1", feature = "initial-pagetable"))]
27-
global_asm!(include_str!("el1_enable_mmu.S"),);
28-
#[cfg(all(feature = "el2", feature = "initial-pagetable"))]
29-
global_asm!(include_str!("el2_enable_mmu.S"));
30-
#[cfg(all(feature = "el3", feature = "initial-pagetable"))]
31-
global_asm!(include_str!("el3_enable_mmu.S"));
3231

3332
#[cfg(feature = "exceptions")]
3433
global_asm!(include_str!("exceptions.S"));
@@ -124,23 +123,6 @@ macro_rules! entry {
124123
};
125124
}
126125

127-
/// Provides an initial pagetable which can be used before any Rust code is run.
128-
///
129-
/// The `initial-pagetable` feature must be enabled for this to be used.
130-
#[cfg(feature = "initial-pagetable")]
131-
#[macro_export]
132-
macro_rules! initial_pagetable {
133-
($value:expr) => {
134-
#[unsafe(export_name = "initial_pagetable")]
135-
#[unsafe(link_section = ".rodata.initial_pagetable")]
136-
static INITIAL_PAGETABLE: $crate::InitialPagetable = $value;
137-
};
138-
}
139-
140-
/// A hardcoded pagetable.
141-
#[repr(C, align(4096))]
142-
pub struct InitialPagetable(pub [usize; 512]);
143-
144126
/// A stack for some CPU core.
145127
///
146128
/// This is used by the [`entry!`] macro to reserve space for the boot stack.

src/pagetable.rs

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
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+
7+
use core::arch::global_asm;
8+
9+
const MAIR_DEV_NGNRE: u64 = 0x04;
10+
const MAIR_MEM_WBWA: u64 = 0xff;
11+
const MAIR_VALUE: u64 = MAIR_DEV_NGNRE | MAIR_MEM_WBWA << 8;
12+
13+
/// 4 KiB granule size for TTBR0_ELx.
14+
const TCR_TG0_4KB: u64 = 0x0 << 14;
15+
/// 4 KiB granule size for TTBR1_ELx.
16+
#[cfg(not(feature = "el3"))]
17+
const TCR_TG1_4KB: u64 = 0x2 << 30;
18+
/// Disable translation table walk for TTBR1_ELx, generating a translation fault instead.
19+
#[cfg(not(feature = "el3"))]
20+
const TCR_EPD1: u64 = 0x1 << 23;
21+
/// Translation table walks for TTBR0_ELx are inner sharable.
22+
const TCR_SH_INNER: u64 = 0x3 << 12;
23+
/// Translation table walks for TTBR0_ELx are outer write-back read-allocate write-allocate
24+
/// cacheable.
25+
const TCR_RGN_OWB: u64 = 0x1 << 10;
26+
/// Translation table walks for TTBR0_ELx are inner write-back read-allocate write-allocate
27+
/// cacheable.
28+
const TCR_RGN_IWB: u64 = 0x1 << 8;
29+
/// Size offset for TTBR0_ELx is 2**39 bytes (512 GiB).
30+
const TCR_T0SZ_512: u64 = 64 - 39;
31+
#[cfg(not(feature = "el3"))]
32+
const 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")]
35+
const 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.
38+
const SCTLR_ELX_I: u64 = 0x1 << 12;
39+
/// SP alignment fault if SP is not aligned to a 16 byte boundary.
40+
const SCTLR_ELX_SA: u64 = 0x1 << 3;
41+
/// Stage 1 data access cacheability is unaffected.
42+
const SCTLR_ELX_C: u64 = 0x1 << 2;
43+
/// EL0 and EL1 stage 1 MMU enabled.
44+
const SCTLR_ELX_M: u64 = 0x1 << 0;
45+
/// Privileged Access Never is unchanged on taking an exception to ELx.
46+
const SCTLR_ELX_SPAN: u64 = 0x1 << 23;
47+
/// SETEND instruction disabled at EL0 in aarch32 mode.
48+
const SCTLR_ELX_SED: u64 = 0x1 << 8;
49+
/// Various IT instructions are disabled at EL0 in aarch32 mode.
50+
const SCTLR_ELX_ITD: u64 = 0x1 << 7;
51+
const SCTLR_ELX_RES1: u64 = (0x1 << 11) | (0x1 << 20) | (0x1 << 22) | (0x1 << 28) | (0x1 << 29);
52+
const 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")]
62+
global_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")]
69+
global_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")]
76+
global_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]
87+
macro_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))]
97+
pub struct InitialPagetable(pub [usize; 512]);

0 commit comments

Comments
 (0)