1/* 2 * Copyright (c) 2022 BayLibre, SAS 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7#include <zephyr/toolchain.h> 8#include <zephyr/linker/sections.h> 9#include <zephyr/kernel.h> 10#include <zephyr/sys/util.h> 11#include <offsets_short.h> 12#include <zephyr/arch/cpu.h> 13#include "asm_macros.inc" 14 15/* Convenience macros for loading/storing register states. */ 16 17#define DO_CALLEE_SAVED(op, reg) \ 18 RV_E( op ra, _thread_offset_to_ra(reg) );\ 19 RV_E( op s0, _thread_offset_to_s0(reg) );\ 20 RV_E( op s1, _thread_offset_to_s1(reg) );\ 21 RV_I( op s2, _thread_offset_to_s2(reg) );\ 22 RV_I( op s3, _thread_offset_to_s3(reg) );\ 23 RV_I( op s4, _thread_offset_to_s4(reg) );\ 24 RV_I( op s5, _thread_offset_to_s5(reg) );\ 25 RV_I( op s6, _thread_offset_to_s6(reg) );\ 26 RV_I( op s7, _thread_offset_to_s7(reg) );\ 27 RV_I( op s8, _thread_offset_to_s8(reg) );\ 28 RV_I( op s9, _thread_offset_to_s9(reg) );\ 29 RV_I( op s10, _thread_offset_to_s10(reg) );\ 30 RV_I( op s11, _thread_offset_to_s11(reg) ) 31 32GTEXT(z_riscv_switch) 33GTEXT(z_thread_mark_switched_in) 34GTEXT(z_riscv_configure_stack_guard) 35GTEXT(z_riscv_fpu_thread_context_switch) 36 37/* void z_riscv_switch(k_thread_t *switch_to, k_thread_t *switch_from) */ 38SECTION_FUNC(TEXT, z_riscv_switch) 39 40 /* Save the old thread's callee-saved registers */ 41 DO_CALLEE_SAVED(sr, a1) 42 43 /* Save the old thread's stack pointer */ 44 sr sp, _thread_offset_to_sp(a1) 45 46 /* Set thread->switch_handle = thread to mark completion */ 47 sr a1, ___thread_t_switch_handle_OFFSET(a1) 48 49 /* Get the new thread's stack pointer */ 50 lr sp, _thread_offset_to_sp(a0) 51 52#if defined(CONFIG_THREAD_LOCAL_STORAGE) 53 /* Get the new thread's tls pointer */ 54 lr tp, _thread_offset_to_tls(a0) 55#endif 56 57#if defined(CONFIG_FPU_SHARING) 58 /* Preserve a0 across following call. s0 is not yet restored. */ 59 mv s0, a0 60 call z_riscv_fpu_thread_context_switch 61 mv a0, s0 62#endif 63 64#if defined(CONFIG_PMP_STACK_GUARD) 65 /* Stack guard has priority over user space for PMP usage. */ 66 mv s0, a0 67 call z_riscv_pmp_stackguard_enable 68 mv a0, s0 69#elif defined(CONFIG_USERSPACE) 70 /* 71 * When stackguard is not enabled, we need to configure the PMP only 72 * at context switch time as the PMP is not in effect while inm-mode. 73 * (it is done on every exception return otherwise). 74 */ 75 lb t0, _thread_offset_to_user_options(a0) 76 andi t0, t0, K_USER 77 beqz t0, not_user_task 78 mv s0, a0 79 call z_riscv_pmp_usermode_enable 80 mv a0, s0 81not_user_task: 82#endif 83 84#if CONFIG_INSTRUMENT_THREAD_SWITCHING 85 mv s0, a0 86 call z_thread_mark_switched_in 87 mv a0, s0 88#endif 89 90 /* Restore the new thread's callee-saved registers */ 91 DO_CALLEE_SAVED(lr, a0) 92 93 /* Return to arch_switch() or _irq_wrapper() */ 94 ret 95