• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *   Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  * Description:  OAM TRACE for RISCV31
15  *
16  * Create: 2021-10-25
17  */
18 #include "oam_trace.h"
19 #include "print_config.h"
20 #include "arch_encoding.h"
21 #include "arch_trace.h"
22 #include "memory_config.h"
23 #include "share_mem_config.h"
24 #include "arch/exception.h"
25 
26 #define  USER_STACK_OFFSET_PER   4
27 #define  USER_STACK_PRINT_DEPTH  128
28 
check_txt_addr_range(uint32_t pc,uint32_t text_start,uint32_t text_end)29 static bool check_txt_addr_range(uint32_t pc, uint32_t text_start, uint32_t text_end)
30 {
31     if (pc >= text_start && pc < text_end) {
32         return true;
33     } else {
34         return false;
35     }
36 }
37 
is_valid_txt_addr(uint32_t pc)38 bool is_valid_txt_addr(uint32_t pc)
39 {
40     /* flash text */
41     if (check_txt_addr_range(pc, (uintptr_t)&__text_begin__, (uintptr_t)&__text_end__)) {
42         return true;
43     }
44 
45     /* tcm text */
46     if (check_txt_addr_range(pc, (uintptr_t)&__tcm_text_begin__, (uintptr_t)&__tcm_text_end__)) {
47         return true;
48     }
49 
50     /* sram text */
51     if (check_txt_addr_range(pc, (uintptr_t)&__sram_text_begin__, (uintptr_t)&__sram_text_end__)) {
52         return true;
53     }
54 
55     /* rom */
56     if (check_txt_addr_range(pc, ROM_START, ROM_START + ROM_LENGTH)) {
57         return true;
58     }
59 
60     return false;
61 }
62 
63 #ifdef USE_CMSIS_OS
64 EXC_PROC_FUNC g_exec_hook;
65 #endif
66 
back_trace(uint32_t sp)67 static void back_trace(uint32_t sp)
68 {
69     uint32_t back_sp = sp;
70     uint32_t count = 0;
71 
72     oam_trace_print("*******stack txt info begin*******\r\n");
73 
74     while (back_sp != 0) {
75         if (is_valid_txt_addr(*((uint32_t *)(back_sp)))) {
76             oam_trace_print("traceback %d -- sp addr= 0x%x    sp content= 0x%x\r\n", count, back_sp,
77                             *((uint32_t *)(back_sp)));
78         }
79 
80         back_sp = back_sp + USER_STACK_OFFSET_PER;
81         count++;
82         if (count == USER_STACK_PRINT_DEPTH) {
83             break;
84         }
85     }
86     oam_trace_print("*******stack txt info end*******\r\n");
87 }
88 
89 #ifdef SUPPORT_CPU_TRACE
riscv_cpu_trace_print(void)90 static void riscv_cpu_trace_print(void)
91 {
92     riscv_cpu_trace_item_t *item = (riscv_cpu_trace_item_t *)(uintptr_t)(RISCV_TRACE_MEM_REGION_START);
93     uint32_t cpu_trace_end_addr = RISCV_TRACE_MEM_REGION_START + RISCV_TRACE_MEM_REGION_LENGTH;
94 
95     oam_trace_print("**************CPU Trace Information************** \r\n");
96 
97     for (uint32_t i = 0; &item[i] < (riscv_cpu_trace_item_t *)(uintptr_t)(cpu_trace_end_addr); i++) {
98         oam_trace_print("cpu trace %d:\r\n", i);
99         oam_trace_print("step time:0x%x   LR:0x%x   PC:0x%x\r\n", item[i].time, item[i].lr, item[i].pc);
100     }
101 
102     oam_trace_print("**************CPU Trace end*********************** \r\n");
103 }
104 #endif
105 
print_excptsc(void)106 static void print_excptsc(void)
107 {
108     oam_trace_print("cxcptsc = 0x%x\r\n", read_custom_csr(CXCPTSC));
109 }
110 
111 #ifdef USE_CMSIS_OS
exec_fault_handler(uint32_t exc_type,const ExcContext * exc_buff_addr)112 void exec_fault_handler(uint32_t exc_type, const ExcContext *exc_buff_addr)
113 {
114     riscv_cpu_trace_disable();
115     if (g_exec_hook != NULL) {
116         g_exec_hook(exc_type, exc_buff_addr);
117     }
118     // custom oam information
119     print_excptsc();
120     if (exc_buff_addr != NULL) {
121 #ifdef USE_ALIOS
122         back_trace((uint32_t)exc_buff_addr->taskContext.X2);
123 #else
124         oam_trace_print("*******backtrace begin*******\r\n");
125         ArchBackTraceGet(exc_buff_addr->taskContext.s0, NULL, USER_STACK_PRINT_DEPTH, 0);
126         oam_trace_print("*******backtrace end*******\r\n");
127         back_trace(exc_buff_addr->taskContext.sp);
128 #endif
129     }
130 #ifdef SUPPORT_CPU_TRACE
131     riscv_cpu_trace_print();
132 #endif
133 }
134 
register_os_exec_hook(void)135 void register_os_exec_hook(void)
136 {
137     g_exec_hook = ArchGetExcHook();
138     ArchSetExcHook((EXC_PROC_FUNC)exec_fault_handler);
139 }
140 #endif
141