Skip to content

Commit c4a51ea

Browse files
authored
Merge pull request #199 from rust-osdev/custom-error-types
Use custom error types instead of `()`
2 parents f316ad4 + 7544957 commit c4a51ea

File tree

6 files changed

+63
-22
lines changed

6 files changed

+63
-22
lines changed

Changelog.md

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Unreleased
22

33
- **Breaking:** Also return flags for `MapperAllSizes::translate()` ([#207](https://github.com/rust-osdev/x86_64/pull/207))
4+
- **Breaking:** Use custom error types instead of `()` ([#199](https://github.com/rust-osdev/x86_64/pull/199))
45
- Relaxe `Sized` requirement for `FrameAllocator` in `Mapper::map_to` ([204](https://github.com/rust-osdev/x86_64/pull/204))
56

67
# 0.12.3 – 2020-10-31

src/structures/paging/frame.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! Abstractions for default-sized and huge physical memory frames.
22
3+
use super::page::AddressNotAligned;
34
use crate::structures::paging::page::{PageSize, Size4KiB};
45
use crate::PhysAddr;
56
use core::fmt;
@@ -19,9 +20,9 @@ impl<S: PageSize> PhysFrame<S> {
1920
///
2021
/// Returns an error if the address is not correctly aligned (i.e. is not a valid frame start).
2122
#[inline]
22-
pub fn from_start_address(address: PhysAddr) -> Result<Self, ()> {
23+
pub fn from_start_address(address: PhysAddr) -> Result<Self, AddressNotAligned> {
2324
if !address.is_aligned(S::SIZE) {
24-
return Err(());
25+
return Err(AddressNotAligned);
2526
}
2627
Ok(PhysFrame::containing_address(address))
2728
}

src/structures/paging/mapper/mapped_page_table.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::structures::paging::{
22
frame::PhysFrame,
33
frame_alloc::FrameAllocator,
44
mapper::*,
5-
page::{Page, Size1GiB, Size2MiB, Size4KiB},
5+
page::{AddressNotAligned, Page, Size1GiB, Size2MiB, Size4KiB},
66
page_table::{FrameError, PageTable, PageTableEntry, PageTableFlags},
77
};
88

@@ -178,7 +178,7 @@ impl<'a, P: PhysToVirt> Mapper<Size1GiB> for MappedPageTable<'a, P> {
178178
}
179179

180180
let frame = PhysFrame::from_start_address(p3_entry.addr())
181-
.map_err(|()| UnmapError::InvalidFrameAddress(p3_entry.addr()))?;
181+
.map_err(|AddressNotAligned| UnmapError::InvalidFrameAddress(p3_entry.addr()))?;
182182

183183
p3_entry.set_unused();
184184
Ok((frame, MapperFlush::new(page)))
@@ -246,7 +246,7 @@ impl<'a, P: PhysToVirt> Mapper<Size1GiB> for MappedPageTable<'a, P> {
246246
}
247247

248248
PhysFrame::from_start_address(p3_entry.addr())
249-
.map_err(|()| TranslateError::InvalidFrameAddress(p3_entry.addr()))
249+
.map_err(|AddressNotAligned| TranslateError::InvalidFrameAddress(p3_entry.addr()))
250250
}
251251
}
252252

@@ -289,7 +289,7 @@ impl<'a, P: PhysToVirt> Mapper<Size2MiB> for MappedPageTable<'a, P> {
289289
}
290290

291291
let frame = PhysFrame::from_start_address(p2_entry.addr())
292-
.map_err(|()| UnmapError::InvalidFrameAddress(p2_entry.addr()))?;
292+
.map_err(|AddressNotAligned| UnmapError::InvalidFrameAddress(p2_entry.addr()))?;
293293

294294
p2_entry.set_unused();
295295
Ok((frame, MapperFlush::new(page)))
@@ -374,7 +374,7 @@ impl<'a, P: PhysToVirt> Mapper<Size2MiB> for MappedPageTable<'a, P> {
374374
}
375375

376376
PhysFrame::from_start_address(p2_entry.addr())
377-
.map_err(|()| TranslateError::InvalidFrameAddress(p2_entry.addr()))
377+
.map_err(|AddressNotAligned| TranslateError::InvalidFrameAddress(p2_entry.addr()))
378378
}
379379
}
380380

@@ -518,7 +518,7 @@ impl<'a, P: PhysToVirt> Mapper<Size4KiB> for MappedPageTable<'a, P> {
518518
}
519519

520520
PhysFrame::from_start_address(p1_entry.addr())
521-
.map_err(|()| TranslateError::InvalidFrameAddress(p1_entry.addr()))
521+
.map_err(|AddressNotAligned| TranslateError::InvalidFrameAddress(p1_entry.addr()))
522522
}
523523
}
524524

@@ -572,7 +572,7 @@ impl<'a, P: PhysToVirt> MapperAllSizes for MappedPageTable<'a, P> {
572572

573573
let frame = match PhysFrame::from_start_address(p1_entry.addr()) {
574574
Ok(frame) => frame,
575-
Err(()) => return TranslateResult::InvalidFrameAddress(p1_entry.addr()),
575+
Err(AddressNotAligned) => return TranslateResult::InvalidFrameAddress(p1_entry.addr()),
576576
};
577577
let offset = u64::from(addr.page_offset());
578578
let flags = p1_entry.flags();

src/structures/paging/mapper/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ pub use self::mapped_page_table::{MappedPageTable, PhysToVirt};
44
#[cfg(target_pointer_width = "64")]
55
pub use self::offset_page_table::OffsetPageTable;
66
#[cfg(feature = "instructions")]
7-
pub use self::recursive_page_table::RecursivePageTable;
7+
pub use self::recursive_page_table::{InvalidPageTable, RecursivePageTable};
88

99
use crate::structures::paging::{
1010
frame_alloc::FrameAllocator, page_table::PageTableFlags, Page, PageSize, PhysFrame, Size1GiB,

src/structures/paging/mapper/recursive_page_table.rs

+39-10
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
//! Access the page tables through a recursively mapped level 4 table.
22
3+
use core::fmt;
4+
35
use super::*;
46
use crate::registers::control::Cr3;
57
use crate::structures::paging::PageTableIndex;
68
use crate::structures::paging::{
79
frame_alloc::FrameAllocator,
8-
page::NotGiantPageSize,
10+
page::{AddressNotAligned, NotGiantPageSize},
911
page_table::{FrameError, PageTable, PageTableEntry, PageTableFlags},
1012
Page, PageSize, PhysFrame, Size1GiB, Size2MiB, Size4KiB,
1113
};
@@ -46,18 +48,18 @@ impl<'a> RecursivePageTable<'a> {
4648
///
4749
/// Otherwise `Err(())` is returned.
4850
#[inline]
49-
pub fn new(table: &'a mut PageTable) -> Result<Self, ()> {
51+
pub fn new(table: &'a mut PageTable) -> Result<Self, InvalidPageTable> {
5052
let page = Page::containing_address(VirtAddr::new(table as *const _ as u64));
5153
let recursive_index = page.p4_index();
5254

5355
if page.p3_index() != recursive_index
5456
|| page.p2_index() != recursive_index
5557
|| page.p1_index() != recursive_index
5658
{
57-
return Err(());
59+
return Err(InvalidPageTable::NotRecursive);
5860
}
5961
if Ok(Cr3::read().0) != table[recursive_index].frame() {
60-
return Err(());
62+
return Err(InvalidPageTable::NotActive);
6163
}
6264

6365
Ok(RecursivePageTable {
@@ -326,7 +328,7 @@ impl<'a> Mapper<Size1GiB> for RecursivePageTable<'a> {
326328
}
327329

328330
let frame = PhysFrame::from_start_address(p3_entry.addr())
329-
.map_err(|()| UnmapError::InvalidFrameAddress(p3_entry.addr()))?;
331+
.map_err(|AddressNotAligned| UnmapError::InvalidFrameAddress(p3_entry.addr()))?;
330332

331333
p3_entry.set_unused();
332334
Ok((frame, MapperFlush::new(page)))
@@ -404,7 +406,7 @@ impl<'a> Mapper<Size1GiB> for RecursivePageTable<'a> {
404406
}
405407

406408
PhysFrame::from_start_address(p3_entry.addr())
407-
.map_err(|()| TranslateError::InvalidFrameAddress(p3_entry.addr()))
409+
.map_err(|AddressNotAligned| TranslateError::InvalidFrameAddress(p3_entry.addr()))
408410
}
409411
}
410412

@@ -454,7 +456,7 @@ impl<'a> Mapper<Size2MiB> for RecursivePageTable<'a> {
454456
}
455457

456458
let frame = PhysFrame::from_start_address(p2_entry.addr())
457-
.map_err(|()| UnmapError::InvalidFrameAddress(p2_entry.addr()))?;
459+
.map_err(|AddressNotAligned| UnmapError::InvalidFrameAddress(p2_entry.addr()))?;
458460

459461
p2_entry.set_unused();
460462
Ok((frame, MapperFlush::new(page)))
@@ -561,7 +563,7 @@ impl<'a> Mapper<Size2MiB> for RecursivePageTable<'a> {
561563
}
562564

563565
PhysFrame::from_start_address(p2_entry.addr())
564-
.map_err(|()| TranslateError::InvalidFrameAddress(p2_entry.addr()))
566+
.map_err(|AddressNotAligned| TranslateError::InvalidFrameAddress(p2_entry.addr()))
565567
}
566568
}
567569

@@ -752,7 +754,7 @@ impl<'a> Mapper<Size4KiB> for RecursivePageTable<'a> {
752754
}
753755

754756
PhysFrame::from_start_address(p1_entry.addr())
755-
.map_err(|()| TranslateError::InvalidFrameAddress(p1_entry.addr()))
757+
.map_err(|AddressNotAligned| TranslateError::InvalidFrameAddress(p1_entry.addr()))
756758
}
757759
}
758760

@@ -815,7 +817,7 @@ impl<'a> MapperAllSizes for RecursivePageTable<'a> {
815817

816818
let frame = match PhysFrame::from_start_address(p1_entry.addr()) {
817819
Ok(frame) => frame,
818-
Err(()) => return TranslateResult::InvalidFrameAddress(p1_entry.addr()),
820+
Err(AddressNotAligned) => return TranslateResult::InvalidFrameAddress(p1_entry.addr()),
819821
};
820822
let offset = u64::from(addr.page_offset());
821823
let flags = p1_entry.flags();
@@ -827,6 +829,33 @@ impl<'a> MapperAllSizes for RecursivePageTable<'a> {
827829
}
828830
}
829831

832+
/// The given page table was not suitable to create a `RecursivePageTable`.
833+
#[derive(Debug)]
834+
pub enum InvalidPageTable {
835+
/// The given page table was not at an recursive address.
836+
///
837+
/// The page table address must be of the form `0o_xxx_xxx_xxx_xxx_0000` where `xxx`
838+
/// is the recursive entry.
839+
NotRecursive,
840+
/// The given page table was not active on the CPU.
841+
///
842+
/// The recursive page table design requires that the given level 4 table is active
843+
/// on the CPU because otherwise it's not possible to access the other page tables
844+
/// through recursive memory addresses.
845+
NotActive,
846+
}
847+
848+
impl fmt::Display for InvalidPageTable {
849+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
850+
match self {
851+
InvalidPageTable::NotRecursive => {
852+
write!(f, "given page table address is not recursive")
853+
}
854+
InvalidPageTable::NotActive => write!(f, "given page table is not active on the CPU"),
855+
}
856+
}
857+
}
858+
830859
#[inline]
831860
fn p3_ptr<S: PageSize>(page: Page<S>, recursive_index: PageTableIndex) -> *mut PageTable {
832861
p3_page(page, recursive_index).start_address().as_mut_ptr()

src/structures/paging/page.rs

+12-2
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,9 @@ impl<S: PageSize> Page<S> {
6767
///
6868
/// Returns an error if the address is not correctly aligned (i.e. is not a valid page start).
6969
#[inline]
70-
pub fn from_start_address(address: VirtAddr) -> Result<Self, ()> {
70+
pub fn from_start_address(address: VirtAddr) -> Result<Self, AddressNotAligned> {
7171
if !address.is_aligned(S::SIZE) {
72-
return Err(());
72+
return Err(AddressNotAligned);
7373
}
7474
Ok(Page::containing_address(address))
7575
}
@@ -362,6 +362,16 @@ impl<S: PageSize> fmt::Debug for PageRangeInclusive<S> {
362362
}
363363
}
364364

365+
/// The given address was not sufficiently aligned.
366+
#[derive(Debug)]
367+
pub struct AddressNotAligned;
368+
369+
impl fmt::Display for AddressNotAligned {
370+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
371+
write!(f, "the given address was not sufficiently aligned")
372+
}
373+
}
374+
365375
#[cfg(test)]
366376
mod tests {
367377
use super::*;

0 commit comments

Comments
 (0)