use core::fmt;
pub type PAddr = u64;
pub type VAddr = usize;
pub const BASE_PAGE_SIZE: u64 = 4096; pub const LARGE_PAGE_SIZE: u64 = 1024*1024*2; pub const HUGE_PAGE_SIZE: u64 = 1024*1024*1024;
pub const MAXPHYADDR: u64 = 52;
const ADDRESS_MASK: u64 = ((1 << MAXPHYADDR) - 1) & !0xfff;
pub type PML4 = [PML4Entry; 512];
pub type PDPT = [PDPTEntry; 512];
pub type PD = [PDEntry; 512];
pub type PT = [PTEntry; 512];
pub fn pml4_index(addr: VAddr) -> usize {
(addr >> 39) & 0b111111111
}
#[inline]
pub fn pdpt_index(addr: VAddr) -> usize {
(addr >> 30) & 0b111111111
}
#[inline]
pub fn pd_index(addr: VAddr) -> usize {
(addr >> 21) & 0b111111111
}
#[inline]
pub fn pt_index(addr: VAddr) -> usize {
(addr >> 12) & 0b111111111
}
bitflags! {
flags PML4Entry: u64 {
const PML4_P = 0b00000001,
const PML4_RW = 0b00000010,
const PML4_US = 0b00000100,
const PML4_PWT = 0b00001000,
const PML4_PCD = 0b00010000,
const PML4_A = 0b00100000,
const PML4_XD = 1 << 63,
}
}
impl PML4Entry {
pub fn new(pdpt: PAddr, flags: PML4Entry) -> PML4Entry {
assert!(pdpt % BASE_PAGE_SIZE == 0);
PML4Entry { bits: pdpt | flags.bits }
}
pub fn get_address(self) -> PAddr {
self.bits & ADDRESS_MASK
}
pub fn is_present(self) -> bool {
self.contains(PML4_P)
}
}
impl fmt::Debug for PML4Entry {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.bits)
}
}
bitflags! {
flags PDPTEntry: u64 {
const PDPT_P = 0b00000001,
const PDPT_RW = 0b00000010,
const PDPT_US = 0b00000100,
const PDPT_PWT = 0b00001000,
const PDPT_PCD = 0b00010000,
const PDPT_A = 0b00100000,
const PDPT_D = 0b01000000,
const PDPT_PS = 0b10000000,
const PDPT_G = 1<<8,
const PDPT_PAT = 1<<12,
const PDPT_XD = 1 << 63,
}
}
impl PDPTEntry {
pub fn new(pd: PAddr, flags: PDPTEntry) -> PDPTEntry {
assert!(pd % BASE_PAGE_SIZE == 0);
PDPTEntry { bits: pd | flags.bits }
}
pub fn get_address(self) -> PAddr {
self.bits & ADDRESS_MASK
}
pub fn is_present(self) -> bool {
self.contains(PDPT_P)
}
}
impl fmt::Debug for PDPTEntry {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.bits)
}
}
bitflags! {
flags PDEntry: u64 {
const PD_P = 0b00000001,
const PD_RW = 0b00000010,
const PD_US = 0b00000100,
const PD_PWT = 0b00001000,
const PD_PCD = 0b00010000,
const PD_A = 0b00100000,
const PD_D = 0b01000000,
const PD_PS = 0b10000000,
const PD_G = 1<<8,
const PD_PAT = 1<<12,
const PD_XD = 1 << 63,
}
}
impl PDEntry {
pub fn new(pt: PAddr, flags: PDEntry) -> PDEntry {
assert!(pt % BASE_PAGE_SIZE == 0);
PDEntry { bits: pt | flags.bits }
}
pub fn get_address(self) -> PAddr {
self.bits & ADDRESS_MASK
}
pub fn is_present(self) -> bool {
self.contains(PD_P)
}
}
impl fmt::Debug for PDEntry {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.bits)
}
}
bitflags! {
flags PTEntry: u64 {
const PT_P = 0b00000001,
const PT_RW = 0b00000010,
const PT_US = 0b00000100,
const PT_PWT = 0b00001000,
const PT_PCD = 0b00010000,
const PT_A = 0b00100000,
const PT_D = 0b01000000,
const PT_G = 1<<8,
const PT_XD = 1 << 63,
}
}
impl PTEntry {
pub fn new(page: PAddr, flags: PTEntry) -> PTEntry {
assert!(page % BASE_PAGE_SIZE == 0);
PTEntry{ bits: page | flags.bits }
}
pub fn get_address(self) -> PAddr {
self.bits & ADDRESS_MASK
}
pub fn is_present(self) -> bool {
self.contains(PT_P)
}
}
impl fmt::Debug for PTEntry {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.bits)
}
}