Skip to content

Commit 9e567cc

Browse files
committed
Test booting a kernel compiled with lto
1 parent f95e9a9 commit 9e567cc

File tree

6 files changed

+100
-0
lines changed

6 files changed

+100
-0
lines changed

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.

Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ members = [
2323
"tests/test_kernels/map_phys_mem",
2424
"tests/test_kernels/higher_half",
2525
"tests/test_kernels/pie",
26+
"tests/test_kernels/lto",
2627
]
2728
exclude = ["examples/basic", "examples/test_framework"]
2829

@@ -74,6 +75,10 @@ inherits = "release"
7475
debug = true
7576
overflow-checks = true
7677

78+
[profile.lto]
79+
inherits = "release"
80+
lto = true
81+
7782
[profile.test.package.test_kernel_higher_half]
7883
rustflags = [
7984
"-C",

tests/lto.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
use std::{path::Path, process::Command};
2+
3+
use bootloader_test_runner::run_test_kernel;
4+
5+
#[test]
6+
fn basic_boot() {
7+
// build test kernel manually to force-enable link-time optimization
8+
let mut cmd = Command::new(std::env::var("CARGO").unwrap_or("cargo".into()));
9+
cmd.arg("build");
10+
cmd.arg("-p").arg("test_kernel_lto");
11+
cmd.arg("--target").arg("x86_64-unknown-none");
12+
cmd.arg("--profile").arg("lto");
13+
let status = cmd.status().unwrap();
14+
assert!(status.success());
15+
16+
let root = env!("CARGO_MANIFEST_DIR");
17+
let kernel_path = Path::new(root)
18+
.join("target")
19+
.join("x86_64-unknown-none")
20+
.join("lto")
21+
.join("basic_boot");
22+
assert!(kernel_path.exists());
23+
24+
run_test_kernel(kernel_path.as_path().to_str().unwrap());
25+
}

tests/test_kernels/lto/Cargo.toml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[package]
2+
name = "test_kernel_lto"
3+
version = "0.1.0"
4+
authors = ["Philipp Oppermann <dev@phil-opp.com>"]
5+
edition = "2018"
6+
7+
[dependencies]
8+
bootloader_api = { path = "../../../api" }
9+
x86_64 = { version = "0.14.7", default-features = false, features = [
10+
"instructions",
11+
"inline_asm",
12+
] }
13+
uart_16550 = "0.2.10"
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#![no_std] // don't link the Rust standard library
2+
#![no_main] // disable all Rust-level entry points
3+
4+
use bootloader_api::{entry_point, BootInfo};
5+
use core::panic::PanicInfo;
6+
use test_kernel_lto::{exit_qemu, QemuExitCode};
7+
8+
entry_point!(kernel_main);
9+
10+
fn kernel_main(_boot_info: &'static mut BootInfo) -> ! {
11+
exit_qemu(QemuExitCode::Success);
12+
}
13+
14+
/// This function is called on panic.
15+
#[panic_handler]
16+
fn panic(info: &PanicInfo) -> ! {
17+
use core::fmt::Write;
18+
19+
let _ = writeln!(test_kernel_lto::serial(), "PANIC: {}", info);
20+
exit_qemu(QemuExitCode::Failed);
21+
}

tests/test_kernels/lto/src/lib.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#![no_std]
2+
3+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
4+
#[repr(u32)]
5+
pub enum QemuExitCode {
6+
Success = 0x10,
7+
Failed = 0x11,
8+
}
9+
10+
pub fn exit_qemu(exit_code: QemuExitCode) -> ! {
11+
use x86_64::instructions::{nop, port::Port};
12+
13+
unsafe {
14+
let mut port = Port::new(0xf4);
15+
port.write(exit_code as u32);
16+
}
17+
18+
loop {
19+
nop();
20+
}
21+
}
22+
23+
pub fn serial() -> uart_16550::SerialPort {
24+
let mut port = unsafe { uart_16550::SerialPort::new(0x3F8) };
25+
port.init();
26+
port
27+
}

0 commit comments

Comments
 (0)