Skip to content

Commit da55ff9

Browse files
authored
Support detecting exception level at runtime (#26)
* set_exception_vector and rust_entry can be mangled. They aren't referred to directly in any assembly code. * Factor out separate functions to enable the MMU at each EL. These are public, so users of the crate can call them directly if needed. * Detect EL at runtime for enable_mmu if no elX feature specified. * Detect current EL for setting exception vector too. * Hide functions to enable MMU. They need to be public because the macro calls them, but they shouldn't be called directly. * Move private public symbols to __private submodule. * Use Rust code to switch on exception level for vector table.
2 parents 873b80d + 51720a0 commit da55ff9

File tree

5 files changed

+239
-89
lines changed

5 files changed

+239
-89
lines changed

CHANGELOG.md

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

3+
## Unreleased
4+
5+
### Improvements
6+
7+
- If the `initial-pagetable` or `exceptions` features are specified without any of the `elX`
8+
features, then the exception level will be checked at runtime and the appropriate registers for
9+
the current EL will be used. The `el1` feature is no longer enabled by default, as this runtime
10+
detection should work instead.
11+
12+
### Bugfixes
13+
14+
- Stopped exposing unmangled symbols for `set_exception_vector` and `rust_entry`.
15+
316
## 0.2.2
417

518
### Improvements

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ arm-pl011-uart = "0.4.0"
1919
smccc = "0.2.2"
2020

2121
[features]
22-
default = ["el1", "exceptions", "initial-pagetable", "psci"]
22+
default = ["exceptions", "initial-pagetable", "psci"]
2323
el1 = []
2424
el2 = []
2525
el3 = []

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ fn main() {
4646

4747
## Features
4848

49-
`el1`, `exceptions`, `initial-pagetable` and `psci` are enabled by default.
49+
`exceptions`, `initial-pagetable` and `psci` are enabled by default.
5050

5151
### `el1`
5252

@@ -115,6 +115,10 @@ while the hypervisor or host has cacheable aliases to the same memory can lead t
115115
issues. Even if the host doesn't explicitly access the memory, speculative accesses can lead to
116116
cache fills.
117117

118+
This may be combined with one of the `elX` features to set up the page table for that exception
119+
level. If not, the exception level will be checked at runtime and the corresponding system registers
120+
used.
121+
118122
### `psci`
119123

120124
Adds the `start_core` function to start another CPU core via a PSCI `CPU_ON` call. This adds a

src/lib.rs

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ mod entry;
1919
#[cfg(feature = "initial-pagetable")]
2020
mod pagetable;
2121

22+
#[cfg(feature = "initial-pagetable")]
23+
#[doc(hidden)]
24+
pub mod __private {
25+
pub use crate::pagetable::{__enable_mmu_el1, __enable_mmu_el2, __enable_mmu_el3};
26+
}
27+
2228
#[cfg(any(feature = "exceptions", feature = "psci"))]
2329
use core::arch::asm;
2430
#[cfg(feature = "exceptions")]
@@ -42,7 +48,6 @@ global_asm!(include_str!("exceptions.S"));
4248

4349
/// Sets the appropriate vbar to point to our `vector_table`, if the `exceptions` feature is
4450
/// enabled.
45-
#[unsafe(no_mangle)]
4651
extern "C" fn set_exception_vector() {
4752
// SAFETY: We provide a valid vector table.
4853
#[cfg(all(feature = "el1", feature = "exceptions"))]
@@ -74,9 +79,55 @@ extern "C" fn set_exception_vector() {
7479
out("x9") _,
7580
);
7681
}
82+
#[cfg(all(
83+
feature = "exceptions",
84+
not(any(feature = "el1", feature = "el2", feature = "el3"))
85+
))]
86+
{
87+
let current_el: u64;
88+
// SAFETY: Reading CurrentEL is always safe.
89+
unsafe {
90+
asm!(
91+
"mrs {current_el}, CurrentEL",
92+
options(nomem, nostack, preserves_flags),
93+
current_el = out(reg) current_el,
94+
);
95+
}
96+
match (current_el >> 2) & 0b11 {
97+
// SAFETY: We provide a valid vector table.
98+
1 => unsafe {
99+
asm!(
100+
"adr x9, vector_table_el1",
101+
"msr vbar_el1, x9",
102+
options(nomem, nostack, preserves_flags),
103+
out("x9") _,
104+
);
105+
},
106+
// SAFETY: We provide a valid vector table.
107+
2 => unsafe {
108+
asm!(
109+
"adr x9, vector_table_el2",
110+
"msr vbar_el2, x9",
111+
options(nomem, nostack, preserves_flags),
112+
out("x9") _,
113+
);
114+
},
115+
// SAFETY: We provide a valid vector table.
116+
3 => unsafe {
117+
asm!(
118+
"adr x9, vector_table_el3",
119+
"msr vbar_el3, x9",
120+
options(nomem, nostack, preserves_flags),
121+
out("x9") _,
122+
);
123+
},
124+
_ => {
125+
panic!("Unexpected EL");
126+
}
127+
}
128+
}
77129
}
78130

79-
#[unsafe(no_mangle)]
80131
extern "C" fn rust_entry(arg0: u64, arg1: u64, arg2: u64, arg3: u64) -> ! {
81132
set_exception_vector();
82133
__main(arg0, arg1, arg2, arg3)

0 commit comments

Comments
 (0)