1 /*
2 * Copyright 2014, General Dynamics C4 Systems
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 */
6
7 #include <config.h>
8 #include <model/statedata.h>
9 #include <arch/fastpath/fastpath.h>
10 #include <arch/kernel/traps.h>
11 #include <arch/machine/debug.h>
12 #include <arch/machine/debug_conf.h>
13 #include <api/syscall.h>
14 #include <linker.h>
15 #include <machine/fpu.h>
16
17 #include <benchmark/benchmark_track.h>
18 #include <benchmark/benchmark_utilisation.h>
19
20 /** DONT_TRANSLATE */
restore_user_context(void)21 void VISIBLE NORETURN restore_user_context(void)
22 {
23 NODE_UNLOCK_IF_HELD;
24
25 word_t cur_thread_reg = (word_t) NODE_STATE(ksCurThread);
26
27 c_exit_hook();
28
29 #ifdef ARM_CP14_SAVE_AND_RESTORE_NATIVE_THREADS
30 restore_user_debug_context(NODE_STATE(ksCurThread));
31 #endif
32
33 #ifdef CONFIG_HAVE_FPU
34 lazyFPURestore(NODE_STATE(ksCurThread));
35 #endif /* CONFIG_HAVE_FPU */
36
37 if (config_set(CONFIG_ARM_HYPERVISOR_SUPPORT)) {
38 asm volatile(
39 /* Set stack pointer to point at the r0 of the user context. */
40 "mov sp, %[cur_thread_reg] \n"
41 /* Pop user registers */
42 "pop {r0-r12} \n"
43 /* Retore the user stack pointer */
44 "pop {lr} \n"
45 "msr sp_usr, lr \n"
46 /* prepare the exception return lr */
47 "ldr lr, [sp, #4] \n"
48 "msr elr_hyp, lr \n"
49 /* prepare the user status register */
50 "ldr lr, [sp, #8] \n"
51 "msr spsr_hyp, lr \n"
52 /* Finally, pop our LR */
53 "pop {lr} \n"
54 /* Return to user */
55 "eret"
56 : /* no output */
57 : [cur_thread_reg] "r"(cur_thread_reg)
58 : "memory"
59 );
60 } else {
61 asm volatile("mov sp, %[cur_thread] \n\
62 ldmdb sp, {r0-lr}^ \n\
63 rfeia sp"
64 : /* no output */
65 : [cur_thread] "r"(cur_thread_reg + NextIP * sizeof(word_t))
66 );
67 }
68 UNREACHABLE();
69 }
70