1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * drivers/auth_ctl/auth_qos_debug.c
4 *
5 * Copyright (c) 2022 Huawei Device Co., Ltd.
6 *
7 */
8 #include <linux/cred.h>
9 #include <linux/mutex.h>
10 #include <linux/errno.h>
11 #include <linux/fs.h>
12 #include <linux/miscdevice.h>
13 #include <linux/module.h>
14 #include <linux/sched.h>
15 #include <linux/kernel.h>
16 #include <linux/slab.h>
17 #include <linux/proc_fs.h>
18 #include <linux/seq_file.h>
19 #include <linux/sched/auth_ctrl.h>
20 #include <linux/sched/rtg_auth.h>
21 #include <linux/sched/qos_ctrl.h>
22 #include <linux/sched/qos_auth.h>
23
24 #include "auth_ctrl.h"
25 #include "qos_ctrl.h"
26
27 #define seq_printf_auth(m, x...) \
28 do { \
29 if (m) \
30 seq_printf(m, x); \
31 else \
32 printk(x); \
33 } while (0)
34
print_auth_id(struct seq_file * file,const int tgid)35 static void print_auth_id(struct seq_file *file,
36 const int tgid)
37 {
38 seq_printf_auth(file, "AUTH_PID :%d\n", tgid);
39 }
40
print_auth_info(struct seq_file * file,const struct auth_struct * auth)41 static void print_auth_info(struct seq_file *file,
42 const struct auth_struct *auth)
43 {
44 seq_printf_auth(file, "AUTH_STATUS :%d\n", auth->status);
45 #ifdef CONFIG_RTG_AUTHORITY
46 seq_printf_auth(file, "RTG_FLAG :%04x\n", auth->rtg_auth_flag);
47 #endif
48 #ifdef CONFIG_QOS_AUTHORITY
49 seq_printf_auth(file, "QOS_FLAG :%04x\n", auth->qos_auth_flag);
50 #endif
51 }
52
print_qos_count(struct seq_file * file,const struct auth_struct * auth)53 static void print_qos_count(struct seq_file *file,
54 const struct auth_struct *auth)
55 {
56 int i;
57
58 for (i = QOS_POLICY_MIN_LEVEL; i < NR_QOS; ++i)
59 seq_printf_auth(file, "QOS level %d thread nr :%d\n", i, auth->num[i]);
60 }
61
print_qos_thread(struct seq_file * file,const struct auth_struct * auth)62 static void print_qos_thread(struct seq_file *file,
63 const struct auth_struct *auth)
64 {
65 struct qos_task_struct *tmp, *next;
66 struct task_struct *p;
67 int i;
68
69 for (i = QOS_POLICY_MIN_LEVEL; i < NR_QOS; ++i) {
70 seq_printf_auth(file, "QOS level %d threads:", i);
71 list_for_each_entry_safe(tmp, next, &auth->tasks[i], qos_list) {
72 p = container_of(tmp, struct task_struct, qts);
73 seq_printf_auth(file, "%d ", p->pid);
74 }
75 seq_printf_auth(file, "\n");
76 }
77
78 }
79
print_auth_struct(struct seq_file * file,struct auth_struct * auth)80 static inline void print_auth_struct(struct seq_file *file, struct auth_struct *auth)
81 {
82 print_auth_info(file, auth);
83 seq_printf_auth(file, "\n");
84 print_qos_count(file, auth);
85 seq_printf_auth(file, "\n");
86 #ifdef CONFIG_QOS_CTRL
87 print_qos_thread(file, auth);
88 #endif
89 seq_printf_auth(file, "---------------------------------------------------------\n");
90
91 }
92
authority_printf_handler(int id,void * p,void * para)93 int authority_printf_handler(int id, void *p, void *para)
94 {
95 struct auth_struct *auth = (struct auth_struct *)p;
96 struct seq_file *file = (struct seq_file *)para;
97
98 /*
99 * data consistency is not that important here
100 */
101 seq_printf_auth(file, "\n\n");
102 print_auth_id(file, id);
103 seq_printf_auth(file, "\n");
104
105 /* no need to add refcount here, auth must alive in ua_idr_mutex */
106 print_auth_struct(file, auth);
107
108 return 0;
109 }
110
sched_auth_debug_show(struct seq_file * file,void * param)111 static int sched_auth_debug_show(struct seq_file *file, void *param)
112 {
113 struct idr *ua_idr = get_auth_ctrl_idr();
114 struct mutex *ua_idr_mutex = get_auth_idr_mutex();
115 /*
116 * NOTICE:
117 * if mutex in authority_printf_handler, sleep may occur
118 * change ths spin_lock to mutex, or remove mutex in handler
119 */
120
121 mutex_lock(ua_idr_mutex);
122 /* will never return 0 here, auth in ua_idr must alive */
123 idr_for_each(ua_idr, authority_printf_handler, file);
124 mutex_unlock(ua_idr_mutex);
125
126 return 0;
127 }
128
sched_auth_debug_release(struct inode * inode,struct file * file)129 static int sched_auth_debug_release(struct inode *inode, struct file *file)
130 {
131 seq_release(inode, file);
132 return 0;
133 }
134
sched_auth_debug_open(struct inode * inode,struct file * filp)135 static int sched_auth_debug_open(struct inode *inode, struct file *filp)
136 {
137 return single_open(filp, sched_auth_debug_show, NULL);
138 }
139
140 static const struct proc_ops sched_auth_debug_fops = {
141 .proc_open = sched_auth_debug_open,
142 .proc_read = seq_read,
143 .proc_lseek = seq_lseek,
144 .proc_release = sched_auth_debug_release,
145 };
146
init_sched_auth_debug_procfs(void)147 int __init init_sched_auth_debug_procfs(void)
148 {
149 struct proc_dir_entry *pe = NULL;
150
151 pe = proc_create("sched_auth_qos_debug",
152 0400, NULL, &sched_auth_debug_fops);
153 if (unlikely(!pe))
154 return -ENOMEM;
155 return 0;
156 }
157
158