target/arm: Export arm_v7m_get_sp_ptr
Allow the function to be used outside of m_helper.c. Move to be outside of ifndef CONFIG_USER_ONLY block. Rename from get_v7m_sp_ptr. Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Signed-off-by: David Reiss <dreiss@meta.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20230227213329.793795-14-richard.henderson@linaro.org [rth: Split out of a larger patch] Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
48688c9441
commit
6c8676512f
|
@ -1360,6 +1360,16 @@ void arm_cpu_lpa2_finalize(ARMCPU *cpu, Error **errp);
|
||||||
/* Read the CONTROL register as the MRS instruction would. */
|
/* Read the CONTROL register as the MRS instruction would. */
|
||||||
uint32_t arm_v7m_mrs_control(CPUARMState *env, uint32_t secure);
|
uint32_t arm_v7m_mrs_control(CPUARMState *env, uint32_t secure);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return a pointer to the location where we currently store the
|
||||||
|
* stack pointer for the requested security state and thread mode.
|
||||||
|
* This pointer will become invalid if the CPU state is updated
|
||||||
|
* such that the stack pointers are switched around (eg changing
|
||||||
|
* the SPSEL control bit).
|
||||||
|
*/
|
||||||
|
uint32_t *arm_v7m_get_sp_ptr(CPUARMState *env, bool secure,
|
||||||
|
bool threadmode, bool spsel);
|
||||||
|
|
||||||
#ifdef CONFIG_USER_ONLY
|
#ifdef CONFIG_USER_ONLY
|
||||||
static inline void define_cortex_a72_a57_a53_cp_reginfo(ARMCPU *cpu) { }
|
static inline void define_cortex_a72_a57_a53_cp_reginfo(ARMCPU *cpu) { }
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -650,42 +650,6 @@ void HELPER(v7m_blxns)(CPUARMState *env, uint32_t dest)
|
||||||
arm_rebuild_hflags(env);
|
arm_rebuild_hflags(env);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t *get_v7m_sp_ptr(CPUARMState *env, bool secure, bool threadmode,
|
|
||||||
bool spsel)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Return a pointer to the location where we currently store the
|
|
||||||
* stack pointer for the requested security state and thread mode.
|
|
||||||
* This pointer will become invalid if the CPU state is updated
|
|
||||||
* such that the stack pointers are switched around (eg changing
|
|
||||||
* the SPSEL control bit).
|
|
||||||
* Compare the v8M ARM ARM pseudocode LookUpSP_with_security_mode().
|
|
||||||
* Unlike that pseudocode, we require the caller to pass us in the
|
|
||||||
* SPSEL control bit value; this is because we also use this
|
|
||||||
* function in handling of pushing of the callee-saves registers
|
|
||||||
* part of the v8M stack frame (pseudocode PushCalleeStack()),
|
|
||||||
* and in the tailchain codepath the SPSEL bit comes from the exception
|
|
||||||
* return magic LR value from the previous exception. The pseudocode
|
|
||||||
* opencodes the stack-selection in PushCalleeStack(), but we prefer
|
|
||||||
* to make this utility function generic enough to do the job.
|
|
||||||
*/
|
|
||||||
bool want_psp = threadmode && spsel;
|
|
||||||
|
|
||||||
if (secure == env->v7m.secure) {
|
|
||||||
if (want_psp == v7m_using_psp(env)) {
|
|
||||||
return &env->regs[13];
|
|
||||||
} else {
|
|
||||||
return &env->v7m.other_sp;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (want_psp) {
|
|
||||||
return &env->v7m.other_ss_psp;
|
|
||||||
} else {
|
|
||||||
return &env->v7m.other_ss_msp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool arm_v7m_load_vector(ARMCPU *cpu, int exc, bool targets_secure,
|
static bool arm_v7m_load_vector(ARMCPU *cpu, int exc, bool targets_secure,
|
||||||
uint32_t *pvec)
|
uint32_t *pvec)
|
||||||
{
|
{
|
||||||
|
@ -810,8 +774,8 @@ static bool v7m_push_callee_stack(ARMCPU *cpu, uint32_t lr, bool dotailchain,
|
||||||
!mode;
|
!mode;
|
||||||
|
|
||||||
mmu_idx = arm_v7m_mmu_idx_for_secstate_and_priv(env, M_REG_S, priv);
|
mmu_idx = arm_v7m_mmu_idx_for_secstate_and_priv(env, M_REG_S, priv);
|
||||||
frame_sp_p = get_v7m_sp_ptr(env, M_REG_S, mode,
|
frame_sp_p = arm_v7m_get_sp_ptr(env, M_REG_S, mode,
|
||||||
lr & R_V7M_EXCRET_SPSEL_MASK);
|
lr & R_V7M_EXCRET_SPSEL_MASK);
|
||||||
want_psp = mode && (lr & R_V7M_EXCRET_SPSEL_MASK);
|
want_psp = mode && (lr & R_V7M_EXCRET_SPSEL_MASK);
|
||||||
if (want_psp) {
|
if (want_psp) {
|
||||||
limit = env->v7m.psplim[M_REG_S];
|
limit = env->v7m.psplim[M_REG_S];
|
||||||
|
@ -1656,10 +1620,8 @@ static void do_v7m_exception_exit(ARMCPU *cpu)
|
||||||
* use 'frame_sp_p' after we do something that makes it invalid.
|
* use 'frame_sp_p' after we do something that makes it invalid.
|
||||||
*/
|
*/
|
||||||
bool spsel = env->v7m.control[return_to_secure] & R_V7M_CONTROL_SPSEL_MASK;
|
bool spsel = env->v7m.control[return_to_secure] & R_V7M_CONTROL_SPSEL_MASK;
|
||||||
uint32_t *frame_sp_p = get_v7m_sp_ptr(env,
|
uint32_t *frame_sp_p = arm_v7m_get_sp_ptr(env, return_to_secure,
|
||||||
return_to_secure,
|
!return_to_handler, spsel);
|
||||||
!return_to_handler,
|
|
||||||
spsel);
|
|
||||||
uint32_t frameptr = *frame_sp_p;
|
uint32_t frameptr = *frame_sp_p;
|
||||||
bool pop_ok = true;
|
bool pop_ok = true;
|
||||||
ARMMMUIdx mmu_idx;
|
ARMMMUIdx mmu_idx;
|
||||||
|
@ -1965,7 +1927,7 @@ static bool do_v7m_function_return(ARMCPU *cpu)
|
||||||
threadmode = !arm_v7m_is_handler_mode(env);
|
threadmode = !arm_v7m_is_handler_mode(env);
|
||||||
spsel = env->v7m.control[M_REG_S] & R_V7M_CONTROL_SPSEL_MASK;
|
spsel = env->v7m.control[M_REG_S] & R_V7M_CONTROL_SPSEL_MASK;
|
||||||
|
|
||||||
frame_sp_p = get_v7m_sp_ptr(env, true, threadmode, spsel);
|
frame_sp_p = arm_v7m_get_sp_ptr(env, true, threadmode, spsel);
|
||||||
frameptr = *frame_sp_p;
|
frameptr = *frame_sp_p;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2900,3 +2862,39 @@ uint32_t HELPER(v7m_tt)(CPUARMState *env, uint32_t addr, uint32_t op)
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* !CONFIG_USER_ONLY */
|
#endif /* !CONFIG_USER_ONLY */
|
||||||
|
|
||||||
|
uint32_t *arm_v7m_get_sp_ptr(CPUARMState *env, bool secure, bool threadmode,
|
||||||
|
bool spsel)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Return a pointer to the location where we currently store the
|
||||||
|
* stack pointer for the requested security state and thread mode.
|
||||||
|
* This pointer will become invalid if the CPU state is updated
|
||||||
|
* such that the stack pointers are switched around (eg changing
|
||||||
|
* the SPSEL control bit).
|
||||||
|
* Compare the v8M ARM ARM pseudocode LookUpSP_with_security_mode().
|
||||||
|
* Unlike that pseudocode, we require the caller to pass us in the
|
||||||
|
* SPSEL control bit value; this is because we also use this
|
||||||
|
* function in handling of pushing of the callee-saves registers
|
||||||
|
* part of the v8M stack frame (pseudocode PushCalleeStack()),
|
||||||
|
* and in the tailchain codepath the SPSEL bit comes from the exception
|
||||||
|
* return magic LR value from the previous exception. The pseudocode
|
||||||
|
* opencodes the stack-selection in PushCalleeStack(), but we prefer
|
||||||
|
* to make this utility function generic enough to do the job.
|
||||||
|
*/
|
||||||
|
bool want_psp = threadmode && spsel;
|
||||||
|
|
||||||
|
if (secure == env->v7m.secure) {
|
||||||
|
if (want_psp == v7m_using_psp(env)) {
|
||||||
|
return &env->regs[13];
|
||||||
|
} else {
|
||||||
|
return &env->v7m.other_sp;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (want_psp) {
|
||||||
|
return &env->v7m.other_ss_psp;
|
||||||
|
} else {
|
||||||
|
return &env->v7m.other_ss_msp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue