cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ibt.h (2205B)


      1/* SPDX-License-Identifier: GPL-2.0 */
      2#ifndef _ASM_X86_IBT_H
      3#define _ASM_X86_IBT_H
      4
      5#include <linux/types.h>
      6
      7/*
      8 * The rules for enabling IBT are:
      9 *
     10 *  - CC_HAS_IBT:         the toolchain supports it
     11 *  - X86_KERNEL_IBT:     it is selected in Kconfig
     12 *  - !__DISABLE_EXPORTS: this is regular kernel code
     13 *
     14 * Esp. that latter one is a bit non-obvious, but some code like compressed,
     15 * purgatory, realmode etc.. is built with custom CFLAGS that do not include
     16 * -fcf-protection=branch and things will go *bang*.
     17 *
     18 * When all the above are satisfied, HAS_KERNEL_IBT will be 1, otherwise 0.
     19 */
     20#if defined(CONFIG_X86_KERNEL_IBT) && !defined(__DISABLE_EXPORTS)
     21
     22#define HAS_KERNEL_IBT	1
     23
     24#ifndef __ASSEMBLY__
     25
     26#ifdef CONFIG_X86_64
     27#define ASM_ENDBR	"endbr64\n\t"
     28#else
     29#define ASM_ENDBR	"endbr32\n\t"
     30#endif
     31
     32#define __noendbr	__attribute__((nocf_check))
     33
     34static inline __attribute_const__ u32 gen_endbr(void)
     35{
     36	u32 endbr;
     37
     38	/*
     39	 * Generate ENDBR64 in a way that is sure to not result in
     40	 * an ENDBR64 instruction as immediate.
     41	 */
     42	asm ( "mov $~0xfa1e0ff3, %[endbr]\n\t"
     43	      "not %[endbr]\n\t"
     44	       : [endbr] "=&r" (endbr) );
     45
     46	return endbr;
     47}
     48
     49static inline __attribute_const__ u32 gen_endbr_poison(void)
     50{
     51	/*
     52	 * 4 byte NOP that isn't NOP4 (in fact it is OSP NOP3), such that it
     53	 * will be unique to (former) ENDBR sites.
     54	 */
     55	return 0x001f0f66; /* osp nopl (%rax) */
     56}
     57
     58static inline bool is_endbr(u32 val)
     59{
     60	if (val == gen_endbr_poison())
     61		return true;
     62
     63	val &= ~0x01000000U; /* ENDBR32 -> ENDBR64 */
     64	return val == gen_endbr();
     65}
     66
     67extern __noendbr u64 ibt_save(void);
     68extern __noendbr void ibt_restore(u64 save);
     69
     70#else /* __ASSEMBLY__ */
     71
     72#ifdef CONFIG_X86_64
     73#define ENDBR	endbr64
     74#else
     75#define ENDBR	endbr32
     76#endif
     77
     78#endif /* __ASSEMBLY__ */
     79
     80#else /* !IBT */
     81
     82#define HAS_KERNEL_IBT	0
     83
     84#ifndef __ASSEMBLY__
     85
     86#define ASM_ENDBR
     87
     88#define __noendbr
     89
     90static inline bool is_endbr(u32 val) { return false; }
     91
     92static inline u64 ibt_save(void) { return 0; }
     93static inline void ibt_restore(u64 save) { }
     94
     95#else /* __ASSEMBLY__ */
     96
     97#define ENDBR
     98
     99#endif /* __ASSEMBLY__ */
    100
    101#endif /* CONFIG_X86_KERNEL_IBT */
    102
    103#define ENDBR_INSN_SIZE		(4*HAS_KERNEL_IBT)
    104
    105#endif /* _ASM_X86_IBT_H */