From 1fb34780f6d875ed542f91c71ecc8bb7bb1c0b9d Mon Sep 17 00:00:00 2001 From: Chen Chengjun Date: Thu, 12 Sep 2024 20:02:12 +0800 Subject: [PATCH] Eliminate an additional current!() operation in user space pagefault handling --- kernel/src/thread/exception.rs | 37 +++++++++++++++++++++------------- kernel/src/vm/vmar/mod.rs | 4 ++-- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/kernel/src/thread/exception.rs b/kernel/src/thread/exception.rs index a60d5c521..6b6317150 100644 --- a/kernel/src/thread/exception.rs +++ b/kernel/src/thread/exception.rs @@ -2,11 +2,13 @@ #![allow(unused_variables)] +use aster_rights::Full; use ostd::{cpu::*, mm::VmSpace}; use crate::{ - prelude::*, process::signal::signals::fault::FaultSignal, - vm::page_fault_handler::PageFaultHandler, + prelude::*, + 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. @@ -14,11 +16,10 @@ pub fn handle_exception(ctx: &Context, context: &UserContext) { let trap_info = context.trap_information(); let exception = CpuException::to_cpu_exception(trap_info.id as u16).unwrap(); log_trap_info(exception, trap_info); - let root_vmar = ctx.process.root_vmar(); match *exception { 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); } } @@ -30,9 +31,26 @@ pub fn handle_exception(ctx: &Context, context: &UserContext) { } /// 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, 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, + trap_info: &CpuExceptionInfo, ) -> core::result::Result<(), ()> { const PAGE_NOT_PRESENT_ERROR_MASK: usize = 0x1 << 0; 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 write = trap_info.error_code & WRITE_ACCESS_MASK != 0; 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) { warn!( "page fault handler failed: addr: 0x{:x}, err: {:?}", diff --git a/kernel/src/vm/vmar/mod.rs b/kernel/src/vm/vmar/mod.rs index af91f2e64..c3f857020 100644 --- a/kernel/src/vm/vmar/mod.rs +++ b/kernel/src/vm/vmar/mod.rs @@ -21,7 +21,7 @@ use self::{ vm_mapping::VmMapping, }; 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 /// user address spaces. @@ -228,7 +228,7 @@ impl Vmar_ { free_regions, }; 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) }