diff options
author | Idan Horowitz <idan.horowitz@gmail.com> | 2023-04-02 03:41:41 +0300 |
---|---|---|
committer | Andrew Kaster <andrewdkaster@gmail.com> | 2023-04-03 02:59:37 -0600 |
commit | 402c9e5e23e12500807a9b29b2d8b6465a496446 (patch) | |
tree | f6cd0410dc70277df17044c317c509f0e04ba811 /Kernel/Arch | |
parent | 0dc5c499387440497d93c9902a2fdc66d4ba5a02 (diff) | |
download | serenity-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.cpp | 48 | ||||
-rw-r--r-- | Kernel/Arch/aarch64/RegisterState.h | 3 | ||||
-rw-r--r-- | Kernel/Arch/aarch64/TrapFrame.h | 3 |
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)); } |