[WIP]: memory paging
This commit is contained in:
parent
f300229fa4
commit
23fe830220
6
Cargo.lock
generated
6
Cargo.lock
generated
@ -2,6 +2,7 @@
|
|||||||
name = "mahdi_os"
|
name = "mahdi_os"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"multiboot2 0.1.0 (git+https://github.com/phil-opp/multiboot2-elf64)",
|
"multiboot2 0.1.0 (git+https://github.com/phil-opp/multiboot2-elf64)",
|
||||||
"rlibc 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rlibc 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"spin 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"spin 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -12,6 +13,11 @@ name = "bitflags"
|
|||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "multiboot2"
|
name = "multiboot2"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
@ -9,6 +9,7 @@ crate-type = ["staticlib"]
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
rlibc = "0.1.4"
|
rlibc = "0.1.4"
|
||||||
spin = "0.3.4"
|
spin = "0.3.4"
|
||||||
|
bitflags = "0.7.0"
|
||||||
|
|
||||||
[dependencies.multiboot2]
|
[dependencies.multiboot2]
|
||||||
git = "https://github.com/phil-opp/multiboot2-elf64"
|
git = "https://github.com/phil-opp/multiboot2-elf64"
|
||||||
|
@ -13,6 +13,9 @@ start:
|
|||||||
call check_long_mode
|
call check_long_mode
|
||||||
|
|
||||||
call set_up_page_tables
|
call set_up_page_tables
|
||||||
|
mov eax, p4_table
|
||||||
|
or eax, 0b11 ; present + writable
|
||||||
|
mov [p4_table + 511 * 8], eax
|
||||||
call enable_paging
|
call enable_paging
|
||||||
|
|
||||||
call set_up_SSE
|
call set_up_SSE
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
#![feature(unique)]
|
#![feature(unique)]
|
||||||
#![feature(const_fn)]
|
#![feature(const_fn)]
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate bitflags;
|
||||||
extern crate rlibc;
|
extern crate rlibc;
|
||||||
extern crate spin;
|
extern crate spin;
|
||||||
extern crate multiboot2;
|
extern crate multiboot2;
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
pub use self::area_frame_allocator::AreaFrameAllocator;
|
pub use self::area_frame_allocator::AreaFrameAllocator;
|
||||||
|
use self::paging::PhysicalAddress;
|
||||||
|
|
||||||
mod area_frame_allocator;
|
mod area_frame_allocator;
|
||||||
|
mod paging;
|
||||||
|
|
||||||
pub const PAGE_SIZE: usize = 4096;
|
pub const PAGE_SIZE: usize = 4096;
|
||||||
|
|
||||||
@ -12,6 +15,10 @@ impl Frame {
|
|||||||
fn containing_address(address: usize) -> Frame {
|
fn containing_address(address: usize) -> Frame {
|
||||||
Frame { number: address / PAGE_SIZE }
|
Frame { number: address / PAGE_SIZE }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn start_address(&self) -> PhysicalAddress {
|
||||||
|
self.number * PAGE_SIZE
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait FrameAllocator {
|
pub trait FrameAllocator {
|
||||||
|
49
src/memory/paging/entry.rs
Normal file
49
src/memory/paging/entry.rs
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
use memory::PAGE_SIZE;
|
||||||
|
|
||||||
|
pub struct Entry(u64);
|
||||||
|
|
||||||
|
impl Entry {
|
||||||
|
pub fn is_unused(&self) -> bool {
|
||||||
|
self.0 == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_unused(&mut self) {
|
||||||
|
self.0 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn flags(&self) -> EntryFlags {
|
||||||
|
EntryFlags::from_bits_truncate(self.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pointed_frame(&self) -> Option<Frame> {
|
||||||
|
if self.flags().contains(PRESENT) {
|
||||||
|
Some(Frame::containing_address(
|
||||||
|
self.0 as usize & 0x000fffff_fffff000
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set (&mut self, frame: Frame, flags: EntryFlags) {
|
||||||
|
assert!(frame.start_address() & !x000fffff_fffff000 == 0);
|
||||||
|
self.0 = (frame.start_address() as u64) | flags.bits();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
pub flags EntryFlags: u64 {
|
||||||
|
const PRESENT = 1 << 0,
|
||||||
|
const WRITABLE = 1 << 1,
|
||||||
|
const USER_ACCESSABLE = 1 << 2,
|
||||||
|
const WRITE_THROUGH = 1 << 3,
|
||||||
|
const NO_CACHE = 1 << 4,
|
||||||
|
const ACCESSED = 1 << 5,
|
||||||
|
const DIRTY = 1 << 6,
|
||||||
|
const HUGE_PAGE = 1 << 7,
|
||||||
|
const GLOBAL = 1 << 8,
|
||||||
|
const NO_EXECUTE = 1 << 63,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
57
src/memory/paging/mod.rs
Normal file
57
src/memory/paging/mod.rs
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
use memory::PAGE_SIZE;
|
||||||
|
use memory::Frame;
|
||||||
|
|
||||||
|
const ENTRY_COUNT: usize = 512;
|
||||||
|
|
||||||
|
pub type PhysicalAddress = usize;
|
||||||
|
pub type VirtualAddress = usize;
|
||||||
|
|
||||||
|
pub struct Page {
|
||||||
|
number: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Entry(u64);
|
||||||
|
|
||||||
|
impl Entry {
|
||||||
|
pub fn is_unused(&self) -> bool {
|
||||||
|
self.0 == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_unused(&mut self) {
|
||||||
|
self.0 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn flags(&self) -> EntryFlags {
|
||||||
|
EntryFlags::from_bits_truncate(self.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pointed_frame(&self) -> Option<Frame> {
|
||||||
|
if self.flags().contains(PRESENT) {
|
||||||
|
Some(Frame::containing_address(
|
||||||
|
self.0 as usize & 0x000fffff_fffff000
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set(&mut self, frame: Frame, flags: EntryFlags) {
|
||||||
|
assert!(frame.start_address() & !0x000fffff_fffff000 == 0);
|
||||||
|
self.0 = (frame.start_address() as u64) | flags.bits();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
pub flags EntryFlags: u64 {
|
||||||
|
const PRESENT = 1 << 0,
|
||||||
|
const WRITABLE = 1 << 1,
|
||||||
|
const USER_ACCESSABLE = 1 << 2,
|
||||||
|
const WRITE_THROUGH = 1 << 3,
|
||||||
|
const NO_CACHE = 1 << 4,
|
||||||
|
const ACCESSED = 1 << 5,
|
||||||
|
const DIRTY = 1 << 6,
|
||||||
|
const HUGE_PAGE = 1 << 7,
|
||||||
|
const GLOBAL = 1 << 8,
|
||||||
|
const NO_EXECUTE = 1 << 63,
|
||||||
|
}
|
||||||
|
}
|
89
src/memory/paging/table.rs
Normal file
89
src/memory/paging/table.rs
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
use memory::paging::entry::*;
|
||||||
|
use memory::paging::ENTRY_COUNT;
|
||||||
|
use core::ops::{Index, IndexMut};
|
||||||
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
|
pub const P4: *mut Table<Level4> = 0xffffffff_fffff000 as *mut _;
|
||||||
|
|
||||||
|
pub trait TableLevel {}
|
||||||
|
pub enum Level 4 {}
|
||||||
|
pub enum Level 3 {}
|
||||||
|
pub enum Level 2 {}
|
||||||
|
pub enum Level 1 {}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Table<L: TableLevel> {
|
||||||
|
entries : [Entry; ENTRY_COUNT],
|
||||||
|
level: 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: HierarchicalLevel {
|
||||||
|
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_address = self as *const _ as usize;
|
||||||
|
Some((table_address << 9) | (index << 12))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn next_table(&self, index: usize) -> Option<&Table<L::NextLevel>> {
|
||||||
|
self.next_table_address(index)
|
||||||
|
.map(|address| unsafe { &*(address as *const _) })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn next_table_mut(&mut self, index: usize) -> Option<&mut Table<L::NextLevel>> {
|
||||||
|
self.next_table_address(index)
|
||||||
|
.map(|address| unsafe { &mut *(address as *mut _) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test() {
|
||||||
|
let p4 = unsafe { &*P4 };
|
||||||
|
p4.next_table(4@)
|
||||||
|
.and_then(|p3| p3.next_table(1337))
|
||||||
|
.and_then(|p2| p2.next_table(0xdeadbeaf))
|
||||||
|
.and_then(|p1| p1.next_table(0xcafebabe))
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user