![]() |
|
|||
0001 /* SPDX-License-Identifier: GPL-2.0 */ 0002 #ifndef __LINUX_INSTRUMENTATION_H 0003 #define __LINUX_INSTRUMENTATION_H 0004 0005 #ifdef CONFIG_NOINSTR_VALIDATION 0006 0007 #include <linux/stringify.h> 0008 0009 /* Begin/end of an instrumentation safe region */ 0010 #define __instrumentation_begin(c) ({ \ 0011 asm volatile(__stringify(c) ": nop\n\t" \ 0012 ".pushsection .discard.instr_begin\n\t" \ 0013 ".long " __stringify(c) "b - .\n\t" \ 0014 ".popsection\n\t" : : "i" (c)); \ 0015 }) 0016 #define instrumentation_begin() __instrumentation_begin(__COUNTER__) 0017 0018 /* 0019 * Because instrumentation_{begin,end}() can nest, objtool validation considers 0020 * _begin() a +1 and _end() a -1 and computes a sum over the instructions. 0021 * When the value is greater than 0, we consider instrumentation allowed. 0022 * 0023 * There is a problem with code like: 0024 * 0025 * noinstr void foo() 0026 * { 0027 * instrumentation_begin(); 0028 * ... 0029 * if (cond) { 0030 * instrumentation_begin(); 0031 * ... 0032 * instrumentation_end(); 0033 * } 0034 * bar(); 0035 * instrumentation_end(); 0036 * } 0037 * 0038 * If instrumentation_end() would be an empty label, like all the other 0039 * annotations, the inner _end(), which is at the end of a conditional block, 0040 * would land on the instruction after the block. 0041 * 0042 * If we then consider the sum of the !cond path, we'll see that the call to 0043 * bar() is with a 0-value, even though, we meant it to happen with a positive 0044 * value. 0045 * 0046 * To avoid this, have _end() be a NOP instruction, this ensures it will be 0047 * part of the condition block and does not escape. 0048 */ 0049 #define __instrumentation_end(c) ({ \ 0050 asm volatile(__stringify(c) ": nop\n\t" \ 0051 ".pushsection .discard.instr_end\n\t" \ 0052 ".long " __stringify(c) "b - .\n\t" \ 0053 ".popsection\n\t" : : "i" (c)); \ 0054 }) 0055 #define instrumentation_end() __instrumentation_end(__COUNTER__) 0056 #else /* !CONFIG_NOINSTR_VALIDATION */ 0057 # define instrumentation_begin() do { } while(0) 0058 # define instrumentation_end() do { } while(0) 0059 #endif /* CONFIG_NOINSTR_VALIDATION */ 0060 0061 #endif /* __LINUX_INSTRUMENTATION_H */
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.1.0 LXR engine. The LXR team |
![]() ![]() |