arch/x86/intel64: Fix assumption with dummy threads
The intel64 switch implementation doesn't actually use a switch handle per se, just the raw thread struct pointers which get stored into the handle field. This works fine for normally initialized threads, but when switching out of a dummy thread at initialization, nothing has initialized that field and the code was dumping registers into the bottom of memory through the resulting NULL pointer. Fix this by skipping the load of the field value and just using an offset instead to get the struct address, which is actually slightly faster anyway (a SUB immediate instruction vs. the load). Actually for extra credit we could even move the switch_handle field to the top of the thread struct and eliminate the instruction entirely, though if we did that it's probably worth adding some conditional code to make the switch_handle field disappear entirely. Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
This commit is contained in:
parent
beb81885c2
commit
8bc3b6f673
2 changed files with 10 additions and 2 deletions
|
@ -189,12 +189,16 @@ mxcsr: .long X86_MXCSR_SANE
|
|||
* 'struct k_thread', thus:
|
||||
*
|
||||
* RDI = (struct k_thread *) switch_to
|
||||
* RSI = (struct k_thread **) switched_from
|
||||
* RSI = (struct k_thread **) address of output thread switch_handle field
|
||||
*/
|
||||
|
||||
.globl z_x86_switch
|
||||
z_x86_switch:
|
||||
movq (%rsi), %rsi
|
||||
/* RSI contains the switch_handle field to which we are
|
||||
* notionally supposed to store. Offset it to get back to the
|
||||
* thread handle instead.
|
||||
*/
|
||||
subq $___thread_t_switch_handle_OFFSET, %rsi
|
||||
|
||||
andb $~X86_THREAD_FLAG_ALL, _thread_offset_to_flags(%rsi)
|
||||
|
||||
|
|
|
@ -64,6 +64,10 @@ GEN_OFFSET_SYM(_thread_t, base);
|
|||
GEN_OFFSET_SYM(_thread_t, callee_saved);
|
||||
GEN_OFFSET_SYM(_thread_t, arch);
|
||||
|
||||
#ifdef CONFIG_USE_SWITCH
|
||||
GEN_OFFSET_SYM(_thread_t, switch_handle);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_THREAD_STACK_INFO
|
||||
GEN_OFFSET_SYM(_thread_stack_info_t, start);
|
||||
GEN_OFFSET_SYM(_thread_stack_info_t, size);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue