/*
 * AArch64 specific prctl functions for linux-user
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 */
#ifndef AARCH64_TARGET_PRCTL_H
#define AARCH64_TARGET_PRCTL_H

static abi_long do_prctl_sve_get_vl(CPUArchState *env)
{
    ARMCPU *cpu = env_archcpu(env);
    if (cpu_isar_feature(aa64_sve, cpu)) {
        /* PSTATE.SM is always unset on syscall entry. */
        return sve_vq(env) * 16;
    }
    return -TARGET_EINVAL;
}
#define do_prctl_sve_get_vl do_prctl_sve_get_vl

static abi_long do_prctl_sve_set_vl(CPUArchState *env, abi_long arg2)
{
    /*
     * We cannot support either PR_SVE_SET_VL_ONEXEC or PR_SVE_VL_INHERIT.
     * Note the kernel definition of sve_vl_valid allows for VQ=512,
     * i.e. VL=8192, even though the current architectural maximum is VQ=16.
     */
    if (cpu_isar_feature(aa64_sve, env_archcpu(env))
        && arg2 >= 0 && arg2 <= 512 * 16 && !(arg2 & 15)) {
        uint32_t vq, old_vq;

        /* PSTATE.SM is always unset on syscall entry. */
        old_vq = sve_vq(env);

        /*
         * Bound the value of arg2, so that we know that it fits into
         * the 4-bit field in ZCR_EL1.  Rely on the hflags rebuild to
         * sort out the length supported by the cpu.
         */
        vq = MAX(arg2 / 16, 1);
        vq = MIN(vq, ARM_MAX_VQ);
        env->vfp.zcr_el[1] = vq - 1;
        arm_rebuild_hflags(env);

        vq = sve_vq(env);
        if (vq < old_vq) {
            aarch64_sve_narrow_vq(env, vq);
        }
        return vq * 16;
    }
    return -TARGET_EINVAL;
}
#define do_prctl_sve_set_vl do_prctl_sve_set_vl

static abi_long do_prctl_sme_get_vl(CPUArchState *env)
{
    ARMCPU *cpu = env_archcpu(env);
    if (cpu_isar_feature(aa64_sme, cpu)) {
        return sme_vq(env) * 16;
    }
    return -TARGET_EINVAL;
}
#define do_prctl_sme_get_vl do_prctl_sme_get_vl

static abi_long do_prctl_sme_set_vl(CPUArchState *env, abi_long arg2)
{
    /*
     * We cannot support either PR_SME_SET_VL_ONEXEC or PR_SME_VL_INHERIT.
     * Note the kernel definition of sve_vl_valid allows for VQ=512,
     * i.e. VL=8192, even though the architectural maximum is VQ=16.
     */
    if (cpu_isar_feature(aa64_sme, env_archcpu(env))
        && arg2 >= 0 && arg2 <= 512 * 16 && !(arg2 & 15)) {
        int vq, old_vq;

        old_vq = sme_vq(env);

        /*
         * Bound the value of vq, so that we know that it fits into
         * the 4-bit field in SMCR_EL1.  Because PSTATE.SM is cleared
         * on syscall entry, we are not modifying the current SVE
         * vector length.
         */
        vq = MAX(arg2 / 16, 1);
        vq = MIN(vq, 16);
        env->vfp.smcr_el[1] =
            FIELD_DP64(env->vfp.smcr_el[1], SMCR, LEN, vq - 1);

        /* Delay rebuilding hflags until we know if ZA must change. */
        vq = sve_vqm1_for_el_sm(env, 0, true) + 1;

        if (vq != old_vq) {
            /*
             * PSTATE.ZA state is cleared on any change to SVL.
             * We need not call arm_rebuild_hflags because PSTATE.SM was
             * cleared on syscall entry, so this hasn't changed VL.
             */
            env->svcr = FIELD_DP64(env->svcr, SVCR, ZA, 0);
            arm_rebuild_hflags(env);
        }
        return vq * 16;
    }
    return -TARGET_EINVAL;
}
#define do_prctl_sme_set_vl do_prctl_sme_set_vl

static abi_long do_prctl_reset_keys(CPUArchState *env, abi_long arg2)
{
    ARMCPU *cpu = env_archcpu(env);

    if (cpu_isar_feature(aa64_pauth, cpu)) {
        int all = (PR_PAC_APIAKEY | PR_PAC_APIBKEY |
                   PR_PAC_APDAKEY | PR_PAC_APDBKEY | PR_PAC_APGAKEY);
        int ret = 0;
        Error *err = NULL;

        if (arg2 == 0) {
            arg2 = all;
        } else if (arg2 & ~all) {
            return -TARGET_EINVAL;
        }
        if (arg2 & PR_PAC_APIAKEY) {
            ret |= qemu_guest_getrandom(&env->keys.apia,
                                        sizeof(ARMPACKey), &err);
        }
        if (arg2 & PR_PAC_APIBKEY) {
            ret |= qemu_guest_getrandom(&env->keys.apib,
                                        sizeof(ARMPACKey), &err);
        }
        if (arg2 & PR_PAC_APDAKEY) {
            ret |= qemu_guest_getrandom(&env->keys.apda,
                                        sizeof(ARMPACKey), &err);
        }
        if (arg2 & PR_PAC_APDBKEY) {
            ret |= qemu_guest_getrandom(&env->keys.apdb,
                                        sizeof(ARMPACKey), &err);
        }
        if (arg2 & PR_PAC_APGAKEY) {
            ret |= qemu_guest_getrandom(&env->keys.apga,
                                        sizeof(ARMPACKey), &err);
        }
        if (ret != 0) {
            /*
             * Some unknown failure in the crypto.  The best
             * we can do is log it and fail the syscall.
             * The real syscall cannot fail this way.
             */
            qemu_log_mask(LOG_UNIMP, "PR_PAC_RESET_KEYS: Crypto failure: %s",
                          error_get_pretty(err));
            error_free(err);
            return -TARGET_EIO;
        }
        return 0;
    }
    return -TARGET_EINVAL;
}
#define do_prctl_reset_keys do_prctl_reset_keys

static abi_long do_prctl_set_tagged_addr_ctrl(CPUArchState *env, abi_long arg2)
{
    abi_ulong valid_mask = PR_TAGGED_ADDR_ENABLE;
    ARMCPU *cpu = env_archcpu(env);

    if (cpu_isar_feature(aa64_mte, cpu)) {
        valid_mask |= PR_MTE_TCF_MASK;
        valid_mask |= PR_MTE_TAG_MASK;
    }

    if (arg2 & ~valid_mask) {
        return -TARGET_EINVAL;
    }
    env->tagged_addr_enable = arg2 & PR_TAGGED_ADDR_ENABLE;

    if (cpu_isar_feature(aa64_mte, cpu)) {
        /*
         * Write PR_MTE_TCF to SCTLR_EL1[TCF0].
         *
         * The kernel has a per-cpu configuration for the sysadmin,
         * /sys/devices/system/cpu/cpu<N>/mte_tcf_preferred,
         * which qemu does not implement.
         *
         * Because there is no performance difference between the modes, and
         * because SYNC is most useful for debugging MTE errors, choose SYNC
         * as the preferred mode.  With this preference, and the way the API
         * uses only two bits, there is no way for the program to select
         * ASYMM mode.
         */
        unsigned tcf = 0;
        if (arg2 & PR_MTE_TCF_SYNC) {
            tcf = 1;
        } else if (arg2 & PR_MTE_TCF_ASYNC) {
            tcf = 2;
        }
        env->cp15.sctlr_el[1] = deposit64(env->cp15.sctlr_el[1], 38, 2, tcf);

        /*
         * Write PR_MTE_TAG to GCR_EL1[Exclude].
         * Note that the syscall uses an include mask,
         * and hardware uses an exclude mask -- invert.
         */
        env->cp15.gcr_el1 =
            deposit64(env->cp15.gcr_el1, 0, 16, ~arg2 >> PR_MTE_TAG_SHIFT);
        arm_rebuild_hflags(env);
    }
    return 0;
}
#define do_prctl_set_tagged_addr_ctrl do_prctl_set_tagged_addr_ctrl

static abi_long do_prctl_get_tagged_addr_ctrl(CPUArchState *env)
{
    ARMCPU *cpu = env_archcpu(env);
    abi_long ret = 0;

    if (env->tagged_addr_enable) {
        ret |= PR_TAGGED_ADDR_ENABLE;
    }
    if (cpu_isar_feature(aa64_mte, cpu)) {
        /* See do_prctl_set_tagged_addr_ctrl. */
        ret |= extract64(env->cp15.sctlr_el[1], 38, 2) << PR_MTE_TCF_SHIFT;
        ret = deposit64(ret, PR_MTE_TAG_SHIFT, 16, ~env->cp15.gcr_el1);
    }
    return ret;
}
#define do_prctl_get_tagged_addr_ctrl do_prctl_get_tagged_addr_ctrl

#endif /* AARCH64_TARGET_PRCTL_H */
