|
|
@@ -1,7 +1,9 @@
|
|
|
use core::{marker::PhantomData, ptr::NonNull};
|
|
|
use eonix_mm::{
|
|
|
address::{Addr as _, PAddr},
|
|
|
- page_table::{PageAttribute, PageTableLevel, PagingMode, RawPageTable, PTE},
|
|
|
+ page_table::{
|
|
|
+ PageAttribute, PageTableLevel, PagingMode, RawAttribute, RawPageTable, TableAttribute, PTE,
|
|
|
+ },
|
|
|
paging::{PageBlock, PFN},
|
|
|
};
|
|
|
|
|
|
@@ -18,7 +20,6 @@ const PA_PWT: u64 = 0x008;
|
|
|
const PA_PCD: u64 = 0x010;
|
|
|
const PA_A: u64 = 0x020;
|
|
|
const PA_D: u64 = 0x040;
|
|
|
-#[allow(dead_code)]
|
|
|
const PA_PS: u64 = 0x080;
|
|
|
const PA_G: u64 = 0x100;
|
|
|
const PA_COW: u64 = 0x200;
|
|
|
@@ -84,117 +85,117 @@ impl<'a> RawPageTable<'a> for RawPageTable4Levels<'a> {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-impl PageAttribute for PageAttribute64 {
|
|
|
- fn new() -> Self {
|
|
|
- Self(PA_NXE)
|
|
|
+impl RawAttribute for PageAttribute64 {
|
|
|
+ fn null() -> Self {
|
|
|
+ Self(0)
|
|
|
}
|
|
|
|
|
|
- fn present(self, present: bool) -> Self {
|
|
|
- if present {
|
|
|
- Self(self.0 | PA_P)
|
|
|
- } else {
|
|
|
- Self(self.0 & !PA_P)
|
|
|
- }
|
|
|
- }
|
|
|
+ fn as_table_attr(self) -> Option<TableAttribute> {
|
|
|
+ let mut table_attr = TableAttribute::empty();
|
|
|
|
|
|
- fn write(self, write: bool) -> Self {
|
|
|
- if write {
|
|
|
- Self(self.0 | PA_RW)
|
|
|
- } else {
|
|
|
- Self(self.0 & !PA_RW)
|
|
|
+ if self.0 & PA_PS != 0 {
|
|
|
+ panic!("Encountered a huge page while parsing table attributes");
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- fn execute(self, execute: bool) -> Self {
|
|
|
- if execute {
|
|
|
- Self(self.0 & !PA_NXE)
|
|
|
- } else {
|
|
|
- Self(self.0 | PA_NXE)
|
|
|
+ if self.0 & PA_P != 0 {
|
|
|
+ table_attr |= TableAttribute::PRESENT;
|
|
|
+ }
|
|
|
+ if self.0 & PA_G != 0 {
|
|
|
+ table_attr |= TableAttribute::GLOBAL;
|
|
|
+ }
|
|
|
+ if self.0 & PA_US != 0 {
|
|
|
+ table_attr |= TableAttribute::USER;
|
|
|
+ }
|
|
|
+ if self.0 & PA_A != 0 {
|
|
|
+ table_attr |= TableAttribute::ACCESSED;
|
|
|
}
|
|
|
+
|
|
|
+ Some(table_attr)
|
|
|
}
|
|
|
|
|
|
- fn user(self, user: bool) -> Self {
|
|
|
- if user {
|
|
|
- Self(self.0 | PA_US)
|
|
|
- } else {
|
|
|
- Self(self.0 & !PA_US)
|
|
|
+ fn as_page_attr(self) -> Option<PageAttribute> {
|
|
|
+ let mut page_attr = PageAttribute::READ;
|
|
|
+
|
|
|
+ if self.0 & PA_P != 0 {
|
|
|
+ page_attr |= PageAttribute::PRESENT;
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- fn accessed(self, accessed: bool) -> Self {
|
|
|
- if accessed {
|
|
|
- Self(self.0 | PA_A)
|
|
|
- } else {
|
|
|
- Self(self.0 & !PA_A)
|
|
|
+ if self.0 & PA_RW != 0 {
|
|
|
+ page_attr |= PageAttribute::WRITE;
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- fn dirty(self, dirty: bool) -> Self {
|
|
|
- if dirty {
|
|
|
- Self(self.0 | PA_D)
|
|
|
- } else {
|
|
|
- Self(self.0 & !PA_D)
|
|
|
+ if self.0 & PA_NXE == 0 {
|
|
|
+ page_attr |= PageAttribute::EXECUTE;
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- fn global(self, global: bool) -> Self {
|
|
|
- if global {
|
|
|
- Self(self.0 | PA_G)
|
|
|
- } else {
|
|
|
- Self(self.0 & !PA_G)
|
|
|
+ if self.0 & PA_US != 0 {
|
|
|
+ page_attr |= PageAttribute::USER;
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- fn copy_on_write(self, cow: bool) -> Self {
|
|
|
- if cow {
|
|
|
- Self(self.0 | PA_COW)
|
|
|
- } else {
|
|
|
- Self(self.0 & !PA_COW)
|
|
|
+ if self.0 & PA_A != 0 {
|
|
|
+ page_attr |= PageAttribute::ACCESSED;
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- fn mapped(self, mmap: bool) -> Self {
|
|
|
- if mmap {
|
|
|
- Self(self.0 | PA_MMAP)
|
|
|
- } else {
|
|
|
- Self(self.0 & !PA_MMAP)
|
|
|
+ if self.0 & PA_D != 0 {
|
|
|
+ page_attr |= PageAttribute::DIRTY;
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- fn is_present(&self) -> bool {
|
|
|
- self.0 & PA_P != 0
|
|
|
- }
|
|
|
+ if self.0 & PA_G != 0 {
|
|
|
+ page_attr |= PageAttribute::GLOBAL;
|
|
|
+ }
|
|
|
|
|
|
- fn is_write(&self) -> bool {
|
|
|
- self.0 & PA_RW != 0
|
|
|
- }
|
|
|
+ if self.0 & PA_COW != 0 {
|
|
|
+ page_attr |= PageAttribute::COPY_ON_WRITE;
|
|
|
+ }
|
|
|
|
|
|
- fn is_execute(&self) -> bool {
|
|
|
- self.0 & PA_NXE == 0
|
|
|
- }
|
|
|
+ if self.0 & PA_MMAP != 0 {
|
|
|
+ page_attr |= PageAttribute::MAPPED;
|
|
|
+ }
|
|
|
|
|
|
- fn is_user(&self) -> bool {
|
|
|
- self.0 & PA_US != 0
|
|
|
- }
|
|
|
+ if self.0 & PA_ANON != 0 {
|
|
|
+ page_attr |= PageAttribute::ANONYMOUS;
|
|
|
+ }
|
|
|
|
|
|
- fn is_accessed(&self) -> bool {
|
|
|
- self.0 & PA_A != 0
|
|
|
+ Some(page_attr)
|
|
|
}
|
|
|
|
|
|
- fn is_dirty(&self) -> bool {
|
|
|
- self.0 & PA_D != 0
|
|
|
- }
|
|
|
+ fn from_table_attr(table_attr: TableAttribute) -> Self {
|
|
|
+ let mut raw_attr = PA_RW;
|
|
|
|
|
|
- fn is_global(&self) -> bool {
|
|
|
- self.0 & PA_G != 0
|
|
|
- }
|
|
|
+ for attr in table_attr.iter() {
|
|
|
+ match attr {
|
|
|
+ TableAttribute::PRESENT => raw_attr |= PA_P,
|
|
|
+ TableAttribute::GLOBAL => raw_attr |= PA_G,
|
|
|
+ TableAttribute::USER => raw_attr |= PA_US,
|
|
|
+ TableAttribute::ACCESSED => raw_attr |= PA_A,
|
|
|
+ _ => unreachable!("Invalid table attribute"),
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- fn is_copy_on_write(&self) -> bool {
|
|
|
- self.0 & PA_COW != 0
|
|
|
- }
|
|
|
+ Self(raw_attr)
|
|
|
+ }
|
|
|
+
|
|
|
+ fn from_page_attr(page_attr: PageAttribute) -> Self {
|
|
|
+ let mut raw_attr = PA_NXE;
|
|
|
+
|
|
|
+ for attr in page_attr.iter() {
|
|
|
+ match attr {
|
|
|
+ PageAttribute::PRESENT => raw_attr |= PA_P,
|
|
|
+ PageAttribute::READ => {}
|
|
|
+ PageAttribute::WRITE => raw_attr |= PA_RW,
|
|
|
+ PageAttribute::EXECUTE => raw_attr &= !PA_NXE,
|
|
|
+ PageAttribute::USER => raw_attr |= PA_US,
|
|
|
+ PageAttribute::ACCESSED => raw_attr |= PA_A,
|
|
|
+ PageAttribute::DIRTY => raw_attr |= PA_D,
|
|
|
+ PageAttribute::GLOBAL => raw_attr |= PA_G,
|
|
|
+ PageAttribute::COPY_ON_WRITE => raw_attr |= PA_COW,
|
|
|
+ PageAttribute::MAPPED => raw_attr |= PA_MMAP,
|
|
|
+ PageAttribute::ANONYMOUS => raw_attr |= PA_ANON,
|
|
|
+ _ => unreachable!("Invalid page attribute"),
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- fn is_mapped(&self) -> bool {
|
|
|
- self.0 & PA_MMAP != 0
|
|
|
+ Self(raw_attr)
|
|
|
}
|
|
|
}
|
|
|
|