• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2021 Huawei Device Co., Ltd. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without modification,
5  * are permitted provided that the following conditions are met:
6  *
7  * 1. Redistributions of source code must retain the above copyright notice, this list of
8  *    conditions and the following disclaimer.
9  *
10  * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11  *    of conditions and the following disclaimer in the documentation and/or other materials
12  *    provided with the distribution.
13  *
14  * 3. Neither the name of the copyright holder nor the names of its contributors may be used
15  *    to endorse or promote products derived from this software without specific prior written
16  *    permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
22  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 /* ------------ includes ------------ */
32 #include "los_hidumper.h"
33 #ifdef LOSCFG_BLACKBOX
34 #include "los_blackbox.h"
35 #endif
36 #ifdef LOSCFG_CPUP_INCLUDE_IRQ
37 #include "los_cpup_pri.h"
38 #endif
39 #include "los_hwi_pri.h"
40 #include "los_init.h"
41 #include "los_mp.h"
42 #include "los_mux.h"
43 #include "los_printf.h"
44 #include "los_process_pri.h"
45 #include "los_task_pri.h"
46 #include "los_vm_dump.h"
47 #include "los_vm_lock.h"
48 #include "los_vm_map.h"
49 #ifdef LOSCFG_FS_VFS
50 #include "fs/file.h"
51 #endif
52 #include "fs/driver.h"
53 #include "securec.h"
54 #ifdef LOSCFG_LIB_LIBC
55 #include "unistd.h"
56 #endif
57 #include "user_copy.h"
58 
59 /* ------------ local macroes ------------ */
60 #define CPUP_TYPE_COUNT      3
61 #define HIDUMPER_DEVICE      "/dev/hidumper"
62 #define HIDUMPER_DEVICE_MODE 0666
63 #define KERNEL_FAULT_ADDR    0x1
64 #define KERNEL_FAULT_VALUE   0x2
65 #define READ_BUF_SIZE        128
66 #define SYS_INFO_HEADER      "************ sys info ***********"
67 #define CPU_USAGE_HEADER     "************ cpu usage ***********"
68 #define MEM_USAGE_HEADER     "************ mem usage ***********"
69 #define PAGE_USAGE_HEADER    "************ physical page usage ***********"
70 #define TASK_INFO_HEADER     "************ task info ***********"
71 #ifndef ARRAY_SIZE
72 #define ARRAY_SIZE(array)    (sizeof(array) / sizeof(array[0]))
73 #endif
74 #define REPLACE_INTERFACE(dst, src, type, func) {           \
75     if (((type *)src)->func != NULL) {                      \
76         ((type *)dst)->func = ((type *)src)->func;          \
77     } else {                                                \
78         PRINT_ERR("%s->%s is NULL!\n", #src, #func);        \
79     }                                                       \
80 }
81 #define INVOKE_INTERFACE(adapter, type, func) {             \
82     if (((type *)adapter)->func != NULL) {                  \
83         ((type *)adapter)->func();                          \
84     } else {                                                \
85         PRINT_ERR("%s->%s is NULL!\n", #adapter, #func);    \
86     }                                                       \
87 }
88 
89 /* ------------ local prototypes ------------ */
90 /* ------------ local function declarations ------------ */
91 STATIC INT32 HiDumperOpen(struct file *filep);
92 STATIC INT32 HiDumperClose(struct file *filep);
93 STATIC INT32 HiDumperIoctl(struct file *filep, INT32 cmd, unsigned long arg);
94 
95 /* ------------ global function declarations ------------ */
96 #ifdef LOSCFG_SHELL
97 extern VOID   OsShellCmdSystemInfoGet(VOID);
98 extern UINT32 OsShellCmdFree(INT32 argc, const CHAR *argv[]);
99 extern UINT32 OsShellCmdUname(INT32 argc, const CHAR *argv[]);
100 extern UINT32 OsShellCmdDumpPmm(VOID);
101 #endif
102 
103 /* ------------ local variables ------------ */
104 static struct HiDumperAdapter g_adapter;
105 STATIC struct file_operations_vfs g_hidumperDevOps = {
106     HiDumperOpen,  /* open */
107     HiDumperClose, /* close */
108     NULL,          /* read */
109     NULL,          /* write */
110     NULL,          /* seek */
111     HiDumperIoctl, /* ioctl */
112     NULL,          /* mmap */
113 #ifndef CONFIG_DISABLE_POLL
114     NULL,          /* poll */
115 #endif
116     NULL,          /* unlink */
117 };
118 
119 /* ------------ function definitions ------------ */
HiDumperOpen(struct file * filep)120 STATIC INT32 HiDumperOpen(struct file *filep)
121 {
122     (VOID)filep;
123     return 0;
124 }
125 
HiDumperClose(struct file * filep)126 STATIC INT32 HiDumperClose(struct file *filep)
127 {
128     (VOID)filep;
129     return 0;
130 }
131 
DumpSysInfo(void)132 static void DumpSysInfo(void)
133 {
134     PRINTK("\n%s\n", SYS_INFO_HEADER);
135 #ifdef LOSCFG_SHELL
136     const char *argv[1] = {"-a"};
137     (VOID)OsShellCmdUname(ARRAY_SIZE(argv), &argv[0]);
138     (VOID)OsShellCmdSystemInfoGet();
139 #else
140     PRINTK("\nUnsupported!\n");
141 #endif
142 }
143 
144 #ifdef LOSCFG_KERNEL_CPUP
DoDumpCpuUsageUnsafe(CPUP_INFO_S * processCpupAll,CPUP_INFO_S * processCpup10s,CPUP_INFO_S * processCpup1s)145 static void DoDumpCpuUsageUnsafe(CPUP_INFO_S *processCpupAll,
146     CPUP_INFO_S *processCpup10s,
147     CPUP_INFO_S *processCpup1s)
148 {
149     UINT32 pid;
150 
151     PRINTK("%-32s PID CPUUSE CPUUSE10S CPUUSE1S\n", "PName");
152     for (pid = 0; pid < g_processMaxNum; pid++) {
153         LosProcessCB *processCB = g_processCBArray + pid;
154         if (OsProcessIsUnused(processCB)) {
155             continue;
156         }
157         PRINTK("%-32s %u %5u.%1u%8u.%1u%7u.%-1u\n",
158             processCB->processName, processCB->processID,
159             processCpupAll[pid].usage / LOS_CPUP_PRECISION_MULT,
160             processCpupAll[pid].usage % LOS_CPUP_PRECISION_MULT,
161             processCpup10s[pid].usage / LOS_CPUP_PRECISION_MULT,
162             processCpup10s[pid].usage % LOS_CPUP_PRECISION_MULT,
163             processCpup1s[pid].usage / LOS_CPUP_PRECISION_MULT,
164             processCpup1s[pid].usage % LOS_CPUP_PRECISION_MULT);
165     }
166 }
167 #endif
168 
DumpCpuUsageUnsafe(void)169 static void DumpCpuUsageUnsafe(void)
170 {
171     PRINTK("\n%s\n", CPU_USAGE_HEADER);
172 #ifdef LOSCFG_KERNEL_CPUP
173     UINT32 size;
174     CPUP_INFO_S *processCpup = NULL;
175     CPUP_INFO_S *processCpupAll = NULL;
176     CPUP_INFO_S *processCpup10s = NULL;
177     CPUP_INFO_S *processCpup1s = NULL;
178 
179     size = sizeof(*processCpup) * g_processMaxNum * CPUP_TYPE_COUNT;
180     processCpup = LOS_MemAlloc(m_aucSysMem1, size);
181     if (processCpup == NULL) {
182         PRINT_ERR("func: %s, LOS_MemAlloc failed, Line: %d\n", __func__, __LINE__);
183         return;
184     }
185     processCpupAll = processCpup;
186     processCpup10s = processCpupAll + g_processMaxNum;
187     processCpup1s = processCpup10s + g_processMaxNum;
188     (VOID)memset_s(processCpup, size, 0, size);
189     LOS_GetAllProcessCpuUsage(CPUP_ALL_TIME, processCpupAll, g_processMaxNum * sizeof(CPUP_INFO_S));
190     LOS_GetAllProcessCpuUsage(CPUP_LAST_TEN_SECONDS, processCpup10s, g_processMaxNum * sizeof(CPUP_INFO_S));
191     LOS_GetAllProcessCpuUsage(CPUP_LAST_ONE_SECONDS, processCpup1s, g_processMaxNum * sizeof(CPUP_INFO_S));
192     DoDumpCpuUsageUnsafe(processCpupAll, processCpup10s, processCpup1s);
193     (VOID)LOS_MemFree(m_aucSysMem1, processCpup);
194 #else
195     PRINTK("\nUnsupported!\n");
196 #endif
197 }
198 
DumpMemUsage(void)199 static void DumpMemUsage(void)
200 {
201     PRINTK("\n%s\n", MEM_USAGE_HEADER);
202 #ifdef LOSCFG_SHELL
203     PRINTK("Unit: KB\n");
204     const char *argv[1] = {"-k"};
205     (VOID)OsShellCmdFree(ARRAY_SIZE(argv), &argv[0]);
206     PRINTK("%s\n", PAGE_USAGE_HEADER);
207     (VOID)OsShellCmdDumpPmm();
208 #else
209     PRINTK("\nUnsupported!\n");
210 #endif
211 }
212 
DumpTaskInfo(void)213 static void DumpTaskInfo(void)
214 {
215     PRINTK("\n%s\n", TASK_INFO_HEADER);
216 #ifdef LOSCFG_SHELL
217     (VOID)OsShellCmdTskInfoGet(OS_ALL_TASK_MASK, NULL, OS_PROCESS_INFO_ALL);
218 #else
219     PRINTK("\nUnsupported!\n");
220 #endif
221 }
222 
223 #ifdef LOSCFG_BLACKBOX
PrintFileData(INT32 fd)224 static void PrintFileData(INT32 fd)
225 {
226 #ifdef LOSCFG_FS_VFS
227     CHAR buf[READ_BUF_SIZE];
228 
229     if (fd < 0) {
230         PRINT_ERR("fd: %d!\n", fd);
231         return;
232     }
233 
234     (void)memset_s(buf, sizeof(buf), 0, sizeof(buf));
235     while (read(fd, buf, sizeof(buf) - 1) > 0) {
236         PRINTK("%s", buf);
237         (void)memset_s(buf, sizeof(buf), 0, sizeof(buf));
238     }
239 #else
240     (VOID)fd;
241     PRINT_ERR("LOSCFG_FS_VFS isn't defined!\n");
242 #endif
243 }
244 
PrintFile(const char * filePath,const char * pHeader)245 static void PrintFile(const char *filePath, const char *pHeader)
246 {
247 #ifdef LOSCFG_FS_VFS
248     int fd;
249 
250     if (filePath == NULL || pHeader == NULL) {
251         PRINT_ERR("filePath: %p, pHeader: %p\n", filePath, pHeader);
252         return;
253     }
254 
255     fd = open(filePath, O_RDONLY);
256     if (fd >= 0) {
257         PRINTK("\n%s\n", pHeader);
258         PrintFileData(fd);
259         (void)close(fd);
260     } else {
261         PRINT_ERR("Open [%s] failed or there's no fault log!\n", filePath);
262     }
263 #else
264     (VOID)filePath;
265     (VOID)pHeader;
266     PRINT_ERR("LOSCFG_FS_VFS isn't defined!\n");
267 #endif
268 }
269 #endif
270 
DumpFaultLog(void)271 static void DumpFaultLog(void)
272 {
273 #ifdef LOSCFG_BLACKBOX
274     PrintFile(KERNEL_FAULT_LOG_PATH, "************kernel fault info************");
275     PrintFile(USER_FAULT_LOG_PATH, "************user fault info************");
276 #endif
277 }
278 
DumpMemData(struct MemDumpParam * param)279 static void DumpMemData(struct MemDumpParam *param)
280 {
281     PRINTK("\nDumpType: %d\n", param->type);
282     PRINTK("Unsupported now!\n");
283 }
284 
InjectKernelCrash(void)285 static void InjectKernelCrash(void)
286 {
287 #ifdef LOSCFG_DEBUG_VERSION
288     *((INT32 *)KERNEL_FAULT_ADDR) = KERNEL_FAULT_VALUE;
289 #else
290     PRINTK("\nUnsupported!\n");
291 #endif
292 }
293 
HiDumperIoctl(struct file * filep,INT32 cmd,unsigned long arg)294 static INT32 HiDumperIoctl(struct file *filep, INT32 cmd, unsigned long arg)
295 {
296     INT32 ret = 0;
297 
298     switch (cmd) {
299         case HIDUMPER_DUMP_ALL:
300             INVOKE_INTERFACE(&g_adapter, struct HiDumperAdapter, DumpSysInfo);
301             INVOKE_INTERFACE(&g_adapter, struct HiDumperAdapter, DumpCpuUsage);
302             INVOKE_INTERFACE(&g_adapter, struct HiDumperAdapter, DumpMemUsage);
303             INVOKE_INTERFACE(&g_adapter, struct HiDumperAdapter, DumpTaskInfo);
304             break;
305         case HIDUMPER_CPU_USAGE:
306             INVOKE_INTERFACE(&g_adapter, struct HiDumperAdapter, DumpCpuUsage);
307             break;
308         case HIDUMPER_MEM_USAGE:
309             INVOKE_INTERFACE(&g_adapter, struct HiDumperAdapter, DumpMemUsage);
310             break;
311         case HIDUMPER_TASK_INFO:
312             INVOKE_INTERFACE(&g_adapter, struct HiDumperAdapter, DumpTaskInfo);
313             break;
314         case HIDUMPER_INJECT_KERNEL_CRASH:
315             INVOKE_INTERFACE(&g_adapter, struct HiDumperAdapter, InjectKernelCrash);
316             break;
317         case HIDUMPER_DUMP_FAULT_LOG:
318             INVOKE_INTERFACE(&g_adapter, struct HiDumperAdapter, DumpFaultLog);
319             break;
320         case HIDUMPER_MEM_DATA:
321             if (g_adapter.DumpMemData != NULL) {
322                 g_adapter.DumpMemData((struct MemDumpParam *)((UINTPTR)arg));
323             }
324             break;
325         default:
326             ret = EPERM;
327             PRINTK("Invalid CMD: 0x%x\n", (UINT32)cmd);
328             break;
329     }
330 
331     return ret;
332 }
333 
RegisterCommonAdapter(void)334 static void RegisterCommonAdapter(void)
335 {
336     struct HiDumperAdapter adapter;
337 
338     adapter.DumpSysInfo = DumpSysInfo;
339     adapter.DumpCpuUsage = DumpCpuUsageUnsafe;
340     adapter.DumpMemUsage = DumpMemUsage;
341     adapter.DumpTaskInfo = DumpTaskInfo;
342     adapter.DumpFaultLog = DumpFaultLog;
343     adapter.DumpMemData = DumpMemData;
344     adapter.InjectKernelCrash = InjectKernelCrash;
345     HiDumperRegisterAdapter(&adapter);
346 }
347 
HiDumperRegisterAdapter(struct HiDumperAdapter * pAdapter)348 int HiDumperRegisterAdapter(struct HiDumperAdapter *pAdapter)
349 {
350     if (pAdapter == NULL) {
351         PRINT_ERR("pAdapter: %p\n", pAdapter);
352         return -1;
353     }
354 
355     REPLACE_INTERFACE(&g_adapter, pAdapter, struct HiDumperAdapter, DumpSysInfo);
356     REPLACE_INTERFACE(&g_adapter, pAdapter, struct HiDumperAdapter, DumpCpuUsage);
357     REPLACE_INTERFACE(&g_adapter, pAdapter, struct HiDumperAdapter, DumpMemUsage);
358     REPLACE_INTERFACE(&g_adapter, pAdapter, struct HiDumperAdapter, DumpTaskInfo);
359     REPLACE_INTERFACE(&g_adapter, pAdapter, struct HiDumperAdapter, DumpFaultLog);
360     REPLACE_INTERFACE(&g_adapter, pAdapter, struct HiDumperAdapter, DumpMemData);
361     REPLACE_INTERFACE(&g_adapter, pAdapter, struct HiDumperAdapter, InjectKernelCrash);
362 
363     return 0;
364 }
365 
OsHiDumperDriverInit(void)366 int OsHiDumperDriverInit(void)
367 {
368     INT32 ret;
369 
370 #ifdef LOSCFG_DEBUG_VERSION
371     RegisterCommonAdapter();
372     ret = register_driver(HIDUMPER_DEVICE, &g_hidumperDevOps, HIDUMPER_DEVICE_MODE, NULL);
373     if (ret != 0) {
374         PRINT_ERR("Hidumper register driver failed!\n");
375         return -1;
376     }
377 #endif
378 
379     return 0;
380 }
381 LOS_MODULE_INIT(OsHiDumperDriverInit, LOS_INIT_LEVEL_KMOD_EXTENDED);
382