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@xxxxxxx> --- 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 _______________________________________________ kvmarm mailing list kvmarm@xxxxxxxxxxxxxxxxxxxxx https://lists.cs.columbia.edu/mailman/listinfo/kvmarm