diff --git a/headers/private/kernel/thread_types.h b/headers/private/kernel/thread_types.h index 2088f8c98a..83ccfe30fe 100644 --- a/headers/private/kernel/thread_types.h +++ b/headers/private/kernel/thread_types.h @@ -224,6 +224,9 @@ struct team { typedef int32 (*thread_entry_func)(thread_func, void *); +typedef bool (*page_fault_callback)(addr_t address, addr_t faultAddress, + bool isWrite); + struct thread { int32 flags; // summary of events relevant in interrupt // handlers (signals pending, user debugging @@ -275,7 +278,13 @@ struct thread { cbuf *buffer; } msg; - addr_t fault_handler; + union { + addr_t fault_handler; + page_fault_callback fault_callback; + // TODO: this is a temporary field used for the vm86 implementation + // and should be removed again when that one is moved into the + // kernel entirely. + }; int32 page_faults_allowed; /* this field may only stay in debug builds in the future */ diff --git a/src/system/kernel/vm/vm.cpp b/src/system/kernel/vm/vm.cpp index b6e8a5f81c..b26e4b946f 100644 --- a/src/system/kernel/vm/vm.cpp +++ b/src/system/kernel/vm/vm.cpp @@ -3864,8 +3864,13 @@ vm_page_fault(addr_t address, addr_t faultAddress, bool isWrite, bool isUser, release_sem_etc(addressSpace->sem, READ_COUNT, 0); vm_put_address_space(addressSpace); #endif - if (user_debug_exception_occurred(B_SEGMENT_VIOLATION, SIGSEGV)) - send_signal(team_get_current_team_id(), SIGSEGV); + struct thread *thread = thread_get_current_thread(); + // TODO: the fault_callback is a temporary solution for vm86 + if (thread->fault_callback == NULL + || thread->fault_callback(address, faultAddress, isWrite)) { + if (user_debug_exception_occurred(B_SEGMENT_VIOLATION, SIGSEGV)) + send_signal(team_get_current_team_id(), SIGSEGV); + } } }