10 #include "processor.h"
12 #include "std_macros.h"
18 * The global page fault handler switch.
19 * Handles page-fault monitoring, classification of page faults based on
20 * virtual-memory area they occured in, page-directory updates for kernel
21 * faults, IPC-window updates, and invocation of paging function for
22 * user-space page faults (handle_page_fault_pager).
23 * @param pfa page-fault virtual address
24 * @param error_code CPU error code
25 * @return true if page fault could be resolved, false otherwise
26 * @exception longjmp longjumps to recovery location if page-fault
27 * handling fails (i.e., return value would be false),
28 * but recovery location has been installed
30 IMPLEMENT inline NEEDS[<cstdio>,"regdefs.h", "kdb_ke.h","processor.h",
31 "config.h","std_macros.h","logdefs.h",
32 "warn.h",Thread::page_fault_log]
33 int Thread::handle_page_fault (Address pfa, Mword error_code, Mword pc,
36 //if (Config::Log_kernel_page_faults && !PF::is_usermode_error(error_code))
37 if (0 && current_cpu() != 0)
39 auto guard = lock_guard(cpu_lock);
40 printf("*KP[cpu=%u, sp=%lx, pfa=%lx, pc=%lx, error=(%lx)", current_cpu(), Proc::stack_pointer(), pfa, pc, error_code);
41 print_page_fault_error(error_code);
46 printf("Translation error ? %x\n"
47 " current space has mapping : %08x\n"
48 " Kernel space has mapping : %08x\n",
49 PF::is_translation_error(error_code),
50 current_mem_space()->lookup((void*)pfa),
51 Space::kernel_space()->lookup((void*)pfa));
57 // TODO: put this into a debug_page_fault_handler
58 if (EXPECT_FALSE(log_page_fault()))
59 page_fault_log(pfa, error_code, pc);
61 L4_msg_tag ipc_code = L4_msg_tag(0, 0, 0, 0);
63 // Check for page fault in user memory area
64 if (EXPECT_TRUE (!Kmem::is_kmem_page_fault(pfa, error_code)))
66 // Make sure that we do not handle page faults that do not
67 // belong to this thread.
68 //assert_kdb (mem_space() == current_mem_space());
70 if (EXPECT_FALSE (mem_space()->is_sigma0()))
72 // special case: sigma0 can map in anything from the kernel
73 if(handle_sigma0_page_fault(pfa))
80 // user mode page fault -- send pager request
81 if (handle_page_fault_pager(_pager, pfa, error_code,
82 L4_msg_tag::Label_page_fault))
88 // Check for page fault in kernel memory region caused by user mode
89 else if (EXPECT_FALSE(PF::is_usermode_error(error_code)))
90 return 0; // disallow access after mem_user_max
92 // Check for page fault in IO bit map or in delimiter byte behind IO bitmap
93 // assume it is caused by an input/output instruction and fall through to
95 else if (EXPECT_FALSE(Kmem::is_io_bitmap_page_fault(pfa)))
98 // We're in kernel code faulting on a kernel memory region
100 // A page is not present but a mapping exists in the global page dir.
101 // Update our page directory by copying from the master pdir
102 // This is the only path that should be executed with interrupts
103 // disabled if the page faulter also had interrupts disabled.
104 // thread_page_fault() takes care of that.
105 else if (Mem_layout::is_caps_area(pfa))
107 // Test for special case -- see function documentation
108 if (pagein_tcb_request(regs))
111 printf("Fiasco BUG: Invalid CAP access (pc=%lx, pfa=%lx)\n", pc, pfa);
112 kdb_ke("Fiasco BUG: Invalid access to Caps area");
116 WARN("No page-fault handler for 0x%lx, error 0x%lx, pc " L4_PTR_FMT "\n",
117 pfa, error_code, pc);
119 // An error occurred. Our last chance to recover is an exception
120 // handler a kernel function may have set.
124 longjmp (*_recover_jmpbuf, 1);