]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
KVM: arm64: Hide S1PIE registers from userspace when disabled for guests
authorMark Brown <broonie@kernel.org>
Wed, 23 Oct 2024 14:53:33 +0000 (15:53 +0100)
committerOliver Upton <oliver.upton@linux.dev>
Thu, 31 Oct 2024 02:44:21 +0000 (02:44 +0000)
When the guest does not support S1PIE we should not allow any access
to the system registers it adds in order to ensure that we do not create
spurious issues with guest migration. Add a visibility operation for these
registers.

Fixes: 86f9de9db178 ("KVM: arm64: Save/restore PIE registers")
Signed-off-by: Mark Brown <broonie@kernel.org>
Link: https://lore.kernel.org/r/20240822-kvm-arm64-hide-pie-regs-v2-3-376624fa829c@kernel.org
[maz: simplify by using __el2_visibility(), kvm_has_s1pie() throughout]
Signed-off-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20241023145345.1613824-26-maz@kernel.org
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
arch/arm64/include/asm/kvm_host.h
arch/arm64/kvm/at.c
arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h
arch/arm64/kvm/nested.c
arch/arm64/kvm/sys_regs.c

index fb5dd6a287eb72dcf01addf35bd14bd8a2b56556..063463d056444ba05c3f0520d8d627a66d322629 100644 (file)
@@ -1522,4 +1522,7 @@ void kvm_set_vm_id_reg(struct kvm *kvm, u32 reg, u64 val);
 #define kvm_has_tcr2(k)                                \
        (kvm_has_feat((k), ID_AA64MMFR3_EL1, TCRX, IMP))
 
+#define kvm_has_s1pie(k)                               \
+       (kvm_has_feat((k), ID_AA64MMFR3_EL1, S1PIE, IMP))
+
 #endif /* __ARM64_KVM_HOST_H__ */
index a9f665d5ceb0b719227168cc28b051a87e0d6709..de7109111e404fd24fa7178d1bbbb5b83e9acb5e 100644 (file)
@@ -95,7 +95,7 @@ static enum trans_regime compute_translation_regime(struct kvm_vcpu *vcpu, u32 o
 
 static bool s1pie_enabled(struct kvm_vcpu *vcpu, enum trans_regime regime)
 {
-       if (!kvm_has_feat(vcpu->kvm, ID_AA64MMFR3_EL1, S1PIE, IMP))
+       if (!kvm_has_s1pie(vcpu->kvm))
                return false;
 
        switch (regime) {
@@ -1101,7 +1101,7 @@ static u64 __kvm_at_s1e01_fast(struct kvm_vcpu *vcpu, u32 op, u64 vaddr)
        write_sysreg_el1(vcpu_read_sys_reg(vcpu, MAIR_EL1),     SYS_MAIR);
        if (kvm_has_tcr2(vcpu->kvm)) {
                write_sysreg_el1(vcpu_read_sys_reg(vcpu, TCR2_EL1), SYS_TCR2);
-               if (kvm_has_feat(vcpu->kvm, ID_AA64MMFR3_EL1, S1PIE, IMP)) {
+               if (kvm_has_s1pie(vcpu->kvm)) {
                        write_sysreg_el1(vcpu_read_sys_reg(vcpu, PIR_EL1), SYS_PIR);
                        write_sysreg_el1(vcpu_read_sys_reg(vcpu, PIRE0_EL1), SYS_PIRE0);
                }
index c92c2c0b86aa896d56aca7e708c607fa15cf302f..a306ea70502c429b50d45ad0684c00015108c884 100644 (file)
@@ -58,7 +58,7 @@ static inline bool ctxt_has_s1pie(struct kvm_cpu_context *ctxt)
                return false;
 
        vcpu = ctxt_to_vcpu(ctxt);
-       return kvm_has_feat(kern_hyp_va(vcpu->kvm), ID_AA64MMFR3_EL1, S1PIE, IMP);
+       return kvm_has_s1pie(kern_hyp_va(vcpu->kvm));
 }
 
 static inline bool ctxt_has_tcrx(struct kvm_cpu_context *ctxt)
index a4e085dab3ba5162ee33c16681052bc7a0a090c9..9838b92dde5f1fdc62f8fb2767039acb86d7c78f 100644 (file)
@@ -1105,7 +1105,7 @@ int kvm_init_nv_sysregs(struct kvm *kvm)
                res0 |= (HFGxTR_EL2_nSMPRI_EL1 | HFGxTR_EL2_nTPIDR2_EL0);
        if (!kvm_has_feat(kvm, ID_AA64PFR1_EL1, THE, IMP))
                res0 |= HFGxTR_EL2_nRCWMASK_EL1;
-       if (!kvm_has_feat(kvm, ID_AA64MMFR3_EL1, S1PIE, IMP))
+       if (!kvm_has_s1pie(kvm))
                res0 |= (HFGxTR_EL2_nPIRE0_EL1 | HFGxTR_EL2_nPIR_EL1);
        if (!kvm_has_feat(kvm, ID_AA64MMFR3_EL1, S1POE, IMP))
                res0 |= (HFGxTR_EL2_nPOR_EL0 | HFGxTR_EL2_nPOR_EL1);
@@ -1219,7 +1219,7 @@ int kvm_init_nv_sysregs(struct kvm *kvm)
                res0 |= TCR2_EL2_AIE;
        if (!kvm_has_feat(kvm, ID_AA64MMFR3_EL1, S1POE, IMP))
                res0 |= TCR2_EL2_POE | TCR2_EL2_E0POE;
-       if (!kvm_has_feat(kvm, ID_AA64MMFR3_EL1, S1PIE, IMP))
+       if (!kvm_has_s1pie(kvm))
                res0 |= TCR2_EL2_PIE;
        if (!kvm_has_feat(kvm, ID_AA64MMFR1_EL1, VH, IMP))
                res0 |= (TCR2_EL2_E0POE | TCR2_EL2_D128 |
index d4b5faacf06644a837e113e79d7e8def84d6a6e2..46aa3d54b528395daeb600434c7692a22c65b0be 100644 (file)
@@ -373,7 +373,7 @@ static bool check_s1pie_access_rw(struct kvm_vcpu *vcpu,
                                  struct sys_reg_params *p,
                                  const struct sys_reg_desc *r)
 {
-       if (!kvm_has_feat(vcpu->kvm, ID_AA64MMFR3_EL1, S1PIE, IMP)) {
+       if (!kvm_has_s1pie(vcpu->kvm)) {
                kvm_inject_undefined(vcpu);
                return false;
        }
@@ -2372,6 +2372,21 @@ static unsigned int tcr2_el2_visibility(const struct kvm_vcpu *vcpu,
        return __el2_visibility(vcpu, rd, tcr2_visibility);
 }
 
+static unsigned int s1pie_visibility(const struct kvm_vcpu *vcpu,
+                                    const struct sys_reg_desc *rd)
+{
+       if (kvm_has_s1pie(vcpu->kvm))
+               return 0;
+
+       return REG_HIDDEN;
+}
+
+static unsigned int s1pie_el2_visibility(const struct kvm_vcpu *vcpu,
+                                        const struct sys_reg_desc *rd)
+{
+       return __el2_visibility(vcpu, rd, s1pie_visibility);
+}
+
 /*
  * Architected system registers.
  * Important: Must be sorted ascending by Op0, Op1, CRn, CRm, Op2
@@ -2637,8 +2652,10 @@ static const struct sys_reg_desc sys_reg_descs[] = {
        { SYS_DESC(SYS_PMMIR_EL1), trap_raz_wi },
 
        { SYS_DESC(SYS_MAIR_EL1), access_vm_reg, reset_unknown, MAIR_EL1 },
-       { SYS_DESC(SYS_PIRE0_EL1), NULL, reset_unknown, PIRE0_EL1 },
-       { SYS_DESC(SYS_PIR_EL1), NULL, reset_unknown, PIR_EL1 },
+       { SYS_DESC(SYS_PIRE0_EL1), NULL, reset_unknown, PIRE0_EL1,
+         .visibility = s1pie_visibility },
+       { SYS_DESC(SYS_PIR_EL1), NULL, reset_unknown, PIR_EL1,
+         .visibility = s1pie_visibility },
        { SYS_DESC(SYS_POR_EL1), NULL, reset_unknown, POR_EL1,
          .visibility = s1poe_visibility },
        { SYS_DESC(SYS_AMAIR_EL1), access_vm_reg, reset_amair_el1, AMAIR_EL1 },
@@ -2949,8 +2966,10 @@ static const struct sys_reg_desc sys_reg_descs[] = {
        EL2_REG(HPFAR_EL2, access_rw, reset_val, 0),
 
        EL2_REG(MAIR_EL2, access_rw, reset_val, 0),
-       EL2_REG(PIRE0_EL2, check_s1pie_access_rw, reset_val, 0),
-       EL2_REG(PIR_EL2, check_s1pie_access_rw, reset_val, 0),
+       EL2_REG_FILTERED(PIRE0_EL2, check_s1pie_access_rw, reset_val, 0,
+                        s1pie_el2_visibility),
+       EL2_REG_FILTERED(PIR_EL2, check_s1pie_access_rw, reset_val, 0,
+                        s1pie_el2_visibility),
        EL2_REG(AMAIR_EL2, access_rw, reset_val, 0),
 
        EL2_REG(VBAR_EL2, access_rw, reset_val, 0),
@@ -4867,7 +4886,7 @@ void kvm_calculate_traps(struct kvm_vcpu *vcpu)
                kvm->arch.fgu[HFGITR_GROUP] |= (HFGITR_EL2_ATS1E1RP |
                                                HFGITR_EL2_ATS1E1WP);
 
-       if (!kvm_has_feat(kvm, ID_AA64MMFR3_EL1, S1PIE, IMP))
+       if (!kvm_has_s1pie(kvm))
                kvm->arch.fgu[HFGxTR_GROUP] |= (HFGxTR_EL2_nPIRE0_EL1 |
                                                HFGxTR_EL2_nPIR_EL1);