From 6ae2357be6c3228d6db4504c3cbedf1f9a212ac2 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 20 Feb 2018 22:06:30 -0500 Subject: [PATCH] target-arm: Give CPSR setting on 32-bit exception return its own helper The rules for setting the CPSR on a 32-bit exception return are subtly different from those for setting the CPSR via an instruction like MSR or CPS. (In particular, in Hyp mode changing the mode bits is not valid via MSR or CPS.) Split the exception-return case into its own helper for setting CPSR, so we can eventually handle them differently in the helper function. Backports commit 235ea1f5c89abf30e452539b973b0dbe43d3fe2b from qemu --- qemu/aarch64.h | 2 ++ qemu/aarch64eb.h | 2 ++ qemu/arm.h | 2 ++ qemu/armeb.h | 2 ++ qemu/header_gen.py | 2 ++ qemu/m68k.h | 2 ++ qemu/mips.h | 2 ++ qemu/mips64.h | 2 ++ qemu/mips64el.h | 2 ++ qemu/mipsel.h | 2 ++ qemu/powerpc.h | 2 ++ qemu/sparc.h | 2 ++ qemu/sparc64.h | 2 ++ qemu/target-arm/helper.h | 1 + qemu/target-arm/op_helper.c | 6 ++++++ qemu/target-arm/translate.c | 6 +++--- qemu/x86_64.h | 2 ++ 17 files changed, 38 insertions(+), 3 deletions(-) diff --git a/qemu/aarch64.h b/qemu/aarch64.h index d7ada6ea..b6de9963 100644 --- a/qemu/aarch64.h +++ b/qemu/aarch64.h @@ -681,6 +681,7 @@ #define gen_helper_clz_arm gen_helper_clz_arm_aarch64 #define gen_helper_cpsr_read gen_helper_cpsr_read_aarch64 #define gen_helper_cpsr_write gen_helper_cpsr_write_aarch64 +#define gen_helper_cpsr_write_eret gen_helper_cpsr_write_eret_aarch64 #define gen_helper_crc32_arm gen_helper_crc32_arm_aarch64 #define gen_helper_crc32c gen_helper_crc32c_aarch64 #define gen_helper_crypto_aese gen_helper_crypto_aese_aarch64 @@ -1400,6 +1401,7 @@ #define helper_clz_arm helper_clz_arm_aarch64 #define helper_cpsr_read helper_cpsr_read_aarch64 #define helper_cpsr_write helper_cpsr_write_aarch64 +#define helper_cpsr_write_eret helper_cpsr_write_eret_aarch64 #define helper_crc32_arm helper_crc32_arm_aarch64 #define helper_crc32c helper_crc32c_aarch64 #define helper_crypto_aese helper_crypto_aese_aarch64 diff --git a/qemu/aarch64eb.h b/qemu/aarch64eb.h index 95f25aea..e60cead5 100644 --- a/qemu/aarch64eb.h +++ b/qemu/aarch64eb.h @@ -681,6 +681,7 @@ #define gen_helper_clz_arm gen_helper_clz_arm_aarch64eb #define gen_helper_cpsr_read gen_helper_cpsr_read_aarch64eb #define gen_helper_cpsr_write gen_helper_cpsr_write_aarch64eb +#define gen_helper_cpsr_write_eret gen_helper_cpsr_write_eret_aarch64eb #define gen_helper_crc32_arm gen_helper_crc32_arm_aarch64eb #define gen_helper_crc32c gen_helper_crc32c_aarch64eb #define gen_helper_crypto_aese gen_helper_crypto_aese_aarch64eb @@ -1400,6 +1401,7 @@ #define helper_clz_arm helper_clz_arm_aarch64eb #define helper_cpsr_read helper_cpsr_read_aarch64eb #define helper_cpsr_write helper_cpsr_write_aarch64eb +#define helper_cpsr_write_eret helper_cpsr_write_eret_aarch64eb #define helper_crc32_arm helper_crc32_arm_aarch64eb #define helper_crc32c helper_crc32c_aarch64eb #define helper_crypto_aese helper_crypto_aese_aarch64eb diff --git a/qemu/arm.h b/qemu/arm.h index 13121a33..38af2db4 100644 --- a/qemu/arm.h +++ b/qemu/arm.h @@ -681,6 +681,7 @@ #define gen_helper_clz_arm gen_helper_clz_arm_arm #define gen_helper_cpsr_read gen_helper_cpsr_read_arm #define gen_helper_cpsr_write gen_helper_cpsr_write_arm +#define gen_helper_cpsr_write_eret gen_helper_cpsr_write_eret_arm #define gen_helper_crc32_arm gen_helper_crc32_arm_arm #define gen_helper_crc32c gen_helper_crc32c_arm #define gen_helper_crypto_aese gen_helper_crypto_aese_arm @@ -1400,6 +1401,7 @@ #define helper_clz_arm helper_clz_arm_arm #define helper_cpsr_read helper_cpsr_read_arm #define helper_cpsr_write helper_cpsr_write_arm +#define helper_cpsr_write_eret helper_cpsr_write_eret_arm #define helper_crc32_arm helper_crc32_arm_arm #define helper_crc32c helper_crc32c_arm #define helper_crypto_aese helper_crypto_aese_arm diff --git a/qemu/armeb.h b/qemu/armeb.h index 2c318666..9c6d819c 100644 --- a/qemu/armeb.h +++ b/qemu/armeb.h @@ -681,6 +681,7 @@ #define gen_helper_clz_arm gen_helper_clz_arm_armeb #define gen_helper_cpsr_read gen_helper_cpsr_read_armeb #define gen_helper_cpsr_write gen_helper_cpsr_write_armeb +#define gen_helper_cpsr_write_eret gen_helper_cpsr_write_eret_armeb #define gen_helper_crc32_arm gen_helper_crc32_arm_armeb #define gen_helper_crc32c gen_helper_crc32c_armeb #define gen_helper_crypto_aese gen_helper_crypto_aese_armeb @@ -1400,6 +1401,7 @@ #define helper_clz_arm helper_clz_arm_armeb #define helper_cpsr_read helper_cpsr_read_armeb #define helper_cpsr_write helper_cpsr_write_armeb +#define helper_cpsr_write_eret helper_cpsr_write_eret_armeb #define helper_crc32_arm helper_crc32_arm_armeb #define helper_crc32c helper_crc32c_armeb #define helper_crypto_aese helper_crypto_aese_armeb diff --git a/qemu/header_gen.py b/qemu/header_gen.py index 1877eebd..3192b4d4 100644 --- a/qemu/header_gen.py +++ b/qemu/header_gen.py @@ -687,6 +687,7 @@ symbols = ( 'gen_helper_clz_arm', 'gen_helper_cpsr_read', 'gen_helper_cpsr_write', + 'gen_helper_cpsr_write_eret', 'gen_helper_crc32_arm', 'gen_helper_crc32c', 'gen_helper_crypto_aese', @@ -1406,6 +1407,7 @@ symbols = ( 'helper_clz_arm', 'helper_cpsr_read', 'helper_cpsr_write', + 'helper_cpsr_write_eret', 'helper_crc32_arm', 'helper_crc32c', 'helper_crypto_aese', diff --git a/qemu/m68k.h b/qemu/m68k.h index c1e234f7..04a9e8d2 100644 --- a/qemu/m68k.h +++ b/qemu/m68k.h @@ -681,6 +681,7 @@ #define gen_helper_clz_arm gen_helper_clz_arm_m68k #define gen_helper_cpsr_read gen_helper_cpsr_read_m68k #define gen_helper_cpsr_write gen_helper_cpsr_write_m68k +#define gen_helper_cpsr_write_eret gen_helper_cpsr_write_eret_m68k #define gen_helper_crc32_arm gen_helper_crc32_arm_m68k #define gen_helper_crc32c gen_helper_crc32c_m68k #define gen_helper_crypto_aese gen_helper_crypto_aese_m68k @@ -1400,6 +1401,7 @@ #define helper_clz_arm helper_clz_arm_m68k #define helper_cpsr_read helper_cpsr_read_m68k #define helper_cpsr_write helper_cpsr_write_m68k +#define helper_cpsr_write_eret helper_cpsr_write_eret_m68k #define helper_crc32_arm helper_crc32_arm_m68k #define helper_crc32c helper_crc32c_m68k #define helper_crypto_aese helper_crypto_aese_m68k diff --git a/qemu/mips.h b/qemu/mips.h index 448b1bc9..96eebc44 100644 --- a/qemu/mips.h +++ b/qemu/mips.h @@ -681,6 +681,7 @@ #define gen_helper_clz_arm gen_helper_clz_arm_mips #define gen_helper_cpsr_read gen_helper_cpsr_read_mips #define gen_helper_cpsr_write gen_helper_cpsr_write_mips +#define gen_helper_cpsr_write_eret gen_helper_cpsr_write_eret_mips #define gen_helper_crc32_arm gen_helper_crc32_arm_mips #define gen_helper_crc32c gen_helper_crc32c_mips #define gen_helper_crypto_aese gen_helper_crypto_aese_mips @@ -1400,6 +1401,7 @@ #define helper_clz_arm helper_clz_arm_mips #define helper_cpsr_read helper_cpsr_read_mips #define helper_cpsr_write helper_cpsr_write_mips +#define helper_cpsr_write_eret helper_cpsr_write_eret_mips #define helper_crc32_arm helper_crc32_arm_mips #define helper_crc32c helper_crc32c_mips #define helper_crypto_aese helper_crypto_aese_mips diff --git a/qemu/mips64.h b/qemu/mips64.h index f76c9b81..e2becb2f 100644 --- a/qemu/mips64.h +++ b/qemu/mips64.h @@ -681,6 +681,7 @@ #define gen_helper_clz_arm gen_helper_clz_arm_mips64 #define gen_helper_cpsr_read gen_helper_cpsr_read_mips64 #define gen_helper_cpsr_write gen_helper_cpsr_write_mips64 +#define gen_helper_cpsr_write_eret gen_helper_cpsr_write_eret_mips64 #define gen_helper_crc32_arm gen_helper_crc32_arm_mips64 #define gen_helper_crc32c gen_helper_crc32c_mips64 #define gen_helper_crypto_aese gen_helper_crypto_aese_mips64 @@ -1400,6 +1401,7 @@ #define helper_clz_arm helper_clz_arm_mips64 #define helper_cpsr_read helper_cpsr_read_mips64 #define helper_cpsr_write helper_cpsr_write_mips64 +#define helper_cpsr_write_eret helper_cpsr_write_eret_mips64 #define helper_crc32_arm helper_crc32_arm_mips64 #define helper_crc32c helper_crc32c_mips64 #define helper_crypto_aese helper_crypto_aese_mips64 diff --git a/qemu/mips64el.h b/qemu/mips64el.h index 0d42ad24..7d9ab32f 100644 --- a/qemu/mips64el.h +++ b/qemu/mips64el.h @@ -681,6 +681,7 @@ #define gen_helper_clz_arm gen_helper_clz_arm_mips64el #define gen_helper_cpsr_read gen_helper_cpsr_read_mips64el #define gen_helper_cpsr_write gen_helper_cpsr_write_mips64el +#define gen_helper_cpsr_write_eret gen_helper_cpsr_write_eret_mips64el #define gen_helper_crc32_arm gen_helper_crc32_arm_mips64el #define gen_helper_crc32c gen_helper_crc32c_mips64el #define gen_helper_crypto_aese gen_helper_crypto_aese_mips64el @@ -1400,6 +1401,7 @@ #define helper_clz_arm helper_clz_arm_mips64el #define helper_cpsr_read helper_cpsr_read_mips64el #define helper_cpsr_write helper_cpsr_write_mips64el +#define helper_cpsr_write_eret helper_cpsr_write_eret_mips64el #define helper_crc32_arm helper_crc32_arm_mips64el #define helper_crc32c helper_crc32c_mips64el #define helper_crypto_aese helper_crypto_aese_mips64el diff --git a/qemu/mipsel.h b/qemu/mipsel.h index 31d4c891..5fd01ed2 100644 --- a/qemu/mipsel.h +++ b/qemu/mipsel.h @@ -681,6 +681,7 @@ #define gen_helper_clz_arm gen_helper_clz_arm_mipsel #define gen_helper_cpsr_read gen_helper_cpsr_read_mipsel #define gen_helper_cpsr_write gen_helper_cpsr_write_mipsel +#define gen_helper_cpsr_write_eret gen_helper_cpsr_write_eret_mipsel #define gen_helper_crc32_arm gen_helper_crc32_arm_mipsel #define gen_helper_crc32c gen_helper_crc32c_mipsel #define gen_helper_crypto_aese gen_helper_crypto_aese_mipsel @@ -1400,6 +1401,7 @@ #define helper_clz_arm helper_clz_arm_mipsel #define helper_cpsr_read helper_cpsr_read_mipsel #define helper_cpsr_write helper_cpsr_write_mipsel +#define helper_cpsr_write_eret helper_cpsr_write_eret_mipsel #define helper_crc32_arm helper_crc32_arm_mipsel #define helper_crc32c helper_crc32c_mipsel #define helper_crypto_aese helper_crypto_aese_mipsel diff --git a/qemu/powerpc.h b/qemu/powerpc.h index 8debe063..7eb4f066 100644 --- a/qemu/powerpc.h +++ b/qemu/powerpc.h @@ -681,6 +681,7 @@ #define gen_helper_clz_arm gen_helper_clz_arm_powerpc #define gen_helper_cpsr_read gen_helper_cpsr_read_powerpc #define gen_helper_cpsr_write gen_helper_cpsr_write_powerpc +#define gen_helper_cpsr_write_eret gen_helper_cpsr_write_eret_powerpc #define gen_helper_crc32_arm gen_helper_crc32_arm_powerpc #define gen_helper_crc32c gen_helper_crc32c_powerpc #define gen_helper_crypto_aese gen_helper_crypto_aese_powerpc @@ -1400,6 +1401,7 @@ #define helper_clz_arm helper_clz_arm_powerpc #define helper_cpsr_read helper_cpsr_read_powerpc #define helper_cpsr_write helper_cpsr_write_powerpc +#define helper_cpsr_write_eret helper_cpsr_write_eret_powerpc #define helper_crc32_arm helper_crc32_arm_powerpc #define helper_crc32c helper_crc32c_powerpc #define helper_crypto_aese helper_crypto_aese_powerpc diff --git a/qemu/sparc.h b/qemu/sparc.h index 6f458f7f..a49f61c9 100644 --- a/qemu/sparc.h +++ b/qemu/sparc.h @@ -681,6 +681,7 @@ #define gen_helper_clz_arm gen_helper_clz_arm_sparc #define gen_helper_cpsr_read gen_helper_cpsr_read_sparc #define gen_helper_cpsr_write gen_helper_cpsr_write_sparc +#define gen_helper_cpsr_write_eret gen_helper_cpsr_write_eret_sparc #define gen_helper_crc32_arm gen_helper_crc32_arm_sparc #define gen_helper_crc32c gen_helper_crc32c_sparc #define gen_helper_crypto_aese gen_helper_crypto_aese_sparc @@ -1400,6 +1401,7 @@ #define helper_clz_arm helper_clz_arm_sparc #define helper_cpsr_read helper_cpsr_read_sparc #define helper_cpsr_write helper_cpsr_write_sparc +#define helper_cpsr_write_eret helper_cpsr_write_eret_sparc #define helper_crc32_arm helper_crc32_arm_sparc #define helper_crc32c helper_crc32c_sparc #define helper_crypto_aese helper_crypto_aese_sparc diff --git a/qemu/sparc64.h b/qemu/sparc64.h index 10e22648..47911816 100644 --- a/qemu/sparc64.h +++ b/qemu/sparc64.h @@ -681,6 +681,7 @@ #define gen_helper_clz_arm gen_helper_clz_arm_sparc64 #define gen_helper_cpsr_read gen_helper_cpsr_read_sparc64 #define gen_helper_cpsr_write gen_helper_cpsr_write_sparc64 +#define gen_helper_cpsr_write_eret gen_helper_cpsr_write_eret_sparc64 #define gen_helper_crc32_arm gen_helper_crc32_arm_sparc64 #define gen_helper_crc32c gen_helper_crc32c_sparc64 #define gen_helper_crypto_aese gen_helper_crypto_aese_sparc64 @@ -1400,6 +1401,7 @@ #define helper_clz_arm helper_clz_arm_sparc64 #define helper_cpsr_read helper_cpsr_read_sparc64 #define helper_cpsr_write helper_cpsr_write_sparc64 +#define helper_cpsr_write_eret helper_cpsr_write_eret_sparc64 #define helper_crc32_arm helper_crc32_arm_sparc64 #define helper_crc32c helper_crc32c_sparc64 #define helper_crypto_aese helper_crypto_aese_sparc64 diff --git a/qemu/target-arm/helper.h b/qemu/target-arm/helper.h index 11cbb9aa..8231d046 100644 --- a/qemu/target-arm/helper.h +++ b/qemu/target-arm/helper.h @@ -60,6 +60,7 @@ DEF_HELPER_2(pre_smc, void, env, i32) DEF_HELPER_1(check_breakpoints, void, env) DEF_HELPER_3(cpsr_write, void, env, i32, i32) +DEF_HELPER_2(cpsr_write_eret, void, env, i32) DEF_HELPER_1(cpsr_read, i32, env) DEF_HELPER_3(v7m_msr, void, env, i32, i32) diff --git a/qemu/target-arm/op_helper.c b/qemu/target-arm/op_helper.c index 025870d6..bae52183 100644 --- a/qemu/target-arm/op_helper.c +++ b/qemu/target-arm/op_helper.c @@ -425,6 +425,12 @@ void HELPER(cpsr_write)(CPUARMState *env, uint32_t val, uint32_t mask) cpsr_write(env, val, mask); } +/* Write the CPSR for a 32-bit exception return */ +void HELPER(cpsr_write_eret)(CPUARMState *env, uint32_t val) +{ + cpsr_write(env, val, CPSR_ERET_MASK); +} + /* Access to user mode registers from privileged modes. */ uint32_t HELPER(get_user_reg)(CPUARMState *env, uint32_t regno) { diff --git a/qemu/target-arm/translate.c b/qemu/target-arm/translate.c index a4253575..46fac23c 100644 --- a/qemu/target-arm/translate.c +++ b/qemu/target-arm/translate.c @@ -4203,7 +4203,7 @@ static void gen_exception_return(DisasContext *s, TCGv_i32 pc) TCGv_i32 tmp; store_reg(s, 15, pc); tmp = load_cpu_field(s->uc, spsr); - gen_set_cpsr(s, tmp, CPSR_ERET_MASK); + gen_helper_cpsr_write_eret(tcg_ctx, tcg_ctx->cpu_env, tmp); tcg_temp_free_i32(tcg_ctx, tmp); s->is_jmp = DISAS_JUMP; } @@ -4212,7 +4212,7 @@ static void gen_exception_return(DisasContext *s, TCGv_i32 pc) static void gen_rfe(DisasContext *s, TCGv_i32 pc, TCGv_i32 cpsr) { TCGContext *tcg_ctx = s->uc->tcg_ctx; - gen_set_cpsr(s, cpsr, CPSR_ERET_MASK); + gen_helper_cpsr_write_eret(tcg_ctx, tcg_ctx->cpu_env, cpsr); tcg_temp_free_i32(tcg_ctx, cpsr); store_reg(s, 15, pc); s->is_jmp = DISAS_JUMP; @@ -9233,7 +9233,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) // qq if (exc_return) { /* Restore CPSR from SPSR. */ tmp = load_cpu_field(s->uc, spsr); - gen_set_cpsr(s, tmp, CPSR_ERET_MASK); + gen_helper_cpsr_write_eret(tcg_ctx, tcg_ctx->cpu_env, tmp); tcg_temp_free_i32(tcg_ctx, tmp); s->is_jmp = DISAS_JUMP; } diff --git a/qemu/x86_64.h b/qemu/x86_64.h index 527c9c4d..a42bd40e 100644 --- a/qemu/x86_64.h +++ b/qemu/x86_64.h @@ -681,6 +681,7 @@ #define gen_helper_clz_arm gen_helper_clz_arm_x86_64 #define gen_helper_cpsr_read gen_helper_cpsr_read_x86_64 #define gen_helper_cpsr_write gen_helper_cpsr_write_x86_64 +#define gen_helper_cpsr_write_eret gen_helper_cpsr_write_eret_x86_64 #define gen_helper_crc32_arm gen_helper_crc32_arm_x86_64 #define gen_helper_crc32c gen_helper_crc32c_x86_64 #define gen_helper_crypto_aese gen_helper_crypto_aese_x86_64 @@ -1400,6 +1401,7 @@ #define helper_clz_arm helper_clz_arm_x86_64 #define helper_cpsr_read helper_cpsr_read_x86_64 #define helper_cpsr_write helper_cpsr_write_x86_64 +#define helper_cpsr_write_eret helper_cpsr_write_eret_x86_64 #define helper_crc32_arm helper_crc32_arm_x86_64 #define helper_crc32c helper_crc32c_x86_64 #define helper_crypto_aese helper_crypto_aese_x86_64