Except CSV2, which is allowed to set 1 if the value of host is 0, each
ID field should be not greater than that of host.  And FP and AdvSIMD
must have the same value.

Signed-off-by: zhanghailiang <[email protected]>
Signed-off-by: Peng Liang <[email protected]>
---
 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 68ed83657c07..bcc57cbe0421 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1323,6 +1323,50 @@ static int set_raz_id_reg(struct kvm_vcpu *vcpu, const 
struct sys_reg_desc *rd,
        return __set_id_reg(vcpu, rd, uaddr, true);
 }
 
+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)
+{
+       u32 reg_id = sys_reg((u32)rd->Op0, (u32)rd->Op1, (u32)rd->CRn,
+                            (u32)rd->CRm, (u32)rd->Op2);
+       int err;
+       u64 val, host_val, tmp_val;
+       unsigned int fp, asimd;
+
+       err = reg_from_user(&val, uaddr, sys_reg_to_index(rd));
+       if (err)
+               return err;
+
+       /*
+        * If the hardware is not affected by Spectre-v2 and doesn't support
+        * CSV2 but userspace set CSV2 to 1, we can ignore it when checking.
+        */
+       host_val = read_sanitised_ftr_reg(reg_id);
+       tmp_val = val;
+       if (arm64_get_spectre_v2_state() == SPECTRE_UNAFFECTED &&
+           !cpuid_feature_extract_unsigned_field(host_val, 
ID_AA64PFR0_CSV2_SHIFT) &&
+           cpuid_feature_extract_unsigned_field(tmp_val, 
ID_AA64PFR0_CSV2_SHIFT) == 1) {
+               tmp_val &= ~(0xfULL << ID_AA64PFR0_CSV2_SHIFT);
+       }
+       err = check_features(reg_id, tmp_val);
+       if (err)
+               return err;
+
+       fp = cpuid_feature_extract_signed_field(val, ID_AA64PFR0_FP_SHIFT);
+       asimd = cpuid_feature_extract_signed_field(val, 
ID_AA64PFR0_ASIMD_SHIFT);
+       if (fp != asimd)
+               return -EINVAL;
+
+       if (!vcpu_has_sve(vcpu) &&
+           cpuid_feature_extract_unsigned_field(val, ID_AA64PFR0_SVE_SHIFT))
+               return -EINVAL;
+       if (cpuid_feature_extract_unsigned_field(val, ID_AA64PFR0_AMU_SHIFT))
+               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)
 {
@@ -1517,7 +1561,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
 
        /* AArch64 ID registers */
        /* CRm=4 */
-       ID_SANITISED(ID_AA64PFR0_EL1),
+       { SYS_DESC(SYS_ID_AA64PFR0_EL1), access_id_reg, .get_user = get_id_reg, 
.set_user = set_id_aa64pfr0_el1 },
        ID_SANITISED(ID_AA64PFR1_EL1),
        ID_UNALLOCATED(4,2),
        ID_UNALLOCATED(4,3),
-- 
2.26.2

_______________________________________________
kvmarm mailing list
[email protected]
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

Reply via email to