1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 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 */
|