1/*
2 * Copyright 2017, Data61
3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO)
4 * ABN 41 687 119 230.
5 *
6 * This software may be distributed and modified according to the terms of
7 * the GNU General Public License version 2. Note that NO WARRANTY is provided.
8 * See "LICENSE_GPLv2.txt" for details.
9 *
10 * @TAG(DATA61_GPL)
11 */
12
13#include <config.h>
14#include <model/statedata.h>
15#include <arch/fastpath/fastpath.h>
16#include <arch/kernel/traps.h>
17#include <api/syscall.h>
18#include <linker.h>
19#include <machine/fpu.h>
20
21#include <benchmark/benchmark_track.h>
22#include <benchmark/benchmark_utilisation.h>
23
24/** DONT_TRANSLATE */
25void VISIBLE NORETURN restore_user_context(void)
26{
27    NODE_UNLOCK_IF_HELD;
28
29    c_exit_hook();
30
31#ifdef CONFIG_HAVE_FPU
32    lazyFPURestore(NODE_STATE(ksCurThread));
33#endif /* CONFIG_HAVE_FPU */
34
35    writeTPIDRURW(getRegister(NODE_STATE(ksCurThread), TPIDRURW));
36
37    asm volatile(
38        "mov     sp, %0                     \n"
39
40        /* Restore thread's SPSR, LR, and SP */
41        "ldp     x21, x22, [sp, %[SP_EL0]] \n"
42        "ldr     x23, [sp, %[SPSR_EL1]]    \n"
43        "msr     sp_el0, x21                \n"
44#ifdef CONFIG_ARM_HYPERVISOR_SUPPORT
45        "msr     elr_el2, x22               \n"
46        "msr     spsr_el2, x23              \n"
47#else
48        "msr     elr_el1, x22               \n"
49        "msr     spsr_el1, x23              \n"
50#endif
51        /* Restore remaining registers */
52        "ldp     x0,  x1,  [sp, #16 * 0]    \n"
53        "ldp     x2,  x3,  [sp, #16 * 1]    \n"
54        "ldp     x4,  x5,  [sp, #16 * 2]    \n"
55        "ldp     x6,  x7,  [sp, #16 * 3]    \n"
56        "ldp     x8,  x9,  [sp, #16 * 4]    \n"
57        "ldp     x10, x11, [sp, #16 * 5]    \n"
58        "ldp     x12, x13, [sp, #16 * 6]    \n"
59        "ldp     x14, x15, [sp, #16 * 7]    \n"
60        "ldp     x16, x17, [sp, #16 * 8]    \n"
61        "ldp     x18, x19, [sp, #16 * 9]    \n"
62        "ldp     x20, x21, [sp, #16 * 10]   \n"
63        "ldp     x22, x23, [sp, #16 * 11]   \n"
64        "ldp     x24, x25, [sp, #16 * 12]   \n"
65        "ldp     x26, x27, [sp, #16 * 13]   \n"
66        "ldp     x28, x29, [sp, #16 * 14]   \n"
67        "ldr     x30, [sp, %[LR]]          \n"
68        "eret"
69        :
70        : "r" (NODE_STATE(ksCurThread)->tcbArch.tcbContext.registers),
71        [SP_EL0] "i" (PT_SP_EL0), [SPSR_EL1] "i" (PT_SPSR_EL1), [LR] "i" (PT_LR)
72        : "memory"
73    );
74    UNREACHABLE();
75}
76