![Thomas Gleixner](/assets/img/avatar_default.png)
Some code pathes, especially the low level entry code, must be protected against instrumentation for various reasons: - Low level entry code can be a fragile beast, especially on x86. - With NO_HZ_FULL RCU state needs to be established before using it. Having a dedicated section for such code allows to validate with tooling that no unsafe functions are invoked. Add the .noinstr.text section and the noinstr attribute to mark functions. noinstr implies notrace. Kprobes will gain a section check later. Provide also a set of markers: instrumentation_begin()/end() These are used to mark code inside a noinstr function which calls into regular instrumentable text section as safe. The instrumentation markers are only active when CONFIG_DEBUG_ENTRY is enabled as the end marker emits a NOP to prevent the compiler from merging the annotation points. This means the objtool verification requires a kernel compiled with this option. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Alexandre Chartre <alexandre.chartre@oracle.com> Acked-by: Peter Zijlstra <peterz@infradead.org> Link: https://lkml.kernel.org/r/20200505134100.075416272@linutronix.de
242 lines
7.1 KiB
C
242 lines
7.1 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#ifndef __LINUX_COMPILER_TYPES_H
|
|
#define __LINUX_COMPILER_TYPES_H
|
|
|
|
#ifndef __ASSEMBLY__
|
|
|
|
#ifdef __CHECKER__
|
|
# define __user __attribute__((noderef, address_space(1)))
|
|
# define __kernel __attribute__((address_space(0)))
|
|
# define __safe __attribute__((safe))
|
|
# define __force __attribute__((force))
|
|
# define __nocast __attribute__((nocast))
|
|
# define __iomem __attribute__((noderef, address_space(2)))
|
|
# define __must_hold(x) __attribute__((context(x,1,1)))
|
|
# define __acquires(x) __attribute__((context(x,0,1)))
|
|
# define __releases(x) __attribute__((context(x,1,0)))
|
|
# define __acquire(x) __context__(x,1)
|
|
# define __release(x) __context__(x,-1)
|
|
# define __cond_lock(x,c) ((c) ? ({ __acquire(x); 1; }) : 0)
|
|
# define __percpu __attribute__((noderef, address_space(3)))
|
|
# define __rcu __attribute__((noderef, address_space(4)))
|
|
# define __private __attribute__((noderef))
|
|
extern void __chk_user_ptr(const volatile void __user *);
|
|
extern void __chk_io_ptr(const volatile void __iomem *);
|
|
# define ACCESS_PRIVATE(p, member) (*((typeof((p)->member) __force *) &(p)->member))
|
|
#else /* __CHECKER__ */
|
|
# ifdef STRUCTLEAK_PLUGIN
|
|
# define __user __attribute__((user))
|
|
# else
|
|
# define __user
|
|
# endif
|
|
# define __kernel
|
|
# define __safe
|
|
# define __force
|
|
# define __nocast
|
|
# define __iomem
|
|
# define __chk_user_ptr(x) (void)0
|
|
# define __chk_io_ptr(x) (void)0
|
|
# define __builtin_warning(x, y...) (1)
|
|
# define __must_hold(x)
|
|
# define __acquires(x)
|
|
# define __releases(x)
|
|
# define __acquire(x) (void)0
|
|
# define __release(x) (void)0
|
|
# define __cond_lock(x,c) (c)
|
|
# define __percpu
|
|
# define __rcu
|
|
# define __private
|
|
# define ACCESS_PRIVATE(p, member) ((p)->member)
|
|
#endif /* __CHECKER__ */
|
|
|
|
/* Indirect macros required for expanded argument pasting, eg. __LINE__. */
|
|
#define ___PASTE(a,b) a##b
|
|
#define __PASTE(a,b) ___PASTE(a,b)
|
|
|
|
#ifdef __KERNEL__
|
|
|
|
/* Attributes */
|
|
#include <linux/compiler_attributes.h>
|
|
|
|
/* Compiler specific macros. */
|
|
#ifdef __clang__
|
|
#include <linux/compiler-clang.h>
|
|
#elif defined(__INTEL_COMPILER)
|
|
#include <linux/compiler-intel.h>
|
|
#elif defined(__GNUC__)
|
|
/* The above compilers also define __GNUC__, so order is important here. */
|
|
#include <linux/compiler-gcc.h>
|
|
#else
|
|
#error "Unknown compiler"
|
|
#endif
|
|
|
|
/*
|
|
* Some architectures need to provide custom definitions of macros provided
|
|
* by linux/compiler-*.h, and can do so using asm/compiler.h. We include that
|
|
* conditionally rather than using an asm-generic wrapper in order to avoid
|
|
* build failures if any C compilation, which will include this file via an
|
|
* -include argument in c_flags, occurs prior to the asm-generic wrappers being
|
|
* generated.
|
|
*/
|
|
#ifdef CONFIG_HAVE_ARCH_COMPILER_H
|
|
#include <asm/compiler.h>
|
|
#endif
|
|
|
|
struct ftrace_branch_data {
|
|
const char *func;
|
|
const char *file;
|
|
unsigned line;
|
|
union {
|
|
struct {
|
|
unsigned long correct;
|
|
unsigned long incorrect;
|
|
};
|
|
struct {
|
|
unsigned long miss;
|
|
unsigned long hit;
|
|
};
|
|
unsigned long miss_hit[2];
|
|
};
|
|
};
|
|
|
|
struct ftrace_likely_data {
|
|
struct ftrace_branch_data data;
|
|
unsigned long constant;
|
|
};
|
|
|
|
#ifdef CONFIG_ENABLE_MUST_CHECK
|
|
#define __must_check __attribute__((__warn_unused_result__))
|
|
#else
|
|
#define __must_check
|
|
#endif
|
|
|
|
#if defined(CC_USING_HOTPATCH)
|
|
#define notrace __attribute__((hotpatch(0, 0)))
|
|
#elif defined(CC_USING_PATCHABLE_FUNCTION_ENTRY)
|
|
#define notrace __attribute__((patchable_function_entry(0, 0)))
|
|
#else
|
|
#define notrace __attribute__((__no_instrument_function__))
|
|
#endif
|
|
|
|
/* Section for code which can't be instrumented at all */
|
|
#define noinstr \
|
|
noinline notrace __attribute((__section__(".noinstr.text")))
|
|
|
|
/*
|
|
* it doesn't make sense on ARM (currently the only user of __naked)
|
|
* to trace naked functions because then mcount is called without
|
|
* stack and frame pointer being set up and there is no chance to
|
|
* restore the lr register to the value before mcount was called.
|
|
*/
|
|
#define __naked __attribute__((__naked__)) notrace
|
|
|
|
#define __compiler_offsetof(a, b) __builtin_offsetof(a, b)
|
|
|
|
/*
|
|
* Prefer gnu_inline, so that extern inline functions do not emit an
|
|
* externally visible function. This makes extern inline behave as per gnu89
|
|
* semantics rather than c99. This prevents multiple symbol definition errors
|
|
* of extern inline functions at link time.
|
|
* A lot of inline functions can cause havoc with function tracing.
|
|
*/
|
|
#define inline inline __gnu_inline __inline_maybe_unused notrace
|
|
|
|
/*
|
|
* gcc provides both __inline__ and __inline as alternate spellings of
|
|
* the inline keyword, though the latter is undocumented. New kernel
|
|
* code should only use the inline spelling, but some existing code
|
|
* uses __inline__. Since we #define inline above, to ensure
|
|
* __inline__ has the same semantics, we need this #define.
|
|
*
|
|
* However, the spelling __inline is strictly reserved for referring
|
|
* to the bare keyword.
|
|
*/
|
|
#define __inline__ inline
|
|
|
|
/*
|
|
* GCC does not warn about unused static inline functions for -Wunused-function.
|
|
* Suppress the warning in clang as well by using __maybe_unused, but enable it
|
|
* for W=1 build. This will allow clang to find unused functions. Remove the
|
|
* __inline_maybe_unused entirely after fixing most of -Wunused-function warnings.
|
|
*/
|
|
#ifdef KBUILD_EXTRA_WARN1
|
|
#define __inline_maybe_unused
|
|
#else
|
|
#define __inline_maybe_unused __maybe_unused
|
|
#endif
|
|
|
|
/*
|
|
* Rather then using noinline to prevent stack consumption, use
|
|
* noinline_for_stack instead. For documentation reasons.
|
|
*/
|
|
#define noinline_for_stack noinline
|
|
|
|
#endif /* __KERNEL__ */
|
|
|
|
#endif /* __ASSEMBLY__ */
|
|
|
|
/*
|
|
* The below symbols may be defined for one or more, but not ALL, of the above
|
|
* compilers. We don't consider that to be an error, so set them to nothing.
|
|
* For example, some of them are for compiler specific plugins.
|
|
*/
|
|
#ifndef __latent_entropy
|
|
# define __latent_entropy
|
|
#endif
|
|
|
|
#ifndef __randomize_layout
|
|
# define __randomize_layout __designated_init
|
|
#endif
|
|
|
|
#ifndef __no_randomize_layout
|
|
# define __no_randomize_layout
|
|
#endif
|
|
|
|
#ifndef randomized_struct_fields_start
|
|
# define randomized_struct_fields_start
|
|
# define randomized_struct_fields_end
|
|
#endif
|
|
|
|
#ifndef asm_volatile_goto
|
|
#define asm_volatile_goto(x...) asm goto(x)
|
|
#endif
|
|
|
|
#ifdef CONFIG_CC_HAS_ASM_INLINE
|
|
#define asm_inline asm __inline
|
|
#else
|
|
#define asm_inline asm
|
|
#endif
|
|
|
|
#ifndef __no_fgcse
|
|
# define __no_fgcse
|
|
#endif
|
|
|
|
/* Are two types/vars the same type (ignoring qualifiers)? */
|
|
#define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
|
|
|
|
/* Is this type a native word size -- useful for atomic operations */
|
|
#define __native_word(t) \
|
|
(sizeof(t) == sizeof(char) || sizeof(t) == sizeof(short) || \
|
|
sizeof(t) == sizeof(int) || sizeof(t) == sizeof(long))
|
|
|
|
/* Helpers for emitting diagnostics in pragmas. */
|
|
#ifndef __diag
|
|
#define __diag(string)
|
|
#endif
|
|
|
|
#ifndef __diag_GCC
|
|
#define __diag_GCC(version, severity, string)
|
|
#endif
|
|
|
|
#define __diag_push() __diag(push)
|
|
#define __diag_pop() __diag(pop)
|
|
|
|
#define __diag_ignore(compiler, version, option, comment) \
|
|
__diag_ ## compiler(version, ignore, option)
|
|
#define __diag_warn(compiler, version, option, comment) \
|
|
__diag_ ## compiler(version, warn, option)
|
|
#define __diag_error(compiler, version, option, comment) \
|
|
__diag_ ## compiler(version, error, option)
|
|
|
|
#endif /* __LINUX_COMPILER_TYPES_H */
|