xref: /optee_os/core/arch/arm/kernel/unwind_arm64.c (revision 93dc6b2960b97055bffaa67f1eb4adb1b4e9bfcd)
11bb92983SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause
2923c1f34SJens Wiklander /*-
3923c1f34SJens Wiklander  * Copyright (c) 2015 Linaro Limited
4923c1f34SJens Wiklander  * Copyright (c) 2015 The FreeBSD Foundation
5923c1f34SJens Wiklander  * All rights reserved.
6923c1f34SJens Wiklander  *
7923c1f34SJens Wiklander  * This software was developed by Semihalf under
8923c1f34SJens Wiklander  * the sponsorship of the FreeBSD Foundation.
9923c1f34SJens Wiklander  *
10923c1f34SJens Wiklander  * Redistribution and use in source and binary forms, with or without
11923c1f34SJens Wiklander  * modification, are permitted provided that the following conditions
12923c1f34SJens Wiklander  * are met:
13923c1f34SJens Wiklander  * 1. Redistributions of source code must retain the above copyright
14923c1f34SJens Wiklander  *    notice, this list of conditions and the following disclaimer.
15923c1f34SJens Wiklander  * 2. Redistributions in binary form must reproduce the above copyright
16923c1f34SJens Wiklander  *    notice, this list of conditions and the following disclaimer in the
17923c1f34SJens Wiklander  *    documentation and/or other materials provided with the distribution.
18923c1f34SJens Wiklander  *
19923c1f34SJens Wiklander  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20923c1f34SJens Wiklander  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21923c1f34SJens Wiklander  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22923c1f34SJens Wiklander  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23923c1f34SJens Wiklander  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24923c1f34SJens Wiklander  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25923c1f34SJens Wiklander  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26923c1f34SJens Wiklander  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27923c1f34SJens Wiklander  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28923c1f34SJens Wiklander  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29923c1f34SJens Wiklander  * SUCH DAMAGE.
30923c1f34SJens Wiklander  */
31923c1f34SJens Wiklander 
32a681fabaSJerome Forissier #include <arm.h>
33170e9084SJens Wiklander #include <kernel/linker.h>
34170e9084SJens Wiklander #include <kernel/thread.h>
35170e9084SJens Wiklander #include <kernel/unwind.h>
3602d307b7SJerome Forissier #include <unw/unwind.h>
37a367dcbbSJerome Forissier 
38a367dcbbSJerome Forissier #include "unwind_private.h"
39923c1f34SJens Wiklander 
40*93dc6b29SJens Wiklander #if defined(CFG_CORE_PAUTH)
pauth_strip_pac(uint64_t * lr)41*93dc6b29SJens Wiklander void pauth_strip_pac(uint64_t *lr)
42*93dc6b29SJens Wiklander {
43*93dc6b29SJens Wiklander 	const uint64_t va_mask = GENMASK_64(CFG_LPAE_ADDR_SPACE_BITS - 1, 0);
44*93dc6b29SJens Wiklander 
45*93dc6b29SJens Wiklander 	*lr = *lr & va_mask;
46*93dc6b29SJens Wiklander }
47*93dc6b29SJens Wiklander #endif
48*93dc6b29SJens Wiklander 
unw_get_kernel_stack(void)49a367dcbbSJerome Forissier vaddr_t *unw_get_kernel_stack(void)
50a367dcbbSJerome Forissier {
51a367dcbbSJerome Forissier 	size_t n = 0;
52a367dcbbSJerome Forissier 	size_t size = 0;
53a367dcbbSJerome Forissier 	vaddr_t *tmp = NULL;
54a367dcbbSJerome Forissier 	vaddr_t *addr = NULL;
55a367dcbbSJerome Forissier 	uaddr_t stack = thread_stack_start();
56a367dcbbSJerome Forissier 	size_t stack_size = thread_stack_size();
5702d307b7SJerome Forissier 	struct unwind_state_arm64 state = {
5802d307b7SJerome Forissier 		.pc = read_pc(),
5902d307b7SJerome Forissier 		.fp = read_fp()
6002d307b7SJerome Forissier 	};
61a367dcbbSJerome Forissier 
62c9826bf5SJens Wiklander 	while (unwind_stack_arm64(&state, stack, stack_size)) {
63a367dcbbSJerome Forissier 		tmp = unw_grow(addr, &size, (n + 1) * sizeof(vaddr_t));
64a367dcbbSJerome Forissier 		if (!tmp)
65a367dcbbSJerome Forissier 			goto err;
66a367dcbbSJerome Forissier 		addr = tmp;
67a367dcbbSJerome Forissier 		addr[n] = state.pc;
68a367dcbbSJerome Forissier 		n++;
69a367dcbbSJerome Forissier 	}
70a367dcbbSJerome Forissier 
71a367dcbbSJerome Forissier 	if (addr) {
72a367dcbbSJerome Forissier 		tmp = unw_grow(addr, &size, (n + 1) * sizeof(vaddr_t));
73a367dcbbSJerome Forissier 		if (!tmp)
74a367dcbbSJerome Forissier 			goto err;
75a367dcbbSJerome Forissier 		addr = tmp;
76a367dcbbSJerome Forissier 		addr[n] = 0;
77a367dcbbSJerome Forissier 	}
78a367dcbbSJerome Forissier 
79a367dcbbSJerome Forissier 	return addr;
80a367dcbbSJerome Forissier err:
81a367dcbbSJerome Forissier 	EMSG("Out of memory");
82a367dcbbSJerome Forissier 	free(addr);
83a367dcbbSJerome Forissier 	return NULL;
84a367dcbbSJerome Forissier }
8502d307b7SJerome Forissier 
86adb7766eSMoritz Lummerzheim #if defined(CFG_UNWIND) && (TRACE_LEVEL > 0)
print_kernel_stack(void)8702d307b7SJerome Forissier void print_kernel_stack(void)
8802d307b7SJerome Forissier {
8902d307b7SJerome Forissier 	struct unwind_state_arm64 state = { };
9002d307b7SJerome Forissier 	vaddr_t stack_start = 0;
9102d307b7SJerome Forissier 	vaddr_t stack_end = 0;
9202d307b7SJerome Forissier 
9302d307b7SJerome Forissier 	state.pc = read_pc();
9402d307b7SJerome Forissier 	state.fp = read_fp();
9502d307b7SJerome Forissier 
9602d307b7SJerome Forissier 	trace_printf_helper_raw(TRACE_ERROR, true,
9702d307b7SJerome Forissier 				"TEE load address @ %#"PRIxVA, VCORE_START_VA);
9802d307b7SJerome Forissier 	get_stack_hard_limits(&stack_start, &stack_end);
9902d307b7SJerome Forissier 	print_stack_arm64(&state, stack_start, stack_end - stack_start);
10002d307b7SJerome Forissier }
101adb7766eSMoritz Lummerzheim #endif
102