From c027f963bc9ecea4ae64ef64d6252c212b579322 Mon Sep 17 00:00:00 2001 From: ruty8086 Date: Tue, 16 Aug 2022 19:51:22 +0800 Subject: [PATCH 1/2] Revert "sched:Add qos control and qos authority" This reverts commit 821306940eca5f9fa25cc1e199457956f3cf3981. --- include/linux/sched.h | 5 - include/linux/sched/rtg_ctrl.h | 30 -- init/main.c | 8 - kernel/sched/core.c | 5 - kernel/sched/rtg/Kconfig | 18 -- kernel/sched/rtg/Makefile | 1 - kernel/sched/rtg/rtg_ctrl.c | 487 +-------------------------------- kernel/sched/rtg/rtg_ctrl.h | 69 ----- kernel/sched/rtg/rtg_qos.c | 241 ---------------- kernel/sched/rtg/rtg_qos.h | 37 --- kernel/sched/walt.c | 4 - 11 files changed, 1 insertion(+), 904 deletions(-) delete mode 100644 kernel/sched/rtg/rtg_qos.c delete mode 100644 kernel/sched/rtg/rtg_qos.h diff --git a/include/linux/sched.h b/include/linux/sched.h index a67583bfada7..6db123826eb9 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -824,11 +824,6 @@ struct task_struct { struct list_head grp_list; #endif -#ifdef CONFIG_SCHED_RTG_QOS - struct list_head qos_list; - int in_qos; -#endif - #ifdef CONFIG_CGROUP_SCHED struct task_group *sched_task_group; #endif diff --git a/include/linux/sched/rtg_ctrl.h b/include/linux/sched/rtg_ctrl.h index 6bd3046e18aa..b71dd74e7fc3 100644 --- a/include/linux/sched/rtg_ctrl.h +++ b/include/linux/sched/rtg_ctrl.h @@ -42,14 +42,6 @@ _IOWR(RTG_SCHED_IPC_MAGIC, SEARCH_RTG, struct proc_state_data) #define CMD_ID_GET_ENABLE \ _IOWR(RTG_SCHED_IPC_MAGIC, GET_ENABLE, struct rtg_enable_data) -#ifdef CONFIG_SCHED_RTG_AUTHORITY -#define CMD_ID_AUTH_MANIPULATE \ - _IOWR(RTG_SCHED_IPC_MAGIC, AUTH_MANIPULATE, struct rtg_auth_data) -#endif -#ifdef CONFIG_SCHED_RTG_QOS -#define CMD_ID_QOS_MANIPULATE \ - _IOWR(RTG_SCHED_IPC_MAGIC, QOS_MANIPULATE, struct rtg_qos_data) -#endif int proc_rtg_open(struct inode *inode, struct file *filp); long proc_rtg_ioctl(struct file *file, unsigned int cmd, unsigned long arg); @@ -76,12 +68,6 @@ enum rtg_sched_cmdid { LIST_RTG_THREAD, SEARCH_RTG, GET_ENABLE, -#ifdef CONFIG_SCHED_RTG_AUTHORITY - AUTH_MANIPULATE, /* SYSTEM OR ROOT */ -#endif -#ifdef CONFIG_SCHED_RTG_QOS - QOS_MANIPULATE, -#endif RTG_CTRL_MAX_NR, }; @@ -110,20 +96,4 @@ struct proc_state_data { int grp_id; int state_param; }; - -#ifdef CONFIG_SCHED_RTG_AUTHORITY -struct rtg_auth_data { - unsigned int uid; - unsigned int type; - unsigned int ua_flag; - unsigned int status; -}; -#endif - -#ifdef CONFIG_SCHED_RTG_QOS -struct rtg_qos_data { - unsigned int type; - unsigned int level; -}; -#endif #endif diff --git a/init/main.c b/init/main.c index e8d5c6477991..9b9e589af4bd 100644 --- a/init/main.c +++ b/init/main.c @@ -113,10 +113,6 @@ #include -#ifdef CONFIG_SCHED_RTG_AUTHORITY -extern int init_rtg_authority_control(void); -#endif - static int kernel_init(void *); extern void init_IRQ(void); @@ -930,10 +926,6 @@ asmlinkage __visible void __init __no_sanitize_address start_kernel(void) local_irq_disable(); radix_tree_init(); -#ifdef CONFIG_SCHED_RTG_AUTHORITY - BUG_ON(init_rtg_authority_control()); -#endif - /* * Set up housekeeping before setting up workqueues to allow the unbound * workqueue to take non-housekeeping into account. diff --git a/kernel/sched/core.c b/kernel/sched/core.c index e2f00be4bb61..f9cc6b8adb4f 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -31,7 +31,6 @@ #include "smp.h" #include "walt.h" #include "rtg/rtg.h" -#include "rtg/rtg_qos.h" /* * Export tracepoints that act as a bare tracehook (ie: have no trace event @@ -9173,10 +9172,6 @@ void sched_exit(struct task_struct *p) sched_set_group_id(p, 0); #endif -#ifdef CONFIG_SCHED_RTG_QOS - sched_exit_qos_list(p); -#endif - rq = task_rq_lock(p, &rf); /* rq->curr == p */ diff --git a/kernel/sched/rtg/Kconfig b/kernel/sched/rtg/Kconfig index 8f556d28a9aa..1cb0c4298b09 100644 --- a/kernel/sched/rtg/Kconfig +++ b/kernel/sched/rtg/Kconfig @@ -37,22 +37,4 @@ config SCHED_RTG_RT_THREAD_LIMIT default n help If set, limit the number of RT threads in frame RTG. - -config SCHED_RTG_AUTHORITY - bool "Related Thread Group authority control" - depends on SCHED_RTG - default n - help - Support authority for RTG-related operations. If set, - only thread authorized can do RTG-related operations. - -config SCHED_RTG_QOS - bool "Related Thread Group authority control" - depends on SCHED_RTG - depends on SCHED_RTG_AUTHORITY - default n - help - Introduce qos support for thread. If set, thread can - apply kernel qos for better cpu time supply or lower - latency. endmenu diff --git a/kernel/sched/rtg/Makefile b/kernel/sched/rtg/Makefile index dd2206e4d61f..4d55523d1f32 100644 --- a/kernel/sched/rtg/Makefile +++ b/kernel/sched/rtg/Makefile @@ -1,4 +1,3 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_SCHED_RTG) += rtg.o obj-$(CONFIG_SCHED_RTG_FRAME) += frame_rtg.o rtg_ctrl.o -obj-$(CONFIG_SCHED_RTG_QOS) += rtg_qos.o diff --git a/kernel/sched/rtg/rtg_ctrl.c b/kernel/sched/rtg/rtg_ctrl.c index b01e0ab026b2..d49e02899495 100644 --- a/kernel/sched/rtg/rtg_ctrl.c +++ b/kernel/sched/rtg/rtg_ctrl.c @@ -7,18 +7,11 @@ #include "rtg.h" #include "rtg_ctrl.h" -#include "rtg_qos.h" #include #include #include #include -#ifdef CONFIG_SCHED_RTG_AUTHORITY -#include -#include -#include -#include -#endif #include atomic_t g_rtg_enable = ATOMIC_INIT(0); @@ -40,12 +33,6 @@ static long ctrl_list_rtg(int abi, void __user *uarg); static long ctrl_list_rtg_thread(int abi, void __user *uarg); static long ctrl_search_rtg(int abi, void __user *uarg); static long ctrl_get_enable(int abi, void __user *uarg); -#ifdef CONFIG_SCHED_RTG_AUTHORITY -static long ctrl_auth_manipulate(int abi, void __user *uarg); -#endif -#ifdef CONFIG_SCHED_RTG_QOS -static long ctrl_qos_manipulate(int abi, void __user *uarg); -#endif static rtg_ctrl_func g_func_array[RTG_CTRL_MAX_NR] = { NULL, /* reserved */ @@ -61,13 +48,7 @@ static rtg_ctrl_func g_func_array[RTG_CTRL_MAX_NR] = { ctrl_list_rtg, // 10 ctrl_list_rtg_thread, ctrl_search_rtg, - ctrl_get_enable, -#ifdef CONFIG_SCHED_RTG_AUTHORITY - ctrl_auth_manipulate, -#endif -#ifdef CONFIG_SCHED_RTG_QOS - ctrl_qos_manipulate, -#endif + ctrl_get_enable }; static int init_proc_state(const int *config, int len); @@ -897,462 +878,6 @@ static long ctrl_search_rtg(int abi, void __user *uarg) return search_rtg(search_data.state_param); } -#ifdef CONFIG_SCHED_RTG_AUTHORITY -/* - * uid-based authority idr table - */ -static struct idr *ua_idr; - -static DEFINE_RAW_SPINLOCK(ua_idr_lock); - -static struct rtg_authority rtg_auth_super; - -static void change_to_super(struct rtg_authority *auth) -{ - auth->flag = AF_RTG_ALL; - auth->status = AUTH_STATUS_ENABLE; -} - -static void init_rtg_authority_record(struct rtg_authority *auth) -{ -#ifdef CONFIG_SCHED_RTG_QOS - int i; -#endif - - auth->flag = 0; - auth->status = AUTH_STATUS_CACHED; - raw_spin_lock_init(&auth->auth_lock); - refcount_set(&auth->usage, 1); -#ifdef CONFIG_SCHED_RTG_QOS - for (i = 0; i <= NR_QOS; ++i) { - INIT_LIST_HEAD(&auth->tasks[i]); - auth->num[i] = 0; - } -#endif -} - -void get_rtg_auth(struct rtg_authority *auth) -{ - refcount_inc(&auth->usage); -} - -#ifdef CONFIG_SCHED_RTG_QOS -static void remove_qos_tasks(struct rtg_authority *auth) -{ - int i; - struct task_struct *tmp, *next; - - for (i = 0; i <= NR_QOS; ++i) { - list_for_each_entry_safe(tmp, next, &auth->tasks[i], qos_list) { - get_task_struct(tmp); - tmp->in_qos = 0; - list_del_init(&tmp->qos_list); - put_task_struct(tmp); - } - } -} -#endif - -static void __put_rtg_auth(struct rtg_authority *auth) -{ - WARN_ON(auth->status != AUTH_STATUS_DEAD); - WARN_ON(refcount_read(&auth->usage)); - -#ifdef CONFIG_SCHED_RTG_QOS - /* refcount is zero here, no contend, no lock. */ - remove_qos_tasks(auth); -#endif - kfree(auth); -} - -void put_rtg_auth(struct rtg_authority *auth) -{ - if (refcount_dec_and_test(&auth->usage)) - __put_rtg_auth(auth); -} - -int init_rtg_authority_control(void) -{ - int ret; - - ua_idr = kzalloc(sizeof(*ua_idr), GFP_ATOMIC); - if (ua_idr == NULL) { - pr_err("[SCHED_RTG] rtg idr init failed, no memory!\n"); - return -ENOMEM; - } - - idr_init(ua_idr); - - init_rtg_authority_record(&rtg_auth_super); - change_to_super(&rtg_auth_super); - - ret = idr_alloc(ua_idr, &rtg_auth_super, UID_FOR_SUPER, UID_FOR_SUPER + 1, GFP_ATOMIC); - if (ret != UID_FOR_SUPER) { - pr_err("[SCHED_RTG] rtg authority for super init failed! ret=%d\n", ret); - goto err; - } - - return 0; - -err: - idr_destroy(ua_idr); - kfree(ua_idr); - - return ret; -} - -int authority_remove_handler(int id, void *p, void *para) -{ - struct rtg_authority *auth = (struct rtg_authority *)p; - - raw_spin_lock(&auth->auth_lock); -#ifdef CONFIG_SCHED_RTG_QOS - qos_pause(auth); -#endif - auth->status = AUTH_STATUS_DEAD; - raw_spin_unlock(&auth->auth_lock); - put_rtg_auth(auth); - - return 0; -} - -void remove_rtg_authority_control(void) -{ - int ret; - - raw_spin_lock(&ua_idr_lock); - ret = idr_for_each(ua_idr, authority_remove_handler, NULL); - if (ret < 0) - pr_err("[SCHED_RTG] rtg authority item remove failed\n"); - - idr_destroy(ua_idr); - kfree(ua_idr); - - raw_spin_unlock(&ua_idr_lock); -} - -static int auth_trim(unsigned int ua_flag) -{ - return ua_flag & AF_RTG_DELEGATED; -} - -static int auth_enable(struct rtg_auth_data *data) -{ - struct rtg_authority *auth_to_enable; - unsigned int uid = data->uid; - bool enable = (data->status == AUTH_STATUS_ENABLE); - int ret; - - raw_spin_lock(&ua_idr_lock); - auth_to_enable = idr_find(ua_idr, uid); - /* auth exist, just resume the task's qos request */ - if (auth_to_enable) { - get_rtg_auth(auth_to_enable); - raw_spin_unlock(&ua_idr_lock); - - raw_spin_lock(&auth_to_enable->auth_lock); - if (auth_to_enable->status == AUTH_STATUS_DEAD) { - raw_spin_unlock(&auth_to_enable->auth_lock); - put_rtg_auth(auth_to_enable); - return -INVALID_AUTH; - } - - auth_to_enable->flag = auth_trim(data->ua_flag); -#ifdef CONFIG_SCHED_RTG_QOS - if (enable) - qos_resume(auth_to_enable); -#endif - raw_spin_unlock(&auth_to_enable->auth_lock); - ret = 0; - put_rtg_auth(auth_to_enable); - goto out; - } - - /* auth not exist, build a new auth, then insert to idr */ - auth_to_enable = kzalloc(sizeof(*auth_to_enable), GFP_ATOMIC); - if (!auth_to_enable) { - raw_spin_unlock(&ua_idr_lock); - pr_err("[SCHED_RTG] alloc auth data failed, no memory!\n"); - ret = -ENOMEM; - goto out; - } - - init_rtg_authority_record(auth_to_enable); - - /* no one could get the auth from idr now, no need to lock */ - auth_to_enable->flag = auth_trim(data->ua_flag); - if (enable) - auth_to_enable->status = AUTH_STATUS_ENABLE; - - ret = idr_alloc(ua_idr, auth_to_enable, uid, uid + 1, GFP_ATOMIC); - if (ret < 0) { - pr_err("[SCHED_RTG] add auth to idr failed, no memory!\n"); - kfree(auth_to_enable); - } - - raw_spin_unlock(&ua_idr_lock); - -out: - return ret; -} - -static int auth_pause(struct rtg_auth_data *data) -{ - struct rtg_authority *auth_to_pause; - unsigned int uid = data->uid; - - raw_spin_lock(&ua_idr_lock); - auth_to_pause = idr_find(ua_idr, uid); - if (!auth_to_pause) { - raw_spin_unlock(&ua_idr_lock); - pr_err("[SCHED_RTG] no auth data for this uid to pause=%d\n", uid); - return UID_NOT_FOUND; - } - get_rtg_auth(auth_to_pause); - raw_spin_unlock(&ua_idr_lock); - - raw_spin_lock(&auth_to_pause->auth_lock); - if (auth_to_pause->status == AUTH_STATUS_DEAD) { - raw_spin_unlock(&auth_to_pause->auth_lock); - put_rtg_auth(auth_to_pause); - return -INVALID_AUTH; - } -#ifdef CONFIG_SCHED_RTG_QOS - qos_pause(auth_to_pause); -#endif - raw_spin_unlock(&auth_to_pause->auth_lock); - - put_rtg_auth(auth_to_pause); - - return 0; -} - -static int auth_delete(struct rtg_auth_data *data) -{ - struct rtg_authority *auth_to_delete; - unsigned int uid = data->uid; - - raw_spin_lock(&ua_idr_lock); - auth_to_delete = (struct rtg_authority *)idr_remove(ua_idr, uid); - if (!auth_to_delete) { - raw_spin_unlock(&ua_idr_lock); - pr_err("[SCHED_RTG] no auth data for this uid=%d, delete failed\n", uid); - return -UID_NOT_FOUND; - } - raw_spin_unlock(&ua_idr_lock); - - raw_spin_lock(&auth_to_delete->auth_lock); -#ifdef CONFIG_SCHED_RTG_QOS - qos_pause(auth_to_delete); -#endif - auth_to_delete->status = AUTH_STATUS_DEAD; - raw_spin_unlock(&auth_to_delete->auth_lock); - - put_rtg_auth(auth_to_delete); - - return 0; -} - -static int auth_get(struct rtg_auth_data *data) -{ - struct rtg_authority *auth_to_get; - unsigned int uid = data->uid; - - raw_spin_lock(&ua_idr_lock); - auth_to_get = idr_find(ua_idr, uid); - if (!auth_to_get) { - raw_spin_unlock(&ua_idr_lock); - pr_err("[SCHED_RTG] no auth data for this uid=%d to get\n", uid); - return -UID_NOT_FOUND; - } - get_rtg_auth(auth_to_get); - raw_spin_unlock(&ua_idr_lock); - - raw_spin_lock(&auth_to_get->auth_lock); - if (auth_to_get->status == AUTH_STATUS_DEAD) { - raw_spin_unlock(&auth_to_get->auth_lock); - put_rtg_auth(auth_to_get); - return -INVALID_AUTH; - } - data->ua_flag = auth_to_get->flag; - data->status = auth_to_get->status; - raw_spin_unlock(&auth_to_get->auth_lock); - - put_rtg_auth(auth_to_get); - - return 0; -} - -typedef int (*rtg_auth_manipulate_func)(struct rtg_auth_data *data); - -static rtg_auth_manipulate_func auth_func_array[AUTH_MAX_NR] = { - NULL, - auth_enable, //1 - auth_pause, - auth_delete, - auth_get, -}; - -static long do_auth_manipulate(struct rtg_auth_data *data) -{ - long ret = 0; - unsigned int type = data->type; - - if (type >= AUTH_MAX_NR) { - pr_err("[SCHED_RTG] CMD_ID_AUTH_MANIPULATE type not valid\n"); - return -INVALID_ARG; - } - - if (auth_func_array[type]) - ret = (long)(*auth_func_array[type])(data); - - return ret; -} - -static long ctrl_auth_manipulate(int abi, void __user *uarg) -{ - struct rtg_auth_data auth_data; - long ret; - - if (copy_from_user(&auth_data, uarg, sizeof(struct rtg_auth_data))) { - pr_err("[SCHED_RTG] CMD_ID_AUTH_MANIPULATE copy data failed\n"); - return -INVALID_ARG; - } - - ret = do_auth_manipulate(&auth_data); - if (ret < 0) { - pr_err("[SCHED_RTG]] CMD_ID_AUTH_MANIPULATE failed\n"); - return ret; - } - - if (copy_to_user(uarg, &auth_data, sizeof(struct rtg_auth_data))) { - pr_err("[SCHED_RTG]] CMD_ID_AUTH_MANIPULATE send data failed\n"); - return -INVALID_ARG; - } - - return 0; -} - -#define get_authority_flag(func_id) (1 << (func_id - 1)) - -static inline unsigned int get_true_uid(struct task_struct *p) -{ - if (!p) - return get_uid(current_user())->uid.val; - - return task_uid(p).val; -} - -/* - * Return 1000 for both SYSTEM and ROOT - */ -static inline unsigned int get_authority_uid(struct task_struct *p) -{ - unsigned int uid = get_true_uid(p); - - if (super_uid(uid)) - uid = UID_FOR_SUPER; - - return uid; -} - -static bool rtg_check_authorized(unsigned int func_id) -{ - bool authorized = false; - struct rtg_authority *auth; - unsigned int af = get_authority_flag(func_id); - unsigned int uid = get_authority_uid(NULL); - - raw_spin_lock(&ua_idr_lock); - if (!ua_idr) { - raw_spin_unlock(&ua_idr_lock); - pr_err("[SCHED_RTG] authority idr table missed, auth failed\n"); - return authorized; - } - - auth = (struct rtg_authority *)idr_find(ua_idr, uid); - if (!auth) { - raw_spin_unlock(&ua_idr_lock); - pr_err("[SCHED_RTG] no auth data for this uid=%d\n", uid); - return authorized; - } - get_rtg_auth(auth); - raw_spin_unlock(&ua_idr_lock); - - raw_spin_lock(&auth->auth_lock); - if (auth->status == AUTH_STATUS_DEAD) { - raw_spin_unlock(&auth->auth_lock); - pr_info("[SCHED_RTG] not valied auth for uid %d\n", uid); - put_rtg_auth(auth); - return authorized; - } - if (auth && (auth->flag & af)) - authorized = true; - - raw_spin_unlock(&auth->auth_lock); - - put_rtg_auth(auth); - - return authorized; -} - -/* - * Return RTG authority info for given task - * return current's auth if p is NULL - * recount will inc if this call return the valid auth - * make sure to call put_rtg_auth before the calling end - */ -struct rtg_authority *get_authority(struct task_struct *p) -{ - unsigned int uid = get_authority_uid(NULL); - struct rtg_authority *auth; - - raw_spin_lock(&ua_idr_lock); - auth = idr_find(ua_idr, uid); - if (auth) - get_rtg_auth(auth); - raw_spin_unlock(&ua_idr_lock); - - return auth; -} - -#ifdef CONFIG_SCHED_RTG_QOS -static rtg_qos_manipulate_func qos_func_array[QOS_MAX_NR] = { - NULL, - qos_apply, //1 - qos_leave, -}; - -static long do_qos_manipulate(struct rtg_qos_data *data) -{ - long ret = 0; - unsigned int type = data->type; - - if (type >= QOS_MAX_NR) { - pr_err("[SCHED_RTG] CMD_ID_QOS_MANIPULATE type not valid\n"); - return -INVALID_ARG; - } - - if (qos_func_array[type]) - ret = (long)(*qos_func_array[type])(data); - - return ret; -} - -static long ctrl_qos_manipulate(int abi, void __user *uarg) -{ - struct rtg_qos_data qos_data; - - if (copy_from_user(&qos_data, uarg, sizeof(struct rtg_qos_data))) { - pr_err("[SCHED_RTG] CMD_ID_QOS_APPLY copy data failed\n"); - return -INVALID_ARG; - } - - return do_qos_manipulate(&qos_data); -} -#endif -#endif /* CONFIG_SCHED_RTG_AUTHORITY */ - static long do_proc_rtg_ioctl(int abi, struct file *file, unsigned int cmd, unsigned long arg) { void __user *uarg = (void __user *)(uintptr_t)arg; @@ -1363,13 +888,6 @@ static long do_proc_rtg_ioctl(int abi, struct file *file, unsigned int cmd, unsi return -EINVAL; } -#ifdef CONFIG_SCHED_RTG_AUTHORITY - if (!rtg_check_authorized(func_id)) { - pr_err("[SCHED_RTG] %s: uid not authorized\n", __func__); - return -UID_NOT_AUTHORIZED; - } -#endif - if (_IOC_TYPE(cmd) != RTG_SCHED_IPC_MAGIC) { pr_err("[SCHED_RTG] %s: RTG_SCHED_IPC_MAGIC fail, TYPE=%d\n", __func__, _IOC_TYPE(cmd)); @@ -1531,9 +1049,6 @@ static int __init rtg_ctrl_dev_init(void) static void __exit rtg_ctrl_dev_exit(void) { misc_deregister(&rtg_ctrl_device); -#ifdef CONFIG_SCHED_RTG_AUTHORITY - remove_rtg_authority_control(); -#endif } module_init(rtg_ctrl_dev_init); diff --git a/kernel/sched/rtg/rtg_ctrl.h b/kernel/sched/rtg/rtg_ctrl.h index 6f8db6426464..6d405f589dab 100644 --- a/kernel/sched/rtg/rtg_ctrl.h +++ b/kernel/sched/rtg/rtg_ctrl.h @@ -11,13 +11,8 @@ #include #include #include -#ifdef CONFIG_SCHED_RTG_AUTHORITY -#include -#include -#endif #include "frame_rtg.h" -#include "rtg_qos.h" /* set rtg */ #define INVALID_VALUE 0xffff @@ -41,50 +36,6 @@ #define MAX_FREQ_CYCLE 16 #define DEFAULT_INVALID_INTERVAL 50 - -#ifdef CONFIG_SCHED_RTG_AUTHORITY -/* - * RTG authority flags for SYSTEM or ROOT - * - * keep sync with rtg_sched_cmdid - * when add a new cmd to rtg_sched_cmdid - * keep new_flag = (old_flag << 1) + 1 - * up to now, next flag value is 0xbfff - */ -#define AF_RTG_ALL 0x7fff - -/* - * delegated authority for normal uid - * no AUTH_MANIPULATE (rtg_sched_cmdid = 14) - */ -#define AF_RTG_DELEGATED 0x5fff - -#define ROOT_UID 0 -#define SYSTEM_UID 1000 - -#define UID_FOR_SUPER SYSTEM_UID -#define super_uid(uid) (uid == ROOT_UID || uid == SYSTEM_UID) - -enum auth_manipulate_type { - AUTH_ENABLE = 1, - AUTH_PAUSE, - AUTH_DELETE, - AUTH_GET, - AUTH_MAX_NR, -}; - -enum rtg_auth_status { - AUTH_STATUS_CACHED = 0, - AUTH_STATUS_ENABLE, - AUTH_STATUS_DEAD, -}; - -extern int init_rtg_authority_control(void); -struct rtg_authority *get_authority(struct task_struct *p); -void get_rtg_auth(struct rtg_authority *auth); -void put_rtg_auth(struct rtg_authority *auth); -#endif - /* proc_state */ enum proc_state { STATE_MIN = 0, @@ -115,13 +66,6 @@ enum rtg_err_no { NOT_MULTI_FRAME, INVALID_RTG_ID, NO_RT_FRAME, -#ifdef CONFIG_SCHED_RTG_AUTHORITY - UID_NOT_AUTHORIZED, - UID_NOT_FOUND, - PID_DUPLICATE, - PID_NOT_EXIST, - INVALID_AUTH, -#endif }; struct rtg_grp_data { @@ -140,17 +84,4 @@ struct rtg_proc_data { int rtcnt; }; -#ifdef CONFIG_SCHED_RTG_AUTHORITY -struct rtg_authority { - raw_spinlock_t auth_lock; - refcount_t usage; - unsigned int status; - unsigned int flag; -#ifdef CONFIG_SCHED_RTG_QOS - unsigned int num[NR_QOS + 1]; - struct list_head tasks[NR_QOS + 1]; -#endif -}; -#endif - #endif diff --git a/kernel/sched/rtg/rtg_qos.c b/kernel/sched/rtg/rtg_qos.c deleted file mode 100644 index 6cdcac14c1b0..000000000000 --- a/kernel/sched/rtg/rtg_qos.c +++ /dev/null @@ -1,241 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * rtg control entry - * - * Copyright (c) 2022-2023 Huawei Technologies Co., Ltd. - */ -#include "rtg.h" -#include "rtg_ctrl.h" -#include "rtg_qos.h" - -/* - * Pause uid-own-tasks' qos supply - * Called after get auth->auth_lock - */ -void qos_pause(struct rtg_authority *auth) -{ - int i; - struct task_struct *task; - - if (auth->status == AUTH_STATUS_ENABLE) { - for (i = 0; i <= NR_QOS; ++i) { - list_for_each_entry(task, &auth->tasks[i], qos_list) { - /* remove_latency_nice || remove_from_rtg_nocheck*/ - /* what if reset failed on some task ? */ - } - } - } - - auth->status = AUTH_STATUS_CACHED; -} - -/* - * Resume uid-own-tasks' qos supply - * Called after get auth->auth_lock - */ -void qos_resume(struct rtg_authority *auth) -{ - int i; - struct task_struct *task; - - if (!auth) { - pr_err("[SCHED_RTG] auth no exist, qos resume failed\n"); - return; - } - - if (auth->status == AUTH_STATUS_CACHED) { - for (i = 0; i <= NR_QOS; ++i) { - list_for_each_entry(task, &auth->tasks[i], qos_list) { - /* add_latency_nice || add_to_rtg_nocheck */ - /* what if resume failed on some task ? */ - } - } - } -} - -static int insert_task(struct task_struct *p, struct list_head *head, unsigned int level) -{ - if (p->in_qos) { - pr_err("[SCHED_RTG] qos apply request has cached, duplicate add\n"); - return -PID_DUPLICATE; - } - - list_add(&p->qos_list, head); - p->in_qos = level; - - return 0; -} - -static int remove_task(struct task_struct *p) -{ - if (!p->in_qos) { - pr_err("[SCHED_RTG] qos apply request not cached, stop failed\n"); - return -PID_NOT_EXIST; - } - - list_del_init(&p->qos_list); - p->in_qos = 0; - - return 0; -} - -int qos_apply(struct rtg_qos_data *data) -{ - unsigned int level = data->level; - struct rtg_authority *auth; - int ret; - - if (level > NR_QOS || level == 0) { - pr_err("[SCHED_RTG] no this qos level, qos apply failed\n"); - ret = -INVALID_ARG; - goto out; - } - - auth = get_authority(NULL); - if (!auth) { - pr_err("[SCHED_RTG] no auth data for pid=%d(%s) this uid=%d, qos apply failed\n", - current->pid, current->comm, current->cred->uid.val); - return -UID_NOT_FOUND; - } - - raw_spin_lock(&auth->auth_lock); - if (auth->status == AUTH_STATUS_DEAD) { - pr_err("[SCHED_RTG] this auth data has been deleted\n"); - ret = -INVALID_AUTH; - goto out_unlock; - } - - if (auth->num[level] >= RTG_QOS_NUM_MAX) { - pr_notice("[SCHED_RTG] qos num exceeds limit, cached only\n"); - ret = 0; - goto out_unlock; - } - - ret = insert_task(current, &auth->tasks[level], level); - if (ret < 0) - goto out_unlock; - - ++auth->num[level]; - - if (auth->status == AUTH_STATUS_ENABLE) { - switch (level) { - case 5: - /* add_to_rtg_nocheck*/ - break; - case 4: - /* add_to_latency_nice */ - break; - default: - break; - } - } - - ret = 0; - -out_unlock: - raw_spin_unlock(&auth->auth_lock); - put_rtg_auth(auth); -out: - return ret; -} - -int qos_leave(struct rtg_qos_data *data) -{ - unsigned int level; - struct rtg_authority *auth; - int ret; - - auth = get_authority(NULL); - if (!auth) { - pr_err("[SCHED_RTG] no auth data for pid=%d(%s) this uid=%d, qos stop failed\n", - current->pid, current->comm, current->cred->uid.val); - ret = -UID_NOT_FOUND; - } - - raw_spin_lock(&auth->auth_lock); - level = current->in_qos; - if (level == 0) { - pr_err("[SCHED_RTG] no this qos level, qos stop failed\n"); - ret = -INVALID_ARG; - goto out_unlock; - } - - if (auth->status == AUTH_STATUS_DEAD) { - pr_err("[SCHED_RTG] this auth data has been deleted\n"); - ret = -INVALID_AUTH; - goto out_unlock; - } - - ret = remove_task(current); - if (ret < 0) - goto out_unlock; - - --auth->num[level]; - - if (auth->status == AUTH_STATUS_ENABLE) { - switch (level) { - case 5: - /* remove_from_rtg_nocheck*/ - break; - case 4: - /* remove_latency_nice */ - break; - default: - break; - } - } - - ret = 0; - -out_unlock: - raw_spin_unlock(&auth->auth_lock); - put_rtg_auth(auth); - - return ret; -} - -void init_task_qos(struct task_struct *p) -{ - INIT_LIST_HEAD(&p->qos_list); - p->in_qos = 0; -} - -/* - * Remove statistic info in auth when task exit - */ -void sched_exit_qos_list(struct task_struct *p) -{ - struct rtg_authority *auth; - - /* - * For common tasks(the vast majority): - * skip get authority, fast return here. - * - * For qos tasks: - * If contend with auth_delete() happens, - * 1. function return here, auth_delete() will do the clean up - * 2. function go on, either no auth return, either do clean up here - * Both cases guarantee data synchronization - */ - if (likely(!p->in_qos)) - return; - - auth = get_authority(p); - if (!auth) - goto out; - - raw_spin_lock(&auth->auth_lock); - if (!p->in_qos) { - raw_spin_unlock(&auth->auth_lock); - goto out_put_auth; - } - --auth->num[p->in_qos]; - list_del_init(&p->qos_list); - p->in_qos = 0; - raw_spin_unlock(&auth->auth_lock); - -out_put_auth: - put_rtg_auth(auth); -out: - return; -} diff --git a/kernel/sched/rtg/rtg_qos.h b/kernel/sched/rtg/rtg_qos.h deleted file mode 100644 index af92efe4a861..000000000000 --- a/kernel/sched/rtg/rtg_qos.h +++ /dev/null @@ -1,37 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * rtg qos interface - * - * Copyright (c) 2022-2023 Huawei Technologies Co., Ltd. - */ - -#ifndef __RTG_QOS_H -#define __RTG_QOS_H - -#ifdef CONFIG_SCHED_RTG_QOS -#include - -enum qos_manipulate_type { - QOS_APPLY = 1, - QOS_LEAVE, - QOS_MAX_NR, -}; - -#define NR_QOS 5 -#define RTG_QOS_NUM_MAX 10 - -struct rtg_authority; - -int qos_apply(struct rtg_qos_data *data); -int qos_leave(struct rtg_qos_data *data); - -void qos_pause(struct rtg_authority *auth); -void qos_resume(struct rtg_authority *auth); - -void init_task_qos(struct task_struct *p); -void sched_exit_qos_list(struct task_struct *p); - -typedef int (*rtg_qos_manipulate_func)(struct rtg_qos_data *data); -#endif - -#endif /* __RTG_QOS_H */ diff --git a/kernel/sched/walt.c b/kernel/sched/walt.c index 6aa9267055d6..0f42120463ef 100644 --- a/kernel/sched/walt.c +++ b/kernel/sched/walt.c @@ -25,7 +25,6 @@ #include "walt.h" #include "core_ctl.h" #include "rtg/rtg.h" -#include "rtg/rtg_qos.h" #define CREATE_TRACE_POINTS #include #undef CREATE_TRACE_POINTS @@ -1238,9 +1237,6 @@ void init_new_task_load(struct task_struct *p) #ifdef CONFIG_SCHED_RTG init_task_rtg(p); #endif -#ifdef CONFIG_SCHED_RTG_QOS - init_task_qos(p); -#endif p->last_sleep_ts = 0; p->init_load_pct = 0; -- Gitee From 85b4d97efa6543f168921fb0547c8c6382b44c99 Mon Sep 17 00:00:00 2001 From: Ruty Dude Date: Mon, 1 Aug 2022 07:21:38 -0700 Subject: [PATCH 2/2] authority control --- drivers/Kconfig | 2 + drivers/Makefile | 1 + drivers/auth_ctl/Kconfig | 18 ++ drivers/auth_ctl/Makefile | 3 + drivers/auth_ctl/auth_ctrl.c | 543 ++++++++++++++++++++++++++++++++ drivers/auth_ctl/auth_ctrl.h | 34 ++ drivers/auth_ctl/qos_ctrl.c | 541 +++++++++++++++++++++++++++++++ drivers/auth_ctl/qos_ctrl.h | 24 ++ fs/proc/base.c | 14 + include/linux/sched.h | 5 + include/linux/sched/auth_ctrl.h | 78 +++++ include/linux/sched/qos_auth.h | 37 +++ include/linux/sched/qos_ctrl.h | 74 +++++ include/linux/sched/rtg_auth.h | 33 ++ kernel/sched/core.c | 7 +- kernel/sched/rtg/rtg_ctrl.c | 9 + 16 files changed, 1422 insertions(+), 1 deletion(-) create mode 100644 drivers/auth_ctl/Kconfig create mode 100644 drivers/auth_ctl/Makefile create mode 100644 drivers/auth_ctl/auth_ctrl.c create mode 100644 drivers/auth_ctl/auth_ctrl.h create mode 100644 drivers/auth_ctl/qos_ctrl.c create mode 100644 drivers/auth_ctl/qos_ctrl.h create mode 100644 include/linux/sched/auth_ctrl.h create mode 100644 include/linux/sched/qos_auth.h create mode 100644 include/linux/sched/qos_ctrl.h create mode 100644 include/linux/sched/rtg_auth.h diff --git a/drivers/Kconfig b/drivers/Kconfig index 3584901f1252..7e9116ade1cb 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -242,4 +242,6 @@ source "drivers/accesstokenid/Kconfig" source "drivers/hooks/Kconfig" +source "drivers/auth_ctl/Kconfig" + endmenu diff --git a/drivers/Makefile b/drivers/Makefile index f13d70df6557..deefa22a6180 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -188,6 +188,7 @@ obj-$(CONFIG_TEE) += tee/ obj-$(CONFIG_MULTIPLEXER) += mux/ obj-$(CONFIG_UNISYS_VISORBUS) += visorbus/ obj-$(CONFIG_SIOX) += siox/ +obj-$(CONFIG_AUTHORITY_CTRL) += auth_ctl/ obj-$(CONFIG_GNSS) += gnss/ obj-$(CONFIG_INTERCONNECT) += interconnect/ obj-$(CONFIG_COUNTER) += counter/ diff --git a/drivers/auth_ctl/Kconfig b/drivers/auth_ctl/Kconfig new file mode 100644 index 000000000000..5ae3c2eb1c3b --- /dev/null +++ b/drivers/auth_ctl/Kconfig @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0 +config AUTHORITY_CTRL + bool "Authority Control for RTG & QOS" + default y + help + control access range for procces belong to specific uid. + +config RTG_AUTHORITY + bool "Authority Control for RTG" + default y + help + authority control for RTG + +config QOS_AUTHORITY + bool "Authority Control for QOS" + default y + help + authority control for QOS diff --git a/drivers/auth_ctl/Makefile b/drivers/auth_ctl/Makefile new file mode 100644 index 000000000000..ddc115c7dd05 --- /dev/null +++ b/drivers/auth_ctl/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0-only +obj-$(CONFIG_AUTHORITY_CTRL) += auth_ctrl.o +obj-$(CONFIG_QOS_AUTHORITY) += qos_ctrl.o diff --git a/drivers/auth_ctl/auth_ctrl.c b/drivers/auth_ctl/auth_ctrl.c new file mode 100644 index 000000000000..2dfbc188691c --- /dev/null +++ b/drivers/auth_ctl/auth_ctrl.c @@ -0,0 +1,543 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * auth_ctrl.c + * + * Copyright (C) 2022 Huawei Technologies Co., Ltd. All rights reserved. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "auth_ctrl.h" + +typedef long (*auth_ctrl_func)(struct file *file, void __user *arg); + +static long ctrl_auth_basic_operation(struct file *file, void __user *uarg); + +static auth_ctrl_func g_func_array[AUTH_CTRL_MAX_NR] = { + NULL, /* reserved */ + ctrl_auth_basic_operation, +}; + +/* + * uid-based authority idr table + */ +static struct idr *ua_idr; + +static DEFINE_RAW_SPINLOCK(ua_idr_lock); + +static struct auth_struct auth_super; + +static void change_to_super(struct auth_struct *auth) +{ +#ifdef CONFIG_RTG_AUTHORITY + auth->rtg_auth_flag = AF_RTG_ALL; +#endif +#ifdef CONFIG_QOS_AUTHORITY + auth->qos_auth_flag = AF_QOS_ALL; +#endif + auth->status = AUTH_STATUS_ENABLE; +} + +static void init_authority_record(struct auth_struct *auth) +{ +#ifdef CONFIG_QOS_AUTHORITY + int i; +#endif + +#ifdef CONFIG_RTG_AUTHORITY + auth->rtg_auth_flag = 0; +#endif +#ifdef CONFIG_QOS_AUTHORITY + auth->qos_auth_flag = 0; +#endif + auth->status = AUTH_STATUS_CACHED; + raw_spin_lock_init(&auth->auth_lock); + refcount_set(&auth->usage, 1); +#ifdef CONFIG_QOS_AUTHORITY + for (i = 0; i <= NR_QOS; ++i) { + INIT_LIST_HEAD(&auth->tasks[i]); + auth->num[i] = 0; + } +#endif +} + +void get_auth_struct(struct auth_struct *auth) +{ + refcount_inc(&auth->usage); +} + +static void __put_auth_struct(struct auth_struct *auth) + +{ + WARN_ON(auth->status != AUTH_STATUS_DEAD); + WARN_ON(refcount_read(&auth->usage)); + +#ifdef CONFIG_QOS_AUTHORITY + /* refcount is zero here, no contend, no lock. */ + remove_qos_tasks(auth); +#endif + kfree(auth); +} + +void put_auth_struct(struct auth_struct *auth) +{ + if (refcount_dec_and_test(&auth->usage)) + __put_auth_struct(auth); +} + +static int init_authority_control(void) +{ + int ret; + + ua_idr = kzalloc(sizeof(*ua_idr), GFP_ATOMIC); + if (ua_idr == NULL) { + pr_err("[AUTH_CTRL] auth idr init failed, no memory!\n"); + return -ENOMEM; + } + + idr_init(ua_idr); + + init_authority_record(&auth_super); + change_to_super(&auth_super); + + ret = idr_alloc(ua_idr, &auth_super, UID_FOR_SUPER, UID_FOR_SUPER + 1, GFP_ATOMIC); + if (ret != UID_FOR_SUPER) { + pr_err("[AUTH_CTRL] authority for super init failed! ret=%d\n", ret); + goto err; + } + + return 0; + +err: + idr_destroy(ua_idr); + kfree(ua_idr); + + return ret; +} + +int authority_remove_handler(int id, void *p, void *para) +{ + struct auth_struct *auth = (struct auth_struct *)p; + + raw_spin_lock(&auth->auth_lock); +#ifdef CONFIG_QOS_AUTHORITY + qos_suppress(auth, 0, true); +#endif + auth->status = AUTH_STATUS_DEAD; + raw_spin_unlock(&auth->auth_lock); + put_auth_struct(auth); + + return 0; +} + +void remove_authority_control(void) +{ + int ret; + + raw_spin_lock(&ua_idr_lock); + ret = idr_for_each(ua_idr, authority_remove_handler, NULL); + if (ret < 0) + pr_err("[AUTH_CTRL] authority item remove failed\n"); + + idr_destroy(ua_idr); + kfree(ua_idr); + + raw_spin_unlock(&ua_idr_lock); +} + +static int generic_auth_trim(unsigned int orig_flag, unsigned int constrain) +{ + return orig_flag & constrain; +} + +static inline void set_auth_flag(struct auth_ctrl_data *data, struct auth_struct *auth_to_enable) +{ +#ifdef CONFIG_RTG_AUTHORITY + auth_to_enable->rtg_auth_flag = generic_auth_trim(data->rtg_ua_flag, AF_RTG_DELEGATED); +#endif +#ifdef CONFIG_QOS_AUTHORITY + auth_to_enable->qos_auth_flag = generic_auth_trim(data->qos_ua_flag, AF_QOS_ALL); +#endif +} + +static int auth_enable(struct auth_ctrl_data *data) +{ + struct auth_struct *auth_to_enable; + unsigned int uid = data->uid; + bool enable = (data->status == AUTH_STATUS_ENABLE); + int ret; + + raw_spin_lock(&ua_idr_lock); + auth_to_enable = idr_find(ua_idr, uid); + /* auth exist, just resume the task's qos request */ + if (auth_to_enable) { + get_auth_struct(auth_to_enable); + raw_spin_unlock(&ua_idr_lock); + + raw_spin_lock(&auth_to_enable->auth_lock); + if (auth_to_enable->status == AUTH_STATUS_DEAD) { + raw_spin_unlock(&auth_to_enable->auth_lock); + put_auth_struct(auth_to_enable); + return -INVALID_AUTH; + } + + set_auth_flag(data, auth_to_enable); +#ifdef CONFIG_QOS_AUTHORITY + if (enable) + qos_resume(auth_to_enable, uid); +#endif + raw_spin_unlock(&auth_to_enable->auth_lock); + ret = 0; + put_auth_struct(auth_to_enable); + goto out; + } + + /* auth not exist, build a new auth, then insert to idr */ + auth_to_enable = kzalloc(sizeof(*auth_to_enable), GFP_ATOMIC); + if (!auth_to_enable) { + raw_spin_unlock(&ua_idr_lock); + pr_err("[AUTH_CTRL] alloc auth data failed, no memory!\n"); + ret = -ENOMEM; + goto out; + } + + init_authority_record(auth_to_enable); + + /* no one could get the auth from idr now, no need to lock */ + set_auth_flag(data, auth_to_enable); + if (enable) + auth_to_enable->status = AUTH_STATUS_ENABLE; + + ret = idr_alloc(ua_idr, auth_to_enable, uid, uid + 1, GFP_ATOMIC); + if (ret < 0) { + pr_err("[AUTH_CTRL] add auth to idr failed, no memory!\n"); + kfree(auth_to_enable); + } + + raw_spin_unlock(&ua_idr_lock); + +out: + return ret; +} + +static int auth_pause(struct auth_ctrl_data *data) +{ + struct auth_struct *auth_to_pause; + unsigned int uid = data->uid; + + raw_spin_lock(&ua_idr_lock); + auth_to_pause = idr_find(ua_idr, uid); + if (!auth_to_pause) { + raw_spin_unlock(&ua_idr_lock); + pr_err("[AUTH_CTRL] no auth data for this uid to pause=%d\n", uid); + return UID_NOT_FOUND; + } + get_auth_struct(auth_to_pause); + raw_spin_unlock(&ua_idr_lock); + + raw_spin_lock(&auth_to_pause->auth_lock); + if (auth_to_pause->status == AUTH_STATUS_DEAD) { + raw_spin_unlock(&auth_to_pause->auth_lock); + put_auth_struct(auth_to_pause); + return -INVALID_AUTH; + } +#ifdef CONFIG_QOS_AUTHORITY + qos_suppress(auth_to_pause, uid, false); +#endif + raw_spin_unlock(&auth_to_pause->auth_lock); + + put_auth_struct(auth_to_pause); + + return 0; +} + +static int auth_delete(struct auth_ctrl_data *data) +{ + struct auth_struct *auth_to_delete; + unsigned int uid = data->uid; + + raw_spin_lock(&ua_idr_lock); + auth_to_delete = (struct auth_struct *)idr_remove(ua_idr, uid); + if (!auth_to_delete) { + raw_spin_unlock(&ua_idr_lock); + pr_err("[AUTH_CTRL] no auth data for this uid=%d, delete failed\n", uid); + return -UID_NOT_FOUND; + } + raw_spin_unlock(&ua_idr_lock); + + raw_spin_lock(&auth_to_delete->auth_lock); +#ifdef CONFIG_QOS_AUTHORITY + qos_suppress(auth_to_delete, uid, true); +#endif + auth_to_delete->status = AUTH_STATUS_DEAD; + raw_spin_unlock(&auth_to_delete->auth_lock); + + put_auth_struct(auth_to_delete); + + return 0; +} + +static int auth_get(struct auth_ctrl_data *data) +{ + struct auth_struct *auth_to_get; + unsigned int uid = data->uid; + + raw_spin_lock(&ua_idr_lock); + auth_to_get = idr_find(ua_idr, uid); + if (!auth_to_get) { + raw_spin_unlock(&ua_idr_lock); + pr_err("[AUTH_CTRL] no auth data for this uid=%d to get\n", uid); + return -UID_NOT_FOUND; + } + get_auth_struct(auth_to_get); + raw_spin_unlock(&ua_idr_lock); + + raw_spin_lock(&auth_to_get->auth_lock); + if (auth_to_get->status == AUTH_STATUS_DEAD) { + raw_spin_unlock(&auth_to_get->auth_lock); + put_auth_struct(auth_to_get); + return -INVALID_AUTH; + } +#ifdef CONFIG_RTG_AUTHORITY + data->rtg_ua_flag = auth_to_get->rtg_auth_flag; +#endif +#ifdef CONFIG_QOS_AUTHORITY + data->qos_ua_flag = auth_to_get->qos_auth_flag; +#endif + data->status = auth_to_get->status; + raw_spin_unlock(&auth_to_get->auth_lock); + + put_auth_struct(auth_to_get); + + return 0; +} + +typedef int (*auth_manipulate_func)(struct auth_ctrl_data *data); + +static auth_manipulate_func auth_func_array[AUTH_MAX_NR] = { + NULL, + auth_enable, //1 + auth_pause, + auth_delete, + auth_get, +}; + +static long do_auth_manipulate(struct auth_ctrl_data *data) +{ + long ret = 0; + unsigned int type = data->type; + + if (type >= AUTH_MAX_NR) { + pr_err("[AUTH_CTRL] BASIC_AUTH_CTRL_OPERATION type not valid\n"); + return -ARG_INVALID; + } + + if (auth_func_array[type]) + ret = (long)(*auth_func_array[type])(data); + + return ret; +} + +static long ctrl_auth_basic_operation(struct file *file, void __user *uarg) +{ + struct auth_ctrl_data auth_data; + long ret; + + if (copy_from_user(&auth_data, uarg, sizeof(struct auth_ctrl_data))) { + pr_err("[AUTH_CTRL] BASIC_AUTH_CTRL_OPERATION copy data failed\n"); + return -ARG_INVALID; + } + + ret = do_auth_manipulate(&auth_data); + if (ret < 0) { + pr_err("[AUTH_CTRL] BASIC_AUTH_CTRL_OPERATION failed\n"); + return ret; + } + + if (copy_to_user(uarg, &auth_data, sizeof(struct auth_ctrl_data))) { + pr_err("[AUTH_CTRL] BASIC_AUTH_CTRL_OPERATION send data failed\n"); + return -ARG_INVALID; + } + + return 0; +} + +long auth_ctrl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + void __user *uarg = (void __user *)arg; + unsigned int func_cmd = _IOC_NR(cmd); + + if (uarg == NULL) { + pr_err("%s: invalid user uarg\n", __func__); + return -EINVAL; + } + + if (_IOC_TYPE(cmd) != AUTH_CTRL_IPC_MAGIG) { + pr_err("%s: authority ctrl magic fail, TYPE=%d\n", + __func__, _IOC_TYPE(cmd)); + return -EINVAL; + } + + if (func_cmd >= AUTH_CTRL_MAX_NR) { + pr_err("%s: authority ctrl cmd error, cmd:%d\n", + __func__, _IOC_TYPE(cmd)); + return -EINVAL; + } + + if (g_func_array[func_cmd]) + return (*g_func_array[func_cmd])(file, uarg); + + return -EINVAL; +} + +#define get_authority_flag(func_id) (1 << (func_id - 1)) + +static inline unsigned int get_true_uid(struct task_struct *p) +{ + if (!p) + return get_uid(current_user())->uid.val; + + return task_uid(p).val; +} + +/* + * Return 1000 for both SYSTEM and ROOT + * Return current's uid if p is NULL + */ +static inline unsigned int get_authority_uid(struct task_struct *p) +{ + unsigned int uid = get_true_uid(p); + + if (super_uid(uid)) + uid = UID_FOR_SUPER; + + return uid; +} + +static unsigned int auth_flag(struct auth_struct *auth, unsigned int type) +{ + switch(type) { +#ifdef CONFIG_RTG_AUTHORITY + case RTG_AUTH_FLAG: + return auth->rtg_auth_flag; +#endif +#ifdef CONFIG_QOS_AUTHORITY + case QOS_AUTH_FLAG: + return auth->qos_auth_flag; +#endif + default: + pr_err("[AUTH_CTRL] not valid auth type\n"); + return INVALIED_AUTH_FLAG; + } +} + +bool check_authorized(unsigned int func_id, unsigned int type) +{ + bool authorized = false; + struct auth_struct *auth; + unsigned int af = get_authority_flag(func_id); + unsigned int uid = get_authority_uid(NULL); + + raw_spin_lock(&ua_idr_lock); + if (!ua_idr) { + raw_spin_unlock(&ua_idr_lock); + pr_err("[AUTH_CTRL] authority idr table missed, auth failed\n"); + return authorized; + } + + auth = (struct auth_struct *)idr_find(ua_idr, uid); + if (!auth) { + raw_spin_unlock(&ua_idr_lock); + pr_err("[AUTH_CTRL] no auth data for this uid=%d\n", uid); + return authorized; + } + get_auth_struct(auth); + raw_spin_unlock(&ua_idr_lock); + + raw_spin_lock(&auth->auth_lock); + if (auth->status == AUTH_STATUS_DEAD) { + raw_spin_unlock(&auth->auth_lock); + pr_info("[AUTH_CTRL] not valied auth for uid %d\n", uid); + put_auth_struct(auth); + return authorized; + } + if (auth && (auth_flag(auth, type) & af)) + authorized = true; + + raw_spin_unlock(&auth->auth_lock); + + put_auth_struct(auth); + + return authorized; +} + +/* + * Return authority info for given task + * return current's auth if p is NULL + * recount will inc if this call return the valid auth + * make sure to call put_auth_struct before the calling end + */ +struct auth_struct *get_authority(struct task_struct *p) +{ + unsigned int uid = get_authority_uid(p); + struct auth_struct *auth; + + raw_spin_lock(&ua_idr_lock); + auth = idr_find(ua_idr, uid); + if (auth) + get_auth_struct(auth); + raw_spin_unlock(&ua_idr_lock); + + return auth; +} + +static const struct file_operations auth_ctrl_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = auth_ctrl_ioctl, + .compat_ioctl = auth_ctrl_ioctl, +}; + +static struct miscdevice auth_ctrl_device = { + .minor = MISC_DYNAMIC_MINOR, + .name = "auth_ctrl", + .fops = &auth_ctrl_fops, +}; + +static int auth_ctrl_init_module(void) +{ + int err; + + err = misc_register(&auth_ctrl_device); + if (err < 0) { + pr_err("auth_ctrl register failed\n"); + return err; + } + + pr_info("auth_ctrl init success\n"); + + BUG_ON(init_authority_control()); + + return 0; +} + +static void auth_ctrl_exit_module(void) +{ + remove_authority_control(); + misc_deregister(&auth_ctrl_device); +} + +/* module entry points */ +module_init(auth_ctrl_init_module); +module_exit(auth_ctrl_exit_module); diff --git a/drivers/auth_ctl/auth_ctrl.h b/drivers/auth_ctl/auth_ctrl.h new file mode 100644 index 000000000000..11a99b29e56f --- /dev/null +++ b/drivers/auth_ctl/auth_ctrl.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * auth_ctrl.h + * + * Copyright (C) 2022 Huawei Technologies Co., Ltd. All rights reserved. + * + */ + +#ifndef __AUTH_CTRL_H +#define __AUTH_CTRL_H + +#include +#include +#include +#include +#include + +#include + +struct auth_struct { + raw_spinlock_t auth_lock; + refcount_t usage; + unsigned int status; +#ifdef CONFIG_RTG_AUTHORITY + unsigned int rtg_auth_flag; +#endif +#ifdef CONFIG_QOS_AUTHORITY + unsigned int qos_auth_flag; + unsigned int num[NR_QOS + 1]; + struct list_head tasks[NR_QOS + 1]; +#endif +}; + +#endif /* __AUTH_CTRL_H */ diff --git a/drivers/auth_ctl/qos_ctrl.c b/drivers/auth_ctl/qos_ctrl.c new file mode 100644 index 000000000000..759aa8a3877d --- /dev/null +++ b/drivers/auth_ctl/qos_ctrl.c @@ -0,0 +1,541 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * auth_ctrl.c + * + * Copyright (C) 2022 Huawei Technologies Co., Ltd. All rights reserved. + * + */ +/* + * Pause uid-own-tasks' qos supply + * Called after get auth->auth_lock + */ +#include +#include +#include +#include +#include +#include +#include + +#include "auth_ctrl.h" +#include "qos_ctrl.h" + +typedef long (*qos_ctrl_func)(struct file *file, void __user *uarg); + +static long ctrl_qos_operation(struct file *file, void __user *uarg); +static long ctrl_qos_policy(struct file *file, void __user *uarg); + +static qos_ctrl_func g_func_array[QOS_CTRL_MAX_NR] = { + NULL, /* reserved */ + ctrl_qos_operation, + ctrl_qos_policy, +}; + +static struct qos_policy_map qos_policy_array[QOS_POLICY_MAX_NR]; + +void remove_qos_tasks(struct auth_struct *auth) +{ + int i; + struct task_struct *tmp, *next; + + for (i = 0; i <= NR_QOS; ++i) { + list_for_each_entry_safe(tmp, next, &auth->tasks[i], qos_list) { + get_task_struct(tmp); + tmp->in_qos = 0; + list_del_init(&tmp->qos_list); + put_task_struct(tmp); + } + } +} + +#ifdef CONFIG_SCHED_LATENCY_NICE +static void set_latency_nice(struct task_struct *p, int latency_nice) +{ + struct sched_attr attr; + + memset(&attr, 0, sizeof(struct sched_attr)); + attr.sched_flags |= SCHED_FLAG_LATENCY_NICE; + attr.sched_latency_nice = latency_nice; + + rcu_read_lock(); + if (likely(p)) + get_task_struct(p); + rcu_read_unlock(); + + if (likely(p)) { + pr_info("[QOS_CTRL] prev latency_prio is %d\n", p->latency_prio); + sched_setattr(p, &attr); + pr_info("[QOS_CTRL] curr latency_prio is %d\n", p->latency_prio); + put_task_struct(p); + } +} +#else +static inline void set_latency_nice(struct task_struct *p, int latency_nice) +{ +} +#endif + +static inline bool is_system(unsigned int uid) +{ + return uid == SYSTEM_UID; +} + +static void reset_task_qos(struct task_struct *p) +{ + if (!p->in_qos) + return; + + set_user_nice(p, 0); + set_latency_nice(p, 0); +} + +static void suppress_task_qos(struct task_struct *p, bool system) +{ + bool level = p->in_qos; + int nice; + int latency_nice; + + if (!level) + return; + + if (system) + return; + + nice = qos_policy_array[QOS_POLICY_BACK].levels[level].nice; + latency_nice = qos_policy_array[QOS_POLICY_BACK].levels[level].latency_nice; + + + set_user_nice(p, nice); + set_latency_nice(p, latency_nice); +} + +static void enable_task_qos(struct task_struct *p, int level, bool system) +{ + int type = system ? QOS_POLICY_SYSTEM_SERVER : QOS_POLICY_FRONT; + int nice = qos_policy_array[type].levels[level].nice; + int latency_nice = qos_policy_array[type].levels[level].latency_nice; + + set_user_nice(p, nice); + set_latency_nice(p, latency_nice); +} + +void qos_suppress(struct auth_struct *auth, unsigned int uid, bool reset) +{ + int i; + struct task_struct *task; + bool system = is_system(uid); + + if (auth->status == AUTH_STATUS_ENABLE) { + for (i = 1; i <= NR_QOS; ++i) { + list_for_each_entry(task, &auth->tasks[i], qos_list) { + if (reset) { + reset_task_qos(task); + continue; + } + suppress_task_qos(task, system); + } + } + } + + auth->status = AUTH_STATUS_CACHED; +} + +/* + * Resume uid-own-tasks' qos supply + * Called after get auth->auth_lock + */ +void qos_resume(struct auth_struct *auth, unsigned int uid) +{ + int i; + struct task_struct *task; + bool system = is_system(uid); + + if (!auth) { + pr_err("[QOS_CTRL] auth no exist, qos resume failed\n"); + return; + } + + if (auth->status == AUTH_STATUS_CACHED) { + for (i = 1; i <= NR_QOS; ++i) { + list_for_each_entry(task, &auth->tasks[i], qos_list) { + enable_task_qos(task, i, system); + } + } + } +} + +static int insert_task(struct task_struct *p, struct list_head *head, unsigned int level) +{ + if (p->in_qos) { + pr_err("[QOS_CTRL] qos apply request has cached, duplicate add\n"); + return -PID_DUPLICATE; + } + + list_add(&p->qos_list, head); + p->in_qos = level; + + return 0; +} + +static int remove_task(struct task_struct *p) +{ + if (!p->in_qos) { + pr_err("[QOS_CTRL] qos apply request not cached, stop failed\n"); + return -PID_NOT_EXIST; + } + + list_del_init(&p->qos_list); + p->in_qos = 0; + + return 0; +} + +extern struct task_struct *find_process_by_pid(pid_t pid); + +static inline bool same_uid(struct task_struct *dude, struct task_struct *bro) +{ + return dude->cred->uid.val == bro->cred->uid.val; +} + +/* + * judge permission for changing other tasks' qos + */ +static bool can_change_qos(struct auth_struct *auth, struct task_struct *p) +{ + if (p != current) { + if (!(auth->qos_auth_flag & AF_QOS_GLOBAL_APPLY)) { + pr_err("[QOS_CTRL] apply for others not permit\n"); + return false; + } + + if (!same_uid(current, p) && !is_system(current->cred->uid.val)) { + pr_err("[QOS_CTRL] only system apply for other task belong other uid\n"); + return false; + } + } + + return true; +} + +int qos_apply(struct qos_ctrl_data *data) +{ + unsigned int level = data->level; + struct auth_struct *auth; + struct task_struct *p; + int pid = data->pid; + int ret; + + if (level > NR_QOS || level == 0) { + pr_err("[QOS_CTRL] no this qos level, qos apply failed\n"); + ret = -ARG_INVALID; + goto out; + } + + rcu_read_lock(); + /* p is current when pid was not assigned */ + p = find_process_by_pid((pid_t)pid); + if (unlikely(!p)) { + ret = -ESRCH; + rcu_read_unlock(); + pr_err("[QOS_CTRL] not valid pid, qos apply failed\n"); + goto out; + } + get_task_struct(p); + rcu_read_unlock(); + + auth = get_authority(p); + if (!auth) { + pr_err("[QOS_CTRL] no auth data for pid=%d(%s) this uid=%d, qos apply failed\n", + p->pid, p->comm, p->cred->uid.val); + put_task_struct(p); + return -UID_NOT_FOUND; + } + + raw_spin_lock(&auth->auth_lock); + if (auth->status == AUTH_STATUS_DEAD) { + pr_err("[QOS_CTRL] this auth data has been deleted\n"); + ret = -INVALID_AUTH; + goto out_unlock; + } + + if (!can_change_qos(auth, p)) { + ret = -ARG_INVALID; + goto out_unlock; + } + + if (auth->num[level] >= QOS_NUM_MAX) { + pr_notice("[QOS_CTRL] qos num exceeds limit, cached only\n"); + ret = 0; + goto out_unlock; + } + + ret = insert_task(p, &auth->tasks[level], level); + if (ret < 0) + goto out_unlock; + + ++auth->num[level]; + + if (auth->status == AUTH_STATUS_ENABLE) + enable_task_qos(p, level, is_system(task_uid(p).val)); + + ret = 0; + +out_unlock: + raw_spin_unlock(&auth->auth_lock); + put_auth_struct(auth); + put_task_struct(p); +out: + return ret; +} + +int qos_leave(struct qos_ctrl_data *data) +{ + unsigned int level; + struct auth_struct *auth; + struct task_struct *p; + int pid = data->pid; + int ret; + + rcu_read_lock(); + /* p is current when pid was not assigned */ + p = find_process_by_pid((pid_t)pid); + if (unlikely(!p)) { + ret = -ESRCH; + rcu_read_unlock(); + pr_err("[QOS_CTRL] not valid pid, qos leave failed\n"); + goto out; + } + get_task_struct(p); + rcu_read_unlock(); + + auth = get_authority(p); + if (!auth) { + pr_err("[QOS_CTRL] no auth data for pid=%d(%s) this uid=%d, qos stop failed\n", + p->pid, p->comm, p->cred->uid.val); + put_task_struct(p); + return -UID_NOT_FOUND; + } + + raw_spin_lock(&auth->auth_lock); + level = p->in_qos; + if (level == 0) { + pr_err("[QOS_CTRL] task not in qos list, qos stop failed\n"); + ret = -ARG_INVALID; + goto out_unlock; + } + + if (auth->status == AUTH_STATUS_DEAD) { + pr_err("[QOS_CTRL] this auth data has been deleted\n"); + ret = -INVALID_AUTH; + goto out_unlock; + } + + if (!can_change_qos(auth, p)) { + ret = -ARG_INVALID; + goto out_unlock; + } + + ret = remove_task(p); + if (ret < 0) + goto out_unlock; + + --auth->num[level]; + + if (auth->status == AUTH_STATUS_ENABLE) + reset_task_qos(p); + + ret = 0; + +out_unlock: + raw_spin_unlock(&auth->auth_lock); + put_auth_struct(auth); + put_task_struct(p); +out: + return ret; +} + +void init_task_qos(struct task_struct *p) +{ + INIT_LIST_HEAD(&p->qos_list); + p->in_qos = 0; +} + +/* + * Remove statistic info in auth when task exit + */ +void sched_exit_qos_list(struct task_struct *p) +{ + struct auth_struct *auth; + + /* + * For common tasks(the vast majority): + * skip get authority, fast return here. + * + * For qos tasks: + * If contend with auth_delete() happens, + * 1. function return here, auth_delete() will do the clean up + * 2. function go on, either no auth return, either do clean up here + * Both cases guarantee data synchronization + */ + if (likely(!p->in_qos)) + return; + + auth = get_authority(p); + if (!auth) + goto out; + + raw_spin_lock(&auth->auth_lock); + if (!p->in_qos) { + raw_spin_unlock(&auth->auth_lock); + goto out_put_auth; + } + --auth->num[p->in_qos]; + list_del_init(&p->qos_list); + p->in_qos = 0; + raw_spin_unlock(&auth->auth_lock); + +out_put_auth: + put_auth_struct(auth); +out: + return; +} + +typedef int (*qos_manipulate_func)(struct qos_ctrl_data *data); + +static qos_manipulate_func qos_func_array[QOS_MAX_NR] = { + NULL, + qos_apply, //1 + qos_leave, +}; + +static long do_qos_manipulate(struct qos_ctrl_data *data) +{ + long ret = 0; + unsigned int type = data->type; + + if (type >= QOS_MAX_NR) { + pr_err("[QOS_CTRL] CMD_ID_QOS_MANIPULATE type not valid\n"); + return -ARG_INVALID; + } + + if (qos_func_array[type]) + ret = (long)(*qos_func_array[type])(data); + + return ret; +} + +static long ctrl_qos_operation(struct file *file, void __user *uarg) +{ + struct qos_ctrl_data qos_data; + + if (copy_from_user(&qos_data, uarg, sizeof(struct qos_ctrl_data))) { + pr_err("[QOS_CTRL] CMD_ID_QOS_APPLY copy data failed\n"); + return -ARG_INVALID; + } + + return do_qos_manipulate(&qos_data); +} + +#define MIN_LATENCY_NICE 19 +#define MAX_LATENCY_NICE -20 + +static inline bool valid_qos_item(int nice, int latency_nice) +{ + return (nice >= MIN_NICE && nice <= MAX_NICE) && + (latency_nice >= MIN_LATENCY_NICE && latency_nice <= MAX_LATENCY_NICE); +} + +static inline void reset_qos_policy_map(struct qos_policy_map *map) +{ + memset(map, 0, sizeof(struct qos_policy_map)); +} + +static long do_qos_policy_change(struct qos_policy_datas *datas) +{ + long ret = 0; + int i; + int cur_nice; + int cur_latency_nice; + int type = datas->policy_type; + + if (type <= 0 || type >= QOS_POLICY_MAX_NR) { + pr_err("[QOS_CTRL] not valid qos policy type, policy change failed\n"); + goto out; + } + + for (i = 1; i <= NR_QOS; ++i) { + cur_nice = datas->policys[i].nice; + cur_latency_nice = datas->policys[i].latency_nice; + + if (!valid_qos_item(cur_nice, cur_latency_nice)) + goto err; + + qos_policy_array[type].levels[i].nice = cur_nice; + qos_policy_array[type].levels[i].latency_nice = cur_latency_nice; + } + + qos_policy_array[type].initialized = true; + + return ret; +err: + reset_qos_policy_map(&qos_policy_array[type]); +out: + return -ARG_INVALID; +} + +static long ctrl_qos_policy(struct file *file, void __user *uarg) +{ + struct qos_policy_datas policy_datas; + + if (copy_from_user(&policy_datas, uarg, sizeof(struct qos_policy_datas))) { + pr_err("[QOS_CTRL] CMD_ID_QOS_APPLY copy data failed\n"); + return -ARG_INVALID; + } + + return do_qos_policy_change(&policy_datas); +} + +static long do_qos_ctrl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + void __user *uarg = (void __user *)arg; + unsigned int func_cmd = _IOC_NR(cmd); + + if (uarg == NULL) { + pr_err("%s: invalid user uarg\n", __func__); + return -EINVAL; + } + + if (_IOC_TYPE(cmd) != QOS_CTRL_IPC_MAGIG) { + pr_err("%s: qos ctrl magic fail, TYPE=%d\n", + __func__, _IOC_TYPE(cmd)); + return -EINVAL; + } + +#ifdef CONFIG_QOS_AUTHORITY + if (!check_authorized(func_cmd, QOS_AUTH_FLAG)) { + pr_err("[QOS_CTRL] %s: uid not authorized\n", __func__); + return -UID_NOT_AUTHORIZED; + } +#endif + + if (func_cmd >= QOS_CTRL_MAX_NR) { + pr_err("%s: qos ctrl cmd error, cmd:%d\n", + __func__, _IOC_TYPE(cmd)); + return -EINVAL; + } + + if (g_func_array[func_cmd]) + return (*g_func_array[func_cmd])(file, uarg); + + return -EINVAL; +} + +long proc_qos_ctrl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + return do_qos_ctrl_ioctl(file, cmd, arg); +} + +int proc_qos_ctrl_open(struct inode *inode, struct file *filp) +{ + return 0; +} diff --git a/drivers/auth_ctl/qos_ctrl.h b/drivers/auth_ctl/qos_ctrl.h new file mode 100644 index 000000000000..2c2d0f94bda5 --- /dev/null +++ b/drivers/auth_ctl/qos_ctrl.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * qos_ctrl.h + * + * Copyright (C) 2022 Huawei Technologies Co., Ltd. All rights reserved. + * + */ + +#ifndef __QOS_CTRL_H +#define __QOS_CTRL_H + +#include + +struct qos_policy_item { + int nice; + int latency_nice; +}; + +struct qos_policy_map { + bool initialized; + struct qos_policy_item levels[NR_QOS + 1]; +}; + +#endif /* __OQS_CTRL_H */ diff --git a/fs/proc/base.c b/fs/proc/base.c index 27145778c144..2c1abb271469 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -92,6 +92,9 @@ #ifdef CONFIG_SCHED_RTG #include #endif +#ifdef CONFIG_QOS_AUTHORITY +#include +#endif #include #include #include @@ -1512,6 +1515,14 @@ static const struct file_operations proc_rtg_operations = { }; #endif +#ifdef CONFIG_QOS_AUTHORITY +static const struct file_operations proc_qos_ctrl_operations = { + .open = proc_qos_ctrl_open, + .unlocked_ioctl = proc_qos_ctrl_ioctl, +}; +#endif + + #ifdef CONFIG_SCHED_RTG_DEBUG static int sched_group_id_show(struct seq_file *m, void *v) { @@ -3794,6 +3805,9 @@ static const struct pid_entry tid_base_stuff[] = { #ifdef CONFIG_SCHED_RTG_DEBUG REG("sched_group_id", S_IRUGO|S_IWUGO, proc_pid_sched_group_id_operations), #endif +#ifdef CONFIG_QOS_AUTHORITY + REG("sched_qos_ctrl", S_IRUGO|S_IWUGO, proc_qos_ctrl_operations), +#endif }; static int proc_tid_base_readdir(struct file *file, struct dir_context *ctx) diff --git a/include/linux/sched.h b/include/linux/sched.h index 6db123826eb9..efb735ddcde5 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -824,6 +824,11 @@ struct task_struct { struct list_head grp_list; #endif +#ifdef CONFIG_QOS_AUTHORITY + struct list_head qos_list; + int in_qos; +#endif + #ifdef CONFIG_CGROUP_SCHED struct task_group *sched_task_group; #endif diff --git a/include/linux/sched/auth_ctrl.h b/include/linux/sched/auth_ctrl.h new file mode 100644 index 000000000000..4f78b89536e7 --- /dev/null +++ b/include/linux/sched/auth_ctrl.h @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * authority control interface + * + * Copyright (c) 2022-2023 Huawei Technologies Co., Ltd. + */ + +#ifndef _AUTH_CTRL_H +#define _AUTH_CTRL_H + +#include + +#define ROOT_UID 0 +#define SYSTEM_UID 1000 + +#define UID_FOR_SUPER SYSTEM_UID +#define super_uid(uid) (uid == ROOT_UID || uid == SYSTEM_UID) + +enum auth_ctrl_cmdid { + BASIC_AUTH_CTRL = 1, + AUTH_CTRL_MAX_NR +}; + +#define AUTH_CTRL_IPC_MAGIG 0xCD + +#define BASIC_AUTH_CTRL_OPERATION \ + _IOWR(AUTH_CTRL_IPC_MAGIG, BASIC_AUTH_CTRL, struct auth_ctrl_data) + +enum auth_flag_type { + PLACE_HOLDER, +#ifdef CONFIG_RTG_AUTHORITY + RTG_AUTH_FLAG, +#endif +#ifdef CONFIG_QOS_AUTHORITY + QOS_AUTH_FLAG, +#endif +}; + +#define INVALIED_AUTH_FLAG 0x00000000 + +struct auth_ctrl_data { + unsigned int uid; + unsigned int type; + unsigned int rtg_ua_flag; + unsigned int qos_ua_flag; + unsigned int status; +}; + +enum auth_err_no { + ARG_INVALID, + UID_NOT_AUTHORIZED, + UID_NOT_FOUND, + PID_DUPLICATE, + PID_NOT_EXIST, + INVALID_AUTH, +}; + +enum auth_manipulate_type { + AUTH_ENABLE = 1, + AUTH_PAUSE, + AUTH_DELETE, + AUTH_GET, + AUTH_MAX_NR, +}; + +enum auth_status { + AUTH_STATUS_CACHED = 0, + AUTH_STATUS_ENABLE, + AUTH_STATUS_DEAD, +}; + +struct auth_struct; +long auth_ctrl_ioctl(struct file *file, unsigned int cmd, unsigned long arg); +void get_auth_struct(struct auth_struct *auth); +void put_auth_struct(struct auth_struct *auth); +struct auth_struct *get_authority(struct task_struct *p); + +#endif /* _AUTH_CTRL_H */ diff --git a/include/linux/sched/qos_auth.h b/include/linux/sched/qos_auth.h new file mode 100644 index 000000000000..a3ac3dc85f34 --- /dev/null +++ b/include/linux/sched/qos_auth.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * rtg authority interface + * + * Copyright (c) 2022-2023 Huawei Technologies Co., Ltd. + */ + +#ifndef _QOS_AUTH_H +#define _QOS_AUTH_H + +#include +#include + +/* + * apply QOS for other thread + */ +#define AF_QOS_GLOBAL_APPLY 0X80000000 + +/* + * QOS authority flags for SYSTEM or ROOT + * + * keep sync with qos_ctrl_cmdid + * when add a new cmd to qos_ctrl_cmdid + * keep new_flag = ((old_flag << 1) + 1 & AF_QOS_GLOBAL_APPLY) + * up to now, next flag value is 0x80000007 + */ +#define AF_QOS_ALL 0x80000003 + +/* + * delegated authority for normal uid + * trim access range for QOS + */ +#define AF_QOS_DELEGATED 0x80000001 + +bool check_authorized(unsigned int func_id, unsigned int type); + +#endif /* _QOS_AUTH_H */ diff --git a/include/linux/sched/qos_ctrl.h b/include/linux/sched/qos_ctrl.h new file mode 100644 index 000000000000..6c91ac3b9c89 --- /dev/null +++ b/include/linux/sched/qos_ctrl.h @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * qos ctrl interface + * + * Copyright (c) 2022-2023 Huawei Technologies Co., Ltd. + */ + +#ifndef _QOS_CTRL_H +#define _QOS_CTRL_H + +#include +#include + +enum qos_ctrl_cmdid { + QOS_CTRL = 1, + QOS_POLICY, + QOS_CTRL_MAX_NR +}; + +#define QOS_CTRL_IPC_MAGIG 0xCC + +#define QOS_CTRL_BASIC_OPERATION \ + _IOWR(QOS_CTRL_IPC_MAGIG, QOS_CTRL, struct qos_ctrl_data) +#define QOS_CTRL_POLICY_OPERATION \ + _IOWR(QOS_CTRL_IPC_MAGIG, QOS_POLICY, struct qos_policy_datas) + +#define NR_QOS 5 +#define QOS_NUM_MAX 10 + +enum qos_manipulate_type { + QOS_APPLY = 1, + QOS_LEAVE, + QOS_MAX_NR, +}; + +enum qos_policy_type { + QOS_POLICY_SYSTEM_SERVER = 1, + QOS_POLICY_FRONT, + QOS_POLICY_BACK, + QOS_POLICY_MAX_NR, +}; + +struct qos_ctrl_data { + int pid; + unsigned int type; + unsigned int level; +}; + +struct qos_policy_data { + int nice; + int latency_nice; +}; + +struct qos_policy_datas { + int policy_type; + struct qos_policy_data policys[NR_QOS + 1]; +}; + +struct auth_struct; + +int qos_apply(struct qos_ctrl_data *data); +int qos_leave(struct qos_ctrl_data *data); + +void qos_suppress(struct auth_struct *auth, unsigned int uid, bool reset); +void qos_resume(struct auth_struct *auth, unsigned int uid); + +void init_task_qos(struct task_struct *p); +void sched_exit_qos_list(struct task_struct *p); +void remove_qos_tasks(struct auth_struct *auth); + +long proc_qos_ctrl_ioctl(struct file *file, unsigned int cmd, unsigned long arg); +int proc_qos_ctrl_open(struct inode *inode, struct file *filp); + +#endif /* _QOS_CTRL_H */ diff --git a/include/linux/sched/rtg_auth.h b/include/linux/sched/rtg_auth.h new file mode 100644 index 000000000000..5e81ef899f46 --- /dev/null +++ b/include/linux/sched/rtg_auth.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * rtg authority interface + * + * Copyright (c) 2022-2023 Huawei Technologies Co., Ltd. + */ + +#ifndef _RTG_AUTH_H +#define _RTG_AUTH_H + +#include +#include + +/* + * RTG authority flags for SYSTEM or ROOT + * + * keep sync with rtg_sched_cmdid + * when add a new cmd to rtg_sched_cmdid + * keep new_flag = (old_flag << 1) + 1 + * up to now, next flag value is 0x3fff + */ +#define AF_RTG_ALL 0x1fff + +/* + * delegated authority for normal uid + * trim access range for RTG + */ +#define AF_RTG_DELEGATED 0x1fff + +bool check_authorized(unsigned int func_id, unsigned int type); + +#endif /* _RTG_AUTH_H */ + diff --git a/kernel/sched/core.c b/kernel/sched/core.c index f9cc6b8adb4f..39330a9f2396 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -5344,7 +5345,7 @@ struct task_struct *idle_task(int cpu) * * The task of @pid, if found. %NULL otherwise. */ -static struct task_struct *find_process_by_pid(pid_t pid) +struct task_struct *find_process_by_pid(pid_t pid) { return pid ? find_task_by_vpid(pid) : current; } @@ -9172,6 +9173,10 @@ void sched_exit(struct task_struct *p) sched_set_group_id(p, 0); #endif +#ifdef CONFIG_QOS_AUTHORITY + sched_exit_qos_list(p); +#endif + rq = task_rq_lock(p, &rf); /* rq->curr == p */ diff --git a/kernel/sched/rtg/rtg_ctrl.c b/kernel/sched/rtg/rtg_ctrl.c index d49e02899495..4ae36e5c914b 100644 --- a/kernel/sched/rtg/rtg_ctrl.c +++ b/kernel/sched/rtg/rtg_ctrl.c @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include atomic_t g_rtg_enable = ATOMIC_INIT(0); @@ -894,6 +896,13 @@ static long do_proc_rtg_ioctl(int abi, struct file *file, unsigned int cmd, unsi return -INVALID_MAGIC; } +#ifdef CONFIG_RTG_AUTHORITY + if (!check_authorized(func_id, RTG_AUTH_FLAG)) { + pr_err("[SCHED_RTG] %s: uid not authorized\n", __func__); + return -UID_NOT_AUTHORIZED; + } +#endif + if (!atomic_read(&g_rtg_enable) && (func_id != SET_ENABLE) && (func_id != GET_ENABLE)) { pr_err("[SCHED_RTG] CMD_ID %x error: Rtg not enabled yet.\n", cmd); return -RTG_DISABLED; -- Gitee