20#include "pedigree/kernel/Log.h"
21#include "pedigree/kernel/Metrics.h"
22#include "pedigree/kernel/Subsystem.h"
23#include "pedigree/kernel/debugger/Debugger.h"
24#include "pedigree/kernel/panic.h"
25#include "pedigree/kernel/process/Process.h"
26#include "pedigree/kernel/process/Scheduler.h"
27#include "pedigree/kernel/process/Thread.h"
28#include "pedigree/kernel/processor/InterruptManager.h"
29#include "pedigree/kernel/processor/PageFaultHandler.h"
30#include "pedigree/kernel/processor/Processor.h"
31#include "pedigree/kernel/processor/state.h"
33#include "HostedPlatform.h"
34#include "InterruptManager.h"
35#include "VirtualAddressSpace.h"
37namespace __pedigree_hosted {};
38using namespace __pedigree_hosted;
40#if HAS_ADDRESS_SANITIZER
41extern "C" void __asan_report_error(
void* pc,
void* bp,
void* sp,
void* addr,
int is_write,
61 Metrics::increment(Metrics::PageFault);
64 siginfo_t* info =
reinterpret_cast<siginfo_t*
>(state.getRegister(1));
66 uintptr_t page =
reinterpret_cast<uintptr_t
>(
page_align(info->si_addr));
67 uintptr_t unaligned_page =
reinterpret_cast<uintptr_t
>(info->si_addr);
68 uintptr_t code = info->si_code;
69 uintptr_t ucontext_loc = state.getRegister(2);
70 ucontext_t* ctx =
reinterpret_cast<ucontext_t*
>(ucontext_loc);
72 state.setInstructionPointer(HostedPlatform::instructionPointer(ctx));
73 state.setStackPointer(HostedPlatform::stackPointer(ctx));
74 state.setBasePointer(HostedPlatform::basePointer(ctx));
77 uintptr_t errorCode = code;
78 bool wasPresent = code == SEGV_ACCERR;
79#if defined(__APPLE__) && defined(__aarch64__)
80 isWrite = (ctx->uc_mcontext->__es.__esr & (1U << 6U)) != 0;
81 errorCode = (wasPresent ? 0x1 : 0) | (isWrite ? 0x2 : 0);
82#elif defined(__APPLE__) && defined(__x86_64__)
83 errorCode = ctx->uc_mcontext->__es.__err;
84 isWrite = (errorCode & 0x2) != 0;
85 wasPresent = (errorCode & 0x1) != 0;
89 isWrite = (ctx->uc_mcontext.gregs[REG_ERR] & 0x2) != 0;
90 errorCode = ctx->uc_mcontext.gregs[REG_ERR];
91 wasPresent = (errorCode & 0x1) != 0;
95 if (wasPresent && isWrite &&
98 Metrics::increment(Metrics::PageFaultCopyOnWrite);
103 if (page <
reinterpret_cast<uintptr_t
>(KERNEL_SPACE_START)) {
104 if (dispatchHandlers(state, page, isWrite, wasPresent)) {
105 if (collectMetrics) {
106 Metrics::increment(Metrics::PageFaultHandled);
113 if (pThread && !state.kernelMode()) {
115 if (process && process->getSubsystem()) {
118 if (collectMetrics) {
119 Metrics::increment(Metrics::PageFaultDeferred);
125#if HAS_ADDRESS_SANITIZER
129 .getOriginalSigaction(info->si_signo);
130 if (oact.sa_handler == SIG_IGN) {
132 }
else if (oact.sa_handler == SIG_DFL) {
133 sigaction(info->si_signo, &oact,
nullptr);
134 raise(info->si_signo);
135 }
else if (oact.sa_flags & SA_SIGINFO) {
136 oact.sa_sigaction(info->si_signo, info, ctx);
138 oact.sa_handler(info->si_signo);
147 sError.append(
"Page Fault Exception at 0x");
148 sError.append(unaligned_page, 16, 8,
'0');
149 sError.append(
", error code 0x");
150 sError.append(code, 16, 8,
'0');
151 sError.append(
", EIP 0x");
152 sError.append(state.getInstructionPointer(), 16, 8,
'0');
157 sCode.append(
"Details: PID=");
161 if (code == SEGV_MAPERR)
162 sCode.append(
"NOT ");
163 sCode.append(
"PRESENT | ");
164 if (code == SEGV_ACCERR)
165 sCode.append(
"ACCESS ERROR");
167 ERROR(
static_cast<const char*
>(sError));
168 ERROR(
static_cast<const char*
>(sCode));
171 if (state.kernelMode())
185 Subsystem* pSubsystem = pProcess->getSubsystem();
186 if (!pSubsystem || state.kernelMode()) {
void start(InterruptState &state, LargeStaticString &description)
static Debugger & instance()
Handles interrupts and interrupt registrations from kernel components.
static EXPORTED_PUBLIC InterruptManager & instance()
virtual bool registerInterruptHandler(size_t nInterruptNumber, InterruptHandler *pHandler)=0
static EXPORTED_PUBLIC PageFaultHandler m_Instance
virtual void interrupt(size_t interruptNumber, InterruptState &state)
static ProcessorInformation & information()
static size_t m_Initialised
This class manages how processes and threads are scheduled across processors.
static Scheduler & instance()
bool deferSubsystemException(size_t type, uintptr_t faultAddress, uintptr_t errorCode)
Process * getParent() const
virtual bool handleCopyOnWriteFault(void *virtualAddress, bool userMode)=0
void EXPORTED_PUBLIC panic(const char *msg) NORETURN
EXPORTED_PUBLIC void * page_align(void *p) PURE