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 */ 21void 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