From: Richard Henderson <richard.hender...@linaro.org> This is the prctl bit that controls whether syscalls accept tagged addresses. See Documentation/arm64/tagged-address-abi.rst in the linux kernel.
Reviewed-by: Peter Maydell <peter.mayd...@linaro.org> Signed-off-by: Richard Henderson <richard.hender...@linaro.org> Message-id: 20210212184902.1251044-21-richard.hender...@linaro.org Signed-off-by: Peter Maydell <peter.mayd...@linaro.org> --- linux-user/aarch64/target_syscall.h | 4 ++++ target/arm/cpu-param.h | 3 +++ target/arm/cpu.h | 31 +++++++++++++++++++++++++++++ linux-user/syscall.c | 24 ++++++++++++++++++++++ 4 files changed, 62 insertions(+) diff --git a/linux-user/aarch64/target_syscall.h b/linux-user/aarch64/target_syscall.h index 3194e6b0093..820601dfcc8 100644 --- a/linux-user/aarch64/target_syscall.h +++ b/linux-user/aarch64/target_syscall.h @@ -30,4 +30,8 @@ struct target_pt_regs { # define TARGET_PR_PAC_APDBKEY (1 << 3) # define TARGET_PR_PAC_APGAKEY (1 << 4) +#define TARGET_PR_SET_TAGGED_ADDR_CTRL 55 +#define TARGET_PR_GET_TAGGED_ADDR_CTRL 56 +# define TARGET_PR_TAGGED_ADDR_ENABLE (1UL << 0) + #endif /* AARCH64_TARGET_SYSCALL_H */ diff --git a/target/arm/cpu-param.h b/target/arm/cpu-param.h index 00e7d9e9377..7f38d33b8ea 100644 --- a/target/arm/cpu-param.h +++ b/target/arm/cpu-param.h @@ -20,6 +20,9 @@ #ifdef CONFIG_USER_ONLY #define TARGET_PAGE_BITS 12 +# ifdef TARGET_AARCH64 +# define TARGET_TAGGED_ADDRESSES +# endif #else /* * ARMv7 and later CPUs have 4K pages minimum, but ARMv5 and v6 diff --git a/target/arm/cpu.h b/target/arm/cpu.h index f240275407b..72a0819eb8c 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -721,6 +721,11 @@ typedef struct CPUARMState { const struct arm_boot_info *boot_info; /* Store GICv3CPUState to access from this struct */ void *gicv3state; + +#ifdef TARGET_TAGGED_ADDRESSES + /* Linux syscall tagged address support */ + bool tagged_addr_enable; +#endif } CPUARMState; static inline void set_feature(CPUARMState *env, int feature) @@ -3604,6 +3609,32 @@ static inline MemTxAttrs *typecheck_memtxattrs(MemTxAttrs *x) */ #define PAGE_BTI PAGE_TARGET_1 +#ifdef TARGET_TAGGED_ADDRESSES +/** + * cpu_untagged_addr: + * @cs: CPU context + * @x: tagged address + * + * Remove any address tag from @x. This is explicitly related to the + * linux syscall TIF_TAGGED_ADDR setting, not TBI in general. + * + * There should be a better place to put this, but we need this in + * include/exec/cpu_ldst.h, and not some place linux-user specific. + */ +static inline target_ulong cpu_untagged_addr(CPUState *cs, target_ulong x) +{ + ARMCPU *cpu = ARM_CPU(cs); + if (cpu->env.tagged_addr_enable) { + /* + * TBI is enabled for userspace but not kernelspace addresses. + * Only clear the tag if bit 55 is clear. + */ + x &= sextract64(x, 0, 56); + } + return x; +} +#endif + /* * Naming convention for isar_feature functions: * Functions which test 32-bit ID registers should have _aa32_ in diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 3d0411da57e..cf0b39461b6 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -10993,6 +10993,30 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, } } return -TARGET_EINVAL; + case TARGET_PR_SET_TAGGED_ADDR_CTRL: + { + abi_ulong valid_mask = TARGET_PR_TAGGED_ADDR_ENABLE; + CPUARMState *env = cpu_env; + + if ((arg2 & ~valid_mask) || arg3 || arg4 || arg5) { + return -TARGET_EINVAL; + } + env->tagged_addr_enable = arg2 & TARGET_PR_TAGGED_ADDR_ENABLE; + return 0; + } + case TARGET_PR_GET_TAGGED_ADDR_CTRL: + { + abi_long ret = 0; + CPUARMState *env = cpu_env; + + if (arg2 || arg3 || arg4 || arg5) { + return -TARGET_EINVAL; + } + if (env->tagged_addr_enable) { + ret |= TARGET_PR_TAGGED_ADDR_ENABLE; + } + return ret; + } #endif /* AARCH64 */ case PR_GET_SECCOMP: case PR_SET_SECCOMP: -- 2.20.1