use std::ops::{BitOr, Deref};
use crate::bits::Bits;
use crate::gxa::Gpa;
#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq, Default, PartialOrd, Ord)]
pub struct PxeFlags(u64);
impl PxeFlags {
pub const ACCESSED: Self = Self(1 << 5);
pub const CACHE_DISABLED: Self = Self(1 << 4);
pub const DIRTY: Self = Self(1 << 6);
pub const LARGE_PAGE: Self = Self(1 << 7);
pub const NO_EXECUTE: Self = Self(1 << 63);
pub const PRESENT: Self = Self(1 << 0);
pub const TRANSITION: Self = Self(1 << 11);
pub const USER_ACCESSIBLE: Self = Self(1 << 2);
pub const WRITABLE: Self = Self(1 << 1);
pub const WRITE_THROUGH: Self = Self(1 << 3);
#[must_use]
pub fn new(bits: u64) -> Self {
Self(bits)
}
#[must_use]
pub fn present(&self) -> bool {
self.0.bit(0) != 0
}
#[must_use]
pub fn writable(&self) -> bool {
self.0.bit(1) != 0
}
#[must_use]
pub fn user_accessible(&self) -> bool {
self.0.bit(2) != 0
}
#[must_use]
pub fn write_through(&self) -> bool {
self.0.bit(3) != 0
}
#[must_use]
pub fn cache_disabled(&self) -> bool {
self.0.bit(4) != 0
}
#[must_use]
pub fn accessed(&self) -> bool {
self.0.bit(5) != 0
}
#[must_use]
pub fn dirty(&self) -> bool {
self.0.bit(6) != 0
}
#[must_use]
pub fn large_page(&self) -> bool {
self.0.bit(7) != 0
}
#[must_use]
pub fn transition(&self) -> bool {
self.0.bit(11) != 0
}
#[must_use]
pub fn no_execute(&self) -> bool {
self.0.bit(63) != 0
}
}
impl BitOr for PxeFlags {
type Output = Self;
fn bitor(self, rhs: Self) -> Self::Output {
Self::new(*self | *rhs)
}
}
impl Deref for PxeFlags {
type Target = u64;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq, Default, PartialOrd, Ord)]
pub struct Pfn(u64);
impl Pfn {
#[must_use]
pub const fn new(pfn: u64) -> Self {
Self(pfn)
}
#[must_use]
pub const fn u64(&self) -> u64 {
self.0
}
#[must_use]
pub const fn gpa(&self) -> Gpa {
Gpa::from_pfn(*self)
}
#[must_use]
pub const fn gpa_with_offset(&self, offset: u64) -> Gpa {
Gpa::from_pfn_with_offset(*self, offset)
}
}
impl From<u64> for Pfn {
fn from(value: u64) -> Self {
Self(value)
}
}
impl From<Pfn> for u64 {
fn from(value: Pfn) -> Self {
value.u64()
}
}
#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq, Default, PartialOrd, Ord)]
pub struct Pxe {
pub pfn: Pfn,
pub flags: PxeFlags,
}
impl Pxe {
#[must_use]
pub fn new(pfn: Pfn, flags: PxeFlags) -> Self {
Self { pfn, flags }
}
#[must_use]
pub fn present(&self) -> bool {
self.flags.present()
}
#[must_use]
pub fn large_page(&self) -> bool {
self.flags.large_page()
}
#[must_use]
pub fn transition(&self) -> bool {
!self.present() && self.flags.transition()
}
#[must_use]
pub fn writable(&self) -> bool {
self.flags.writable()
}
#[must_use]
pub fn executable(&self) -> bool {
!self.flags.no_execute()
}
#[must_use]
pub fn user_accessible(&self) -> bool {
self.flags.user_accessible()
}
}
impl From<u64> for Pxe {
fn from(value: u64) -> Self {
const PFN_MASK: u64 = 0xffff_ffff_f000;
const FLAGS_MASK: u64 = !PFN_MASK;
let pfn = Pfn::new((value & PFN_MASK) >> 12);
let flags = PxeFlags::new(value & FLAGS_MASK);
Self::new(pfn, flags)
}
}
impl From<Pxe> for u64 {
fn from(pxe: Pxe) -> Self {
debug_assert!(pxe.pfn.u64() <= 0xf_ffff_ffffu64);
*pxe.flags | (pxe.pfn.u64() << 12u64)
}
}