diff options
| author | geniusgogo <[email protected]> | 2023-08-08 00:22:14 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-08-07 12:22:14 -0400 |
| commit | 4d20416b2f62cbb6c98e88223d6a0d1638b7f1c0 (patch) | |
| tree | 6cb74da348244a1b1584d08faf9e02294d92d139 /libcpu | |
| parent | 7e7b303dd475f71c3301fb494f7622fe0295435e (diff) | |
update components & lwp. (#7888)
Diffstat (limited to 'libcpu')
| -rw-r--r-- | libcpu/aarch64/common/backtrace.c | 131 | ||||
| -rw-r--r-- | libcpu/aarch64/common/backtrace.h | 6 | ||||
| -rw-r--r-- | libcpu/aarch64/common/context_gcc.S | 30 | ||||
| -rw-r--r-- | libcpu/aarch64/common/trap.c | 13 |
4 files changed, 173 insertions, 7 deletions
diff --git a/libcpu/aarch64/common/backtrace.c b/libcpu/aarch64/common/backtrace.c index d8985d0c09..14ea18a97f 100644 --- a/libcpu/aarch64/common/backtrace.c +++ b/libcpu/aarch64/common/backtrace.c @@ -6,10 +6,15 @@ * Change Logs: * Date Author Notes * 2022-06-02 Jesven the first version + * 2023-06-24 WangXiaoyao Support backtrace for non-active thread */ +#include "mm_aspace.h" +#include "mmu.h" + #include <rtthread.h> #include <backtrace.h> +#include <stdlib.h> #define BT_NESTING_MAX 100 @@ -19,7 +24,7 @@ static int unwind_frame(struct bt_frame *frame) if ((fp & 0x7) #ifdef RT_USING_LWP - || fp < KERNEL_VADDR_START + || (rt_kmem_v2p((void *)fp) == ARCH_MAP_FAILED) #endif ) { @@ -27,16 +32,18 @@ static int unwind_frame(struct bt_frame *frame) } frame->fp = *(unsigned long *)fp; frame->pc = *(unsigned long *)(fp + 8); + + if ((rt_kmem_v2p((void *)frame->pc) == ARCH_MAP_FAILED)) + return 1; return 0; } static void walk_unwind(unsigned long pc, unsigned long fp) { - struct bt_frame frame; + struct bt_frame frame = {fp, 1}; unsigned long lr = pc; int nesting = 0; - frame.fp = fp; while (nesting < BT_NESTING_MAX) { rt_kprintf(" %p", (void *)lr); @@ -51,18 +58,128 @@ static void walk_unwind(unsigned long pc, unsigned long fp) void backtrace(unsigned long pc, unsigned long lr, unsigned long fp) { - rt_kprintf("please use: addr2line -e rtthread.elf -a -f %p", (void *)pc); - walk_unwind(lr, fp); + rt_kprintf("please use: addr2line -e rtthread.elf -a -f"); + if (pc) + rt_kprintf(" %p", (void *)pc); + + if (lr && fp) + walk_unwind(lr, fp); rt_kprintf("\n"); } int rt_backtrace(void) { - unsigned long pc = (unsigned long)backtrace; unsigned long ra = (unsigned long)__builtin_return_address(0U); unsigned long fr = (unsigned long)__builtin_frame_address(0U); - backtrace(pc, ra, fr); + backtrace(0, ra, fr); return 0; } MSH_CMD_EXPORT_ALIAS(rt_backtrace, bt_test, backtrace test); + +#define ARCH_CONTEXT_FETCH(pctx, id) (*(((unsigned long *)pctx) + (id))) + +int rt_backtrace_thread(rt_thread_t thread) +{ + unsigned long lr; + unsigned long fp; + + if (thread == rt_thread_self()) + { + return -RT_EINVAL; + } + else + { + lr = ARCH_CONTEXT_FETCH(thread->sp, 3); + fp = ARCH_CONTEXT_FETCH(thread->sp, 7); + backtrace(0, lr, fp); + return 0; + } +} + +#ifdef RT_USING_SMART + +int rt_backtrace_user_thread(rt_thread_t thread) +{ + unsigned long pc; + unsigned long lr; + unsigned long fp; + unsigned long ctx = (unsigned long)thread->user_ctx.ctx; + + if (ctx > (unsigned long)thread->stack_addr + && ctx < (unsigned long)thread->stack_addr + thread->stack_size) + { + pc = ARCH_CONTEXT_FETCH(thread->user_ctx.ctx, 0); + lr = ARCH_CONTEXT_FETCH(thread->user_ctx.ctx, 3); + fp = ARCH_CONTEXT_FETCH(thread->user_ctx.ctx, 7); + backtrace(pc, lr, fp); + return 0; + } + else + return -1; +} + +#endif /* RT_USING_SMART */ + +static long custom_hex_to_long(const char* hex) +{ + long result = 0; + int i = 0; + + // Skip the "0x" prefix + if (hex[0] == '0' && (hex[1] == 'x' || hex[1] == 'X')) + { + i = 2; + } + + // Convert each hex digit to its decimal value + for (; hex[i] != '\0'; i++) + { + char digit = hex[i]; + if (digit >= '0' && digit <= '9') + { + result = result * 16 + (digit - '0'); + } + else if (digit >= 'a' && digit <= 'f') + { + result = result * 16 + (digit - 'a' + 10); + } + else if (digit >= 'A' && digit <= 'F') + { + result = result * 16 + (digit - 'A' + 10); + } + else + { + // Invalid hex digit + return 0; + } + } + + return result; +} + +static void cmd_backtrace(int argc, char** argv) +{ + long pid; + + if (argc < 2) + { + rt_kprintf("please use: backtrace pid\n"); + return; + } + + if (strncmp(argv[1], "0x", 2) == 0) + { + pid = custom_hex_to_long(argv[1]); + } + else + { + pid = atol(argv[1]); + } + if (pid) + { + rt_kprintf("backtrace %s(0x%lx), from %s\n", ((rt_thread_t)pid)->parent.name, pid, argv[1]); + rt_backtrace_thread((rt_thread_t)pid); + } +} +MSH_CMD_EXPORT_ALIAS(cmd_backtrace, backtrace, print backtrace of a thread); diff --git a/libcpu/aarch64/common/backtrace.h b/libcpu/aarch64/common/backtrace.h index 8c8006690c..e5e281978c 100644 --- a/libcpu/aarch64/common/backtrace.h +++ b/libcpu/aarch64/common/backtrace.h @@ -6,11 +6,14 @@ * Change Logs: * Date Author Notes * 2022-06-02 Jesven the first version + * 2023-06-24 WangXiaoyao Support backtrace for non-active thread */ #ifndef __BACKTRACE_H__ #define __BACKTRACE_H__ +#include <rtthread.h> + struct bt_frame { unsigned long fp; @@ -20,4 +23,7 @@ struct bt_frame void backtrace(unsigned long pc, unsigned long lr, unsigned long fp); int rt_backtrace(void); +int rt_backtrace_user_thread(rt_thread_t thread); +int rt_backtrace_thread(rt_thread_t thread); + #endif /*__BACKTRACE_H__*/ diff --git a/libcpu/aarch64/common/context_gcc.S b/libcpu/aarch64/common/context_gcc.S index d9dc2d1c93..e3487c9135 100644 --- a/libcpu/aarch64/common/context_gcc.S +++ b/libcpu/aarch64/common/context_gcc.S @@ -6,6 +6,7 @@ * Change Logs: * Date Author Notes * 2021-05-18 Jesven the first version + * 2023-06-24 WangXiaoyao Support backtrace for user thread */ #include "rtconfig.h" @@ -375,13 +376,31 @@ rt_hw_context_switch_interrupt: vector_fiq: B . +.macro SAVE_USER_CTX + MRS X1, SPSR_EL1 + AND X1, X1, 0xf + CMP X1, XZR + + BNE 1f + BL lwp_uthread_ctx_save + LDP X0, X1, [SP] +1: +.endm + .globl vector_irq vector_irq: SAVE_CONTEXT STP X0, X1, [SP, #-0x10]! /* X0 is thread sp */ BL rt_interrupt_enter + LDP X0, X1, [SP] +#ifdef RT_USING_LWP + SAVE_USER_CTX +#endif BL rt_hw_trap_irq +#ifdef RT_USING_LWP + BL lwp_uthread_ctx_restore +#endif BL rt_interrupt_leave LDP X0, X1, [SP], #0x10 @@ -515,7 +534,15 @@ vector_irq_exit: START_POINT(vector_exception) SAVE_CONTEXT STP X0, X1, [SP, #-0x10]! +#ifdef RT_USING_LWP + SAVE_USER_CTX +#endif + BL rt_hw_trap_exception +#ifdef RT_USING_LWP + BL lwp_uthread_ctx_restore +#endif + LDP X0, X1, [SP], #0x10 MOV SP, X0 RESTORE_CONTEXT_WITHOUT_MMU_SWITCH @@ -523,6 +550,9 @@ START_POINT_END(vector_exception) START_POINT(vector_serror) SAVE_CONTEXT +#ifdef RT_USING_LWP + SAVE_USER_CTX +#endif STP X0, X1, [SP, #-0x10]! BL rt_hw_trap_serror b . diff --git a/libcpu/aarch64/common/trap.c b/libcpu/aarch64/common/trap.c index dd5468daf1..8e97a8b0aa 100644 --- a/libcpu/aarch64/common/trap.c +++ b/libcpu/aarch64/common/trap.c @@ -296,6 +296,19 @@ void rt_hw_trap_exception(struct rt_hw_exp_stack *regs) #ifdef RT_USING_FINSH list_thread(); #endif + +#ifdef RT_USING_LWP + { + rt_thread_t th; + + th = rt_thread_self(); + if (th && th->lwp) + { + rt_backtrace_user_thread(th); + } + } +#endif + backtrace((unsigned long)regs->pc, (unsigned long)regs->x30, (unsigned long)regs->x29); rt_hw_cpu_shutdown(); } |
