[MODERATED] [PATCH v6 11/43] MDSv6
Andi Kleen <[email protected]>
| Newsgroups | org.kernel.lore.historical-speck |
|---|---|
| Message-ID | <070a815f4c3a38e70f39f95b782b90d93be295f3.1551019522.git.ak@linux.intel.com> |
Add basic infrastructure for code to request CPU buffer clearing on the next kernel exit. We have two functions lazy_clear_cpu to request clearing, and lazy_clear_cpu_interrupt to request clearing if running in an interrupt. Non architecture specific code can include linux/clearcpu.h and use lazy_clear_cpu / lazy_clear_interrupt. On x86 we provide low level implementations that sets a per cpu flag to request cpu clearing on the next kernel exit. Suggested-by: Linus Torvalds <[email protected]> Signed-off-by: Andi Kleen <[email protected]> --- arch/Kconfig | 3 +++ arch/x86/Kconfig | 1 + arch/x86/include/asm/clearcpu.h | 12 +++++++++-- arch/x86/kernel/cpu/bugs.c | 3 +++ include/linux/clearcpu.h | 36 +++++++++++++++++++++++++++++++++ 5 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 include/linux/clearcpu.h diff --git a/arch/Kconfig b/arch/Kconfig index 4cfb6de48f79..e6b7bf9174aa 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -808,6 +808,9 @@ config VMAP_STACK the stack to map directly to the KASAN shadow map using a formula that is incorrect if the stack is in vmalloc space. +config ARCH_HAS_CLEAR_CPU + def_bool n + config ARCH_OPTIONAL_KERNEL_RWX def_bool n diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 68261430fe6e..1b837b61d07b 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -84,6 +84,7 @@ config X86 select ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH select ARCH_WANTS_DYNAMIC_TASK_STRUCT select ARCH_WANTS_THP_SWAP if X86_64 + select ARCH_HAS_CLEAR_CPU select BUILDTIME_EXTABLE_SORT select CLKEVT_I8253 select CLOCKSOURCE_VALIDATE_LAST_CYCLE diff --git a/arch/x86/include/asm/clearcpu.h b/arch/x86/include/asm/clearcpu.h index 88ab27694aa6..15d25c2436da 100644 --- a/arch/x86/include/asm/clearcpu.h +++ b/arch/x86/include/asm/clearcpu.h @@ -5,7 +5,8 @@ #include <linux/jump_label.h> #include <linux/sched/smt.h> #include <asm/alternative.h> -#include <linux/thread_info.h> + +DECLARE_PER_CPU(bool, clear_cpu_flag); /* * Clear CPU buffers to avoid side channels. @@ -34,8 +35,15 @@ static inline void clear_cpu(void) static inline void clear_cpu_idle(void) { - if (sched_smt_active()) + if (sched_smt_active()) { + __this_cpu_write(clear_cpu_flag, false); clear_cpu(); + } +} + +static inline void lazy_clear_cpu(void) +{ + __this_cpu_write(clear_cpu_flag, true); } #endif diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c index 26b890f18239..067309190a6a 100644 --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -1061,6 +1061,9 @@ early_param("l1tf", l1tf_cmdline); #undef pr_fmt +DEFINE_PER_CPU(bool, clear_cpu_flag); +EXPORT_PER_CPU_SYMBOL(clear_cpu_flag); + static void mds_select_mitigation(void) { if (!boot_cpu_has(X86_BUG_MDS)) diff --git a/include/linux/clearcpu.h b/include/linux/clearcpu.h new file mode 100644 index 000000000000..63a6952b46fa --- /dev/null +++ b/include/linux/clearcpu.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LINUX_CLEARCPU_H +#define _LINUX_CLEARCPU_H 1 + +#include <linux/preempt.h> + +#ifdef CONFIG_ARCH_HAS_CLEAR_CPU +#include <asm/clearcpu.h> +#else +static inline void lazy_clear_cpu(void) +{ +} +#endif + +/* + * Use this function when potentially touching (reading or writing) + * user data in an interrupt. In this case schedule to clear the + * CPU buffers on kernel exit to avoid any potential side channels. + * + * If not in an interrupt we assume the touched data belongs to the + * current process and doesn't need to be cleared. + * + * This version is for code who might be in an interrupt. + * If you know for sure you're in interrupt context call + * lazy_clear_cpu directly. + * + * lazy_clear_cpu is reasonably cheap (just sets a bit) and + * can be used in fast paths. + */ +static inline void lazy_clear_cpu_interrupt(void) +{ + if (in_interrupt()) + lazy_clear_cpu(); +} + +#endif -- 2.17.2