Paolo Abeni | 283c16a | 2018-12-14 11:51:57 +0100 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
| 2 | #ifndef _LINUX_INDIRECT_CALL_WRAPPER_H |
| 3 | #define _LINUX_INDIRECT_CALL_WRAPPER_H |
| 4 | |
| 5 | #ifdef CONFIG_RETPOLINE |
| 6 | |
| 7 | /* |
| 8 | * INDIRECT_CALL_$NR - wrapper for indirect calls with $NR known builtin |
| 9 | * @f: function pointer |
| 10 | * @f$NR: builtin functions names, up to $NR of them |
| 11 | * @__VA_ARGS__: arguments for @f |
| 12 | * |
| 13 | * Avoid retpoline overhead for known builtin, checking @f vs each of them and |
| 14 | * eventually invoking directly the builtin function. The functions are check |
| 15 | * in the given order. Fallback to the indirect call. |
| 16 | */ |
| 17 | #define INDIRECT_CALL_1(f, f1, ...) \ |
| 18 | ({ \ |
| 19 | likely(f == f1) ? f1(__VA_ARGS__) : f(__VA_ARGS__); \ |
| 20 | }) |
| 21 | #define INDIRECT_CALL_2(f, f2, f1, ...) \ |
| 22 | ({ \ |
| 23 | likely(f == f2) ? f2(__VA_ARGS__) : \ |
| 24 | INDIRECT_CALL_1(f, f1, __VA_ARGS__); \ |
| 25 | }) |
Brian Vazquez | e678e9dd | 2020-06-23 09:42:31 -0700 | [diff] [blame] | 26 | #define INDIRECT_CALL_3(f, f3, f2, f1, ...) \ |
| 27 | ({ \ |
| 28 | likely(f == f3) ? f3(__VA_ARGS__) : \ |
| 29 | INDIRECT_CALL_2(f, f2, f1, __VA_ARGS__); \ |
| 30 | }) |
| 31 | #define INDIRECT_CALL_4(f, f4, f3, f2, f1, ...) \ |
| 32 | ({ \ |
| 33 | likely(f == f4) ? f4(__VA_ARGS__) : \ |
| 34 | INDIRECT_CALL_3(f, f3, f2, f1, __VA_ARGS__); \ |
| 35 | }) |
Paolo Abeni | 283c16a | 2018-12-14 11:51:57 +0100 | [diff] [blame] | 36 | |
| 37 | #define INDIRECT_CALLABLE_DECLARE(f) f |
| 38 | #define INDIRECT_CALLABLE_SCOPE |
| 39 | |
| 40 | #else |
Paolo Abeni | c03b035 | 2018-12-17 12:39:02 +0100 | [diff] [blame] | 41 | #define INDIRECT_CALL_1(f, f1, ...) f(__VA_ARGS__) |
| 42 | #define INDIRECT_CALL_2(f, f2, f1, ...) f(__VA_ARGS__) |
Brian Vazquez | e678e9dd | 2020-06-23 09:42:31 -0700 | [diff] [blame] | 43 | #define INDIRECT_CALL_3(f, f3, f2, f1, ...) f(__VA_ARGS__) |
| 44 | #define INDIRECT_CALL_4(f, f4, f3, f2, f1, ...) f(__VA_ARGS__) |
Paolo Abeni | 283c16a | 2018-12-14 11:51:57 +0100 | [diff] [blame] | 45 | #define INDIRECT_CALLABLE_DECLARE(f) |
| 46 | #define INDIRECT_CALLABLE_SCOPE static |
| 47 | #endif |
| 48 | |
| 49 | /* |
| 50 | * We can use INDIRECT_CALL_$NR for ipv6 related functions only if ipv6 is |
| 51 | * builtin, this macro simplify dealing with indirect calls with only ipv4/ipv6 |
| 52 | * alternatives |
| 53 | */ |
| 54 | #if IS_BUILTIN(CONFIG_IPV6) |
| 55 | #define INDIRECT_CALL_INET(f, f2, f1, ...) \ |
| 56 | INDIRECT_CALL_2(f, f2, f1, __VA_ARGS__) |
| 57 | #elif IS_ENABLED(CONFIG_INET) |
| 58 | #define INDIRECT_CALL_INET(f, f2, f1, ...) INDIRECT_CALL_1(f, f1, __VA_ARGS__) |
| 59 | #else |
| 60 | #define INDIRECT_CALL_INET(f, f2, f1, ...) f(__VA_ARGS__) |
| 61 | #endif |
| 62 | |
| 63 | #endif |