1419b0af8Sopenharmony_ci/*
2419b0af8Sopenharmony_ci * ko_adapt.c
3419b0af8Sopenharmony_ci *
4419b0af8Sopenharmony_ci * function for find symbols not exported
5419b0af8Sopenharmony_ci *
6419b0af8Sopenharmony_ci * Copyright (C) 2022 Huawei Technologies Co., Ltd.
7419b0af8Sopenharmony_ci *
8419b0af8Sopenharmony_ci * This software is licensed under the terms of the GNU General Public
9419b0af8Sopenharmony_ci * License version 2, as published by the Free Software Foundation, and
10419b0af8Sopenharmony_ci * may be copied, distributed, and modified under those terms.
11419b0af8Sopenharmony_ci *
12419b0af8Sopenharmony_ci * This program is distributed in the hope that it will be useful,
13419b0af8Sopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
14419b0af8Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15419b0af8Sopenharmony_ci * GNU General Public License for more details.
16419b0af8Sopenharmony_ci */
17419b0af8Sopenharmony_ci#include "ko_adapt.h"
18419b0af8Sopenharmony_ci#include <linux/types.h>
19419b0af8Sopenharmony_ci#include <linux/mm_types.h>
20419b0af8Sopenharmony_ci#include <linux/stddef.h>
21419b0af8Sopenharmony_ci#include <linux/cred.h>
22419b0af8Sopenharmony_ci#include <linux/version.h>
23419b0af8Sopenharmony_ci#if (KERNEL_VERSION(4, 14, 0) <= LINUX_VERSION_CODE)
24419b0af8Sopenharmony_ci#include <linux/sched/task.h>
25419b0af8Sopenharmony_ci#endif
26419b0af8Sopenharmony_ci#include <linux/cpumask.h>
27419b0af8Sopenharmony_ci#include <linux/syscalls.h>
28419b0af8Sopenharmony_ci#include <linux/fs.h>
29419b0af8Sopenharmony_ci#include "tc_ns_log.h"
30419b0af8Sopenharmony_ci
31419b0af8Sopenharmony_citypedef const struct cred *(get_task_cred_func)(struct task_struct *);
32419b0af8Sopenharmony_citypedef void (kthread_bind_mask_func)(struct task_struct *, const struct cpumask *);
33419b0af8Sopenharmony_citypedef struct page *(alloc_pages_func)(gfp_t gfp_mask, unsigned int order);
34419b0af8Sopenharmony_citypedef struct workqueue_attrs *(alloc_workqueue_attrs_func)(gfp_t gfp_mask);
35419b0af8Sopenharmony_citypedef void (free_workqueue_attrs_func)(struct workqueue_attrs *attrs);
36419b0af8Sopenharmony_ci
37419b0af8Sopenharmony_ciconst struct cred *koadpt_get_task_cred(struct task_struct *task)
38419b0af8Sopenharmony_ci{
39419b0af8Sopenharmony_ci#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0))
40419b0af8Sopenharmony_ci	return get_task_cred(task);
41419b0af8Sopenharmony_ci#else
42419b0af8Sopenharmony_ci	static get_task_cred_func *get_task_cred_pt = NULL;
43419b0af8Sopenharmony_ci
44419b0af8Sopenharmony_ci	if (!task)
45419b0af8Sopenharmony_ci		return NULL;
46419b0af8Sopenharmony_ci
47419b0af8Sopenharmony_ci	if (!get_task_cred_pt) {
48419b0af8Sopenharmony_ci		get_task_cred_pt = (get_task_cred_func *)
49419b0af8Sopenharmony_ci			(uintptr_t)kallsyms_lookup_name("get_task_cred");
50419b0af8Sopenharmony_ci		if (IS_ERR_OR_NULL(get_task_cred_pt)) {
51419b0af8Sopenharmony_ci			tloge("fail to find symbol get task cred\n");
52419b0af8Sopenharmony_ci			return NULL;
53419b0af8Sopenharmony_ci		}
54419b0af8Sopenharmony_ci	}
55419b0af8Sopenharmony_ci	return get_task_cred_pt(task);
56419b0af8Sopenharmony_ci#endif
57419b0af8Sopenharmony_ci}
58419b0af8Sopenharmony_ci
59419b0af8Sopenharmony_civoid koadpt_kthread_bind_mask(struct task_struct *task,
60419b0af8Sopenharmony_ci	const struct cpumask *mask)
61419b0af8Sopenharmony_ci{
62419b0af8Sopenharmony_ci#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0))
63419b0af8Sopenharmony_ci	(void)set_cpus_allowed_ptr(task, mask);
64419b0af8Sopenharmony_ci#else
65419b0af8Sopenharmony_ci	static kthread_bind_mask_func *kthread_bind_mask_pt = NULL;
66419b0af8Sopenharmony_ci
67419b0af8Sopenharmony_ci	if (!task || !mask)
68419b0af8Sopenharmony_ci		return;
69419b0af8Sopenharmony_ci
70419b0af8Sopenharmony_ci	if (!kthread_bind_mask_pt) {
71419b0af8Sopenharmony_ci		kthread_bind_mask_pt = (kthread_bind_mask_func *)
72419b0af8Sopenharmony_ci			(uintptr_t)kallsyms_lookup_name("kthread_bind_mask");
73419b0af8Sopenharmony_ci		if (IS_ERR_OR_NULL(kthread_bind_mask_pt)) {
74419b0af8Sopenharmony_ci			tloge("fail to find symbol kthread bind mask\n");
75419b0af8Sopenharmony_ci			return;
76419b0af8Sopenharmony_ci		}
77419b0af8Sopenharmony_ci	}
78419b0af8Sopenharmony_ci	kthread_bind_mask_pt(task, mask);
79419b0af8Sopenharmony_ci#endif
80419b0af8Sopenharmony_ci}
81419b0af8Sopenharmony_ci
82419b0af8Sopenharmony_cistruct page *koadpt_alloc_pages(gfp_t gfp_mask, unsigned int order)
83419b0af8Sopenharmony_ci{
84419b0af8Sopenharmony_ci#ifdef CONFIG_NUMA
85419b0af8Sopenharmony_ci#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0))
86419b0af8Sopenharmony_ci	return alloc_pages(gfp_mask, order);
87419b0af8Sopenharmony_ci#else
88419b0af8Sopenharmony_ci	static alloc_pages_func *alloc_pages_pt = NULL;
89419b0af8Sopenharmony_ci
90419b0af8Sopenharmony_ci	if (!alloc_pages_pt) {
91419b0af8Sopenharmony_ci		alloc_pages_pt = (alloc_pages_func *)
92419b0af8Sopenharmony_ci			(uintptr_t)kallsyms_lookup_name("alloc_pages_current");
93419b0af8Sopenharmony_ci		if (IS_ERR_OR_NULL(alloc_pages_pt)) {
94419b0af8Sopenharmony_ci			tloge("fail to find symbol alloc pages current\n");
95419b0af8Sopenharmony_ci			return NULL;
96419b0af8Sopenharmony_ci		}
97419b0af8Sopenharmony_ci	}
98419b0af8Sopenharmony_ci	return alloc_pages_pt(gfp_mask, order);
99419b0af8Sopenharmony_ci#endif
100419b0af8Sopenharmony_ci#else
101419b0af8Sopenharmony_ci	return alloc_pages(gfp_mask, order);
102419b0af8Sopenharmony_ci#endif
103419b0af8Sopenharmony_ci}
104419b0af8Sopenharmony_ci
105419b0af8Sopenharmony_cistruct workqueue_attrs *koadpt_alloc_workqueue_attrs(gfp_t gfp_mask)
106419b0af8Sopenharmony_ci{
107419b0af8Sopenharmony_ci#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0))
108419b0af8Sopenharmony_ci	struct workqueue_attrs *attrs;
109419b0af8Sopenharmony_ci	(void)gfp_mask;
110419b0af8Sopenharmony_ci
111419b0af8Sopenharmony_ci	attrs = kzalloc(sizeof(*attrs), GFP_KERNEL);
112419b0af8Sopenharmony_ci	if (!attrs) {
113419b0af8Sopenharmony_ci		tloge("alloc workqueue attr fail\n");
114419b0af8Sopenharmony_ci		return NULL;
115419b0af8Sopenharmony_ci	}
116419b0af8Sopenharmony_ci
117419b0af8Sopenharmony_ci	if (alloc_cpumask_var(&attrs->cpumask, GFP_KERNEL) == false) {
118419b0af8Sopenharmony_ci		tloge("alloc cpumask var fail\n");
119419b0af8Sopenharmony_ci		kfree(attrs);
120419b0af8Sopenharmony_ci		return NULL;
121419b0af8Sopenharmony_ci	}
122419b0af8Sopenharmony_ci
123419b0af8Sopenharmony_ci	cpumask_copy(attrs->cpumask, cpu_possible_mask);
124419b0af8Sopenharmony_ci
125419b0af8Sopenharmony_ci	return attrs;
126419b0af8Sopenharmony_ci#else
127419b0af8Sopenharmony_ci	static alloc_workqueue_attrs_func *alloc_workqueue_attrs_pt = NULL;
128419b0af8Sopenharmony_ci
129419b0af8Sopenharmony_ci	if (!alloc_workqueue_attrs_pt) {
130419b0af8Sopenharmony_ci		alloc_workqueue_attrs_pt = (alloc_workqueue_attrs_func *)
131419b0af8Sopenharmony_ci			(uintptr_t)kallsyms_lookup_name("alloc_workqueue_attrs");
132419b0af8Sopenharmony_ci		if (IS_ERR_OR_NULL(alloc_workqueue_attrs_pt)) {
133419b0af8Sopenharmony_ci			tloge("fail to find symbol alloc workqueue attrs\n");
134419b0af8Sopenharmony_ci			return NULL;
135419b0af8Sopenharmony_ci		}
136419b0af8Sopenharmony_ci	}
137419b0af8Sopenharmony_ci	return alloc_workqueue_attrs_pt(gfp_mask);
138419b0af8Sopenharmony_ci#endif
139419b0af8Sopenharmony_ci}
140419b0af8Sopenharmony_ci
141419b0af8Sopenharmony_civoid koadpt_free_workqueue_attrs(struct workqueue_attrs *attrs)
142419b0af8Sopenharmony_ci{
143419b0af8Sopenharmony_ci#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0))
144419b0af8Sopenharmony_ci	if (!attrs)
145419b0af8Sopenharmony_ci		return;
146419b0af8Sopenharmony_ci
147419b0af8Sopenharmony_ci	free_cpumask_var(attrs->cpumask);
148419b0af8Sopenharmony_ci	kfree(attrs);
149419b0af8Sopenharmony_ci#else
150419b0af8Sopenharmony_ci	static free_workqueue_attrs_func *free_workqueue_attrs_pt = NULL;
151419b0af8Sopenharmony_ci
152419b0af8Sopenharmony_ci	if (!attrs)
153419b0af8Sopenharmony_ci		return;
154419b0af8Sopenharmony_ci
155419b0af8Sopenharmony_ci	if (!free_workqueue_attrs_pt) {
156419b0af8Sopenharmony_ci		free_workqueue_attrs_pt = (free_workqueue_attrs_func *)
157419b0af8Sopenharmony_ci			(uintptr_t)kallsyms_lookup_name("free_workqueue_attrs");
158419b0af8Sopenharmony_ci		if (IS_ERR_OR_NULL(free_workqueue_attrs_pt)) {
159419b0af8Sopenharmony_ci			tloge("fail to find symbol free workqueue attrs\n");
160419b0af8Sopenharmony_ci			return;
161419b0af8Sopenharmony_ci		}
162419b0af8Sopenharmony_ci	}
163419b0af8Sopenharmony_ci	free_workqueue_attrs_pt(attrs);
164419b0af8Sopenharmony_ci#endif
165419b0af8Sopenharmony_ci}