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:
Andy Ross 2019-10-18 14:12:00 -07:00 committed by Andrew Boie
commit 8bc3b6f673
2 changed files with 10 additions and 2 deletions

View file

@ -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)

View file

@ -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);