Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 | /*
* Copyright (c) 2018 Synopsys.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <offsets_short.h>
#include <toolchain.h>
#include <linker/sections.h>
#include <kernel_structs.h>
#include <arch/cpu.h>
#include <syscall.h>
#include <swap_macros.h>
.macro clear_scratch_regs
mov r1, 0
mov r2, 0
mov r3, 0
mov r4, 0
mov r5, 0
mov r6, 0
mov r7, 0
mov r8, 0
mov r9, 0
mov r10, 0
mov r11, 0
mov r12, 0
.endm
.macro clear_callee_regs
mov r25, 0
mov r24, 0
mov r23, 0
mov r22, 0
mov r21, 0
mov r20, 0
mov r19, 0
mov r18, 0
mov r17, 0
mov r16, 0
mov r15, 0
mov r14, 0
mov r13, 0
.endm
GTEXT(_arc_userspace_enter)
GTEXT(_arc_do_syscall)
GTEXT(_user_thread_entry_wrapper)
/*
* @brief Wrapper for _thread_entry in the case of user thread
*
* @return N/A
*/
SECTION_FUNC(TEXT, _user_thread_entry_wrapper)
/* sp the user stack pointer, r0-r4 are in stack */
mov r5, sp
/* start of privilege stack */
add blink, r5, CONFIG_PRIVILEGED_STACK_SIZE+16
/* r4<- start of user stack region */
mov r0, _kernel
ld_s r1, [r0, _kernel_offset_to_current]
ld r4, [r1, ___thread_stack_info_t_start_OFFSET]
/*
* when CONFIG_INIT_STACKS is enable, stack will be initialized
* in _new_thread_init.
*/
j _arc_go_to_user_space
/**
*
* User space entry function
*
* This function is the entry point to user mode from privileged execution.
* The conversion is one way, and threads which transition to user mode do
* not transition back later, unless they are doing system calls.
*
*/
SECTION_FUNC(TEXT, _arc_userspace_enter)
/*
* In ARCv2, the U bit can only be set through exception return
*/
#ifdef CONFIG_ARC_STACK_CHECKING
/* disable stack checking during swap */
lr blink, [_ARC_V2_STATUS32]
bclr blink, blink, _ARC_V2_STATUS32_SC_BIT
kflag blink
#endif
/* the end of user stack in r5 */
add r5, r4, r5
/* start of privilege stack */
add blink, r5, CONFIG_PRIVILEGED_STACK_SIZE
mov sp, r5
push_s r0
push_s r1
push_s r2
push_s r3
mov r5, sp /* skip r0, r1, r2, r3 */
#ifdef CONFIG_INIT_STACKS
mov r0, 0xaaaaaaaa
#else
mov r0, 0x0
#endif
_clear_user_stack:
st.ab r0, [r4, 4]
cmp r4, r5
jlt _clear_user_stack
#ifdef CONFIG_ARC_STACK_CHECKING
mov r1, _kernel
ld_s r2, [r1, _kernel_offset_to_current]
_load_stack_check_regs
lr r0, [_ARC_V2_STATUS32]
bset r0, r0, _ARC_V2_STATUS32_SC_BIT
kflag r0
#endif
_arc_go_to_user_space:
lr r0, [_ARC_V2_STATUS32]
bset r0, r0, _ARC_V2_STATUS32_U_BIT
mov r1, _thread_entry_wrapper
/* fake exception return */
kflag _ARC_V2_STATUS32_AE
sr r0, [_ARC_V2_ERSTATUS]
sr r1, [_ARC_V2_ERET]
#ifdef CONFIG_ARC_HAS_SECURE
lr r0, [_ARC_V2_SEC_STAT]
/* the mode returns from exception return is secure mode */
bset r0, r0, 31
sr r0, [_ARC_V2_ERSEC_STAT]
sr r5, [_ARC_V2_SEC_U_SP]
#else
/* when exception returns from kernel to user, sp and _ARC_V2_USER_SP
* will be switched
*/
sr r5, [_ARC_V2_USER_SP]
#endif
mov sp, blink
mov r0, 0
clear_callee_regs
clear_scratch_regs
mov fp, 0
mov r29, 0
mov r30, 0
mov blink, 0
rtie
/**
*
* Userspace system call function
*
* This function is used to do system calls from unprivileged code. This
* function is responsible for the following:
* 1) Dispatching the system call
* 2) Restoring stack and calling back to the caller of the system call
*
*/
SECTION_FUNC(TEXT, _arc_do_syscall)
/* r0-r5: arg1-arg6, r6 is call id */
/* the call id is already checked in trap_s handler */
push_s blink
mov blink, _k_syscall_table
ld.as r6, [blink, r6]
jl [r6]
/*
* no need to clear callee regs, as they will be saved and restored
* automatically
*/
clear_scratch_regs
mov r29, 0
mov r30, 0
pop_s blink
/* through fake exception return, go back to the caller */
kflag _ARC_V2_STATUS32_AE
/* the status and return address are saved in trap_s handler */
pop r6
sr r6, [_ARC_V2_ERSTATUS]
pop r6
sr r6, [_ARC_V2_ERET]
#ifdef CONFIG_ARC_HAS_SECURE
pop r6
sr r6, [_ARC_V2_ERSEC_STAT]
#endif
mov r6, 0
rtie
|