Vaddr to phaddr translation
This commit is contained in:
parent
c200938bec
commit
be027961dc
26
Cargo.lock
generated
26
Cargo.lock
generated
@ -11,12 +11,6 @@ dependencies = [
|
||||
"sptr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "align-address"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cee078b3ed87e2621e0389729e2f032cc0408a4548768ced01678c9451c62237"
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.5.1"
|
||||
@ -73,17 +67,6 @@ version = "0.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b7ac824320a75a52197e8f2d787f6a38b6718bb6897a35142d749af3c0e8f4fe"
|
||||
|
||||
[[package]]
|
||||
name = "free-list"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "358d33fcfc734d809ab9d4c45de31f1e73e3b973656deaff0db3cd5951782134"
|
||||
dependencies = [
|
||||
"align-address",
|
||||
"smallvec",
|
||||
"x86_64",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "intbits"
|
||||
version = "0.2.0"
|
||||
@ -92,12 +75,11 @@ checksum = "5170c2c8ecda29c1bccb9d95ccbe107bc75fa084dc0c9c6087e719f9d46330e5"
|
||||
|
||||
[[package]]
|
||||
name = "kernel"
|
||||
version = "0.3.1"
|
||||
version = "0.3.2"
|
||||
dependencies = [
|
||||
"acid_alloc",
|
||||
"enumflags2",
|
||||
"flagset",
|
||||
"free-list",
|
||||
"intbits",
|
||||
"lazy_static",
|
||||
"libgila",
|
||||
@ -218,12 +200,6 @@ version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.15.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90"
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.9.8"
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
timeout: 2
|
||||
timeout: 1
|
||||
wallpaper: boot():/bg.png
|
||||
wallpaper_style: centered
|
||||
|
||||
/Gila
|
||||
protocol: limine
|
||||
kernel_path: boot():/boot/${ARCH}/gila
|
||||
cmdline: -loglevel=Trace -logdev=display,serial -initramfs=/boot/${ARCH}/initramfs.tar.lzma
|
||||
cmdline: -loglevel=Info -logdev=display,serial -initramfs=/boot/${ARCH}/initramfs.tar.lzma
|
||||
kaslr: yes
|
||||
randomize_hhdm_base: yes
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "kernel"
|
||||
version = "0.3.1"
|
||||
version = "0.3.2"
|
||||
edition = "2024"
|
||||
license = "MIT"
|
||||
|
||||
@ -8,7 +8,6 @@ license = "MIT"
|
||||
acid_alloc = { version = "0.1.0", features = ["alloc"] }
|
||||
enumflags2 = "0.7.12"
|
||||
flagset = "0.4.7"
|
||||
free-list = { version = "0.3.1", features = ["x86_64"] }
|
||||
intbits = "0.2.0"
|
||||
lazy_static = { version = "1.5.0", default-features = false, features = ["spin_no_std"] }
|
||||
limine = "0.6.5"
|
||||
|
||||
@ -26,6 +26,8 @@ pub fn amd_v_supported() -> bool {
|
||||
pub fn enable_svm() {
|
||||
let mut efer = x86_64::registers::model_specific::Efer::read().bits();
|
||||
efer.set_bit(12, true);
|
||||
// I'm not sure why this is here. But clearly there was a reason for it.
|
||||
// So now I'm scared to touch it...
|
||||
assert!(efer.bit(12));
|
||||
unsafe { x86_64::registers::model_specific::Efer::write(EferFlags::from_bits_retain(efer)) };
|
||||
}
|
||||
|
||||
@ -70,6 +70,7 @@ impl Logger {
|
||||
line: u32,
|
||||
column: u32,
|
||||
) {
|
||||
if level <= self.level {
|
||||
for dev in &self.devices {
|
||||
let message = format!(
|
||||
"{} {}:{},{}- {}",
|
||||
@ -82,6 +83,7 @@ impl Logger {
|
||||
dev(&message)
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn add_device(&mut self, device: Box<dyn Fn(&str) + Send + Sync>) {
|
||||
self.devices.push(device);
|
||||
}
|
||||
|
||||
@ -16,6 +16,8 @@ mod panic;
|
||||
mod process;
|
||||
mod util;
|
||||
|
||||
use core::ptr::addr_of;
|
||||
|
||||
use arch::x86_64::interrupts::IDT;
|
||||
use arch::x86_64::serial::SerialPort;
|
||||
use boot::{BASE_REVISION, params, *};
|
||||
@ -29,6 +31,7 @@ use limine::firmware::{
|
||||
FIRMWARE_TYPE_EFI32, FIRMWARE_TYPE_EFI64, FIRMWARE_TYPE_SBI, FIRMWARE_TYPE_X86BIOS,
|
||||
};
|
||||
use spin::mutex::Mutex;
|
||||
use x86_64::VirtAddr;
|
||||
|
||||
use crate::{
|
||||
arch::{
|
||||
@ -38,7 +41,7 @@ use crate::{
|
||||
gdt::dump_gdt,
|
||||
},
|
||||
},
|
||||
memory::{paging, phys_to_virt},
|
||||
memory::paging::{self, active_root_table, virt_to_phys},
|
||||
};
|
||||
|
||||
lazy_static! {
|
||||
@ -95,6 +98,9 @@ unsafe extern "C" fn main() -> ! {
|
||||
EXECUTABLE_FILE_RESPONSE.executable_file().path()
|
||||
);
|
||||
|
||||
let log_level = log::LOGGER.lock().level;
|
||||
log_info!("Log level: {:?}", log_level);
|
||||
|
||||
// Branding
|
||||
for line in ASCII_LOGO {
|
||||
let mut locked = SERIAL_3F8.lock();
|
||||
@ -171,13 +177,24 @@ unsafe extern "C" fn main() -> ! {
|
||||
}
|
||||
log_info!("Virtualization provider: {:?}", virt_supported());
|
||||
|
||||
let l4_start = x86_64::registers::control::Cr3::read().0.start_address();
|
||||
log_info!("Physical address of current L4 table: 0x{:x}", l4_start);
|
||||
{
|
||||
let root_ptable_info = unsafe { active_root_table() };
|
||||
log_info!(
|
||||
"Virtual address of current L4 table: 0x{:x}",
|
||||
phys_to_virt(l4_start)
|
||||
"Root page table is Level {} at 0x{:x}",
|
||||
root_ptable_info.1,
|
||||
addr_of!(*root_ptable_info.0) as usize
|
||||
);
|
||||
paging::walk_tables();
|
||||
log_info!(
|
||||
"Testing virt_to_phys: 0x{:x}",
|
||||
addr_of!(*root_ptable_info.0) as usize
|
||||
);
|
||||
log_info!(
|
||||
"Result: 0x{:x}",
|
||||
virt_to_phys(VirtAddr::new(addr_of!(*root_ptable_info.0) as u64)).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
log_info!("Long mode: {}", asm::long_mode());
|
||||
dump_gdt();
|
||||
|
||||
|
||||
@ -12,16 +12,11 @@ use lazy_static::lazy_static;
|
||||
use limine::request::{ExecutableAddressRequest, HhdmRepsonse, HhdmRequest};
|
||||
use limine::request::{MemmapRequest, MemmapResponse};
|
||||
use talc::*;
|
||||
use x86_64::{PhysAddr, VirtAddr};
|
||||
|
||||
pub extern crate alloc;
|
||||
|
||||
pub mod paging;
|
||||
|
||||
pub fn phys_to_virt(phys: PhysAddr) -> VirtAddr {
|
||||
VirtAddr::new(phys.as_u64() + HHDM_RESPONSE.offset)
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
pub static ref MEMMAP_RESPONSE: &'static MemmapResponse = MEMMAP_REQUEST
|
||||
.response()
|
||||
|
||||
@ -1,6 +1,10 @@
|
||||
use lazy_static::lazy_static;
|
||||
use core::ops::Index;
|
||||
|
||||
use intbits::Bits;
|
||||
use x86_64::PhysAddr;
|
||||
use x86_64::VirtAddr;
|
||||
use x86_64::registers::control;
|
||||
use x86_64::registers::control::Cr4Flags;
|
||||
use x86_64::structures::paging::PageTable;
|
||||
use x86_64::structures::paging::PageTableFlags;
|
||||
|
||||
@ -25,62 +29,100 @@ pub fn unmap_page(_virt: VirtAddr) -> Result<(), ()> {
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub unsafe fn active_level_4_table() -> &'static mut PageTable {
|
||||
/// Safety: CR3 must never be modified while a PageTable returned from
|
||||
/// this function is in scope. Otherwise, it could point to stale or even
|
||||
/// invalid tables.
|
||||
pub unsafe fn active_root_table() -> (&'static mut PageTable, usize) {
|
||||
use x86_64::registers::control::Cr3;
|
||||
|
||||
let (level_4_table_frame, _) = Cr3::read();
|
||||
|
||||
let phys = level_4_table_frame.start_address();
|
||||
let virt: VirtAddr = VirtAddr::new(HHDM_RESPONSE.offset + phys.as_u64());
|
||||
let root_table_frame = Cr3::read().0;
|
||||
let virt = phys_to_virt(root_table_frame.start_address());
|
||||
let page_table_ptr: *mut PageTable = virt.as_mut_ptr();
|
||||
|
||||
unsafe { &mut *page_table_ptr }
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
pub static ref PML4: &'static mut PageTable = unsafe { active_level_4_table() };
|
||||
(
|
||||
unsafe { &mut *page_table_ptr },
|
||||
match control::Cr4::read().contains(Cr4Flags::L5_PAGING) {
|
||||
true => 5,
|
||||
false => 4,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub fn walk_tables() {
|
||||
iter_table(4, &PML4);
|
||||
iter_table(
|
||||
match control::Cr4::read().contains(Cr4Flags::L5_PAGING) {
|
||||
true => 5,
|
||||
false => 4,
|
||||
},
|
||||
unsafe { active_root_table().0 },
|
||||
);
|
||||
}
|
||||
|
||||
// Not used right now, helpful for debugging
|
||||
#[allow(dead_code)]
|
||||
pub fn iter_table(level: usize, table: &PageTable) {
|
||||
for (i, entry) in table.iter().enumerate() {
|
||||
if !entry.is_unused() & entry.flags().contains(PageTableFlags::PRESENT) {
|
||||
log_info!("L{} Entry {}: {:?}", level, i, entry);
|
||||
log_trace!("L{} Entry {}: {:?}", level, i, entry);
|
||||
if (level > 1) & !entry.flags().contains(PageTableFlags::HUGE_PAGE) {
|
||||
let phys = entry.frame().unwrap().start_address();
|
||||
let virt = phys.as_u64() + HHDM_RESPONSE.offset;
|
||||
let ptr = VirtAddr::new(virt).as_mut_ptr();
|
||||
let new_table: &PageTable = unsafe { &*ptr };
|
||||
let phys = entry.addr();
|
||||
let virt = phys_to_virt(phys).as_mut_ptr();
|
||||
let new_table: &PageTable = unsafe { &*virt };
|
||||
iter_table(level - 1, new_table);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
let l4_table = unsafe { active_level_4_table() };
|
||||
pub fn phys_to_virt(phys: PhysAddr) -> VirtAddr {
|
||||
VirtAddr::new(phys.as_u64() + HHDM_RESPONSE.offset)
|
||||
}
|
||||
|
||||
for (i, entry) in l4_table.iter().enumerate() {
|
||||
if !entry.is_unused() {
|
||||
log_info!("L4 Entry {}: {:?}", i, entry);
|
||||
|
||||
// get the physical address from the entry and convert it
|
||||
let phys = entry.frame().unwrap().start_address();
|
||||
let virt = phys.as_u64() + HHDM_RESPONSE.offset();
|
||||
let ptr = VirtAddr::new(virt).as_mut_ptr();
|
||||
let l3_table: &PageTable = unsafe { &*ptr };
|
||||
|
||||
// print non-empty entries of the level 3 table
|
||||
for (i, entry) in l3_table.iter().enumerate() {
|
||||
if !entry.is_unused() {
|
||||
log_info!(" L3 Entry {}: {:?}", i, entry);
|
||||
pub fn virt_to_phys(virt: VirtAddr) -> Option<PhysAddr> {
|
||||
let root_table = unsafe { active_root_table() };
|
||||
let mut current_table = root_table;
|
||||
let table_indices = [
|
||||
virt.as_u64().bits(0..=11) as usize, // Page offset
|
||||
virt.as_u64().bits(12..=20) as usize, // Page Table index
|
||||
virt.as_u64().bits(21..=29) as usize, // Page Directory index
|
||||
virt.as_u64().bits(30..=38) as usize, // Page Directory Pointer Table index
|
||||
virt.as_u64().bits(39..=47) as usize, // Page Map Level 4 index
|
||||
virt.as_u64().bits(48..=56) as usize, // Page Map Level 5 index
|
||||
];
|
||||
while current_table.1 > 1 {
|
||||
let current_table_entry = current_table.0.index(table_indices[current_table.1]);
|
||||
if current_table_entry
|
||||
.flags()
|
||||
.contains(PageTableFlags::PRESENT)
|
||||
&& !current_table_entry.is_unused()
|
||||
{
|
||||
if current_table_entry
|
||||
.flags()
|
||||
.contains(PageTableFlags::HUGE_PAGE)
|
||||
{
|
||||
if current_table.1 == 3 {
|
||||
// Huge page (1GiB), last 30 bits preserved
|
||||
return Some(PhysAddr::new(
|
||||
current_table_entry.addr().as_u64() | virt.as_u64().bits(0..=29),
|
||||
));
|
||||
} else if current_table.1 == 2 {
|
||||
// Large page (2MiB), last 21 bits preserved
|
||||
return Some(PhysAddr::new(
|
||||
current_table_entry.addr().as_u64() | virt.as_u64().bits(0..=20),
|
||||
));
|
||||
}
|
||||
} else if current_table.1 > 1 {
|
||||
current_table = (
|
||||
unsafe { &mut *phys_to_virt(current_table_entry.addr()).as_mut_ptr() }
|
||||
as &mut PageTable,
|
||||
current_table.1 - 1,
|
||||
);
|
||||
} else {
|
||||
return Some(PhysAddr::new(
|
||||
current_table_entry.addr().as_u64() | virt.as_u64().bits(0..=11),
|
||||
));
|
||||
}
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
Loading…
Reference in New Issue
Block a user