When SPE is not implemented, accesses to the SPE registers cause an
undefined exception. KVM advertises the presence of SPE in the
ID_AA64DFR0_EL1 register, but configures MDCR_EL2 to trap accesses to the
registers and injects an undefined exception when that happens.

The architecture doesn't allow trapping access to the PMBIDR_EL1 register,
which means the guest will be able to read it even if SPE is not advertised
in the ID register. However, since it's usually better for a read to
unexpectedly succeed than to cause an exception, let's stop advertising the
presence of SPE to guests to better match how KVM emulates the
architecture.

Signed-off-by: Alexandru Elisei <[email protected]>
---
 arch/arm64/kvm/sys_regs.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index d9117bc56237..aa776c006a2a 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -244,6 +244,12 @@ static bool access_vm_reg(struct kvm_vcpu *vcpu,
        return true;
 }
 
+static unsigned int spe_visibility(const struct kvm_vcpu *vcpu,
+                                  const struct sys_reg_desc *r)
+{
+       return REG_HIDDEN_GUEST | REG_HIDDEN_USER;
+}
+
 static bool access_actlr(struct kvm_vcpu *vcpu,
                         struct sys_reg_params *p,
                         const struct sys_reg_desc *r)
@@ -1143,6 +1149,8 @@ static u64 read_id_reg(const struct kvm_vcpu *vcpu,
                val = cpuid_feature_cap_perfmon_field(val,
                                                ID_AA64DFR0_PMUVER_SHIFT,
                                                ID_AA64DFR0_PMUVER_8_1);
+               /* Don't advertise SPE to guests */
+               val &= ~(0xfUL << ID_AA64DFR0_PMSVER_SHIFT);
        } else if (id == SYS_ID_DFR0_EL1) {
                /* Limit guests to PMUv3 for ARMv8.1 */
                val = cpuid_feature_cap_perfmon_field(val,
@@ -1590,6 +1598,17 @@ static const struct sys_reg_desc sys_reg_descs[] = {
        { SYS_DESC(SYS_FAR_EL1), access_vm_reg, reset_unknown, FAR_EL1 },
        { SYS_DESC(SYS_PAR_EL1), NULL, reset_unknown, PAR_EL1 },
 
+       { SYS_DESC(SYS_PMSCR_EL1), .visibility = spe_visibility },
+       { SYS_DESC(SYS_PMSICR_EL1), .visibility = spe_visibility },
+       { SYS_DESC(SYS_PMSIRR_EL1), .visibility = spe_visibility },
+       { SYS_DESC(SYS_PMSFCR_EL1), .visibility = spe_visibility },
+       { SYS_DESC(SYS_PMSEVFR_EL1), .visibility = spe_visibility },
+       { SYS_DESC(SYS_PMSLATFR_EL1), .visibility = spe_visibility },
+       { SYS_DESC(SYS_PMSIDR_EL1), .visibility = spe_visibility },
+       { SYS_DESC(SYS_PMBLIMITR_EL1), .visibility = spe_visibility },
+       { SYS_DESC(SYS_PMBPTR_EL1), .visibility = spe_visibility },
+       { SYS_DESC(SYS_PMBSR_EL1), .visibility = spe_visibility },
+
        { SYS_DESC(SYS_PMINTENSET_EL1), access_pminten, reset_unknown, 
PMINTENSET_EL1 },
        { SYS_DESC(SYS_PMINTENCLR_EL1), access_pminten, reset_unknown, 
PMINTENSET_EL1 },
 
-- 
2.29.1

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

Reply via email to