FRED and IDT differ by a Supervisor Token on the base of the shstk. This means that switch_stack_and_jump() needs to discard one extra word when FRED is active.
Signed-off-by: Andrew Cooper <andrew.coop...@citrix.com> --- CC: Jan Beulich <jbeul...@suse.com> CC: Roger Pau Monné <roger....@citrix.com> RFC. I don't like this, but it does work. This emits opt_fred logic outside of CONFIG_XEN_SHSTK. But frankly, the construct is already too unweildly, and all options I can think of make it moreso. --- xen/arch/x86/include/asm/current.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/xen/arch/x86/include/asm/current.h b/xen/arch/x86/include/asm/current.h index 962eb76a82b3..24d7d906a8c6 100644 --- a/xen/arch/x86/include/asm/current.h +++ b/xen/arch/x86/include/asm/current.h @@ -11,6 +11,7 @@ #include <xen/page-size.h> #include <asm/cpu-user-regs.h> +#include <asm/traps.h> /* * Xen's cpu stacks are 8 pages (8-page aligned), arranged as: @@ -154,7 +155,6 @@ unsigned long get_stack_dump_bottom (unsigned long sp); "rdsspd %[ssp];" \ "cmp $1, %[ssp];" \ "je .L_shstk_done.%=;" /* CET not active? Skip. */ \ - "mov $%c[skstk_base], %[val];" \ "and $%c[stack_mask], %[ssp];" \ "sub %[ssp], %[val];" \ "shr $3, %[val];" \ @@ -177,6 +177,8 @@ unsigned long get_stack_dump_bottom (unsigned long sp); #define switch_stack_and_jump(fn, instr, constr) \ ({ \ + unsigned int token_offset = \ + (PRIMARY_SHSTK_SLOT + 1) * PAGE_SIZE - (opt_fred ? 0 : 8); \ unsigned int tmp; \ BUILD_BUG_ON(!ssaj_has_attr_noreturn(fn)); \ __asm__ __volatile__ ( \ @@ -184,12 +186,11 @@ unsigned long get_stack_dump_bottom (unsigned long sp); "mov %[stk], %%rsp;" \ CHECK_FOR_LIVEPATCH_WORK \ instr "[fun]" \ - : [val] "=&r" (tmp), \ + : [val] "=r" (tmp), \ [ssp] "=&r" (tmp) \ : [stk] "r" (guest_cpu_user_regs()), \ [fun] constr (fn), \ - [skstk_base] "i" \ - ((PRIMARY_SHSTK_SLOT + 1) * PAGE_SIZE - 8), \ + "[val]" (token_offset), \ [stack_mask] "i" (STACK_SIZE - 1), \ _ASM_BUGFRAME_INFO(BUGFRAME_bug, __LINE__, \ __FILE__, NULL) \ -- 2.39.5