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/linker/KernelElf.h"
25#include "pedigree/kernel/panic.h"
26#include "pedigree/kernel/process/Process.h"
27#include "pedigree/kernel/process/Scheduler.h"
28#include "pedigree/kernel/process/Thread.h"
29#include "pedigree/kernel/processor/InterruptManager.h"
30#include "pedigree/kernel/processor/PageFaultHandler.h"
31#include "pedigree/kernel/processor/PhysicalMemoryManager.h"
32#include "pedigree/kernel/processor/Processor.h"
33#include "pedigree/kernel/processor/ProcessorInformation.h"
34#include "pedigree/kernel/processor/VirtualAddressSpace.h"
35#include "pedigree/kernel/processor/state.h"
36#include "pedigree/kernel/utilities/Iterator.h"
37#include "pedigree/kernel/utilities/StaticString.h"
38#include "pedigree/kernel/utilities/utility.h"
42#define PAGE_FAULT_EXCEPTION 0x0E
43#define PFE_PAGE_PRESENT 0x01
44#define PFE_ATTEMPTED_WRITE 0x02
45#define PFE_USER_MODE 0x04
46#define PFE_RESERVED_BIT 0x08
47#define PFE_INSTRUCTION_FETCH 0x10
48#define PFE_PROTECTION_KEY 0x20
49#define PFE_SHADOW_STACK 0x40
60 Metrics::increment(Metrics::PageFault);
64 asm volatile(
"mov %%cr2, %%rax" :
"=a"(cr2));
65 code = state.m_Errorcode;
70 const bool copyOnWriteFault =
71 (code & (PFE_PAGE_PRESENT | PFE_ATTEMPTED_WRITE)) ==
72 (PFE_PAGE_PRESENT | PFE_ATTEMPTED_WRITE) &&
73 !(code & (PFE_RESERVED_BIT | PFE_INSTRUCTION_FETCH | PFE_PROTECTION_KEY | PFE_SHADOW_STACK));
74 if (copyOnWriteFault &&
77 Metrics::increment(Metrics::PageFaultCopyOnWrite);
85 if (dispatchHandlers(state, cr2, code & PFE_ATTEMPTED_WRITE, code & PFE_PAGE_PRESENT)) {
87 Metrics::increment(Metrics::PageFaultHandled);
95 if (pThread && !state.kernelMode()) {
97 if (process && process->getSubsystem()) {
100 Metrics::increment(Metrics::PageFaultDeferred);
108 sError.append(
"Page Fault Exception at 0x");
109 sError.append(cr2, 16, 16,
'0');
110 sError.append(
", EIP 0x");
111 sError.append(state.getInstructionPointer(), 16, 16,
'0');
112 sError.append(
", error code 0x");
113 sError.append(code, 16, 8,
'0');
124 sCode.append(
"Details: CPU=");
129 sCode.append(
" PID=");
130 sCode.append(pParent->
getId());
132 sCode.append(
" TID=");
133 sCode.append(pThread->
getId());
137 if (!(code & PFE_PAGE_PRESENT))
138 sCode.append(
"NOT ");
139 sCode.append(
"PRESENT | ");
141 if (code & PFE_ATTEMPTED_WRITE)
142 sCode.append(
"WRITE | ");
144 sCode.append(
"READ | ");
146 if (code & PFE_USER_MODE)
147 sCode.append(
"USER ");
149 sCode.append(
"KERNEL ");
150 sCode.append(
"MODE | ");
152 if (code & PFE_RESERVED_BIT)
153 sCode.append(
"RESERVED BIT SET | ");
154 if (code & PFE_INSTRUCTION_FETCH)
155 sCode.append(
"FETCH |");
160 ERROR(
static_cast<const char*
>(sError));
161 ERROR(
static_cast<const char*
>(sCode));
167 if (!(code & PFE_USER_MODE))
179 Subsystem* pSubsystem = pProcess->getSubsystem();
180 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 KernelElf & instance()
static EXPORTED_PUBLIC PageFaultHandler m_Instance
virtual void interrupt(size_t interruptNumber, InterruptState &state)
static PhysicalMemoryManager & instance()
static constexpr size_t getPageSize() PURE
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
virtual bool memIsInKernelHeap(void *pMem)=0
void EXPORTED_PUBLIC panic(const char *msg) NORETURN