20#include "pedigree/kernel/Log.h"
21#include "pedigree/kernel/process/PerProcessorScheduler.h"
22#include "pedigree/kernel/processor/Processor.h"
23#include "pedigree/kernel/processor/hosted/ProcessorInformation.h"
24#include "pedigree/kernel/processor/types.h"
26#include "VirtualAddressSpace.h"
28namespace __pedigree_hosted {};
29using namespace __pedigree_hosted;
36#define SS_AUTODISARM (1U << 31)
39extern void* safe_stack_top;
42enum class HostedSignalStackMode :
size_t {
48size_t g_HostedSignalStackMode =
static_cast<size_t>(HostedSignalStackMode::Unprobed);
50HostedSignalStackMode hostedSignalStackMode() {
51 return static_cast<HostedSignalStackMode
>(
52 __atomic_load_n(&g_HostedSignalStackMode, __ATOMIC_ACQUIRE));
55int desiredHostedSignalStackFlags() {
56 return hostedSignalStackMode() == HostedSignalStackMode::ExplicitHandoff ? 0 : SS_AUTODISARM;
61 : m_ProcessorId(processorId),
66 m_HostedExecutionThreadId(0),
67 m_DeviceHardIrqDepth(0),
68 m_HostedSignalFrameDepth(0) {}
83Thread* HostedProcessorInformation::getCurrentThread()
const {
87void HostedProcessorInformation::setCurrentThread(
Thread* pThread) {
88 if (m_RcuState.active()) {
89 panic(
"Context switch inside an RCU read section.");
110static int trickSigaltstack(stack_t* p) {
111 return callOnStack(
reinterpret_cast<uintptr_t
>(&safe_stack_top),
112 reinterpret_cast<uintptr_t
>(sigaltstack),
reinterpret_cast<uintptr_t
>(p));
115static void installHostedSignalStack(stack_t& stack) {
116 int result = sigaltstack(&stack,
nullptr);
117 if (result < 0 && errno == EPERM) {
118 result = trickSigaltstack(&stack);
121 if (result < 0 && errno == EINVAL && (stack.ss_flags & SS_AUTODISARM) &&
122 hostedSignalStackMode() == HostedSignalStackMode::Unprobed) {
127 stack.ss_flags &= ~SS_AUTODISARM;
128 result = sigaltstack(&stack,
nullptr);
129 if (result < 0 && errno == EPERM) {
130 result = trickSigaltstack(&stack);
133 __atomic_store_n(&g_HostedSignalStackMode,
134 static_cast<size_t>(HostedSignalStackMode::ExplicitHandoff),
137 "Hosted signal stacks are using explicit scheduler "
138 "handoff because SS_AUTODISARM is unavailable");
144 if (stack.ss_flags & SS_AUTODISARM) {
145 __atomic_store_n(&g_HostedSignalStackMode,
146 static_cast<size_t>(HostedSignalStackMode::Autodisarm), __ATOMIC_RELEASE);
151 FATAL(
"Hosted failed to install a scheduler signal stack: errno=" <<
Dec << errno);
154void HostedProcessorInformation::setKernelStack(uintptr_t stack) {
155#if defined(PEDIGREE_HOSTED_DARWIN) && PEDIGREE_HOSTED_DARWIN
160 sigset_t blockedSignals;
161 sigset_t previousSignals;
162 sigfillset(&blockedSignals);
163 if (pthread_sigmask(SIG_SETMASK, &blockedSignals, &previousSignals) != 0) {
164 FATAL(
"Hosted failed to mask signals for a scheduler stack handoff");
170 void* new_sp =
reinterpret_cast<void*
>(stack - KERNEL_STACK_SIZE);
171 const int desiredFlags = desiredHostedSignalStackFlags();
173 if (sigaltstack(
nullptr, &s) < 0) {
174 FATAL(
"Hosted failed to inspect the scheduler signal stack");
176 if (s.ss_sp != new_sp || s.ss_size != KERNEL_STACK_SIZE || (s.ss_flags & SS_DISABLE) ||
177 (s.ss_flags & SS_AUTODISARM) != (desiredFlags & SS_AUTODISARM)) {
178 ByteSet(&s, 0,
sizeof(s));
180 s.ss_size = KERNEL_STACK_SIZE;
181 s.ss_flags = desiredFlags;
182 installHostedSignalStack(s);
186 if (sigaltstack(
nullptr, &s) < 0) {
187 FATAL(
"Hosted failed to inspect the scheduler signal stack");
189 if (!(s.ss_flags & SS_DISABLE)) {
190 ByteSet(&s, 0,
sizeof(s));
191 s.ss_flags = SS_DISABLE;
192 installHostedSignalStack(s);
198 const int handoffErrno = errno;
199 if (pthread_sigmask(SIG_SETMASK, &previousSignals,
nullptr) != 0) {
200 FATAL(
"Hosted failed to restore signals after a scheduler stack handoff");
202 errno = handoffErrno;
205uintptr_t HostedProcessorInformation::getKernelStack()
const {
static EXPORTED_PUBLIC VirtualAddressSpace & getKernelAddressSpace()
void EXPORTED_PUBLIC panic(const char *msg) NORETURN