Skip to content

Commit 4ede863

Browse files
committed
Support booting the kernel in EL1 with a PSCI proxy
1 parent 738f4d1 commit 4ede863

File tree

10 files changed

+618
-17
lines changed

10 files changed

+618
-17
lines changed

Cargo.lock

Lines changed: 40 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,19 @@ aarch64-paging = { version = "0.10", default-features = false }
1414
aarch64-rt = { version = "0.3", features = ["el2", "exceptions", "initial-pagetable", "psci"], default-features = false }
1515
arm-pl011-uart = "0.4"
1616
buddy_system_allocator = { version = "0.11", default-features = false, features = ["alloc", "use_spin"] }
17+
# TODO: replace with a crates.io version when it's released
18+
dtoolkit = { version = "0.1", git = "ssh://git@github.com/google/dtoolkit.git", rev = "35c8644de5fd2ff0098cfd8e493a8cffc163cf04", features = ["write"] }
1719
embedded-io = "0.7"
1820
log = "0.4"
1921
percore = "0.2"
2022
safe-mmio = "0.2"
2123
smccc = "0.2"
2224
spin = { version = "0.10", features = ["lazy", "once", "spin_mutex"], default-features = false }
2325

26+
[patch.crates-io]
27+
# TODO: replace with a crates.io version when this is merged: https://github.com/google/aarch64-rt/pull/31
28+
aarch64-rt = { git = "https://github.com/m4tx/aarch64-rt.git", rev = "a93fdb00baa88549c7e9c90a4dd1c66b164844bf" }
29+
2430
[lints.rust]
2531
deprecated-safe = "warn"
2632
keyword-idents = "warn"

linker/qemu.ld

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,19 @@
11
MEMORY
22
{
3-
image : ORIGIN = 0x40080000, LENGTH = 64M
3+
image : ORIGIN = 0x40080000, LENGTH = 4M
4+
heap (rw) : ORIGIN = 0x40400000, LENGTH = 4M
5+
payload (rwx) : ORIGIN = 0x40800000, LENGTH = 64M
46
}
7+
8+
SECTIONS {
9+
.heap :
10+
{
11+
*(.heap);
12+
. = ALIGN(4);
13+
} > heap
14+
.payload :
15+
{
16+
*(.payload);
17+
. = ALIGN(4);
18+
} > payload
19+
} INSERT AFTER .text;

src/arch.rs

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,32 @@ pub fn tlbi_alle2is() {
5050
}
5151
}
5252

53+
/// Get the current stack pointer.
54+
pub fn sp() -> u64 {
55+
let val: u64;
56+
// SAFETY: Reading from the sp register is always safe.
57+
unsafe { asm!("mov {}, sp", out(reg) val, options(nostack)) };
58+
val
59+
}
60+
61+
pub fn esr() -> u64 {
62+
let mut esr: u64;
63+
// SAFETY: Reading esr is always safe.
64+
unsafe {
65+
asm!("mrs {esr}, esr_el2", esr = out(reg) esr);
66+
}
67+
esr
68+
}
69+
70+
pub fn far() -> u64 {
71+
let mut far: u64;
72+
// SAFETY: Reading far is always safe.
73+
unsafe {
74+
asm!("mrs {far}, far_el2", far = out(reg) far);
75+
}
76+
far
77+
}
78+
5379
macro_rules! sys_reg {
5480
($name:ident, {$($const_name:ident: $const_val:expr),*}) => {
5581
pub mod $name {
@@ -109,10 +135,20 @@ sys_reg!(sctlr_el2, {
109135
sys_reg!(clidr_el1);
110136
sys_reg!(csselr_el1);
111137
sys_reg!(ccsidr_el1);
112-
sys_reg!(hcr_el2);
138+
sys_reg!(hcr_el2, {
139+
RW: 1 << 31,
140+
TID1: 1 << 19,
141+
AMO: 1 << 4
142+
});
113143
sys_reg!(cntvoff_el2);
114-
sys_reg!(cnthctl_el2);
115-
sys_reg!(spsr_el2);
144+
sys_reg!(cnthctl_el2, {
145+
ENABLE: 1 << 0,
146+
IMASK: 1 << 1
147+
});
148+
sys_reg!(spsr_el2, {
149+
MASK_ALL: 0b1111 << 6,
150+
EL1H: 5
151+
});
116152
sys_reg!(elr_el2);
117153
sys_reg!(sp_el1);
118154

src/exceptions.rs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
// option. This file may not be copied, modified, or distributed
77
// except according to those terms.
88

9+
use core::arch::naked_asm;
10+
911
#[unsafe(no_mangle)]
1012
extern "C" fn sync_exception_current(_elr: u64, _spsr: u64) {
1113
panic!("Unexpected sync_exception_current");
@@ -26,9 +28,34 @@ extern "C" fn serr_current(_elr: u64, _spsr: u64) {
2628
panic!("Unexpected serr_current");
2729
}
2830

31+
#[unsafe(naked)]
2932
#[unsafe(no_mangle)]
30-
extern "C" fn sync_lower(_elr: u64, _spsr: u64) {
31-
panic!("Unexpected sync_lower");
33+
#[rustfmt::skip]
34+
unsafe extern "C" fn sync_lower() {
35+
naked_asm!(
36+
// We load and store the registers from/to where aarch64 exception handler expects them:
37+
// https://github.com/google/aarch64-rt/blob/047f3b0962064d334f149fe5fcd46ba57ea758ab/src/exceptions.S#L16-L65
38+
"stp x29, x30, [sp, #-0x10]!",
39+
40+
"ldp x2, x3, [sp, #0x10]",
41+
"ldp x4, x5, [sp, #0x20]",
42+
43+
"bl {sync_lower_impl}",
44+
45+
"mov x1, xzr",
46+
"mov x2, xzr",
47+
"mov x3, xzr",
48+
"stp x0, x1, [sp, #0x10]",
49+
"stp x2, x3, [sp, #0x20]",
50+
"ldr x4, [sp, #8 * 22 + 16]",
51+
// Return after the HVC call
52+
"add x4, x4, #4",
53+
"str x4, [sp, #8 * 22 + 16]",
54+
55+
"ldp x29, x30, [sp], #0x10",
56+
"ret",
57+
sync_lower_impl = sym crate::hypervisor::sync_lower_impl,
58+
)
3259
}
3360

3461
#[unsafe(no_mangle)]

0 commit comments

Comments
 (0)