Re: [PATCH v3 1/3] arm64: cpufeature: Extract capped fields

2020-01-02 Thread Suzuki Kuruppassery Poulose

On 02/01/2020 12:39, Andrew Murray wrote:

When emulating ID registers there is often a need to cap the version
bits of a feature such that the guest will not use features that do
not yet exist.

Let's add a helper that extracts a field and caps the version to a
given value.

Signed-off-by: Andrew Murray 


Reviewed-by: Suzuki K Poulose 

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH v2 02/18] arm64: KVM: reset E2PB correctly in MDCR_EL2 when exiting the guest(VHE)

2020-01-02 Thread Andrew Murray
On Tue, Dec 24, 2019 at 10:29:50AM +, Andrew Murray wrote:
> On Sat, Dec 21, 2019 at 01:12:14PM +, Marc Zyngier wrote:
> > On Fri, 20 Dec 2019 14:30:09 +
> > Andrew Murray  wrote:
> > 
> > > From: Sudeep Holla 
> > > 
> > > On VHE systems, the reset value for MDCR_EL2.E2PB=b00 which defaults
> > > to profiling buffer using the EL2 stage 1 translations. 
> > 
> > Does the reset value actually matter here? I don't see it being
> > specific to VHE systems, and all we're trying to achieve is to restore
> > the SPE configuration to a state where it can be used by the host.
> > 
> > > However if the
> > > guest are allowed to use profiling buffers changing E2PB settings, we
> > 
> > How can the guest be allowed to change E2PB settings? Or do you mean
> > here that allowing the guest to use SPE will mandate changes of the
> > E2PB settings, and that we'd better restore the hypervisor state once
> > we exit?
> > 
> > > need to ensure we resume back MDCR_EL2.E2PB=b00. Currently we just
> > > do bitwise '&' with MDCR_EL2_E2PB_MASK which will retain the value.
> > > 
> > > So fix it by clearing all the bits in E2PB.
> > > 
> > > Signed-off-by: Sudeep Holla 
> > > Signed-off-by: Andrew Murray 
> > > ---
> > >  arch/arm64/kvm/hyp/switch.c | 4 +---
> > >  1 file changed, 1 insertion(+), 3 deletions(-)
> > > 
> > > diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
> > > index 72fbbd86eb5e..250f13910882 100644
> > > --- a/arch/arm64/kvm/hyp/switch.c
> > > +++ b/arch/arm64/kvm/hyp/switch.c
> > > @@ -228,9 +228,7 @@ void deactivate_traps_vhe_put(void)
> > >  {
> > >   u64 mdcr_el2 = read_sysreg(mdcr_el2);
> > >  
> > > - mdcr_el2 &= MDCR_EL2_HPMN_MASK |
> > > - MDCR_EL2_E2PB_MASK << MDCR_EL2_E2PB_SHIFT |
> > > - MDCR_EL2_TPMS;
> > > + mdcr_el2 &= MDCR_EL2_HPMN_MASK | MDCR_EL2_TPMS;
> > >  
> > >   write_sysreg(mdcr_el2, mdcr_el2);
> > >  
> > 
> > I'm OK with this change, but I believe the commit message could use
> > some tidying up.
> 
> No problem, I'll update the commit message.

This is my new description:

arm64: KVM: reset E2PB correctly in MDCR_EL2 when exiting the guest (VHE)

Upon leaving the guest on VHE systems we currently preserve the value of
MDCR_EL2.E2PB. This register determines if the SPE profiling buffer controls
are trapped and which translation regime they use.

In order to permit guest access to SPE we may use a different translation
regime whilst the vCPU is scheduled - therefore let's ensure that upon 
leaving
the guest we set E2PB back to the value expected by the host (b00).

For nVHE systems we already explictly set E2PB back to the expected value
of 0b11 in __deactivate_traps_nvhe.

Thanks,

Andrew Murray

> 
> Thanks,
> 
> Andrew Murray
> 
> > 
> > Thanks,
> > 
> > M.
> > -- 
> > Jazz is not dead. It just smells funny...
> ___
> kvmarm mailing list
> kvmarm@lists.cs.columbia.edu
> https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH v3 0/3] arm64: perf: Add support for ARMv8.5-PMU 64-bit counters

2020-01-02 Thread Andrew Murray
At present ARMv8 event counters are limited to 32-bits, though by
using the CHAIN event it's possible to combine adjacent counters to
achieve 64-bits. The perf config1:0 bit can be set to use such a
configuration.

With the introduction of ARMv8.5-PMU support, all event counters can
now be used as 64-bit counters. Let's add support for 64-bit event
counters.

As KVM doesn't yet support 64-bit event counters, we also trap
and emulate the Debug Feature Registers to limit the PMU version a
guest sees to PMUv3 for ARMv8.4.

Tested by running the following perf command on both guest and host
and ensuring that the figures are very similar:

perf stat -e armv8_pmuv3/inst_retired,long=1/ \
  -e armv8_pmuv3/inst_retired,long=0/ -e cycles

Changes since v2:

 - Rebased onto v5.5-rc4
 - Mask 'cap' value to 'width' in cpuid_feature_cap_signed_field_width

Changes since v1:

 - Rebased onto v5.5-rc1


Andrew Murray (3):
  arm64: cpufeature: Extract capped fields
  KVM: arm64: limit PMU version to ARMv8.4
  arm64: perf: Add support for ARMv8.5-PMU 64-bit counters

 arch/arm64/include/asm/cpufeature.h | 16 ++
 arch/arm64/include/asm/perf_event.h |  3 +-
 arch/arm64/include/asm/sysreg.h |  4 ++
 arch/arm64/kernel/perf_event.c  | 86 +++--
 arch/arm64/kvm/sys_regs.c   | 36 +++-
 include/linux/perf/arm_pmu.h|  1 +
 6 files changed, 126 insertions(+), 20 deletions(-)

-- 
2.21.0

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH v3 1/3] arm64: cpufeature: Extract capped fields

2020-01-02 Thread Andrew Murray
When emulating ID registers there is often a need to cap the version
bits of a feature such that the guest will not use features that do
not yet exist.

Let's add a helper that extracts a field and caps the version to a
given value.

Signed-off-by: Andrew Murray 
---
 arch/arm64/include/asm/cpufeature.h | 16 
 1 file changed, 16 insertions(+)

diff --git a/arch/arm64/include/asm/cpufeature.h 
b/arch/arm64/include/asm/cpufeature.h
index 4261d55e8506..1462fd1101e3 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -447,6 +447,22 @@ cpuid_feature_extract_unsigned_field(u64 features, int 
field)
return cpuid_feature_extract_unsigned_field_width(features, field, 4);
 }
 
+static inline u64 __attribute_const__
+cpuid_feature_cap_signed_field_width(u64 features, int field, int width,
+s64 cap)
+{
+   s64 val = cpuid_feature_extract_signed_field_width(features, field,
+  width);
+   u64 mask = GENMASK_ULL(field + width - 1, field);
+
+   if (val > cap) {
+   features &= ~mask;
+   features |= (cap << field) & mask;
+   }
+
+   return features;
+}
+
 static inline u64 arm64_ftr_mask(const struct arm64_ftr_bits *ftrp)
 {
return (u64)GENMASK(ftrp->shift + ftrp->width - 1, ftrp->shift);
-- 
2.21.0

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH v3 3/3] arm64: perf: Add support for ARMv8.5-PMU 64-bit counters

2020-01-02 Thread Andrew Murray
At present ARMv8 event counters are limited to 32-bits, though by
using the CHAIN event it's possible to combine adjacent counters to
achieve 64-bits. The perf config1:0 bit can be set to use such a
configuration.

With the introduction of ARMv8.5-PMU support, all event counters can
now be used as 64-bit counters.

Let's enable 64-bit event counters where support exists. Unless the
user sets config1:0 we will adjust the counter value such that it
overflows upon 32-bit overflow. This follows the same behaviour as
the cycle counter which has always been (and remains) 64-bits.

Signed-off-by: Andrew Murray 
Reviewed-by: Suzuki K Poulose 
---
 arch/arm64/include/asm/perf_event.h |  3 +-
 arch/arm64/kernel/perf_event.c  | 86 +++--
 include/linux/perf/arm_pmu.h|  1 +
 3 files changed, 72 insertions(+), 18 deletions(-)

diff --git a/arch/arm64/include/asm/perf_event.h 
b/arch/arm64/include/asm/perf_event.h
index 2bdbc79bbd01..e7765b62c712 100644
--- a/arch/arm64/include/asm/perf_event.h
+++ b/arch/arm64/include/asm/perf_event.h
@@ -176,9 +176,10 @@
 #define ARMV8_PMU_PMCR_X   (1 << 4) /* Export to ETM */
 #define ARMV8_PMU_PMCR_DP  (1 << 5) /* Disable CCNT if non-invasive debug*/
 #define ARMV8_PMU_PMCR_LC  (1 << 6) /* Overflow on 64 bit cycle counter */
+#define ARMV8_PMU_PMCR_LP  (1 << 7) /* Long event counter enable */
 #defineARMV8_PMU_PMCR_N_SHIFT  11   /* Number of counters 
supported */
 #defineARMV8_PMU_PMCR_N_MASK   0x1f
-#defineARMV8_PMU_PMCR_MASK 0x7f /* Mask for writable bits */
+#defineARMV8_PMU_PMCR_MASK 0xff /* Mask for writable bits */
 
 /*
  * PMOVSR: counters overflow flag status reg
diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c
index e40b65645c86..4e27f90bb89e 100644
--- a/arch/arm64/kernel/perf_event.c
+++ b/arch/arm64/kernel/perf_event.c
@@ -285,6 +285,17 @@ static struct attribute_group 
armv8_pmuv3_format_attr_group = {
 #defineARMV8_IDX_COUNTER_LAST(cpu_pmu) \
(ARMV8_IDX_CYCLE_COUNTER + cpu_pmu->num_events - 1)
 
+
+/*
+ * We unconditionally enable ARMv8.5-PMU long event counter support
+ * (64-bit events) where supported. Indicate if this arm_pmu has long
+ * event counter support.
+ */
+static bool armv8pmu_has_long_event(struct arm_pmu *cpu_pmu)
+{
+   return (cpu_pmu->pmuver > ID_DFR0_EL1_PMUVER_8_4);
+}
+
 /*
  * We must chain two programmable counters for 64 bit events,
  * except when we have allocated the 64bit cycle counter (for CPU
@@ -294,9 +305,11 @@ static struct attribute_group 
armv8_pmuv3_format_attr_group = {
 static inline bool armv8pmu_event_is_chained(struct perf_event *event)
 {
int idx = event->hw.idx;
+   struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
 
return !WARN_ON(idx < 0) &&
   armv8pmu_event_is_64bit(event) &&
+  !armv8pmu_has_long_event(cpu_pmu) &&
   (idx != ARMV8_IDX_CYCLE_COUNTER);
 }
 
@@ -345,7 +358,7 @@ static inline void armv8pmu_select_counter(int idx)
isb();
 }
 
-static inline u32 armv8pmu_read_evcntr(int idx)
+static inline u64 armv8pmu_read_evcntr(int idx)
 {
armv8pmu_select_counter(idx);
return read_sysreg(pmxevcntr_el0);
@@ -362,6 +375,44 @@ static inline u64 armv8pmu_read_hw_counter(struct 
perf_event *event)
return val;
 }
 
+/*
+ * The cycle counter is always a 64-bit counter. When ARMV8_PMU_PMCR_LP
+ * is set the event counters also become 64-bit counters. Unless the
+ * user has requested a long counter (attr.config1) then we want to
+ * interrupt upon 32-bit overflow - we achieve this by applying a bias.
+ */
+static bool armv8pmu_event_needs_bias(struct perf_event *event)
+{
+   struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
+   struct hw_perf_event *hwc = &event->hw;
+   int idx = hwc->idx;
+
+   if (armv8pmu_event_is_64bit(event))
+   return false;
+
+   if (armv8pmu_has_long_event(cpu_pmu) ||
+   idx == ARMV8_IDX_CYCLE_COUNTER)
+   return true;
+
+   return false;
+}
+
+static u64 armv8pmu_bias_long_counter(struct perf_event *event, u64 value)
+{
+   if (armv8pmu_event_needs_bias(event))
+   value |= GENMASK(63, 32);
+
+   return value;
+}
+
+static u64 armv8pmu_unbias_long_counter(struct perf_event *event, u64 value)
+{
+   if (armv8pmu_event_needs_bias(event))
+   value &= ~GENMASK(63, 32);
+
+   return value;
+}
+
 static u64 armv8pmu_read_counter(struct perf_event *event)
 {
struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
@@ -377,10 +428,10 @@ static u64 armv8pmu_read_counter(struct perf_event *event)
else
value = armv8pmu_read_hw_counter(event);
 
-   return value;
+   return  armv8pmu_unbias_long_counter(event, value);
 }
 
-static inline void armv8pmu_write_evcntr(int idx, u32 value)
+static inline void armv8pmu_write_evcntr(int idx, u64 value)
 {

[PATCH v3 2/3] KVM: arm64: limit PMU version to ARMv8.4

2020-01-02 Thread Andrew Murray
ARMv8.5-PMU introduces 64-bit event counters, however KVM doesn't yet
support this. Let's trap the Debug Feature Registers in order to limit
PMUVer/PerfMon in the Debug Feature Registers to PMUv3 for ARMv8.4.

Signed-off-by: Andrew Murray 
Reviewed-by: Suzuki K Poulose 
---
 arch/arm64/include/asm/sysreg.h |  4 
 arch/arm64/kvm/sys_regs.c   | 36 +++--
 2 files changed, 38 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index 6e919fafb43d..1b74f275a115 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -672,6 +672,10 @@
 #define ID_AA64DFR0_TRACEVER_SHIFT 4
 #define ID_AA64DFR0_DEBUGVER_SHIFT 0
 
+#define ID_DFR0_PERFMON_SHIFT  24
+
+#define ID_DFR0_EL1_PMUVER_8_4 5
+
 #define ID_ISAR5_RDM_SHIFT 24
 #define ID_ISAR5_CRC32_SHIFT   16
 #define ID_ISAR5_SHA2_SHIFT12
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 9f2165937f7d..61b984d934d1 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -668,6 +668,37 @@ static bool pmu_access_event_counter_el0_disabled(struct 
kvm_vcpu *vcpu)
return check_pmu_access_disabled(vcpu, ARMV8_PMU_USERENR_ER | 
ARMV8_PMU_USERENR_EN);
 }
 
+static bool access_id_aa64dfr0_el1(struct kvm_vcpu *vcpu,
+  struct sys_reg_params *p,
+  const struct sys_reg_desc *rd)
+{
+   if (p->is_write)
+   return write_to_read_only(vcpu, p, rd);
+
+   /* Limit guests to PMUv3 for ARMv8.4 */
+   p->regval = read_sanitised_ftr_reg(SYS_ID_AA64DFR0_EL1);
+   p->regval = cpuid_feature_cap_signed_field_width(p->regval,
+   ID_AA64DFR0_PMUVER_SHIFT,
+   4, ID_DFR0_EL1_PMUVER_8_4);
+
+   return p->regval;
+}
+
+static bool access_id_dfr0_el1(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
+  const struct sys_reg_desc *rd)
+{
+   if (p->is_write)
+   return write_to_read_only(vcpu, p, rd);
+
+   /* Limit guests to PMUv3 for ARMv8.4 */
+   p->regval = read_sanitised_ftr_reg(SYS_ID_DFR0_EL1);
+   p->regval = cpuid_feature_cap_signed_field_width(p->regval,
+   ID_DFR0_PERFMON_SHIFT,
+   4, ID_DFR0_EL1_PMUVER_8_4);
+
+   return p->regval;
+}
+
 static bool access_pmcr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
const struct sys_reg_desc *r)
 {
@@ -1409,7 +1440,8 @@ static const struct sys_reg_desc sys_reg_descs[] = {
/* CRm=1 */
ID_SANITISED(ID_PFR0_EL1),
ID_SANITISED(ID_PFR1_EL1),
-   ID_SANITISED(ID_DFR0_EL1),
+   { SYS_DESC(SYS_ID_DFR0_EL1), access_id_dfr0_el1 },
+
ID_HIDDEN(ID_AFR0_EL1),
ID_SANITISED(ID_MMFR0_EL1),
ID_SANITISED(ID_MMFR1_EL1),
@@ -1448,7 +1480,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
ID_UNALLOCATED(4,7),
 
/* CRm=5 */
-   ID_SANITISED(ID_AA64DFR0_EL1),
+   { SYS_DESC(SYS_ID_AA64DFR0_EL1), access_id_aa64dfr0_el1 },
ID_SANITISED(ID_AA64DFR1_EL1),
ID_UNALLOCATED(5,2),
ID_UNALLOCATED(5,3),
-- 
2.21.0

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm