[RFC PATCH v3 03/16] KVM: arm64: Hide SPE from guests
Alexandru Elisei
alexandru.elisei at arm.com
Tue Oct 27 13:26:52 EDT 2020
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 <alexandru.elisei at arm.com>
---
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
More information about the linux-arm-kernel
mailing list