1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 16:37:35 +00:00

Kernel: Replace raw asm functions with naked ones

This commit is contained in:
Hendiadyoin1 2021-07-05 15:34:07 +02:00 committed by Gunnar Beutner
parent c830de4983
commit 9b7e48c6bd
7 changed files with 203 additions and 202 deletions

View file

@ -54,6 +54,16 @@
#endif #endif
#define NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address)) #define NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address))
#ifdef NO_RETURN
# undef NO_RETURN
#endif
#define NO_RETURN [[noreturn]]
#ifdef NAKED
# undef NAKED
#endif
#define NAKED __attribute__((naked))
// GCC doesn't have __has_feature but clang does // GCC doesn't have __has_feature but clang does
#ifndef __has_feature #ifndef __has_feature
# define __has_feature(...) 0 # define __has_feature(...) 0

View file

@ -32,6 +32,11 @@ struct ProcessorMessageEntry;
struct TrapFrame; struct TrapFrame;
class ProcessorInfo; class ProcessorInfo;
// FIXME: Find a better place for these
extern "C" void thread_context_first_enter(void);
extern "C" void exit_kernel_thread(void);
extern "C" void do_assume_context(Thread* thread, u32 flags);
struct [[gnu::aligned(16)]] FPUState struct [[gnu::aligned(16)]] FPUState
{ {
u8 buffer[512]; u8 buffer[512];

View file

@ -42,122 +42,122 @@ static EntropySource s_entropy_source_interrupts { EntropySource::Static::Interr
// clang-format off // clang-format off
#if ARCH(I386) #if ARCH(I386)
#define EH_ENTRY(ec, title) \ #define EH_ENTRY(ec, title) \
extern "C" void title##_asm_entry(); \ extern "C" void title##_asm_entry(); \
extern "C" void title##_handler(TrapFrame*) __attribute__((used)); \ extern "C" void title##_handler(TrapFrame*) __attribute__((used)); \
asm( \ NAKED void title##_asm_entry(){ \
".globl " #title "_asm_entry\n" \ asm( \
"" #title "_asm_entry: \n" \ " pusha\n" \
" pusha\n" \ " pushl %ds\n" \
" pushl %ds\n" \ " pushl %es\n" \
" pushl %es\n" \ " pushl %fs\n" \
" pushl %fs\n" \ " pushl %gs\n" \
" pushl %gs\n" \ " pushl %ss\n" \
" pushl %ss\n" \ " mov $" __STRINGIFY(GDT_SELECTOR_DATA0) ", %ax\n" \
" mov $" __STRINGIFY(GDT_SELECTOR_DATA0) ", %ax\n" \ " mov %ax, %ds\n" \
" mov %ax, %ds\n" \ " mov %ax, %es\n" \
" mov %ax, %es\n" \ " mov $" __STRINGIFY(GDT_SELECTOR_PROC) ", %ax\n" \
" mov $" __STRINGIFY(GDT_SELECTOR_PROC) ", %ax\n" \ " mov %ax, %gs\n" \
" mov %ax, %gs\n" \ " pushl %esp \n" /* set TrapFrame::regs */ \
" pushl %esp \n" /* set TrapFrame::regs */ \ " subl $" __STRINGIFY(TRAP_FRAME_SIZE - 4) ", %esp \n" \
" subl $" __STRINGIFY(TRAP_FRAME_SIZE - 4) ", %esp \n" \ " pushl %esp \n" \
" pushl %esp \n" \ " cld\n" \
" cld\n" \ " call enter_trap_no_irq \n" \
" call enter_trap_no_irq \n" \ " call " #title "_handler\n" \
" call " #title "_handler\n" \ " jmp common_trap_exit \n"); \
" jmp common_trap_exit \n"); }
#define EH_ENTRY_NO_CODE(ec, title) \ #define EH_ENTRY_NO_CODE(ec, title) \
extern "C" void title##_asm_entry(); \ extern "C" void title##_asm_entry(); \
extern "C" void title##_handler(TrapFrame*) __attribute__((used)); \ extern "C" void title##_handler(TrapFrame*) __attribute__((used)); \
asm( \ NAKED void title##_asm_entry(){ \
".globl " #title "_asm_entry\n" \ asm( \
"" #title "_asm_entry: \n" \ " pushl $0x0\n" \
" pushl $0x0\n" \ " pusha\n" \
" pusha\n" \ " pushl %ds\n" \
" pushl %ds\n" \ " pushl %es\n" \
" pushl %es\n" \ " pushl %fs\n" \
" pushl %fs\n" \ " pushl %gs\n" \
" pushl %gs\n" \ " pushl %ss\n" \
" pushl %ss\n" \ " mov $" __STRINGIFY(GDT_SELECTOR_DATA0) ", %ax\n" \
" mov $" __STRINGIFY(GDT_SELECTOR_DATA0) ", %ax\n" \ " mov %ax, %ds\n" \
" mov %ax, %ds\n" \ " mov %ax, %es\n" \
" mov %ax, %es\n" \ " mov $" __STRINGIFY(GDT_SELECTOR_PROC) ", %ax\n" \
" mov $" __STRINGIFY(GDT_SELECTOR_PROC) ", %ax\n" \ " mov %ax, %gs\n" \
" mov %ax, %gs\n" \ " pushl %esp \n" /* set TrapFrame::regs */ \
" pushl %esp \n" /* set TrapFrame::regs */ \ " subl $" __STRINGIFY(TRAP_FRAME_SIZE - 4) ", %esp \n" \
" subl $" __STRINGIFY(TRAP_FRAME_SIZE - 4) ", %esp \n" \ " pushl %esp \n" \
" pushl %esp \n" \ " cld\n" \
" cld\n" \ " call enter_trap_no_irq \n" \
" call enter_trap_no_irq \n" \ " call " #title "_handler\n" \
" call " #title "_handler\n" \ " jmp common_trap_exit \n"); \
" jmp common_trap_exit \n"); }
#elif ARCH(X86_64) #elif ARCH(X86_64)
#define EH_ENTRY(ec, title) \ #define EH_ENTRY(ec, title) \
extern "C" void title##_asm_entry(); \ extern "C" void title##_asm_entry(); \
extern "C" void title##_handler(TrapFrame*) __attribute__((used)); \ extern "C" void title##_handler(TrapFrame*) __attribute__((used)); \
asm( \ NAKED void title##_asm_entry(){ \
".globl " #title "_asm_entry\n" \ asm( \
"" #title "_asm_entry: \n" \ " pushq %r15\n" \
" pushq %r15\n" \ " pushq %r14\n" \
" pushq %r14\n" \ " pushq %r13\n" \
" pushq %r13\n" \ " pushq %r12\n" \
" pushq %r12\n" \ " pushq %r11\n" \
" pushq %r11\n" \ " pushq %r10\n" \
" pushq %r10\n" \ " pushq %r9\n" \
" pushq %r9\n" \ " pushq %r8\n" \
" pushq %r8\n" \ " pushq %rax\n" \
" pushq %rax\n" \ " pushq %rcx\n" \
" pushq %rcx\n" \ " pushq %rdx\n" \
" pushq %rdx\n" \ " pushq %rbx\n" \
" pushq %rbx\n" \ " pushq %rsp\n" \
" pushq %rsp\n" \ " pushq %rbp\n" \
" pushq %rbp\n" \ " pushq %rsi\n" \
" pushq %rsi\n" \ " pushq %rdi\n" \
" pushq %rdi\n" \ " pushq %rsp \n" /* set TrapFrame::regs */ \
" pushq %rsp \n" /* set TrapFrame::regs */ \ " subq $" __STRINGIFY(TRAP_FRAME_SIZE - 8) ", %rsp \n" \
" subq $" __STRINGIFY(TRAP_FRAME_SIZE - 8) ", %rsp \n" \ " subq $0x8, %rsp\n" /* align stack */ \
" subq $0x8, %rsp\n" /* align stack */ \ " lea 0x8(%rsp), %rdi \n" \
" lea 0x8(%rsp), %rdi \n" \ " cld\n" \
" cld\n" \ " call enter_trap_no_irq \n" \
" call enter_trap_no_irq \n" \ " lea 0x8(%rsp), %rdi \n" \
" lea 0x8(%rsp), %rdi \n" \ " call " #title "_handler\n" \
" call " #title "_handler\n" \ " addq $0x8, %rsp\n" /* undo alignment */ \
" addq $0x8, %rsp\n" /* undo alignment */ \ " jmp common_trap_exit \n"); \
" jmp common_trap_exit \n"); }
#define EH_ENTRY_NO_CODE(ec, title) \ #define EH_ENTRY_NO_CODE(ec, title) \
extern "C" void title##_handler(TrapFrame*) __attribute__((used)); \ extern "C" void title##_handler(TrapFrame*) __attribute__((used)); \
extern "C" void title##_asm_entry(); \ extern "C" void title##_asm_entry(); \
asm( \ NAKED void title##_asm_entry(){ \
".globl " #title "_asm_entry\n" \ asm( \
"" #title "_asm_entry: \n" \ " pushq $0x0\n" \
" pushq $0x0\n" \ " pushq %r15\n" \
" pushq %r15\n" \ " pushq %r14\n" \
" pushq %r14\n" \ " pushq %r13\n" \
" pushq %r13\n" \ " pushq %r12\n" \
" pushq %r12\n" \ " pushq %r11\n" \
" pushq %r11\n" \ " pushq %r10\n" \
" pushq %r10\n" \ " pushq %r9\n" \
" pushq %r9\n" \ " pushq %r8\n" \
" pushq %r8\n" \ " pushq %rax\n" \
" pushq %rax\n" \ " pushq %rcx\n" \
" pushq %rcx\n" \ " pushq %rdx\n" \
" pushq %rdx\n" \ " pushq %rbx\n" \
" pushq %rbx\n" \ " pushq %rsp\n" \
" pushq %rsp\n" \ " pushq %rbp\n" \
" pushq %rbp\n" \ " pushq %rsi\n" \
" pushq %rsi\n" \ " pushq %rdi\n" \
" pushq %rdi\n" \ " pushq %rsp \n" /* set TrapFrame::regs */ \
" pushq %rsp \n" /* set TrapFrame::regs */ \ " subq $" __STRINGIFY(TRAP_FRAME_SIZE - 8) ", %rsp \n" \
" subq $" __STRINGIFY(TRAP_FRAME_SIZE - 8) ", %rsp \n" \ " movq %rsp, %rdi \n" \
" movq %rsp, %rdi \n" \ " cld\n" \
" cld\n" \ " call enter_trap_no_irq \n" \
" call enter_trap_no_irq \n" \ " movq %rsp, %rdi \n" \
" movq %rsp, %rdi \n" \ " call " #title "_handler\n" \
" call " #title "_handler\n" \ " jmp common_trap_exit \n"); \
" jmp common_trap_exit \n"); }
#endif #endif
// clang-format on // clang-format on

View file

@ -37,10 +37,6 @@ static volatile bool s_smp_enabled;
static Atomic<ProcessorMessage*> s_message_pool; static Atomic<ProcessorMessage*> s_message_pool;
Atomic<u32> Processor::s_idle_cpu_mask { 0 }; Atomic<u32> Processor::s_idle_cpu_mask { 0 };
extern "C" void thread_context_first_enter(void);
extern "C" void exit_kernel_thread(void);
extern "C" void do_assume_context(Thread* thread, u32 flags);
// The compiler can't see the calls to these functions inside assembly. // The compiler can't see the calls to these functions inside assembly.
// Declare them, to avoid dead code warnings. // Declare them, to avoid dead code warnings.
extern "C" void context_first_init(Thread* from_thread, Thread* to_thread, TrapFrame* trap) __attribute__((used)); extern "C" void context_first_init(Thread* from_thread, Thread* to_thread, TrapFrame* trap) __attribute__((used));

View file

@ -16,47 +16,47 @@
namespace Kernel { namespace Kernel {
#define ENTER_THREAD_CONTEXT_ARGS_SIZE (2 * 4) // to_thread, from_thread #define ENTER_THREAD_CONTEXT_ARGS_SIZE (2 * 4) // to_thread, from_thread
extern "C" void thread_context_first_enter(void);
extern "C" void exit_kernel_thread(void);
// clang-format off NAKED void thread_context_first_enter(void)
asm( {
// enter_thread_context returns to here first time a thread is executing // clang-format off
".globl thread_context_first_enter \n" // enter_thread_context returns to here first time a thread is executing
"thread_context_first_enter: \n" asm(
// switch_context will have pushed from_thread and to_thread to our new // switch_context will have pushed from_thread and to_thread to our new
// stack prior to thread_context_first_enter() being called, and the // stack prior to thread_context_first_enter() being called, and the
// pointer to TrapFrame was the top of the stack before that // pointer to TrapFrame was the top of the stack before that
" movl 8(%esp), %ebx \n" // save pointer to TrapFrame " movl 8(%esp), %ebx \n" // save pointer to TrapFrame
" cld \n" " cld \n"
" call context_first_init \n" " call context_first_init \n"
" addl $" __STRINGIFY(ENTER_THREAD_CONTEXT_ARGS_SIZE) ", %esp \n" " addl $" __STRINGIFY(ENTER_THREAD_CONTEXT_ARGS_SIZE) ", %esp \n"
" movl %ebx, 0(%esp) \n" // push pointer to TrapFrame " movl %ebx, 0(%esp) \n" // push pointer to TrapFrame
" jmp common_trap_exit \n" " jmp common_trap_exit \n");
); // clang-format on
// clang-format on }
// clang-format off NAKED void do_assume_context(Thread*, u32)
asm( {
".global do_assume_context \n" // clang-format off
"do_assume_context: \n" // FIXME: I hope (Thread* thread, u32 flags) aren't compiled away
" movl 4(%esp), %ebx \n" asm(
" movl 8(%esp), %esi \n" " movl 4(%esp), %ebx \n"
// We're going to call Processor::init_context, so just make sure " movl 8(%esp), %esi \n"
// we have enough stack space so we don't stomp over it // We're going to call Processor::init_context, so just make sure
" subl $(" __STRINGIFY(4 + REGISTER_STATE_SIZE + TRAP_FRAME_SIZE + 4) "), %esp \n" // we have enough stack space so we don't stomp over it
" pushl %esi \n" " subl $(" __STRINGIFY(4 + REGISTER_STATE_SIZE + TRAP_FRAME_SIZE + 4) "), %esp \n"
" pushl %ebx \n" " pushl %esi \n"
" cld \n" " pushl %ebx \n"
" call do_init_context \n" " cld \n"
" addl $8, %esp \n" " call do_init_context \n"
" movl %eax, %esp \n" // move stack pointer to what Processor::init_context set up for us " addl $8, %esp \n"
" pushl %ebx \n" // push to_thread " movl %eax, %esp \n" // move stack pointer to what Processor::init_context set up for us
" pushl %ebx \n" // push from_thread " pushl %ebx \n" // push to_thread
" pushl $thread_context_first_enter \n" // should be same as regs.eip " pushl %ebx \n" // push from_thread
" jmp enter_thread_context \n" " pushl $thread_context_first_enter \n" // should be same as regs.eip
); " jmp enter_thread_context \n"
// clang-format on );
// clang-format on
}
String Processor::platform_string() const String Processor::platform_string() const
{ {
@ -273,5 +273,4 @@ UNMAP_AFTER_INIT void Processor::initialize_context_switching(Thread& initial_th
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
} }
} }

View file

@ -15,47 +15,43 @@
namespace Kernel { namespace Kernel {
extern "C" void thread_context_first_enter(void); NAKED void thread_context_first_enter(void)
extern "C" void exit_kernel_thread(void); {
// enter_thread_context returns to here first time a thread is executing
asm(
// switch_context will have pushed from_thread and to_thread to our news
// stack prior to thread_context_first_enter() being called, and the
// pointer to TrapFrame was the top of the stack before that
" popq %rdi \n" // from_thread (argument 0)
" popq %rsi \n" // to_thread (argument 1)
" popq %rdx \n" // pointer to TrapFrame (argument 2)
" cld \n"
" call context_first_init \n"
" jmp common_trap_exit \n");
};
// clang-format off NAKED void do_assume_context(Thread*, u32)
asm( {
// enter_thread_context returns to here first time a thread is executing // clang-format off
".globl thread_context_first_enter \n" // FIXME: I hope (Thread* thread, u32 flags) aren't compiled away
"thread_context_first_enter: \n" asm(
// switch_context will have pushed from_thread and to_thread to our new " movq %rdi, %r12 \n" // save thread ptr
// stack prior to thread_context_first_enter() being called, and the " movq %rsi, %r13 \n" // save flags
// pointer to TrapFrame was the top of the stack before that // We're going to call Processor::init_context, so just make sure
" popq %rdi \n" // from_thread (argument 0) // we have enough stack space so we don't stomp over it
" popq %rsi \n" // to_thread (argument 1) " subq $(" __STRINGIFY(16 + REGISTER_STATE_SIZE + TRAP_FRAME_SIZE + 8) "), %rsp \n"
" popq %rdx \n" // pointer to TrapFrame (argument 2) " cld \n"
" cld \n" " call do_init_context \n"
" call context_first_init \n" " movq %rax, %rsp \n" // move stack pointer to what Processor::init_context set up for us
" jmp common_trap_exit \n" " movq %r12, %rdi \n" // to_thread
); " movq %r12, %rsi \n" // from_thread
// clang-format on " pushq %r12 \n" // to_thread (for thread_context_first_enter)
" pushq %r12 \n" // from_thread (for thread_context_first_enter)
// clang-format off " movabs $thread_context_first_enter, %r12 \n" // should be same as regs.rip
asm( " pushq %r12 \n"
".global do_assume_context \n" " jmp enter_thread_context \n");
"do_assume_context: \n" // clang-format on
" movq %rdi, %r12 \n" // save thread ptr }
" movq %rsi, %r13 \n" // save flags
// We're going to call Processor::init_context, so just make sure
// we have enough stack space so we don't stomp over it
" subq $(" __STRINGIFY(16 + REGISTER_STATE_SIZE + TRAP_FRAME_SIZE + 8) "), %rsp \n"
" cld \n"
" call do_init_context \n"
" movq %rax, %rsp \n" // move stack pointer to what Processor::init_context set up for us
" movq %r12, %rdi \n" // to_thread
" movq %r12, %rsi \n" // from_thread
" pushq %r12 \n" // to_thread (for thread_context_first_enter)
" pushq %r12 \n" // from_thread (for thread_context_first_enter)
" movabs $thread_context_first_enter, %r12 \n" // should be same as regs.rip
" pushq %r12 \n"
" jmp enter_thread_context \n"
);
// clang-format on
String Processor::platform_string() const String Processor::platform_string() const
{ {

View file

@ -19,14 +19,11 @@ namespace Kernel {
extern "C" void syscall_handler(TrapFrame*) __attribute__((used)); extern "C" void syscall_handler(TrapFrame*) __attribute__((used));
extern "C" void syscall_asm_entry(); extern "C" void syscall_asm_entry();
static void syscall_asm_entry_dummy() __attribute__((used)); NEVER_INLINE NAKED void syscall_asm_entry()
NEVER_INLINE void syscall_asm_entry_dummy()
{ {
// clang-format off // clang-format off
#if ARCH(I386) #if ARCH(I386)
asm( asm(
".globl syscall_asm_entry\n"
"syscall_asm_entry:\n"
" pushl $0x0\n" " pushl $0x0\n"
" pusha\n" " pusha\n"
" pushl %ds\n" " pushl %ds\n"
@ -53,8 +50,6 @@ NEVER_INLINE void syscall_asm_entry_dummy()
" jmp common_trap_exit \n"); " jmp common_trap_exit \n");
#elif ARCH(X86_64) #elif ARCH(X86_64)
asm( asm(
".globl syscall_asm_entry\n"
"syscall_asm_entry:\n"
" pushq $0x0\n" " pushq $0x0\n"
" pushq %r15\n" " pushq %r15\n"
" pushq %r14\n" " pushq %r14\n"