[arch][x86-64] clean up the context switch code to only save required registers

-Move the guts into a separate asm fileto clean up the fake return hack.
This commit is contained in:
Travis Geiselbrecht
2015-11-06 16:24:29 -08:00
parent 64fe297cb5
commit e189cd3223
3 changed files with 40 additions and 57 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2009 Corey Tabaka
* Copyright (c) 2015 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
@@ -22,3 +22,27 @@
*/
#include <asm.h>
/* void x86_64_context_switch(uint64_t *oldsp, uint64_t newsp) */
FUNCTION(x86_64_context_switch)
/* save the old context and restore the new */
pushf
pushq %rbx
pushq %rbp
pushq %r12
pushq %r13
pushq %r14
pushq %r15
movq %rsp,(%rdi)
movq %rsi,%rsp
popq %r15
popq %r14
popq %r13
popq %r12
popq %rbp
popq %rbx
popf
retq

View File

@@ -39,6 +39,16 @@ __BEGIN_CDECLS
void arch_mmu_init(void);
struct x86_context_switch_frame {
uint64_t r15, r14, r13, r12;
uint64_t rbp;
uint64_t rbx;
uint64_t rflags;
uint64_t rip;
};
void x86_64_context_switch(vaddr_t *oldsp, vaddr_t newsp);
struct x86_iframe {
uint64_t pivot; // stack switch pivot
uint64_t rdi, rsi, rbp, rbx, rdx, rcx, rax; // pushed by common handler

View File

@@ -32,13 +32,6 @@
#include <arch/x86/descriptor.h>
#include <arch/fpu.h>
struct context_switch_frame {
uint64_t rdi, rsi, rdx, rcx, rax, rbx, rbp;
uint64_t r8, r9, r10, r11, r12, r13, r14, r15;
uint64_t rflags;
uint64_t rip;
};
/* we're uniprocessor at this point for x86-64, so store a global pointer to the current thread */
struct thread *_current_thread;
@@ -61,13 +54,13 @@ void arch_thread_initialize(thread_t *t)
/* create a default stack frame on the stack */
vaddr_t stack_top = (vaddr_t)t->stack + t->stack_size;
/* make sure the top of the stack is 8 byte aligned
/* make sure the top of the stack is 8 byte aligned
for EABI compliance */
stack_top = ROUNDDOWN(stack_top, 8);
struct context_switch_frame *frame =
(struct context_switch_frame *)(stack_top);
struct x86_context_switch_frame *frame =
(struct x86_context_switch_frame *)(stack_top);
frame--;
/* fill it in */
@@ -98,51 +91,7 @@ void arch_context_switch(thread_t *oldthread, thread_t *newthread)
fpu_context_switch(oldthread, newthread);
#endif
/* save the old context and restore the new */
__asm__ __volatile__ (
"pushq $1f \n\t"
"pushf \n\t"
"pushq %%rdi \n\t"
"pushq %%rsi \n\t"
"pushq %%rdx \n\t"
"pushq %%rcx \n\t"
"pushq %%rax \n\t"
"pushq %%rbx \n\t"
"pushq %%rbp \n\t"
"pushq %%r8 \n\t"
"pushq %%r9 \n\t"
"pushq %%r10 \n\t"
"pushq %%r11 \n\t"
"pushq %%r12 \n\t"
"pushq %%r13 \n\t"
"pushq %%r14 \n\t"
"pushq %%r15 \n\t"
"movq %%rsp,%[old] \n\t"
"movq %[new],%%rsp \n\t"
"popq %%r15 \n\t"
"popq %%r14 \n\t"
"popq %%r13 \n\t"
"popq %%r12 \n\t"
"popq %%r11 \n\t"
"popq %%r10 \n\t"
"popq %%r9 \n\t"
"popq %%r8 \n\t"
"popq %%rbp \n\t"
"popq %%rbx \n\t"
"popq %%rax \n\t"
"popq %%rcx \n\t"
"popq %%rdx \n\t"
"popq %%rsi \n\t"
"popq %%rdi \n\t"
"popf \n\t"
"ret \n\t"
"1: \n\t"
: [old] "=m" (oldthread->arch.rsp)
: [new] "g" (newthread->arch.rsp)
);
x86_64_context_switch(&oldthread->arch.rsp, newthread->arch.rsp);
}
/* vim: noexpandtab: */
/* vim: set noexpandtab: */