Move .bss and .data tests to inline asm

If .bss is not properly cleared or .data is incorrectly cleared, there
is no way to tell what will happen if we try to run Rust code.
This commit is contained in:
bjorn3
2025-09-14 16:39:33 +02:00
committed by Jeremy Soller
parent ac35b7984a
commit ede9a47f9c
3 changed files with 95 additions and 31 deletions
+25 -8
View File
@@ -3,6 +3,7 @@
//! It must create the IDT with the correct entries, those entries are
//! defined in other files inside of the `arch` module
use core::{
arch::global_asm,
slice,
sync::atomic::{AtomicBool, Ordering},
};
@@ -21,19 +22,35 @@ static mut DATA_TEST_NONZERO: usize = 0xFFFF_FFFF_FFFF_FFFF;
pub static AP_READY: AtomicBool = AtomicBool::new(false);
static BSP_READY: AtomicBool = AtomicBool::new(false);
global_asm!("
.globl kstart
kstart:
// BSS should already be zero
adrp x9, {bss_test_zero}
ldr x9, [x9, :lo12:{bss_test_zero}]
cbnz x9, .Lkstart_crash
adrp x9, {data_test_nonzero}
ldr x9, [x9, :lo12:{data_test_nonzero}]
cbz x9, .Lkstart_crash
mov lr, 0
b {start}
.Lkstart_crash:
mov x9, 0
br x9
",
bss_test_zero = sym BSS_TEST_ZERO,
data_test_nonzero = sym DATA_TEST_NONZERO,
start = sym start,
);
/// The entry to Rust, all things must be initialized
#[unsafe(no_mangle)]
pub unsafe extern "C" fn kstart(args_ptr: *const KernelArgs) -> ! {
unsafe extern "C" fn start(args_ptr: *const KernelArgs) -> ! {
unsafe {
let bootstrap = {
let args = args_ptr.read();
// BSS should already be zero
{
assert_eq!(BSS_TEST_ZERO, 0);
assert_eq!(DATA_TEST_NONZERO, 0xFFFF_FFFF_FFFF_FFFF);
}
// Set up graphical debug
graphical_debug::init(args.env());
+26 -13
View File
@@ -1,9 +1,7 @@
use core::{
arch::asm,
slice,
arch::{asm, global_asm},
sync::atomic::{AtomicUsize, Ordering},
};
use fdt::Fdt;
use crate::{
allocator,
@@ -38,13 +36,34 @@ fn get_boot_hart_id(env: &[u8]) -> Option<usize> {
None
}
global_asm!("
.globl kstart
kstart:
mv gp, x0 // ensure gp relative accesses crash
mv tp, x0 // reset percpu until it is initialized
csrw sscratch, tp
// BSS should already be zero
ld t0, {bss_test_zero}
bnez t0, .Lkstart_crash
ld t0, {data_test_nonzero}
beqz t0, .Lkstart_crash
li ra, 0
j {start}
.Lkstart_crash:
jr x0
",
bss_test_zero = sym BSS_TEST_ZERO,
data_test_nonzero = sym DATA_TEST_NONZERO,
start = sym start,
);
/// The entry to Rust, all things must be initialized
#[unsafe(no_mangle)]
pub unsafe extern "C" fn kstart(args_ptr: *const KernelArgs) -> ! {
unsafe extern "C" fn start(args_ptr: *const KernelArgs) -> ! {
unsafe {
asm!(
"mv tp, x0", // reset percpu until it is initialized
"csrw sscratch, tp",
"sd x0, -16(fp)", // and stop frame walker here
"sd x0, -8(fp)",
);
@@ -52,12 +71,6 @@ pub unsafe extern "C" fn kstart(args_ptr: *const KernelArgs) -> ! {
let bootstrap = {
let args = args_ptr.read();
// BSS should already be zero
{
assert_eq!(BSS_TEST_ZERO, 0);
assert_eq!(DATA_TEST_NONZERO, 0xFFFF_FFFF_FFFF_FFFF);
}
let dtb_data = if args.hwdesc_base != 0 {
Some((
crate::PHYS_OFFSET + args.hwdesc_base as usize,
+44 -10
View File
@@ -3,6 +3,7 @@
//! It must create the IDT with the correct entries, those entries are
//! defined in other files inside of the `arch` module
use core::{
arch::global_asm,
cell::SyncUnsafeCell,
hint,
sync::atomic::{AtomicBool, Ordering},
@@ -29,19 +30,54 @@ static DATA_TEST_NONZERO: SyncUnsafeCell<usize> = SyncUnsafeCell::new(usize::max
pub static AP_READY: AtomicBool = AtomicBool::new(false);
static BSP_READY: AtomicBool = AtomicBool::new(false);
#[cfg(target_arch = "x86")]
global_asm!("
.globl kstart
kstart:
// BSS should already be zero
cmp dword ptr [{bss_test_zero}], 0
jne .Lkstart_crash
cmp dword ptr [{data_test_nonzero}], 0
je .Lkstart_crash
jmp {start}
.Lkstart_crash:
mov eax, 0
jmp eax
",
bss_test_zero = sym BSS_TEST_ZERO,
data_test_nonzero = sym DATA_TEST_NONZERO,
start = sym start,
);
#[cfg(target_arch = "x86_64")]
global_asm!("
.globl kstart
kstart:
// BSS should already be zero
cmp qword ptr [rip + {bss_test_zero}], 0
jne .Lkstart_crash
cmp qword ptr [rip + {data_test_nonzero}], 0
je .Lkstart_crash
jmp {start}
.Lkstart_crash:
mov rax, 0
jmp rax
",
bss_test_zero = sym BSS_TEST_ZERO,
data_test_nonzero = sym DATA_TEST_NONZERO,
start = sym start,
);
/// The entry to Rust, all things must be initialized
#[unsafe(no_mangle)]
pub unsafe extern "C" fn kstart(args_ptr: *const KernelArgs) -> ! {
unsafe extern "C" fn start(args_ptr: *const KernelArgs) -> ! {
unsafe {
let bootstrap = {
let args = args_ptr.read();
// BSS should already be zero
{
assert_eq!(BSS_TEST_ZERO.get().read(), 0);
assert_eq!(DATA_TEST_NONZERO.get().read(), usize::max_value());
}
// Set up serial debug
device::serial::init();
@@ -123,8 +159,6 @@ pub unsafe extern "C" fn kstart_ap(args_ptr: *const KernelArgsAp) -> ! {
unsafe {
let cpu_id = {
let args = &*args_ptr;
assert_eq!(BSS_TEST_ZERO.get().read(), 0);
assert_eq!(DATA_TEST_NONZERO.get().read(), usize::max_value());
// Set up GDT
gdt::install_pcr(args.pcr_ptr);