#![allow(dead_code)]
#![allow(unused_parens)]
use {
crate::{error::HypervisorError, x86_64::addr::{Addrtransfer, page_align}}, core::ptr::addr_of, modular_bitfield::{bitfield, prelude::B5}, static_assertions::const_assert_eq
};
pub const BASE_PAGE_SHIFT: usize = 12;
pub const BASE_PAGE_SIZE: usize = 4096;
pub const LARGE_PAGE_SIZE: usize = 1024 * 1024 * 2;
pub const HUGE_PAGE_SIZE: usize = 1024 * 1024 * 1024;
#[cfg(target_arch = "x86_64")]
pub const PML4_SLOT_SIZE: usize = HUGE_PAGE_SIZE * 512;
pub const CACHE_LINE_SIZE: usize = 64;
#[repr(C, align(4096))]
#[derive(Debug, Clone, Copy)]
pub struct PageTables {
pml4: Pml4,
pdpt: Pdpt,
pd: [Pd; 512],
}
impl PageTables {
pub fn init_hypervisor_paging<T: Addrtransfer>(&mut self, system_cr3: u64, trans: &mut T) {
let system_cr3 =page_align(system_cr3 as usize);
let system_pml4_va = trans.pa_into_va(system_cr3 as u64);
log::info!("virtual addr for cr3:{:#x}",system_pml4_va);
unsafe {
self.pml4.0.entries[256..].copy_from_slice(
core::slice::from_raw_parts((system_pml4_va as *const Entry).add(256), 256)
);
}
for entry in &mut self.pml4.0.entries[..255] {
*entry = Entry::new();
}
let ptr = self.pml4.0.entries[511];
log::info!("virtual addr for pml4:{:#x}", u64::from_ne_bytes(ptr.bytes));
}
pub fn build_identity<T: Addrtransfer>(&mut self, trans: &mut T) {
self.pml4.0.entries[0].set_present(true);
self.pml4.0.entries[0].set_writable(true);
self.pml4.0.entries[0].set_pfn(trans.va_into_pa(addr_of!(self.pdpt) as u64) >> BASE_PAGE_SHIFT);
let mut pa = 0;
for (i, pdpte) in self.pdpt.0.entries.iter_mut().enumerate() {
pdpte.set_present(true);
pdpte.set_writable(true);
pdpte.set_pfn(
trans.va_into_pa(addr_of!(self.pd[i]) as u64) >> BASE_PAGE_SHIFT,
);
for pde in &mut self.pd[i].0.entries {
pde.set_present(true);
pde.set_writable(true);
pde.set_large(true);
pde.set_pfn(pa >> BASE_PAGE_SHIFT);
pa += LARGE_PAGE_SIZE as u64;
}
}
}
pub fn get_pml4_pa<T: Addrtransfer>(&self, trans: &mut T) -> Result<u64, HypervisorError> {
let addr = addr_of!(self.pml4) as u64;
let pa = trans.va_into_pa(addr);
if pa.trailing_zeros() >= BASE_PAGE_SHIFT as u32 {
Ok(pa)
} else {
Err(HypervisorError::InvalidCr3BaseAddress)
}
}
}
#[derive(Debug, Clone, Copy)]
struct Pml4(Table);
#[derive(Debug, Clone, Copy)]
struct Pdpt(Table);
#[derive(Debug, Clone, Copy)]
struct Pd(Table);
#[derive(Debug, Clone, Copy)]
struct Pt(Table);
#[repr(C, align(4096))]
#[derive(Debug, Clone, Copy)]
struct Table {
entries: [Entry; 512],
}
const_assert_eq!(size_of::<Entry>(), size_of::<u64>());
#[bitfield(bits=64)]
#[derive(Debug,Clone, Copy)]
pub struct Entry{
pub present: bool,
pub writable: bool,
#[skip]
pading1: B5,
pub large: bool,
#[skip]
pading2: modular_bitfield::prelude::B4,
pub pfn: modular_bitfield::prelude::B40,
pading3: modular_bitfield::prelude::B11,
nx: bool,
}