Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ test_kernel_min_stack = { path = "tests/test_kernels/min_stack", artifact = "bin
test_kernel_lower_memory_free = { path = "tests/test_kernels/lower_memory_free", artifact = "bin", target = "x86_64-unknown-none" }
test_kernel_write_usable_memory = { path = "tests/test_kernels/write_usable_memory", artifact = "bin", target = "x86_64-unknown-none" }
test_kernel_fixed_kernel_address = { path = "tests/test_kernels/fixed_kernel_address", artifact = "bin", target = "x86_64-unknown-none" }
test_kernel_stack_address = { path = "tests/test_kernels/stack_address", artifact = "bin", target = "x86_64-unknown-none" }

[profile.dev]
panic = "abort"
Expand Down
6 changes: 6 additions & 0 deletions api/src/info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ pub struct BootInfo {
pub kernel_len: u64,
/// Virtual address of the loaded kernel image.
pub kernel_image_offset: u64,
/// Virtual address of the kernel stack bottom.
pub kernel_stack_bottom: u64,
/// Size of the kernel stack
pub kernel_stack_len: u64,

#[doc(hidden)]
pub _test_sentinel: u64,
Expand All @@ -85,6 +89,8 @@ impl BootInfo {
kernel_addr: 0,
kernel_len: 0,
kernel_image_offset: 0,
kernel_stack_bottom: 0,
kernel_stack_len: 0,
_test_sentinel: 0,
}
}
Expand Down
4 changes: 4 additions & 0 deletions common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,7 @@ where
Mappings {
framebuffer: framebuffer_virt_addr,
entry_point,
stack_bottom: stack_start.start_address(),
// Use the configured stack size, even if it's not page-aligned. However, we
// need to align it down to the next 16-byte boundary because the System V
// ABI requires a 16-byte stack alignment.
Expand All @@ -438,6 +439,7 @@ where
pub struct Mappings {
/// The entry point address of the kernel.
pub entry_point: VirtAddr,
pub stack_bottom: VirtAddr,
/// The (exclusive) end address of the kernel stack.
pub stack_top: VirtAddr,
/// Keeps track of used entries in the level 4 page table, useful for finding a free
Expand Down Expand Up @@ -579,6 +581,8 @@ where
info.kernel_addr = mappings.kernel_slice_start.as_u64();
info.kernel_len = mappings.kernel_slice_len as _;
info.kernel_image_offset = mappings.kernel_image_offset.as_u64();
info.kernel_stack_bottom = mappings.stack_bottom.as_u64();
info.kernel_stack_len = config.kernel_stack_size;
info._test_sentinel = boot_config._test_sentinel;
info
});
Expand Down
6 changes: 6 additions & 0 deletions tests/stack_address.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
use bootloader_test_runner::run_test_kernel;

#[test]
fn basic_boot() {
run_test_kernel(env!("CARGO_BIN_FILE_TEST_KERNEL_STACK_ADDRESS_basic_boot"));
}
9 changes: 9 additions & 0 deletions tests/test_kernels/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions tests/test_kernels/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ members = [
"lower_memory_free",
"write_usable_memory",
"fixed_kernel_address",
"stack_address",
]

[profile.release]
Expand Down
11 changes: 11 additions & 0 deletions tests/test_kernels/stack_address/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
name = "test_kernel_stack_address"
version = "0.1.0"
edition = "2024"

[target.'cfg(target_arch = "x86_64")'.dependencies]
bootloader_api = { path = "../../../api" }
x86_64 = { version = "0.15.2", default-features = false, features = [
"instructions",
] }
uart_16550 = "0.2.10"
32 changes: 32 additions & 0 deletions tests/test_kernels/stack_address/src/bin/basic_boot.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#![no_std] // don't link the Rust standard library
#![no_main] // disable all Rust-level entry points

use bootloader_api::{BootInfo, entry_point};
use test_kernel_stack_address::{BOOTLOADER_CONFIG, QemuExitCode, exit_qemu};

entry_point!(kernel_main, config = &BOOTLOADER_CONFIG);

fn kernel_main(boot_info: &'static mut BootInfo) -> ! {
let x: i32 = 42;
let vaddr = &x as *const _ as usize as u64;

assert_ne!(boot_info.kernel_stack_bottom, 0);
assert_eq!(
boot_info.kernel_stack_len,
BOOTLOADER_CONFIG.kernel_stack_size
);
assert!(vaddr >= boot_info.kernel_stack_bottom);
assert!(vaddr < boot_info.kernel_stack_bottom + boot_info.kernel_stack_len);

exit_qemu(QemuExitCode::Success);
}

/// This function is called on panic.
#[cfg(not(test))]
#[panic_handler]
fn panic(info: &core::panic::PanicInfo) -> ! {
use core::fmt::Write;

let _ = writeln!(test_kernel_stack_address::serial(), "PANIC: {info}");
exit_qemu(QemuExitCode::Failed);
}
37 changes: 37 additions & 0 deletions tests/test_kernels/stack_address/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#![no_std]

use bootloader_api::{BootloaderConfig, config::Mapping};

pub const KERNEL_ADDR: u64 = 0x1987_6543_0000;

pub const BOOTLOADER_CONFIG: BootloaderConfig = {
let mut config = BootloaderConfig::new_default();
config.mappings.kernel_base = Mapping::FixedAddress(KERNEL_ADDR);
config
};

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u32)]
pub enum QemuExitCode {
Success = 0x10,
Failed = 0x11,
}

pub fn exit_qemu(exit_code: QemuExitCode) -> ! {
use x86_64::instructions::{nop, port::Port};

unsafe {
let mut port = Port::new(0xf4);
port.write(exit_code as u32);
}

loop {
nop();
}
}

pub fn serial() -> uart_16550::SerialPort {
let mut port = unsafe { uart_16550::SerialPort::new(0x3F8) };
port.init();
port
}
Loading