285 lines
7.9 KiB
C
285 lines
7.9 KiB
C
#include <linux/workqueue.h>
|
|
#include <linux/kthread.h>
|
|
#include <linux/list.h>
|
|
#include <linux/sched.h>
|
|
#include <linux/delay.h>
|
|
#include <linux/mutex.h>
|
|
#include <linux/timer.h>
|
|
#include <linux/kernel.h>
|
|
|
|
#include "tc_ns_log.h"
|
|
#include "securec.h"
|
|
#include "teek_ns_client.h"
|
|
#include "smc.h"
|
|
#ifdef CONFIG_TEELOG
|
|
#include <huawei_platform/log/imonitor.h>
|
|
#define IMONITOR_TA_CRASH_EVENT_ID (901002003)
|
|
#include "tlogger.h"
|
|
#endif
|
|
|
|
const char g_cmd_monitor_white_table[][TASK_COMM_LEN]={
|
|
{"FIAgentThread"},
|
|
{"AIAgentThread"},
|
|
#ifdef DEF_ENG
|
|
{"tee_test_ut"},
|
|
#endif
|
|
};
|
|
const uint32_t g_white_table_thread_num = sizeof(g_cmd_monitor_white_table) / TASK_COMM_LEN;
|
|
|
|
extern void wakeup_tc_siq(void);
|
|
|
|
static int cmd_need_archivelog = 0;
|
|
static LIST_HEAD(cmd_monitor_list);
|
|
static int cmd_monitor_list_size = 0;
|
|
#define MAX_CMD_MONITOR_LIST 200
|
|
static DEFINE_MUTEX(cmd_monitor_lock);
|
|
struct cmd_monitor {
|
|
struct list_head list;
|
|
struct timespec sendtime;
|
|
int count ;
|
|
bool returned;
|
|
bool isReported;
|
|
unsigned int pid;
|
|
unsigned int tid;
|
|
char pname[TASK_COMM_LEN];
|
|
char tname[TASK_COMM_LEN];
|
|
unsigned int lastcmdid;
|
|
long timetotal;
|
|
};
|
|
static struct delayed_work cmd_monitor_work;
|
|
static struct delayed_work cmd_monitor_work_archive;
|
|
static int g_tee_detect_ta_crash = 0;
|
|
enum {
|
|
TYPE_CRASH_TA = 1,
|
|
TYPE_CRASH_TEE = 2,
|
|
};
|
|
|
|
void tzdebug_archivelog(void)
|
|
{
|
|
schedule_delayed_work(&cmd_monitor_work_archive, usecs_to_jiffies(0));
|
|
}
|
|
void cmd_monitor_ta_crash(int32_t type)
|
|
{
|
|
g_tee_detect_ta_crash = ((type == TYPE_CRASH_TEE) ? TYPE_CRASH_TEE : TYPE_CRASH_TA);
|
|
tzdebug_archivelog();
|
|
}
|
|
static int get_pid_name(pid_t pid,char* comm,size_t size)
|
|
{
|
|
struct task_struct *task;
|
|
int sret;
|
|
if (size <= TASK_COMM_LEN - 1 || !comm) {
|
|
return -1;
|
|
}
|
|
rcu_read_lock();
|
|
task = find_task_by_vpid(pid);
|
|
if (task != NULL) {
|
|
get_task_struct(task);
|
|
}
|
|
rcu_read_unlock();
|
|
if (task != NULL) {
|
|
sret = strncpy_s(comm, size, task->comm, strlen(task->comm));
|
|
if (sret != 0) {
|
|
tloge("strncpy_s faild: errno = %d.\n", sret);
|
|
}
|
|
put_task_struct(task);
|
|
return sret;
|
|
}
|
|
return -1;
|
|
|
|
}
|
|
|
|
static bool is_thread_in_white_table(char *tname)
|
|
{
|
|
uint32_t i;
|
|
if (!tname)
|
|
return false;
|
|
|
|
for (i=0; i < g_white_table_thread_num; i++) {
|
|
if (!strcmp(tname, g_cmd_monitor_white_table[i])) { /*lint !e421 */
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
static void cmd_monitor_tick(void)
|
|
{
|
|
long timedif;
|
|
struct cmd_monitor *monitor = NULL;
|
|
struct cmd_monitor *tmp = NULL;
|
|
struct timespec nowtime = current_kernel_time();
|
|
mutex_lock(&cmd_monitor_lock);
|
|
list_for_each_entry_safe(monitor, tmp, &cmd_monitor_list, list) {
|
|
if (monitor->returned ==true) {
|
|
tloge("[cmd_monitor_tick] pid=%d,pname=%s,tid=%d,tname=%s,lastcmdid=%d,count=%d timetotal=%ld us returned, remained command(s)=%d\n", monitor->pid, monitor->pname, monitor->tid, monitor->tname ,monitor->lastcmdid, monitor->count, monitor->timetotal, cmd_monitor_list_size);
|
|
list_del(&monitor->list);
|
|
kfree(monitor);
|
|
cmd_monitor_list_size--;
|
|
continue;
|
|
}
|
|
/* not return, we need to check */
|
|
timedif = 1000*nowtime.tv_sec-1000*monitor->sendtime.tv_sec+nowtime.tv_nsec/1000000-monitor->sendtime.tv_nsec/1000000;
|
|
|
|
/* Temporally change timeout to 25s, we log the teeos log,and report*/
|
|
if (timedif > 25*1000 && !monitor->isReported) {
|
|
monitor->isReported = true;
|
|
/* print tee stask*/
|
|
tloge("[cmd_monitor_tick] pid=%d,pname=%s,tid=%d,tname=%s,lastcmdid=%d,timedif=%ld ms and report\n", monitor->pid, monitor->pname, monitor->tid, monitor->tname,monitor->lastcmdid, timedif);
|
|
/* threads out of white table need info dump*/
|
|
if(!(is_thread_in_white_table(monitor->tname))){
|
|
cmd_need_archivelog = 1;
|
|
wakeup_tc_siq();
|
|
}
|
|
} else if (timedif > 1*1000) {
|
|
tloge("[cmd_monitor_tick] pid=%d,pname=%s,tid=%d,timedif=%ld ms\n", monitor->pid, monitor->pname, monitor->tid, timedif);
|
|
}
|
|
}
|
|
tlogi("[cmd_monitor_tick] cmd_monitor_list_size=%d\n",cmd_monitor_list_size);
|
|
if (cmd_monitor_list_size > 0) {
|
|
/* if have cmd in monitor list, we need tick*/
|
|
schedule_delayed_work(&cmd_monitor_work, usecs_to_jiffies(1000000));
|
|
}
|
|
mutex_unlock(&cmd_monitor_lock);
|
|
}
|
|
static void cmd_monitor_tickfn(struct work_struct *work)
|
|
{
|
|
(void)(work);
|
|
cmd_monitor_tick();
|
|
|
|
/* check tlogcat if have new log */
|
|
#ifdef CONFIG_TEELOG
|
|
tz_log_write();
|
|
#endif
|
|
}
|
|
static void cmd_monitor_archivefn(struct work_struct *work)
|
|
{
|
|
(void)(work);
|
|
#ifdef CONFIG_TEELOG
|
|
if( tlogger_store_lastmsg() < 0)
|
|
tloge("[cmd_monitor_tick]tlogger_store_lastmsg failed\n");
|
|
|
|
if (g_tee_detect_ta_crash == TYPE_CRASH_TA) {
|
|
|
|
if (0 > teeos_log_exception_archive(IMONITOR_TA_CRASH_EVENT_ID, "ta crash"))
|
|
tloge("log_exception_archive failed\n");
|
|
|
|
}
|
|
|
|
g_tee_detect_ta_crash = 0;
|
|
#endif
|
|
}
|
|
|
|
|
|
static struct cmd_monitor* init_monitor_locked(void)
|
|
{
|
|
struct cmd_monitor* newitem;
|
|
int pidnameresult;
|
|
int tidnameresult;
|
|
newitem = kzalloc(sizeof(struct cmd_monitor),GFP_KERNEL);/*lint !429 !593*/
|
|
if (newitem == NULL) {
|
|
tloge("[cmd_monitor_tick]kmalloc faild\n");
|
|
return NULL;
|
|
}
|
|
newitem->sendtime = current_kernel_time();
|
|
newitem->count = 1;
|
|
newitem->returned = false;
|
|
newitem->isReported = false;
|
|
newitem->pid = current->tgid;
|
|
newitem->tid = current->pid;
|
|
pidnameresult = get_pid_name(newitem->pid, newitem->pname, sizeof(newitem->pname));
|
|
if (pidnameresult != 0) {
|
|
newitem->pname[0] = '\0';
|
|
}
|
|
tidnameresult = get_pid_name(newitem->tid, newitem->tname, sizeof(newitem->tname));
|
|
if (tidnameresult != 0) {
|
|
newitem->pname[0] = '\0';
|
|
}
|
|
INIT_LIST_HEAD(&newitem->list);
|
|
list_add_tail(&newitem->list, &cmd_monitor_list);
|
|
cmd_monitor_list_size++;
|
|
return newitem;
|
|
}
|
|
|
|
void cmd_monitor_log(TC_NS_SMC_CMD *cmd)
|
|
{
|
|
int foundFlag =0;
|
|
unsigned int pid;
|
|
unsigned int tid;
|
|
struct cmd_monitor *monitor = NULL;
|
|
struct cmd_monitor* newitem;
|
|
if (cmd == NULL)
|
|
{
|
|
return;
|
|
}
|
|
pid = current->tgid;
|
|
tid = current->pid;
|
|
mutex_lock(&cmd_monitor_lock);
|
|
do {
|
|
list_for_each_entry(monitor, &cmd_monitor_list, list) {
|
|
if(monitor->pid == pid && monitor->tid == tid){
|
|
foundFlag = 1;
|
|
/* restart*/
|
|
monitor->sendtime = current_kernel_time();
|
|
monitor->count++;
|
|
monitor->returned = false;
|
|
monitor->isReported = false;
|
|
monitor->lastcmdid = cmd->cmd_id;
|
|
break;
|
|
}
|
|
}
|
|
if (foundFlag == 0) {
|
|
if (cmd_monitor_list_size > MAX_CMD_MONITOR_LIST-1) {
|
|
tloge("[cmd_monitor_tick]MAX_CMD_MONITOR_LIST\n");
|
|
break;
|
|
}
|
|
newitem = init_monitor_locked();
|
|
if (newitem == NULL) {
|
|
tloge("[cmd_monitor_tick]init_monitor failed\n");
|
|
break;
|
|
}
|
|
newitem->lastcmdid = cmd->cmd_id;
|
|
/* the first cmd will cause timer*/
|
|
if (cmd_monitor_list_size == 1) {
|
|
schedule_delayed_work(&cmd_monitor_work, usecs_to_jiffies(1000000));
|
|
}
|
|
}
|
|
}while(0);
|
|
mutex_unlock(&cmd_monitor_lock);
|
|
}
|
|
|
|
void cmd_monitor_logend(TC_NS_SMC_CMD *cmd)
|
|
{
|
|
unsigned int pid;
|
|
unsigned int tid;
|
|
struct cmd_monitor *monitor = NULL;
|
|
if (cmd == NULL)
|
|
{
|
|
return;
|
|
}
|
|
pid = current->tgid;
|
|
tid = current->pid;
|
|
mutex_lock(&cmd_monitor_lock);
|
|
list_for_each_entry(monitor, &cmd_monitor_list, list) {
|
|
if(monitor->pid == pid && monitor->tid == tid && monitor->returned ==false){
|
|
struct timespec nowtime = current_kernel_time();
|
|
long timedif = 1000000*nowtime.tv_sec-1000000*monitor->sendtime.tv_sec+nowtime.tv_nsec/1000-monitor->sendtime.tv_nsec/1000;
|
|
monitor->timetotal += timedif;
|
|
monitor->returned = true;
|
|
/* we need set all monitor.returned = true ,dont break;*/
|
|
}
|
|
}
|
|
mutex_unlock(&cmd_monitor_lock);
|
|
}
|
|
void do_cmd_need_archivelog(void)
|
|
{
|
|
if(cmd_need_archivelog == 1) {
|
|
cmd_need_archivelog =0;
|
|
schedule_delayed_work(&cmd_monitor_work_archive, usecs_to_jiffies(1000000));
|
|
}
|
|
}
|
|
void init_cmd_monitor(void)
|
|
{
|
|
INIT_DEFERRABLE_WORK(&cmd_monitor_work, cmd_monitor_tickfn);
|
|
INIT_DEFERRABLE_WORK(&cmd_monitor_work_archive, cmd_monitor_archivefn);
|
|
}
|