aarch64/mmu: simply handle page fault

master
equation314 6 years ago
parent d6a54496f0
commit a59a7fbe9a

@ -0,0 +1,31 @@
/*
* Copyright (c) 2018 by the author(s)
*
* =============================================================================
*
* Licensed under either of
* - Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
* - MIT License (http://opensource.org/licenses/MIT)
* at your option.
*
* =============================================================================
*
* Author(s):
* - Andre Richter <andre.o.richter@gmail.com>
*/
//! Fault Address Register - EL1
//!
//! Holds the faulting Virtual Address for all synchronous Instruction or Data
//! Abort, PC alignment fault and Watchpoint exceptions that are taken to EL1.
use register::cpu::RegisterReadWrite;
pub struct Reg;
impl RegisterReadWrite<u64, ()> for Reg {
sys_coproc_read_raw!(u64, "FAR_EL1");
sys_coproc_write_raw!(u64, "FAR_EL1");
}
pub static FAR_EL1: Reg = Reg {};

@ -12,6 +12,7 @@ mod cntvoff_el2;
mod currentel; mod currentel;
mod daif; mod daif;
mod elr_el2; mod elr_el2;
mod far_el1;
mod hcr_el2; mod hcr_el2;
mod id_aa64mmfr0_el1; mod id_aa64mmfr0_el1;
mod mair_el1; mod mair_el1;
@ -38,6 +39,7 @@ pub use self::cntvoff_el2::CNTVOFF_EL2;
pub use self::currentel::CurrentEL; pub use self::currentel::CurrentEL;
pub use self::daif::DAIF; pub use self::daif::DAIF;
pub use self::elr_el2::ELR_EL2; pub use self::elr_el2::ELR_EL2;
pub use self::far_el1::FAR_EL1;
pub use self::hcr_el2::HCR_EL2; pub use self::hcr_el2::HCR_EL2;
pub use self::id_aa64mmfr0_el1::ID_AA64MMFR0_EL1; pub use self::id_aa64mmfr0_el1::ID_AA64MMFR0_EL1;
pub use self::mair_el1::{MAIR_EL1, MAIR_ATTR}; pub use self::mair_el1::{MAIR_EL1, MAIR_ATTR};

@ -2,7 +2,9 @@
use arch::board::irq::handle_irq; use arch::board::irq::handle_irq;
use super::context::TrapFrame; use super::context::TrapFrame;
use super::syndrome::Syndrome; use super::syndrome::{Fault, Syndrome};
use aarch64::regs::*;
global_asm!(include_str!("trap.S")); global_asm!(include_str!("trap.S"));
global_asm!(include_str!("vector.S")); global_asm!(include_str!("vector.S"));
@ -46,7 +48,14 @@ pub extern "C" fn rust_trap(info: Info, esr: u32, tf: &mut TrapFrame) {
// syndrome is only valid with sync // syndrome is only valid with sync
match syndrome { match syndrome {
Syndrome::Brk(brk) => handle_break(brk, tf), Syndrome::Brk(brk) => handle_break(brk, tf),
Syndrome::Svc(_) => handle_syscall(tf), Syndrome::Svc(svc) => handle_syscall(svc, tf),
Syndrome::DataAbort { kind, level: _ }
| Syndrome::InstructionAbort { kind, level: _ } => match kind {
Fault::Translation | Fault::AccessFlag | Fault::Permission => {
handle_page_fault(tf)
}
_ => ::trap::error(tf),
},
_ => ::trap::error(tf), _ => ::trap::error(tf),
} }
} }
@ -57,12 +66,16 @@ pub extern "C" fn rust_trap(info: Info, esr: u32, tf: &mut TrapFrame) {
trace!("Interrupt end"); trace!("Interrupt end");
} }
fn handle_break(num: u16, tf: &mut TrapFrame) { fn handle_break(_num: u16, tf: &mut TrapFrame) {
// Skip the current brk instruction (ref: J1.1.2, page 6147) // Skip the current brk instruction (ref: J1.1.2, page 6147)
tf.elr += 4; tf.elr += 4;
} }
fn handle_syscall(tf: &mut TrapFrame) { fn handle_syscall(num: u16, tf: &mut TrapFrame) {
if num != 0 {
::trap::error(tf);
}
// svc instruction has been skipped in syscall (ref: J1.1.2, page 6152) // svc instruction has been skipped in syscall (ref: J1.1.2, page 6152)
let ret = ::syscall::syscall( let ret = ::syscall::syscall(
tf.x1to29[7] as usize, tf.x1to29[7] as usize,
@ -78,3 +91,10 @@ fn handle_syscall(tf: &mut TrapFrame) {
); );
tf.x0 = ret as usize; tf.x0 = ret as usize;
} }
fn handle_page_fault(tf: &mut TrapFrame) {
let addr = FAR_EL1.get();
trace!("\nEXCEPTION: Page Fault @ {:#x}", addr);
::trap::error(tf);
}

Loading…
Cancel
Save