The Pedigree Project 0.1
include/pedigree/kernel/processor/SyscallManager.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_PROCESSOR_SYSCALLMANAGER_H
21#define KERNEL_PROCESSOR_SYSCALLMANAGER_H
22#include "pedigree/kernel/Spinlock.h"
23#include "pedigree/kernel/compiler.h"
24#include "pedigree/kernel/machine/Machine.h"
25#include "pedigree/kernel/process/DeferredScope.h"
26#include "pedigree/kernel/process/Thread.h"
27#include "pedigree/kernel/processor/SyscallHandler.h"
28#include "pedigree/kernel/processor/Syscalls.h"
29#include "pedigree/kernel/processor/state.h"
30#include "pedigree/kernel/processor/types.h"
31
32#include <config.h>
33
34class Thread;
35
42 protected:
43 struct PostSyscallAction;
44
45 private:
46 struct HandlerSlot;
47
48 public:
49 using FastEntry = uintptr_t (*)(SyscallHandler*, SyscallState&);
50
51 enum PostSyscallActionKind {
52 NoPostSyscallAction,
53 TerminateCurrentThread,
54 ExitCurrentProcess,
55 ReturnFromEvent,
56 PopEventState,
57 RestoreProcessorState,
58 JumpToUserspace,
59 RebootSystem
60 };
61
62 class EXPORTED_PUBLIC Registration {
63 public:
67
68 Registration& operator=(Registration&& other);
69
71 bool closeAdmission();
72
73 bool reset();
74 explicit operator bool() const {
75 return m_pManager != nullptr;
76 }
77
78 private:
79 friend class SyscallManager;
80
81 Registration(const Registration&) = delete;
82 Registration& operator=(const Registration&) = delete;
83
84 SyscallManager* m_pManager;
85 Service_t m_Service;
86 HandlerSlot* m_pSlot;
87 };
88
91 EXPORTED_PUBLIC static SyscallManager& instance();
97 virtual bool registerSyscallHandler(Service_t Service, SyscallHandler* pHandler,
98 Registration& registration, FastEntry entry = nullptr) = 0;
99
101 EXPORTED_PUBLIC bool requestThreadExit();
102 EXPORTED_PUBLIC bool requestProcessExit(int status);
103 EXPORTED_PUBLIC bool requestEventReturn();
104 EXPORTED_PUBLIC bool requestEventStatePop();
105 EXPORTED_PUBLIC bool requestStateRestore(const ProcessorState& state);
106 EXPORTED_PUBLIC bool requestUserJump(uintptr_t instructionPointer, uintptr_t stackPointer);
107 EXPORTED_PUBLIC bool requestReboot(Machine::ShutdownType type = Machine::ShutdownType::Restart);
108
110 virtual uintptr_t syscall(Service_t service, uintptr_t function, uintptr_t p1 = 0,
111 uintptr_t p2 = 0, uintptr_t p3 = 0, uintptr_t p4 = 0,
112 uintptr_t p5 = 0) = 0;
113
114#if PEDIGREE_CONCURRENCY_SMOKE_TESTS
116 EXPORTED_PUBLIC bool dispatchHandlerForTest(Service_t service, uintptr_t& result);
117#endif
118
119#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
120 using HandlerPinHook = void (*)(Service_t, SyscallHandler*);
121 using PostSyscallHook = bool (*)(PostSyscallActionKind, intptr_t, const ProcessorState*);
122
123 EXPORTED_PUBLIC void setHandlerPinHook(HandlerPinHook hook);
124 EXPORTED_PUBLIC void setPostSyscallHook(PostSyscallHook hook);
125#endif
126
127 protected:
129 PostSyscallAction() : kind(NoPostSyscallAction), value(0) {}
130
132 if (kind == RestoreProcessorState || kind == JumpToUserspace) {
133 state.~ProcessorState();
134 }
135 }
136
137 PostSyscallAction(const PostSyscallAction&) = delete;
138 PostSyscallAction& operator=(const PostSyscallAction&) = delete;
139
140 PostSyscallActionKind kind;
141 intptr_t value;
142 // Ordinary syscalls need only the discriminator. State-bearing actions
143 // copy-construct their owned payload before the handler's frame disappears.
144 union {
145 ProcessorState state;
146 };
147 };
148
156 public:
158 : m_pThread(nullptr), m_Cleanup(DeferredScopeRecord::Uninitialised{}) {}
160 if (m_pThread) {
161 releaseHandler(*this, true);
162 }
163 }
164
165 private:
166 friend class SyscallManager;
167
168 HandlerLease(const HandlerLease&) = delete;
169 HandlerLease& operator=(const HandlerLease&) = delete;
170
171 Service_t m_Service;
172 SyscallHandler* m_pHandler;
173 FastEntry m_Entry;
174 Thread* m_pThread;
175 HandlerLease* m_Previous;
176 PostSyscallAction* m_Action;
177 DeferredScopeRecord m_Cleanup;
178 };
179
180 bool registerHandler(Service_t service, SyscallHandler* pHandler, Registration& registration,
181 FastEntry entry = nullptr);
182 ALWAYS_INLINE uintptr_t dispatchHandler(const HandlerLease& lease, SyscallState& state) const {
183 if (UNLIKELY(lease.m_pThread->hasSecurityState())) {
184 auto security = lease.m_pThread->securityState();
185 uintptr_t result = 0;
186 if (security && security->interceptSyscall(state, result)) {
187 return result;
188 }
189 }
190 return lease.m_Entry(lease.m_pHandler, state);
191 }
192 bool closeHandler(Registration& registration);
193 bool unregisterHandler(Registration& registration);
194 bool acquireHandler(Service_t service, HandlerLease& lease, PostSyscallAction& action);
195
196#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
197 bool postSyscallHookHandled(const PostSyscallAction& action);
198#endif
199
204
205 private:
206 static uintptr_t dispatchVirtual(SyscallHandler* handler, SyscallState& state);
207 static bool inCallback();
208 static void abandonedHandlerCleanup(void* context);
209 bool requestPostSyscallAction(PostSyscallActionKind kind, intptr_t value,
210 const ProcessorState* state = nullptr);
211 static void releaseHandler(HandlerLease& lease, bool normalReturn);
212
219
220 Spinlock m_HandlerLock;
221 HandlerSlot* m_HandlerSlots[serviceEnd];
222 HandlerSlot* m_Published[serviceEnd];
223 static HandlerSlot m_ClosingSlot;
224
225#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
226 HandlerPinHook m_HandlerPinHook;
227 PostSyscallHook m_PostSyscallHook;
228#endif
229};
230
233#endif
virtual uintptr_t syscall(Service_t service, uintptr_t function, uintptr_t p1=0, uintptr_t p2=0, uintptr_t p3=0, uintptr_t p4=0, uintptr_t p5=0)=0
virtual bool registerSyscallHandler(Service_t Service, SyscallHandler *pHandler, Registration &registration, FastEntry entry=nullptr)=0
SyscallManager(const SyscallManager &)
virtual ~SyscallManager()
static EXPORTED_PUBLIC SyscallManager & instance()
EXPORTED_PUBLIC bool requestThreadExit()
SyscallManager & operator=(const SyscallManager &)