Commit | Line | Data |
---|---|---|
92e2c5fe MD |
1 | /* SPDX-License-Identifier: (GPL-2.0-only) |
2 | * | |
3 | * wrapper/ibt.h | |
4 | * | |
5 | * Copyright (C) 2024 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> | |
6 | */ | |
7 | ||
8 | #ifndef _LTTNG_WRAPPER_IBT_H | |
9 | #define _LTTNG_WRAPPER_IBT_H | |
10 | ||
11 | struct irq_ibt_state { | |
12 | u64 msr; | |
13 | unsigned long flags; | |
14 | }; | |
15 | ||
16 | /* | |
17 | * Save (disable) and restore interrupts around MSR bit change and indirect | |
18 | * function call to make sure this thread is not migrated to another CPU which | |
19 | * would not have the MSR bit cleared. | |
20 | */ | |
21 | ||
22 | #ifdef CONFIG_X86_KERNEL_IBT | |
23 | # include <asm/cpufeature.h> | |
24 | # include <asm/msr.h> | |
25 | static inline __attribute__((always_inline)) | |
26 | struct irq_ibt_state wrapper_irq_ibt_save(void) | |
27 | { | |
28 | struct irq_ibt_state state = { 0, 0 }; | |
29 | u64 msr; | |
30 | ||
31 | if (!cpu_feature_enabled(X86_FEATURE_IBT)) | |
32 | goto end; | |
33 | local_irq_save(state.flags); | |
34 | rdmsrl(MSR_IA32_S_CET, msr); | |
35 | wrmsrl(MSR_IA32_S_CET, msr & ~CET_ENDBR_EN); | |
36 | state.msr = msr; | |
37 | end: | |
38 | return state; | |
39 | } | |
40 | ||
41 | static inline __attribute__((always_inline)) | |
42 | void wrapper_irq_ibt_restore(struct irq_ibt_state state) | |
43 | { | |
44 | u64 msr; | |
45 | ||
46 | if (!cpu_feature_enabled(X86_FEATURE_IBT)) | |
47 | return; | |
48 | rdmsrl(MSR_IA32_S_CET, msr); | |
49 | msr &= ~CET_ENDBR_EN; | |
50 | msr |= (state.msr & CET_ENDBR_EN); | |
51 | wrmsrl(MSR_IA32_S_CET, msr); | |
52 | local_irq_restore(state.flags); | |
53 | } | |
54 | #else | |
55 | static inline struct irq_ibt_state wrapper_irq_ibt_save(void) { struct irq_ibt_state state = { 0, 0 }; return state; } | |
56 | static inline void wrapper_irq_ibt_restore(struct irq_ibt_state state) { } | |
57 | #endif | |
58 | ||
59 | #endif /* _LTTNG_WRAPPER_IBT_H */ |