Skip to content
Snippets Groups Projects
Commit 5384840a authored by Avi Kivity's avatar Avi Kivity
Browse files

x64: avoid stack instructions in context switch code

Due to the "red zone", stack operations may corrupt local variables.
Use ordinary moves and jumps instead.
parent 2c57b0ce
No related branches found
No related tags found
No related merge requests found
......@@ -24,15 +24,18 @@ void thread::switch_to()
barrier();
_cpu->arch.set_exception_stack(&_arch);
asm volatile
("push %%rbp \n\t"
"pushq $1f \n\t"
"mov %%rsp, (%0) \n\t"
"mov %1, %%rsp \n\t"
"ret \n\t"
("mov %%rbp, %c[rbp](%0) \n\t"
"movq $1f, %c[rip](%0) \n\t"
"mov %%rsp, %c[rsp](%0) \n\t"
"mov %c[rsp](%1), %%rsp \n\t"
"mov %c[rbp](%1), %%rbp \n\t"
"jmpq *%c[rip](%1) \n\t"
"1: \n\t"
"pop %%rbp"
:
: "a"(&old->_state.rsp), "c"(this->_state.rsp)
: "a"(&old->_state), "c"(&this->_state),
[rsp]"i"(offsetof(thread_state, rsp)),
[rbp]"i"(offsetof(thread_state, rbp)),
[rip]"i"(offsetof(thread_state, rip))
: "rbx", "rdx", "rsi", "rdi", "r8", "r9",
"r10", "r11", "r12", "r13", "r14", "r15", "memory");
}
......@@ -45,10 +48,14 @@ void thread::switch_to_first()
s_current = this;
_cpu->arch.set_exception_stack(&_arch);
asm volatile
("mov %0, %%rsp \n\t"
"ret"
("mov %c[rsp](%0), %%rsp \n\t"
"mov %c[rbp](%0), %%rbp \n\t"
"jmp *%c[rip](%0)"
:
: "c"(this->_state.rsp)
: "c"(&this->_state),
[rsp]"i"(offsetof(thread_state, rsp)),
[rbp]"i"(offsetof(thread_state, rbp)),
[rip]"i"(offsetof(thread_state, rip))
: "rbx", "rdx", "rsi", "rdi", "r8", "r9",
"r10", "r11", "r12", "r13", "r14", "r15", "memory");
}
......@@ -64,8 +71,8 @@ void thread::init_stack()
stack.deleter = free;
}
void** stacktop = reinterpret_cast<void**>(stack.begin + stack.size);
*--stacktop = this;
*--stacktop = reinterpret_cast<void*>(thread_main);
_state.rbp = this;
_state.rip = reinterpret_cast<void*>(thread_main);
_state.rsp = stacktop;
}
......
......@@ -3,6 +3,8 @@
struct thread_state {
void* rsp;
void* rbp;
void* rip;
};
#endif /* ARCH_THREAD_STATE_HH_ */
......@@ -97,7 +97,7 @@ exception_error_entry interrupt_entry_common, interrupt
thread_main:
.cfi_startproc simple
.cfi_def_cfa %rsp, 0
pop %rdi
mov %rbp, %rdi
call thread_main_c
.cfi_endproc
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment