1#include "pedigree/kernel/BootstrapInfo.h"
2#include "pedigree/kernel/machine/Machine.h"
3#include "pedigree/kernel/process/initialiseMultitasking.h"
4#include "pedigree/kernel/processor/PageFaultHandler.h"
5#include "pedigree/kernel/processor/Processor.h"
6#include "pedigree/kernel/processor/state.h"
7#include "pedigree/kernel/utilities/StaticString.h"
9#include "PhysicalMemoryManager.h"
10#include "VirtualAddressSpace.h"
12extern "C" char arm64_boot_low_l0;
13extern "C" bool arm64SaveSchedulerState(SchedulerState* state);
14extern "C" void arm64RestoreSchedulerState(SchedulerState* state,
16extern "C" void arm64ReturnToUser(InterruptState* state,
volatile uintptr_t* lock,
18extern "C" void arm64JumpKernel(
volatile uintptr_t* lock, uintptr_t address, uintptr_t stack,
19 uintptr_t p1, uintptr_t p2, uintptr_t p3, uintptr_t p4)
NORETURN;
20extern "C" void arm64JumpUser(
volatile uintptr_t* lock, uintptr_t address, uintptr_t stack,
21 uintptr_t p1, uintptr_t p2, uintptr_t p3, uintptr_t p4,
25bool terminalTlbFailure =
false;
30 asm volatile(
"msr tpidr_el1, %0" : :
"r"(current) :
"memory");
31 Arm64PhysicalMemoryManager::instance().initialise(info);
37 initialiseMultitasking();
42 g_pBootstrapInfo =
nullptr;
46 shutdownMultitasking();
52 ?
reinterpret_cast<uintptr_t
>(&arm64_boot_low_l0)
55 asm volatile(
"mrs %0, ttbr0_el1" :
"=r"(current));
56 if ((current & ~uintptr_t(PAGE_SIZE - 1)) != root) {
57 asm volatile(
"dsb ishst\n\tmsr ttbr0_el1, %0\n\tisb\n\ttlbi vmalle1is\n\tdsb ish\n\tisb"
66 return arm64SaveSchedulerState(&state);
70 arm64RestoreSchedulerState(&state, lock);
74 arm64ReturnToUser(&state, lock,
information().getKernelStack());
78 volatile uintptr_t* lock) {
87 volatile uintptr_t* lock) {
96 volatile uintptr_t* lock, uintptr_t address, uintptr_t stack,
97 uintptr_t p1, uintptr_t p2, uintptr_t p3, uintptr_t p4) {
102 jumpKernel(lock, address, stack, p1, p2, p3, p4);
106 volatile uintptr_t* lock, uintptr_t address, uintptr_t stack,
107 uintptr_t p1, uintptr_t p2, uintptr_t p3, uintptr_t p4) {
112 jumpUser(lock, address, stack, p1, p2, p3, p4);
116 uintptr_t p1, uintptr_t p2, uintptr_t p3, uintptr_t p4) {
117 arm64JumpKernel(lock, address, stack, p1, p2, p3, p4);
121 uintptr_t p1, uintptr_t p2, uintptr_t p3, uintptr_t p4) {
122 uintptr_t kernelStack =
information().getKernelStack();
126 arm64JumpUser(lock, address, stack, p1, p2, p3, p4, kernelStack);
131 asm volatile(
"mov %0, x29" :
"=r"(value));
137 asm volatile(
"mov %0, sp" :
"=r"(value));
142 return reinterpret_cast<uintptr_t
>(__builtin_return_address(0));
146 asm volatile(
"msr tpidr_el0, %0" : :
"r"(value) :
"memory");
151 asm volatile(
"msr daifclr, #2" : : :
"memory");
153 asm volatile(
"msr daifset, #2" : : :
"memory");
159 asm volatile(
"mrs %0, daif" :
"=r"(daif));
160 return !(daif & (1U << 7));
164 asm volatile(
"brk #0");
174 asm volatile(
"wfi" : : :
"memory");
181 asm volatile(
"yield");
185 Machine::instance().
finalShutdown(Machine::ShutdownType::Restart);
197 type = DebugFlags::InstructionFetch;
210 state.pstate |= 1ULL << 21;
212 state.pstate &= ~(1ULL << 21);
217 asm volatile(
"dsb ishst" : : :
"memory");
219 uintptr_t page =
reinterpret_cast<uintptr_t
>(address) >> 12;
220 asm volatile(
"tlbi vaae1is, %0" : :
"r"(page) :
"memory");
222 asm volatile(
"tlbi vmalle1is" : : :
"memory");
224 asm volatile(
"dsb ish\n\tisb" : : :
"memory");
229 if (terminalTlbFailure || guard.m_Active ||
230 (context != ExecutionContext::WaitableThread && context != ExecutionContext::AtomicThread)) {
231 return TlbInvalidationResult::InvalidContext;
233 guard.m_Active =
true;
234 guard.m_Global =
false;
235 return TlbInvalidationResult::Success;
239 guard.m_Active =
false;
240 guard.m_Global =
false;
245 if (!guard.m_Active || terminalTlbFailure) {
248 terminalTlbFailure =
true;
253 return terminalTlbFailure;
256 return terminalTlbFailure;
262 return result == TlbInvalidationResult::Success ?
invalidateAll(address, guard) : result;
266 if (!guard.m_Active) {
267 return TlbInvalidationResult::InvalidContext;
269 if (m_nProcessors != 1) {
270 return TlbInvalidationResult::UnsupportedTopology;
273 return TlbInvalidationResult::Success;
277 asm volatile(
"ic ivau, %0\n\tdsb ish\n\tisb" : :
"r"(address) :
"memory");
281 asm volatile(
"dc ivac, %0\n\tdsb ish" : :
"r"(address) :
"memory");
285 asm volatile(
"dc cvac, %0\n\tdsb ish" : :
"r"(address) :
"memory");
290 asm volatile(
"mrs %0, ctr_el0" :
"=r"(ctr));
291 size_t dline = 4U << ((ctr >> 16) & 0xf);
292 size_t iline = 4U << (ctr & 0xf);
293 for (uintptr_t p = start & ~(dline - 1); p < end; p += dline) {
294 asm volatile(
"dc cvau, %0" : :
"r"(p) :
"memory");
296 asm volatile(
"dsb ish" : : :
"memory");
297 for (uintptr_t p = start & ~(iline - 1); p < end; p += iline) {
298 asm volatile(
"ic ivau, %0" : :
"r"(p) :
"memory");
300 asm volatile(
"dsb ish\n\tisb" : : :
"memory");
305 asm volatile(
"mrs %0, midr_el1" :
"=r"(midr));
306 text =
"ARM64 (MIDR ";
307 text.append(midr, 16, 16,
'0');
315 return m_nProcessors;
virtual void finalShutdown(ShutdownType type)
static PageFaultHandler & instance()
static void restoreState(SchedulerState &state, volatile uintptr_t *pLock=0) NORETURN
static void jumpUser(volatile uintptr_t *pLock, uintptr_t address, uintptr_t stack, uintptr_t p1=0, uintptr_t p2=0, uintptr_t p3=0, uintptr_t p4=0) NORETURN
static uintptr_t getDebugStatus()
static uintptr_t getInstructionPointer()
static void flushDCache(uintptr_t nAddr)
static void invalidateICache(uintptr_t nAddr)
static bool getInterrupts()
static MUST_USE_RESULT TlbInvalidationResult invalidateAll(void *pAddress)
static void initialise2(const BootstrapStruct_t &Info) INITIALISATION_ONLY
second/last stage in the initialisation of the processor-specific interface
static void setTlsBase(uintptr_t newBase)
static void initialise1(const BootstrapStruct_t &Info) INITIALISATION_ONLY
first stage in the initialisation of the processor-specific interface
static void initialisationDone()
static ProcessorInformation & information()
static void identify(HugeStaticString &str)
static bool saveState(SchedulerState &state)
static bool tlbInvalidationTerminal()
static uintptr_t getDebugBreakpoint(size_t nBpNumber, DebugFlags::FaultType &nFaultType, size_t &nLength, bool &bEnabled)
static bool tlbInvalidationFailureActive()
static size_t m_Initialised
static uintptr_t getStackPointer()
static void disableDebugBreakpoint(size_t nBpNumber)
static void switchAddressSpace(VirtualAddressSpace &AddressSpace)
static ExecutionContext executionContext()
static void flushDCacheAndInvalidateICache(uintptr_t startAddr, uintptr_t endAddr)
static void setSingleStep(bool bEnable, InterruptState &state)
static void switchState(bool bInterrupts, SchedulerState &a, SchedulerState &b, volatile uintptr_t *pLock=0)
static void endTlbInvalidation(TlbInvalidationGuard &guard)
static void invalidate(void *pAddress)
static uintptr_t getBasePointer()
static void jumpKernel(volatile uintptr_t *pLock, uintptr_t address, uintptr_t stack, uintptr_t p1=0, uintptr_t p2=0, uintptr_t p3=0, uintptr_t p4=0) NORETURN
static ProcessorInformation m_SafeBspProcessorInformation
static void invalidateDCache(uintptr_t nAddr)
static void enableDebugBreakpoint(size_t nBpNumber, uintptr_t nLinearAddress, DebugFlags::FaultType nFaultType, size_t nLength)
static void saveAndJumpKernel(bool bInterrupts, SchedulerState &s, volatile uintptr_t *pLock, uintptr_t address, uintptr_t stack, uintptr_t p1=0, uintptr_t p2=0, uintptr_t p3=0, uintptr_t p4=0)
static void setInterrupts(bool bEnable)
static void deinitialise()
static MUST_USE_RESULT TlbInvalidationResult beginTlbInvalidation(TlbInvalidationGuard &guard)
static size_t getDebugBreakpointCount()
static void saveAndJumpUser(bool bInterrupts, SchedulerState &s, volatile uintptr_t *pLock, uintptr_t address, uintptr_t stack, uintptr_t p1=0, uintptr_t p2=0, uintptr_t p3=0, uintptr_t p4=0)
static MUST_USE_RESULT bool closeTlbInvalidationAdmissionForTerminalFailure(TlbInvalidationGuard &guard, TlbInvalidationResult result)
static void haltUntilInterrupt()
static EXPORTED_PUBLIC VirtualAddressSpace & getKernelAddressSpace()