When MTE3 is supported, the kernel maps PR_MTE_TCF_ASYNC | PR_MTE_TCF_SYNC to MTE_CTRL_TCF_ASYMM and from there to SCTLR_EL1.TCF0 = 3
There is no error reported for setting ASYNC | SYNC when MTE3 is not supported; the kernel simply selects the ASYNC behavior of TCF0=2. Signed-off-by: Richard Henderson <richard.hender...@linaro.org> --- linux-user/aarch64/target_prctl.h | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/linux-user/aarch64/target_prctl.h b/linux-user/aarch64/target_prctl.h index 5067e7d731..49bd16aa95 100644 --- a/linux-user/aarch64/target_prctl.h +++ b/linux-user/aarch64/target_prctl.h @@ -173,21 +173,22 @@ static abi_long do_prctl_set_tagged_addr_ctrl(CPUArchState *env, abi_long arg2) env->tagged_addr_enable = arg2 & PR_TAGGED_ADDR_ENABLE; if (cpu_isar_feature(aa64_mte, cpu)) { - switch (arg2 & PR_MTE_TCF_MASK) { - case PR_MTE_TCF_NONE: - case PR_MTE_TCF_SYNC: - case PR_MTE_TCF_ASYNC: - break; - default: - return -EINVAL; - } - /* * Write PR_MTE_TCF to SCTLR_EL1[TCF0]. - * Note that the syscall values are consistent with hw. + * Note that SYNC | ASYNC -> ASYMM with FEAT_MTE3, + * otherwise mte_update_sctlr_user chooses ASYNC. */ - env->cp15.sctlr_el[1] = - deposit64(env->cp15.sctlr_el[1], 38, 2, arg2 >> PR_MTE_TCF_SHIFT); + unsigned tcf = 0; + if (arg2 & PR_MTE_TCF_ASYNC) { + if ((arg2 & PR_MTE_TCF_SYNC) && cpu_isar_feature(aa64_mte3, cpu)) { + tcf = 3; + } else { + tcf = 2; + } + } else if (arg2 & PR_MTE_TCF_SYNC) { + tcf = 1; + } + env->cp15.sctlr_el[1] = deposit64(env->cp15.sctlr_el[1], 38, 2, tcf); /* * Write PR_MTE_TAG to GCR_EL1[Exclude]. -- 2.34.1