Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 04fc88d

Browse filesBrowse files
committed
Add a test to verify that ramdisk is marked as used in memory map
1 parent 6b23732 commit 04fc88d
Copy full SHA for 04fc88d

File tree

Expand file treeCollapse file tree

2 files changed

+97
-0
lines changed
Filter options
Expand file treeCollapse file tree

2 files changed

+97
-0
lines changed

‎tests/ramdisk.rs

Copy file name to clipboardExpand all lines: tests/ramdisk.rs
+8Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,11 @@ fn check_ramdisk() {
1818
Some(Path::new(RAMDISK_PATH)),
1919
);
2020
}
21+
22+
#[test]
23+
fn memory_map() {
24+
run_test_kernel_with_ramdisk(
25+
env!("CARGO_BIN_FILE_TEST_KERNEL_RAMDISK_memory_map"),
26+
Some(Path::new(RAMDISK_PATH)),
27+
);
28+
}
+89Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
#![no_std] // don't link the Rust standard library
2+
#![no_main] // disable all Rust-level entry points
3+
4+
use bootloader_api::{
5+
config::Mapping, entry_point, info::MemoryRegionKind, BootInfo, BootloaderConfig,
6+
};
7+
use core::{fmt::Write, ptr::slice_from_raw_parts};
8+
use test_kernel_ramdisk::{exit_qemu, serial, QemuExitCode, RAMDISK_CONTENTS};
9+
use x86_64::{
10+
structures::paging::{OffsetPageTable, PageTable, PageTableFlags, Translate},
11+
VirtAddr,
12+
};
13+
14+
pub const BOOTLOADER_CONFIG: BootloaderConfig = {
15+
let mut config = BootloaderConfig::new_default();
16+
config.mappings.physical_memory = Some(Mapping::FixedAddress(0x0000_6000_0000_0000));
17+
config
18+
};
19+
20+
entry_point!(kernel_main, config = &BOOTLOADER_CONFIG);
21+
22+
fn kernel_main(boot_info: &'static mut BootInfo) -> ! {
23+
writeln!(serial(), "Boot info: {boot_info:?}").unwrap();
24+
25+
let phys_mem_offset = VirtAddr::new(boot_info.physical_memory_offset.into_option().unwrap());
26+
let level_4_table = unsafe { active_level_4_table(phys_mem_offset) };
27+
let page_table = unsafe { OffsetPageTable::new(level_4_table, phys_mem_offset) };
28+
29+
let ramdisk_start_addr = VirtAddr::new(boot_info.ramdisk_addr.into_option().unwrap());
30+
assert_eq!(boot_info.ramdisk_len as usize, RAMDISK_CONTENTS.len());
31+
let ramdisk_end_addr = ramdisk_start_addr + boot_info.ramdisk_len;
32+
33+
let mut next_addr = ramdisk_start_addr;
34+
while next_addr < ramdisk_end_addr {
35+
let phys_addr = match page_table.translate(next_addr) {
36+
x86_64::structures::paging::mapper::TranslateResult::Mapped {
37+
frame,
38+
offset: _,
39+
flags,
40+
} => {
41+
assert!(flags.contains(PageTableFlags::PRESENT));
42+
assert!(flags.contains(PageTableFlags::WRITABLE));
43+
assert!(flags.contains(PageTableFlags::NO_EXECUTE));
44+
45+
next_addr += frame.size();
46+
47+
frame.start_address()
48+
}
49+
other => panic!("invalid result: {other:?}"),
50+
};
51+
let region = boot_info
52+
.memory_regions
53+
.iter()
54+
.find(|r| r.start <= phys_addr.as_u64() && r.end > phys_addr.as_u64())
55+
.unwrap();
56+
assert_eq!(region.kind, MemoryRegionKind::Bootloader);
57+
}
58+
59+
let actual_ramdisk = unsafe {
60+
&*slice_from_raw_parts(
61+
boot_info.ramdisk_addr.into_option().unwrap() as *const u8,
62+
boot_info.ramdisk_len as usize,
63+
)
64+
};
65+
writeln!(serial(), "Actual contents: {actual_ramdisk:?}").unwrap();
66+
assert_eq!(RAMDISK_CONTENTS, actual_ramdisk);
67+
68+
exit_qemu(QemuExitCode::Success);
69+
}
70+
71+
/// This function is called on panic.
72+
#[cfg(not(test))]
73+
#[panic_handler]
74+
fn panic(info: &core::panic::PanicInfo) -> ! {
75+
let _ = writeln!(test_kernel_ramdisk::serial(), "PANIC: {info}");
76+
exit_qemu(QemuExitCode::Failed);
77+
}
78+
79+
pub unsafe fn active_level_4_table(physical_memory_offset: VirtAddr) -> &'static mut PageTable {
80+
use x86_64::registers::control::Cr3;
81+
82+
let (level_4_table_frame, _) = Cr3::read();
83+
84+
let phys = level_4_table_frame.start_address();
85+
let virt = physical_memory_offset + phys.as_u64();
86+
let page_table_ptr: *mut PageTable = virt.as_mut_ptr();
87+
88+
&mut *page_table_ptr // unsafe
89+
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.