176a38f4fSMarouene Boubakri // SPDX-License-Identifier: BSD-2-Clause
276a38f4fSMarouene Boubakri /*
3efc69401SAlvin Chang * Copyright (c) 2023 Andes Technology Corporation
476a38f4fSMarouene Boubakri * Copyright 2022-2023 NXP
576a38f4fSMarouene Boubakri * Copyright (c) 2014-2022, Linaro Limited
676a38f4fSMarouene Boubakri * Copyright (c) 2020, Arm Limited
776a38f4fSMarouene Boubakri */
876a38f4fSMarouene Boubakri
976a38f4fSMarouene Boubakri #include <kernel/abort.h>
1076a38f4fSMarouene Boubakri #include <kernel/scall.h>
1176a38f4fSMarouene Boubakri #include <kernel/thread.h>
1276a38f4fSMarouene Boubakri #include <kernel/trace_ta.h>
13*3db1b3e3SAlvin Chang #include <kernel/user_access.h>
1476a38f4fSMarouene Boubakri #include <kernel/user_ta.h>
1576a38f4fSMarouene Boubakri #include <mm/vm.h>
1676a38f4fSMarouene Boubakri #include <riscv.h>
1776a38f4fSMarouene Boubakri #include <types_ext.h>
1876a38f4fSMarouene Boubakri
1976a38f4fSMarouene Boubakri #define TA_CONTEXT_MAX_SIZE (RISCV_XLEN_BYTES * 32)
2076a38f4fSMarouene Boubakri
2176a38f4fSMarouene Boubakri #ifdef CFG_UNWIND
2276a38f4fSMarouene Boubakri
23efc69401SAlvin Chang /* Get register values pushed onto the stack by _utee_panic() */
save_panic_regs_rv_ta(struct thread_specific_data * tsd,unsigned long * pushed)2476a38f4fSMarouene Boubakri static void save_panic_regs_rv_ta(struct thread_specific_data *tsd,
2576a38f4fSMarouene Boubakri unsigned long *pushed)
2676a38f4fSMarouene Boubakri {
27*3db1b3e3SAlvin Chang TEE_Result res = TEE_SUCCESS;
28*3db1b3e3SAlvin Chang unsigned long s0 = 0;
29*3db1b3e3SAlvin Chang unsigned long epc = 0;
30*3db1b3e3SAlvin Chang #if defined(RV32)
31*3db1b3e3SAlvin Chang unsigned long *stack_s0 = &pushed[2];
32*3db1b3e3SAlvin Chang unsigned long *stack_epc = &pushed[3];
33*3db1b3e3SAlvin Chang #elif defined(RV64)
34*3db1b3e3SAlvin Chang unsigned long *stack_s0 = &pushed[0];
35*3db1b3e3SAlvin Chang unsigned long *stack_epc = &pushed[1];
36*3db1b3e3SAlvin Chang #endif
37*3db1b3e3SAlvin Chang
38*3db1b3e3SAlvin Chang res = GET_USER_SCALAR(s0, stack_s0);
39*3db1b3e3SAlvin Chang if (res)
40*3db1b3e3SAlvin Chang s0 = 0;
41*3db1b3e3SAlvin Chang
42*3db1b3e3SAlvin Chang res = GET_USER_SCALAR(epc, stack_epc);
43*3db1b3e3SAlvin Chang if (res)
44*3db1b3e3SAlvin Chang epc = 0;
45*3db1b3e3SAlvin Chang
4676a38f4fSMarouene Boubakri tsd->abort_regs = (struct thread_abort_regs){
4776a38f4fSMarouene Boubakri .sp = (unsigned long)pushed,
48*3db1b3e3SAlvin Chang .s0 = s0,
49*3db1b3e3SAlvin Chang .epc = epc,
5076a38f4fSMarouene Boubakri };
5176a38f4fSMarouene Boubakri }
5276a38f4fSMarouene Boubakri
scall_save_panic_stack(struct thread_scall_regs * regs)5376a38f4fSMarouene Boubakri void scall_save_panic_stack(struct thread_scall_regs *regs)
5476a38f4fSMarouene Boubakri {
5576a38f4fSMarouene Boubakri struct thread_specific_data *tsd = thread_get_tsd();
5676a38f4fSMarouene Boubakri struct ts_session *s = ts_get_current_session();
5776a38f4fSMarouene Boubakri struct user_ta_ctx *utc = to_user_ta_ctx(s->ctx);
5876a38f4fSMarouene Boubakri
5976a38f4fSMarouene Boubakri if (vm_check_access_rights(&utc->uctx,
6076a38f4fSMarouene Boubakri TEE_MEMORY_ACCESS_READ |
6176a38f4fSMarouene Boubakri TEE_MEMORY_ACCESS_WRITE,
6276a38f4fSMarouene Boubakri (uaddr_t)regs->a1,
6376a38f4fSMarouene Boubakri TA_CONTEXT_MAX_SIZE)) {
6476a38f4fSMarouene Boubakri TAMSG_RAW("");
6576a38f4fSMarouene Boubakri TAMSG_RAW("Can't unwind invalid user stack 0x%"PRIxUA,
6676a38f4fSMarouene Boubakri (uaddr_t)regs->a1);
6776a38f4fSMarouene Boubakri return;
6876a38f4fSMarouene Boubakri }
6976a38f4fSMarouene Boubakri
7076a38f4fSMarouene Boubakri tsd->abort_type = ABORT_TYPE_USER_MODE_PANIC;
7176a38f4fSMarouene Boubakri tsd->abort_descr = 0;
7276a38f4fSMarouene Boubakri tsd->abort_va = 0;
7376a38f4fSMarouene Boubakri
7476a38f4fSMarouene Boubakri save_panic_regs_rv_ta(tsd, (unsigned long *)regs->a1);
7576a38f4fSMarouene Boubakri }
7676a38f4fSMarouene Boubakri
7776a38f4fSMarouene Boubakri #else /* CFG_UNWIND */
scall_save_panic_stack(struct thread_scall_regs * regs __unused)7876a38f4fSMarouene Boubakri void scall_save_panic_stack(struct thread_scall_regs *regs __unused)
7976a38f4fSMarouene Boubakri {
8076a38f4fSMarouene Boubakri struct thread_specific_data *tsd = thread_get_tsd();
8176a38f4fSMarouene Boubakri
8276a38f4fSMarouene Boubakri tsd->abort_type = ABORT_TYPE_USER_MODE_PANIC;
8376a38f4fSMarouene Boubakri }
8476a38f4fSMarouene Boubakri #endif /* CFG_UNWIND */
85