From 8bc3b6f6732c754442de73bc4f490d3f212e00ce Mon Sep 17 00:00:00 2001 From: Andy Ross Date: Fri, 18 Oct 2019 14:12:00 -0700 Subject: [PATCH] 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 --- arch/x86/core/intel64/locore.S | 8 ++++++-- kernel/include/kernel_offsets.h | 4 ++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/arch/x86/core/intel64/locore.S b/arch/x86/core/intel64/locore.S index aed28fd2861..67846b16cd9 100644 --- a/arch/x86/core/intel64/locore.S +++ b/arch/x86/core/intel64/locore.S @@ -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) diff --git a/kernel/include/kernel_offsets.h b/kernel/include/kernel_offsets.h index edca4b1d592..8e233b1e9d0 100644 --- a/kernel/include/kernel_offsets.h +++ b/kernel/include/kernel_offsets.h @@ -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);