diff --git a/headers/private/kernel/arch/x86/64/cpu.h b/headers/private/kernel/arch/x86/64/cpu.h new file mode 100644 index 0000000000..273115914c --- /dev/null +++ b/headers/private/kernel/arch/x86/64/cpu.h @@ -0,0 +1,32 @@ +/* + * Copyright 2014, Paweł Dziepak, pdziepak@quarnos.org. + * Distributed under the terms of the MIT License. + */ +#ifndef _KERNEL_ARCH_X86_64_CPU_H +#define _KERNEL_ARCH_X86_64_CPU_H + + +#include + + +static inline void +x86_context_switch(arch_thread* oldState, arch_thread* newState) +{ + asm volatile( + "pushq %%rbp;" + "movq $1f, %c[rip](%0);" + "movq %%rsp, %c[rsp](%0);" + "movq %c[rsp](%1), %%rsp;" + "jmp *%c[rip](%1);" + "1:" + "popq %%rbp;" + : + : "a" (oldState), "d" (newState), + [rsp] "i" (offsetof(arch_thread, current_stack)), + [rip] "i" (offsetof(arch_thread, instruction_pointer)) + : "rbx", "rcx", "rdi", "rsi", "r8", "r9", "r10", "r11", "r12", "r13", + "r14", "r15", "memory"); +} + + +#endif // _KERNEL_ARCH_X86_64_CPU_H diff --git a/headers/private/kernel/arch/x86/arch_cpu.h b/headers/private/kernel/arch/x86/arch_cpu.h index f745c50c6d..b59717f477 100644 --- a/headers/private/kernel/arch/x86/arch_cpu.h +++ b/headers/private/kernel/arch/x86/arch_cpu.h @@ -13,12 +13,13 @@ #ifndef _ASSEMBLER #include + +#include + #include #ifdef __x86_64__ -# include -#else -# include +# include #endif #endif // !_ASSEMBLER @@ -452,8 +453,6 @@ void __x86_setup_system_time(uint32 conversionFactor, uint32 conversionFactorNsecs, bool conversionFactorNsecsShift); #endif -void x86_context_switch(struct arch_thread* oldState, - struct arch_thread* newState); void x86_userspace_thread_exit(void); void x86_end_userspace_thread_exit(void); void x86_swap_pgdir(addr_t newPageDir); @@ -482,6 +481,8 @@ void x86_hardware_interrupt(iframe* frame); void x86_page_fault_exception(iframe* iframe); #ifndef __x86_64__ +void x86_context_switch(struct arch_thread* oldState, + struct arch_thread* newState); void x86_fnsave(void* fpuState); void x86_frstor(const void* fpuState); diff --git a/headers/private/kernel/arch/x86/arch_thread_types.h b/headers/private/kernel/arch/x86/arch_thread_types.h index 85dfc6bb08..f02ae41ad6 100644 --- a/headers/private/kernel/arch/x86/arch_thread_types.h +++ b/headers/private/kernel/arch/x86/arch_thread_types.h @@ -9,7 +9,13 @@ #define _KERNEL_ARCH_x86_THREAD_TYPES_H -#include +#include + +#ifdef __x86_64__ +# include +#else +# include +#endif namespace BKernel { @@ -40,7 +46,8 @@ struct arch_thread { uint64* syscall_rsp; uint64* user_rsp; - uint64* current_stack; + uintptr_t* current_stack; + uintptr_t instruction_pointer; #else struct farcall current_stack; struct farcall interrupt_stack; @@ -72,7 +79,7 @@ struct arch_fork_arg { inline addr_t arch_thread::GetFramePointer() const { - return current_stack[1]; + return current_stack[0]; } diff --git a/src/system/kernel/arch/x86/64/arch.S b/src/system/kernel/arch/x86/64/arch.S index 3f9b6d1e48..3553081c19 100644 --- a/src/system/kernel/arch/x86/64/arch.S +++ b/src/system/kernel/arch/x86/64/arch.S @@ -79,38 +79,18 @@ FUNCTION_END(x86_write_msr) /* void x86_64_thread_entry(); */ FUNCTION(x86_64_thread_entry): - movq %r15, %rdi - jmp *%r14 + xorq %rbp, %rbp + + movq %rsp, %rax + addq $16, %rsp + andq $0xfffffffffffffff0, %rsp + subq $8, %rsp + + movq 8(%rax), %rdi + jmp *(%rax) FUNCTION_END(x86_64_thread_entry) -/* void x86_context_switch(struct arch_thread* oldState, - struct arch_thread* newState); */ -FUNCTION(x86_context_switch): - // Just need to save callee-save registers: RBP, RBX, R12-15. - push %r15 - push %r14 - push %r13 - push %r12 - push %rbp - push %rbx - - // Swap the stack pointers. - movq %rsp, ARCH_THREAD_current_stack(%rdi) - movq ARCH_THREAD_current_stack(%rsi), %rsp - - // Restore callee-save registers. - pop %rbx - pop %rbp - pop %r12 - pop %r13 - pop %r14 - pop %r15 - - ret -FUNCTION_END(x86_context_switch) - - /* void x86_swap_pgdir(uint64 newPageDir); */ FUNCTION(x86_swap_pgdir): movq %rdi, %cr3 diff --git a/src/system/kernel/arch/x86/64/thread.cpp b/src/system/kernel/arch/x86/64/thread.cpp index 5ee839a711..71da974abf 100644 --- a/src/system/kernel/arch/x86/64/thread.cpp +++ b/src/system/kernel/arch/x86/64/thread.cpp @@ -165,7 +165,7 @@ void arch_thread_init_kthread_stack(Thread* thread, void* _stack, void* _stackTop, void (*function)(void*), const void* data) { - addr_t* stackTop = (addr_t*)_stackTop; + uintptr_t* stackTop = static_cast(_stackTop); TRACE("arch_thread_init_kthread_stack: stack top %p, function %p, data: " "%p\n", _stackTop, function, data); @@ -173,23 +173,11 @@ arch_thread_init_kthread_stack(Thread* thread, void* _stack, void* _stackTop, // Save the stack top for system call entry. thread->arch_info.syscall_rsp = (uint64*)thread->kernel_stack_top; - // x86_64 uses registers for argument passing, first argument in RDI, - // however we don't save RDI on every context switch (there is no need - // for us to: it is not callee-save, and only contains the first argument - // to x86_context_switch). However, this presents a problem since we - // cannot store the argument for the entry function here. Therefore, we - // save the function address in R14 and the argument in R15 (which are - // restored), and then set up the stack to initially call a wrapper - // function which passes the argument correctly. + thread->arch_info.instruction_pointer + = reinterpret_cast(x86_64_thread_entry); - *--stackTop = 0; // Dummy return address. - *--stackTop = (addr_t)x86_64_thread_entry; // Wrapper function. - *--stackTop = (addr_t)data; // R15: argument. - *--stackTop = (addr_t)function; // R14: entry function. - *--stackTop = 0; // R13. - *--stackTop = 0; // R12. - *--stackTop = 0; // RBP. - *--stackTop = 0; // RBX. + *--stackTop = uintptr_t(data); + *--stackTop = uintptr_t(function); // Save the stack position. thread->arch_info.current_stack = stackTop;