KVM: arm64: Add helper for last ditch idreg adjustments
authorMarc Zyngier <maz@kernel.org>
Tue, 27 Aug 2024 15:25:10 +0000 (16:25 +0100)
committerMarc Zyngier <maz@kernel.org>
Tue, 27 Aug 2024 17:32:55 +0000 (18:32 +0100)
We already have to perform a set of last-chance adjustments for
NV purposes. We will soon have to do the same for the GIC, so
introduce a helper for that exact purpose.

Reviewed-by: Oliver Upton <oliver.upton@linux.dev>
Link: https://lore.kernel.org/r/20240827152517.3909653-5-maz@kernel.org
Signed-off-by: Marc Zyngier <maz@kernel.org>
arch/arm64/kvm/arm.c
arch/arm64/kvm/nested.c
arch/arm64/kvm/sys_regs.c
arch/arm64/kvm/sys_regs.h

index 9bef7638342ef748d10277c905091e458bdff2af..f634f88e987ed4259b62016b5c1eb8cb48f78b4c 100644 (file)
@@ -46,6 +46,8 @@
 #include <kvm/arm_pmu.h>
 #include <kvm/arm_psci.h>
 
+#include "sys_regs.h"
+
 static enum kvm_mode kvm_mode = KVM_MODE_DEFAULT;
 
 enum kvm_wfx_trap_policy {
@@ -821,15 +823,13 @@ 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_finalize_sys_regs(vcpu);
+       if (ret)
+               return ret;
 
        /*
-        * This needs to happen after NV has imposed its own restrictions on
-        * the feature set
+        * This needs to happen after any restriction has been applied
+        * to the feature set.
         */
        kvm_calculate_traps(vcpu);
 
index bab27f9d8cc659531291830ec79c13eb62aac4d0..e2067c594e4ace74a67d288dc46250dabd3986a1 100644 (file)
@@ -954,19 +954,16 @@ static void set_sysreg_masks(struct kvm *kvm, int sr, u64 res0, u64 res1)
 int kvm_init_nv_sysregs(struct kvm *kvm)
 {
        u64 res0, res1;
-       int ret = 0;
 
-       mutex_lock(&kvm->arch.config_lock);
+       lockdep_assert_held(&kvm->arch.config_lock);
 
        if (kvm->arch.sysreg_masks)
-               goto out;
+               return 0;
 
        kvm->arch.sysreg_masks = kzalloc(sizeof(*(kvm->arch.sysreg_masks)),
                                         GFP_KERNEL_ACCOUNT);
-       if (!kvm->arch.sysreg_masks) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (!kvm->arch.sysreg_masks)
+               return -ENOMEM;
 
        limit_nv_id_regs(kvm);
 
@@ -1195,8 +1192,6 @@ int kvm_init_nv_sysregs(struct kvm *kvm)
        if (!kvm_has_feat(kvm, ID_AA64PFR0_EL1, AMU, V1P1))
                res0 |= ~(res0 | res1);
        set_sysreg_masks(kvm, HAFGRTR_EL2, res0, res1);
-out:
-       mutex_unlock(&kvm->arch.config_lock);
 
-       return ret;
+       return 0;
 }
index 257c8da23a4e67ec933a648822b3e108407cd54c..bc2d54da38279d333bdc9e8acf1c8a211f2fac4a 100644 (file)
@@ -4620,6 +4620,29 @@ out:
        mutex_unlock(&kvm->arch.config_lock);
 }
 
+/*
+ * Perform last adjustments to the ID registers that are implied by the
+ * configuration outside of the ID regs themselves, as well as any
+ * initialisation that directly depend on these ID registers (such as
+ * RES0/RES1 behaviours). This is not the place to configure traps though.
+ *
+ * Because this can be called once per CPU, changes must be idempotent.
+ */
+int kvm_finalize_sys_regs(struct kvm_vcpu *vcpu)
+{
+       struct kvm *kvm = vcpu->kvm;
+
+       guard(mutex)(&kvm->arch.config_lock);
+
+       if (vcpu_has_nv(vcpu)) {
+               int ret = kvm_init_nv_sysregs(kvm);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
 int __init kvm_sys_reg_table_init(void)
 {
        bool valid = true;
index 997eea21ba2ab3d7b08ae8f6178d208b74453606..7c9b4eb0baa628403d7e4542d3bf0f3cb2c0bea9 100644 (file)
@@ -235,6 +235,8 @@ int kvm_sys_reg_set_user(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg,
 
 bool triage_sysreg_trap(struct kvm_vcpu *vcpu, int *sr_index);
 
+int kvm_finalize_sys_regs(struct kvm_vcpu *vcpu);
+
 #define AA32(_x)       .aarch32_map = AA32_##_x
 #define Op0(_x)        .Op0 = _x
 #define Op1(_x)        .Op1 = _x