11bb92983SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause
2923c1f34SJens Wiklander /*
3923c1f34SJens Wiklander * Copyright 2015 Linaro Limited
4923c1f34SJens Wiklander * Copyright 2013-2014 Andrew Turner.
5923c1f34SJens Wiklander * Copyright 2013-2014 Ian Lepore.
6923c1f34SJens Wiklander * Copyright 2013-2014 Rui Paulo.
7923c1f34SJens Wiklander * Copyright 2013 Eitan Adler.
8923c1f34SJens Wiklander * All rights reserved.
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 are
12923c1f34SJens Wiklander * met:
13923c1f34SJens Wiklander *
14923c1f34SJens Wiklander * 1. Redistributions of source code must retain the above copyright
15923c1f34SJens Wiklander * notice, this list of conditions and the following disclaimer.
16923c1f34SJens Wiklander * 2. Redistributions in binary form must reproduce the above copyright
17923c1f34SJens Wiklander * notice, this list of conditions and the following disclaimer in the
18923c1f34SJens Wiklander * documentation and/or other materials provided with the distribution.
19923c1f34SJens Wiklander *
20923c1f34SJens Wiklander * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21923c1f34SJens Wiklander * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22923c1f34SJens Wiklander * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23923c1f34SJens Wiklander * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
24923c1f34SJens Wiklander * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25923c1f34SJens Wiklander * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26923c1f34SJens Wiklander * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27923c1f34SJens Wiklander * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28923c1f34SJens Wiklander * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29923c1f34SJens Wiklander * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
30923c1f34SJens Wiklander * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31923c1f34SJens Wiklander */
32923c1f34SJens Wiklander
33a681fabaSJerome Forissier #include <arm.h>
34e4c86a07SJens Wiklander #include <kernel/linker.h>
35*02d307b7SJerome Forissier #include <kernel/thread.h>
36923c1f34SJens Wiklander #include <kernel/unwind.h>
37923c1f34SJens Wiklander #include <trace.h>
38*02d307b7SJerome Forissier #include <unw/unwind.h>
39a367dcbbSJerome Forissier
40a367dcbbSJerome Forissier #include "unwind_private.h"
41923c1f34SJens Wiklander
42923c1f34SJens Wiklander /* The register names */
43923c1f34SJens Wiklander #define FP 11
44923c1f34SJens Wiklander #define SP 13
45923c1f34SJens Wiklander #define LR 14
46923c1f34SJens Wiklander #define PC 15
47923c1f34SJens Wiklander
find_exidx(vaddr_t addr __unused,vaddr_t * idx_start,vaddr_t * idx_end)48*02d307b7SJerome Forissier bool find_exidx(vaddr_t addr __unused, vaddr_t *idx_start, vaddr_t *idx_end)
49923c1f34SJens Wiklander {
50*02d307b7SJerome Forissier *idx_start = (vaddr_t)__exidx_start;
51*02d307b7SJerome Forissier *idx_end = (vaddr_t)__exidx_end;
52af8149deSJens Wiklander return true;
53af8149deSJens Wiklander }
54af8149deSJens Wiklander
unw_get_kernel_stack(void)55a367dcbbSJerome Forissier vaddr_t *unw_get_kernel_stack(void)
56a367dcbbSJerome Forissier {
57a367dcbbSJerome Forissier size_t n = 0;
58a367dcbbSJerome Forissier size_t size = 0;
59a367dcbbSJerome Forissier size_t exidx_sz = 0;
60a367dcbbSJerome Forissier vaddr_t *tmp = NULL;
61a367dcbbSJerome Forissier vaddr_t *addr = NULL;
62b5ca5ba1SJerome Forissier struct unwind_state_arm32 state = { };
63a367dcbbSJerome Forissier vaddr_t stack = thread_stack_start();
64a367dcbbSJerome Forissier size_t stack_size = thread_stack_size();
65a367dcbbSJerome Forissier
66a367dcbbSJerome Forissier if (SUB_OVERFLOW((vaddr_t)__exidx_end, (vaddr_t)__exidx_start,
67a367dcbbSJerome Forissier &exidx_sz))
68a367dcbbSJerome Forissier return NULL;
69a367dcbbSJerome Forissier
70a367dcbbSJerome Forissier /* r7: Thumb-style frame pointer */
71a367dcbbSJerome Forissier state.registers[7] = read_r7();
72a367dcbbSJerome Forissier /* r11: ARM-style frame pointer */
73a367dcbbSJerome Forissier state.registers[FP] = read_fp();
74a367dcbbSJerome Forissier state.registers[SP] = read_sp();
75a367dcbbSJerome Forissier state.registers[LR] = read_lr();
7619b3fe6cSAngelina Zhao
7719b3fe6cSAngelina Zhao /*
7819b3fe6cSAngelina Zhao * Add 4 to make sure that we have an address well inside this function.
7919b3fe6cSAngelina Zhao * This is needed because we're subtracting 2 from PC when calling
8019b3fe6cSAngelina Zhao * find_index() above. See a comment there for more details.
8119b3fe6cSAngelina Zhao */
8219b3fe6cSAngelina Zhao state.registers[PC] = (uint32_t)unw_get_kernel_stack + 4;
83a367dcbbSJerome Forissier
84*02d307b7SJerome Forissier while (unwind_stack_arm32(&state, stack, stack_size)) {
85a367dcbbSJerome Forissier tmp = unw_grow(addr, &size, (n + 1) * sizeof(vaddr_t));
86a367dcbbSJerome Forissier if (!tmp)
87a367dcbbSJerome Forissier goto err;
88a367dcbbSJerome Forissier addr = tmp;
89a367dcbbSJerome Forissier addr[n] = state.registers[PC];
90a367dcbbSJerome Forissier n++;
91a367dcbbSJerome Forissier }
92a367dcbbSJerome Forissier
93a367dcbbSJerome Forissier if (addr) {
94a367dcbbSJerome Forissier tmp = unw_grow(addr, &size, (n + 1) * sizeof(vaddr_t));
95a367dcbbSJerome Forissier if (!tmp)
96a367dcbbSJerome Forissier goto err;
97a367dcbbSJerome Forissier addr = tmp;
98a367dcbbSJerome Forissier addr[n] = 0;
99a367dcbbSJerome Forissier }
100a367dcbbSJerome Forissier
101a367dcbbSJerome Forissier return addr;
102a367dcbbSJerome Forissier err:
103a367dcbbSJerome Forissier EMSG("Out of memory");
104a367dcbbSJerome Forissier return NULL;
105a367dcbbSJerome Forissier }
106*02d307b7SJerome Forissier
107*02d307b7SJerome Forissier #if (TRACE_LEVEL > 0)
print_kernel_stack(void)108*02d307b7SJerome Forissier void print_kernel_stack(void)
109*02d307b7SJerome Forissier {
110*02d307b7SJerome Forissier struct unwind_state_arm32 state = { };
111*02d307b7SJerome Forissier vaddr_t stack_start = 0;
112*02d307b7SJerome Forissier vaddr_t stack_end = 0;
113*02d307b7SJerome Forissier
114*02d307b7SJerome Forissier /* r7: Thumb-style frame pointer */
115*02d307b7SJerome Forissier state.registers[7] = read_r7();
116*02d307b7SJerome Forissier /* r11: ARM-style frame pointer */
117*02d307b7SJerome Forissier state.registers[FP] = read_fp();
118*02d307b7SJerome Forissier state.registers[SP] = read_sp();
119*02d307b7SJerome Forissier state.registers[LR] = read_lr();
120*02d307b7SJerome Forissier
121*02d307b7SJerome Forissier /*
122*02d307b7SJerome Forissier * Add 4 to make sure that we have an address well inside this function.
123*02d307b7SJerome Forissier * This is needed because we're subtracting 2 from PC when calling
124*02d307b7SJerome Forissier * find_index() above. See a comment there for more details.
125*02d307b7SJerome Forissier */
126*02d307b7SJerome Forissier state.registers[PC] = (uint32_t)print_kernel_stack + 4;
127*02d307b7SJerome Forissier
128*02d307b7SJerome Forissier trace_printf_helper_raw(TRACE_ERROR, true,
129*02d307b7SJerome Forissier "TEE load address @ %#"PRIxVA, VCORE_START_VA);
130*02d307b7SJerome Forissier get_stack_hard_limits(&stack_start, &stack_end);
131*02d307b7SJerome Forissier print_stack_arm32(&state, stack_start, stack_end - stack_start);
132*02d307b7SJerome Forissier }
133a367dcbbSJerome Forissier #endif
134