Support more operations on PageFlags

This commit is contained in:
Jeremy Soller
2021-05-03 16:39:04 -06:00
parent 2f74326384
commit 5e47692b8d
+55 -1
View File
@@ -1,4 +1,7 @@
use core::marker::PhantomData;
use core::{
fmt,
marker::PhantomData
};
use crate::Arch;
@@ -21,6 +24,18 @@ impl<A: Arch> PageFlags<A> {
}
}
#[inline(always)]
pub fn new_table() -> Self {
unsafe {
Self::from_data(
// Flags set to present, kernel space, read-only, no-execute by default
A::ENTRY_FLAG_DEFAULT_TABLE |
A::ENTRY_FLAG_READONLY |
A::ENTRY_FLAG_NO_EXEC
)
}
}
#[inline(always)]
pub unsafe fn from_data(data: usize) -> Self {
Self { data, phantom: PhantomData }
@@ -31,6 +46,7 @@ impl<A: Arch> PageFlags<A> {
self.data
}
#[must_use]
#[inline(always)]
pub fn custom_flag(mut self, flag: usize, value: bool) -> Self {
if value {
@@ -41,11 +57,28 @@ impl<A: Arch> PageFlags<A> {
self
}
#[inline(always)]
pub fn has_flag(&self, flag: usize) -> bool {
self.data & flag == flag
}
#[inline(always)]
pub fn has_present(&self) -> bool {
self.has_flag(A::ENTRY_FLAG_PRESENT)
}
#[must_use]
#[inline(always)]
pub fn user(self, value: bool) -> Self {
self.custom_flag(A::ENTRY_FLAG_USER, value)
}
#[inline(always)]
pub fn has_user(&self) -> bool {
self.has_flag(A::ENTRY_FLAG_USER)
}
#[must_use]
#[inline(always)]
pub fn write(self, value: bool) -> Self {
// Architecture may use readonly or readwrite, support either
@@ -53,6 +86,13 @@ impl<A: Arch> PageFlags<A> {
.custom_flag(A::ENTRY_FLAG_READWRITE, value)
}
#[inline(always)]
pub fn has_write(&self) -> bool {
// Architecture may use readonly or readwrite, support either
self.data & (A::ENTRY_FLAG_READONLY | A::ENTRY_FLAG_READWRITE) == A::ENTRY_FLAG_READWRITE
}
#[must_use]
#[inline(always)]
pub fn execute(self, value: bool) -> Self {
//TODO: write xor execute?
@@ -60,4 +100,18 @@ impl<A: Arch> PageFlags<A> {
self.custom_flag(A::ENTRY_FLAG_NO_EXEC, !value)
.custom_flag(A::ENTRY_FLAG_EXEC, value)
}
#[inline(always)]
pub fn has_execute(&self) -> bool {
// Architecture may use no exec or exec, support either
self.data & (A::ENTRY_FLAG_NO_EXEC | A::ENTRY_FLAG_EXEC) == A::ENTRY_FLAG_EXEC
}
}
impl<A: Arch> fmt::Debug for PageFlags<A> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("PageFlags")
.field("data", &self.data)
.finish()
}
}