summaryrefslogtreecommitdiff
path: root/Kernel
diff options
context:
space:
mode:
Diffstat (limited to 'Kernel')
-rw-r--r--Kernel/Arch/i386/CPU.cpp20
1 files changed, 17 insertions, 3 deletions
diff --git a/Kernel/Arch/i386/CPU.cpp b/Kernel/Arch/i386/CPU.cpp
index d1a9ccb136..ca5425cffd 100644
--- a/Kernel/Arch/i386/CPU.cpp
+++ b/Kernel/Arch/i386/CPU.cpp
@@ -401,9 +401,23 @@ void page_fault_handler(TrapFrame* trap)
dump(regs);
#endif
- bool faulted_in_userspace = (regs.cs & 3) == 3;
+ bool faulted_in_kernel = !(regs.cs & 3);
+
+ if (faulted_in_kernel && Processor::current().in_irq()) {
+ // If we're faulting in an IRQ handler, first check if we failed
+ // due to safe_memcpy, safe_strnlen, or safe_memset. If we did,
+ // gracefully continue immediately. Because we're in an IRQ handler
+ // we can't really try to resolve the page fault in a meaningful
+ // way, so we need to do this before calling into
+ // MemoryManager::handle_page_fault, which would just bail and
+ // request a crash
+ if (handle_safe_access_fault(regs, fault_address))
+ return;
+ }
+
+
auto current_thread = Thread::current();
- if (faulted_in_userspace && !MM.validate_user_stack(current_thread->process(), VirtualAddress(regs.userspace_esp))) {
+ if (!faulted_in_kernel && !MM.validate_user_stack(current_thread->process(), VirtualAddress(regs.userspace_esp))) {
dbg() << "Invalid stack pointer: " << VirtualAddress(regs.userspace_esp);
handle_crash(regs, "Bad stack on page fault", SIGSTKFLT);
ASSERT_NOT_REACHED();
@@ -412,7 +426,7 @@ void page_fault_handler(TrapFrame* trap)
auto response = MM.handle_page_fault(PageFault(regs.exception_code, VirtualAddress(fault_address)));
if (response == PageFaultResponse::ShouldCrash || response == PageFaultResponse::OutOfMemory) {
- if (!(regs.cs & 3) && handle_safe_access_fault(regs, fault_address)) {
+ if (faulted_in_kernel && handle_safe_access_fault(regs, fault_address)) {
// If this would be a ring0 (kernel) fault and the fault was triggered by
// safe_memcpy, safe_strnlen, or safe_memset then we resume execution at
// the appropriate _fault label rather than crashing