Skip to content

Commit

Permalink
feat(x86_64): display page fault address in oopses (#420)
Browse files Browse the repository at this point in the history
Debugging page faults in Mycelium is currently a bit difficult, because
the oops message doesn't display the virtual address at which the page
fault occurred. We can fix this quite easily by reading the `cr2`
control register, which contains the linear address of the page fault.
  • Loading branch information
hawkw committed Apr 9, 2023
1 parent aa6e82f commit d011cf1
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 3 deletions.
17 changes: 16 additions & 1 deletion hal-x86_64/src/control_regs.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use core::arch::asm;
use hal_core::VAddr;
use mycelium_util::bits::bitfield;

pub mod cr3 {
Expand All @@ -15,7 +16,7 @@ pub mod cr3 {
asm!("mov {0}, cr3", out(reg) val, options(readonly));
};
let addr = PAddr::from_u64(val);
tracing::debug!(?addr);
tracing::trace!(rax = ?addr, "mov rax, cr3");
let pml4_page = Page::starting_at_fixed(addr)
.expect("PML4 physical addr not aligned! this is very bad");
(pml4_page, Flags(val))
Expand Down Expand Up @@ -236,6 +237,20 @@ impl Cr4 {
}
}

/// Control Register 2 (CR2) contains the Page Fault Linear Address (PFLA).
pub struct Cr2;

impl Cr2 {
/// Returns the 32-bit Page Fault Linear Address (PFLA) stored in CR2.
pub fn read() -> VAddr {
let addr: u64;
unsafe {
asm!("mov {0}, cr2", out(reg) addr, options(readonly));
};
VAddr::from_u64(addr)
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
2 changes: 1 addition & 1 deletion hal-x86_64/src/interrupt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ impl<'a, T> hal_core::interrupt::Context for Context<'a, T> {

impl<'a> ctx::PageFault for Context<'a, PageFaultCode> {
fn fault_vaddr(&self) -> crate::VAddr {
unimplemented!("eliza")
crate::control_regs::Cr2::read()
}

fn debug_error_code(&self) -> &dyn fmt::Debug {
Expand Down
4 changes: 3 additions & 1 deletion src/arch/x86_64/interrupt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,12 @@ impl hal_core::interrupt::Handlers<Registers> for InterruptHandlers {
where
C: interrupt::Context<Registers = Registers> + hal_core::interrupt::ctx::PageFault,
{
let fault_vaddr = cx.fault_vaddr();
let code = cx.display_error_code();
oops(Oops::fault_with_details(
&cx,
"PAGE FAULT",
&format_args!("\n{}", cx.display_error_code()),
&format_args!("at {fault_vaddr:?}\n{code}"),
))
}

Expand Down

0 comments on commit d011cf1

Please sign in to comment.