/* * Copyright 2014, General Dynamics C4 Systems * * SPDX-License-Identifier: GPL-2.0-only */ #include #include #include #include #include #include #include #include #include #include #include /** DONT_TRANSLATE */ void VISIBLE NORETURN restore_user_context(void) { NODE_UNLOCK_IF_HELD; word_t cur_thread_reg = (word_t) NODE_STATE(ksCurThread); c_exit_hook(); #ifdef ARM_CP14_SAVE_AND_RESTORE_NATIVE_THREADS restore_user_debug_context(NODE_STATE(ksCurThread)); #endif #ifdef CONFIG_HAVE_FPU lazyFPURestore(NODE_STATE(ksCurThread)); #endif /* CONFIG_HAVE_FPU */ if (config_set(CONFIG_ARM_HYPERVISOR_SUPPORT)) { asm volatile( /* Set stack pointer to point at the r0 of the user context. */ "mov sp, %[cur_thread_reg] \n" /* Pop user registers */ "pop {r0-r12} \n" /* Retore the user stack pointer */ "pop {lr} \n" "msr sp_usr, lr \n" /* prepare the exception return lr */ "ldr lr, [sp, #4] \n" "msr elr_hyp, lr \n" /* prepare the user status register */ "ldr lr, [sp, #8] \n" "msr spsr_hyp, lr \n" /* Finally, pop our LR */ "pop {lr} \n" /* Return to user */ "eret" : /* no output */ : [cur_thread_reg] "r"(cur_thread_reg) : "memory" ); } else { asm volatile("mov sp, %[cur_thread] \n\ ldmdb sp, {r0-lr}^ \n\ rfeia sp" : /* no output */ : [cur_thread] "r"(cur_thread_reg + NextIP * sizeof(word_t)) ); } UNREACHABLE(); }