@@ -11,6 +11,8 @@
#include <efi/efidevp.h>
#include <efi/efiapi.h>
+bool __initdata efi_no_cet_ibt;
+
/*
* Here we are in EFI stub. EFI calls are not supported due to lack
* of relevant functionality in compiler and/or linker.
@@ -735,6 +735,12 @@ static void __init efi_init(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTabl
StdOut = SystemTable->ConOut;
StdErr = SystemTable->StdErr ?: StdOut;
+
+ /*
+ * Heuristic. Look under an arbitrary function pointer to see if UEFI was
+ * compiled with CET-IBT support. Experimentally some are not.
+ */
+ efi_no_cet_ibt = memcmp(efi_rs->GetTime, "\xf3\x0f\x1e\xfa", 4) != 0;
}
static void __init efi_console_set_mode(void)
@@ -21,6 +21,7 @@ struct efi_rs_state {
* don't strictly need that.
*/
unsigned long __aligned(32) cr3;
+ unsigned long msr_s_cet;
#endif
};
@@ -61,6 +62,7 @@ UINTN __read_mostly efi_apple_properties_len;
/* Bit field representing available EFI features/properties. */
unsigned int efi_flags;
+bool __read_mostly efi_no_cet_ibt;
struct efi __read_mostly efi = {
.acpi = EFI_INVALID_TABLE_ADDR,
@@ -113,6 +115,17 @@ struct efi_rs_state efi_rs_enter(void)
switch_cr3_cr4(mfn_to_maddr(efi_l4_mfn), read_cr4());
+ /*
+ * If UEFI doesn't appear to be CET-IBT compatible, stash and clobber
+ * ENDBR_EN. Always read the current CET setting, because CET-SS isn't
+ * configured until very late on the BSP.
+ */
+ if ( cpu_has_xen_ibt && efi_no_cet_ibt )
+ {
+ rdmsrl(MSR_S_CET, state.msr_s_cet);
+ wrmsrl(MSR_S_CET, state.msr_s_cet & ~CET_ENDBR_EN);
+ }
+
return state;
}
@@ -122,6 +135,10 @@ void efi_rs_leave(struct efi_rs_state *state)
if ( !state->cr3 )
return;
+
+ if ( state->msr_s_cet )
+ wrmsrl(MSR_S_CET, state->msr_s_cet);
+
switch_cr3_cr4(state->cr3, read_cr4());
if ( is_pv_vcpu(curr) && !is_idle_vcpu(curr) )
{
@@ -30,6 +30,7 @@ union compat_pf_efi_info;
struct xenpf_efi_runtime_call;
struct compat_pf_efi_runtime_call;
+extern bool efi_no_cet_ibt;
bool efi_enabled(unsigned int feature);
void efi_init_memory(void);
At least one TigerLake NUC has UEFI firmware which isn't CET-IBT compatible. Read under a function pointer to see whether an endbr64 instruction is present, and use this as a heuristic. Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com> --- CC: Jan Beulich <JBeulich@suse.com> CC: Roger Pau Monné <roger.pau@citrix.com> CC: Wei Liu <wl@xen.org> This was disappointing to discover. I've pestered some folk and maybe something will improve in due course, but it remains an open question how best to discover that Runtime Services are CET-IBT compatible. --- xen/arch/x86/efi/stub.c | 2 ++ xen/common/efi/boot.c | 6 ++++++ xen/common/efi/runtime.c | 17 +++++++++++++++++ xen/include/xen/efi.h | 1 + 4 files changed, 26 insertions(+)