KVM: arm64: nv: Compute NV view of idregs as a one-off
authorMarc Zyngier <maz@kernel.org>
Sun, 12 Nov 2023 21:05:14 +0000 (21:05 +0000)
committerMarc Zyngier <maz@kernel.org>
Tue, 19 Dec 2023 09:51:00 +0000 (09:51 +0000)
Now that we have a full copy of the idregs for each VM, there is
no point in repainting the sysregs on each access. Instead, we
can simply perform the transmation as a one-off and be done
with it.

Reviewed-by: Oliver Upton <oliver.upton@linux.dev>
Signed-off-by: Marc Zyngier <maz@kernel.org>
arch/arm64/include/asm/kvm_host.h
arch/arm64/include/asm/kvm_nested.h
arch/arm64/kvm/arm.c
arch/arm64/kvm/nested.c
arch/arm64/kvm/sys_regs.c

index 4103a12ecaafaed92b9be203547f20250781e790..fce2e5f583a727aad7f2148b9298bb83b3337839 100644 (file)
@@ -306,6 +306,7 @@ struct kvm_arch {
         * Atomic access to multiple idregs are guarded by kvm_arch.config_lock.
         */
 #define IDREG_IDX(id)          (((sys_reg_CRm(id) - 1) << 3) | sys_reg_Op2(id))
+#define IDX_IDREG(idx)         sys_reg(3, 0, 0, ((idx) >> 3) + 1, (idx) & Op2_mask)
 #define IDREG(kvm, id)         ((kvm)->arch.id_regs[IDREG_IDX(id)])
 #define KVM_ARM_ID_REG_NUM     (IDREG_IDX(sys_reg(3, 0, 0, 7, 7)) + 1)
        u64 id_regs[KVM_ARM_ID_REG_NUM];
index 6cec8e9c6c9126b1f9b01ba0eed4a2f156deb334..249b03fc2ccee86d9534b872f9201ec558a24d40 100644 (file)
@@ -14,10 +14,6 @@ static inline bool vcpu_has_nv(const struct kvm_vcpu *vcpu)
 
 extern bool __check_nv_sr_forward(struct kvm_vcpu *vcpu);
 
-struct sys_reg_params;
-struct sys_reg_desc;
-
-void access_nested_id_reg(struct kvm_vcpu *v, struct sys_reg_params *p,
-                         const struct sys_reg_desc *r);
+int kvm_init_nv_sysregs(struct kvm *kvm);
 
 #endif /* __ARM64_KVM_NESTED_H */
index e5f75f1f10853941f35afa1e488c7c05d54e0fb9..b65df612b41b12871d1fb2e1856c7b8f389bfc5e 100644 (file)
@@ -669,6 +669,12 @@ int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu)
                        return ret;
        }
 
+       if (vcpu_has_nv(vcpu)) {
+               ret = kvm_init_nv_sysregs(vcpu->kvm);
+               if (ret)
+                       return ret;
+       }
+
        ret = kvm_timer_enable(vcpu);
        if (ret)
                return ret;
index 042695a210cebdcf753120a380175a46169e82d9..ba95d044bc98fd397d2b59e48aeb92d56a39c656 100644 (file)
  * This list should get updated as new features get added to the NV
  * support, and new extension to the architecture.
  */
-void access_nested_id_reg(struct kvm_vcpu *v, struct sys_reg_params *p,
-                         const struct sys_reg_desc *r)
+static u64 limit_nv_id_reg(u32 id, u64 val)
 {
-       u32 id = reg_to_encoding(r);
-       u64 val, tmp;
-
-       val = p->regval;
+       u64 tmp;
 
        switch (id) {
        case SYS_ID_AA64ISAR0_EL1:
@@ -158,5 +154,17 @@ void access_nested_id_reg(struct kvm_vcpu *v, struct sys_reg_params *p,
                break;
        }
 
-       p->regval = val;
+       return val;
+}
+int kvm_init_nv_sysregs(struct kvm *kvm)
+{
+       mutex_lock(&kvm->arch.config_lock);
+
+       for (int i = 0; i < KVM_ARM_ID_REG_NUM; i++)
+               kvm->arch.id_regs[i] = limit_nv_id_reg(IDX_IDREG(i),
+                                                      kvm->arch.id_regs[i]);
+
+       mutex_unlock(&kvm->arch.config_lock);
+
+       return 0;
 }
index 4735e1b37fb3e08afd9825ae4e9ebad953605937..3eae84195d48281a34e1a7b381e75e0855ef577f 100644 (file)
@@ -1505,8 +1505,6 @@ static bool access_id_reg(struct kvm_vcpu *vcpu,
                return write_to_read_only(vcpu, p, r);
 
        p->regval = read_id_reg(vcpu, r);
-       if (vcpu_has_nv(vcpu))
-               access_nested_id_reg(vcpu, p, r);
 
        return true;
 }