Except that each ID field should be not greater than that of host, the allowed value par of (FPHP, SIMDHP) are (0, 0), (2, 1), (3, 2). Signed-off-by: zhanghailiang <zhang.zhanghailiang@xxxxxxxxxx> Signed-off-by: Peng Liang <liangpeng10@xxxxxxxxxx> --- arch/arm64/kvm/sys_regs.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index aac62f6fa846..1bcfaf738491 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -1349,6 +1349,34 @@ static int set_id_dfr0_el1(struct kvm_vcpu *vcpu, return 0; } +static int set_mvfr1_el1(struct kvm_vcpu *vcpu, + const struct sys_reg_desc *rd, + const struct kvm_one_reg *reg, void __user *uaddr) +{ + u32 reg_id = sys_reg((u32)rd->Op0, (u32)rd->Op1, (u32)rd->CRn, + (u32)rd->CRm, (u32)rd->Op2); + int err; + u64 val; + unsigned int fphp, simdhp; + + err = reg_from_user(&val, uaddr, sys_reg_to_index(rd)); + if (err) + return err; + + err = check_features(reg_id, val); + if (err) + return err; + + fphp = cpuid_feature_extract_unsigned_field(val, MVFR1_FPHP_SHIFT); + simdhp = cpuid_feature_extract_unsigned_field(val, MVFR1_SIMDHP_SHIFT); + if (!((fphp == 0 && simdhp == 0) || (fphp == 2 && simdhp == 1) || + (fphp == 3 && simdhp == 2))) + return -EINVAL; + + __vcpu_sys_reg(vcpu, ID_REG_INDEX(reg_id)) = val; + return 0; +} + static int set_id_aa64pfr0_el1(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, const struct kvm_one_reg *reg, void __user *uaddr) @@ -1687,7 +1715,7 @@ static const struct sys_reg_desc sys_reg_descs[] = { /* CRm=3 */ ID_SANITISED(MVFR0_EL1), - ID_SANITISED(MVFR1_EL1), + { SYS_DESC(SYS_MVFR1_EL1), access_id_reg, .get_user = get_id_reg, .set_user = set_mvfr1_el1 }, ID_SANITISED(MVFR2_EL1), ID_UNALLOCATED(3,3), ID_SANITISED(ID_PFR2_EL1), -- 2.26.2