The Pedigree Project 0.1
arm64/PageFaultHandler.cc
1#include "pedigree/kernel/Log.h"
2#include "pedigree/kernel/Subsystem.h"
3#include "pedigree/kernel/panic.h"
4#include "pedigree/kernel/process/Process.h"
5#include "pedigree/kernel/process/Thread.h"
6#include "pedigree/kernel/processor/InterruptManager.h"
7#include "pedigree/kernel/processor/PageFaultHandler.h"
8#include "pedigree/kernel/processor/Processor.h"
9#include "pedigree/kernel/processor/VirtualAddressSpace.h"
10#include "pedigree/kernel/processor/state.h"
11
13
17
18void PageFaultHandler::interrupt(size_t, InterruptState& state) {
19 const uintptr_t address = state.far;
20 const uintptr_t page = address & ~(PAGE_SIZE - 1);
21 const size_t faultStatus = state.esr & 0x3f;
22 const size_t exceptionClass = (state.esr >> 26) & 0x3f;
23 const bool fetch = exceptionClass == 0x20 || exceptionClass == 0x21;
24 const bool write = !fetch && (state.esr & (1U << 6));
25 const bool present = (faultStatus & 0x3c) == 0x0c;
26 VirtualAddressSpace& space = Processor::information().getVirtualAddressSpace();
27 if (present && write &&
28 space.handleCopyOnWriteFault(reinterpret_cast<void*>(page), !state.kernelMode())) {
29 return;
30 }
31 if (dispatchHandlers(state, address, write, present)) {
32 return;
33 }
34
35 Thread* thread = Processor::information().getCurrentThread();
36 if (thread && !state.kernelMode()) {
37 Process* process = thread->getParent();
38 if (process && process->getSubsystem()) {
39 const uintptr_t errorCode = (present ? 1 : 0) | (write ? 2 : 0) | 4 | (fetch ? 16 : 0);
40 thread->deferSubsystemException(static_cast<size_t>(Subsystem::PageFault), address,
41 errorCode);
42 return;
43 }
44 }
45 ERROR("ARM64: page fault at " << Hex << address << " PC " << state.pc << " ESR " << state.esr);
46 panic("ARM64: unrecoverable page fault");
47}
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()
bool deferSubsystemException(size_t type, uintptr_t faultAddress, uintptr_t errorCode)
Definition Thread.cc:3597
Process * getParent() const
Definition Thread.h:325
virtual bool handleCopyOnWriteFault(void *virtualAddress, bool userMode)=0
void EXPORTED_PUBLIC panic(const char *msg) NORETURN
Definition panic.cc:117
@ Hex
Definition Log.h:124