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/processor/SyscallHandler.h"
27#include "pedigree/kernel/processor/Syscalls.h"
28#include "pedigree/kernel/processor/state.h"
29#include "pedigree/kernel/processor/types.h"
30
31#include <config.h>
32
33class Thread;
34
41 protected:
42 struct PostSyscallAction;
43
44 private:
45 struct HandlerSlot;
46
47 public:
48 using FastEntry = uintptr_t (*)(SyscallHandler*, SyscallState&);
49
50 enum PostSyscallActionKind {
51 NoPostSyscallAction,
52 TerminateCurrentThread,
53 ExitCurrentProcess,
54 ReturnFromEvent,
55 PopEventState,
56 RestoreProcessorState,
57 JumpToUserspace,
58 RebootSystem
59 };
60
61 class EXPORTED_PUBLIC Registration {
62 public:
66
67 Registration& operator=(Registration&& other);
68
70 bool closeAdmission();
71
72 bool reset();
73 explicit operator bool() const {
74 return m_pManager != nullptr;
75 }
76
77 private:
78 friend class SyscallManager;
79
80 Registration(const Registration&) = delete;
81 Registration& operator=(const Registration&) = delete;
82
83 SyscallManager* m_pManager;
84 Service_t m_Service;
85 HandlerSlot* m_pSlot;
86 };
87
90 EXPORTED_PUBLIC static SyscallManager& instance();
96 virtual bool registerSyscallHandler(Service_t Service, SyscallHandler* pHandler,
97 Registration& registration, FastEntry entry = nullptr) = 0;
98
100 EXPORTED_PUBLIC bool requestThreadExit();
101 EXPORTED_PUBLIC bool requestProcessExit(int status);
102 EXPORTED_PUBLIC bool requestEventReturn();
103 EXPORTED_PUBLIC bool requestEventStatePop();
104 EXPORTED_PUBLIC bool requestStateRestore(const ProcessorState& state);
105 EXPORTED_PUBLIC bool requestUserJump(uintptr_t instructionPointer, uintptr_t stackPointer);
106 EXPORTED_PUBLIC bool requestReboot(Machine::ShutdownType type = Machine::ShutdownType::Restart);
107
109 virtual uintptr_t syscall(Service_t service, uintptr_t function, uintptr_t p1 = 0,
110 uintptr_t p2 = 0, uintptr_t p3 = 0, uintptr_t p4 = 0,
111 uintptr_t p5 = 0) = 0;
112
113#if PEDIGREE_CONCURRENCY_SMOKE_TESTS
115 EXPORTED_PUBLIC bool dispatchHandlerForTest(Service_t service, uintptr_t& result);
116#endif
117
118#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
119 using HandlerPinHook = void (*)(Service_t, SyscallHandler*);
120 using PostSyscallHook = bool (*)(PostSyscallActionKind, intptr_t, const ProcessorState*);
121
122 EXPORTED_PUBLIC void setHandlerPinHook(HandlerPinHook hook);
123 EXPORTED_PUBLIC void setPostSyscallHook(PostSyscallHook hook);
124#endif
125
126 protected:
128 PostSyscallAction() : kind(NoPostSyscallAction), value(0) {}
129
131 if (kind == RestoreProcessorState || kind == JumpToUserspace) {
132 state.~ProcessorState();
133 }
134 }
135
136 PostSyscallAction(const PostSyscallAction&) = delete;
137 PostSyscallAction& operator=(const PostSyscallAction&) = delete;
138
139 PostSyscallActionKind kind;
140 intptr_t value;
141 // Ordinary syscalls need only the discriminator. State-bearing actions
142 // copy-construct their owned payload before the handler's frame disappears.
143 union {
144 ProcessorState state;
145 };
146 };
147
155 public:
157 : m_pManager(nullptr), m_Cleanup(DeferredScopeRecord::Uninitialised{}) {}
159 if (m_pManager) {
160 m_pManager->releaseHandler(*this, true);
161 }
162 }
163
164 private:
165 friend class SyscallManager;
166
167 HandlerLease(const HandlerLease&) = delete;
168 HandlerLease& operator=(const HandlerLease&) = delete;
169
170 SyscallManager* m_pManager;
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 return lease.m_Entry(lease.m_pHandler, state);
184 }
185 bool closeHandler(Registration& registration);
186 bool unregisterHandler(Registration& registration);
187 bool acquireHandler(Service_t service, HandlerLease& lease, PostSyscallAction& action);
188
189#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
190 bool postSyscallHookHandled(const PostSyscallAction& action);
191#endif
192
197
198 private:
199 static uintptr_t dispatchVirtual(SyscallHandler* handler, SyscallState& state);
200 static bool inCallback();
201 static void abandonedHandlerCleanup(void* context);
202 bool requestPostSyscallAction(PostSyscallActionKind kind, intptr_t value,
203 const ProcessorState* state = nullptr);
204 void releaseHandler(HandlerLease& lease, bool normalReturn);
205
212
213 Spinlock m_HandlerLock;
214 HandlerSlot* m_HandlerSlots[serviceEnd];
215 HandlerSlot* m_Published[serviceEnd];
216 static HandlerSlot m_ClosingSlot;
217
218#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
219 HandlerPinHook m_HandlerPinHook;
220 PostSyscallHook m_PostSyscallHook;
221#endif
222};
223
226#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 &)