Skip to content

Commit c6f304f

Browse files
Copilotguoweikang
andauthored
kbootloader/aarch64: replace broken PIE loader with self-contained Rynux-style boot (#45)
* Initial plan * Refactor kbootloader: implement Rynux-style PIE kernel boot for AArch64 Co-authored-by: guoweikang <18571063+guoweikang@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: guoweikang <18571063+guoweikang@users.noreply.github.com>
1 parent 7cd7886 commit c6f304f

8 files changed

Lines changed: 354 additions & 533 deletions

File tree

platforms/kbootloader/Cargo.toml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ macros = { workspace = true }
1616
# Architecture-specific dependencies
1717
[target.'cfg(target_arch = "aarch64")'.dependencies]
1818
aarch64-cpu = "10.0"
19-
aarch64-cpu-ext = "0.1"
20-
kasm-aarch64 = {workspace = true}
21-
smccc = "0.2"
19+
karch = { workspace = true }
20+
page_table = { workspace = true }
21+
memaddr = { workspace = true }
22+
kplat = { workspace = true, features = ["smp"] }

platforms/kbootloader/build.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
use std::{env, fs, path::PathBuf};
22

3+
fn out_dir() -> PathBuf {
4+
PathBuf::from(env::var("OUT_DIR").unwrap())
5+
}
6+
37
fn main() {
48
let arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
59

@@ -13,7 +17,7 @@ fn main() {
1317
println!("cargo::rustc-cfg=hard_float");
1418
}
1519

16-
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
20+
let out_dir = out_dir();
1721

1822
// Read linker script template
1923
let linker_script_src =

platforms/kbootloader/linker.lds.S

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
OUTPUT_ARCH(%ARCH%)
22

3-
BASE_ADDRESS = %KERNEL_IMAGE_VADDR%;
3+
PAGE_SIZE = 0x1000;
4+
BASE_ADDRESS = %KERNEL_BASE%;
45

56
SECTIONS
67
{
@@ -39,12 +40,6 @@ SECTIONS
3940
__init_array_end = .;
4041
}
4142

42-
.boot_loader : ALIGN(PAGE_SIZE) {
43-
__boot_loader_start = .;
44-
KEEP(*(.boot_loader))
45-
__boot_loader_end = .;
46-
}
47-
4843
.data : ALIGN(4K) {
4944
_erodata = .;
5045
_sdata = .;
@@ -113,9 +108,3 @@ SECTIONS
113108
*(.comment) *(.gnu*) *(.note*) *(.eh_frame*)
114109
}
115110
}
116-
117-
EXTERN(__pie_boot_default_secondary);
118-
EXTERN(__somehal_handle_irq_default);
119-
120-
PROVIDE(__pie_boot_secondary = __pie_boot_default_secondary);
121-
PROVIDE(__somehal_handle_irq = __somehal_handle_irq_default);
Lines changed: 26 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,100 +1,57 @@
1-
use core::arch::asm;
1+
// SPDX-License-Identifier: Apache-2.0
2+
// Copyright 2025 KylinSoft Co., Ltd. <https://www.kylinos.cn/>
3+
// See LICENSES for license details.
4+
5+
//! AArch64 exception level switching for early boot.
26
37
use aarch64_cpu::{asm::barrier, registers::*};
4-
use aarch64_cpu_ext::asm::tlb::{VAAE1IS, VMALLE1, tlbi};
5-
use page_table_generic::VirtAddr;
6-
use crate::start_code;
7-
use crate::mem::PageTable;
88

9+
/// Switch from EL3/EL2 down to EL1.
10+
///
11+
/// Must be called before the MMU is enabled. All addresses are physical.
12+
///
13+
/// # Safety
14+
///
15+
/// Changes the CPU exception level. Must only be called once during early boot.
916
#[unsafe(link_section = ".idmap.text")]
10-
pub fn switch_to_elx(bootargs: usize) {
17+
pub unsafe fn switch_to_el1() {
1118
SPSel.write(SPSel::SP::ELx);
1219
SP_EL0.set(0);
1320
let current_el = CurrentEL.read(CurrentEL::EL);
14-
let ret = sym_lma!(super::_start_secondary);
1521
if current_el >= 2 {
1622
if current_el == 3 {
17-
// Set EL2 to 64bit and enable the HVC instruction.
23+
// Set EL2 to 64-bit and enable the HVC instruction.
1824
SCR_EL3.write(
19-
SCR_EL3::NS::NonSecure + SCR_EL3::HCE::HvcEnabled + SCR_EL3::RW::NextELIsAarch64,
25+
SCR_EL3::NS::NonSecure
26+
+ SCR_EL3::HCE::HvcEnabled
27+
+ SCR_EL3::RW::NextELIsAarch64,
2028
);
21-
// Set the return address and exception level.
29+
// Return to EL1h.
2230
SPSR_EL3.write(
2331
SPSR_EL3::M::EL1h
2432
+ SPSR_EL3::D::Masked
2533
+ SPSR_EL3::A::Masked
2634
+ SPSR_EL3::I::Masked
2735
+ SPSR_EL3::F::Masked,
2836
);
29-
30-
ELR_EL3.set(ret as _);
31-
barrier::isb(barrier::SY);
32-
unsafe {
33-
asm!(
34-
"
35-
mov x0, {}
36-
eret
37-
",
38-
in(reg) bootargs,
39-
options(nostack, noreturn),
40-
);
41-
}
37+
ELR_EL3.set(LR.get());
4238
}
43-
// Disable EL1 timer traps and the timer offset.
39+
// Disable EL1 timer traps and clear the timer offset.
4440
CNTHCTL_EL2.modify(CNTHCTL_EL2::EL1PCEN::SET + CNTHCTL_EL2::EL1PCTEN::SET);
4541
CNTVOFF_EL2.set(0);
46-
// Set EL1 to 64bit.
42+
// Set EL1 to 64-bit.
4743
HCR_EL2.write(HCR_EL2::RW::EL1IsAarch64);
48-
// Set the return address and exception level.
44+
// Return to EL1h.
4945
SPSR_EL2.write(
5046
SPSR_EL2::M::EL1h
5147
+ SPSR_EL2::D::Masked
5248
+ SPSR_EL2::A::Masked
5349
+ SPSR_EL2::I::Masked
5450
+ SPSR_EL2::F::Masked,
5551
);
56-
57-
unsafe {
58-
ELR_EL2.set(ret as _);
59-
barrier::isb(barrier::SY);
60-
61-
asm!(
62-
"
63-
mov x0, {}
64-
eret
65-
",
66-
in(reg) bootargs,
67-
options(nostack, noreturn),
68-
)
69-
};
70-
}
71-
}
72-
73-
#[inline(always)]
74-
pub(crate) fn flush_tlb(vaddr: Option<VirtAddr>) {
75-
match vaddr {
76-
Some(addr) => {
77-
tlbi(VAAE1IS::new(addr.raw()));
78-
}
79-
None => {
80-
tlbi(VMALLE1);
81-
}
52+
SP_EL1.set(SP.get());
53+
ELR_EL2.set(LR.get());
54+
barrier::isb(barrier::SY);
55+
aarch64_cpu::asm::eret();
8256
}
83-
barrier::dsb(barrier::SY);
84-
barrier::isb(barrier::SY);
85-
}
86-
87-
pub fn get_kernal_table() -> PageTable {
88-
let val = TTBR1_EL1.extract();
89-
PageTable {
90-
id: val.read(TTBR1_EL1::ASID) as _,
91-
addr: (val.read(TTBR1_EL1::BADDR) << 1) as _,
92-
}
93-
}
94-
95-
pub fn set_kernal_table(tb: PageTable) {
96-
TTBR1_EL1.set(TTBR1_EL1::ASID.val(tb.id as u64).value + tb.addr as u64);
97-
tlbi(VMALLE1);
98-
barrier::dsb(barrier::SY);
99-
barrier::isb(barrier::SY);
10057
}

0 commit comments

Comments
 (0)