From f917bd67a1794f64083dd9bd9c4be61b9279b0ef Mon Sep 17 00:00:00 2001 From: Philipp Oppermann Date: Thu, 19 Nov 2015 15:44:38 +0100 Subject: [PATCH] Begin paging module --- posts/DRAFT-paging.md | 15 +++++++++++++++ src/lib.rs | 2 +- src/memory/mod.rs | 1 + src/memory/paging/mod.rs | 8 ++++++++ 4 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 src/memory/paging/mod.rs diff --git a/posts/DRAFT-paging.md b/posts/DRAFT-paging.md index 102dafed..9d9e627c 100644 --- a/posts/DRAFT-paging.md +++ b/posts/DRAFT-paging.md @@ -15,6 +15,21 @@ When accessing a `P2` table, we only loop two times and then choose entries that The math checks out, too. If all page tables are used, there is 1 `P4` table, 511 `P3` tables (the last entry is used for the recursive mapping), `511*512` `P2` tables, and `511*512*512` `P1` tables. So there are `134217728` page tables altogether. Each page table occupies 4KiB, so we need `134217728 * 4KiB = 512GiB` to store them. That's exactly the amount of memory that can be accessed through one `P4` entry since `4KiB per page * 512 P1 entries * 512 P2 entries * 512 P3 entries = 512GiB`. ## A Safe Module +We need to make sure that the page tables can't be modified concurrently. So we must ensure exclusive access for all functions that modify the page table. For a normal struct, Rust would handle it at compile time through the `&` and `&mut` rules. But since we have some magic memory address instead, we must do some manual work. + +To ensure exclusivity, we introduce a `Lock` struct. All operations that modify the current page table borrow it exclusively (`&mut`) and all operations that just read the table borrow it through `&`. That way, we benefit from Rust's aliasing rules. + +The `Lock` struct looks like this (in a new `memory/paging/mod.rs` module): + +```rust +pub struct Lock { + _private: (), +} + +impl !Send for Lock {} +impl !Sync for Lock {} +``` +The `_private` field is needed to forbid construction from outside. The `!Send` and `!Sync` ## Switching Page Tables diff --git a/src/lib.rs b/src/lib.rs index e0ae38fc..b30e79a4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,7 +13,7 @@ // limitations under the License. #![feature(no_std, lang_items)] -#![feature(const_fn, unique, core_str_ext, iter_cmp)] +#![feature(const_fn, unique, core_str_ext, iter_cmp, optin_builtin_traits)] #![no_std] extern crate rlibc; diff --git a/src/memory/mod.rs b/src/memory/mod.rs index 7bfc85d8..062cf380 100644 --- a/src/memory/mod.rs +++ b/src/memory/mod.rs @@ -1,5 +1,6 @@ pub use self::area_frame_allocator::AreaFrameAllocator; +mod paging; mod area_frame_allocator; pub const PAGE_SIZE: usize = 4096; diff --git a/src/memory/paging/mod.rs b/src/memory/paging/mod.rs new file mode 100644 index 00000000..3f7d97ae --- /dev/null +++ b/src/memory/paging/mod.rs @@ -0,0 +1,8 @@ +/// The paging lock must be unique. It is required for all page table operations and thus +/// guarantees exclusive page table access. +pub struct Lock { + _private: (), +} + +impl !Send for Lock {} +impl !Sync for Lock {}