]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/thread-pagefault.cpp
c2ae77c5ca04ea17c606589be8f992fae0abe746
[l4.git] / kernel / fiasco / src / kern / thread-pagefault.cpp
1 IMPLEMENTATION:
2
3 #include <cstdio>
4
5 #include "config.h"
6 #include "cpu.h"
7 #include "kdb_ke.h"
8 #include "kmem.h"
9 #include "logdefs.h"
10 #include "processor.h"
11 #include "regdefs.h"
12 #include "std_macros.h"
13 #include "thread.h"
14 #include "warn.h"
15
16
17 /** 
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           
29  */
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,
34     Return_frame *regs)
35 {
36   //if (Config::Log_kernel_page_faults && !PF::is_usermode_error(error_code))
37   if (0 && current_cpu() != 0)
38     {
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);
42       printf("]\n");
43     }
44
45 #if 0
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));
52 #endif
53
54
55   CNT_PAGE_FAULT;
56
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);
60
61   L4_msg_tag ipc_code = L4_msg_tag(0, 0, 0, 0);
62
63   // Check for page fault in user memory area
64   if (EXPECT_TRUE (!Kmem::is_kmem_page_fault(pfa, error_code)))
65     {
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());
69
70       if (EXPECT_FALSE (mem_space()->is_sigma0()))
71         {
72           // special case: sigma0 can map in anything from the kernel
73           if(handle_sigma0_page_fault(pfa))
74             return 1;
75
76           ipc_code.set_error();
77           goto error;
78         }
79
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))
83         return 1;
84
85       goto error;
86     }
87
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
91
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
94   // handle_slow_trap
95   else if (EXPECT_FALSE(Kmem::is_io_bitmap_page_fault(pfa)))
96     return 0;
97
98   // We're in kernel code faulting on a kernel memory region
99
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))
106     {
107       // Test for special case -- see function documentation
108       if (pagein_tcb_request(regs))
109          return 2;
110
111       printf("Fiasco BUG: Invalid CAP access (pc=%lx, pfa=%lx)\n", pc, pfa);
112       kdb_ke("Fiasco BUG: Invalid access to Caps area");
113       return 0;
114     }
115
116   WARN("No page-fault handler for 0x%lx, error 0x%lx, pc " L4_PTR_FMT "\n",
117         pfa, error_code, pc);
118
119   // An error occurred.  Our last chance to recover is an exception
120   // handler a kernel function may have set.
121  error:
122
123   if (_recover_jmpbuf)
124     longjmp (*_recover_jmpbuf, 1);
125
126   return 0;
127 }