summaryrefslogtreecommitdiff
path: root/Kernel/Arch
diff options
context:
space:
mode:
authorIdan Horowitz <idan.horowitz@gmail.com>2023-04-02 03:41:41 +0300
committerAndrew Kaster <andrewdkaster@gmail.com>2023-04-03 02:59:37 -0600
commit402c9e5e23e12500807a9b29b2d8b6465a496446 (patch)
treef6cd0410dc70277df17044c317c509f0e04ba811 /Kernel/Arch
parent0dc5c499387440497d93c9902a2fdc66d4ba5a02 (diff)
downloadserenity-402c9e5e23e12500807a9b29b2d8b6465a496446.zip
Kernel: Implement Processor::assume_context for AArch64
With this implemented sys$execve should be fully working on AArch64.
Diffstat (limited to 'Kernel/Arch')
-rw-r--r--Kernel/Arch/aarch64/Processor.cpp48
-rw-r--r--Kernel/Arch/aarch64/RegisterState.h3
-rw-r--r--Kernel/Arch/aarch64/TrapFrame.h3
3 files changed, 51 insertions, 3 deletions
diff --git a/Kernel/Arch/aarch64/Processor.cpp b/Kernel/Arch/aarch64/Processor.cpp
index 3946f8ea33..431828b380 100644
--- a/Kernel/Arch/aarch64/Processor.cpp
+++ b/Kernel/Arch/aarch64/Processor.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2022, Timon Kruiper <timonkruiper@gmail.com>
+ * Copyright (c) 2023, Idan Horowitz <idan.horowitz@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@@ -23,8 +24,10 @@ namespace Kernel {
extern "C" void thread_context_first_enter(void);
extern "C" void exit_kernel_thread(void);
+extern "C" void do_assume_context(Thread* thread, u32 new_interrupts_state);
extern "C" void context_first_init(Thread* from_thread, Thread* to_thread) __attribute__((used));
extern "C" void enter_thread_context(Thread* from_thread, Thread* to_thread) __attribute__((used));
+extern "C" FlatPtr do_init_context(Thread* thread, u32 new_interrupts_state) __attribute__((used));
Processor* g_current_processor;
READONLY_AFTER_INIT FPUState Processor::s_clean_fpu_state;
@@ -255,11 +258,31 @@ void Processor::switch_context(Thread*& from_thread, Thread*& to_thread)
dbgln_if(CONTEXT_SWITCH_DEBUG, "switch_context <-- from {} {} to {} {}", VirtualAddress(from_thread), *from_thread, VirtualAddress(to_thread), *to_thread);
}
+extern "C" FlatPtr do_init_context(Thread* thread, u32 new_interrupts_state)
+{
+ VERIFY_INTERRUPTS_DISABLED();
+
+ Aarch64::SPSR_EL1 spsr_el1 = {};
+ memcpy(&spsr_el1, (u8 const*)&thread->regs().spsr_el1, sizeof(u64));
+ spsr_el1.I = (new_interrupts_state == to_underlying(InterruptsState::Disabled));
+ memcpy((void*)&thread->regs().spsr_el1, &spsr_el1, sizeof(u64));
+
+ return Processor::current().init_context(*thread, true);
+}
+
void Processor::assume_context(Thread& thread, InterruptsState new_interrupts_state)
{
- (void)thread;
- (void)new_interrupts_state;
- TODO_AARCH64();
+ dbgln_if(CONTEXT_SWITCH_DEBUG, "Assume context for thread {} {}", VirtualAddress(&thread), thread);
+
+ VERIFY_INTERRUPTS_DISABLED();
+ Scheduler::prepare_after_exec();
+ // in_critical() should be 2 here. The critical section in Process::exec
+ // and then the scheduler lock
+ VERIFY(Processor::in_critical() == 2);
+
+ do_assume_context(&thread, to_underlying(new_interrupts_state));
+
+ VERIFY_NOT_REACHED();
}
FlatPtr Processor::init_context(Thread& thread, bool leave_crit)
@@ -415,6 +438,25 @@ NAKED void thread_context_first_enter(void)
"b restore_context_and_eret \n");
}
+NAKED void do_assume_context(Thread*, u32)
+{
+ // clang-format off
+ asm(
+ "mov x19, x0 \n" // save thread ptr
+ // We're going to call Processor::init_context, so just make sure
+ // we have enough stack space so we don't stomp over it
+ "sub sp, sp, #" __STRINGIFY(8 + REGISTER_STATE_SIZE + TRAP_FRAME_SIZE + 8) " \n"
+ "bl do_init_context \n"
+ "mov sp, x0 \n" // move stack pointer to what Processor::init_context set up for us
+ "mov x0, x19 \n" // to_thread
+ "mov x1, x19 \n" // from_thread
+ "sub sp, sp, 24 \n"
+ "stp x19, x19, [sp] \n" // to_thread, from_thread (for thread_context_first_enter)
+ "ldr lr, =thread_context_first_enter \n" // should be same as regs.elr_el1
+ "b enter_thread_context \n");
+ // clang-format on
+}
+
void exit_kernel_thread(void)
{
Thread::current()->exit();
diff --git a/Kernel/Arch/aarch64/RegisterState.h b/Kernel/Arch/aarch64/RegisterState.h
index 803015c603..128c93bcb4 100644
--- a/Kernel/Arch/aarch64/RegisterState.h
+++ b/Kernel/Arch/aarch64/RegisterState.h
@@ -51,6 +51,9 @@ struct RegisterState {
}
};
+#define REGISTER_STATE_SIZE (34 * 8)
+static_assert(AssertSize<RegisterState, REGISTER_STATE_SIZE>());
+
inline void copy_kernel_registers_into_ptrace_registers(PtraceRegisters& ptrace_regs, RegisterState const& kernel_regs)
{
(void)ptrace_regs;
diff --git a/Kernel/Arch/aarch64/TrapFrame.h b/Kernel/Arch/aarch64/TrapFrame.h
index b6172cbf24..beca67a8a8 100644
--- a/Kernel/Arch/aarch64/TrapFrame.h
+++ b/Kernel/Arch/aarch64/TrapFrame.h
@@ -24,6 +24,9 @@ struct TrapFrame {
TrapFrame& operator=(TrapFrame&&) = delete;
};
+#define TRAP_FRAME_SIZE (2 * 8)
+static_assert(AssertSize<TrapFrame, TRAP_FRAME_SIZE>());
+
extern "C" void exit_trap(TrapFrame*) __attribute__((used));
}