• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 Huawei Technologies Co., Ltd.
3  * Decription: cmdmonitor function, monitor every cmd which is sent to TEE.
4  *
5  * This software is licensed under the terms of the GNU General Public
6  * License version 2, as published by the Free Software Foundation, and
7  * may be copied, distributed, and modified under those terms.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  */
14 #include "cmdmonitor.h"
15 #include <linux/workqueue.h>
16 #include <linux/kthread.h>
17 #include <linux/list.h>
18 #include <linux/sched.h>
19 #include <linux/pid.h>
20 #include <linux/delay.h>
21 #include <linux/mutex.h>
22 #include <linux/timer.h>
23 #include <linux/kernel.h>
24 #include <linux/version.h>
25 #include <securec.h>
26 #if (KERNEL_VERSION(4, 14, 0) <= LINUX_VERSION_CODE)
27 #include <linux/sched/task.h>
28 #endif
29 
30 #ifdef CONFIG_TEE_LOG_EXCEPTION
31 #include <huawei_platform/log/imonitor.h>
32 #define IMONITOR_TA_CRASH_EVENT_ID 901002003
33 #define IMONITOR_MEMSTAT_EVENT_ID 940007001
34 #define IMONITOR_TAMEMSTAT_EVENT_ID 940007002
35 #endif
36 
37 #include "tc_ns_log.h"
38 #include "smc_smp.h"
39 #include "internal_functions.h"
40 #include "mailbox_mempool.h"
41 #include "tlogger.h"
42 #include "log_cfg_api.h"
43 #include "tui.h"
44 
45 static int g_cmd_need_archivelog;
46 static LIST_HEAD(g_cmd_monitor_list);
47 static int g_cmd_monitor_list_size;
48 /* report 2 hours */
49 static const long long g_memstat_report_freq = 2 * 60 * 60 * 1000;
50 #define MAX_CMD_MONITOR_LIST 200
51 #define MAX_AGENT_CALL_COUNT 5000
52 static DEFINE_MUTEX(g_cmd_monitor_lock);
53 
54 /* independent wq to avoid block system_wq */
55 static struct workqueue_struct *g_cmd_monitor_wq;
56 static struct delayed_work g_cmd_monitor_work;
57 static struct delayed_work g_cmd_monitor_work_archive;
58 static struct delayed_work g_mem_stat;
59 static int g_tee_detect_ta_crash;
60 static struct tc_uuid g_crashed_ta_uuid;
61 
get_time_spec(struct time_spec * time)62 void get_time_spec(struct time_spec *time)
63 {
64 	if (!time)
65 		return;
66 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0))
67 	time->ts = current_kernel_time();
68 #else
69 	ktime_get_coarse_ts64(&time->ts);
70 #endif
71 }
72 
schedule_memstat_work(struct delayed_work * work,unsigned long delay)73 static void schedule_memstat_work(struct delayed_work *work,
74 	unsigned long delay)
75 {
76 	schedule_delayed_work(work, delay);
77 }
78 
schedule_cmd_monitor_work(struct delayed_work * work,unsigned long delay)79 static void schedule_cmd_monitor_work(struct delayed_work *work,
80 	unsigned long delay)
81 {
82 	if (g_cmd_monitor_wq)
83 		queue_delayed_work(g_cmd_monitor_wq, work, delay);
84 	else
85 		schedule_delayed_work(work, delay);
86 }
87 
tzdebug_memstat(void)88 void tzdebug_memstat(void)
89 {
90 	schedule_memstat_work(&g_mem_stat, usecs_to_jiffies(S_TO_MS));
91 }
92 
tzdebug_archivelog(void)93 void tzdebug_archivelog(void)
94 {
95 	schedule_cmd_monitor_work(&g_cmd_monitor_work_archive,
96 		usecs_to_jiffies(0));
97 }
98 
cmd_monitor_ta_crash(int32_t type,const uint8_t * ta_uuid,uint32_t uuid_len)99 void cmd_monitor_ta_crash(int32_t type, const uint8_t *ta_uuid, uint32_t uuid_len)
100 {
101 	g_tee_detect_ta_crash = type;
102 	if (g_tee_detect_ta_crash != TYPE_CRASH_TEE &&
103 		ta_uuid != NULL && uuid_len == sizeof(struct tc_uuid))
104 		(void)memcpy_s(&g_crashed_ta_uuid, sizeof(g_crashed_ta_uuid),
105 			ta_uuid, uuid_len);
106 	tzdebug_archivelog();
107 	fault_monitor_start(type);
108 }
109 
get_pid_name(pid_t pid,char * comm,size_t size)110 static int get_pid_name(pid_t pid, char *comm, size_t size)
111 {
112 	struct task_struct *task = NULL;
113 	int sret;
114 
115 	if (size <= TASK_COMM_LEN - 1 || !comm)
116 		return -1;
117 
118 	rcu_read_lock();
119 
120 #ifndef CONFIG_TZDRIVER_MODULE
121 	task = find_task_by_vpid(pid);
122 #else
123 	task = pid_task(find_vpid(pid), PIDTYPE_PID);
124 #endif
125 	if (task)
126 		get_task_struct(task);
127 	rcu_read_unlock();
128 	if (!task) {
129 		tloge("get task failed\n");
130 		return -1;
131 	}
132 
133 	sret = strncpy_s(comm, size, task->comm, strlen(task->comm));
134 	if (sret != 0)
135 		tloge("strncpy failed: errno = %d\n", sret);
136 	put_task_struct(task);
137 
138 	return sret;
139 }
140 
is_thread_reported(pid_t tid)141 bool is_thread_reported(pid_t tid)
142 {
143 	bool ret = false;
144 	struct cmd_monitor *monitor = NULL;
145 
146 	mutex_lock(&g_cmd_monitor_lock);
147 	list_for_each_entry(monitor, &g_cmd_monitor_list, list) {
148 		if (monitor->tid == tid && !is_tui_in_use(monitor->tid)) {
149 			ret = (monitor->is_reported ||
150 				monitor->agent_call_count >
151 				MAX_AGENT_CALL_COUNT);
152 			break;
153 		}
154 	}
155 	mutex_unlock(&g_cmd_monitor_lock);
156 	return ret;
157 }
158 
159 #ifdef CONFIG_TEE_LOG_EXCEPTION
160 #define FAIL_RET (-1)
161 #define SUCC_RET 0
162 
send_memstat_packet(const struct tee_mem * meminfo)163 static int send_memstat_packet(const struct tee_mem *meminfo)
164 {
165 	struct imonitor_eventobj *memstat = NULL;
166 	uint32_t result = 0;
167 	struct time_spec nowtime;
168 	int ret;
169 	get_time_spec(&nowtime);
170 
171 	memstat = imonitor_create_eventobj(IMONITOR_MEMSTAT_EVENT_ID);
172 	if (!memstat) {
173 		tloge("create eventobj failed\n");
174 		return FAIL_RET;
175 	}
176 
177 	result |= (uint32_t)imonitor_set_param_integer_v2(memstat, "totalmem", meminfo->total_mem);
178 	result |= (uint32_t)imonitor_set_param_integer_v2(memstat, "mem", meminfo->pmem);
179 	result |= (uint32_t)imonitor_set_param_integer_v2(memstat, "freemem", meminfo->free_mem);
180 	result |= (uint32_t)imonitor_set_param_integer_v2(memstat, "freememmin", meminfo->free_mem_min);
181 	result |= (uint32_t)imonitor_set_param_integer_v2(memstat, "tanum", meminfo->ta_num);
182 	result |= (uint32_t)imonitor_set_time(memstat, nowtime.ts.tv_sec);
183 	if (result) {
184 		tloge("set param integer1 failed ret=%u\n", result);
185 		imonitor_destroy_eventobj(memstat);
186 		return FAIL_RET;
187 	}
188 
189 	ret = imonitor_send_event(memstat);
190 	imonitor_destroy_eventobj(memstat);
191 	if (ret <= 0) {
192 		tloge("imonitor send memstat packet failed\n");
193 		return FAIL_RET;
194 	}
195 	return SUCC_RET;
196 }
197 
report_imonitor(const struct tee_mem * meminfo)198 void report_imonitor(const struct tee_mem *meminfo)
199 {
200 	int ret;
201 	uint32_t result = 0;
202 	uint32_t i;
203 	struct imonitor_eventobj *pamemobj = NULL;
204 	struct time_spec nowtime;
205 	get_time_spec(&nowtime);
206 
207 	if (!meminfo)
208 		return;
209 
210 	if (meminfo->ta_num > MEMINFO_TA_MAX)
211 		return;
212 
213 	if (send_memstat_packet(meminfo))
214 		return;
215 
216 	for (i = 0; i < meminfo->ta_num; i++) {
217 		pamemobj = imonitor_create_eventobj(IMONITOR_TAMEMSTAT_EVENT_ID);
218 		if (!pamemobj) {
219 			tloge("create obj failed\n");
220 			break;
221 		}
222 
223 		result |= (uint32_t)imonitor_set_param_string_v2(pamemobj, "NAME", meminfo->ta_mem_info[i].ta_name);
224 		result |= (uint32_t)imonitor_set_param_integer_v2(pamemobj, "MEM", meminfo->ta_mem_info[i].pmem);
225 		result |= (uint32_t)imonitor_set_param_integer_v2(pamemobj, "MEMMAX", meminfo->ta_mem_info[i].pmem_max);
226 		result |= (uint32_t)imonitor_set_param_integer_v2(pamemobj, "MEMLIMIT", meminfo->ta_mem_info[i].pmem_limit);
227 		result |= (uint32_t)imonitor_set_time(pamemobj, nowtime.ts.tv_sec);
228 		if (result) {
229 			tloge("set param integer2 failed ret=%d\n", result);
230 			imonitor_destroy_eventobj(pamemobj);
231 			return;
232 		}
233 		ret = imonitor_send_event(pamemobj);
234 		imonitor_destroy_eventobj(pamemobj);
235 		if (ret <= 0) {
236 			tloge("imonitor send pamem packet failed\n");
237 			break;
238 		}
239 	}
240 }
241 #endif
242 
memstat_report(void)243 static void memstat_report(void)
244 {
245 	int ret;
246 	struct tee_mem *meminfo = NULL;
247 
248 	meminfo = mailbox_alloc(sizeof(*meminfo), MB_FLAG_ZERO);
249 	if (!meminfo) {
250 		tloge("mailbox alloc failed\n");
251 		return;
252 	}
253 
254 	ret = get_tee_meminfo(meminfo);
255 #ifdef CONFIG_TEE_LOG_EXCEPTION
256 	if (ret == 0) {
257 		tlogd("report imonitor\n");
258 		report_imonitor(meminfo);
259 	}
260 #endif
261 	if (ret != 0)
262 		tlogd("get meminfo failed\n");
263 
264 	mailbox_free(meminfo);
265 }
266 
memstat_work(struct work_struct * work)267 static void memstat_work(struct work_struct *work)
268 {
269 	(void)(work);
270 	memstat_report();
271 }
272 
cmd_monitor_reset_context(void)273 void cmd_monitor_reset_context(void)
274 {
275 	struct cmd_monitor *monitor = NULL;
276 	pid_t pid = current->tgid;
277 	pid_t tid = current->pid;
278 
279 	mutex_lock(&g_cmd_monitor_lock);
280 	list_for_each_entry(monitor, &g_cmd_monitor_list, list) {
281 		if (monitor->pid == pid && monitor->tid == tid) {
282 			get_time_spec(&monitor->sendtime);
283 			if (monitor->agent_call_count + 1 < 0)
284 				tloge("agent call count add overflow\n");
285 			else
286 				monitor->agent_call_count++;
287 			break;
288 		}
289 	}
290 	mutex_unlock(&g_cmd_monitor_lock);
291 }
292 
293 #ifdef CONFIG_TEE_LOG_EXCEPTION
294 static struct time_spec g_memstat_check_time;
295 static bool g_after_loader = false;
296 
auto_report_memstat(void)297 static void auto_report_memstat(void)
298 {
299 	long long timedif;
300 	struct time_spec nowtime;
301 	get_time_spec(&nowtime);
302 
303 	/*
304 	 * get time value D (timedif=nowtime-sendtime),
305 	 * we do not care about overflow
306 	 * 1 year means 1000 * (60*60*24*365) = 0x757B12C00
307 	 * only 5bytes, will not overflow
308 	 */
309 	timedif = S_TO_MS * (nowtime.ts.tv_sec - g_memstat_check_time.ts.tv_sec) +
310 		(nowtime.ts.tv_nsec - g_memstat_check_time.ts.tv_nsec) / S_TO_US;
311 	if (timedif > g_memstat_report_freq && g_after_loader) {
312 		tlogi("cmdmonitor auto report memstat\n");
313 		memstat_report();
314 		g_memstat_check_time = nowtime;
315 	}
316 
317 	if (!g_after_loader) {
318 		g_memstat_check_time = nowtime;
319 		g_after_loader = true;
320 	}
321 }
322 #endif
323 
324 /*
325  * if one session timeout, monitor will print timedifs every step[n] in seconds,
326  * if lasted more then 360s, monitor will print timedifs every 360s.
327  */
328 const int32_t g_timer_step[] = {1, 1, 1, 2, 5, 10, 40, 120, 180, 360};
329 const int32_t g_timer_nums = sizeof(g_timer_step) / sizeof(int32_t);
show_timeout_cmd_info(struct cmd_monitor * monitor)330 static void show_timeout_cmd_info(struct cmd_monitor *monitor)
331 {
332 	long long timedif, timedif2;
333 	struct time_spec nowtime;
334 	int32_t time_in_sec;
335 	get_time_spec(&nowtime);
336 
337 	/*
338 	 * 1 year means 1000 * (60*60*24*365) = 0x757B12C00
339 	 * only 5bytes, so timedif (timedif=nowtime-sendtime) will not overflow
340 	 */
341 	timedif = S_TO_MS * (nowtime.ts.tv_sec - monitor->sendtime.ts.tv_sec) +
342 		(nowtime.ts.tv_nsec - monitor->sendtime.ts.tv_nsec) / S_TO_US;
343 
344 	/* timeout to 10s, we log the teeos log, and report */
345 	if ((timedif > CMD_MAX_EXECUTE_TIME * S_TO_MS) && (!monitor->is_reported)) {
346 		monitor->is_reported = true;
347 		tloge("[cmd_monitor_tick] pid=%d,pname=%s,tid=%d, "
348 			"tname=%s, lastcmdid=%u, agent call count:%d, "
349 			"running with timedif=%lld ms and report\n",
350 			monitor->pid, monitor->pname, monitor->tid,
351 			monitor->tname, monitor->lastcmdid,
352 			monitor->agent_call_count, timedif);
353 		/* threads out of white table need info dump */
354 		tloge("monitor: pid-%d", monitor->pid);
355 		if (!is_tui_in_use(monitor->tid)) {
356 			show_cmd_bitmap();
357 			g_cmd_need_archivelog = 1;
358 			wakeup_tc_siq(SIQ_DUMP_TIMEOUT);
359 		}
360 	}
361 
362 	timedif2 = S_TO_MS * (nowtime.ts.tv_sec - monitor->lasttime.ts.tv_sec) +
363 		(nowtime.ts.tv_nsec - monitor->lasttime.ts.tv_nsec) / S_TO_US;
364 	time_in_sec = monitor->timer_index >= g_timer_nums ?
365 		g_timer_step[g_timer_nums - 1] : g_timer_step[monitor->timer_index];
366 	if (timedif2 > time_in_sec * S_TO_MS) {
367 		monitor->lasttime = nowtime;
368 		monitor->timer_index = monitor->timer_index >= (int32_t)sizeof(g_timer_step) ?
369 			(int32_t)sizeof(g_timer_step) : (monitor->timer_index + 1);
370 		tlogi("[cmd_monitor_tick] pid=%d,pname=%s,tid=%d, "
371 			"lastcmdid=%u,agent call count:%d,timedif=%lld ms\n",
372 			monitor->pid, monitor->pname, monitor->tid,
373 			monitor->lastcmdid, monitor->agent_call_count,
374 			timedif);
375 	}
376 }
377 
cmd_monitor_tick(void)378 static void cmd_monitor_tick(void)
379 {
380 	struct cmd_monitor *monitor = NULL;
381 	struct cmd_monitor *tmp = NULL;
382 
383 	mutex_lock(&g_cmd_monitor_lock);
384 	list_for_each_entry_safe(monitor, tmp, &g_cmd_monitor_list, list) {
385 		if (monitor->returned) {
386 			g_cmd_monitor_list_size--;
387 			tlogd("[cmd_monitor_tick] pid=%d,pname=%s,tid=%d, "
388 				"tname=%s,lastcmdid=%u,count=%d,agent call count=%d, "
389 				"timetotal=%lld us returned, remained command(s)=%d\n",
390 				monitor->pid, monitor->pname, monitor->tid, monitor->tname,
391 				monitor->lastcmdid, monitor->count, monitor->agent_call_count,
392 				monitor->timetotal, g_cmd_monitor_list_size);
393 			list_del(&monitor->list);
394 			kfree(monitor);
395 			continue;
396 		}
397 		show_timeout_cmd_info(monitor);
398 	}
399 
400 	/* if have cmd in monitor list, we need tick */
401 	if (g_cmd_monitor_list_size > 0)
402 		schedule_cmd_monitor_work(&g_cmd_monitor_work, usecs_to_jiffies(S_TO_US));
403 	mutex_unlock(&g_cmd_monitor_lock);
404 #ifdef CONFIG_TEE_LOG_EXCEPTION
405 	auto_report_memstat();
406 #endif
407 }
408 
cmd_monitor_tickfn(struct work_struct * work)409 static void cmd_monitor_tickfn(struct work_struct *work)
410 {
411 	(void)(work);
412 	cmd_monitor_tick();
413 	/* check tlogcat if have new log */
414 	tz_log_write();
415 }
416 
417 #define MAX_CRASH_INFO_LEN 100
cmd_monitor_archivefn(struct work_struct * work)418 static void cmd_monitor_archivefn(struct work_struct *work)
419 {
420 	(void)(work);
421 
422 	if (tlogger_store_msg(CONFIG_TEE_LOG_ACHIVE_PATH,
423 		sizeof(CONFIG_TEE_LOG_ACHIVE_PATH)) < 0)
424 		tloge("[cmd_monitor_tick]tlogger store lastmsg failed\n");
425 
426 	if (g_tee_detect_ta_crash == TYPE_CRASH_TEE) {
427 		tloge("detect teeos crash, panic\n");
428 		report_log_system_panic();
429 	} else if (g_tee_detect_ta_crash == TYPE_CRASH_TA ||
430 		g_tee_detect_ta_crash == TYPE_KILLED_TA) {
431 #ifdef CONFIG_TEE_LOG_EXCEPTION
432 		const char crash_prefix[] = "ta crash: ";
433 		const char killed_prefix[] = "ta timeout and killed: ";
434 		const char crash_info_get_failed[] = "ta crash: get uuid failed";
435 		char buffer[MAX_CRASH_INFO_LEN] = {0};
436 		const char *crash_info = buffer;
437 		int ret = snprintf_s(buffer, sizeof(buffer), sizeof(buffer) - 1,
438 							 "%s%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
439 							 (g_tee_detect_ta_crash == TYPE_CRASH_TA) ? crash_prefix : killed_prefix,
440 							 g_crashed_ta_uuid.time_low, g_crashed_ta_uuid.time_mid,
441 							 g_crashed_ta_uuid.timehi_and_version,
442 							 g_crashed_ta_uuid.clockseq_and_node[0], g_crashed_ta_uuid.clockseq_and_node[1],
443 							 g_crashed_ta_uuid.clockseq_and_node[2], g_crashed_ta_uuid.clockseq_and_node[3],
444 							 g_crashed_ta_uuid.clockseq_and_node[4], g_crashed_ta_uuid.clockseq_and_node[5],
445 							 g_crashed_ta_uuid.clockseq_and_node[6], g_crashed_ta_uuid.clockseq_and_node[7]);
446 		if (ret <= 0) {
447 			tlogw("append crash info failed\n");
448 			crash_info = crash_info_get_failed;
449 		}
450 		if (teeos_log_exception_archive(IMONITOR_TA_CRASH_EVENT_ID, crash_info) < 0)
451 			tloge("log exception archive failed\n");
452 		(void)memset_s(&g_crashed_ta_uuid, sizeof(g_crashed_ta_uuid), 0, sizeof(g_crashed_ta_uuid));
453 #endif
454 	}
455 
456 	g_tee_detect_ta_crash = 0;
457 }
458 
init_monitor_locked(void)459 static struct cmd_monitor *init_monitor_locked(void)
460 {
461 	struct cmd_monitor *newitem = NULL;
462 
463 	newitem = kzalloc(sizeof(*newitem), GFP_KERNEL);
464 	if (ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)newitem)) {
465 		tloge("[cmd_monitor_tick]kzalloc failed\n");
466 		return NULL;
467 	}
468 
469 	get_time_spec(&newitem->sendtime);
470 	newitem->lasttime = newitem->sendtime;
471 	newitem->timer_index = 0;
472 	newitem->count = 1;
473 	newitem->agent_call_count = 0;
474 	newitem->returned = false;
475 	newitem->is_reported = false;
476 	newitem->pid = current->tgid;
477 	newitem->tid = current->pid;
478 	if (get_pid_name(newitem->pid, newitem->pname,
479 		sizeof(newitem->pname)) != 0)
480 		newitem->pname[0] = '\0';
481 	if (get_pid_name(newitem->tid, newitem->tname,
482 		sizeof(newitem->tname)) != 0)
483 		newitem->tname[0] = '\0';
484 	INIT_LIST_HEAD(&newitem->list);
485 	list_add_tail(&newitem->list, &g_cmd_monitor_list);
486 	g_cmd_monitor_list_size++;
487 	return newitem;
488 }
489 
cmd_monitor_log(const struct tc_ns_smc_cmd * cmd)490 struct cmd_monitor *cmd_monitor_log(const struct tc_ns_smc_cmd *cmd)
491 {
492 	bool found_flag = false;
493 	pid_t pid;
494 	pid_t tid;
495 	struct cmd_monitor *monitor = NULL;
496 
497 	if (!cmd)
498 		return NULL;
499 
500 	pid = current->tgid;
501 	tid = current->pid;
502 	mutex_lock(&g_cmd_monitor_lock);
503 	do {
504 		list_for_each_entry(monitor, &g_cmd_monitor_list, list) {
505 			if (monitor->pid == pid && monitor->tid == tid) {
506 				found_flag = true;
507 				/* restart */
508 				get_time_spec(&monitor->sendtime);
509 				monitor->lasttime = monitor->sendtime;
510 				monitor->timer_index = 0;
511 				monitor->count++;
512 				monitor->returned = false;
513 				monitor->is_reported = false;
514 				monitor->lastcmdid = cmd->cmd_id;
515 				monitor->agent_call_count = 0;
516 				monitor->timetotal = 0;
517 				break;
518 			}
519 		}
520 
521 		if (!found_flag) {
522 #ifndef CONFIG_BIG_SESSION
523 			if (g_cmd_monitor_list_size > MAX_CMD_MONITOR_LIST - 1) {
524 				tloge("monitor reach max node num\n");
525 				monitor = NULL;
526 				break;
527 			}
528 #endif
529 			monitor = init_monitor_locked();
530 			if (!monitor) {
531 				tloge("init monitor failed\n");
532 				break;
533 			}
534 			monitor->lastcmdid = cmd->cmd_id;
535 			/* the first cmd will cause timer */
536 			if (g_cmd_monitor_list_size == 1)
537 				schedule_cmd_monitor_work(&g_cmd_monitor_work,
538 					usecs_to_jiffies(S_TO_US));
539 		}
540 	} while (0);
541 	mutex_unlock(&g_cmd_monitor_lock);
542 
543 	return monitor;
544 }
545 
cmd_monitor_logend(struct cmd_monitor * item)546 void cmd_monitor_logend(struct cmd_monitor *item)
547 {
548 	struct time_spec nowtime;
549 	long long timedif;
550 
551 	if (!item)
552 		return;
553 
554 	get_time_spec(&nowtime);
555 	/*
556 	 * get time value D (timedif=nowtime-sendtime),
557 	 * we do not care about overflow
558 	 * 1 year means 1000000 * (60*60*24*365) = 0x1CAE8C13E000
559 	 * only 6bytes, will not overflow
560 	 */
561 	timedif = S_TO_US * (nowtime.ts.tv_sec - item->sendtime.ts.tv_sec) +
562 		(nowtime.ts.tv_nsec - item->sendtime.ts.tv_nsec) / S_TO_MS;
563 	item->timetotal += timedif;
564 	item->returned = true;
565 }
566 
do_cmd_need_archivelog(void)567 void do_cmd_need_archivelog(void)
568 {
569 	if (g_cmd_need_archivelog == 1) {
570 		g_cmd_need_archivelog = 0;
571 		schedule_cmd_monitor_work(&g_cmd_monitor_work_archive,
572 			usecs_to_jiffies(S_TO_US));
573 	}
574 }
575 
init_cmd_monitor(void)576 void init_cmd_monitor(void)
577 {
578 	g_cmd_monitor_wq = alloc_workqueue("tz_cmd_monitor_wq",
579 		WQ_UNBOUND, TZ_WQ_MAX_ACTIVE);
580 	if (!g_cmd_monitor_wq)
581 		tloge("alloc cmd monitor wq failed\n");
582 	else
583 		tz_workqueue_bind_mask(g_cmd_monitor_wq, 0);
584 
585 	INIT_DEFERRABLE_WORK((struct delayed_work *)
586 		(uintptr_t)&g_cmd_monitor_work, cmd_monitor_tickfn);
587 	INIT_DEFERRABLE_WORK((struct delayed_work *)
588 		(uintptr_t)&g_cmd_monitor_work_archive, cmd_monitor_archivefn);
589 	INIT_DEFERRABLE_WORK((struct delayed_work *)
590 		(uintptr_t)&g_mem_stat, memstat_work);
591 }
592 
free_cmd_monitor(void)593 void free_cmd_monitor(void)
594 {
595 	struct cmd_monitor *monitor = NULL;
596 	struct cmd_monitor *tmp = NULL;
597 
598 	mutex_lock(&g_cmd_monitor_lock);
599 	list_for_each_entry_safe(monitor, tmp, &g_cmd_monitor_list, list) {
600 		list_del(&monitor->list);
601 		kfree(monitor);
602 	}
603 	mutex_unlock(&g_cmd_monitor_lock);
604 
605 	flush_delayed_work(&g_cmd_monitor_work);
606 	flush_delayed_work(&g_cmd_monitor_work_archive);
607 	flush_delayed_work(&g_mem_stat);
608 	if (g_cmd_monitor_wq) {
609 		flush_workqueue(g_cmd_monitor_wq);
610 		destroy_workqueue(g_cmd_monitor_wq);
611 		g_cmd_monitor_wq = NULL;
612 	}
613 }
614