Skip to content

Commit 94a7329

Browse files
committed
remove recursive page table
1 parent d1f968e commit 94a7329

File tree

7 files changed

+154
-570
lines changed

7 files changed

+154
-570
lines changed

src/addr/gpax4.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use core::convert::TryInto;
44

55
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
66
pub struct GPAddrSv32X4(u64);
7+
78
impl Address for GPAddrSv32X4 {
89
fn new(addr: usize) -> Self {
910
Self::new_u64(addr as u64)
@@ -21,6 +22,7 @@ impl Address for GPAddrSv32X4 {
2122
GPAddrSv32X4((self.0 >> 12) << 12)
2223
}
2324
}
25+
2426
impl VirtualAddress for GPAddrSv32X4 {
2527
unsafe fn as_mut<'a, 'b, T>(&'a self) -> &'b mut T {
2628
&mut *(self.0 as *mut T)
@@ -31,7 +33,6 @@ impl AddressL2 for GPAddrSv32X4 {
3133
fn p2_index(&self) -> usize {
3234
self.0.get_bits(22..34) as usize
3335
}
34-
3536
fn p1_index(&self) -> usize {
3637
self.0.get_bits(12..22) as usize
3738
}
@@ -61,6 +62,7 @@ impl AddressX64 for GPAddrSv32X4 {
6162

6263
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
6364
pub struct GPAddrSv39X4(u64);
65+
6466
impl Address for GPAddrSv39X4 {
6567
fn new(addr: usize) -> Self {
6668
GPAddrSv39X4(addr.try_into().unwrap())
@@ -78,6 +80,7 @@ impl Address for GPAddrSv39X4 {
7880
GPAddrSv39X4((self.0 >> 12) << 12)
7981
}
8082
}
83+
8184
impl VirtualAddress for GPAddrSv39X4 {
8285
unsafe fn as_mut<'a, 'b, T>(&'a self) -> &'b mut T {
8386
&mut *(self.0 as *mut T)
@@ -91,7 +94,6 @@ impl AddressL3 for GPAddrSv39X4 {
9194
fn p2_index(&self) -> usize {
9295
self.0.get_bits(21..30) as usize
9396
}
94-
9597
fn p1_index(&self) -> usize {
9698
self.0.get_bits(12..21) as usize
9799
}
@@ -130,6 +132,7 @@ impl AddressX64 for GPAddrSv39X4 {
130132

131133
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
132134
pub struct GPAddrSv48X4(u64);
135+
133136
impl Address for GPAddrSv48X4 {
134137
fn new(addr: usize) -> Self {
135138
GPAddrSv48X4(addr.try_into().unwrap())
@@ -147,6 +150,7 @@ impl Address for GPAddrSv48X4 {
147150
GPAddrSv48X4((self.0 >> 12) << 12)
148151
}
149152
}
153+
150154
impl VirtualAddress for GPAddrSv48X4 {
151155
unsafe fn as_mut<'a, 'b, T>(&'a self) -> &'b mut T {
152156
&mut *(self.0 as *mut T)
@@ -157,14 +161,12 @@ impl AddressL4 for GPAddrSv48X4 {
157161
fn p4_index(&self) -> usize {
158162
self.0.get_bits(39..50) as usize
159163
}
160-
161164
fn p3_index(&self) -> usize {
162165
self.0.get_bits(30..39) as usize
163166
}
164167
fn p2_index(&self) -> usize {
165168
self.0.get_bits(21..30) as usize
166169
}
167-
168170
fn p1_index(&self) -> usize {
169171
self.0.get_bits(12..21) as usize
170172
}

src/paging/mapper.rs

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
use super::frame_alloc::*;
2+
use super::page_table::*;
3+
use addr::*;
4+
5+
pub trait Mapper {
6+
type P: PhysicalAddress;
7+
type V: VirtualAddress;
8+
type MapperFlush: MapperFlushable;
9+
type Entry: PTE;
10+
11+
/// Creates a new mapping in the page table.
12+
///
13+
/// This function might need additional physical frames to create new page tables. These
14+
/// frames are allocated from the `allocator` argument. At most three frames are required.
15+
fn map_to(
16+
&mut self,
17+
page: PageWith<Self::V>,
18+
frame: FrameWith<Self::P>,
19+
flags: PageTableFlags,
20+
allocator: &mut impl FrameAllocatorFor<<Self as Mapper>::P>,
21+
) -> Result<Self::MapperFlush, MapToError>;
22+
23+
/// Removes a mapping from the page table and returns the frame that used to be mapped.
24+
///
25+
/// Note that no page tables or pages are deallocated.
26+
fn unmap(
27+
&mut self,
28+
page: PageWith<Self::V>,
29+
) -> Result<(FrameWith<Self::P>, Self::MapperFlush), UnmapError<<Self as Mapper>::P>>;
30+
31+
/// Get the reference of the specified `page` entry
32+
fn ref_entry(&mut self, page: PageWith<Self::V>) -> Result<&mut Self::Entry, FlagUpdateError>;
33+
34+
/// Updates the flags of an existing mapping.
35+
fn update_flags(
36+
&mut self,
37+
page: PageWith<Self::V>,
38+
flags: PageTableFlags,
39+
) -> Result<Self::MapperFlush, FlagUpdateError> {
40+
self.ref_entry(page).map(|e| {
41+
e.set(e.frame::<Self::P>(), flags);
42+
Self::MapperFlush::new(page)
43+
})
44+
}
45+
46+
/// Return the frame that the specified page is mapped to.
47+
fn translate_page(&mut self, page: PageWith<Self::V>) -> Option<FrameWith<Self::P>> {
48+
match self.ref_entry(page) {
49+
Ok(e) => {
50+
if e.is_unused() {
51+
None
52+
} else {
53+
Some(e.frame())
54+
}
55+
}
56+
Err(_) => None,
57+
}
58+
}
59+
60+
/// Maps the given frame to the virtual page with the same address.
61+
fn identity_map(
62+
&mut self,
63+
frame: FrameWith<Self::P>,
64+
flags: PageTableFlags,
65+
allocator: &mut impl FrameAllocatorFor<<Self as Mapper>::P>,
66+
) -> Result<Self::MapperFlush, MapToError> {
67+
let page = PageWith::of_addr(Self::V::new(frame.start_address().as_usize()));
68+
self.map_to(page, frame, flags, allocator)
69+
}
70+
}
71+
72+
pub trait MapperFlushable {
73+
/// Create a new flush promise
74+
fn new<T: VirtualAddress>(page: PageWith<T>) -> Self;
75+
/// Flush the page from the TLB to ensure that the newest mapping is used.
76+
fn flush(self);
77+
/// Don't flush the TLB and silence the “must be used” warning.
78+
fn ignore(self);
79+
}
80+
81+
#[must_use = "Page Table changes must be flushed or ignored."]
82+
pub struct MapperFlush(usize);
83+
84+
impl MapperFlushable for MapperFlush {
85+
fn new<T: VirtualAddress>(page: PageWith<T>) -> Self {
86+
MapperFlush(page.start_address().as_usize())
87+
}
88+
fn flush(self) {
89+
unsafe {
90+
crate::asm::sfence_vma(0, self.0);
91+
}
92+
}
93+
fn ignore(self) {}
94+
}
95+
96+
/// This error is returned from `map_to` and similar methods.
97+
#[derive(Debug)]
98+
pub enum MapToError {
99+
/// An additional frame was needed for the mapping process, but the frame allocator
100+
/// returned `None`.
101+
FrameAllocationFailed,
102+
/// An upper level page table entry has the `HUGE_PAGE` flag set, which means that the
103+
/// given page is part of an already mapped huge page.
104+
ParentEntryHugePage,
105+
/// The given page is already mapped to a physical frame.
106+
PageAlreadyMapped,
107+
}
108+
109+
/// An error indicating that an `unmap` call failed.
110+
#[derive(Debug)]
111+
pub enum UnmapError<P: PhysicalAddress> {
112+
/// An upper level page table entry has the `HUGE_PAGE` flag set, which means that the
113+
/// given page is part of a huge page and can't be freed individually.
114+
ParentEntryHugePage,
115+
/// The given page is not mapped to a physical frame.
116+
PageNotMapped,
117+
/// The page table entry for the given page points to an invalid physical address.
118+
InvalidFrameAddress(P),
119+
}
120+
121+
/// An error indicating that an `update_flags` call failed.
122+
#[derive(Debug)]
123+
pub enum FlagUpdateError {
124+
/// The given page is not mapped to a physical frame.
125+
PageNotMapped,
126+
}
127+
128+
pub trait MapperExt {
129+
type Page;
130+
type Frame;
131+
}
132+
133+
impl<T: Mapper> MapperExt for T {
134+
type Page = PageWith<<T as Mapper>::V>;
135+
type Frame = FrameWith<<T as Mapper>::P>;
136+
}

src/paging/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
mod frame_alloc;
2+
mod mapper;
23
mod multi_level;
34
mod multi_level_x4;
45
mod page_table;
56
mod page_table_x4;
6-
mod recursive;
77

88
pub use self::frame_alloc::*;
9+
pub use self::mapper::*;
910
pub use self::multi_level::*;
1011
pub use self::multi_level_x4::*;
1112
pub use self::page_table::*;
1213
pub use self::page_table_x4::*;
13-
pub use self::recursive::*;

src/paging/multi_level.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
use super::frame_alloc::*;
2+
use super::mapper::*;
23
use super::page_table::{PageTableFlags as F, *};
3-
use super::recursive::*;
44
use crate::addr::*;
55
use core::marker::PhantomData;
6-
/// This struct is a two level page table with `Mapper` trait implemented.
76

7+
/// This struct is a two level page table with `Mapper` trait implemented.
88
pub struct Rv32PageTableWith<'a, V: VirtualAddress + AddressL2, FL: MapperFlushable> {
99
root_table: &'a mut PageTableX32,
1010
linear_offset: u64, // VA = PA + linear_offset
11-
phantom: PhantomData<fn() -> (V, FL)>,
11+
phantom: PhantomData<(V, FL)>,
1212
}
1313

1414
impl<'a, V: VirtualAddress + AddressL2, FL: MapperFlushable> Rv32PageTableWith<'a, V, FL> {
@@ -98,7 +98,7 @@ impl<'a, V: VirtualAddress + AddressL2, FL: MapperFlushable> Mapper
9898
pub struct Rv39PageTableWith<'a, V: VirtualAddress + AddressL3, FL: MapperFlushable> {
9999
root_table: &'a mut PageTableX64,
100100
linear_offset: u64, // VA = PA + linear_offset
101-
phantom: PhantomData<fn() -> (V, FL)>,
101+
phantom: PhantomData<(V, FL)>,
102102
}
103103

104104
impl<'a, V: VirtualAddress + AddressL3, FL: MapperFlushable> Rv39PageTableWith<'a, V, FL> {
@@ -211,7 +211,7 @@ impl<'a, V: VirtualAddress + AddressL3, FL: MapperFlushable> Mapper
211211
pub struct Rv48PageTableWith<'a, V: VirtualAddress + AddressL4, FL: MapperFlushable> {
212212
root_table: &'a mut PageTableX64,
213213
linear_offset: u64, // VA = PA + linear_offset
214-
phantom: PhantomData<*const (V, FL)>,
214+
phantom: PhantomData<(V, FL)>,
215215
}
216216

217217
impl<'a, V: VirtualAddress + AddressL4, FL: MapperFlushable> Rv48PageTableWith<'a, V, FL> {

src/paging/multi_level_x4.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use crate::addr::*;
22
use crate::asm::{hfence_gvma, hfence_vvma};
3+
use crate::paging::mapper::MapperFlushable;
34
use crate::paging::multi_level::Rv32PageTableWith;
45
use crate::paging::multi_level::{Rv39PageTableWith, Rv48PageTableWith};
5-
use crate::paging::recursive::MapperFlushable;
66

77
#[must_use = "Guest Physical Address Table changes must be flushed or ignored."]
88
pub struct MapperFlushGPA(usize);
@@ -16,7 +16,6 @@ impl MapperFlushable for MapperFlushGPA {
1616
hfence_gvma(self.0, 0);
1717
}
1818
}
19-
2019
fn ignore(self) {}
2120
}
2221

@@ -32,7 +31,6 @@ impl MapperFlushable for MapperFlushGPT {
3231
hfence_vvma(self.0, 0);
3332
}
3433
}
35-
3634
fn ignore(self) {}
3735
}
3836

src/paging/page_table.rs

Lines changed: 4 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
use addr::*;
22
use core::convert::TryInto;
33
use core::fmt::{Debug, Error, Formatter};
4+
use core::marker::PhantomData;
45
use core::ops::{Index, IndexMut};
56

67
pub type Entries32 = [PageTableEntryX32; RV32_ENTRY_COUNT];
78
pub type Entries64 = [PageTableEntryX64; RV64_ENTRY_COUNT];
9+
810
// To avoid const generic.
911
pub trait PTEIterableSlice<T> {
1012
fn to_pte_slice<'a>(&'a self) -> &'a [T];
@@ -55,28 +57,6 @@ impl<T: PTEIterableSlice<E>, E: PTE> PageTableWith<T, E> {
5557
entry.set_unused();
5658
}
5759
}
58-
59-
/// Parameter `frame` is the actual physical frame where the root page table resides,
60-
/// it can be anywhere in the main memory.
61-
/// Denote `recursive_index` by K, then virtual address of the root page table is
62-
/// (K, K+1, 0) in Sv32, and (K, K, K+1, 0) in Sv39, and (K, K, K, K+1, 0) in Sv48.
63-
pub fn set_recursive<F: PhysicalAddress>(
64-
&mut self,
65-
recursive_index: usize,
66-
frame: FrameWith<F>,
67-
) {
68-
self[recursive_index].set(frame.clone(), EF::VALID);
69-
self[recursive_index + 1].set(frame.clone(), EF::VALID | EF::READABLE | EF::WRITABLE);
70-
}
71-
72-
/// Setup identity map for the page with first level page table index.
73-
#[cfg(riscv32)]
74-
pub fn map_identity(&mut self, p2idx: usize, flags: PageTableFlags) {
75-
self.entries.pte_index_mut(p2idx).set(
76-
FrameWith::of_addr(PhysAddrSv32::new_u64((p2idx as u64) << 22)),
77-
flags,
78-
);
79-
}
8060
}
8161

8262
impl<T: PTEIterableSlice<E>, E: PTE> Index<usize> for PageTableWith<T, E> {
@@ -118,6 +98,7 @@ pub trait PTE {
11898
fn set<T: PhysicalAddress>(&mut self, frame: FrameWith<T>, flags: PageTableFlags);
11999
fn flags_mut(&mut self) -> &mut PageTableFlags;
120100
}
101+
121102
#[derive(Copy, Clone)]
122103
#[repr(C)]
123104
pub struct PageTableEntryX32(u32);
@@ -197,7 +178,7 @@ impl PTE for PageTableEntryX64 {
197178
unsafe { &mut *(self as *mut _ as *mut PageTableFlags) }
198179
}
199180
}
200-
use core::marker::PhantomData;
181+
201182
pub struct PageTableEntryX64Printer<'a, P: PhysicalAddress>(
202183
&'a PageTableEntryX64,
203184
PhantomData<*const P>,

0 commit comments

Comments
 (0)