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