1/*
2 * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved.
3 *
4 * UniProton is licensed under Mulan PSL v2.
5 * You can use this software according to the terms and conditions of the Mulan PSL v2.
6 * You may obtain a copy of Mulan PSL v2 at:
7 *          http://license.coscl.org.cn/MulanPSL2
8 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
9 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
10 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
11 * See the Mulan PSL v2 for more details.
12 * Create: 2009-12-22
13 * Description: HOOK模块的内部头文件
14 */
15#ifndef PRT_HOOK_EXTERNAL_H
16#define PRT_HOOK_EXTERNAL_H
17
18#include "prt_hook.h"
19#include "prt_sys.h"
20
21/* 限制:参数类型不能为U64大于uintptr_t */
22typedef void (*OsFunPara0)(void);
23typedef void (*OsFunPara1)(uintptr_t);
24typedef void (*OsFunPara2)(uintptr_t, uintptr_t);
25typedef void (*OsFunPara3)(uintptr_t, uintptr_t, uintptr_t);
26typedef void (*OsFunPara4)(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
27typedef void (*OsFunPara5)(uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t);
28
29/*
30 * 内核钩子管理原则
31 * 1)服务于内核模块的钩子才可纳入钩子模块统一管理,例如补丁、shell模块的钩子就不适合。
32 * 内核模块指mem,kernel,ipc,服务于内核的arch。
33 * 2)没有返回值,没有输出参数的钩子才可纳入钩子模块统一管理。
34 */
35#define OS_MHOOK_BOUNDARY ((U32)1)
36
37#define OS_MHOOK_NODE_DEAD ((OsVoidFunc)2)
38
39// 除了OS_HOOK_EMPTY和OS_MHOOK_BOUNDARY外,都是有效钩子
40#define OS_MHOOK_IS_VALID(hook) ((uintptr_t)(hook) > OS_MHOOK_BOUNDARY)
41
42#define OS_MHOOK_NOT_BOUNDARY(hook) ((uintptr_t)(hook) != OS_MHOOK_BOUNDARY)
43
44OS_SEC_ALW_INLINE INLINE bool OsMhookBoundaryCheck(OsVoidFunc hook)
45{
46    return ((uintptr_t)hook <= OS_MHOOK_BOUNDARY);
47}
48
49OS_SEC_ALW_INLINE INLINE bool OsMhookValidCheck(OsVoidFunc hook)
50{
51    return (hook != OS_MHOOK_NODE_DEAD);
52}
53
54#define OS_MHOOK_ACTIVATE_PROC(hook, funcType, pfn, list)                        \
55    do {                                                                         \
56        OsVoidFunc *tmp_ = hook;                                                 \
57        while (!OsMhookBoundaryCheck((OsVoidFunc)((pfn) = (funcType)(*tmp_)))) { \
58            if (OsMhookValidCheck((OsVoidFunc)(pfn))) {                          \
59                (list);                                                          \
60            }                                                                    \
61            tmp_++;                                                              \
62        }                                                                        \
63    } while (0)
64
65#define OS_MHOOK_ACTIVATE(hookType, funcType, list)              \
66    do {                                                         \
67        OsVoidFunc *hook = g_hookCb[(hookType)].mulHook;         \
68        funcType pfn;                                            \
69        if (hook != NULL) {                                      \
70            OS_MHOOK_ACTIVATE_PROC(hook, funcType, pfn, (list)); \
71        }                                                        \
72    } while (0)
73
74#define OS_SHOOK_ACTIVATE(hookType, funcType, list)            \
75    do {                                                       \
76        funcType pfn = (funcType)g_hookCb[(hookType)].sigHook; \
77        if (pfn != NULL)                                       \
78            (list);                                            \
79    } while (0)
80
81#define OS_MHOOK_ACTIVATE_PARA0(hookType) OS_MHOOK_ACTIVATE((hookType), OsFunPara0, pfn())
82#define OS_MHOOK_ACTIVATE_PARA1(hookType, arg0) OS_MHOOK_ACTIVATE((hookType), OsFunPara1, pfn((uintptr_t)(arg0)))
83#define OS_MHOOK_ACTIVATE_PARA2(hookType, arg0, arg1) OS_MHOOK_ACTIVATE((hookType), \
84    OsFunPara2, pfn((uintptr_t)(arg0), (uintptr_t)(arg1)))
85#define OS_MHOOK_ACTIVATE_PARA3(hookType, arg0, arg1, arg2) OS_MHOOK_ACTIVATE((hookType), \
86    OsFunPara3, pfn((uintptr_t)(arg0), (uintptr_t)(arg1), (uintptr_t)(arg2)))
87#define OS_MHOOK_ACTIVATE_PARA4(hookType, arg0, arg1, arg2, arg3) \
88    OS_MHOOK_ACTIVATE((hookType),                                 \
89    OsFunPara4, pfn((uintptr_t)(arg0), (uintptr_t)(arg1), (uintptr_t)(arg2), (uintptr_t)(arg3)))
90#define OS_MHOOK_ACTIVATE_PARA5(hookType, arg0, arg1, arg2, arg3, arg4) \
91    OS_MHOOK_ACTIVATE((hookType), OsFunPara5,                           \
92    pfn((uintptr_t)(arg0), (uintptr_t)(arg1), (uintptr_t)(arg2), (uintptr_t)(arg3), (uintptr_t)(arg4)))
93
94#define OS_SHOOK_ACTIVATE_PARA0(hookType) OS_SHOOK_ACTIVATE((hookType), OsFunPara0, pfn())
95#define OS_SHOOK_ACTIVATE_PARA1(hookType, arg0) OS_SHOOK_ACTIVATE((hookType), OsFunPara1, pfn((uintptr_t)(arg0)))
96#define OS_SHOOK_ACTIVATE_PARA2(hookType, arg0, arg1) OS_SHOOK_ACTIVATE((hookType), \
97    OsFunPara2, pfn((uintptr_t)(arg0), (uintptr_t)(arg1)))
98#define OS_SHOOK_ACTIVATE_PARA3(hookType, arg0, arg1, arg2) OS_SHOOK_ACTIVATE((hookType), \
99    OsFunPara3, pfn((uintptr_t)(arg0), (uintptr_t)(arg1), (uintptr_t)(arg2)))
100#define OS_SHOOK_ACTIVATE_PARA4(hookType, arg0, arg1, arg2, arg3) \
101    OS_SHOOK_ACTIVATE((hookType), OsFunPara4,                     \
102    pfn((uintptr_t)(arg0), (uintptr_t)(arg1), (uintptr_t)(arg2), (uintptr_t)(arg3)))
103#define OS_SHOOK_ACTIVATE_PARA5(hookType, arg0, arg1, arg2, arg3, arg4) \
104    OS_SHOOK_ACTIVATE((hookType), OsFunPara5,                           \
105    pfn((uintptr_t)(arg0), (uintptr_t)(arg1), (uintptr_t)(arg2), (uintptr_t)(arg3), (uintptr_t)(arg4)))
106
107#define HOOK_ADD_IRQ_LOCK(intSave) \
108    do {                           \
109        (intSave) = PRT_HwiLock(); \
110    } while (0)
111#define HOOK_ADD_IRQ_UNLOCK(intSave) PRT_HwiRestore((intSave))
112
113#define HOOK_DEL_IRQ_LOCK(intSave) \
114    do {                           \
115        (intSave) = PRT_HwiLock(); \
116    } while (0)
117#define HOOK_DEL_IRQ_UNLOCK(intSave) PRT_HwiRestore((intSave))
118
119enum {
120    OS_HOOK_TICK_ENTRY = OS_HOOK_TYPE_NUM,
121    OS_HOOK_TICK_EXIT,
122    OS_HOOK_FIRST_TIME_SWH,
123    OS_HOOK_TSK_MON, /* TSKMON钩子 */
124    OS_HOOK_CPUP_WARN, /* CPUP告警钩子 */
125    OS_HOOK_ERR_REG, /* 错误处理钩子 */
126    OS_HOOK_IDLE_PREFIX, /* IDLE前置钩子 */
127    OS_HOOK_MEM_DAMAGE, /* 踩内存处理钩子 */
128
129    OS_HOOK_TYPE_TOTAL
130};
131
132#define OS_SHOOK_TYPE_START ((U32)OS_HOOK_TSK_MON)
133
134enum HookChgType {
135    HOOK_ADD_FIRST,
136    HOOK_DEL_LAST
137};
138
139union TagMhookCb {
140    // 在初始化阶段复用为钩子注册数目
141    uintptr_t num;
142    // 单钩子
143    OsVoidFunc sigHook;
144    OsVoidFunc *mulHook;
145};
146
147typedef U32(*OsHookChgFunc)(U32 hookType, enum HookChgType chgType);
148
149extern union TagMhookCb g_hookCb[OS_HOOK_TYPE_TOTAL];
150
151typedef void *(*MemAllocHook)(enum MoudleId mid, U8 ptNo, U32 size);
152extern MemAllocHook g_osMemAlloc;
153
154/*
155 * 多钩子添加内部接口
156 */
157extern U32 OsMhookAdd(U32 hookType, OsVoidFunc hook);
158
159/*
160 * 多钩子删除内部接口
161 */
162extern U32 OsMhookDel(U32 hookType, OsVoidFunc hook);
163
164/*
165 * 钩子添加内部接口
166 */
167extern U32 OsHookAdd(enum HookType hookType, OsVoidFunc hook);
168
169/*
170 * 钩子删除内部接口
171 */
172extern U32 OsHookDel(enum HookType hookType, OsVoidFunc hook);
173
174/*
175 * 多钩子注册内部接口, 为了与原有规格兼容,传入NULL表示删除
176 */
177extern U32 OsShookReg(U32 hookType, OsVoidFunc hook);
178
179/*
180 * 在注册阶段,不同模块通过osMhookReserve接口预留钩子,不影响用户注册钩子数
181 * 仅在register阶段使用
182 */
183extern void OsMhookReserve(U32 hookType, U32 incCnt);
184
185#endif /* PRT_HOOK_EXTERNAL_H */
186