This is an automated email from the ASF dual-hosted git repository. xiaoxiang781216 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit a36dfe904ded30477ebc9f088407cce58e89ac58 Author: Parthiban Nallathambi <[email protected]> AuthorDate: Thu Nov 5 16:44:55 2026 +0530 arch/tricore: Report the free context list underflow trap. On a free context list underflow (FCU) no free CSA is left, so the trap vector cannot save the lower context and the core faults again inside the trap, with nothing reported. Keep a small pool of CSAs for this trap, from TRICORE_FCU_CSA_NUM or from the board through tricore_fcu_register_pool. Save the trapped context there and report the trap through the normal trap path. Signed-off-by: Parthiban Nallathambi <[email protected]> --- arch/tricore/Kconfig | 10 +++ arch/tricore/src/common/gnu/tricore_vectors.S | 33 +++++++- .../tricore/src/common/tasking/tricore_vectors.asm | 25 ++++++- arch/tricore/src/common/tricore_internal.h | 2 + arch/tricore/src/common/tricore_trapcall.c | 87 ++++++++++++++++++++++ 5 files changed, 155 insertions(+), 2 deletions(-) diff --git a/arch/tricore/Kconfig b/arch/tricore/Kconfig index ad5cbf972df..3fcadc28c02 100644 --- a/arch/tricore/Kconfig +++ b/arch/tricore/Kconfig @@ -123,6 +123,16 @@ config CPU_COREID default 0 range 0 6 +config TRICORE_FCU_CSA_NUM + int "Context save areas for the FCU trap" + default 0 + ---help--- + Context save areas reserved for a free context list underflow + (FCU) trap, so that the trap can still be reported when no free + context save area is left. 0 reserves none, then the core stops + in the trap unless the board passes its own pool to + tricore_fcu_register_pool. At least 20 are needed. + if ARCH_CHIP_TC3XX source "arch/tricore/src/tc3xx/Kconfig" endif diff --git a/arch/tricore/src/common/gnu/tricore_vectors.S b/arch/tricore/src/common/gnu/tricore_vectors.S index 6d31a6e1b8a..df9be09084f 100644 --- a/arch/tricore/src/common/gnu/tricore_vectors.S +++ b/arch/tricore/src/common/gnu/tricore_vectors.S @@ -32,6 +32,14 @@ * The handler returns with ji %a11, then the entry restores the lower * context and returns from the trap. * + * Context management traps go through tricore_ctx_entry first: on a free + * context list underflow (FCU, TIN 4) there is no free CSA, so svlcx + * cannot run. tricore_fcu_entry then saves the trapped context into the + * pool registered with tricore_fcu_register_pool and continues in + * tricore_fcu_recover. The saved %a4 is lost, as the entry uses it, and + * so is %sp when the trap switched to the interrupt stack. Without a pool + * the core stops in tricore_fcu_entry. + * * tasking/tricore_vectors.asm is the same code in the TASKING syntax. ****************************************************************************/ @@ -44,6 +52,11 @@ .p2align 5 .endm + .macro TRAPJUMP entry + j \entry + .p2align 5 + .endm + .macro TRAPTAB cpu .section .traptab_cpu\cpu, "ax", %progbits .p2align 8 @@ -52,7 +65,7 @@ tricore_trap_vectors_cpu\cpu: TRAPSLOT 0, tricore_trap_entry TRAPSLOT 1, tricore_trap_entry TRAPSLOT 2, tricore_trap_entry - TRAPSLOT 3, tricore_trap_entry + TRAPJUMP tricore_ctx_entry TRAPSLOT 4, tricore_trap_entry TRAPSLOT 5, tricore_trap_entry TRAPSLOT 6, tricore_syscall_entry @@ -69,6 +82,7 @@ tricore_trap_vectors_cpu\cpu: /* struct tricore_trap_s: taddr at 0, tid at 4, tclass at 5, tcpu at 6 */ .macro TRAPENTRY name, handler + .global \name .type \name, %function \name: sub.a %sp, 8 @@ -92,3 +106,20 @@ tricore_trap_vectors_cpu\cpu: TRAPENTRY tricore_trap_entry, tricore_trapcall TRAPENTRY tricore_syscall_entry, tricore_svcall + + .type tricore_ctx_entry, %function +tricore_ctx_entry: + jeq %d15, 4, tricore_fcu_entry + svlcx + mov %d5, 3 + j tricore_trap_entry + + .type tricore_fcu_entry, %function +tricore_fcu_entry: + movh.a %a4, hi:g_tricore_fcu_pool + ld.a %a4, [%a4]lo:g_tricore_fcu_pool +.Lfcu_nopool: + jz.a %a4, .Lfcu_nopool + stucx [%a4]0 + stlcx [%a4]64 + j tricore_fcu_recover diff --git a/arch/tricore/src/common/tasking/tricore_vectors.asm b/arch/tricore/src/common/tasking/tricore_vectors.asm index 0609fd2891a..3a9a3439f43 100644 --- a/arch/tricore/src/common/tasking/tricore_vectors.asm +++ b/arch/tricore/src/common/tasking/tricore_vectors.asm @@ -29,6 +29,8 @@ .extern tricore_trapcall .extern tricore_svcall + .extern tricore_fcu_recover + .extern g_tricore_fcu_pool TRAPSLOT .macro cls, entry svlcx @@ -37,6 +39,11 @@ TRAPSLOT .macro cls, entry .align 32 .endm +TRAPJUMP .macro entry + j entry + .align 32 + .endm + TRAPTAB .macro cpu, label .sdecl ".text.traptab_cpu\cpu",code,protect .sect ".text.traptab_cpu\cpu" @@ -46,7 +53,7 @@ label: TRAPSLOT 0, tricore_trap_entry TRAPSLOT 1, tricore_trap_entry TRAPSLOT 2, tricore_trap_entry - TRAPSLOT 3, tricore_trap_entry + TRAPJUMP tricore_ctx_entry TRAPSLOT 4, tricore_trap_entry TRAPSLOT 5, tricore_trap_entry TRAPSLOT 6, tricore_syscall_entry @@ -63,6 +70,7 @@ label: ; struct tricore_trap_s: taddr at 0, tid at 4, tclass at 5, tcpu at 6 TRAPENTRY .macro name, handler + .global name name: sub.a sp, #8 st.a [sp]0, a11 @@ -86,4 +94,19 @@ name: TRAPENTRY tricore_trap_entry, tricore_trapcall TRAPENTRY tricore_syscall_entry, tricore_svcall +tricore_ctx_entry: + jeq d15, #4, tricore_fcu_entry + svlcx + mov d5, #3 + j tricore_trap_entry + +tricore_fcu_entry: + movh.a a4, #@HIS(g_tricore_fcu_pool) + ld.a a4, [a4]@LOS(g_tricore_fcu_pool) +fcu_nopool: + jz.a a4, fcu_nopool + stucx [a4]0 + stlcx [a4]64 + j tricore_fcu_recover + .end diff --git a/arch/tricore/src/common/tricore_internal.h b/arch/tricore/src/common/tricore_internal.h index a3b077edfc4..11d4fbfaea8 100644 --- a/arch/tricore/src/common/tricore_internal.h +++ b/arch/tricore/src/common/tricore_internal.h @@ -201,6 +201,8 @@ void tricore_svcall(volatile void *trap); void tricore_trapcall(volatile void *trap); void tricore_trapinit(void); void tricore_bustrap_register_hook(tricore_bustrap_hook_t hook); +void tricore_fcu_register_pool(void *base, size_t num); +void tricore_fcu_recover(void); /* Context Save Areas *******************************************************/ diff --git a/arch/tricore/src/common/tricore_trapcall.c b/arch/tricore/src/common/tricore_trapcall.c index 8ae97e5dcf7..801d074a7ef 100644 --- a/arch/tricore/src/common/tricore_trapcall.c +++ b/arch/tricore/src/common/tricore_trapcall.c @@ -106,6 +106,16 @@ static struct tricore_trap_s g_trapinfo; +/* FCU pool, also read by tricore_fcu_entry in tricore_vectors.S/.asm */ + +uintptr_t *g_tricore_fcu_pool; +static size_t g_tricore_fcu_num; + +#if CONFIG_TRICORE_FCU_CSA_NUM > 0 +static uintptr_t g_fcu_csa[CONFIG_TRICORE_FCU_CSA_NUM * TC_CONTEXT_REGS] + aligned_data(TC_CONTEXT_SIZE); +#endif + /* Bus trap hook for safety test modules (e.g., BusMonTst). */ static tricore_bustrap_hook_t g_bustrap_hook; @@ -511,6 +521,79 @@ void tricore_trapcall(volatile void *trap) PANIC_WITH_REGS("Trap", regs); } +/**************************************************************************** + * Name: tricore_fcu_register_pool + * + * Description: + * Register the context save areas that the free context list underflow + * (FCU) trap uses to report the trap when no free CSA is left. The pool + * is linked only when the trap happens, so it may also be RAM that is in + * use until then. + * + * Input Parameters: + * base - 64-byte aligned start of the pool + * num - Number of context save areas, at least 20: two for the trapped + * context, the rest for the panic path + * + ****************************************************************************/ + +void tricore_fcu_register_pool(void *base, size_t num) +{ + DEBUGASSERT(base != NULL); + DEBUGASSERT(((uintptr_t)base & (TC_CONTEXT_SIZE - 1)) == 0); + + g_tricore_fcu_num = num; + g_tricore_fcu_pool = base; +} + +/**************************************************************************** + * Name: tricore_fcu_recover + * + * Description: + * Entered by a jump from tricore_fcu_entry, after the trapped upper and + * lower context were saved into the first two CSAs of the FCU pool. + * Link the rest of the pool into the free context list, point PCXI at + * the saved lower context and report the trap through the normal trap + * entry, as a context management trap with TIN 4. + * + ****************************************************************************/ + +noinstrument_function void tricore_fcu_recover(void) +{ + uintptr_t *csa = g_tricore_fcu_pool; + size_t i; + + for (i = 2; i < g_tricore_fcu_num - 1; i++) + { + csa[i * TC_CONTEXT_REGS + REG_LPCXI] = + tricore_addr2csa(&csa[(i + 1) * TC_CONTEXT_REGS]); + } + + csa[(g_tricore_fcu_num - 1) * TC_CONTEXT_REGS + REG_LPCXI] = 0; + csa[TC_CONTEXT_REGS + REG_LPCXI] = tricore_addr2csa(csa) | PCXI_UL; + + tricore_mtcr(TRICORE_CPU_PCXI, tricore_addr2csa(&csa[TC_CONTEXT_REGS])); + tricore_mtcr(TRICORE_CPU_FCX, + tricore_addr2csa(&csa[2 * TC_CONTEXT_REGS])); + UP_ISB(); + + /* A11 is the trap return address, from the saved upper context */ + +#ifdef CONFIG_TRICORE_TOOLCHAIN_TASKING + __asm__ volatile ("ld.a a11, [%0]12\n\t" + "mov d15, #4\n\t" + "mov d5, #3\n\t" + "j tricore_trap_entry\n\t" : : "a"(csa)); +#else + __asm__ volatile ("ld.a %%a11, [%0]12\n\t" + "mov %%d15, 4\n\t" + "mov %%d5, 3\n\t" + "j tricore_trap_entry\n\t" : : "a"(csa)); +#endif + + for (; ; ); +} + /**************************************************************************** * Function: tricore_trapinit * @@ -521,6 +604,10 @@ void tricore_trapcall(volatile void *trap) void tricore_trapinit(void) { +#if CONFIG_TRICORE_FCU_CSA_NUM > 0 + tricore_fcu_register_pool(g_fcu_csa, CONFIG_TRICORE_FCU_CSA_NUM); +#endif + #ifdef CONFIG_COREDUMP coredump_add_memory_region(&g_trapinfo, sizeof(g_trapinfo), PF_REGISTER);
