mirror of
https://github.com/phil-opp/blog_os.git
synced 2025-12-16 22:37:49 +00:00
Use type system tricks to make next_table methods safe
This commit is contained in:
@@ -1,20 +1,24 @@
|
|||||||
|
use core::marker::PhantomData;
|
||||||
use core::ops::{Index, IndexMut};
|
use core::ops::{Index, IndexMut};
|
||||||
use memory::paging::entry::*;
|
use memory::paging::entry::*;
|
||||||
use memory::paging::ENTRY_COUNT;
|
use memory::paging::ENTRY_COUNT;
|
||||||
|
|
||||||
pub const P4: *mut Table = 0xffffffff_fffff000 as *mut _;
|
pub const P4: *mut Table<Level4> = 0xffffffff_fffff000 as *mut _;
|
||||||
|
|
||||||
pub struct Table {
|
pub struct Table<L: TableLevel> {
|
||||||
entries: [Entry; ENTRY_COUNT],
|
entries: [Entry; ENTRY_COUNT],
|
||||||
|
level: PhantomData<L>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Table {
|
impl<L> Table<L> where L: TableLevel {
|
||||||
pub fn zero(&mut self) {
|
pub fn zero(&mut self) {
|
||||||
for entry in self.entries.iter_mut() {
|
for entry in self.entries.iter_mut() {
|
||||||
entry.set_unused();
|
entry.set_unused();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<L> Table<L> where L: HierarchicalLevel {
|
||||||
fn next_table_address(&self, index: usize) -> Option<usize> {
|
fn next_table_address(&self, index: usize) -> Option<usize> {
|
||||||
let entry_flags = self[index].flags();
|
let entry_flags = self[index].flags();
|
||||||
if entry_flags.contains(PRESENT) && !entry_flags.contains(HUGE_PAGE) {
|
if entry_flags.contains(PRESENT) && !entry_flags.contains(HUGE_PAGE) {
|
||||||
@@ -25,18 +29,18 @@ impl Table {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next_table(&self, index: usize) -> Option<&Table> {
|
pub fn next_table(&self, index: usize) -> Option<&Table<L::NextLevel>> {
|
||||||
self.next_table_address(index)
|
self.next_table_address(index)
|
||||||
.map(|address| unsafe { &*(address as *const _) })
|
.map(|address| unsafe { &*(address as *const _) })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next_table_mut(&mut self, index: usize) -> Option<&mut Table> {
|
pub fn next_table_mut(&mut self, index: usize) -> Option<&mut Table<L::NextLevel>> {
|
||||||
self.next_table_address(index)
|
self.next_table_address(index)
|
||||||
.map(|address| unsafe { &mut *(address as *mut _) })
|
.map(|address| unsafe { &mut *(address as *mut _) })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Index<usize> for Table {
|
impl<L> Index<usize> for Table<L> where L: TableLevel {
|
||||||
type Output = Entry;
|
type Output = Entry;
|
||||||
|
|
||||||
fn index(&self, index: usize) -> &Entry {
|
fn index(&self, index: usize) -> &Entry {
|
||||||
@@ -44,8 +48,36 @@ impl Index<usize> for Table {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IndexMut<usize> for Table {
|
impl<L> IndexMut<usize> for Table<L> where L: TableLevel {
|
||||||
fn index_mut(&mut self, index: usize) -> &mut Entry {
|
fn index_mut(&mut self, index: usize) -> &mut Entry {
|
||||||
&mut self.entries[index]
|
&mut self.entries[index]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait TableLevel {}
|
||||||
|
|
||||||
|
pub enum Level4 {}
|
||||||
|
pub enum Level3 {}
|
||||||
|
pub enum Level2 {}
|
||||||
|
pub enum Level1 {}
|
||||||
|
|
||||||
|
impl TableLevel for Level4 {}
|
||||||
|
impl TableLevel for Level3 {}
|
||||||
|
impl TableLevel for Level2 {}
|
||||||
|
impl TableLevel for Level1 {}
|
||||||
|
|
||||||
|
pub trait HierarchicalLevel: TableLevel {
|
||||||
|
type NextLevel: TableLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl HierarchicalLevel for Level4 {
|
||||||
|
type NextLevel = Level3;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl HierarchicalLevel for Level3 {
|
||||||
|
type NextLevel = Level2;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl HierarchicalLevel for Level2 {
|
||||||
|
type NextLevel = Level1;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user