1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 3 * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved. 4 * OpenHarmony Common Kernel Vendor Hook Support 5 * Based on include/trace/hooks/lite_vendor_hooks.h 6 * 7 */ 8 9 #ifndef LITE_VENDOR_HOOK_H 10 #define LITE_VENDOR_HOOK_H 11 12 #include <asm/bug.h> 13 #include <linux/slab.h> 14 #include <linux/spinlock.h> 15 #include <linux/rcupdate.h> 16 #include <linux/tracepoint.h> 17 #include <linux/module.h> 18 19 struct __lvh_func { 20 void *func; 21 void *data; 22 bool has_data; 23 }; 24 25 struct lite_vendor_hook { 26 struct mutex mutex; 27 struct __lvh_func *funcs; 28 }; 29 #endif // LITE_VENDOR_HOOK_H 30 31 #ifdef CREATE_LITE_VENDOR_HOOK 32 33 #define DEFINE_HCK_LITE_HOOK(name, proto, args) \ 34 struct lite_vendor_hook __lvh_##name __used \ 35 __section("__vendor_hooks") = { \ 36 .mutex = __MUTEX_INITIALIZER(__lvh_##name.mutex), \ 37 .funcs = NULL }; \ 38 EXPORT_SYMBOL(__lvh_##name); \ 39 void lvh_probe_##name(proto) { return; } \ 40 void lvh_probe_data_##name(void *lvh_data, proto) { return; } 41 42 #undef DECLARE_HCK_LITE_HOOK 43 #define DECLARE_HCK_LITE_HOOK(name, proto, args) \ 44 DEFINE_HCK_LITE_HOOK(name, PARAMS(proto), PARAMS(args)) 45 46 #else // #ifndef CREATE_LITE_VENDOR_HOOK 47 48 #define REGISTER_HCK_LITE_HOOK(name, probe) \ 49 extern typeof(lvh_probe_##name) (probe); \ 50 do { \ 51 if (register_lvh_##name(probe)) \ 52 WARN_ONCE(1, "LVH register failed!\n"); \ 53 } while (0) 54 55 #define REGISTER_HCK_LITE_DATA_HOOK(name, probe, data) \ 56 extern typeof(lvh_probe_data_##name) (probe); \ 57 do { \ 58 if (register_lvh_data_##name(probe, data)) \ 59 WARN_ONCE(1, "LVH register failed!\n"); \ 60 } while (0) 61 62 #define CALL_HCK_LITE_HOOK(name, args...) \ 63 call_lvh_##name(args) 64 65 #define __DECLARE_HCK_LITE_HOOK(name, proto, args) \ 66 extern struct lite_vendor_hook __lvh_##name; \ 67 extern void lvh_probe_##name(proto); \ 68 extern void lvh_probe_data_##name(void *lvh_data, proto); \ 69 static inline void \ 70 call_lvh_##name(proto) \ 71 { \ 72 struct __lvh_func *funcs = (&__lvh_##name)->funcs; \ 73 if (funcs && funcs->func) { \ 74 if (funcs->has_data) \ 75 ((void(*)(void *, proto))funcs->func)(funcs->data, args); \ 76 else \ 77 ((void(*)(proto))funcs->func)(args); \ 78 } \ 79 } \ 80 static inline int \ 81 __register_lvh_##name(void *probe, void *data, bool has_data) \ 82 { \ 83 int err = 0; \ 84 struct __lvh_func *funcs; \ 85 struct module *mod; \ 86 mutex_lock(&__lvh_##name.mutex); \ 87 funcs = (&__lvh_##name)->funcs; \ 88 if (funcs) { \ 89 if (funcs->func != probe || funcs->data != data) \ 90 err = -EBUSY; \ 91 goto out; \ 92 } \ 93 \ 94 funcs = (struct __lvh_func*)kmalloc(sizeof(struct __lvh_func), GFP_KERNEL); \ 95 if (!funcs) { \ 96 err = -ENOMEM; \ 97 goto out; \ 98 } \ 99 \ 100 funcs->func = probe; \ 101 funcs->data = data; \ 102 funcs->has_data = has_data; \ 103 mod = __module_address((uintptr_t)probe); \ 104 if (mod) \ 105 (void)try_module_get(mod); \ 106 (&__lvh_##name)->funcs = funcs; \ 107 out: \ 108 mutex_unlock(&__lvh_##name.mutex); \ 109 return err; \ 110 } \ 111 static inline int \ 112 register_lvh_##name(void (*probe)(proto)) \ 113 { \ 114 return __register_lvh_##name((void *)probe, NULL, false); \ 115 } \ 116 static inline int \ 117 register_lvh_data_##name(void (*probe)(void *lvh_data, proto), void *data) \ 118 { \ 119 return __register_lvh_##name((void *)probe, data, true); \ 120 } 121 122 #undef DECLARE_HCK_LITE_HOOK 123 #define DECLARE_HCK_LITE_HOOK(name, proto, args) \ 124 __DECLARE_HCK_LITE_HOOK(name, PARAMS(proto), PARAMS(args)) 125 126 #endif // CREATE_LITE_VENDOR_HOOK 127