Except that each ID field should be not greater than that of host, SM3 and SM4 must have the same value; if the value of SHA1 is 0, then SHA2 must have the value 0, and vice versa; if the value of SHA2 is 2, then SHA3 must have the value 1, and vice versa; if the value of SHA1 is 0, then SHA3 must have the value 0. Signed-off-by: zhanghailiang <zhang.zhanghailiang@xxxxxxxxxx> Signed-off-by: Peng Liang <liangpeng10@xxxxxxxxxx> --- arch/arm64/kvm/sys_regs.c | 46 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 3954b7a21a4b..76b39cab50b8 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -1393,6 +1393,50 @@ static int set_id_aa64dfr0_el1(struct kvm_vcpu *vcpu, return 0; } +static int set_id_aa64isar0_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 sm3, sm4, sha1, sha2, sha3; + + 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; + + sm3 = cpuid_feature_extract_unsigned_field(val, ID_AA64ISAR0_SM3_SHIFT); + sm4 = cpuid_feature_extract_unsigned_field(val, ID_AA64ISAR0_SM4_SHIFT); + /* + * ID_AA64ISAR0_EL1.SM3 and ID_AA64ISAR0_EL1.SM4 must have the same + * value. + */ + if (sm3 != sm4) + return -EINVAL; + + sha1 = cpuid_feature_extract_unsigned_field(val, ID_AA64ISAR0_SHA1_SHIFT); + sha2 = cpuid_feature_extract_unsigned_field(val, ID_AA64ISAR0_SHA2_SHIFT); + sha3 = cpuid_feature_extract_unsigned_field(val, ID_AA64ISAR0_SHA3_SHIFT); + /* + * 1. If the value of ID_AA64ISAR0_EL1.SHA1 is 0, then + * ID_AA64ISAR0_EL1.SHA2 must have the value 0, and vice versa; + * 2. If the value of ID_AA64ISAR0_EL1.SHA2 is 2, then + * ID_AA64ISAR0_EL1.SHA3 must have the value 1, and vice versa; + * 3. If the value of ID_AA64ISAR0_EL1.SHA1 is 0, then + * ID_AA64ISAR0_EL1.SHA3 must have the value 0; + */ + if ((sha1 ^ sha2) || ((sha2 == 2) ^ (sha3 == 1)) || (!sha1 && sha3)) + return -EINVAL; + + __vcpu_sys_reg(vcpu, ID_REG_INDEX(reg_id)) = val; + return 0; +} + static bool access_ctr(struct kvm_vcpu *vcpu, struct sys_reg_params *p, const struct sys_reg_desc *r) { @@ -1607,7 +1651,7 @@ static const struct sys_reg_desc sys_reg_descs[] = { ID_UNALLOCATED(5,7), /* CRm=6 */ - ID_SANITISED(ID_AA64ISAR0_EL1), + { SYS_DESC(SYS_ID_AA64ISAR0_EL1), access_id_reg, .get_user = get_id_reg, .set_user = set_id_aa64isar0_el1 }, ID_SANITISED(ID_AA64ISAR1_EL1), ID_UNALLOCATED(6,2), ID_UNALLOCATED(6,3), -- 2.26.2