The Pedigree Project 0.1
PageFaultHandler.h
1/*
2 * Copyright (c) 2008-2014, Pedigree Developers
3 *
4 * Please see the CONTRIB file in the root of the source tree for a full
5 * list of contributors.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#ifndef KERNEL_CORE_PROCESSOR_PAGEFAULTHANDLER_H_
21#define KERNEL_CORE_PROCESSOR_PAGEFAULTHANDLER_H_
22#include "pedigree/kernel/Spinlock.h"
23#include "pedigree/kernel/compiler.h"
24#include "pedigree/kernel/process/AtomicStateCleanup.h"
25#include "pedigree/kernel/process/WaitQueue.h"
26#include "pedigree/kernel/processor/InterruptHandler.h"
27#include "pedigree/kernel/processor/state_forward.h"
28#include "pedigree/kernel/processor/types.h"
29
30#include <config.h>
31
35class Thread;
36
37class EXPORTED_PUBLIC MemoryTrapHandler {
38 public:
39 virtual ~MemoryTrapHandler();
40
49 virtual bool trap(InterruptState& state, uintptr_t address, bool bIsWrite, bool bWasPresent) = 0;
50};
51
54 public:
57 inline static PageFaultHandler& instance() {
58 return m_Instance;
59 }
60
63 bool initialise();
64
71 EXPORTED_PUBLIC bool registerHandler(MemoryTrapHandler* pHandler);
72
82 EXPORTED_PUBLIC bool unregisterHandler(MemoryTrapHandler* pHandler);
83
84#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
85 using HandlerPinHook = void (*)(MemoryTrapHandler*);
86 using HandlerPrePinHook = void (*)(MemoryTrapHandler*);
87 using AtomicDrainHook = void (*)(MemoryTrapHandler*);
88 using MutationLockHook = void (*)();
89
91 static EXPORTED_PUBLIC void setHandlerPinHook(HandlerPinHook hook);
92
94 static EXPORTED_PUBLIC void setHandlerPrePinHook(HandlerPrePinHook hook);
95
97 static EXPORTED_PUBLIC void setAtomicDrainHook(AtomicDrainHook hook);
98
100 EXPORTED_PUBLIC void withMutationLockForTest(MutationLockHook hook);
101
103 EXPORTED_PUBLIC bool dispatchHandlerForTest(MemoryTrapHandler* pHandler);
104
106 EXPORTED_PUBLIC size_t activeDispatchCountForTest(MemoryTrapHandler* pHandler);
107#endif
108
109 //
110 // InterruptHandler interface.
111 //
112 virtual void interrupt(size_t interruptNumber, InterruptState& state);
113
114 private:
117
121
122 bool dispatchHandlers(InterruptState& state, uintptr_t address, bool bIsWrite, bool bWasPresent,
123 MemoryTrapHandler* pOnlyHandler = nullptr);
124
125 static const size_t MaxMemoryTrapHandlers = 16;
126 static const size_t MaxActiveDispatches = 64;
127
128 enum class SlotMode : size_t {
129 Empty = 0,
130 Enabled,
131 Draining,
132 Deferred,
133 Retiring,
134 };
135
136 static const size_t ModeBits = 3;
137 static const size_t ModeMask = (1 << ModeBits) - 1;
138 static const size_t GenerationShift = ModeBits;
139
140 struct HandlerSlot;
141
143 ActiveDispatch() : token(nullptr), generation(0), owner(nullptr), slot(nullptr) {}
144
145 void* token;
146 size_t generation;
147 void* owner;
148 HandlerSlot* slot;
149 };
150
151 struct HandlerSlot {
152 HandlerSlot() : handler(nullptr), publication(0) {}
153
154 MemoryTrapHandler* handler;
155 size_t publication;
156 };
157
159 explicit DispatchCleanup(PageFaultHandler* registry)
160 : registry(registry), activeDispatch(nullptr), cleanup() {}
161
162 PageFaultHandler* registry;
163 ActiveDispatch* activeDispatch;
165 };
166
167 static size_t makePublication(size_t generation, SlotMode mode);
168 static size_t generationOf(size_t publication);
169 static SlotMode modeOf(size_t publication);
170
171 bool retireSlot(HandlerSlot& slot, size_t expectedPublication,
172 MemoryTrapHandler* expectedHandler);
173 bool publishDispatch(HandlerSlot& slot, void* owner, DispatchCleanup& cleanup);
174 void unpublishDispatch(DispatchCleanup& cleanup);
175 static void abandonedHandlerCleanup(void* context);
176 bool hasActiveDispatch(HandlerSlot& slot) const;
177 bool findCurrentDispatch(void* owner, HandlerSlot* target, bool& callbackContext) const;
178 static void* currentDispatchOwner();
179
181 HandlerSlot m_Handlers[MaxMemoryTrapHandlers];
182 ActiveDispatch m_ActiveDispatches[MaxActiveDispatches];
183 WaitQueue m_DispatchWaiters;
184 Spinlock m_HandlerLock;
185
186#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
187 static HandlerPinHook m_HandlerPinHook;
188 static HandlerPrePinHook m_HandlerPrePinHook;
189 static AtomicDrainHook m_AtomicDrainHook;
190#endif
191
193 EXPORTED_PUBLIC static PageFaultHandler m_Instance;
194};
195
198#endif /* KERNEL_CORE_PROCESSOR_X86_PAGEFAULTHANDLER_H_ */
Abstract base class for interrupt-handlers.
virtual bool trap(InterruptState &state, uintptr_t address, bool bIsWrite, bool bWasPresent)=0
HandlerSlot m_Handlers[MaxMemoryTrapHandlers]
EXPORTED_PUBLIC bool unregisterHandler(MemoryTrapHandler *pHandler)
static EXPORTED_PUBLIC PageFaultHandler m_Instance
EXPORTED_PUBLIC bool registerHandler(MemoryTrapHandler *pHandler)
static PageFaultHandler & instance()
PageFaultHandler() INITIALISATION_ONLY