Skip to content

Commit 4ecba49

Browse files
committedApr 9, 2022
Merge #206 into next
2 parents 768f2a7 + 6423165 commit 4ecba49

14 files changed

+548
-56
lines changed
 

Diff for: ‎Cargo.lock

+9
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: ‎Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ members = [
1818
"tests/test_kernels/default_settings",
1919
"tests/test_kernels/map_phys_mem",
2020
"tests/test_kernels/higher_half",
21+
"tests/test_kernels/pie",
2122
]
2223
exclude = ["examples/basic", "examples/test_framework"]
2324

Diff for: ‎common/src/level_4_entries.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,22 @@ impl UsedLevel4Entries {
1616
/// Initializes a new instance from the given ELF program segments.
1717
///
1818
/// Marks the virtual address range of all segments as used.
19-
pub fn new<'a>(segments: impl Iterator<Item = ProgramHeader<'a>>) -> Self {
19+
pub fn new<'a>(
20+
segments: impl Iterator<Item = ProgramHeader<'a>>,
21+
virtual_address_offset: u64,
22+
) -> Self {
2023
let mut used = UsedLevel4Entries {
2124
entry_state: [false; 512],
2225
};
2326

2427
used.entry_state[0] = true; // TODO: Can we do this dynamically?
2528

2629
for segment in segments {
27-
let start_page: Page = Page::containing_address(VirtAddr::new(segment.virtual_addr()));
30+
let start_page: Page = Page::containing_address(VirtAddr::new(
31+
segment.virtual_addr() + virtual_address_offset,
32+
));
2833
let end_page: Page = Page::containing_address(VirtAddr::new(
29-
segment.virtual_addr() + segment.mem_size(),
34+
segment.virtual_addr() + virtual_address_offset + segment.mem_size(),
3035
));
3136

3237
for p4_index in u64::from(start_page.p4_index())..=u64::from(end_page.p4_index()) {

Diff for: ‎common/src/load_kernel.rs

+289-53
Large diffs are not rendered by default.

Diff for: ‎tests/pie.rs

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
use std::process::Command;
2+
3+
#[test]
4+
fn basic_boot() {
5+
run_test_binary("basic_boot");
6+
}
7+
8+
#[test]
9+
fn should_panic() {
10+
run_test_binary("should_panic");
11+
}
12+
13+
#[test]
14+
fn check_boot_info() {
15+
run_test_binary("check_boot_info");
16+
}
17+
18+
#[test]
19+
fn global_variable() {
20+
run_test_binary("global_variable");
21+
}
22+
23+
fn run_test_binary(bin_name: &str) {
24+
let mut cmd = Command::new(env!("CARGO"));
25+
cmd.current_dir("tests/test_kernels/pie");
26+
cmd.arg("run");
27+
cmd.arg("--bin").arg(bin_name);
28+
cmd.arg("--target").arg("x86_64-pie.json");
29+
cmd.arg("-Zbuild-std=core");
30+
cmd.arg("-Zbuild-std-features=compiler-builtins-mem");
31+
assert!(cmd.status().unwrap().success());
32+
}

Diff for: ‎tests/test_kernels/pie/.cargo/config.toml

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[unstable]
2+
# TODO: Uncomment once https://github.com/rust-lang/cargo/issues/8643 is merged
3+
# build-std = ["core"]
4+
5+
[build]
6+
# TODO: Uncomment once https://github.com/rust-lang/cargo/issues/8643 is merged
7+
# target = "x86_64-example-kernel.json"
8+
9+
[target.'cfg(target_os = "none")']
10+
runner = "cargo run --manifest-path ../../runner/Cargo.toml"

Diff for: ‎tests/test_kernels/pie/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
target

Diff for: ‎tests/test_kernels/pie/Cargo.toml

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[package]
2+
name = "test_kernel_pie"
3+
version = "0.1.0"
4+
authors = ["Tom Dohrmann <erbse.13@gmx.de>"]
5+
edition = "2018"
6+
7+
[dependencies]
8+
bootloader = { path = "../../.." }
9+
x86_64 = { version = "0.14.7", default-features = false, features = ["instructions", "inline_asm"] }
10+
uart_16550 = "0.2.10"

Diff for: ‎tests/test_kernels/pie/src/bin/basic_boot.rs

+21
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::{entry_point, BootInfo};
5+
use core::panic::PanicInfo;
6+
use test_kernel_pie::{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_pie::serial(), "PANIC: {}", info);
20+
exit_qemu(QemuExitCode::Failed);
21+
}

Diff for: ‎tests/test_kernels/pie/src/bin/check_boot_info.rs

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
#![no_std] // don't link the Rust standard library
2+
#![no_main] // disable all Rust-level entry points
3+
4+
use bootloader::{boot_info::PixelFormat, entry_point, BootInfo};
5+
use core::panic::PanicInfo;
6+
use test_kernel_pie::{exit_qemu, QemuExitCode};
7+
8+
entry_point!(kernel_main);
9+
10+
fn kernel_main(boot_info: &'static mut BootInfo) -> ! {
11+
// check memory regions
12+
assert!(boot_info.memory_regions.len() > 4);
13+
14+
// check framebuffer
15+
let framebuffer = boot_info.framebuffer.as_ref().unwrap();
16+
assert_eq!(framebuffer.info().byte_len, framebuffer.buffer().len());
17+
if ![640, 1024].contains(&framebuffer.info().horizontal_resolution) {
18+
panic!(
19+
"unexpected horizontal_resolution `{}`",
20+
framebuffer.info().horizontal_resolution
21+
);
22+
}
23+
if ![480, 768].contains(&framebuffer.info().vertical_resolution) {
24+
panic!(
25+
"unexpected vertical_resolution `{}`",
26+
framebuffer.info().vertical_resolution
27+
);
28+
}
29+
if ![3, 4].contains(&framebuffer.info().bytes_per_pixel) {
30+
panic!(
31+
"unexpected bytes_per_pixel `{}`",
32+
framebuffer.info().bytes_per_pixel
33+
);
34+
}
35+
if ![640, 1024].contains(&framebuffer.info().stride) {
36+
panic!("unexpected stride `{}`", framebuffer.info().stride);
37+
}
38+
assert_eq!(framebuffer.info().pixel_format, PixelFormat::BGR);
39+
assert_eq!(
40+
framebuffer.buffer().len(),
41+
framebuffer.info().stride
42+
* framebuffer.info().vertical_resolution
43+
* framebuffer.info().bytes_per_pixel
44+
);
45+
46+
// check defaults for optional features
47+
assert_eq!(boot_info.physical_memory_offset.into_option(), None);
48+
assert_eq!(boot_info.recursive_index.into_option(), None);
49+
50+
// check rsdp_addr
51+
let rsdp = boot_info.rsdp_addr.into_option().unwrap();
52+
assert!(rsdp > 0x000E0000);
53+
assert!(rsdp < 0x000FFFFF);
54+
55+
// the test kernel has no TLS template
56+
assert_eq!(boot_info.tls_template.into_option(), None);
57+
58+
exit_qemu(QemuExitCode::Success);
59+
}
60+
61+
/// This function is called on panic.
62+
#[panic_handler]
63+
fn panic(info: &PanicInfo) -> ! {
64+
use core::fmt::Write;
65+
66+
let _ = writeln!(test_kernel_pie::serial(), "PANIC: {}", info);
67+
exit_qemu(QemuExitCode::Failed);
68+
}

Diff for: ‎tests/test_kernels/pie/src/bin/global_variable.rs

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#![no_std] // don't link the Rust standard library
2+
#![no_main] // disable all Rust-level entry points
3+
4+
use bootloader::{entry_point, BootInfo};
5+
use core::{
6+
panic::PanicInfo,
7+
sync::atomic::{AtomicU64, Ordering},
8+
};
9+
use test_kernel_pie::{exit_qemu, QemuExitCode};
10+
11+
entry_point!(kernel_main);
12+
13+
fn kernel_main(_boot_info: &'static mut BootInfo) -> ! {
14+
// Initialize with a value that is unlikely to be anywhere in memory.
15+
// If we can later read out this exact value, we can be sure that we actually
16+
// read from this global variable and not some other location in memory.
17+
static FOO: AtomicU64 = AtomicU64::new(0xdeadbeef);
18+
19+
// Make sure that relocations are actually applied by referencing a `FOO`
20+
// in `FOO_REF`. `FOO`'s address will be calculated and put into `FOO_REF`
21+
// at load time using a relocation.
22+
static FOO_REF: &AtomicU64 = &FOO;
23+
24+
// Verify that the memory address pointed to by `FOO_REF` contains our value.
25+
let val = FOO_REF.load(Ordering::Relaxed);
26+
assert_eq!(val, 0xdeadbeef);
27+
28+
exit_qemu(QemuExitCode::Success);
29+
}
30+
31+
/// This function is called on panic.
32+
#[panic_handler]
33+
fn panic(info: &PanicInfo) -> ! {
34+
use core::fmt::Write;
35+
36+
let _ = writeln!(test_kernel_pie::serial(), "PANIC: {}", info);
37+
exit_qemu(QemuExitCode::Failed);
38+
}

Diff for: ‎tests/test_kernels/pie/src/bin/should_panic.rs

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#![no_std] // don't link the Rust standard library
2+
#![no_main] // disable all Rust-level entry points
3+
4+
use bootloader::{entry_point, BootInfo};
5+
use core::panic::PanicInfo;
6+
use test_kernel_pie::{exit_qemu, QemuExitCode};
7+
8+
entry_point!(kernel_main);
9+
10+
fn kernel_main(_boot_info: &'static mut BootInfo) -> ! {
11+
panic!();
12+
}
13+
14+
/// This function is called on panic.
15+
#[panic_handler]
16+
fn panic(_info: &PanicInfo) -> ! {
17+
exit_qemu(QemuExitCode::Success);
18+
}

Diff for: ‎tests/test_kernels/pie/src/lib.rs

+27
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+
}

Diff for: ‎tests/test_kernels/pie/x86_64-pie.json

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"llvm-target": "x86_64-unknown-none",
3+
"data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
4+
"arch": "x86_64",
5+
"target-endian": "little",
6+
"target-pointer-width": "64",
7+
"target-c-int-width": "32",
8+
"os": "none",
9+
"executables": true,
10+
"linker-flavor": "ld.lld",
11+
"linker": "rust-lld",
12+
"panic-strategy": "abort",
13+
"disable-redzone": true,
14+
"features": "-mmx,-sse,+soft-float",
15+
"position-independent-executables": true
16+
}

0 commit comments

Comments
 (0)
Please sign in to comment.