Skip to content

Commit 5b5fd3d

Browse files
committed
feat: walk in page tables
1 parent 7b352b8 commit 5b5fd3d

File tree

6 files changed

+102
-15
lines changed

6 files changed

+102
-15
lines changed

Cargo.lock

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

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
[package]
22
name = "osdev_rust"
33
version = "0.1.0"
4-
edition = "2021"
4+
edition = "2024"
55

66
[dependencies]
7-
bootloader = "0.9"
7+
bootloader = { version = "0.9", features = ["map_physical_memory"] }
88
volatile = "0.2.6"
99
spin = "0.5.2"
1010
x86_64 = "0.14.2"

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# osdev_rust
2+
3+
`rustup component add llvm-tools-preview`
4+
`cargo install bootimage`
5+
`cargo run`

src/lib.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use core::panic::PanicInfo;
99

1010
pub mod gdt;
1111
pub mod interrupts;
12+
pub mod memory;
1213
pub mod serial;
1314
pub mod vga_buffer;
1415

@@ -58,8 +59,13 @@ pub fn hlt_loop() -> ! {
5859
}
5960

6061
#[cfg(test)]
61-
#[no_mangle]
62-
pub extern "C" fn _start() -> ! {
62+
use bootloader::{BootInfo, entry_point};
63+
64+
#[cfg(test)]
65+
entry_point!(test_kernel_main);
66+
67+
#[cfg(test)]
68+
fn test_kernel_main(_boot_info: &'static BootInfo) -> ! {
6369
init();
6470
test_main();
6571
hlt_loop();

src/main.rs

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,44 @@
1+
#![no_std]
2+
#![no_main]
13
#![feature(custom_test_frameworks)]
24
#![test_runner(osdev_rust::test_runner)]
35
#![reexport_test_harness_main = "test_main"]
4-
#![no_std]
5-
#![no_main]
66

7+
use bootloader::{BootInfo, entry_point};
78
use core::panic::PanicInfo;
89
use osdev_rust::println;
910

10-
#[no_mangle]
11-
pub extern "C" fn _start() -> ! {
11+
entry_point!(kernel_main);
12+
13+
fn kernel_main(boot_info: &'static BootInfo) -> ! {
14+
use osdev_rust::memory::active_level_4_table;
15+
use x86_64::VirtAddr;
16+
use x86_64::structures::paging::PageTable;
17+
1218
println!("Hello World!");
1319

1420
osdev_rust::init();
1521

22+
let phys_mem_offset = VirtAddr::new(boot_info.physical_memory_offset);
23+
let l4_table = unsafe { active_level_4_table(phys_mem_offset) };
24+
25+
for (i, entry) in l4_table.iter().enumerate() {
26+
if !entry.is_unused() {
27+
println!("L4 Entry: {}: {:?}", i, entry);
28+
29+
let phys = entry.frame().unwrap().start_address();
30+
let virt = phys.as_u64() + boot_info.physical_memory_offset;
31+
let ptr = VirtAddr::new(virt).as_mut_ptr();
32+
let l3_table: &PageTable = unsafe { &*ptr };
33+
34+
for (i, entry) in l3_table.iter().enumerate() {
35+
if !entry.is_unused() {
36+
println!(" L3 Entry {}: {:?}", i, entry);
37+
}
38+
}
39+
}
40+
}
41+
1642
#[cfg(test)]
1743
test_main();
1844

src/memory.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
use core::panic;
2+
3+
use x86_64::{PhysAddr, VirtAddr, structures::paging::PageTable};
4+
5+
pub unsafe fn active_level_4_table(physical_memory_offset: VirtAddr) -> &'static mut PageTable {
6+
use x86_64::registers::control::Cr3;
7+
8+
let (level_4_table_frame, _) = Cr3::read();
9+
10+
let phys = level_4_table_frame.start_address();
11+
let virt = physical_memory_offset + phys.as_u64();
12+
let page_table_ptr: *mut PageTable = virt.as_mut_ptr();
13+
14+
unsafe { &mut *page_table_ptr }
15+
}
16+
17+
pub unsafe fn translate_addr(addr: VirtAddr, physical_memory_offset: VirtAddr) -> Option<PhysAddr> {
18+
translate_addr_inner(addr, physical_memory_offset);
19+
}
20+
21+
fn translate_addr_inner(addr: VirtAddr, physical_memory_offset: VirtAddr) -> Option<PhysAddr> {
22+
use x86_64::registers::control::Cr3;
23+
use x86_64::structures::paging::page_table::FrameError;
24+
25+
let (level_4_table_frame, _) = Cr3::read();
26+
27+
let table_indexes = [
28+
addr.p4_index(),
29+
addr.p3_index(),
30+
addr.p2_index(),
31+
addr.p1_index(),
32+
];
33+
let mut frame = level_4_table_frame;
34+
35+
for &index in &table_indexes {
36+
let virt = physical_memory_offset + frame.start_address().as_u64();
37+
let table_ptr: *const PageTable = virt.as_ptr();
38+
let table = unsafe { &*table_ptr };
39+
40+
let entry = &table[index];
41+
42+
frame = match entry.frame() {
43+
Ok(frame) => frame,
44+
Err(FrameError::FrameNotPresent) => return None,
45+
Err(FrameError::HugeFrame) => panic!("Huge frames not supported"),
46+
};
47+
}
48+
49+
Some(frame.start_address() + u64::from(addr.page_offset()))
50+
}

0 commit comments

Comments
 (0)