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",
|
"sptr",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "align-address"
|
|
||||||
version = "0.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "cee078b3ed87e2621e0389729e2f032cc0408a4548768ced01678c9451c62237"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.5.1"
|
version = "1.5.1"
|
||||||
@ -73,17 +67,6 @@ version = "0.4.7"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b7ac824320a75a52197e8f2d787f6a38b6718bb6897a35142d749af3c0e8f4fe"
|
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]]
|
[[package]]
|
||||||
name = "intbits"
|
name = "intbits"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
@ -92,12 +75,11 @@ checksum = "5170c2c8ecda29c1bccb9d95ccbe107bc75fa084dc0c9c6087e719f9d46330e5"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kernel"
|
name = "kernel"
|
||||||
version = "0.3.1"
|
version = "0.3.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"acid_alloc",
|
"acid_alloc",
|
||||||
"enumflags2",
|
"enumflags2",
|
||||||
"flagset",
|
"flagset",
|
||||||
"free-list",
|
|
||||||
"intbits",
|
"intbits",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"libgila",
|
"libgila",
|
||||||
@ -218,12 +200,6 @@ version = "1.2.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "smallvec"
|
|
||||||
version = "1.15.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "spin"
|
name = "spin"
|
||||||
version = "0.9.8"
|
version = "0.9.8"
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
timeout: 2
|
timeout: 1
|
||||||
wallpaper: boot():/bg.png
|
wallpaper: boot():/bg.png
|
||||||
wallpaper_style: centered
|
wallpaper_style: centered
|
||||||
|
|
||||||
/Gila
|
/Gila
|
||||||
protocol: limine
|
protocol: limine
|
||||||
kernel_path: boot():/boot/${ARCH}/gila
|
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
|
kaslr: yes
|
||||||
randomize_hhdm_base: yes
|
randomize_hhdm_base: yes
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "kernel"
|
name = "kernel"
|
||||||
version = "0.3.1"
|
version = "0.3.2"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|
||||||
@ -8,7 +8,6 @@ license = "MIT"
|
|||||||
acid_alloc = { version = "0.1.0", features = ["alloc"] }
|
acid_alloc = { version = "0.1.0", features = ["alloc"] }
|
||||||
enumflags2 = "0.7.12"
|
enumflags2 = "0.7.12"
|
||||||
flagset = "0.4.7"
|
flagset = "0.4.7"
|
||||||
free-list = { version = "0.3.1", features = ["x86_64"] }
|
|
||||||
intbits = "0.2.0"
|
intbits = "0.2.0"
|
||||||
lazy_static = { version = "1.5.0", default-features = false, features = ["spin_no_std"] }
|
lazy_static = { version = "1.5.0", default-features = false, features = ["spin_no_std"] }
|
||||||
limine = "0.6.5"
|
limine = "0.6.5"
|
||||||
|
|||||||
@ -26,6 +26,8 @@ pub fn amd_v_supported() -> bool {
|
|||||||
pub fn enable_svm() {
|
pub fn enable_svm() {
|
||||||
let mut efer = x86_64::registers::model_specific::Efer::read().bits();
|
let mut efer = x86_64::registers::model_specific::Efer::read().bits();
|
||||||
efer.set_bit(12, true);
|
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));
|
assert!(efer.bit(12));
|
||||||
unsafe { x86_64::registers::model_specific::Efer::write(EferFlags::from_bits_retain(efer)) };
|
unsafe { x86_64::registers::model_specific::Efer::write(EferFlags::from_bits_retain(efer)) };
|
||||||
}
|
}
|
||||||
|
|||||||
@ -70,6 +70,7 @@ impl Logger {
|
|||||||
line: u32,
|
line: u32,
|
||||||
column: u32,
|
column: u32,
|
||||||
) {
|
) {
|
||||||
|
if level <= self.level {
|
||||||
for dev in &self.devices {
|
for dev in &self.devices {
|
||||||
let message = format!(
|
let message = format!(
|
||||||
"{} {}:{},{}- {}",
|
"{} {}:{},{}- {}",
|
||||||
@ -82,6 +83,7 @@ impl Logger {
|
|||||||
dev(&message)
|
dev(&message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
pub fn add_device(&mut self, device: Box<dyn Fn(&str) + Send + Sync>) {
|
pub fn add_device(&mut self, device: Box<dyn Fn(&str) + Send + Sync>) {
|
||||||
self.devices.push(device);
|
self.devices.push(device);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,6 +16,8 @@ mod panic;
|
|||||||
mod process;
|
mod process;
|
||||||
mod util;
|
mod util;
|
||||||
|
|
||||||
|
use core::ptr::addr_of;
|
||||||
|
|
||||||
use arch::x86_64::interrupts::IDT;
|
use arch::x86_64::interrupts::IDT;
|
||||||
use arch::x86_64::serial::SerialPort;
|
use arch::x86_64::serial::SerialPort;
|
||||||
use boot::{BASE_REVISION, params, *};
|
use boot::{BASE_REVISION, params, *};
|
||||||
@ -29,6 +31,7 @@ use limine::firmware::{
|
|||||||
FIRMWARE_TYPE_EFI32, FIRMWARE_TYPE_EFI64, FIRMWARE_TYPE_SBI, FIRMWARE_TYPE_X86BIOS,
|
FIRMWARE_TYPE_EFI32, FIRMWARE_TYPE_EFI64, FIRMWARE_TYPE_SBI, FIRMWARE_TYPE_X86BIOS,
|
||||||
};
|
};
|
||||||
use spin::mutex::Mutex;
|
use spin::mutex::Mutex;
|
||||||
|
use x86_64::VirtAddr;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::{
|
arch::{
|
||||||
@ -38,7 +41,7 @@ use crate::{
|
|||||||
gdt::dump_gdt,
|
gdt::dump_gdt,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
memory::{paging, phys_to_virt},
|
memory::paging::{self, active_root_table, virt_to_phys},
|
||||||
};
|
};
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
@ -95,6 +98,9 @@ unsafe extern "C" fn main() -> ! {
|
|||||||
EXECUTABLE_FILE_RESPONSE.executable_file().path()
|
EXECUTABLE_FILE_RESPONSE.executable_file().path()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let log_level = log::LOGGER.lock().level;
|
||||||
|
log_info!("Log level: {:?}", log_level);
|
||||||
|
|
||||||
// Branding
|
// Branding
|
||||||
for line in ASCII_LOGO {
|
for line in ASCII_LOGO {
|
||||||
let mut locked = SERIAL_3F8.lock();
|
let mut locked = SERIAL_3F8.lock();
|
||||||
@ -171,13 +177,24 @@ unsafe extern "C" fn main() -> ! {
|
|||||||
}
|
}
|
||||||
log_info!("Virtualization provider: {:?}", virt_supported());
|
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!(
|
log_info!(
|
||||||
"Virtual address of current L4 table: 0x{:x}",
|
"Root page table is Level {} at 0x{:x}",
|
||||||
phys_to_virt(l4_start)
|
root_ptable_info.1,
|
||||||
|
addr_of!(*root_ptable_info.0) as usize
|
||||||
);
|
);
|
||||||
paging::walk_tables();
|
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());
|
log_info!("Long mode: {}", asm::long_mode());
|
||||||
dump_gdt();
|
dump_gdt();
|
||||||
|
|
||||||
|
|||||||
@ -12,16 +12,11 @@ use lazy_static::lazy_static;
|
|||||||
use limine::request::{ExecutableAddressRequest, HhdmRepsonse, HhdmRequest};
|
use limine::request::{ExecutableAddressRequest, HhdmRepsonse, HhdmRequest};
|
||||||
use limine::request::{MemmapRequest, MemmapResponse};
|
use limine::request::{MemmapRequest, MemmapResponse};
|
||||||
use talc::*;
|
use talc::*;
|
||||||
use x86_64::{PhysAddr, VirtAddr};
|
|
||||||
|
|
||||||
pub extern crate alloc;
|
pub extern crate alloc;
|
||||||
|
|
||||||
pub mod paging;
|
pub mod paging;
|
||||||
|
|
||||||
pub fn phys_to_virt(phys: PhysAddr) -> VirtAddr {
|
|
||||||
VirtAddr::new(phys.as_u64() + HHDM_RESPONSE.offset)
|
|
||||||
}
|
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub static ref MEMMAP_RESPONSE: &'static MemmapResponse = MEMMAP_REQUEST
|
pub static ref MEMMAP_RESPONSE: &'static MemmapResponse = MEMMAP_REQUEST
|
||||||
.response()
|
.response()
|
||||||
|
|||||||
@ -1,6 +1,10 @@
|
|||||||
use lazy_static::lazy_static;
|
use core::ops::Index;
|
||||||
|
|
||||||
|
use intbits::Bits;
|
||||||
use x86_64::PhysAddr;
|
use x86_64::PhysAddr;
|
||||||
use x86_64::VirtAddr;
|
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::PageTable;
|
||||||
use x86_64::structures::paging::PageTableFlags;
|
use x86_64::structures::paging::PageTableFlags;
|
||||||
|
|
||||||
@ -25,62 +29,100 @@ pub fn unmap_page(_virt: VirtAddr) -> Result<(), ()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[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;
|
use x86_64::registers::control::Cr3;
|
||||||
|
let root_table_frame = Cr3::read().0;
|
||||||
let (level_4_table_frame, _) = Cr3::read();
|
let virt = phys_to_virt(root_table_frame.start_address());
|
||||||
|
|
||||||
let phys = level_4_table_frame.start_address();
|
|
||||||
let virt: VirtAddr = VirtAddr::new(HHDM_RESPONSE.offset + phys.as_u64());
|
|
||||||
let page_table_ptr: *mut PageTable = virt.as_mut_ptr();
|
let page_table_ptr: *mut PageTable = virt.as_mut_ptr();
|
||||||
|
|
||||||
unsafe { &mut *page_table_ptr }
|
(
|
||||||
}
|
unsafe { &mut *page_table_ptr },
|
||||||
|
match control::Cr4::read().contains(Cr4Flags::L5_PAGING) {
|
||||||
lazy_static! {
|
true => 5,
|
||||||
pub static ref PML4: &'static mut PageTable = unsafe { active_level_4_table() };
|
false => 4,
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn walk_tables() {
|
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)]
|
#[allow(dead_code)]
|
||||||
pub fn iter_table(level: usize, table: &PageTable) {
|
pub fn iter_table(level: usize, table: &PageTable) {
|
||||||
for (i, entry) in table.iter().enumerate() {
|
for (i, entry) in table.iter().enumerate() {
|
||||||
if !entry.is_unused() & entry.flags().contains(PageTableFlags::PRESENT) {
|
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) {
|
if (level > 1) & !entry.flags().contains(PageTableFlags::HUGE_PAGE) {
|
||||||
let phys = entry.frame().unwrap().start_address();
|
let phys = entry.addr();
|
||||||
let virt = phys.as_u64() + HHDM_RESPONSE.offset;
|
let virt = phys_to_virt(phys).as_mut_ptr();
|
||||||
let ptr = VirtAddr::new(virt).as_mut_ptr();
|
let new_table: &PageTable = unsafe { &*virt };
|
||||||
let new_table: &PageTable = unsafe { &*ptr };
|
|
||||||
iter_table(level - 1, new_table);
|
iter_table(level - 1, new_table);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
pub fn phys_to_virt(phys: PhysAddr) -> VirtAddr {
|
||||||
let l4_table = unsafe { active_level_4_table() };
|
VirtAddr::new(phys.as_u64() + HHDM_RESPONSE.offset)
|
||||||
|
}
|
||||||
|
|
||||||
for (i, entry) in l4_table.iter().enumerate() {
|
pub fn virt_to_phys(virt: VirtAddr) -> Option<PhysAddr> {
|
||||||
if !entry.is_unused() {
|
let root_table = unsafe { active_root_table() };
|
||||||
log_info!("L4 Entry {}: {:?}", i, entry);
|
let mut current_table = root_table;
|
||||||
|
let table_indices = [
|
||||||
// get the physical address from the entry and convert it
|
virt.as_u64().bits(0..=11) as usize, // Page offset
|
||||||
let phys = entry.frame().unwrap().start_address();
|
virt.as_u64().bits(12..=20) as usize, // Page Table index
|
||||||
let virt = phys.as_u64() + HHDM_RESPONSE.offset();
|
virt.as_u64().bits(21..=29) as usize, // Page Directory index
|
||||||
let ptr = VirtAddr::new(virt).as_mut_ptr();
|
virt.as_u64().bits(30..=38) as usize, // Page Directory Pointer Table index
|
||||||
let l3_table: &PageTable = unsafe { &*ptr };
|
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
|
||||||
// print non-empty entries of the level 3 table
|
];
|
||||||
for (i, entry) in l3_table.iter().enumerate() {
|
while current_table.1 > 1 {
|
||||||
if !entry.is_unused() {
|
let current_table_entry = current_table.0.index(table_indices[current_table.1]);
|
||||||
log_info!(" L3 Entry {}: {:?}", i, entry);
|
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