blob: 1e5d6646bd00928b28a7988739330ae9741b1597 [file] [log] [blame]
/* SPDX-License-Identifier: BSD-2-Clause */
/*
* Copyright (c) 2016, Linaro Limited
* Copyright (c) 2014, STMicroelectronics International N.V.
*/
#ifndef THREAD_PRIVATE_H
#define THREAD_PRIVATE_H
#ifndef __ASSEMBLER__
#include <mm/core_mmu.h>
#include <mm/pgt_cache.h>
#include <kernel/vfp.h>
#include <kernel/mutex.h>
#include <kernel/thread.h>
enum thread_state {
THREAD_STATE_FREE,
THREAD_STATE_SUSPENDED,
THREAD_STATE_ACTIVE,
};
#ifdef ARM32
struct thread_ctx_regs {
uint32_t r0;
uint32_t r1;
uint32_t r2;
uint32_t r3;
uint32_t r4;
uint32_t r5;
uint32_t r6;
uint32_t r7;
uint32_t r8;
uint32_t r9;
uint32_t r10;
uint32_t r11;
uint32_t r12;
uint32_t usr_sp;
uint32_t usr_lr;
uint32_t svc_spsr;
uint32_t svc_sp;
uint32_t svc_lr;
uint32_t pc;
uint32_t cpsr;
};
#endif /*ARM32*/
#ifdef ARM64
struct thread_ctx_regs {
uint64_t sp;
uint64_t pc;
uint64_t cpsr;
uint64_t x[31];
};
#endif /*ARM64*/
#ifdef ARM64
struct thread_user_mode_rec {
uint64_t ctx_regs_ptr;
uint64_t exit_status0_ptr;
uint64_t exit_status1_ptr;
uint64_t pad;
uint64_t x[31 - 19]; /* x19..x30 */
};
#endif /*ARM64*/
#ifdef CFG_WITH_VFP
struct thread_vfp_state {
bool ns_saved;
bool sec_saved;
bool sec_lazy_saved;
struct vfp_state ns;
struct vfp_state sec;
struct thread_user_vfp_state *uvfp;
};
#endif /*CFG_WITH_VFP*/
struct thread_ctx {
struct thread_ctx_regs regs;
enum thread_state state;
vaddr_t stack_va_end;
uint32_t flags;
struct core_mmu_user_map user_map;
bool have_user_map;
#ifdef ARM64
vaddr_t kern_sp; /* Saved kernel SP during user TA execution */
#endif
#ifdef CFG_WITH_VFP
struct thread_vfp_state vfp_state;
#endif
void *rpc_arg;
struct mobj *rpc_mobj;
struct thread_specific_data tsd;
};
#endif /*__ASSEMBLER__*/
#ifdef ARM64
#ifdef CFG_WITH_VFP
#define THREAD_VFP_STATE_SIZE \
(16 + (16 * 32 + 16) * 2 + 16)
#else
#define THREAD_VFP_STATE_SIZE 0
#endif
#endif /*ARM64*/
/* Describes the flags field of struct thread_core_local */
#define THREAD_CLF_SAVED_SHIFT 4
#define THREAD_CLF_CURR_SHIFT 0
#define THREAD_CLF_MASK 0xf
#define THREAD_CLF_TMP_SHIFT 0
#define THREAD_CLF_ABORT_SHIFT 1
#define THREAD_CLF_IRQ_SHIFT 2
#define THREAD_CLF_FIQ_SHIFT 3
#define THREAD_CLF_TMP (1 << THREAD_CLF_TMP_SHIFT)
#define THREAD_CLF_ABORT (1 << THREAD_CLF_ABORT_SHIFT)
#define THREAD_CLF_IRQ (1 << THREAD_CLF_IRQ_SHIFT)
#define THREAD_CLF_FIQ (1 << THREAD_CLF_FIQ_SHIFT)
#ifndef __ASSEMBLER__
extern const void *stack_tmp_export;
extern const uint32_t stack_tmp_stride;
extern struct thread_ctx threads[];
extern thread_pm_handler_t thread_cpu_on_handler_ptr;
extern thread_pm_handler_t thread_cpu_off_handler_ptr;
extern thread_pm_handler_t thread_cpu_suspend_handler_ptr;
extern thread_pm_handler_t thread_cpu_resume_handler_ptr;
extern thread_pm_handler_t thread_system_off_handler_ptr;
extern thread_pm_handler_t thread_system_reset_handler_ptr;
/*
* During boot note the part of code and data that needs to be mapped while
* in user mode. The provided address and size have to be page aligned.
* Note that the code and data will be mapped at the lowest possible
* addresses available for user space (see core_mmu_get_user_va_range()).
*/
extern long thread_user_kcode_offset;
/*
* Initializes VBAR for current CPU (called by thread_init_per_cpu()
*/
void thread_init_vbar(vaddr_t addr);
void thread_excp_vect(void);
void thread_excp_vect_workaround(void);
void thread_excp_vect_workaround_a15(void);
void thread_excp_vect_end(void);
/*
* Assembly function as the first function in a thread. Handles a stdcall,
* a0-a3 holds the parameters. Hands over to __thread_std_smc_entry() when
* everything is set up and does some post processing once
* __thread_std_smc_entry() returns.
*/
void thread_std_smc_entry(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3);
uint32_t __thread_std_smc_entry(uint32_t a0, uint32_t a1, uint32_t a2,
uint32_t a3);
/*
* Resumes execution of currently active thread by restoring context and
* jumping to the instruction where to continue execution.
*
* Arguments supplied by non-secure world will be copied into the saved
* context of the current thread if THREAD_FLAGS_COPY_ARGS_ON_RETURN is set
* in the flags field in the thread context.
*/
void thread_resume(struct thread_ctx_regs *regs);
uint32_t __thread_enter_user_mode(struct thread_ctx_regs *regs,
uint32_t *exit_status0,
uint32_t *exit_status1);
/*
* Private functions made available for thread_asm.S
*/
/* Returns the temp stack for current CPU */
void *thread_get_tmp_sp(void);
/*
* Marks the current thread as suspended. And updated the flags
* for the thread context (see thread resume for use of flags).
* Returns thread index of the thread that was suspended.
*/
int thread_state_suspend(uint32_t flags, uint32_t cpsr, vaddr_t pc);
/*
* Marks the current thread as free.
*/
void thread_state_free(void);
/* Returns a pointer to the saved registers in current thread context. */
struct thread_ctx_regs *thread_get_ctx_regs(void);
#ifdef ARM32
/* Sets sp for abort mode */
void thread_set_abt_sp(vaddr_t sp);
/* Sets sp for undefined mode */
void thread_set_und_sp(vaddr_t sp);
/* Sets sp for irq mode */
void thread_set_irq_sp(vaddr_t sp);
/* Sets sp for fiq mode */
void thread_set_fiq_sp(vaddr_t sp);
#endif /*ARM32*/
/* Checks stack canaries */
void thread_check_canaries(void);
void thread_alloc_and_run(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3);
void thread_resume_from_rpc(uint32_t thread_id, uint32_t a0, uint32_t a1,
uint32_t a2, uint32_t a3);
void thread_lock_global(void);
void thread_unlock_global(void);
/*
* Suspends current thread and temorarily exits to non-secure world.
* This function returns later when non-secure world returns.
*
* The purpose of this function is to request services from non-secure
* world.
*/
#define THREAD_RPC_NUM_ARGS 4
void thread_rpc(uint32_t rv[THREAD_RPC_NUM_ARGS]);
/*
* Called from assembly only, vector_fast_smc_entry(). Handles a fast SMC
* by dispatching it to the registered fast SMC handler.
*/
void thread_handle_fast_smc(struct thread_smc_args *args);
/*
* Called from assembly only, vector_std_smc_entry(). Handles a std SMC by
* dispatching it to the registered std SMC handler.
*/
uint32_t thread_handle_std_smc(uint32_t a0, uint32_t a1, uint32_t a2,
uint32_t a3, uint32_t a4, uint32_t a5,
uint32_t a6, uint32_t a7);
#endif /*__ASSEMBLER__*/
#endif /*THREAD_PRIVATE_H*/