Eliminate an additional current!() operation in user space pagefault handling

This commit is contained in:
Chen Chengjun
2024-09-12 20:02:12 +08:00
committed by Tate, Hongliang Tian
parent 53ce7df53c
commit 1fb34780f6
2 changed files with 25 additions and 16 deletions

View File

@ -2,11 +2,13 @@
#![allow(unused_variables)] #![allow(unused_variables)]
use aster_rights::Full;
use ostd::{cpu::*, mm::VmSpace}; use ostd::{cpu::*, mm::VmSpace};
use crate::{ use crate::{
prelude::*, process::signal::signals::fault::FaultSignal, prelude::*,
vm::page_fault_handler::PageFaultHandler, process::signal::signals::fault::FaultSignal,
vm::{page_fault_handler::PageFaultHandler, vmar::Vmar},
}; };
/// We can't handle most exceptions, just send self a fault signal before return to user space. /// We can't handle most exceptions, just send self a fault signal before return to user space.
@ -14,11 +16,10 @@ pub fn handle_exception(ctx: &Context, context: &UserContext) {
let trap_info = context.trap_information(); let trap_info = context.trap_information();
let exception = CpuException::to_cpu_exception(trap_info.id as u16).unwrap(); let exception = CpuException::to_cpu_exception(trap_info.id as u16).unwrap();
log_trap_info(exception, trap_info); log_trap_info(exception, trap_info);
let root_vmar = ctx.process.root_vmar();
match *exception { match *exception {
PAGE_FAULT => { PAGE_FAULT => {
if handle_page_fault(root_vmar.vm_space(), trap_info).is_err() { if handle_page_fault_from_vmar(ctx.process.root_vmar(), trap_info).is_err() {
generate_fault_signal(trap_info, ctx); generate_fault_signal(trap_info, ctx);
} }
} }
@ -30,9 +31,26 @@ pub fn handle_exception(ctx: &Context, context: &UserContext) {
} }
/// Handles the page fault occurs in the input `VmSpace`. /// Handles the page fault occurs in the input `VmSpace`.
pub(crate) fn handle_page_fault( pub(crate) fn handle_page_fault_from_vm_space(
vm_space: &VmSpace, vm_space: &VmSpace,
trap_info: &CpuExceptionInfo, trap_info: &CpuExceptionInfo,
) -> core::result::Result<(), ()> {
let current = current!();
let root_vmar = current.root_vmar();
// If page is not present or due to write access, we should ask the vmar try to commit this page
debug_assert_eq!(
Arc::as_ptr(root_vmar.vm_space()),
vm_space as *const VmSpace
);
handle_page_fault_from_vmar(root_vmar, trap_info)
}
/// Handles the page fault occurs in the input `Vmar`.
pub(crate) fn handle_page_fault_from_vmar(
root_vmar: &Vmar<Full>,
trap_info: &CpuExceptionInfo,
) -> core::result::Result<(), ()> { ) -> core::result::Result<(), ()> {
const PAGE_NOT_PRESENT_ERROR_MASK: usize = 0x1 << 0; const PAGE_NOT_PRESENT_ERROR_MASK: usize = 0x1 << 0;
const WRITE_ACCESS_MASK: usize = 0x1 << 1; const WRITE_ACCESS_MASK: usize = 0x1 << 1;
@ -46,15 +64,6 @@ pub(crate) fn handle_page_fault(
let not_present = trap_info.error_code & PAGE_NOT_PRESENT_ERROR_MASK == 0; let not_present = trap_info.error_code & PAGE_NOT_PRESENT_ERROR_MASK == 0;
let write = trap_info.error_code & WRITE_ACCESS_MASK != 0; let write = trap_info.error_code & WRITE_ACCESS_MASK != 0;
if not_present || write { if not_present || write {
let current = current!();
let root_vmar = current.root_vmar();
// If page is not present or due to write access, we should ask the vmar try to commit this page
debug_assert_eq!(
Arc::as_ptr(root_vmar.vm_space()),
vm_space as *const VmSpace
);
if let Err(e) = root_vmar.handle_page_fault(page_fault_addr, not_present, write) { if let Err(e) = root_vmar.handle_page_fault(page_fault_addr, not_present, write) {
warn!( warn!(
"page fault handler failed: addr: 0x{:x}, err: {:?}", "page fault handler failed: addr: 0x{:x}, err: {:?}",

View File

@ -21,7 +21,7 @@ use self::{
vm_mapping::VmMapping, vm_mapping::VmMapping,
}; };
use super::page_fault_handler::PageFaultHandler; use super::page_fault_handler::PageFaultHandler;
use crate::{prelude::*, thread::exception::handle_page_fault, vm::perms::VmPerms}; use crate::{prelude::*, thread::exception::handle_page_fault_from_vm_space, vm::perms::VmPerms};
/// Virtual Memory Address Regions (VMARs) are a type of capability that manages /// Virtual Memory Address Regions (VMARs) are a type of capability that manages
/// user address spaces. /// user address spaces.
@ -228,7 +228,7 @@ impl Vmar_ {
free_regions, free_regions,
}; };
let vm_space = VmSpace::new(); let vm_space = VmSpace::new();
vm_space.register_page_fault_handler(handle_page_fault); vm_space.register_page_fault_handler(handle_page_fault_from_vm_space);
Vmar_::new(vmar_inner, Arc::new(vm_space), 0, ROOT_VMAR_CAP_ADDR, None) Vmar_::new(vmar_inner, Arc::new(vm_space), 0, ROOT_VMAR_CAP_ADDR, None)
} }