mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2024-12-23 08:15:37 +00:00
target/arm: Add v8M stack checks on ADD/SUB/MOV of SP
Add code to insert calls to a helper function to do the stack limit checking when we handle these forms of instruction that write to SP: * ADD (SP plus immediate) * ADD (SP plus register) * SUB (SP minus immediate) * SUB (SP minus register) * MOV (register) Backports commit 5520318939fea5d659bf808157cd726cb967b761 from qemu
This commit is contained in:
parent
b2146058c3
commit
ca5d7b8fd2
|
@ -1707,6 +1707,7 @@
|
|||
#define helper_v7m_mrs helper_v7m_mrs_aarch64
|
||||
#define helper_v7m_msr helper_v7m_msr_aarch64
|
||||
#define helper_v7m_tt helper_v7m_tt_aarch64
|
||||
#define helper_v8m_stackcheck helper_v8m_stackcheck_aarch64
|
||||
#define helper_vfp_absd helper_vfp_absd_aarch64
|
||||
#define helper_vfp_abss helper_vfp_abss_aarch64
|
||||
#define helper_vfp_addd helper_vfp_addd_aarch64
|
||||
|
|
|
@ -1707,6 +1707,7 @@
|
|||
#define helper_v7m_mrs helper_v7m_mrs_aarch64eb
|
||||
#define helper_v7m_msr helper_v7m_msr_aarch64eb
|
||||
#define helper_v7m_tt helper_v7m_tt_aarch64eb
|
||||
#define helper_v8m_stackcheck helper_v8m_stackcheck_aarch64eb
|
||||
#define helper_vfp_absd helper_vfp_absd_aarch64eb
|
||||
#define helper_vfp_abss helper_vfp_abss_aarch64eb
|
||||
#define helper_vfp_addd helper_vfp_addd_aarch64eb
|
||||
|
|
|
@ -1707,6 +1707,7 @@
|
|||
#define helper_v7m_mrs helper_v7m_mrs_arm
|
||||
#define helper_v7m_msr helper_v7m_msr_arm
|
||||
#define helper_v7m_tt helper_v7m_tt_arm
|
||||
#define helper_v8m_stackcheck helper_v8m_stackcheck_arm
|
||||
#define helper_vfp_absd helper_vfp_absd_arm
|
||||
#define helper_vfp_abss helper_vfp_abss_arm
|
||||
#define helper_vfp_addd helper_vfp_addd_arm
|
||||
|
|
|
@ -1707,6 +1707,7 @@
|
|||
#define helper_v7m_mrs helper_v7m_mrs_armeb
|
||||
#define helper_v7m_msr helper_v7m_msr_armeb
|
||||
#define helper_v7m_tt helper_v7m_tt_armeb
|
||||
#define helper_v8m_stackcheck helper_v8m_stackcheck_armeb
|
||||
#define helper_vfp_absd helper_vfp_absd_armeb
|
||||
#define helper_vfp_abss helper_vfp_abss_armeb
|
||||
#define helper_vfp_addd helper_vfp_addd_armeb
|
||||
|
|
|
@ -1713,6 +1713,7 @@ symbols = (
|
|||
'helper_v7m_mrs',
|
||||
'helper_v7m_msr',
|
||||
'helper_v7m_tt',
|
||||
'helper_v8m_stackcheck',
|
||||
'helper_vfp_absd',
|
||||
'helper_vfp_abss',
|
||||
'helper_vfp_addd',
|
||||
|
|
|
@ -1707,6 +1707,7 @@
|
|||
#define helper_v7m_mrs helper_v7m_mrs_m68k
|
||||
#define helper_v7m_msr helper_v7m_msr_m68k
|
||||
#define helper_v7m_tt helper_v7m_tt_m68k
|
||||
#define helper_v8m_stackcheck helper_v8m_stackcheck_m68k
|
||||
#define helper_vfp_absd helper_vfp_absd_m68k
|
||||
#define helper_vfp_abss helper_vfp_abss_m68k
|
||||
#define helper_vfp_addd helper_vfp_addd_m68k
|
||||
|
|
|
@ -1707,6 +1707,7 @@
|
|||
#define helper_v7m_mrs helper_v7m_mrs_mips
|
||||
#define helper_v7m_msr helper_v7m_msr_mips
|
||||
#define helper_v7m_tt helper_v7m_tt_mips
|
||||
#define helper_v8m_stackcheck helper_v8m_stackcheck_mips
|
||||
#define helper_vfp_absd helper_vfp_absd_mips
|
||||
#define helper_vfp_abss helper_vfp_abss_mips
|
||||
#define helper_vfp_addd helper_vfp_addd_mips
|
||||
|
|
|
@ -1707,6 +1707,7 @@
|
|||
#define helper_v7m_mrs helper_v7m_mrs_mips64
|
||||
#define helper_v7m_msr helper_v7m_msr_mips64
|
||||
#define helper_v7m_tt helper_v7m_tt_mips64
|
||||
#define helper_v8m_stackcheck helper_v8m_stackcheck_mips64
|
||||
#define helper_vfp_absd helper_vfp_absd_mips64
|
||||
#define helper_vfp_abss helper_vfp_abss_mips64
|
||||
#define helper_vfp_addd helper_vfp_addd_mips64
|
||||
|
|
|
@ -1707,6 +1707,7 @@
|
|||
#define helper_v7m_mrs helper_v7m_mrs_mips64el
|
||||
#define helper_v7m_msr helper_v7m_msr_mips64el
|
||||
#define helper_v7m_tt helper_v7m_tt_mips64el
|
||||
#define helper_v8m_stackcheck helper_v8m_stackcheck_mips64el
|
||||
#define helper_vfp_absd helper_vfp_absd_mips64el
|
||||
#define helper_vfp_abss helper_vfp_abss_mips64el
|
||||
#define helper_vfp_addd helper_vfp_addd_mips64el
|
||||
|
|
|
@ -1707,6 +1707,7 @@
|
|||
#define helper_v7m_mrs helper_v7m_mrs_mipsel
|
||||
#define helper_v7m_msr helper_v7m_msr_mipsel
|
||||
#define helper_v7m_tt helper_v7m_tt_mipsel
|
||||
#define helper_v8m_stackcheck helper_v8m_stackcheck_mipsel
|
||||
#define helper_vfp_absd helper_vfp_absd_mipsel
|
||||
#define helper_vfp_abss helper_vfp_abss_mipsel
|
||||
#define helper_vfp_addd helper_vfp_addd_mipsel
|
||||
|
|
|
@ -1707,6 +1707,7 @@
|
|||
#define helper_v7m_mrs helper_v7m_mrs_powerpc
|
||||
#define helper_v7m_msr helper_v7m_msr_powerpc
|
||||
#define helper_v7m_tt helper_v7m_tt_powerpc
|
||||
#define helper_v8m_stackcheck helper_v8m_stackcheck_powerpc
|
||||
#define helper_vfp_absd helper_vfp_absd_powerpc
|
||||
#define helper_vfp_abss helper_vfp_abss_powerpc
|
||||
#define helper_vfp_addd helper_vfp_addd_powerpc
|
||||
|
|
|
@ -1707,6 +1707,7 @@
|
|||
#define helper_v7m_mrs helper_v7m_mrs_riscv32
|
||||
#define helper_v7m_msr helper_v7m_msr_riscv32
|
||||
#define helper_v7m_tt helper_v7m_tt_riscv32
|
||||
#define helper_v8m_stackcheck helper_v8m_stackcheck_riscv32
|
||||
#define helper_vfp_absd helper_vfp_absd_riscv32
|
||||
#define helper_vfp_abss helper_vfp_abss_riscv32
|
||||
#define helper_vfp_addd helper_vfp_addd_riscv32
|
||||
|
|
|
@ -1707,6 +1707,7 @@
|
|||
#define helper_v7m_mrs helper_v7m_mrs_riscv64
|
||||
#define helper_v7m_msr helper_v7m_msr_riscv64
|
||||
#define helper_v7m_tt helper_v7m_tt_riscv64
|
||||
#define helper_v8m_stackcheck helper_v8m_stackcheck_riscv64
|
||||
#define helper_vfp_absd helper_vfp_absd_riscv64
|
||||
#define helper_vfp_abss helper_vfp_abss_riscv64
|
||||
#define helper_vfp_addd helper_vfp_addd_riscv64
|
||||
|
|
|
@ -1707,6 +1707,7 @@
|
|||
#define helper_v7m_mrs helper_v7m_mrs_sparc
|
||||
#define helper_v7m_msr helper_v7m_msr_sparc
|
||||
#define helper_v7m_tt helper_v7m_tt_sparc
|
||||
#define helper_v8m_stackcheck helper_v8m_stackcheck_sparc
|
||||
#define helper_vfp_absd helper_vfp_absd_sparc
|
||||
#define helper_vfp_abss helper_vfp_abss_sparc
|
||||
#define helper_vfp_addd helper_vfp_addd_sparc
|
||||
|
|
|
@ -1707,6 +1707,7 @@
|
|||
#define helper_v7m_mrs helper_v7m_mrs_sparc64
|
||||
#define helper_v7m_msr helper_v7m_msr_sparc64
|
||||
#define helper_v7m_tt helper_v7m_tt_sparc64
|
||||
#define helper_v8m_stackcheck helper_v8m_stackcheck_sparc64
|
||||
#define helper_vfp_absd helper_vfp_absd_sparc64
|
||||
#define helper_vfp_abss helper_vfp_abss_sparc64
|
||||
#define helper_vfp_addd helper_vfp_addd_sparc64
|
||||
|
|
|
@ -71,6 +71,8 @@ DEF_HELPER_2(v7m_blxns, void, env, i32)
|
|||
|
||||
DEF_HELPER_3(v7m_tt, i32, env, i32, i32)
|
||||
|
||||
DEF_HELPER_2(v8m_stackcheck, void, env, i32)
|
||||
|
||||
DEF_HELPER_4(access_check_cp_reg, void, env, ptr, i32, i32)
|
||||
DEF_HELPER_3(set_cp_reg, void, env, ptr, i32)
|
||||
DEF_HELPER_2(get_cp_reg, i32, env, ptr)
|
||||
|
|
|
@ -819,4 +819,18 @@ static inline bool v7m_using_psp(CPUARMState *env)
|
|||
env->v7m.control[env->v7m.secure] & R_V7M_CONTROL_SPSEL_MASK;
|
||||
}
|
||||
|
||||
/**
|
||||
* v7m_sp_limit: Return SP limit for current CPU state
|
||||
* Return the SP limit value for the current CPU security state
|
||||
* and stack pointer.
|
||||
*/
|
||||
static inline uint32_t v7m_sp_limit(CPUARMState *env)
|
||||
{
|
||||
if (v7m_using_psp(env)) {
|
||||
return env->v7m.psplim[env->v7m.secure];
|
||||
} else {
|
||||
return env->v7m.msplim[env->v7m.secure];
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -237,6 +237,25 @@ void arm_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
|
|||
|
||||
#endif /* !defined(CONFIG_USER_ONLY) */
|
||||
|
||||
void HELPER(v8m_stackcheck)(CPUARMState *env, uint32_t newvalue)
|
||||
{
|
||||
/*
|
||||
* Perform the v8M stack limit check for SP updates from translated code,
|
||||
* raising an exception if the limit is breached.
|
||||
*/
|
||||
if (newvalue < v7m_sp_limit(env)) {
|
||||
CPUState *cs = CPU(arm_env_get_cpu(env));
|
||||
|
||||
/*
|
||||
* Stack limit exceptions are a rare case, so rather than syncing
|
||||
* PC/condbits before the call, we use cpu_restore_state() to
|
||||
* get them right before raising the exception.
|
||||
*/
|
||||
cpu_restore_state(cs, GETPC(), true);
|
||||
raise_exception(env, EXCP_STKOF, 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t HELPER(add_setq)(CPUARMState *env, uint32_t a, uint32_t b)
|
||||
{
|
||||
uint32_t res = a + b;
|
||||
|
|
|
@ -235,6 +235,25 @@ static void store_reg(DisasContext *s, int reg, TCGv_i32 var)
|
|||
tcg_temp_free_i32(tcg_ctx, var);
|
||||
}
|
||||
|
||||
/*
|
||||
* Variant of store_reg which applies v8M stack-limit checks before updating
|
||||
* SP. If the check fails this will result in an exception being taken.
|
||||
* We disable the stack checks for CONFIG_USER_ONLY because we have
|
||||
* no idea what the stack limits should be in that case.
|
||||
* If stack checking is not being done this just acts like store_reg().
|
||||
*/
|
||||
static void store_sp_checked(DisasContext *s, TCGv_i32 var)
|
||||
{
|
||||
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
if (s->v8m_stackcheck) {
|
||||
gen_helper_v8m_stackcheck(tcg_ctx, tcg_ctx->cpu_env, var);
|
||||
}
|
||||
#endif
|
||||
store_reg(s, 13, var);
|
||||
}
|
||||
|
||||
/* Value extensions. */
|
||||
#define gen_uxtb(var) tcg_gen_ext8u_i32(tcg_ctx, var, var)
|
||||
#define gen_uxth(var) tcg_gen_ext16u_i32(tcg_ctx, var, var)
|
||||
|
@ -10769,7 +10788,13 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
|
|||
if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))
|
||||
goto illegal_op;
|
||||
tcg_temp_free_i32(tcg_ctx, tmp2);
|
||||
if (rd != 15) {
|
||||
if (rd == 13 &&
|
||||
((op == 2 && rn == 15) ||
|
||||
(op == 8 && rn == 13) ||
|
||||
(op == 13 && rn == 13))) {
|
||||
/* MOV SP, ... or ADD SP, SP, ... or SUB SP, SP, ... */
|
||||
store_sp_checked(s, tmp);
|
||||
} else if (rd != 15) {
|
||||
store_reg(s, rd, tmp);
|
||||
} else {
|
||||
tcg_temp_free_i32(tcg_ctx, tmp);
|
||||
|
@ -11453,8 +11478,15 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
|
|||
gen_jmp(s, s->pc + offset);
|
||||
}
|
||||
} else {
|
||||
/* Data processing immediate. */
|
||||
/*
|
||||
* 0b1111_0xxx_xxxx_0xxx_xxxx_xxxx
|
||||
* - Data-processing (modified immediate, plain binary immediate)
|
||||
*/
|
||||
if (insn & (1 << 25)) {
|
||||
/*
|
||||
* 0b1111_0x1x_xxxx_0xxx_xxxx_xxxx
|
||||
* - Data-processing (plain binary immediate)
|
||||
*/
|
||||
if (insn & (1 << 24)) {
|
||||
if (insn & (1 << 20))
|
||||
goto illegal_op;
|
||||
|
@ -11550,6 +11582,7 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
|
|||
tmp = tcg_temp_new_i32(tcg_ctx);
|
||||
tcg_gen_movi_i32(tcg_ctx, tmp, imm);
|
||||
}
|
||||
store_reg(s, rd, tmp);
|
||||
} else {
|
||||
/* Add/sub 12-bit immediate. */
|
||||
if (rn == 15) {
|
||||
|
@ -11560,17 +11593,27 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
|
|||
offset += imm;
|
||||
tmp = tcg_temp_new_i32(tcg_ctx);
|
||||
tcg_gen_movi_i32(tcg_ctx, tmp, offset);
|
||||
store_reg(s, rd, tmp);
|
||||
} else {
|
||||
tmp = load_reg(s, rn);
|
||||
if (insn & (1 << 23))
|
||||
tcg_gen_subi_i32(tcg_ctx, tmp, tmp, imm);
|
||||
else
|
||||
tcg_gen_addi_i32(tcg_ctx, tmp, tmp, imm);
|
||||
}
|
||||
}
|
||||
if (rn == 13 && rd == 13) {
|
||||
/* ADD SP, SP, imm or SUB SP, SP, imm */
|
||||
store_sp_checked(s, tmp);
|
||||
} else {
|
||||
store_reg(s, rd, tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* 0b1111_0x0x_xxxx_0xxx_xxxx_xxxx
|
||||
* - Data-processing (modified immediate)
|
||||
*/
|
||||
int shifter_out = 0;
|
||||
/* modified 12-bit immediate. */
|
||||
shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
|
||||
|
@ -11612,7 +11655,11 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
|
|||
goto illegal_op;
|
||||
tcg_temp_free_i32(tcg_ctx, tmp2);
|
||||
rd = (insn >> 8) & 0xf;
|
||||
if (rd != 15) {
|
||||
if (rd == 13 && rn == 13
|
||||
&& (op == 8 || op == 13)) {
|
||||
/* ADD(S) SP, SP, imm or SUB(S) SP, SP, imm */
|
||||
store_sp_checked(s, tmp);
|
||||
} else if (rd != 15) {
|
||||
store_reg(s, rd, tmp);
|
||||
} else {
|
||||
tcg_temp_free_i32(tcg_ctx, tmp);
|
||||
|
@ -11945,7 +11992,12 @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn)
|
|||
tmp2 = load_reg(s, rm);
|
||||
tcg_gen_add_i32(tcg_ctx, tmp, tmp, tmp2);
|
||||
tcg_temp_free_i32(tcg_ctx, tmp2);
|
||||
if (rd == 13) {
|
||||
/* ADD SP, SP, reg */
|
||||
store_sp_checked(s, tmp);
|
||||
} else {
|
||||
store_reg(s, rd, tmp);
|
||||
}
|
||||
break;
|
||||
case 1: /* cmp */
|
||||
tmp = load_reg(s, rd);
|
||||
|
@ -11956,7 +12008,12 @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn)
|
|||
break;
|
||||
case 2: /* mov/cpy */
|
||||
tmp = load_reg(s, rm);
|
||||
if (rd == 13) {
|
||||
/* MOV SP, reg */
|
||||
store_sp_checked(s, tmp);
|
||||
} else {
|
||||
store_reg(s, rd, tmp);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
{
|
||||
|
@ -12284,7 +12341,10 @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn)
|
|||
break;
|
||||
|
||||
case 10:
|
||||
/* add to high reg */
|
||||
/*
|
||||
* 0b1010_xxxx_xxxx_xxxx
|
||||
* - Add PC/SP (immediate)
|
||||
*/
|
||||
rd = (insn >> 8) & 7;
|
||||
if (insn & (1 << 11)) {
|
||||
/* SP */
|
||||
|
@ -12304,13 +12364,17 @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn)
|
|||
op = (insn >> 8) & 0xf;
|
||||
switch (op) {
|
||||
case 0:
|
||||
/* adjust stack pointer */
|
||||
/*
|
||||
* 0b1011_0000_xxxx_xxxx
|
||||
* - ADD (SP plus immediate)
|
||||
* - SUB (SP minus immediate)
|
||||
*/
|
||||
tmp = load_reg(s, 13);
|
||||
val = (insn & 0x7f) * 4;
|
||||
if (insn & (1 << 7))
|
||||
val = -(int32_t)val;
|
||||
tcg_gen_addi_i32(tcg_ctx, tmp, tmp, val);
|
||||
store_reg(s, 13, tmp);
|
||||
store_sp_checked(s, tmp);
|
||||
break;
|
||||
|
||||
case 2: /* sign/zero extend. */
|
||||
|
|
|
@ -1707,6 +1707,7 @@
|
|||
#define helper_v7m_mrs helper_v7m_mrs_x86_64
|
||||
#define helper_v7m_msr helper_v7m_msr_x86_64
|
||||
#define helper_v7m_tt helper_v7m_tt_x86_64
|
||||
#define helper_v8m_stackcheck helper_v8m_stackcheck_x86_64
|
||||
#define helper_vfp_absd helper_vfp_absd_x86_64
|
||||
#define helper_vfp_abss helper_vfp_abss_x86_64
|
||||
#define helper_vfp_addd helper_vfp_addd_x86_64
|
||||
|
|
Loading…
Reference in a new issue