Fix: Disable IBT around indirect function calls
[lttng-modules.git] / include / wrapper / ibt.h
diff --git a/include/wrapper/ibt.h b/include/wrapper/ibt.h
new file mode 100644 (file)
index 0000000..e089a8f
--- /dev/null
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: (GPL-2.0-only)
+ *
+ * wrapper/ibt.h
+ *
+ * Copyright (C) 2024 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ */
+
+#ifndef _LTTNG_WRAPPER_IBT_H
+#define _LTTNG_WRAPPER_IBT_H
+
+struct irq_ibt_state {
+       u64 msr;
+       unsigned long flags;
+};
+
+/*
+ * Save (disable) and restore interrupts around MSR bit change and indirect
+ * function call to make sure this thread is not migrated to another CPU which
+ * would not have the MSR bit cleared.
+ */
+
+#ifdef CONFIG_X86_KERNEL_IBT
+# include <asm/cpufeature.h>
+# include <asm/msr.h>
+static inline __attribute__((always_inline))
+struct irq_ibt_state wrapper_irq_ibt_save(void)
+{
+       struct irq_ibt_state state = { 0, 0 };
+       u64 msr;
+
+       if (!cpu_feature_enabled(X86_FEATURE_IBT))
+               goto end;
+       local_irq_save(state.flags);
+       rdmsrl(MSR_IA32_S_CET, msr);
+       wrmsrl(MSR_IA32_S_CET, msr & ~CET_ENDBR_EN);
+       state.msr = msr;
+end:
+       return state;
+}
+
+static inline __attribute__((always_inline))
+void wrapper_irq_ibt_restore(struct irq_ibt_state state)
+{
+       u64 msr;
+
+       if (!cpu_feature_enabled(X86_FEATURE_IBT))
+               return;
+       rdmsrl(MSR_IA32_S_CET, msr);
+       msr &= ~CET_ENDBR_EN;
+       msr |= (state.msr & CET_ENDBR_EN);
+       wrmsrl(MSR_IA32_S_CET, msr);
+       local_irq_restore(state.flags);
+}
+#else
+static inline struct irq_ibt_state wrapper_irq_ibt_save(void) { struct irq_ibt_state state = { 0, 0 }; return state; }
+static inline void wrapper_irq_ibt_restore(struct irq_ibt_state state) { }
+#endif
+
+#endif /* _LTTNG_WRAPPER_IBT_H */
This page took 0.023032 seconds and 4 git commands to generate.