From 8b380f0692c96b7f0d2c5c1335b26574d71d3626 Mon Sep 17 00:00:00 2001 From: Philipp Oppermann Date: Sat, 26 Jan 2019 12:52:47 +0100 Subject: [PATCH] Create a new memory module with a `translate_addr` function --- src/lib.rs | 1 + src/memory.rs | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 src/memory.rs diff --git a/src/lib.rs b/src/lib.rs index 34debc4f..5974e73c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,6 +3,7 @@ pub mod gdt; pub mod interrupts; +pub mod memory; pub mod serial; pub mod vga_buffer; diff --git a/src/memory.rs b/src/memory.rs new file mode 100644 index 00000000..76837ef7 --- /dev/null +++ b/src/memory.rs @@ -0,0 +1,43 @@ +use x86_64::structures::paging::PageTable; +use x86_64::PhysAddr; + +/// Returns the physical address for the given virtual address, or `None` if the +/// virtual address is not mapped. +pub fn translate_addr(addr: usize, level_4_table_addr: usize) -> Option { + // retrieve the page table indices of the address that we want to translate + let level_4_index = (addr >> 39) & 0o777; + let level_3_index = (addr >> 30) & 0o777; + let level_2_index = (addr >> 21) & 0o777; + let level_1_index = (addr >> 12) & 0o777; + let page_offset = addr & 0o7777; + + // check that level 4 entry is mapped + let level_4_table = unsafe { &*(level_4_table_addr as *const PageTable) }; + if level_4_table[level_4_index].addr().is_null() { + return None; + } + let level_3_table_addr = (level_4_table_addr << 9) | (level_4_index << 12); + + // check that level 3 entry is mapped + let level_3_table = unsafe { &*(level_3_table_addr as *const PageTable) }; + if level_3_table[level_3_index].addr().is_null() { + return None; + } + let level_2_table_addr = (level_3_table_addr << 9) | (level_3_index << 12); + + // check that level 2 entry is mapped + let level_2_table = unsafe { &*(level_2_table_addr as *const PageTable) }; + if level_2_table[level_2_index].addr().is_null() { + return None; + } + let level_1_table_addr = (level_2_table_addr << 9) | (level_2_index << 12); + + // check that level 1 entry is mapped and retrieve physical address from it + let level_1_table = unsafe { &*(level_1_table_addr as *const PageTable) }; + let phys_addr = level_1_table[level_1_index].addr(); + if phys_addr.is_null() { + return None; + } + + Some(phys_addr + page_offset) +}