pushq %rax
lretq
1:
-#ifdef CONFIG_XEN_SHSTK
+#if defined(CONFIG_XEN_SHSTK) || defined(CONFIG_XEN_IBT)
+ call xen_msr_s_cet_value
+ test %eax, %eax
+ jz .L_cet_done
+
+ /* Set up MSR_S_CET. */
+ mov $MSR_S_CET, %ecx
+ xor %edx, %edx
+ wrmsr
+
+ /* Enable CR4.CET. */
+ mov $XEN_MINIMAL_CR4 | X86_CR4_CET, %ecx
+ mov %rcx, %cr4
+
+ /* WARNING! call/ret now fatal (iff SHSTK) until SETSSBSY loads SSP */
+
+#if defined(CONFIG_XEN_SHSTK)
+ test $CET_SHSTK_EN, %al
+ jz .L_cet_done
+
/*
* Restoring SSP is a little complicated, because we are intercepting
* an in-use shadow stack. Write a temporary token under the stack,
* reset MSR_PL0_SSP to its usual value and pop the temporary token.
*/
mov saved_ssp(%rip), %rdi
- cmpq $1, %rdi
- je .L_shstk_done
-
- /* Set up MSR_S_CET. */
- mov $MSR_S_CET, %ecx
- xor %edx, %edx
- mov $CET_SHSTK_EN | CET_WRSS_EN, %eax
- wrmsr
/* Construct the temporary supervisor token under SSP. */
sub $8, %rdi
mov %edi, %eax
wrmsr
- /* Enable CET. MSR_INTERRUPT_SSP_TABLE is set up later in load_system_tables(). */
- mov $XEN_MINIMAL_CR4 | X86_CR4_CET, %ebx
- mov %rbx, %cr4
-
/* Write the temporary token onto the shadow stack, and activate it. */
wrssq %rdi, (%rdi)
setssbsy
/* Pop the temporary token off the stack. */
mov $2, %eax
incsspd %eax
-.L_shstk_done:
-#endif
+#endif /* CONFIG_XEN_SHSTK */
+.L_cet_done:
+#endif /* CONFIG_XEN_SHSTK || CONFIG_XEN_IBT */
call load_system_tables
test %ebx,%ebx
jz .L_bsp
- /* APs. Set up shadow stacks before entering C. */
-#ifdef CONFIG_XEN_SHSTK
- testl $cpufeat_mask(X86_FEATURE_XEN_SHSTK), \
- CPUINFO_FEATURE_OFFSET(X86_FEATURE_XEN_SHSTK) + boot_cpu_data(%rip)
- je .L_ap_shstk_done
+ /* APs. Set up CET before entering C properly. */
+#if defined(CONFIG_XEN_SHSTK) || defined(CONFIG_XEN_IBT)
+ call xen_msr_s_cet_value
+ test %eax, %eax
+ jz .L_ap_cet_done
/* Set up MSR_S_CET. */
mov $MSR_S_CET, %ecx
xor %edx, %edx
- mov $CET_SHSTK_EN | CET_WRSS_EN, %eax
wrmsr
+ /* Enable CR4.CET. */
+ mov $XEN_MINIMAL_CR4 | X86_CR4_CET, %ecx
+ mov %rcx, %cr4
+
+ /* WARNING! call/ret now fatal (iff SHSTK) until SETSSBSY loads SSP */
+
+#if defined(CONFIG_XEN_SHSTK)
+ test $CET_SHSTK_EN, %al
+ jz .L_ap_cet_done
+
/* Derive MSR_PL0_SSP from %rsp (token written when stack is allocated). */
mov $MSR_PL0_SSP, %ecx
mov %rsp, %rdx
or $(PRIMARY_SHSTK_SLOT + 1) * PAGE_SIZE - 8, %eax
wrmsr
- /* Enable CET. MSR_INTERRUPT_SSP_TABLE is set up later in load_system_tables(). */
- mov $XEN_MINIMAL_CR4 | X86_CR4_CET, %ecx
- mov %rcx, %cr4
setssbsy
-#endif
-.L_ap_shstk_done:
+#endif /* CONFIG_XEN_SHSTK */
+.L_ap_cet_done:
+#endif /* CONFIG_XEN_SHSTK || CONFIG_XEN_IBT */
+
call start_secondary
BUG /* start_secondary() shouldn't return. */
/* Reset CPUID masking and faulting to the host's default. */
ctxt_switch_levelling(NULL);
- /* Disable shadow stacks. */
- if ( cpu_has_xen_shstk )
+ /* Disable CET. */
+ if ( cpu_has_xen_shstk || cpu_has_xen_ibt )
{
wrmsrl(MSR_S_CET, 0);
write_cr4(read_cr4() & ~X86_CR4_CET);
#define MSR_S_CET 0x000006a2
#define CET_SHSTK_EN (_AC(1, ULL) << 0)
#define CET_WRSS_EN (_AC(1, ULL) << 1)
+#define CET_ENDBR_EN (_AC(1, ULL) << 2)
#define MSR_PL0_SSP 0x000006a4
#define MSR_PL1_SSP 0x000006a5
startup_cpu_idle_loop();
}
+#if defined(CONFIG_XEN_SHSTK) || defined(CONFIG_XEN_IBT)
+/*
+ * Used by AP and S3 asm code to calcualte the appropriate MSR_S_CET setting.
+ * Do not use on the BSP before reinit_bsp_stack(), or it may turn SHSTK on
+ * too early.
+ */
+unsigned int xen_msr_s_cet_value(void)
+{
+ return ((cpu_has_xen_shstk ? CET_SHSTK_EN | CET_WRSS_EN : 0) |
+ (cpu_has_xen_ibt ? CET_ENDBR_EN : 0));
+}
+#else
+unsigned int xen_msr_s_cet_value(void); /* To avoid ifdefary */
+#endif
+
/* Reinitalise all state referring to the old virtual address of the stack. */
static void __init noreturn reinit_bsp_stack(void)
{
{
wrmsrl(MSR_PL0_SSP,
(unsigned long)stack + (PRIMARY_SHSTK_SLOT + 1) * PAGE_SIZE - 8);
- wrmsrl(MSR_S_CET, CET_SHSTK_EN | CET_WRSS_EN);
+ wrmsrl(MSR_S_CET, xen_msr_s_cet_value());
asm volatile ("setssbsy" ::: "memory");
}