1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 20:27:45 +00:00

Kernel: Implement Processor::assume_context for AArch64

With this implemented sys$execve should be fully working on AArch64.
This commit is contained in:
Idan Horowitz 2023-04-02 03:41:41 +03:00 committed by Andrew Kaster
parent 0dc5c49938
commit 402c9e5e23
3 changed files with 51 additions and 3 deletions

View file

@ -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();

View file

@ -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;

View file

@ -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));
}