From e6196b2040aed2213d0c6113cc8b139dd59f290f Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 22 Jan 2019 15:26:16 -0500 Subject: [PATCH] target/arm: Add PAuth helpers The cryptographic internals are stubbed out for now, but the enable and trap bits are checked. Backports commit 0d43e1a2d29a05f7b0d5629caaff18733cbdf3bb from qemu --- qemu/aarch64.h | 11 ++ qemu/aarch64eb.h | 11 ++ qemu/header_gen.py | 11 ++ qemu/target/arm/Makefile.objs | 1 + qemu/target/arm/helper-a64.h | 12 +++ qemu/target/arm/internals.h | 6 ++ qemu/target/arm/pauth_helper.c | 186 +++++++++++++++++++++++++++++++++ 7 files changed, 238 insertions(+) create mode 100644 qemu/target/arm/pauth_helper.c diff --git a/qemu/aarch64.h b/qemu/aarch64.h index add16191..c20750d4 100644 --- a/qemu/aarch64.h +++ b/qemu/aarch64.h @@ -3327,6 +3327,10 @@ #define helper_advsimd_rinth_exact helper_advsimd_rinth_exact_aarch64 #define helper_advsimd_sub2h helper_advsimd_sub2h_aarch64 #define helper_advsimd_subh helper_advsimd_subh_aarch64 +#define helper_autda helper_autda_aarch64 +#define helper_autdb helper_autdb_aarch64 +#define helper_autia helper_autia_aarch64 +#define helper_autib helper_autib_aarch64 #define helper_casp_be_parallel helper_casp_be_parallel_aarch64 #define helper_casp_le_parallel helper_casp_le_parallel_aarch64 #define helper_crc32_64 helper_crc32_64_aarch64 @@ -3348,6 +3352,11 @@ #define helper_neon_ceq_f64 helper_neon_ceq_f64_aarch64 #define helper_neon_cge_f64 helper_neon_cge_f64_aarch64 #define helper_neon_cgt_f64 helper_neon_cgt_f64_aarch64 +#define helper_pacda helper_pacda_aarch64 +#define helper_pacdb helper_pacdb_aarch64 +#define helper_pacga helper_pacga_aarch64 +#define helper_pacia helper_pacia_aarch64 +#define helper_pacib helper_pacib_aarch64 #define helper_paired_cmpxchg64_be helper_paired_cmpxchg64_be_aarch64 #define helper_paired_cmpxchg64_le helper_paired_cmpxchg64_le_aarch64 #define helper_rbit64 helper_rbit64_aarch64 @@ -4261,6 +4270,8 @@ #define helper_vfp_cmps_a64 helper_vfp_cmps_a64_aarch64 #define helper_vfp_mulxd helper_vfp_mulxd_aarch64 #define helper_vfp_mulxs helper_vfp_mulxs_aarch64 +#define helper_xpacd helper_xpacd_aarch64 +#define helper_xpaci helper_xpaci_aarch64 #define logic_imm_decode_wmask logic_imm_decode_wmask_aarch64 #define mla_op mla_op_aarch64 #define mls_op mls_op_aarch64 diff --git a/qemu/aarch64eb.h b/qemu/aarch64eb.h index d25d946d..bfad775d 100644 --- a/qemu/aarch64eb.h +++ b/qemu/aarch64eb.h @@ -3327,6 +3327,10 @@ #define helper_advsimd_rinth_exact helper_advsimd_rinth_exact_aarch64eb #define helper_advsimd_sub2h helper_advsimd_sub2h_aarch64eb #define helper_advsimd_subh helper_advsimd_subh_aarch64eb +#define helper_autda helper_autda_aarch64eb +#define helper_autdb helper_autdb_aarch64eb +#define helper_autia helper_autia_aarch64eb +#define helper_autib helper_autib_aarch64eb #define helper_casp_be_parallel helper_casp_be_parallel_aarch64eb #define helper_casp_le_parallel helper_casp_le_parallel_aarch64eb #define helper_crc32_64 helper_crc32_64_aarch64eb @@ -3348,6 +3352,11 @@ #define helper_neon_ceq_f64 helper_neon_ceq_f64_aarch64eb #define helper_neon_cge_f64 helper_neon_cge_f64_aarch64eb #define helper_neon_cgt_f64 helper_neon_cgt_f64_aarch64eb +#define helper_pacda helper_pacda_aarch64eb +#define helper_pacdb helper_pacdb_aarch64eb +#define helper_pacga helper_pacga_aarch64eb +#define helper_pacia helper_pacia_aarch64eb +#define helper_pacib helper_pacib_aarch64eb #define helper_paired_cmpxchg64_be helper_paired_cmpxchg64_be_aarch64eb #define helper_paired_cmpxchg64_le helper_paired_cmpxchg64_le_aarch64eb #define helper_rbit64 helper_rbit64_aarch64eb @@ -4261,6 +4270,8 @@ #define helper_vfp_cmps_a64 helper_vfp_cmps_a64_aarch64eb #define helper_vfp_mulxd helper_vfp_mulxd_aarch64eb #define helper_vfp_mulxs helper_vfp_mulxs_aarch64eb +#define helper_xpacd helper_xpacd_aarch64eb +#define helper_xpaci helper_xpaci_aarch64eb #define logic_imm_decode_wmask logic_imm_decode_wmask_aarch64eb #define mla_op mla_op_aarch64eb #define mls_op mls_op_aarch64eb diff --git a/qemu/header_gen.py b/qemu/header_gen.py index fd0e012f..f5cd8a89 100644 --- a/qemu/header_gen.py +++ b/qemu/header_gen.py @@ -3362,6 +3362,10 @@ aarch64_symbols = ( 'helper_advsimd_rinth_exact', 'helper_advsimd_sub2h', 'helper_advsimd_subh', + 'helper_autda', + 'helper_autdb', + 'helper_autia', + 'helper_autib', 'helper_casp_be_parallel', 'helper_casp_le_parallel', 'helper_crc32_64', @@ -3383,6 +3387,11 @@ aarch64_symbols = ( 'helper_neon_ceq_f64', 'helper_neon_cge_f64', 'helper_neon_cgt_f64', + 'helper_pacda', + 'helper_pacdb', + 'helper_pacga', + 'helper_pacia', + 'helper_pacib', 'helper_paired_cmpxchg64_be', 'helper_paired_cmpxchg64_le', 'helper_rbit64', @@ -4296,6 +4305,8 @@ aarch64_symbols = ( 'helper_vfp_cmps_a64', 'helper_vfp_mulxd', 'helper_vfp_mulxs', + 'helper_xpacd', + 'helper_xpaci', 'logic_imm_decode_wmask', 'mla_op', 'mls_op', diff --git a/qemu/target/arm/Makefile.objs b/qemu/target/arm/Makefile.objs index 6e70f205..6a8838a3 100644 --- a/qemu/target/arm/Makefile.objs +++ b/qemu/target/arm/Makefile.objs @@ -2,6 +2,7 @@ obj-y += translate.o op_helper.o helper.o cpu.o obj-y += neon_helper.o iwmmxt_helper.o vec_helper.o obj-$(CONFIG_SOFTMMU) += psci.o obj-$(TARGET_AARCH64) += cpu64.o translate-a64.o helper-a64.o unicorn_aarch64.o +obj-$(TARGET_AARCH64) += pauth_helper.o obj-$(TARGET_ARM) += unicorn_arm.o obj-y += crypto_helper.o obj-y += arm-powerctl.o diff --git a/qemu/target/arm/helper-a64.h b/qemu/target/arm/helper-a64.h index eab44cfa..d4cdda8c 100644 --- a/qemu/target/arm/helper-a64.h +++ b/qemu/target/arm/helper-a64.h @@ -81,3 +81,15 @@ DEF_HELPER_2(advsimd_rinth, f16, f16, ptr) DEF_HELPER_2(advsimd_f16tosinth, i32, f16, ptr) DEF_HELPER_2(advsimd_f16touinth, i32, f16, ptr) DEF_HELPER_2(sqrt_f16, f16, f16, ptr) + +DEF_HELPER_FLAGS_3(pacia, TCG_CALL_NO_WG, i64, env, i64, i64) +DEF_HELPER_FLAGS_3(pacib, TCG_CALL_NO_WG, i64, env, i64, i64) +DEF_HELPER_FLAGS_3(pacda, TCG_CALL_NO_WG, i64, env, i64, i64) +DEF_HELPER_FLAGS_3(pacdb, TCG_CALL_NO_WG, i64, env, i64, i64) +DEF_HELPER_FLAGS_3(pacga, TCG_CALL_NO_WG, i64, env, i64, i64) +DEF_HELPER_FLAGS_3(autia, TCG_CALL_NO_WG, i64, env, i64, i64) +DEF_HELPER_FLAGS_3(autib, TCG_CALL_NO_WG, i64, env, i64, i64) +DEF_HELPER_FLAGS_3(autda, TCG_CALL_NO_WG, i64, env, i64, i64) +DEF_HELPER_FLAGS_3(autdb, TCG_CALL_NO_WG, i64, env, i64, i64) +DEF_HELPER_FLAGS_2(xpaci, TCG_CALL_NO_RWG_SE, i64, env, i64) +DEF_HELPER_FLAGS_2(xpacd, TCG_CALL_NO_RWG_SE, i64, env, i64) \ No newline at end of file diff --git a/qemu/target/arm/internals.h b/qemu/target/arm/internals.h index 731a63a1..9a3a9a0c 100644 --- a/qemu/target/arm/internals.h +++ b/qemu/target/arm/internals.h @@ -268,6 +268,7 @@ enum arm_exception_class { EC_CP14DTTRAP = 0x06, EC_ADVSIMDFPACCESSTRAP = 0x07, EC_FPIDTRAP = 0x08, + EC_PACTRAP = 0x09, EC_CP14RRTTRAP = 0x0c, EC_ILLEGALSTATE = 0x0e, EC_AA32_SVC = 0x11, @@ -435,6 +436,11 @@ static inline uint32_t syn_sve_access_trap(void) return EC_SVEACCESSTRAP << ARM_EL_EC_SHIFT; } +static inline uint32_t syn_pactrap(void) +{ + return EC_PACTRAP << ARM_EL_EC_SHIFT; +} + static inline uint32_t syn_insn_abort(int same_el, int ea, int s1ptw, int fsc) { return (EC_INSNABORT << ARM_EL_EC_SHIFT) | (same_el << ARM_EL_EC_SHIFT) diff --git a/qemu/target/arm/pauth_helper.c b/qemu/target/arm/pauth_helper.c new file mode 100644 index 00000000..902f68a2 --- /dev/null +++ b/qemu/target/arm/pauth_helper.c @@ -0,0 +1,186 @@ +/* + * ARM v8.3-PAuth Operations + * + * Copyright (c) 2019 Linaro, Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include "qemu/osdep.h" +#include "cpu.h" +#include "internals.h" +#include "exec/exec-all.h" +#include "exec/cpu_ldst.h" +#include "exec/helper-proto.h" +#include "tcg/tcg-gvec-desc.h" + + +static uint64_t pauth_computepac(uint64_t data, uint64_t modifier, + ARMPACKey key) +{ + g_assert_not_reached(); /* FIXME */ +} + +static uint64_t pauth_addpac(CPUARMState *env, uint64_t ptr, uint64_t modifier, + ARMPACKey *key, bool data) +{ + g_assert_not_reached(); /* FIXME */ +} + +static uint64_t pauth_auth(CPUARMState *env, uint64_t ptr, uint64_t modifier, + ARMPACKey *key, bool data, int keynumber) +{ + g_assert_not_reached(); /* FIXME */ +} + +static uint64_t pauth_strip(CPUARMState *env, uint64_t ptr, bool data) +{ + g_assert_not_reached(); /* FIXME */ +} + +static void QEMU_NORETURN pauth_trap(CPUARMState *env, int target_el, + uintptr_t ra) +{ + raise_exception_ra(env, EXCP_UDEF, syn_pactrap(), target_el, ra); +} + +static void pauth_check_trap(CPUARMState *env, int el, uintptr_t ra) +{ + if (el < 2 && arm_feature(env, ARM_FEATURE_EL2)) { + uint64_t hcr = arm_hcr_el2_eff(env); + bool trap = !(hcr & HCR_API); + /* FIXME: ARMv8.1-VHE: trap only applies to EL1&0 regime. */ + /* FIXME: ARMv8.3-NV: HCR_NV trap takes precedence for ERETA[AB]. */ + if (trap) { + pauth_trap(env, 2, ra); + } + } + if (el < 3 && arm_feature(env, ARM_FEATURE_EL3)) { + if (!(env->cp15.scr_el3 & SCR_API)) { + pauth_trap(env, 3, ra); + } + } +} + +static bool pauth_key_enabled(CPUARMState *env, int el, uint32_t bit) +{ + uint32_t sctlr; + if (el == 0) { + /* FIXME: ARMv8.1-VHE S2 translation regime. */ + sctlr = env->cp15.sctlr_el[1]; + } else { + sctlr = env->cp15.sctlr_el[el]; + } + return (sctlr & bit) != 0; +} + +uint64_t HELPER(pacia)(CPUARMState *env, uint64_t x, uint64_t y) +{ + int el = arm_current_el(env); + if (!pauth_key_enabled(env, el, SCTLR_EnIA)) { + return x; + } + pauth_check_trap(env, el, GETPC()); + return pauth_addpac(env, x, y, &env->apia_key, false); +} + +uint64_t HELPER(pacib)(CPUARMState *env, uint64_t x, uint64_t y) +{ + int el = arm_current_el(env); + if (!pauth_key_enabled(env, el, SCTLR_EnIB)) { + return x; + } + pauth_check_trap(env, el, GETPC()); + return pauth_addpac(env, x, y, &env->apib_key, false); +} + +uint64_t HELPER(pacda)(CPUARMState *env, uint64_t x, uint64_t y) +{ + int el = arm_current_el(env); + if (!pauth_key_enabled(env, el, SCTLR_EnDA)) { + return x; + } + pauth_check_trap(env, el, GETPC()); + return pauth_addpac(env, x, y, &env->apda_key, true); +} + +uint64_t HELPER(pacdb)(CPUARMState *env, uint64_t x, uint64_t y) +{ + int el = arm_current_el(env); + if (!pauth_key_enabled(env, el, SCTLR_EnDB)) { + return x; + } + pauth_check_trap(env, el, GETPC()); + return pauth_addpac(env, x, y, &env->apdb_key, true); +} + +uint64_t HELPER(pacga)(CPUARMState *env, uint64_t x, uint64_t y) +{ + uint64_t pac; + + pauth_check_trap(env, arm_current_el(env), GETPC()); + pac = pauth_computepac(x, y, env->apga_key); + + return pac & 0xffffffff00000000ull; +} + +uint64_t HELPER(autia)(CPUARMState *env, uint64_t x, uint64_t y) +{ + int el = arm_current_el(env); + if (!pauth_key_enabled(env, el, SCTLR_EnIA)) { + return x; + } + pauth_check_trap(env, el, GETPC()); + return pauth_auth(env, x, y, &env->apia_key, false, 0); +} + +uint64_t HELPER(autib)(CPUARMState *env, uint64_t x, uint64_t y) +{ + int el = arm_current_el(env); + if (!pauth_key_enabled(env, el, SCTLR_EnIB)) { + return x; + } + pauth_check_trap(env, el, GETPC()); + return pauth_auth(env, x, y, &env->apib_key, false, 1); +} + +uint64_t HELPER(autda)(CPUARMState *env, uint64_t x, uint64_t y) +{ + int el = arm_current_el(env); + if (!pauth_key_enabled(env, el, SCTLR_EnDA)) { + return x; + } + pauth_check_trap(env, el, GETPC()); + return pauth_auth(env, x, y, &env->apda_key, true, 0); +} + +uint64_t HELPER(autdb)(CPUARMState *env, uint64_t x, uint64_t y) +{ + int el = arm_current_el(env); + if (!pauth_key_enabled(env, el, SCTLR_EnDB)) { + return x; + } + pauth_check_trap(env, el, GETPC()); + return pauth_auth(env, x, y, &env->apdb_key, true, 1); +} + +uint64_t HELPER(xpaci)(CPUARMState *env, uint64_t a) +{ + return pauth_strip(env, a, false); +} + +uint64_t HELPER(xpacd)(CPUARMState *env, uint64_t a) +{ + return pauth_strip(env, a, true); +}