Skip to content

Commit 98f86a4

Browse files
committed
Improve PageTableIndex and PageOffset.
- There are now const functions to make them: new_truncate. - The new truncating are used in VirtAddr to avoid needless checks. - The guarantee that they are in 0..512 and 0..4096 is documented. - This guarantee is used in Index for PageTable to avoid needless checks. - They are now both Into<usize>, to make it easier to use them as index.
1 parent 99b8a0a commit 98f86a4

File tree

2 files changed

+40
-8
lines changed

2 files changed

+40
-8
lines changed

src/addr.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use core::convert::{Into, TryInto};
21
use core::fmt;
32
use core::ops::{Add, AddAssign, Sub, SubAssign};
43

@@ -135,27 +134,27 @@ impl VirtAddr {
135134

136135
/// Returns the 12-bit page offset of this virtual address.
137136
pub fn page_offset(&self) -> PageOffset {
138-
PageOffset::new((self.0 & 0xfff).try_into().unwrap())
137+
PageOffset::new_truncate(self.0 as u16)
139138
}
140139

141140
/// Returns the 9-bit level 1 page table index.
142141
pub fn p1_index(&self) -> PageTableIndex {
143-
PageTableIndex::new(((self.0 >> 12) & 0o777).try_into().unwrap())
142+
PageTableIndex::new_truncate((self.0 >> 12) as u16)
144143
}
145144

146145
/// Returns the 9-bit level 2 page table index.
147146
pub fn p2_index(&self) -> PageTableIndex {
148-
PageTableIndex::new(((self.0 >> 12 >> 9) & 0o777).try_into().unwrap())
147+
PageTableIndex::new_truncate((self.0 >> 12 >> 9) as u16)
149148
}
150149

151150
/// Returns the 9-bit level 3 page table index.
152151
pub fn p3_index(&self) -> PageTableIndex {
153-
PageTableIndex::new(((self.0 >> 12 >> 9 >> 9) & 0o777).try_into().unwrap())
152+
PageTableIndex::new_truncate((self.0 >> 12 >> 9 >> 9) as u16)
154153
}
155154

156155
/// Returns the 9-bit level 4 page table index.
157156
pub fn p4_index(&self) -> PageTableIndex {
158-
PageTableIndex::new(((self.0 >> 12 >> 9 >> 9 >> 9) & 0o777).try_into().unwrap())
157+
PageTableIndex::new_truncate((self.0 >> 12 >> 9 >> 9 >> 9) as u16)
159158
}
160159
}
161160

@@ -247,6 +246,11 @@ impl PhysAddr {
247246
PhysAddr(addr)
248247
}
249248

249+
/// Creates a new physical address, throwing bits 52..64 away.
250+
pub const fn new_truncate(addr: u64) -> PhysAddr {
251+
PhysAddr(addr % (1 << 52))
252+
}
253+
250254
/// Tries to create a new physical address.
251255
///
252256
/// Fails if any bits in the range 52 to 64 are set.

src/structures/paging/page_table.rs

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -218,13 +218,15 @@ impl Index<PageTableIndex> for PageTable {
218218
type Output = PageTableEntry;
219219

220220
fn index(&self, index: PageTableIndex) -> &Self::Output {
221-
&self.entries[cast::usize(u16::from(index))]
221+
// Safety: A PageTableIndex never contains a value >= 512.
222+
unsafe { self.entries.get_unchecked(usize::from(index)) }
222223
}
223224
}
224225

225226
impl IndexMut<PageTableIndex> for PageTable {
226227
fn index_mut(&mut self, index: PageTableIndex) -> &mut Self::Output {
227-
&mut self.entries[cast::usize(u16::from(index))]
228+
// Safety: A PageTableIndex never contains a value >= 512.
229+
unsafe { self.entries.get_unchecked_mut(usize::from(index)) }
228230
}
229231
}
230232

@@ -237,6 +239,8 @@ impl fmt::Debug for PageTable {
237239
/// A 9-bit index into a page table.
238240
///
239241
/// Can be used to select one of the 512 entries of a page table.
242+
///
243+
/// Guaranteed to only ever contain 0..512.
240244
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
241245
pub struct PageTableIndex(u16);
242246

@@ -246,6 +250,11 @@ impl PageTableIndex {
246250
assert!(usize::from(index) < ENTRY_COUNT);
247251
Self(index)
248252
}
253+
254+
/// Creates a new index from the given `u16`. Throws away bits if the value is >=512.
255+
pub const fn new_truncate(index: u16) -> Self {
256+
Self(index % ENTRY_COUNT as u16)
257+
}
249258
}
250259

251260
impl From<PageTableIndex> for u16 {
@@ -266,9 +275,17 @@ impl From<PageTableIndex> for u64 {
266275
}
267276
}
268277

278+
impl From<PageTableIndex> for usize {
279+
fn from(index: PageTableIndex) -> Self {
280+
usize::from(index.0)
281+
}
282+
}
283+
269284
/// A 12-bit offset into a 4KiB Page.
270285
///
271286
/// This type is returned by the `VirtAddr::page_offset` method.
287+
///
288+
/// Guaranteed to only ever contain 0..4096.
272289
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
273290
pub struct PageOffset(u16);
274291

@@ -278,6 +295,11 @@ impl PageOffset {
278295
assert!(offset < (1 << 12));
279296
Self(offset)
280297
}
298+
299+
/// Creates a new offset from the given `u16`. Throws away bits if the value is >=4096.
300+
pub const fn new_truncate(offset: u16) -> Self {
301+
Self(offset % (1 << 12))
302+
}
281303
}
282304

283305
impl From<PageOffset> for u16 {
@@ -297,3 +319,9 @@ impl From<PageOffset> for u64 {
297319
u64::from(offset.0)
298320
}
299321
}
322+
323+
impl From<PageOffset> for usize {
324+
fn from(offset: PageOffset) -> Self {
325+
usize::from(offset.0)
326+
}
327+
}

0 commit comments

Comments
 (0)