mirror of
https://github.com/phil-opp/blog_os.git
synced 2025-12-16 14:27:49 +00:00
Finish basics of new paging module
This commit is contained in:
109
src/memory/paging/table.rs
Normal file
109
src/memory/paging/table.rs
Normal file
@@ -0,0 +1,109 @@
|
||||
use memory::FrameAllocator;
|
||||
use memory::paging::{ENTRY_COUNT, Page};
|
||||
use memory::paging::entry::*;
|
||||
use core::ops::{Index, IndexMut};
|
||||
use core::marker::PhantomData;
|
||||
|
||||
pub const P4: *mut Table<Level4> = 0xffffffff_fffff000 as *mut _;
|
||||
|
||||
pub struct Table<L: TableLevel> {
|
||||
entries: [Entry; ENTRY_COUNT],
|
||||
_phantom: PhantomData<L>,
|
||||
}
|
||||
|
||||
impl<L> Table<L> where L: TableLevel
|
||||
{
|
||||
pub fn zero(&mut self) {
|
||||
for entry in self.entries.iter_mut() {
|
||||
entry.set_unused();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<L> Table<L> where L: HierachicalLevel
|
||||
{
|
||||
pub fn next_table(&self, index: usize) -> Option<&Table<L::NextLevel>> {
|
||||
self.next_table_address(index).map(|t| unsafe { &*(t as *const _) })
|
||||
}
|
||||
|
||||
pub fn next_table_mut(&mut self, index: usize) -> Option<&mut Table<L::NextLevel>> {
|
||||
self.next_table_address(index).map(|t| unsafe { &mut *(t as *mut _) })
|
||||
}
|
||||
|
||||
pub fn next_table_create<A>(&mut self,
|
||||
index: usize,
|
||||
allocator: &mut A)
|
||||
-> &mut Table<L::NextLevel>
|
||||
where A: FrameAllocator
|
||||
{
|
||||
if let None = self.next_table_address(index) {
|
||||
assert!(!self.entries[index].flags().contains(HUGE_PAGE),
|
||||
"mapping code does not support huge pages");
|
||||
let frame = allocator.allocate_frame().expect("no frames available");
|
||||
self.entries[index].set(frame, PRESENT | WRITABLE);
|
||||
self.next_table_mut(index).unwrap().zero();
|
||||
}
|
||||
self.next_table_mut(index).unwrap()
|
||||
}
|
||||
|
||||
fn next_table_address(&self, index: usize) -> Option<usize> {
|
||||
let entry_flags = self[index].flags();
|
||||
if entry_flags.contains(PRESENT) && !entry_flags.contains(HUGE_PAGE) {
|
||||
let table_page = Page::containing_address(self as *const _ as usize);
|
||||
assert!(table_page.number >= 0o_777_000_000_000);
|
||||
let next_table_page = Page {
|
||||
number: ((table_page.number << 9) & 0o_777_777_777_777) | index,
|
||||
};
|
||||
Some(next_table_page.start_address())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<L> Index<usize> for Table<L> where L: TableLevel
|
||||
{
|
||||
type Output = Entry;
|
||||
|
||||
fn index(&self, index: usize) -> &Entry {
|
||||
&self.entries[index]
|
||||
}
|
||||
}
|
||||
|
||||
impl<L> IndexMut<usize> for Table<L> where L: TableLevel
|
||||
{
|
||||
fn index_mut(&mut self, index: usize) -> &mut Entry {
|
||||
&mut self.entries[index]
|
||||
}
|
||||
}
|
||||
|
||||
pub trait TableLevel {}
|
||||
|
||||
pub enum Level4 {}
|
||||
#[allow(dead_code)]
|
||||
enum Level3 {}
|
||||
#[allow(dead_code)]
|
||||
enum Level2 {}
|
||||
#[allow(dead_code)]
|
||||
enum Level1 {}
|
||||
|
||||
impl TableLevel for Level4 {}
|
||||
impl TableLevel for Level3 {}
|
||||
impl TableLevel for Level2 {}
|
||||
impl TableLevel for Level1 {}
|
||||
|
||||
trait HierachicalLevel: TableLevel {
|
||||
type NextLevel: TableLevel;
|
||||
}
|
||||
|
||||
impl HierachicalLevel for Level4 {
|
||||
type NextLevel = Level3;
|
||||
}
|
||||
|
||||
impl HierachicalLevel for Level3 {
|
||||
type NextLevel = Level2;
|
||||
}
|
||||
|
||||
impl HierachicalLevel for Level2 {
|
||||
type NextLevel = Level1;
|
||||
}
|
||||
Reference in New Issue
Block a user