]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
KVM: arm64: Hide TCR2_EL1 from userspace when disabled for guests
authorMark Brown <broonie@kernel.org>
Wed, 23 Oct 2024 14:53:32 +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 FEAT_TCR2 we should not allow any access
to it in order to ensure that we do not create spurious issues with guest
migration. Add a visibility operation for it.

Fixes: fbff56068232 ("KVM: arm64: Save/restore TCR2_EL1")
Signed-off-by: Mark Brown <broonie@kernel.org>
Link: https://lore.kernel.org/r/20240822-kvm-arm64-hide-pie-regs-v2-2-376624fa829c@kernel.org
[maz: simplify by using __el2_visibility(), kvm_has_tcr2() throughout]
Signed-off-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20241023145345.1613824-25-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 553fb07f215328245fbd319b54e4a7689f94c50c..fb5dd6a287eb72dcf01addf35bd14bd8a2b56556 100644 (file)
@@ -1519,4 +1519,7 @@ void kvm_set_vm_id_reg(struct kvm *kvm, u32 reg, u64 val);
        (system_supports_fpmr() &&                      \
         kvm_has_feat((k), ID_AA64PFR2_EL1, FPMR, IMP))
 
+#define kvm_has_tcr2(k)                                \
+       (kvm_has_feat((k), ID_AA64MMFR3_EL1, TCRX, IMP))
+
 #endif /* __ARM64_KVM_HOST_H__ */
index 3d93ed1795603a624e6df84045afa1868911c02e..a9f665d5ceb0b719227168cc28b051a87e0d6709 100644 (file)
@@ -1099,7 +1099,7 @@ static u64 __kvm_at_s1e01_fast(struct kvm_vcpu *vcpu, u32 op, u64 vaddr)
        write_sysreg_el1(vcpu_read_sys_reg(vcpu, TTBR1_EL1),    SYS_TTBR1);
        write_sysreg_el1(vcpu_read_sys_reg(vcpu, TCR_EL1),      SYS_TCR);
        write_sysreg_el1(vcpu_read_sys_reg(vcpu, MAIR_EL1),     SYS_MAIR);
-       if (kvm_has_feat(vcpu->kvm, ID_AA64MMFR3_EL1, TCRX, IMP)) {
+       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)) {
                        write_sysreg_el1(vcpu_read_sys_reg(vcpu, PIR_EL1), SYS_PIR);
index d67628d01bf5e27287311a1badff61e29699c1a4..c92c2c0b86aa896d56aca7e708c607fa15cf302f 100644 (file)
@@ -69,7 +69,7 @@ static inline bool ctxt_has_tcrx(struct kvm_cpu_context *ctxt)
                return false;
 
        vcpu = ctxt_to_vcpu(ctxt);
-       return kvm_has_feat(kern_hyp_va(vcpu->kvm), ID_AA64MMFR3_EL1, TCRX, IMP);
+       return kvm_has_tcr2(kern_hyp_va(vcpu->kvm));
 }
 
 static inline bool ctxt_has_s1poe(struct kvm_cpu_context *ctxt)
index 1c8a6aa907df1c812430c1a686253e30ddfeab22..a4e085dab3ba5162ee33c16681052bc7a0a090c9 100644 (file)
@@ -1054,7 +1054,7 @@ int kvm_init_nv_sysregs(struct kvm *kvm)
                res0 |= HCRX_EL2_PTTWI;
        if (!kvm_has_feat(kvm, ID_AA64MMFR3_EL1, SCTLRX, IMP))
                res0 |= HCRX_EL2_SCTLR2En;
-       if (!kvm_has_feat(kvm, ID_AA64MMFR3_EL1, TCRX, IMP))
+       if (!kvm_has_tcr2(kvm))
                res0 |= HCRX_EL2_TCR2En;
        if (!kvm_has_feat(kvm, ID_AA64ISAR2_EL1, MOPS, IMP))
                res0 |= (HCRX_EL2_MSCEn | HCRX_EL2_MCE2);
index a2648a66b88dfbd35ea95186456b17681c4bde62..d4b5faacf06644a837e113e79d7e8def84d6a6e2 100644 (file)
@@ -446,7 +446,7 @@ static bool access_vm_reg(struct kvm_vcpu *vcpu,
        u64 val, mask, shift;
 
        if (reg_to_encoding(r) == SYS_TCR2_EL1 &&
-           !kvm_has_feat(vcpu->kvm, ID_AA64MMFR3_EL1, TCRX, IMP))
+           !kvm_has_tcr2(vcpu->kvm))
                return undef_access(vcpu, p, r);
 
        BUG_ON(!p->is_write);
@@ -471,7 +471,7 @@ static bool access_tcr2_el2(struct kvm_vcpu *vcpu,
                            struct sys_reg_params *p,
                            const struct sys_reg_desc *r)
 {
-       if (!kvm_has_feat(vcpu->kvm, ID_AA64MMFR3_EL1, TCRX, IMP)) {
+       if (!kvm_has_tcr2(vcpu->kvm)) {
                kvm_inject_undefined(vcpu);
                return false;
        }
@@ -2357,6 +2357,21 @@ static unsigned int s1poe_visibility(const struct kvm_vcpu *vcpu,
        return REG_HIDDEN;
 }
 
+static unsigned int tcr2_visibility(const struct kvm_vcpu *vcpu,
+                                   const struct sys_reg_desc *rd)
+{
+       if (kvm_has_tcr2(vcpu->kvm))
+               return 0;
+
+       return REG_HIDDEN;
+}
+
+static unsigned int tcr2_el2_visibility(const struct kvm_vcpu *vcpu,
+                                   const struct sys_reg_desc *rd)
+{
+       return __el2_visibility(vcpu, rd, tcr2_visibility);
+}
+
 /*
  * Architected system registers.
  * Important: Must be sorted ascending by Op0, Op1, CRn, CRm, Op2
@@ -2567,7 +2582,8 @@ static const struct sys_reg_desc sys_reg_descs[] = {
        { SYS_DESC(SYS_TTBR0_EL1), access_vm_reg, reset_unknown, TTBR0_EL1 },
        { SYS_DESC(SYS_TTBR1_EL1), access_vm_reg, reset_unknown, TTBR1_EL1 },
        { SYS_DESC(SYS_TCR_EL1), access_vm_reg, reset_val, TCR_EL1, 0 },
-       { SYS_DESC(SYS_TCR2_EL1), access_vm_reg, reset_val, TCR2_EL1, 0 },
+       { SYS_DESC(SYS_TCR2_EL1), access_vm_reg, reset_val, TCR2_EL1, 0,
+         .visibility = tcr2_visibility },
 
        PTRAUTH_KEY(APIA),
        PTRAUTH_KEY(APIB),
@@ -2904,7 +2920,8 @@ static const struct sys_reg_desc sys_reg_descs[] = {
        EL2_REG(TTBR0_EL2, access_rw, reset_val, 0),
        EL2_REG(TTBR1_EL2, access_rw, reset_val, 0),
        EL2_REG(TCR_EL2, access_rw, reset_val, TCR_EL2_RES1),
-       EL2_REG(TCR2_EL2, access_tcr2_el2, reset_val, TCR2_EL2_RES1),
+       EL2_REG_FILTERED(TCR2_EL2, access_tcr2_el2, reset_val, TCR2_EL2_RES1,
+                        tcr2_el2_visibility),
        EL2_REG_VNCR(VTTBR_EL2, reset_val, 0),
        EL2_REG_VNCR(VTCR_EL2, reset_val, 0),
 
@@ -4800,7 +4817,7 @@ void kvm_calculate_traps(struct kvm_vcpu *vcpu)
                if (kvm_has_feat(kvm, ID_AA64ISAR2_EL1, MOPS, IMP))
                        vcpu->arch.hcrx_el2 |= (HCRX_EL2_MSCEn | HCRX_EL2_MCE2);
 
-               if (kvm_has_feat(kvm, ID_AA64MMFR3_EL1, TCRX, IMP))
+               if (kvm_has_tcr2(kvm))
                        vcpu->arch.hcrx_el2 |= HCRX_EL2_TCR2En;
 
                if (kvm_has_fpmr(kvm))