[RFC PATCH v3 11/16] KVM: arm64: Add SPE system registers to VCPU context
Alexandru Elisei
alexandru.elisei at arm.com
Tue Oct 27 13:27:00 EDT 2020
Add the SPE system registers to the VCPU context. Omitted are PMBIDR_EL1,
which cannot be trapped, and PMSIR_EL1, which is a read-only register. The
registers are simply stored in the sys_regs array on a write, and returned
on a read; complete emulation and save/restore on world switch will be
added in a future patch.
Signed-off-by: Alexandru Elisei <alexandru.elisei at arm.com>
---
arch/arm64/include/asm/kvm_host.h | 11 +++++++
arch/arm64/kvm/spe.c | 10 +++++++
arch/arm64/kvm/sys_regs.c | 48 ++++++++++++++++++++++++-------
include/kvm/arm_spe.h | 9 ++++++
4 files changed, 68 insertions(+), 10 deletions(-)
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 27f581750c6e..bcecc6224c59 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -194,6 +194,17 @@ enum vcpu_sysreg {
CNTP_CVAL_EL0,
CNTP_CTL_EL0,
+ /* Statistical Profiling Extension Registers. */
+ PMSCR_EL1, /* Statistical Profiling Control Register */
+ PMSICR_EL1, /* Sampling Interval Counter Register */
+ PMSIRR_EL1, /* Sampling Interval Reload Register */
+ PMSFCR_EL1, /* Sampling Filter Control Register */
+ PMSEVFR_EL1, /* Sampling Event Filter Register */
+ PMSLATFR_EL1, /* Sampling Latency Filter Register */
+ PMBLIMITR_EL1, /* Profiling Buffer Limit Address Register */
+ PMBPTR_EL1, /* Profiling Buffer Write Pointer Register */
+ PMBSR_EL1, /* Profiling Buffer Status/syndrome Register */
+
/* 32bit specific registers. Keep them at the end of the range */
DACR32_EL2, /* Domain Access Control Register */
IFSR32_EL2, /* Instruction Fault Status Register */
diff --git a/arch/arm64/kvm/spe.c b/arch/arm64/kvm/spe.c
index 316ff8dfed5b..0e365a51cac7 100644
--- a/arch/arm64/kvm/spe.c
+++ b/arch/arm64/kvm/spe.c
@@ -12,6 +12,16 @@
#include <asm/kvm_mmu.h>
+void kvm_arm_spe_write_sysreg(struct kvm_vcpu *vcpu, int reg, u64 val)
+{
+ __vcpu_sys_reg(vcpu, reg) = val;
+}
+
+u64 kvm_arm_spe_read_sysreg(struct kvm_vcpu *vcpu, int reg)
+{
+ return __vcpu_sys_reg(vcpu, reg);
+}
+
void kvm_arm_spe_notify_vcpu_init(struct kvm_vcpu *vcpu)
{
vcpu->kvm->arch.spe.finalized = false;
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index aa776c006a2a..2871484993ec 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -244,9 +244,37 @@ static bool access_vm_reg(struct kvm_vcpu *vcpu,
return true;
}
+static bool access_spe_reg(struct kvm_vcpu *vcpu,
+ struct sys_reg_params *p,
+ const struct sys_reg_desc *r)
+{
+ u64 val = p->regval;
+ int reg = r->reg;
+ u32 sr = sys_reg((u32)r->Op0, (u32)r->Op1,
+ (u32)r->CRn, (u32)r->CRm, (u32)r->Op2);
+
+ if (sr == SYS_PMSIDR_EL1) {
+ /* Ignore writes. */
+ if (!p->is_write)
+ p->regval = read_sysreg_s(SYS_PMSIDR_EL1);
+ goto out;
+ }
+
+ if (p->is_write)
+ kvm_arm_spe_write_sysreg(vcpu, reg, val);
+ else
+ p->regval = kvm_arm_spe_read_sysreg(vcpu, reg);
+
+out:
+ return true;
+}
+
static unsigned int spe_visibility(const struct kvm_vcpu *vcpu,
const struct sys_reg_desc *r)
{
+ if (vcpu_has_spe(vcpu))
+ return 0;
+
return REG_HIDDEN_GUEST | REG_HIDDEN_USER;
}
@@ -1598,16 +1626,16 @@ 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_PMSCR_EL1), access_spe_reg, reset_val, PMSCR_EL1, 0, .visibility = spe_visibility },
+ { SYS_DESC(SYS_PMSICR_EL1), access_spe_reg, reset_val, PMSICR_EL1, 0, .visibility = spe_visibility },
+ { SYS_DESC(SYS_PMSIRR_EL1), access_spe_reg, reset_val, PMSIRR_EL1, 0, .visibility = spe_visibility },
+ { SYS_DESC(SYS_PMSFCR_EL1), access_spe_reg, reset_val, PMSFCR_EL1, 0, .visibility = spe_visibility },
+ { SYS_DESC(SYS_PMSEVFR_EL1), access_spe_reg, reset_val, PMSEVFR_EL1, 0, .visibility = spe_visibility },
+ { SYS_DESC(SYS_PMSLATFR_EL1), access_spe_reg, reset_val, PMSEVFR_EL1, 0, .visibility = spe_visibility },
+ { SYS_DESC(SYS_PMSIDR_EL1), access_spe_reg, .visibility = spe_visibility },
+ { SYS_DESC(SYS_PMBLIMITR_EL1), access_spe_reg, reset_val, PMBLIMITR_EL1, 0, .visibility = spe_visibility },
+ { SYS_DESC(SYS_PMBPTR_EL1), access_spe_reg, reset_unknown, PMBPTR_EL1, .visibility = spe_visibility },
+ { SYS_DESC(SYS_PMBSR_EL1), access_spe_reg, reset_val, PMBSR_EL1, 0, .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 },
diff --git a/include/kvm/arm_spe.h b/include/kvm/arm_spe.h
index 7f9f3a03aadb..a2429edc4483 100644
--- a/include/kvm/arm_spe.h
+++ b/include/kvm/arm_spe.h
@@ -38,6 +38,9 @@ int kvm_arm_vm_spe_has_attr(struct kvm *vcpu, struct kvm_device_attr *attr);
void kvm_arm_spe_notify_vcpu_init(struct kvm_vcpu *vcpu);
+void kvm_arm_spe_write_sysreg(struct kvm_vcpu *vcpu, int reg, u64 val);
+u64 kvm_arm_spe_read_sysreg(struct kvm_vcpu *vcpu, int reg);
+
#else
#define kvm_arm_supports_spe() false
@@ -87,5 +90,11 @@ static inline int kvm_arm_vm_spe_has_attr(struct kvm *vcpu,
static inline void kvm_arm_spe_notify_vcpu_init(struct kvm_vcpu *vcpu) {}
+static inline void kvm_arm_spe_write_sysreg(struct kvm_vcpu *vcpu, int reg, u64 val) {}
+static inline u64 kvm_arm_spe_read_sysreg(struct kvm_vcpu *vcpu, int reg)
+{
+ return 0;
+}
+
#endif /* CONFIG_KVM_ARM_SPE */
#endif /* __ASM_ARM_KVM_SPE_H */
--
2.29.1
More information about the linux-arm-kernel
mailing list