Skip to content

Commit 31a6071

Browse files
authored
Merge pull request #531 from Wasabi375/stack
add kernel stack address to BootInfo
2 parents d570ba7 + 0440530 commit 31a6071

File tree

10 files changed

+117
-0
lines changed

10 files changed

+117
-0
lines changed

Cargo.lock

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

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ test_kernel_min_stack = { path = "tests/test_kernels/min_stack", artifact = "bin
6161
test_kernel_lower_memory_free = { path = "tests/test_kernels/lower_memory_free", artifact = "bin", target = "x86_64-unknown-none" }
6262
test_kernel_write_usable_memory = { path = "tests/test_kernels/write_usable_memory", artifact = "bin", target = "x86_64-unknown-none" }
6363
test_kernel_fixed_kernel_address = { path = "tests/test_kernels/fixed_kernel_address", artifact = "bin", target = "x86_64-unknown-none" }
64+
test_kernel_stack_address = { path = "tests/test_kernels/stack_address", artifact = "bin", target = "x86_64-unknown-none" }
6465

6566
[profile.dev]
6667
panic = "abort"

api/src/info.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ pub struct BootInfo {
6262
pub kernel_len: u64,
6363
/// Virtual address of the loaded kernel image.
6464
pub kernel_image_offset: u64,
65+
/// Virtual address of the kernel stack bottom.
66+
pub kernel_stack_bottom: u64,
67+
/// Size of the kernel stack
68+
pub kernel_stack_len: u64,
6569

6670
#[doc(hidden)]
6771
pub _test_sentinel: u64,
@@ -85,6 +89,8 @@ impl BootInfo {
8589
kernel_addr: 0,
8690
kernel_len: 0,
8791
kernel_image_offset: 0,
92+
kernel_stack_bottom: 0,
93+
kernel_stack_len: 0,
8894
_test_sentinel: 0,
8995
}
9096
}

common/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,7 @@ where
415415
Mappings {
416416
framebuffer: framebuffer_virt_addr,
417417
entry_point,
418+
stack_bottom: stack_start.start_address(),
418419
// Use the configured stack size, even if it's not page-aligned. However, we
419420
// need to align it down to the next 16-byte boundary because the System V
420421
// ABI requires a 16-byte stack alignment.
@@ -438,6 +439,7 @@ where
438439
pub struct Mappings {
439440
/// The entry point address of the kernel.
440441
pub entry_point: VirtAddr,
442+
pub stack_bottom: VirtAddr,
441443
/// The (exclusive) end address of the kernel stack.
442444
pub stack_top: VirtAddr,
443445
/// Keeps track of used entries in the level 4 page table, useful for finding a free
@@ -579,6 +581,8 @@ where
579581
info.kernel_addr = mappings.kernel_slice_start.as_u64();
580582
info.kernel_len = mappings.kernel_slice_len as _;
581583
info.kernel_image_offset = mappings.kernel_image_offset.as_u64();
584+
info.kernel_stack_bottom = mappings.stack_bottom.as_u64();
585+
info.kernel_stack_len = config.kernel_stack_size;
582586
info._test_sentinel = boot_config._test_sentinel;
583587
info
584588
});

tests/stack_address.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
use bootloader_test_runner::run_test_kernel;
2+
3+
#[test]
4+
fn basic_boot() {
5+
run_test_kernel(env!("CARGO_BIN_FILE_TEST_KERNEL_STACK_ADDRESS_basic_boot"));
6+
}

tests/test_kernels/Cargo.lock

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

tests/test_kernels/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ members = [
1313
"lower_memory_free",
1414
"write_usable_memory",
1515
"fixed_kernel_address",
16+
"stack_address",
1617
]
1718

1819
[profile.release]
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[package]
2+
name = "test_kernel_stack_address"
3+
version = "0.1.0"
4+
edition = "2024"
5+
6+
[target.'cfg(target_arch = "x86_64")'.dependencies]
7+
bootloader_api = { path = "../../../api" }
8+
x86_64 = { version = "0.15.2", default-features = false, features = [
9+
"instructions",
10+
] }
11+
uart_16550 = "0.2.10"
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#![no_std] // don't link the Rust standard library
2+
#![no_main] // disable all Rust-level entry points
3+
4+
use bootloader_api::{BootInfo, entry_point};
5+
use test_kernel_stack_address::{BOOTLOADER_CONFIG, QemuExitCode, exit_qemu};
6+
7+
entry_point!(kernel_main, config = &BOOTLOADER_CONFIG);
8+
9+
fn kernel_main(boot_info: &'static mut BootInfo) -> ! {
10+
let x: i32 = 42;
11+
let vaddr = &x as *const _ as usize as u64;
12+
13+
assert_ne!(boot_info.kernel_stack_bottom, 0);
14+
assert_eq!(
15+
boot_info.kernel_stack_len,
16+
BOOTLOADER_CONFIG.kernel_stack_size
17+
);
18+
assert!(vaddr >= boot_info.kernel_stack_bottom);
19+
assert!(vaddr < boot_info.kernel_stack_bottom + boot_info.kernel_stack_len);
20+
21+
exit_qemu(QemuExitCode::Success);
22+
}
23+
24+
/// This function is called on panic.
25+
#[cfg(not(test))]
26+
#[panic_handler]
27+
fn panic(info: &core::panic::PanicInfo) -> ! {
28+
use core::fmt::Write;
29+
30+
let _ = writeln!(test_kernel_stack_address::serial(), "PANIC: {info}");
31+
exit_qemu(QemuExitCode::Failed);
32+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#![no_std]
2+
3+
use bootloader_api::{BootloaderConfig, config::Mapping};
4+
5+
pub const KERNEL_ADDR: u64 = 0x1987_6543_0000;
6+
7+
pub const BOOTLOADER_CONFIG: BootloaderConfig = {
8+
let mut config = BootloaderConfig::new_default();
9+
config.mappings.kernel_base = Mapping::FixedAddress(KERNEL_ADDR);
10+
config
11+
};
12+
13+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
14+
#[repr(u32)]
15+
pub enum QemuExitCode {
16+
Success = 0x10,
17+
Failed = 0x11,
18+
}
19+
20+
pub fn exit_qemu(exit_code: QemuExitCode) -> ! {
21+
use x86_64::instructions::{nop, port::Port};
22+
23+
unsafe {
24+
let mut port = Port::new(0xf4);
25+
port.write(exit_code as u32);
26+
}
27+
28+
loop {
29+
nop();
30+
}
31+
}
32+
33+
pub fn serial() -> uart_16550::SerialPort {
34+
let mut port = unsafe { uart_16550::SerialPort::new(0x3F8) };
35+
port.init();
36+
port
37+
}

0 commit comments

Comments
 (0)