* [PATCH 00/18] KVM: arm64: Support FEAT_PMUv3 on Apple hardware
@ 2024-12-17 21:20 Oliver Upton
2024-12-17 21:20 ` [PATCH 01/18] drivers/perf: apple_m1: Refactor event select/filter configuration Oliver Upton
` (20 more replies)
0 siblings, 21 replies; 27+ messages in thread
From: Oliver Upton @ 2024-12-17 21:20 UTC (permalink / raw)
To: kvmarm
Cc: Marc Zyngier, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
Mingwei Zhang, Colton Lewis, Raghavendra Rao Ananta,
Catalin Marinas, Will Deacon, Mark Rutland, linux-arm-kernel,
linux-kernel, Oliver Upton
One of the interesting features of some Apple M* parts is an IMPDEF trap
that routes EL1/EL0 accesses of the PMUv3 registers to EL2. This allows
a hypervisor to emulate an architectural PMUv3 on top of the IMPDEF PMU
hardware present in the CPU.
And if you squint, this _might_ look like a CPU erratum :-)
This series takes advantage of these IMPDEF traps to provide PMUv3 to
KVM guests. As a starting point, only expose the fixed CPU cycle counter
and no event counters. Conveniently, this is enough to get Windows
running as a KVM guest on Apple hardware.
I've tried to keep the deviation to a minimum by refactoring some of the
flows used for PMUv3, e.g. computing PMCEID from the arm_pmu bitmap
instead of reading hardware directly.
RFC -> v1:
- Rebase to 6.13-rc3
- Add support for 1 event counter in addition to CPU cycle counter
- Don't sneak past the PMU event filter (Marc)
- Have the PMU driver provide a PMUv3 -> HW event ID mapping (Marc)
Tested on my M2 with Linux and Windows guests. If possible, I'd
appreciate someone testing on an M1 as I haven't added those MIDRs to
the erratum yet.
Oliver Upton (18):
drivers/perf: apple_m1: Refactor event select/filter configuration
drivers/perf: apple_m1: Support host/guest event filtering
drivers/perf: apple_m1: Map generic branch events
drivers/perf: apple_m1: Provide helper for mapping PMUv3 events
KVM: arm64: Compute PMCEID from arm_pmu's event bitmaps
KVM: arm64: Always support SW_INCR PMU event
KVM: arm64: Remap PMUv3 events onto hardware
KVM: arm64: Use a cpucap to determine if system supports FEAT_PMUv3
KVM: arm64: Drop kvm_arm_pmu_available static key
KVM: arm64: Use guard() to cleanup usage of arm_pmus_lock
KVM: arm64: Move PMUVer filtering into KVM code
KVM: arm64: Compute synthetic sysreg ESR for Apple PMUv3 traps
KVM: arm64: Advertise PMUv3 if IMPDEF traps are present
KVM: arm64: Advertise 0 event counters for IMPDEF PMU
arm64: Enable IMP DEF PMUv3 traps on Apple M2
drivers/perf: apple_m1: Map a few more PMUv3 events
KVM: arm64: Provide 1 event counter on IMPDEF hardware
KVM: arm64: selftests: Add test for probing PMUv3 sysregs
arch/arm64/include/asm/apple_m1_pmu.h | 1 +
arch/arm64/include/asm/cpufeature.h | 28 +---
arch/arm64/kernel/cpu_errata.c | 38 +++++
arch/arm64/kernel/cpufeature.c | 19 +++
arch/arm64/kernel/image-vars.h | 5 -
arch/arm64/kvm/arm.c | 4 +-
arch/arm64/kvm/hyp/include/hyp/switch.h | 4 +-
arch/arm64/kvm/hyp/vhe/switch.c | 22 +++
arch/arm64/kvm/pmu-emul.c | 127 +++++++++++-----
arch/arm64/kvm/pmu.c | 10 +-
arch/arm64/tools/cpucaps | 2 +
drivers/perf/apple_m1_cpu_pmu.c | 103 ++++++++++---
include/kvm/arm_pmu.h | 15 +-
include/linux/perf/arm_pmu.h | 1 +
tools/testing/selftests/kvm/Makefile | 1 +
.../kvm/aarch64/pmuv3_register_probe.c | 135 ++++++++++++++++++
16 files changed, 407 insertions(+), 108 deletions(-)
create mode 100644 tools/testing/selftests/kvm/aarch64/pmuv3_register_probe.c
base-commit: 78d4f34e2115b517bcbfe7ec0d018bbbb6f9b0b8
--
2.39.5
^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH 01/18] drivers/perf: apple_m1: Refactor event select/filter configuration
2024-12-17 21:20 [PATCH 00/18] KVM: arm64: Support FEAT_PMUv3 on Apple hardware Oliver Upton
@ 2024-12-17 21:20 ` Oliver Upton
2024-12-17 21:20 ` [PATCH 02/18] drivers/perf: apple_m1: Support host/guest event filtering Oliver Upton
` (19 subsequent siblings)
20 siblings, 0 replies; 27+ messages in thread
From: Oliver Upton @ 2024-12-17 21:20 UTC (permalink / raw)
To: kvmarm
Cc: Marc Zyngier, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
Mingwei Zhang, Colton Lewis, Raghavendra Rao Ananta,
Catalin Marinas, Will Deacon, Mark Rutland, linux-arm-kernel,
linux-kernel, Oliver Upton
Supporting guest mode events will necessitate programming two event
filters. Prepare by splitting up the programming of the event selector +
event filter into separate headers.
Opportunistically replace RMW patterns with sysreg_clear_set_s().
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
---
arch/arm64/include/asm/apple_m1_pmu.h | 1 +
drivers/perf/apple_m1_cpu_pmu.c | 52 ++++++++++++++++-----------
2 files changed, 33 insertions(+), 20 deletions(-)
diff --git a/arch/arm64/include/asm/apple_m1_pmu.h b/arch/arm64/include/asm/apple_m1_pmu.h
index 99483b19b99f..02e05d05851f 100644
--- a/arch/arm64/include/asm/apple_m1_pmu.h
+++ b/arch/arm64/include/asm/apple_m1_pmu.h
@@ -37,6 +37,7 @@
#define PMCR0_PMI_ENABLE_8_9 GENMASK(45, 44)
#define SYS_IMP_APL_PMCR1_EL1 sys_reg(3, 1, 15, 1, 0)
+#define SYS_IMP_APL_PMCR1_EL12 sys_reg(3, 1, 15, 7, 2)
#define PMCR1_COUNT_A64_EL0_0_7 GENMASK(15, 8)
#define PMCR1_COUNT_A64_EL1_0_7 GENMASK(23, 16)
#define PMCR1_COUNT_A64_EL0_8_9 GENMASK(41, 40)
diff --git a/drivers/perf/apple_m1_cpu_pmu.c b/drivers/perf/apple_m1_cpu_pmu.c
index 1d4d01e1275e..ecc71f6808dd 100644
--- a/drivers/perf/apple_m1_cpu_pmu.c
+++ b/drivers/perf/apple_m1_cpu_pmu.c
@@ -325,11 +325,10 @@ static void m1_pmu_disable_counter_interrupt(unsigned int index)
__m1_pmu_enable_counter_interrupt(index, false);
}
-static void m1_pmu_configure_counter(unsigned int index, u8 event,
- bool user, bool kernel)
+static void __m1_pmu_configure_event_filter(unsigned int index, bool user,
+ bool kernel)
{
- u64 val, user_bit, kernel_bit;
- int shift;
+ u64 clear, set, user_bit, kernel_bit;
switch (index) {
case 0 ... 7:
@@ -344,19 +343,24 @@ static void m1_pmu_configure_counter(unsigned int index, u8 event,
BUG();
}
- val = read_sysreg_s(SYS_IMP_APL_PMCR1_EL1);
-
+ clear = set = 0;
if (user)
- val |= user_bit;
+ set |= user_bit;
else
- val &= ~user_bit;
+ clear |= user_bit;
if (kernel)
- val |= kernel_bit;
+ set |= kernel_bit;
else
- val &= ~kernel_bit;
+ clear |= kernel_bit;
- write_sysreg_s(val, SYS_IMP_APL_PMCR1_EL1);
+ sysreg_clear_set_s(SYS_IMP_APL_PMCR1_EL1, clear, set);
+}
+
+static void __m1_pmu_configure_eventsel(unsigned int index, u8 event)
+{
+ u64 clear = 0, set = 0;
+ int shift;
/*
* Counters 0 and 1 have fixed events. For anything else,
@@ -369,21 +373,29 @@ static void m1_pmu_configure_counter(unsigned int index, u8 event,
break;
case 2 ... 5:
shift = (index - 2) * 8;
- val = read_sysreg_s(SYS_IMP_APL_PMESR0_EL1);
- val &= ~((u64)0xff << shift);
- val |= (u64)event << shift;
- write_sysreg_s(val, SYS_IMP_APL_PMESR0_EL1);
+ clear |= (u64)0xff << shift;
+ set |= (u64)event << shift;
+ sysreg_clear_set_s(SYS_IMP_APL_PMESR0_EL1, clear, set);
break;
case 6 ... 9:
shift = (index - 6) * 8;
- val = read_sysreg_s(SYS_IMP_APL_PMESR1_EL1);
- val &= ~((u64)0xff << shift);
- val |= (u64)event << shift;
- write_sysreg_s(val, SYS_IMP_APL_PMESR1_EL1);
+ clear |= (u64)0xff << shift;
+ set |= (u64)event << shift;
+ sysreg_clear_set_s(SYS_IMP_APL_PMESR1_EL1, clear, set);
break;
}
}
+static void m1_pmu_configure_counter(unsigned int index, unsigned long config_base)
+{
+ bool kernel = config_base & M1_PMU_CFG_COUNT_KERNEL;
+ bool user = config_base & M1_PMU_CFG_COUNT_USER;
+ u8 evt = config_base & M1_PMU_CFG_EVENT;
+
+ __m1_pmu_configure_event_filter(index, user, kernel);
+ __m1_pmu_configure_eventsel(index, evt);
+}
+
/* arm_pmu backend */
static void m1_pmu_enable_event(struct perf_event *event)
{
@@ -398,7 +410,7 @@ static void m1_pmu_enable_event(struct perf_event *event)
m1_pmu_disable_counter(event->hw.idx);
isb();
- m1_pmu_configure_counter(event->hw.idx, evt, user, kernel);
+ m1_pmu_configure_counter(event->hw.idx, event->hw.config_base);
m1_pmu_enable_counter(event->hw.idx);
m1_pmu_enable_counter_interrupt(event->hw.idx);
isb();
--
2.39.5
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH 02/18] drivers/perf: apple_m1: Support host/guest event filtering
2024-12-17 21:20 [PATCH 00/18] KVM: arm64: Support FEAT_PMUv3 on Apple hardware Oliver Upton
2024-12-17 21:20 ` [PATCH 01/18] drivers/perf: apple_m1: Refactor event select/filter configuration Oliver Upton
@ 2024-12-17 21:20 ` Oliver Upton
2024-12-17 21:20 ` [PATCH 03/18] drivers/perf: apple_m1: Map generic branch events Oliver Upton
` (18 subsequent siblings)
20 siblings, 0 replies; 27+ messages in thread
From: Oliver Upton @ 2024-12-17 21:20 UTC (permalink / raw)
To: kvmarm
Cc: Marc Zyngier, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
Mingwei Zhang, Colton Lewis, Raghavendra Rao Ananta,
Catalin Marinas, Will Deacon, Mark Rutland, linux-arm-kernel,
linux-kernel, Oliver Upton
The PMU appears to have a separate register for filtering 'guest'
exception levels (i.e. EL1 and !ELIsInHost(EL0)) which has the same
layout as PMCR1_EL1. Conveniently, there exists a VHE register alias
(PMCR1_EL12) that can be used to configure it.
Support guest events by programming the EL12 register with the intended
guest kernel/userspace filters. Limit support for guest events to VHE
(i.e. kernel running at EL2), as it avoids involving KVM to context
switch PMU registers. VHE is the only supported mode on M* parts anyway,
so this isn't an actual feature limitation.
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
---
drivers/perf/apple_m1_cpu_pmu.c | 20 ++++++++++++++++----
1 file changed, 16 insertions(+), 4 deletions(-)
diff --git a/drivers/perf/apple_m1_cpu_pmu.c b/drivers/perf/apple_m1_cpu_pmu.c
index ecc71f6808dd..2a34523500f8 100644
--- a/drivers/perf/apple_m1_cpu_pmu.c
+++ b/drivers/perf/apple_m1_cpu_pmu.c
@@ -120,6 +120,8 @@ enum m1_pmu_events {
*/
M1_PMU_CFG_COUNT_USER = BIT(8),
M1_PMU_CFG_COUNT_KERNEL = BIT(9),
+ M1_PMU_CFG_COUNT_HOST = BIT(10),
+ M1_PMU_CFG_COUNT_GUEST = BIT(11),
};
/*
@@ -326,7 +328,7 @@ static void m1_pmu_disable_counter_interrupt(unsigned int index)
}
static void __m1_pmu_configure_event_filter(unsigned int index, bool user,
- bool kernel)
+ bool kernel, bool host)
{
u64 clear, set, user_bit, kernel_bit;
@@ -354,7 +356,10 @@ static void __m1_pmu_configure_event_filter(unsigned int index, bool user,
else
clear |= kernel_bit;
- sysreg_clear_set_s(SYS_IMP_APL_PMCR1_EL1, clear, set);
+ if (host)
+ sysreg_clear_set_s(SYS_IMP_APL_PMCR1_EL1, clear, set);
+ else if (is_kernel_in_hyp_mode())
+ sysreg_clear_set_s(SYS_IMP_APL_PMCR1_EL12, clear, set);
}
static void __m1_pmu_configure_eventsel(unsigned int index, u8 event)
@@ -389,10 +394,13 @@ static void __m1_pmu_configure_eventsel(unsigned int index, u8 event)
static void m1_pmu_configure_counter(unsigned int index, unsigned long config_base)
{
bool kernel = config_base & M1_PMU_CFG_COUNT_KERNEL;
+ bool guest = config_base & M1_PMU_CFG_COUNT_GUEST;
+ bool host = config_base & M1_PMU_CFG_COUNT_HOST;
bool user = config_base & M1_PMU_CFG_COUNT_USER;
u8 evt = config_base & M1_PMU_CFG_EVENT;
- __m1_pmu_configure_event_filter(index, user, kernel);
+ __m1_pmu_configure_event_filter(index, user && host, kernel && host, true);
+ __m1_pmu_configure_event_filter(index, user && guest, kernel && guest, false);
__m1_pmu_configure_eventsel(index, evt);
}
@@ -568,7 +576,7 @@ static int m1_pmu_set_event_filter(struct hw_perf_event *event,
{
unsigned long config_base = 0;
- if (!attr->exclude_guest) {
+ if (!attr->exclude_guest && !is_kernel_in_hyp_mode()) {
pr_debug("ARM performance counters do not support mode exclusion\n");
return -EOPNOTSUPP;
}
@@ -576,6 +584,10 @@ static int m1_pmu_set_event_filter(struct hw_perf_event *event,
config_base |= M1_PMU_CFG_COUNT_KERNEL;
if (!attr->exclude_user)
config_base |= M1_PMU_CFG_COUNT_USER;
+ if (!attr->exclude_host)
+ config_base |= M1_PMU_CFG_COUNT_HOST;
+ if (!attr->exclude_guest)
+ config_base |= M1_PMU_CFG_COUNT_GUEST;
event->config_base = config_base;
--
2.39.5
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH 03/18] drivers/perf: apple_m1: Map generic branch events
2024-12-17 21:20 [PATCH 00/18] KVM: arm64: Support FEAT_PMUv3 on Apple hardware Oliver Upton
2024-12-17 21:20 ` [PATCH 01/18] drivers/perf: apple_m1: Refactor event select/filter configuration Oliver Upton
2024-12-17 21:20 ` [PATCH 02/18] drivers/perf: apple_m1: Support host/guest event filtering Oliver Upton
@ 2024-12-17 21:20 ` Oliver Upton
2024-12-17 21:20 ` [PATCH 04/18] drivers/perf: apple_m1: Provide helper for mapping PMUv3 events Oliver Upton
` (17 subsequent siblings)
20 siblings, 0 replies; 27+ messages in thread
From: Oliver Upton @ 2024-12-17 21:20 UTC (permalink / raw)
To: kvmarm
Cc: Marc Zyngier, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
Mingwei Zhang, Colton Lewis, Raghavendra Rao Ananta,
Catalin Marinas, Will Deacon, Mark Rutland, linux-arm-kernel,
linux-kernel, Oliver Upton
Map the generic perf events for branch prediction stats to the
corresponding hardware events.
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
---
drivers/perf/apple_m1_cpu_pmu.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/perf/apple_m1_cpu_pmu.c b/drivers/perf/apple_m1_cpu_pmu.c
index 2a34523500f8..d6d4ff6da862 100644
--- a/drivers/perf/apple_m1_cpu_pmu.c
+++ b/drivers/perf/apple_m1_cpu_pmu.c
@@ -170,6 +170,8 @@ static const unsigned m1_pmu_perf_map[PERF_COUNT_HW_MAX] = {
PERF_MAP_ALL_UNSUPPORTED,
[PERF_COUNT_HW_CPU_CYCLES] = M1_PMU_PERFCTR_CORE_ACTIVE_CYCLE,
[PERF_COUNT_HW_INSTRUCTIONS] = M1_PMU_PERFCTR_INST_ALL,
+ [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = M1_PMU_PERFCTR_INST_BRANCH,
+ [PERF_COUNT_HW_BRANCH_MISSES] = M1_PMU_PERFCTR_BRANCH_MISPRED_NONSPEC,
};
/* sysfs definitions */
--
2.39.5
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH 04/18] drivers/perf: apple_m1: Provide helper for mapping PMUv3 events
2024-12-17 21:20 [PATCH 00/18] KVM: arm64: Support FEAT_PMUv3 on Apple hardware Oliver Upton
` (2 preceding siblings ...)
2024-12-17 21:20 ` [PATCH 03/18] drivers/perf: apple_m1: Map generic branch events Oliver Upton
@ 2024-12-17 21:20 ` Oliver Upton
2024-12-17 21:20 ` [PATCH 05/18] KVM: arm64: Compute PMCEID from arm_pmu's event bitmaps Oliver Upton
` (16 subsequent siblings)
20 siblings, 0 replies; 27+ messages in thread
From: Oliver Upton @ 2024-12-17 21:20 UTC (permalink / raw)
To: kvmarm
Cc: Marc Zyngier, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
Mingwei Zhang, Colton Lewis, Raghavendra Rao Ananta,
Catalin Marinas, Will Deacon, Mark Rutland, linux-arm-kernel,
linux-kernel, Oliver Upton
Apple M* parts carry some IMP DEF traps for guest accesses to PMUv3
registers, even though the underlying hardware doesn't implement PMUv3.
This means it is possible to virtualize PMUv3 for KVM guests.
Add a helper for mapping common PMUv3 event IDs onto hardware event IDs,
keeping the implementation-specific crud in the PMU driver rather than
KVM proper.
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
---
drivers/perf/apple_m1_cpu_pmu.c | 32 ++++++++++++++++++++++++++++++++
include/linux/perf/arm_pmu.h | 1 +
2 files changed, 33 insertions(+)
diff --git a/drivers/perf/apple_m1_cpu_pmu.c b/drivers/perf/apple_m1_cpu_pmu.c
index d6d4ff6da862..b4fe247543a6 100644
--- a/drivers/perf/apple_m1_cpu_pmu.c
+++ b/drivers/perf/apple_m1_cpu_pmu.c
@@ -12,6 +12,7 @@
#include <linux/of.h>
#include <linux/perf/arm_pmu.h>
+#include <linux/perf/arm_pmuv3.h>
#include <linux/platform_device.h>
#include <asm/apple_m1_pmu.h>
@@ -174,6 +175,14 @@ static const unsigned m1_pmu_perf_map[PERF_COUNT_HW_MAX] = {
[PERF_COUNT_HW_BRANCH_MISSES] = M1_PMU_PERFCTR_BRANCH_MISPRED_NONSPEC,
};
+#define M1_PMUV3_EVENT_MAP(pmuv3_event, m1_event) \
+ [ARMV8_PMUV3_PERFCTR_##pmuv3_event] = M1_PMU_PERFCTR_##m1_event
+
+static const unsigned int m1_pmu_pmceid_map[ARMV8_PMUV3_MAX_COMMON_EVENTS] = {
+ [0 ... ARMV8_PMUV3_MAX_COMMON_EVENTS - 1] = HW_OP_UNSUPPORTED,
+ M1_PMUV3_EVENT_MAP(CPU_CYCLES, CORE_ACTIVE_CYCLE),
+};
+
/* sysfs definitions */
static ssize_t m1_pmu_events_sysfs_show(struct device *dev,
struct device_attribute *attr,
@@ -558,6 +567,26 @@ static int m2_pmu_map_event(struct perf_event *event)
return armpmu_map_event(event, &m1_pmu_perf_map, NULL, M1_PMU_CFG_EVENT);
}
+static int m1_pmu_map_pmuv3_event(unsigned int eventsel)
+{
+ int m1_event = HW_OP_UNSUPPORTED;
+
+ if (eventsel < ARMV8_PMUV3_MAX_COMMON_EVENTS)
+ m1_event = m1_pmu_pmceid_map[eventsel];
+
+ return m1_event == HW_OP_UNSUPPORTED ? -EOPNOTSUPP : m1_event;
+}
+
+static void m1_pmu_init_pmceid(struct arm_pmu *pmu)
+{
+ unsigned int event;
+
+ for (event = 0; event < ARMV8_PMUV3_MAX_COMMON_EVENTS; event++) {
+ if (m1_pmu_map_pmuv3_event(event) >= 0)
+ set_bit(event, pmu->pmceid_bitmap);
+ }
+}
+
static void m1_pmu_reset(void *info)
{
int i;
@@ -618,6 +647,9 @@ static int m1_pmu_init(struct arm_pmu *cpu_pmu, u32 flags)
cpu_pmu->reset = m1_pmu_reset;
cpu_pmu->set_event_filter = m1_pmu_set_event_filter;
+ cpu_pmu->map_pmuv3_event = m1_pmu_map_pmuv3_event;
+ m1_pmu_init_pmceid(cpu_pmu);
+
bitmap_set(cpu_pmu->cntr_mask, 0, M1_PMU_NR_COUNTERS);
cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_EVENTS] = &m1_pmu_events_attr_group;
cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_FORMATS] = &m1_pmu_format_attr_group;
diff --git a/include/linux/perf/arm_pmu.h b/include/linux/perf/arm_pmu.h
index 4b5b83677e3f..35f3778ae20e 100644
--- a/include/linux/perf/arm_pmu.h
+++ b/include/linux/perf/arm_pmu.h
@@ -100,6 +100,7 @@ struct arm_pmu {
void (*stop)(struct arm_pmu *);
void (*reset)(void *);
int (*map_event)(struct perf_event *event);
+ int (*map_pmuv3_event)(unsigned int eventsel);
DECLARE_BITMAP(cntr_mask, ARMPMU_MAX_HWEVENTS);
bool secure_access; /* 32-bit ARM only */
#define ARMV8_PMUV3_MAX_COMMON_EVENTS 0x40
--
2.39.5
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH 05/18] KVM: arm64: Compute PMCEID from arm_pmu's event bitmaps
2024-12-17 21:20 [PATCH 00/18] KVM: arm64: Support FEAT_PMUv3 on Apple hardware Oliver Upton
` (3 preceding siblings ...)
2024-12-17 21:20 ` [PATCH 04/18] drivers/perf: apple_m1: Provide helper for mapping PMUv3 events Oliver Upton
@ 2024-12-17 21:20 ` Oliver Upton
2024-12-17 21:20 ` [PATCH 06/18] KVM: arm64: Always support SW_INCR PMU event Oliver Upton
` (15 subsequent siblings)
20 siblings, 0 replies; 27+ messages in thread
From: Oliver Upton @ 2024-12-17 21:20 UTC (permalink / raw)
To: kvmarm
Cc: Marc Zyngier, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
Mingwei Zhang, Colton Lewis, Raghavendra Rao Ananta,
Catalin Marinas, Will Deacon, Mark Rutland, linux-arm-kernel,
linux-kernel, Oliver Upton
The PMUv3 driver populates a couple of bitmaps with the values of
PMCEID{0,1}, from which the guest's PMCEID{0,1} can be derived. This
is particularly convenient when virtualizing PMUv3 on IMP DEF hardware,
as reading the nonexistent PMCEID registers leads to a rather unpleasant
UNDEF.
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
---
arch/arm64/kvm/pmu-emul.c | 47 ++++++++++++++++++++++++++++++---------
1 file changed, 36 insertions(+), 11 deletions(-)
diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
index 456102bc0b55..809d65b912e8 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -861,8 +861,42 @@ static struct arm_pmu *kvm_pmu_probe_armpmu(void)
return pmu;
}
+static u64 __compute_pmceid(struct arm_pmu *pmu, bool pmceid1)
+{
+ u32 hi[2], lo[2];
+
+ bitmap_to_arr32(lo, pmu->pmceid_bitmap, ARMV8_PMUV3_MAX_COMMON_EVENTS);
+ bitmap_to_arr32(hi, pmu->pmceid_ext_bitmap, ARMV8_PMUV3_MAX_COMMON_EVENTS);
+
+ return ((u64)hi[pmceid1] << 32) | lo[pmceid1];
+}
+
+static u64 compute_pmceid0(struct arm_pmu *pmu)
+{
+ u64 val = __compute_pmceid(pmu, 0);
+
+ /* always support CHAIN */
+ val |= BIT(ARMV8_PMUV3_PERFCTR_CHAIN);
+ return val;
+}
+
+static u64 compute_pmceid1(struct arm_pmu *pmu)
+{
+ u64 val = __compute_pmceid(pmu, 1);
+
+ /*
+ * Don't advertise STALL_SLOT*, as PMMIR_EL0 is handled
+ * as RAZ
+ */
+ val &= ~(BIT_ULL(ARMV8_PMUV3_PERFCTR_STALL_SLOT - 32) |
+ BIT_ULL(ARMV8_PMUV3_PERFCTR_STALL_SLOT_FRONTEND - 32) |
+ BIT_ULL(ARMV8_PMUV3_PERFCTR_STALL_SLOT_BACKEND - 32));
+ return val;
+}
+
u64 kvm_pmu_get_pmceid(struct kvm_vcpu *vcpu, bool pmceid1)
{
+ struct arm_pmu *cpu_pmu = vcpu->kvm->arch.arm_pmu;
unsigned long *bmap = vcpu->kvm->arch.pmu_filter;
u64 val, mask = 0;
int base, i, nr_events;
@@ -871,19 +905,10 @@ u64 kvm_pmu_get_pmceid(struct kvm_vcpu *vcpu, bool pmceid1)
return 0;
if (!pmceid1) {
- val = read_sysreg(pmceid0_el0);
- /* always support CHAIN */
- val |= BIT(ARMV8_PMUV3_PERFCTR_CHAIN);
+ val = compute_pmceid0(cpu_pmu);
base = 0;
} else {
- val = read_sysreg(pmceid1_el0);
- /*
- * Don't advertise STALL_SLOT*, as PMMIR_EL0 is handled
- * as RAZ
- */
- val &= ~(BIT_ULL(ARMV8_PMUV3_PERFCTR_STALL_SLOT - 32) |
- BIT_ULL(ARMV8_PMUV3_PERFCTR_STALL_SLOT_FRONTEND - 32) |
- BIT_ULL(ARMV8_PMUV3_PERFCTR_STALL_SLOT_BACKEND - 32));
+ val = compute_pmceid1(cpu_pmu);
base = 32;
}
--
2.39.5
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH 06/18] KVM: arm64: Always support SW_INCR PMU event
2024-12-17 21:20 [PATCH 00/18] KVM: arm64: Support FEAT_PMUv3 on Apple hardware Oliver Upton
` (4 preceding siblings ...)
2024-12-17 21:20 ` [PATCH 05/18] KVM: arm64: Compute PMCEID from arm_pmu's event bitmaps Oliver Upton
@ 2024-12-17 21:20 ` Oliver Upton
2024-12-17 21:20 ` [PATCH 07/18] KVM: arm64: Remap PMUv3 events onto hardware Oliver Upton
` (14 subsequent siblings)
20 siblings, 0 replies; 27+ messages in thread
From: Oliver Upton @ 2024-12-17 21:20 UTC (permalink / raw)
To: kvmarm
Cc: Marc Zyngier, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
Mingwei Zhang, Colton Lewis, Raghavendra Rao Ananta,
Catalin Marinas, Will Deacon, Mark Rutland, linux-arm-kernel,
linux-kernel, Oliver Upton
Support for SW_INCR is unconditional, as KVM traps accesses to
PMSWINC_EL0 and emulates the intended event increment. While it is
expected that ~all PMUv3 implementations already advertise this event,
non-PMUv3 hardware may not.
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
---
arch/arm64/kvm/pmu-emul.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
index 809d65b912e8..7f20da32266e 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -875,6 +875,8 @@ static u64 compute_pmceid0(struct arm_pmu *pmu)
{
u64 val = __compute_pmceid(pmu, 0);
+ /* always support SW_INCR */
+ val |= BIT(ARMV8_PMUV3_PERFCTR_SW_INCR);
/* always support CHAIN */
val |= BIT(ARMV8_PMUV3_PERFCTR_CHAIN);
return val;
--
2.39.5
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH 07/18] KVM: arm64: Remap PMUv3 events onto hardware
2024-12-17 21:20 [PATCH 00/18] KVM: arm64: Support FEAT_PMUv3 on Apple hardware Oliver Upton
` (5 preceding siblings ...)
2024-12-17 21:20 ` [PATCH 06/18] KVM: arm64: Always support SW_INCR PMU event Oliver Upton
@ 2024-12-17 21:20 ` Oliver Upton
2024-12-17 21:20 ` [PATCH 08/18] KVM: arm64: Use a cpucap to determine if system supports FEAT_PMUv3 Oliver Upton
` (13 subsequent siblings)
20 siblings, 0 replies; 27+ messages in thread
From: Oliver Upton @ 2024-12-17 21:20 UTC (permalink / raw)
To: kvmarm
Cc: Marc Zyngier, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
Mingwei Zhang, Colton Lewis, Raghavendra Rao Ananta,
Catalin Marinas, Will Deacon, Mark Rutland, linux-arm-kernel,
linux-kernel, Oliver Upton
Use the provided helper to map PMUv3 event IDs onto hardware, if the
driver exposes such a helper. This is expected to be quite rare, and
only useful for non-PMUv3 hardware.
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
---
arch/arm64/kvm/pmu-emul.c | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
index 7f20da32266e..6d7fc0051ad8 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -692,6 +692,18 @@ static bool kvm_pmc_counts_at_el2(struct kvm_pmc *pmc)
return kvm_pmc_read_evtreg(pmc) & ARMV8_PMU_INCLUDE_EL2;
}
+static u64 kvm_map_pmu_event(struct kvm *kvm, u64 eventsel)
+{
+ struct arm_pmu *pmu = kvm->arch.arm_pmu;
+ int hw_event;
+
+ if (!pmu->map_pmuv3_event)
+ return eventsel;
+
+ hw_event = pmu->map_pmuv3_event(eventsel);
+ return (hw_event < 0) ? eventsel : hw_event;
+}
+
/**
* kvm_pmu_create_perf_event - create a perf event for a counter
* @pmc: Counter context
@@ -730,13 +742,13 @@ static void kvm_pmu_create_perf_event(struct kvm_pmc *pmc)
memset(&attr, 0, sizeof(struct perf_event_attr));
attr.type = arm_pmu->pmu.type;
+ attr.config = kvm_map_pmu_event(vcpu->kvm, eventsel);
attr.size = sizeof(attr);
attr.pinned = 1;
attr.disabled = !kvm_pmu_counter_is_enabled(pmc);
attr.exclude_user = !kvm_pmc_counts_at_el0(pmc);
attr.exclude_hv = 1; /* Don't count EL2 events */
attr.exclude_host = 1; /* Don't count host events */
- attr.config = eventsel;
/*
* Filter events at EL1 (i.e. vEL2) when in a hyp context based on the
--
2.39.5
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH 08/18] KVM: arm64: Use a cpucap to determine if system supports FEAT_PMUv3
2024-12-17 21:20 [PATCH 00/18] KVM: arm64: Support FEAT_PMUv3 on Apple hardware Oliver Upton
` (6 preceding siblings ...)
2024-12-17 21:20 ` [PATCH 07/18] KVM: arm64: Remap PMUv3 events onto hardware Oliver Upton
@ 2024-12-17 21:20 ` Oliver Upton
2024-12-17 21:20 ` [PATCH 09/18] KVM: arm64: Drop kvm_arm_pmu_available static key Oliver Upton
` (12 subsequent siblings)
20 siblings, 0 replies; 27+ messages in thread
From: Oliver Upton @ 2024-12-17 21:20 UTC (permalink / raw)
To: kvmarm
Cc: Marc Zyngier, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
Mingwei Zhang, Colton Lewis, Raghavendra Rao Ananta,
Catalin Marinas, Will Deacon, Mark Rutland, linux-arm-kernel,
linux-kernel, Oliver Upton
KVM is about to learn some new tricks to virtualize PMUv3 on IMPDEF
hardware. As part of that, we now need to differentiate host support
from guest support for PMUv3.
Add a cpucap to determine if an architectural PMUv3 is present to guard
host usage of PMUv3 controls.
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
---
arch/arm64/include/asm/cpufeature.h | 5 +++++
arch/arm64/kernel/cpufeature.c | 19 +++++++++++++++++++
arch/arm64/kvm/hyp/include/hyp/switch.h | 4 ++--
arch/arm64/kvm/pmu.c | 10 +++++-----
arch/arm64/tools/cpucaps | 1 +
include/kvm/arm_pmu.h | 2 +-
6 files changed, 33 insertions(+), 8 deletions(-)
diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index 8b4e5a3cd24c..6a989927926a 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -866,6 +866,11 @@ static __always_inline bool system_supports_mpam_hcr(void)
return alternative_has_cap_unlikely(ARM64_MPAM_HCR);
}
+static inline bool system_supports_pmuv3(void)
+{
+ return cpus_have_final_cap(ARM64_HAS_PMUV3);
+}
+
int do_emulate_mrs(struct pt_regs *regs, u32 sys_reg, u32 rt);
bool try_emulate_mrs(struct pt_regs *regs, u32 isn);
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 6ce71f444ed8..fa73fbdd8617 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -1889,6 +1889,19 @@ static bool has_lpa2(const struct arm64_cpu_capabilities *entry, int scope)
}
#endif
+static bool has_pmuv3(const struct arm64_cpu_capabilities *entry, int scope)
+{
+ u64 dfr0 = read_sanitised_ftr_reg(SYS_ID_AA64DFR0_EL1);
+ unsigned int pmuver;
+
+ pmuver = cpuid_feature_extract_unsigned_field(dfr0,
+ ID_AA64DFR0_EL1_PMUVer_SHIFT);
+ if (pmuver == ID_AA64DFR0_EL1_PMUVer_IMP_DEF)
+ return false;
+
+ return pmuver >= ID_AA64DFR0_EL1_PMUVer_IMP;
+}
+
#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
#define KPTI_NG_TEMP_VA (-(1UL << PMD_SHIFT))
@@ -2990,6 +3003,12 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
ARM64_CPUID_FIELDS(ID_AA64PFR1_EL1, GCS, IMP)
},
#endif
+ {
+ .desc = "PMUv3",
+ .capability = ARM64_HAS_PMUV3,
+ .type = ARM64_CPUCAP_SYSTEM_FEATURE,
+ .matches = has_pmuv3,
+ },
{},
};
diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h
index 34f53707892d..995aca419b1e 100644
--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -244,7 +244,7 @@ static inline void __activate_traps_common(struct kvm_vcpu *vcpu)
* counter, which could make a PMXEVCNTR_EL0 access UNDEF at
* EL1 instead of being trapped to EL2.
*/
- if (kvm_arm_support_pmu_v3()) {
+ if (system_supports_pmuv3()) {
struct kvm_cpu_context *hctxt;
write_sysreg(0, pmselr_el0);
@@ -281,7 +281,7 @@ static inline void __deactivate_traps_common(struct kvm_vcpu *vcpu)
write_sysreg(*host_data_ptr(host_debug_state.mdcr_el2), mdcr_el2);
write_sysreg(0, hstr_el2);
- if (kvm_arm_support_pmu_v3()) {
+ if (system_supports_pmuv3()) {
struct kvm_cpu_context *hctxt;
hctxt = host_data_ptr(host_ctxt);
diff --git a/arch/arm64/kvm/pmu.c b/arch/arm64/kvm/pmu.c
index 0b3adf3e17b4..6b48a3d16d0d 100644
--- a/arch/arm64/kvm/pmu.c
+++ b/arch/arm64/kvm/pmu.c
@@ -41,7 +41,7 @@ void kvm_set_pmu_events(u64 set, struct perf_event_attr *attr)
{
struct kvm_pmu_events *pmu = kvm_get_pmu_events();
- if (!kvm_arm_support_pmu_v3() || !kvm_pmu_switch_needed(attr))
+ if (!system_supports_pmuv3() || !kvm_pmu_switch_needed(attr))
return;
if (!attr->exclude_host)
@@ -57,7 +57,7 @@ void kvm_clr_pmu_events(u64 clr)
{
struct kvm_pmu_events *pmu = kvm_get_pmu_events();
- if (!kvm_arm_support_pmu_v3())
+ if (!system_supports_pmuv3())
return;
pmu->events_host &= ~clr;
@@ -133,7 +133,7 @@ void kvm_vcpu_pmu_restore_guest(struct kvm_vcpu *vcpu)
struct kvm_pmu_events *pmu;
u64 events_guest, events_host;
- if (!kvm_arm_support_pmu_v3() || !has_vhe())
+ if (!system_supports_pmuv3() || !has_vhe())
return;
preempt_disable();
@@ -154,7 +154,7 @@ void kvm_vcpu_pmu_restore_host(struct kvm_vcpu *vcpu)
struct kvm_pmu_events *pmu;
u64 events_guest, events_host;
- if (!kvm_arm_support_pmu_v3() || !has_vhe())
+ if (!system_supports_pmuv3() || !has_vhe())
return;
pmu = kvm_get_pmu_events();
@@ -180,7 +180,7 @@ bool kvm_set_pmuserenr(u64 val)
struct kvm_cpu_context *hctxt;
struct kvm_vcpu *vcpu;
- if (!kvm_arm_support_pmu_v3() || !has_vhe())
+ if (!system_supports_pmuv3() || !has_vhe())
return false;
vcpu = kvm_get_running_vcpu();
diff --git a/arch/arm64/tools/cpucaps b/arch/arm64/tools/cpucaps
index eb17f59e543c..b291eb73f5e0 100644
--- a/arch/arm64/tools/cpucaps
+++ b/arch/arm64/tools/cpucaps
@@ -45,6 +45,7 @@ HAS_LSE_ATOMICS
HAS_MOPS
HAS_NESTED_VIRT
HAS_PAN
+HAS_PMUV3
HAS_S1PIE
HAS_S1POE
HAS_RAS_EXTN
diff --git a/include/kvm/arm_pmu.h b/include/kvm/arm_pmu.h
index e61dd7dd2286..7ef9eb3cede5 100644
--- a/include/kvm/arm_pmu.h
+++ b/include/kvm/arm_pmu.h
@@ -87,7 +87,7 @@ void kvm_vcpu_pmu_resync_el0(void);
*/
#define kvm_pmu_update_vcpu_events(vcpu) \
do { \
- if (!has_vhe() && kvm_arm_support_pmu_v3()) \
+ if (!has_vhe() && system_supports_pmuv3()) \
vcpu->arch.pmu.events = *kvm_get_pmu_events(); \
} while (0)
--
2.39.5
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH 09/18] KVM: arm64: Drop kvm_arm_pmu_available static key
2024-12-17 21:20 [PATCH 00/18] KVM: arm64: Support FEAT_PMUv3 on Apple hardware Oliver Upton
` (7 preceding siblings ...)
2024-12-17 21:20 ` [PATCH 08/18] KVM: arm64: Use a cpucap to determine if system supports FEAT_PMUv3 Oliver Upton
@ 2024-12-17 21:20 ` Oliver Upton
2024-12-18 23:23 ` kernel test robot
2024-12-17 21:20 ` [PATCH 10/18] KVM: arm64: Use guard() to cleanup usage of arm_pmus_lock Oliver Upton
` (11 subsequent siblings)
20 siblings, 1 reply; 27+ messages in thread
From: Oliver Upton @ 2024-12-17 21:20 UTC (permalink / raw)
To: kvmarm
Cc: Marc Zyngier, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
Mingwei Zhang, Colton Lewis, Raghavendra Rao Ananta,
Catalin Marinas, Will Deacon, Mark Rutland, linux-arm-kernel,
linux-kernel, Oliver Upton
With the PMUv3 cpucap, kvm_arm_pmu_available is no longer used in the
hot path of guest entry/exit. On top of that, guest support for PMUv3
may not correlate with host support for the feature, e.g. on IMPDEF
hardware.
Throw out the static key and just inspect the list of PMUs to determine
if PMUv3 is supported for KVM guests.
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
---
arch/arm64/kernel/image-vars.h | 5 -----
arch/arm64/kvm/arm.c | 4 ++--
arch/arm64/kvm/pmu-emul.c | 11 ++++++-----
include/kvm/arm_pmu.h | 13 +------------
4 files changed, 9 insertions(+), 24 deletions(-)
diff --git a/arch/arm64/kernel/image-vars.h b/arch/arm64/kernel/image-vars.h
index 8f5422ed1b75..5919320bc802 100644
--- a/arch/arm64/kernel/image-vars.h
+++ b/arch/arm64/kernel/image-vars.h
@@ -109,11 +109,6 @@ KVM_NVHE_ALIAS(vgic_v3_cpuif_trap);
KVM_NVHE_ALIAS(__start___kvm_ex_table);
KVM_NVHE_ALIAS(__stop___kvm_ex_table);
-/* PMU available static key */
-#ifdef CONFIG_HW_PERF_EVENTS
-KVM_NVHE_ALIAS(kvm_arm_pmu_available);
-#endif
-
/* Position-independent library routines */
KVM_NVHE_ALIAS_HYP(clear_page, __pi_clear_page);
KVM_NVHE_ALIAS_HYP(copy_page, __pi_copy_page);
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index a102c3aebdbc..081e638c674f 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -391,7 +391,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
r = get_num_wrps();
break;
case KVM_CAP_ARM_PMU_V3:
- r = kvm_arm_support_pmu_v3();
+ r = kvm_supports_guest_pmuv3();
break;
case KVM_CAP_ARM_INJECT_SERROR_ESR:
r = cpus_have_final_cap(ARM64_HAS_RAS_EXTN);
@@ -1397,7 +1397,7 @@ static unsigned long system_supported_vcpu_features(void)
if (!cpus_have_final_cap(ARM64_HAS_32BIT_EL1))
clear_bit(KVM_ARM_VCPU_EL1_32BIT, &features);
- if (!kvm_arm_support_pmu_v3())
+ if (!kvm_supports_guest_pmuv3())
clear_bit(KVM_ARM_VCPU_PMU_V3, &features);
if (!system_supports_sve())
diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
index 6d7fc0051ad8..33cd694c754f 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -17,14 +17,18 @@
#define PERF_ATTR_CFG1_COUNTER_64BIT BIT(0)
-DEFINE_STATIC_KEY_FALSE(kvm_arm_pmu_available);
-
static LIST_HEAD(arm_pmus);
static DEFINE_MUTEX(arm_pmus_lock);
static void kvm_pmu_create_perf_event(struct kvm_pmc *pmc);
static void kvm_pmu_release_perf_event(struct kvm_pmc *pmc);
+bool kvm_supports_guest_pmuv3(void)
+{
+ guard(mutex)(&arm_pmus_lock);
+ return !list_empty(&arm_pmus);
+}
+
static struct kvm_vcpu *kvm_pmc_to_vcpu(const struct kvm_pmc *pmc)
{
return container_of(pmc, struct kvm_vcpu, arch.pmu.pmc[pmc->idx]);
@@ -826,9 +830,6 @@ void kvm_host_pmu_init(struct arm_pmu *pmu)
entry->arm_pmu = pmu;
list_add_tail(&entry->entry, &arm_pmus);
- if (list_is_singular(&arm_pmus))
- static_branch_enable(&kvm_arm_pmu_available);
-
out_unlock:
mutex_unlock(&arm_pmus_lock);
}
diff --git a/include/kvm/arm_pmu.h b/include/kvm/arm_pmu.h
index 7ef9eb3cede5..d3dcf5438315 100644
--- a/include/kvm/arm_pmu.h
+++ b/include/kvm/arm_pmu.h
@@ -37,13 +37,7 @@ struct arm_pmu_entry {
struct arm_pmu *arm_pmu;
};
-DECLARE_STATIC_KEY_FALSE(kvm_arm_pmu_available);
-
-static __always_inline bool kvm_arm_support_pmu_v3(void)
-{
- return static_branch_likely(&kvm_arm_pmu_available);
-}
-
+bool kvm_supports_guest_pmuv3(void);
#define kvm_arm_pmu_irq_initialized(v) ((v)->arch.pmu.irq_num >= VGIC_NR_SGIS)
u64 kvm_pmu_get_counter_value(struct kvm_vcpu *vcpu, u64 select_idx);
void kvm_pmu_set_counter_value(struct kvm_vcpu *vcpu, u64 select_idx, u64 val);
@@ -103,11 +97,6 @@ void kvm_pmu_nested_transition(struct kvm_vcpu *vcpu);
struct kvm_pmu {
};
-static inline bool kvm_arm_support_pmu_v3(void)
-{
- return false;
-}
-
#define kvm_arm_pmu_irq_initialized(v) (false)
static inline u64 kvm_pmu_get_counter_value(struct kvm_vcpu *vcpu,
u64 select_idx)
--
2.39.5
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH 10/18] KVM: arm64: Use guard() to cleanup usage of arm_pmus_lock
2024-12-17 21:20 [PATCH 00/18] KVM: arm64: Support FEAT_PMUv3 on Apple hardware Oliver Upton
` (8 preceding siblings ...)
2024-12-17 21:20 ` [PATCH 09/18] KVM: arm64: Drop kvm_arm_pmu_available static key Oliver Upton
@ 2024-12-17 21:20 ` Oliver Upton
2024-12-17 21:20 ` [PATCH 11/18] KVM: arm64: Move PMUVer filtering into KVM code Oliver Upton
` (10 subsequent siblings)
20 siblings, 0 replies; 27+ messages in thread
From: Oliver Upton @ 2024-12-17 21:20 UTC (permalink / raw)
To: kvmarm
Cc: Marc Zyngier, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
Mingwei Zhang, Colton Lewis, Raghavendra Rao Ananta,
Catalin Marinas, Will Deacon, Mark Rutland, linux-arm-kernel,
linux-kernel, Oliver Upton
Get rid of some goto label patterns by using guard() to drop the
arm_pmus_lock when returning from a function.
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
---
arch/arm64/kvm/pmu-emul.c | 23 ++++++++---------------
1 file changed, 8 insertions(+), 15 deletions(-)
diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
index 33cd694c754f..2c98cf24bef3 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -821,26 +821,23 @@ void kvm_host_pmu_init(struct arm_pmu *pmu)
if (!pmuv3_implemented(kvm_arm_pmu_get_pmuver_limit()))
return;
- mutex_lock(&arm_pmus_lock);
+ guard(mutex)(&arm_pmus_lock);
entry = kmalloc(sizeof(*entry), GFP_KERNEL);
if (!entry)
- goto out_unlock;
+ return;
entry->arm_pmu = pmu;
list_add_tail(&entry->entry, &arm_pmus);
-
-out_unlock:
- mutex_unlock(&arm_pmus_lock);
}
static struct arm_pmu *kvm_pmu_probe_armpmu(void)
{
- struct arm_pmu *tmp, *pmu = NULL;
struct arm_pmu_entry *entry;
+ struct arm_pmu *pmu;
int cpu;
- mutex_lock(&arm_pmus_lock);
+ guard(mutex)(&arm_pmus_lock);
/*
* It is safe to use a stale cpu to iterate the list of PMUs so long as
@@ -861,17 +858,13 @@ static struct arm_pmu *kvm_pmu_probe_armpmu(void)
*/
cpu = raw_smp_processor_id();
list_for_each_entry(entry, &arm_pmus, entry) {
- tmp = entry->arm_pmu;
+ pmu = entry->arm_pmu;
- if (cpumask_test_cpu(cpu, &tmp->supported_cpus)) {
- pmu = tmp;
- break;
- }
+ if (cpumask_test_cpu(cpu, &pmu->supported_cpus))
+ return pmu;
}
- mutex_unlock(&arm_pmus_lock);
-
- return pmu;
+ return NULL;
}
static u64 __compute_pmceid(struct arm_pmu *pmu, bool pmceid1)
--
2.39.5
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH 11/18] KVM: arm64: Move PMUVer filtering into KVM code
2024-12-17 21:20 [PATCH 00/18] KVM: arm64: Support FEAT_PMUv3 on Apple hardware Oliver Upton
` (9 preceding siblings ...)
2024-12-17 21:20 ` [PATCH 10/18] KVM: arm64: Use guard() to cleanup usage of arm_pmus_lock Oliver Upton
@ 2024-12-17 21:20 ` Oliver Upton
2024-12-17 21:20 ` [PATCH 12/18] KVM: arm64: Compute synthetic sysreg ESR for Apple PMUv3 traps Oliver Upton
` (9 subsequent siblings)
20 siblings, 0 replies; 27+ messages in thread
From: Oliver Upton @ 2024-12-17 21:20 UTC (permalink / raw)
To: kvmarm
Cc: Marc Zyngier, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
Mingwei Zhang, Colton Lewis, Raghavendra Rao Ananta,
Catalin Marinas, Will Deacon, Mark Rutland, linux-arm-kernel,
linux-kernel, Oliver Upton
The supported guest PMU version on a particular platform is ultimately a
KVM decision. Move PMUVer filtering into KVM code.
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
---
arch/arm64/include/asm/cpufeature.h | 23 -----------------------
arch/arm64/kvm/pmu-emul.c | 15 +++++++++------
2 files changed, 9 insertions(+), 29 deletions(-)
diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index 6a989927926a..d49e9c7e201c 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -525,29 +525,6 @@ cpuid_feature_extract_unsigned_field(u64 features, int field)
return cpuid_feature_extract_unsigned_field_width(features, field, 4);
}
-/*
- * Fields that identify the version of the Performance Monitors Extension do
- * not follow the standard ID scheme. See ARM DDI 0487E.a page D13-2825,
- * "Alternative ID scheme used for the Performance Monitors Extension version".
- */
-static inline u64 __attribute_const__
-cpuid_feature_cap_perfmon_field(u64 features, int field, u64 cap)
-{
- u64 val = cpuid_feature_extract_unsigned_field(features, field);
- u64 mask = GENMASK_ULL(field + 3, field);
-
- /* Treat IMPLEMENTATION DEFINED functionality as unimplemented */
- if (val == ID_AA64DFR0_EL1_PMUVer_IMP_DEF)
- val = 0;
-
- 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);
diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
index 2c98cf24bef3..98690e53dc73 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -1257,13 +1257,16 @@ int kvm_arm_pmu_v3_has_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
u8 kvm_arm_pmu_get_pmuver_limit(void)
{
- u64 tmp;
+ unsigned int pmuver;
- tmp = read_sanitised_ftr_reg(SYS_ID_AA64DFR0_EL1);
- tmp = cpuid_feature_cap_perfmon_field(tmp,
- ID_AA64DFR0_EL1_PMUVer_SHIFT,
- ID_AA64DFR0_EL1_PMUVer_V3P5);
- return FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_PMUVer), tmp);
+ pmuver = SYS_FIELD_GET(ID_AA64DFR0_EL1, PMUVer,
+ read_sanitised_ftr_reg(SYS_ID_AA64DFR0_EL1));
+
+ /* Treat IMPLEMENTATION DEFINED functionality as unimplemented */
+ if (pmuver == ID_AA64DFR0_EL1_PMUVer_IMP_DEF)
+ return 0;
+
+ return min(pmuver, ID_AA64DFR0_EL1_PMUVer_V3P5);
}
/**
--
2.39.5
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH 12/18] KVM: arm64: Compute synthetic sysreg ESR for Apple PMUv3 traps
2024-12-17 21:20 [PATCH 00/18] KVM: arm64: Support FEAT_PMUv3 on Apple hardware Oliver Upton
` (10 preceding siblings ...)
2024-12-17 21:20 ` [PATCH 11/18] KVM: arm64: Move PMUVer filtering into KVM code Oliver Upton
@ 2024-12-17 21:20 ` Oliver Upton
2024-12-17 21:20 ` [PATCH 13/18] KVM: arm64: Advertise PMUv3 if IMPDEF traps are present Oliver Upton
` (8 subsequent siblings)
20 siblings, 0 replies; 27+ messages in thread
From: Oliver Upton @ 2024-12-17 21:20 UTC (permalink / raw)
To: kvmarm
Cc: Marc Zyngier, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
Mingwei Zhang, Colton Lewis, Raghavendra Rao Ananta,
Catalin Marinas, Will Deacon, Mark Rutland, linux-arm-kernel,
linux-kernel, Oliver Upton
Apple M* CPUs provide an IMPDEF trap for PMUv3 sysregs, where ESR_EL2.EC
is a reserved value (0x3F) and a sysreg-like ISS is reported in
AFSR1_EL2.
Compute a synthetic ESR for these PMUv3 traps, giving the illusion of
something architectural to the rest of KVM.
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
---
arch/arm64/kvm/hyp/vhe/switch.c | 22 ++++++++++++++++++++++
arch/arm64/tools/cpucaps | 1 +
2 files changed, 23 insertions(+)
diff --git a/arch/arm64/kvm/hyp/vhe/switch.c b/arch/arm64/kvm/hyp/vhe/switch.c
index 80581b1c3995..da2ccaefaf6f 100644
--- a/arch/arm64/kvm/hyp/vhe/switch.c
+++ b/arch/arm64/kvm/hyp/vhe/switch.c
@@ -418,6 +418,25 @@ static bool kvm_hyp_handle_sysreg_vhe(struct kvm_vcpu *vcpu, u64 *exit_code)
return kvm_hyp_handle_sysreg(vcpu, exit_code);
}
+static bool kvm_hyp_handle_impdef(struct kvm_vcpu *vcpu, u64 *exit_code)
+{
+ u64 iss;
+
+ if (!cpus_have_final_cap(ARM64_WORKAROUND_PMUV3_IMPDEF_TRAPS))
+ return false;
+
+ /*
+ * Compute a synthetic ESR for a sysreg trap. Conveniently, AFSR1_EL2
+ * is populated with a correct ISS for a sysreg trap. These fruity
+ * parts are 64bit only, so unconditionally set IL.
+ */
+ iss = ESR_ELx_ISS(read_sysreg_s(SYS_AFSR1_EL2));
+ vcpu->arch.fault.esr_el2 = FIELD_PREP(ESR_ELx_EC_MASK, ESR_ELx_EC_SYS64) |
+ FIELD_PREP(ESR_ELx_ISS_MASK, iss) |
+ ESR_ELx_IL;
+ return false;
+}
+
static const exit_handler_fn hyp_exit_handlers[] = {
[0 ... ESR_ELx_EC_MAX] = NULL,
[ESR_ELx_EC_CP15_32] = kvm_hyp_handle_cp15_32,
@@ -429,6 +448,9 @@ static const exit_handler_fn hyp_exit_handlers[] = {
[ESR_ELx_EC_WATCHPT_LOW] = kvm_hyp_handle_watchpt_low,
[ESR_ELx_EC_ERET] = kvm_hyp_handle_eret,
[ESR_ELx_EC_MOPS] = kvm_hyp_handle_mops,
+
+ /* Apple shenanigans */
+ [0x3F] = kvm_hyp_handle_impdef,
};
static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu)
diff --git a/arch/arm64/tools/cpucaps b/arch/arm64/tools/cpucaps
index b291eb73f5e0..a9c7111b831e 100644
--- a/arch/arm64/tools/cpucaps
+++ b/arch/arm64/tools/cpucaps
@@ -105,6 +105,7 @@ WORKAROUND_CAVIUM_TX2_219_TVM
WORKAROUND_CLEAN_CACHE
WORKAROUND_DEVICE_LOAD_ACQUIRE
WORKAROUND_NVIDIA_CARMEL_CNP
+WORKAROUND_PMUV3_IMPDEF_TRAPS
WORKAROUND_QCOM_FALKOR_E1003
WORKAROUND_REPEAT_TLBI
WORKAROUND_SPECULATIVE_AT
--
2.39.5
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH 13/18] KVM: arm64: Advertise PMUv3 if IMPDEF traps are present
2024-12-17 21:20 [PATCH 00/18] KVM: arm64: Support FEAT_PMUv3 on Apple hardware Oliver Upton
` (11 preceding siblings ...)
2024-12-17 21:20 ` [PATCH 12/18] KVM: arm64: Compute synthetic sysreg ESR for Apple PMUv3 traps Oliver Upton
@ 2024-12-17 21:20 ` Oliver Upton
2024-12-17 21:22 ` [PATCH 14/18] KVM: arm64: Advertise 0 event counters for IMPDEF PMU Oliver Upton
` (7 subsequent siblings)
20 siblings, 0 replies; 27+ messages in thread
From: Oliver Upton @ 2024-12-17 21:20 UTC (permalink / raw)
To: kvmarm
Cc: Marc Zyngier, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
Mingwei Zhang, Colton Lewis, Raghavendra Rao Ananta,
Catalin Marinas, Will Deacon, Mark Rutland, linux-arm-kernel,
linux-kernel, Oliver Upton
Advertise a baseline PMUv3 implementation when running on hardware with
IMPDEF traps of the PMUv3 sysregs.
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
---
arch/arm64/kvm/pmu-emul.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
index 98690e53dc73..553d02a03877 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -1262,7 +1262,17 @@ u8 kvm_arm_pmu_get_pmuver_limit(void)
pmuver = SYS_FIELD_GET(ID_AA64DFR0_EL1, PMUVer,
read_sanitised_ftr_reg(SYS_ID_AA64DFR0_EL1));
- /* Treat IMPLEMENTATION DEFINED functionality as unimplemented */
+ /*
+ * Spoof a barebones PMUv3 implementation if the system supports IMPDEF
+ * traps of the PMUv3 sysregs
+ */
+ if (cpus_have_final_cap(ARM64_WORKAROUND_PMUV3_IMPDEF_TRAPS))
+ return ID_AA64DFR0_EL1_PMUVer_IMP;
+
+ /*
+ * Otherwise, treat IMPLEMENTATION DEFINED functionality as
+ * unimplemented
+ */
if (pmuver == ID_AA64DFR0_EL1_PMUVer_IMP_DEF)
return 0;
--
2.39.5
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH 14/18] KVM: arm64: Advertise 0 event counters for IMPDEF PMU
2024-12-17 21:20 [PATCH 00/18] KVM: arm64: Support FEAT_PMUv3 on Apple hardware Oliver Upton
` (12 preceding siblings ...)
2024-12-17 21:20 ` [PATCH 13/18] KVM: arm64: Advertise PMUv3 if IMPDEF traps are present Oliver Upton
@ 2024-12-17 21:22 ` Oliver Upton
2024-12-17 21:22 ` [PATCH 15/18] arm64: Enable IMP DEF PMUv3 traps on Apple M2 Oliver Upton
` (6 subsequent siblings)
20 siblings, 0 replies; 27+ messages in thread
From: Oliver Upton @ 2024-12-17 21:22 UTC (permalink / raw)
To: kvmarm
Cc: Marc Zyngier, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
Mingwei Zhang, Colton Lewis, Raghavendra Rao Ananta,
Catalin Marinas, Will Deacon, Mark Rutland, linux-arm-kernel,
linux-kernel, Oliver Upton
The programmable event counters on Apple M* parts are quite different
from what's available in PMUv3, as the event counters aren't fungible
(some events only work on specific counters) and the event ID space
doesn't match the architecture.
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
---
arch/arm64/kvm/pmu-emul.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
index 553d02a03877..3803737cbf7c 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -1046,6 +1046,9 @@ u8 kvm_arm_pmu_get_max_counters(struct kvm *kvm)
{
struct arm_pmu *arm_pmu = kvm->arch.arm_pmu;
+ if (cpus_have_final_cap(ARM64_WORKAROUND_PMUV3_IMPDEF_TRAPS))
+ return 0;
+
/*
* The arm_pmu->cntr_mask considers the fixed counter(s) as well.
* Ignore those and return only the general-purpose counters.
--
2.39.5
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH 15/18] arm64: Enable IMP DEF PMUv3 traps on Apple M2
2024-12-17 21:20 [PATCH 00/18] KVM: arm64: Support FEAT_PMUv3 on Apple hardware Oliver Upton
` (13 preceding siblings ...)
2024-12-17 21:22 ` [PATCH 14/18] KVM: arm64: Advertise 0 event counters for IMPDEF PMU Oliver Upton
@ 2024-12-17 21:22 ` Oliver Upton
2024-12-17 21:23 ` [RFC PATCH 16/18] drivers/perf: apple_m1: Map a few more PMUv3 events Oliver Upton
` (5 subsequent siblings)
20 siblings, 0 replies; 27+ messages in thread
From: Oliver Upton @ 2024-12-17 21:22 UTC (permalink / raw)
To: kvmarm
Cc: Marc Zyngier, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
Mingwei Zhang, Colton Lewis, Raghavendra Rao Ananta,
Catalin Marinas, Will Deacon, Mark Rutland, linux-arm-kernel,
linux-kernel, Oliver Upton
Apple M2 CPUs support IMPDEF traps of the PMUv3 sysregs, allowing a
hypervisor to virtualize an architectural PMU for a VM. Flip the
appropriate bit in HACR_EL2 on supporting hardware.
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
---
arch/arm64/kernel/cpu_errata.c | 38 ++++++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index a78f247029ae..441ee4ffc770 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -194,6 +194,37 @@ has_neoverse_n1_erratum_1542419(const struct arm64_cpu_capabilities *entry,
return is_midr_in_range(midr, &range) && has_dic;
}
+static const struct midr_range impdef_pmuv3_cpus[] = {
+ MIDR_ALL_VERSIONS(MIDR_APPLE_M2_BLIZZARD),
+ MIDR_ALL_VERSIONS(MIDR_APPLE_M2_AVALANCHE),
+ MIDR_ALL_VERSIONS(MIDR_APPLE_M2_BLIZZARD_PRO),
+ MIDR_ALL_VERSIONS(MIDR_APPLE_M2_AVALANCHE_PRO),
+ MIDR_ALL_VERSIONS(MIDR_APPLE_M2_BLIZZARD_MAX),
+ MIDR_ALL_VERSIONS(MIDR_APPLE_M2_AVALANCHE_MAX),
+ {},
+};
+
+static bool has_impdef_pmuv3(const struct arm64_cpu_capabilities *entry, int scope)
+{
+ u64 dfr0 = read_sanitised_ftr_reg(SYS_ID_AA64DFR0_EL1);
+ unsigned int pmuver;
+
+ if (!is_kernel_in_hyp_mode())
+ return false;
+
+ pmuver = cpuid_feature_extract_unsigned_field(dfr0,
+ ID_AA64DFR0_EL1_PMUVer_SHIFT);
+ if (pmuver != ID_AA64DFR0_EL1_PMUVer_IMP_DEF)
+ return false;
+
+ return is_midr_in_range_list(read_cpuid_id(), impdef_pmuv3_cpus);
+}
+
+static void cpu_enable_impdef_pmuv3_traps(const struct arm64_cpu_capabilities *__unused)
+{
+ sysreg_clear_set_s(SYS_HACR_EL2, 0, BIT(56));
+}
+
#ifdef CONFIG_ARM64_WORKAROUND_REPEAT_TLBI
static const struct arm64_cpu_capabilities arm64_repeat_tlbi_list[] = {
#ifdef CONFIG_QCOM_FALKOR_ERRATUM_1009
@@ -786,6 +817,13 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
ERRATA_MIDR_RANGE_LIST(erratum_ac03_cpu_38_list),
},
#endif
+ {
+ .desc = "Apple IMPDEF PMUv3 Traps",
+ .capability = ARM64_WORKAROUND_PMUV3_IMPDEF_TRAPS,
+ .type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
+ .matches = has_impdef_pmuv3,
+ .cpu_enable = cpu_enable_impdef_pmuv3_traps,
+ },
{
}
};
--
2.39.5
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [RFC PATCH 16/18] drivers/perf: apple_m1: Map a few more PMUv3 events
2024-12-17 21:20 [PATCH 00/18] KVM: arm64: Support FEAT_PMUv3 on Apple hardware Oliver Upton
` (14 preceding siblings ...)
2024-12-17 21:22 ` [PATCH 15/18] arm64: Enable IMP DEF PMUv3 traps on Apple M2 Oliver Upton
@ 2024-12-17 21:23 ` Oliver Upton
2024-12-17 21:23 ` [RFC PATCH 17/18] KVM: arm64: Provide 1 event counter on IMPDEF hardware Oliver Upton
` (4 subsequent siblings)
20 siblings, 0 replies; 27+ messages in thread
From: Oliver Upton @ 2024-12-17 21:23 UTC (permalink / raw)
To: kvmarm
Cc: Marc Zyngier, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
Mingwei Zhang, Colton Lewis, Raghavendra Rao Ananta,
Catalin Marinas, Will Deacon, Mark Rutland, linux-arm-kernel,
linux-kernel, Oliver Upton
Map some more PMUv3 events onto hardware so 'perf stat' in a KVM VM can
show some useful information (e.g. IPC, branch prediction rate).
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
---
drivers/perf/apple_m1_cpu_pmu.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/perf/apple_m1_cpu_pmu.c b/drivers/perf/apple_m1_cpu_pmu.c
index b4fe247543a6..0e54d3f900a7 100644
--- a/drivers/perf/apple_m1_cpu_pmu.c
+++ b/drivers/perf/apple_m1_cpu_pmu.c
@@ -180,7 +180,10 @@ static const unsigned m1_pmu_perf_map[PERF_COUNT_HW_MAX] = {
static const unsigned int m1_pmu_pmceid_map[ARMV8_PMUV3_MAX_COMMON_EVENTS] = {
[0 ... ARMV8_PMUV3_MAX_COMMON_EVENTS - 1] = HW_OP_UNSUPPORTED,
+ M1_PMUV3_EVENT_MAP(INST_RETIRED, INST_ALL),
M1_PMUV3_EVENT_MAP(CPU_CYCLES, CORE_ACTIVE_CYCLE),
+ M1_PMUV3_EVENT_MAP(BR_RETIRED, INST_BRANCH),
+ M1_PMUV3_EVENT_MAP(BR_MIS_PRED_RETIRED, BRANCH_MISPRED_NONSPEC),
};
/* sysfs definitions */
--
2.39.5
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [RFC PATCH 17/18] KVM: arm64: Provide 1 event counter on IMPDEF hardware
2024-12-17 21:20 [PATCH 00/18] KVM: arm64: Support FEAT_PMUv3 on Apple hardware Oliver Upton
` (15 preceding siblings ...)
2024-12-17 21:23 ` [RFC PATCH 16/18] drivers/perf: apple_m1: Map a few more PMUv3 events Oliver Upton
@ 2024-12-17 21:23 ` Oliver Upton
2024-12-17 21:23 ` [HACK PATCH 18/18] KVM: arm64: selftests: Add test for probing PMUv3 sysregs Oliver Upton
` (3 subsequent siblings)
20 siblings, 0 replies; 27+ messages in thread
From: Oliver Upton @ 2024-12-17 21:23 UTC (permalink / raw)
To: kvmarm
Cc: Marc Zyngier, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
Mingwei Zhang, Colton Lewis, Raghavendra Rao Ananta,
Catalin Marinas, Will Deacon, Mark Rutland, linux-arm-kernel,
linux-kernel, Oliver Upton
PMUv3 requires that all programmable event counters are capable of
counting any event. The Apple M* PMU is quite a bit different, and
events have affinities for particular PMCs.
Expose 1 event counter on IMPDEF hardware, allowing the guest to do
something useful with its PMU while also upholding the requirements of
the architecture.
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
---
Jury is still out on whether we want to do this, which is why this patch
is RFC.
arch/arm64/kvm/pmu-emul.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
index 3803737cbf7c..8f96a34d3da5 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -1046,8 +1046,12 @@ u8 kvm_arm_pmu_get_max_counters(struct kvm *kvm)
{
struct arm_pmu *arm_pmu = kvm->arch.arm_pmu;
+ /*
+ * PMUv3 requires that all event counters are capable of counting any
+ * event, though the same may not be true of non-PMUv3 hardware.
+ */
if (cpus_have_final_cap(ARM64_WORKAROUND_PMUV3_IMPDEF_TRAPS))
- return 0;
+ return 1;
/*
* The arm_pmu->cntr_mask considers the fixed counter(s) as well.
--
2.39.5
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [HACK PATCH 18/18] KVM: arm64: selftests: Add test for probing PMUv3 sysregs
2024-12-17 21:20 [PATCH 00/18] KVM: arm64: Support FEAT_PMUv3 on Apple hardware Oliver Upton
` (16 preceding siblings ...)
2024-12-17 21:23 ` [RFC PATCH 17/18] KVM: arm64: Provide 1 event counter on IMPDEF hardware Oliver Upton
@ 2024-12-17 21:23 ` Oliver Upton
2024-12-21 13:45 ` [PATCH 00/18] KVM: arm64: Support FEAT_PMUv3 on Apple hardware Janne Grunau
` (2 subsequent siblings)
20 siblings, 0 replies; 27+ messages in thread
From: Oliver Upton @ 2024-12-17 21:23 UTC (permalink / raw)
To: kvmarm
Cc: Marc Zyngier, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
Mingwei Zhang, Colton Lewis, Raghavendra Rao Ananta,
Catalin Marinas, Will Deacon, Mark Rutland, linux-arm-kernel,
linux-kernel, Oliver Upton
Add a test for sniffing out PMUv3 register traps.
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
---
Not intended to be applied, just sharing in case someone finds it
useful.
tools/testing/selftests/kvm/Makefile | 1 +
.../kvm/aarch64/pmuv3_register_probe.c | 135 ++++++++++++++++++
2 files changed, 136 insertions(+)
create mode 100644 tools/testing/selftests/kvm/aarch64/pmuv3_register_probe.c
diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile
index 41593d2e7de9..739542928306 100644
--- a/tools/testing/selftests/kvm/Makefile
+++ b/tools/testing/selftests/kvm/Makefile
@@ -159,6 +159,7 @@ TEST_GEN_PROGS_aarch64 += aarch64/debug-exceptions
TEST_GEN_PROGS_aarch64 += aarch64/hypercalls
TEST_GEN_PROGS_aarch64 += aarch64/mmio_abort
TEST_GEN_PROGS_aarch64 += aarch64/page_fault_test
+TEST_GEN_PROGS_aarch64 += aarch64/pmuv3_register_probe
TEST_GEN_PROGS_aarch64 += aarch64/psci_test
TEST_GEN_PROGS_aarch64 += aarch64/set_id_regs
TEST_GEN_PROGS_aarch64 += aarch64/smccc_filter
diff --git a/tools/testing/selftests/kvm/aarch64/pmuv3_register_probe.c b/tools/testing/selftests/kvm/aarch64/pmuv3_register_probe.c
new file mode 100644
index 000000000000..859b0162dbeb
--- /dev/null
+++ b/tools/testing/selftests/kvm/aarch64/pmuv3_register_probe.c
@@ -0,0 +1,135 @@
+#include <perf/arm_pmuv3.h>
+
+#include "vgic.h"
+#include "test_util.h"
+#include "processor.h"
+
+static bool undef_taken;
+
+#define test_read(sr) \
+do { \
+ u64 __val = read_sysreg(sr); \
+ \
+ if (READ_ONCE(undef_taken)) \
+ GUEST_PRINTF("read_sysreg("#sr"): UNDEFINED\n"); \
+ else \
+ GUEST_PRINTF("read_sysreg("#sr"): %lx\n", __val); \
+ WRITE_ONCE(undef_taken, false); \
+} while (0)
+
+#define test_write(val, sr) \
+do { \
+ write_sysreg(val, sr); \
+ \
+ if (READ_ONCE(undef_taken)) \
+ GUEST_PRINTF("write_sysreg(%x, "#sr"): UNDEFINED\n", val); \
+ else \
+ GUEST_PRINTF("write_sysreg(%x, "#sr"): OK\n", val); \
+ WRITE_ONCE(undef_taken, false); \
+} while (0)
+
+static void guest_undef_handler(struct ex_regs *regs)
+{
+ WRITE_ONCE(undef_taken, true);
+ regs->pc += 4;
+}
+
+#define READ_PMEVCNTRN(n) test_read(pmevcntr##n##_el0)
+static void test_read_evcntr(int n)
+{
+ PMEVN_SWITCH(n, READ_PMEVCNTRN);
+}
+
+#define READ_PMEVTYPERN(n) test_read(pmevtyper##n##_el0);
+static void test_read_evtyper(int n)
+{
+ PMEVN_SWITCH(n, READ_PMEVTYPERN);
+}
+
+static void guest_code(void)
+{
+ test_read(pmcr_el0);
+ test_read(pmcntenset_el0);
+ test_read(pmcntenclr_el0);
+ test_read(pmovsset_el0);
+ test_read(pmovsclr_el0);
+ test_read(pmintenset_el1);
+ test_read(pmintenclr_el1);
+ test_read(pmceid0_el0);
+ test_read(pmceid1_el0);
+
+ test_read(pmccntr_el0);
+ test_read(pmccfiltr_el0);
+ test_write(0, pmswinc_el0);
+
+ test_write(0, pmselr_el0);
+ test_read(pmxevcntr_el0);
+ test_read(pmxevtyper_el0);
+
+ test_read(pmuserenr_el0);
+
+ for (int i = 0; i < 31; i++) {
+ test_read_evcntr(i);
+ test_read_evtyper(i);
+ }
+
+ GUEST_DONE();
+}
+
+static void run_test(struct kvm_vcpu *vcpu)
+{
+ struct ucall uc;
+
+ while (true) {
+ vcpu_run(vcpu);
+
+ switch (get_ucall(vcpu, &uc)) {
+ case UCALL_PRINTF:
+ REPORT_GUEST_PRINTF(uc);
+ break;
+ case UCALL_DONE:
+ return;
+ default:
+ TEST_FAIL("Unknown ucall %lu", uc.cmd);
+ }
+ }
+}
+
+int main(void)
+{
+ struct kvm_device_attr attr;
+ struct kvm_vcpu_init init;
+ struct kvm_vcpu *vcpu;
+ struct kvm_vm *vm;
+ int irq = 23;
+
+ TEST_REQUIRE(kvm_has_cap(KVM_CAP_ARM_PMU_V3));
+
+ vm = vm_create(1);
+ vm_ioctl(vm, KVM_ARM_PREFERRED_TARGET, &init);
+ init.features[0] |= (1 << KVM_ARM_VCPU_PMU_V3);
+ vcpu = aarch64_vcpu_add(vm, 0, &init, guest_code);
+
+ __TEST_REQUIRE(vgic_v3_setup(vm, 1, 64) >= 0,
+ "Failed to create vgic-v3, skipping");
+
+ vm_init_descriptor_tables(vm);
+ vcpu_init_descriptor_tables(vcpu);
+ vm_install_sync_handler(vm, VECTOR_SYNC_CURRENT, ESR_ELx_EC_UNKNOWN,
+ guest_undef_handler);
+
+ attr = (struct kvm_device_attr) {
+ .group = KVM_ARM_VCPU_PMU_V3_CTRL,
+ .attr = KVM_ARM_VCPU_PMU_V3_IRQ,
+ .addr = (u64)&irq,
+ };
+ vcpu_ioctl(vcpu, KVM_SET_DEVICE_ATTR, &attr);
+
+ attr = (struct kvm_device_attr) {
+ .group = KVM_ARM_VCPU_PMU_V3_CTRL,
+ .attr = KVM_ARM_VCPU_PMU_V3_INIT,
+ };
+ vcpu_ioctl(vcpu, KVM_SET_DEVICE_ATTR, &attr);
+
+ run_test(vcpu);
+}
--
2.39.5
^ permalink raw reply related [flat|nested] 27+ messages in thread
* Re: [PATCH 09/18] KVM: arm64: Drop kvm_arm_pmu_available static key
2024-12-17 21:20 ` [PATCH 09/18] KVM: arm64: Drop kvm_arm_pmu_available static key Oliver Upton
@ 2024-12-18 23:23 ` kernel test robot
0 siblings, 0 replies; 27+ messages in thread
From: kernel test robot @ 2024-12-18 23:23 UTC (permalink / raw)
To: Oliver Upton, kvmarm
Cc: llvm, oe-kbuild-all, Marc Zyngier, Joey Gouly, Suzuki K Poulose,
Zenghui Yu, Mingwei Zhang, Colton Lewis, Raghavendra Rao Ananta,
Catalin Marinas, Will Deacon, Mark Rutland, linux-arm-kernel,
linux-kernel, Oliver Upton
Hi Oliver,
kernel test robot noticed the following build errors:
[auto build test ERROR on 78d4f34e2115b517bcbfe7ec0d018bbbb6f9b0b8]
url: https://github.com/intel-lab-lkp/linux/commits/Oliver-Upton/drivers-perf-apple_m1-Refactor-event-select-filter-configuration/20241218-054416
base: 78d4f34e2115b517bcbfe7ec0d018bbbb6f9b0b8
patch link: https://lore.kernel.org/r/20241217212048.3709204-10-oliver.upton%40linux.dev
patch subject: [PATCH 09/18] KVM: arm64: Drop kvm_arm_pmu_available static key
config: arm64-randconfig-001-20241219 (https://download.01.org/0day-ci/archive/20241219/202412190743.1bLEb7Ps-lkp@intel.com/config)
compiler: clang version 16.0.6 (https://github.com/llvm/llvm-project 7cbf1a2591520c2491aa35339f227775f4d3adf6)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20241219/202412190743.1bLEb7Ps-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202412190743.1bLEb7Ps-lkp@intel.com/
All errors (new ones prefixed by >>):
>> arch/arm64/kvm/arm.c:394:7: error: call to undeclared function 'kvm_supports_guest_pmuv3'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
r = kvm_supports_guest_pmuv3();
^
arch/arm64/kvm/arm.c:1400:7: error: call to undeclared function 'kvm_supports_guest_pmuv3'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
if (!kvm_supports_guest_pmuv3())
^
2 errors generated.
vim +/kvm_supports_guest_pmuv3 +394 arch/arm64/kvm/arm.c
309
310 int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
311 {
312 int r;
313
314 if (kvm && kvm_vm_is_protected(kvm) && !pkvm_ext_allowed(kvm, ext))
315 return 0;
316
317 switch (ext) {
318 case KVM_CAP_IRQCHIP:
319 r = vgic_present;
320 break;
321 case KVM_CAP_IOEVENTFD:
322 case KVM_CAP_USER_MEMORY:
323 case KVM_CAP_SYNC_MMU:
324 case KVM_CAP_DESTROY_MEMORY_REGION_WORKS:
325 case KVM_CAP_ONE_REG:
326 case KVM_CAP_ARM_PSCI:
327 case KVM_CAP_ARM_PSCI_0_2:
328 case KVM_CAP_READONLY_MEM:
329 case KVM_CAP_MP_STATE:
330 case KVM_CAP_IMMEDIATE_EXIT:
331 case KVM_CAP_VCPU_EVENTS:
332 case KVM_CAP_ARM_IRQ_LINE_LAYOUT_2:
333 case KVM_CAP_ARM_NISV_TO_USER:
334 case KVM_CAP_ARM_INJECT_EXT_DABT:
335 case KVM_CAP_SET_GUEST_DEBUG:
336 case KVM_CAP_VCPU_ATTRIBUTES:
337 case KVM_CAP_PTP_KVM:
338 case KVM_CAP_ARM_SYSTEM_SUSPEND:
339 case KVM_CAP_IRQFD_RESAMPLE:
340 case KVM_CAP_COUNTER_OFFSET:
341 r = 1;
342 break;
343 case KVM_CAP_SET_GUEST_DEBUG2:
344 return KVM_GUESTDBG_VALID_MASK;
345 case KVM_CAP_ARM_SET_DEVICE_ADDR:
346 r = 1;
347 break;
348 case KVM_CAP_NR_VCPUS:
349 /*
350 * ARM64 treats KVM_CAP_NR_CPUS differently from all other
351 * architectures, as it does not always bound it to
352 * KVM_CAP_MAX_VCPUS. It should not matter much because
353 * this is just an advisory value.
354 */
355 r = min_t(unsigned int, num_online_cpus(),
356 kvm_arm_default_max_vcpus());
357 break;
358 case KVM_CAP_MAX_VCPUS:
359 case KVM_CAP_MAX_VCPU_ID:
360 if (kvm)
361 r = kvm->max_vcpus;
362 else
363 r = kvm_arm_default_max_vcpus();
364 break;
365 case KVM_CAP_MSI_DEVID:
366 if (!kvm)
367 r = -EINVAL;
368 else
369 r = kvm->arch.vgic.msis_require_devid;
370 break;
371 case KVM_CAP_ARM_USER_IRQ:
372 /*
373 * 1: EL1_VTIMER, EL1_PTIMER, and PMU.
374 * (bump this number if adding more devices)
375 */
376 r = 1;
377 break;
378 case KVM_CAP_ARM_MTE:
379 r = system_supports_mte();
380 break;
381 case KVM_CAP_STEAL_TIME:
382 r = kvm_arm_pvtime_supported();
383 break;
384 case KVM_CAP_ARM_EL1_32BIT:
385 r = cpus_have_final_cap(ARM64_HAS_32BIT_EL1);
386 break;
387 case KVM_CAP_GUEST_DEBUG_HW_BPS:
388 r = get_num_brps();
389 break;
390 case KVM_CAP_GUEST_DEBUG_HW_WPS:
391 r = get_num_wrps();
392 break;
393 case KVM_CAP_ARM_PMU_V3:
> 394 r = kvm_supports_guest_pmuv3();
395 break;
396 case KVM_CAP_ARM_INJECT_SERROR_ESR:
397 r = cpus_have_final_cap(ARM64_HAS_RAS_EXTN);
398 break;
399 case KVM_CAP_ARM_VM_IPA_SIZE:
400 r = get_kvm_ipa_limit();
401 break;
402 case KVM_CAP_ARM_SVE:
403 r = system_supports_sve();
404 break;
405 case KVM_CAP_ARM_PTRAUTH_ADDRESS:
406 case KVM_CAP_ARM_PTRAUTH_GENERIC:
407 r = kvm_has_full_ptr_auth();
408 break;
409 case KVM_CAP_ARM_EAGER_SPLIT_CHUNK_SIZE:
410 if (kvm)
411 r = kvm->arch.mmu.split_page_chunk_size;
412 else
413 r = KVM_ARM_EAGER_SPLIT_CHUNK_SIZE_DEFAULT;
414 break;
415 case KVM_CAP_ARM_SUPPORTED_BLOCK_SIZES:
416 r = kvm_supported_block_sizes();
417 break;
418 case KVM_CAP_ARM_SUPPORTED_REG_MASK_RANGES:
419 r = BIT(0);
420 break;
421 default:
422 r = 0;
423 }
424
425 return r;
426 }
427
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 00/18] KVM: arm64: Support FEAT_PMUv3 on Apple hardware
2024-12-17 21:20 [PATCH 00/18] KVM: arm64: Support FEAT_PMUv3 on Apple hardware Oliver Upton
` (17 preceding siblings ...)
2024-12-17 21:23 ` [HACK PATCH 18/18] KVM: arm64: selftests: Add test for probing PMUv3 sysregs Oliver Upton
@ 2024-12-21 13:45 ` Janne Grunau
2024-12-21 22:00 ` Oliver Upton
2025-01-08 12:38 ` Will Deacon
2025-01-10 16:22 ` [PATCH 00/18] KVM: arm64: Support FEAT_PMUv3 on Apple hardware Will Deacon
20 siblings, 1 reply; 27+ messages in thread
From: Janne Grunau @ 2024-12-21 13:45 UTC (permalink / raw)
To: Oliver Upton
Cc: kvmarm, Marc Zyngier, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
Mingwei Zhang, Colton Lewis, Raghavendra Rao Ananta,
Catalin Marinas, Will Deacon, Mark Rutland, linux-arm-kernel,
linux-kernel, asahi
On Tue, Dec 17, 2024 at 01:20:30PM -0800, Oliver Upton wrote:
> One of the interesting features of some Apple M* parts is an IMPDEF trap
> that routes EL1/EL0 accesses of the PMUv3 registers to EL2. This allows
> a hypervisor to emulate an architectural PMUv3 on top of the IMPDEF PMU
> hardware present in the CPU.
>
> And if you squint, this _might_ look like a CPU erratum :-)
>
> This series takes advantage of these IMPDEF traps to provide PMUv3 to
> KVM guests. As a starting point, only expose the fixed CPU cycle counter
> and no event counters. Conveniently, this is enough to get Windows
> running as a KVM guest on Apple hardware.
>
> I've tried to keep the deviation to a minimum by refactoring some of the
> flows used for PMUv3, e.g. computing PMCEID from the arm_pmu bitmap
> instead of reading hardware directly.
>
> RFC -> v1:
> - Rebase to 6.13-rc3
> - Add support for 1 event counter in addition to CPU cycle counter
> - Don't sneak past the PMU event filter (Marc)
> - Have the PMU driver provide a PMUv3 -> HW event ID mapping (Marc)
>
> Tested on my M2 with Linux and Windows guests. If possible, I'd
> appreciate someone testing on an M1 as I haven't added those MIDRs to
> the erratum yet.
Tested on M1 (t8103) with perf in a Linux guest and the patch below
Tested-by: Janne Grunau <j@jannau.net>
I'll import this into the downstream asahi kernel as there was a request
for performance counters to aid FEX-Emu development recently.
Janne
---
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index 441ee4ffc7709..45ef67ec970f5 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -195,6 +195,12 @@ has_neoverse_n1_erratum_1542419(const struct arm64_cpu_capabilities *entry,
}
static const struct midr_range impdef_pmuv3_cpus[] = {
+ MIDR_ALL_VERSIONS(MIDR_APPLE_M1_ICESTORM),
+ MIDR_ALL_VERSIONS(MIDR_APPLE_M1_FIRESTORM),
+ MIDR_ALL_VERSIONS(MIDR_APPLE_M1_ICESTORM_PRO),
+ MIDR_ALL_VERSIONS(MIDR_APPLE_M1_FIRESTORM_PRO),
+ MIDR_ALL_VERSIONS(MIDR_APPLE_M1_ICESTORM_MAX),
+ MIDR_ALL_VERSIONS(MIDR_APPLE_M1_FIRESTORM_MAX),
MIDR_ALL_VERSIONS(MIDR_APPLE_M2_BLIZZARD),
MIDR_ALL_VERSIONS(MIDR_APPLE_M2_AVALANCHE),
MIDR_ALL_VERSIONS(MIDR_APPLE_M2_BLIZZARD_PRO),
^ permalink raw reply related [flat|nested] 27+ messages in thread
* Re: [PATCH 00/18] KVM: arm64: Support FEAT_PMUv3 on Apple hardware
2024-12-21 13:45 ` [PATCH 00/18] KVM: arm64: Support FEAT_PMUv3 on Apple hardware Janne Grunau
@ 2024-12-21 22:00 ` Oliver Upton
0 siblings, 0 replies; 27+ messages in thread
From: Oliver Upton @ 2024-12-21 22:00 UTC (permalink / raw)
To: Janne Grunau
Cc: kvmarm, Marc Zyngier, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
Mingwei Zhang, Colton Lewis, Raghavendra Rao Ananta,
Catalin Marinas, Will Deacon, Mark Rutland, linux-arm-kernel,
linux-kernel, asahi
On Sat, Dec 21, 2024 at 02:45:49PM +0100, Janne Grunau wrote:
> On Tue, Dec 17, 2024 at 01:20:30PM -0800, Oliver Upton wrote:
> > One of the interesting features of some Apple M* parts is an IMPDEF trap
> > that routes EL1/EL0 accesses of the PMUv3 registers to EL2. This allows
> > a hypervisor to emulate an architectural PMUv3 on top of the IMPDEF PMU
> > hardware present in the CPU.
> >
> > And if you squint, this _might_ look like a CPU erratum :-)
> >
> > This series takes advantage of these IMPDEF traps to provide PMUv3 to
> > KVM guests. As a starting point, only expose the fixed CPU cycle counter
> > and no event counters. Conveniently, this is enough to get Windows
> > running as a KVM guest on Apple hardware.
> >
> > I've tried to keep the deviation to a minimum by refactoring some of the
> > flows used for PMUv3, e.g. computing PMCEID from the arm_pmu bitmap
> > instead of reading hardware directly.
> >
> > RFC -> v1:
> > - Rebase to 6.13-rc3
> > - Add support for 1 event counter in addition to CPU cycle counter
> > - Don't sneak past the PMU event filter (Marc)
> > - Have the PMU driver provide a PMUv3 -> HW event ID mapping (Marc)
> >
> > Tested on my M2 with Linux and Windows guests. If possible, I'd
> > appreciate someone testing on an M1 as I haven't added those MIDRs to
> > the erratum yet.
>
> Tested on M1 (t8103) with perf in a Linux guest and the patch below
>
> Tested-by: Janne Grunau <j@jannau.net>
>
> I'll import this into the downstream asahi kernel as there was a request
> for performance counters to aid FEX-Emu development recently.
>
> Janne
Awesome, greatly appreciate the testing Janne. Hopefully we can get this
worked out for upstream too :)
--
Thanks,
Oliver
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 00/18] KVM: arm64: Support FEAT_PMUv3 on Apple hardware
2024-12-17 21:20 [PATCH 00/18] KVM: arm64: Support FEAT_PMUv3 on Apple hardware Oliver Upton
` (18 preceding siblings ...)
2024-12-21 13:45 ` [PATCH 00/18] KVM: arm64: Support FEAT_PMUv3 on Apple hardware Janne Grunau
@ 2025-01-08 12:38 ` Will Deacon
2025-01-08 20:14 ` Oliver Upton
2025-01-10 16:22 ` [PATCH 00/18] KVM: arm64: Support FEAT_PMUv3 on Apple hardware Will Deacon
20 siblings, 1 reply; 27+ messages in thread
From: Will Deacon @ 2025-01-08 12:38 UTC (permalink / raw)
To: Oliver Upton
Cc: kvmarm, Marc Zyngier, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
Mingwei Zhang, Colton Lewis, Raghavendra Rao Ananta,
Catalin Marinas, Mark Rutland, linux-arm-kernel, linux-kernel
Hi Oliver,
On Tue, Dec 17, 2024 at 01:20:30PM -0800, Oliver Upton wrote:
> One of the interesting features of some Apple M* parts is an IMPDEF trap
> that routes EL1/EL0 accesses of the PMUv3 registers to EL2. This allows
> a hypervisor to emulate an architectural PMUv3 on top of the IMPDEF PMU
> hardware present in the CPU.
>
> And if you squint, this _might_ look like a CPU erratum :-)
>
> This series takes advantage of these IMPDEF traps to provide PMUv3 to
> KVM guests. As a starting point, only expose the fixed CPU cycle counter
> and no event counters. Conveniently, this is enough to get Windows
> running as a KVM guest on Apple hardware.
>
> I've tried to keep the deviation to a minimum by refactoring some of the
> flows used for PMUv3, e.g. computing PMCEID from the arm_pmu bitmap
> instead of reading hardware directly.
What's your plan for this series? I started looking at it and I can take
the first four apple_m1 patches if you like?
Will
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 00/18] KVM: arm64: Support FEAT_PMUv3 on Apple hardware
2025-01-08 12:38 ` Will Deacon
@ 2025-01-08 20:14 ` Oliver Upton
2025-01-08 21:26 ` Marc Zyngier
0 siblings, 1 reply; 27+ messages in thread
From: Oliver Upton @ 2025-01-08 20:14 UTC (permalink / raw)
To: Will Deacon
Cc: kvmarm, Marc Zyngier, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
Mingwei Zhang, Colton Lewis, Raghavendra Rao Ananta,
Catalin Marinas, Mark Rutland, linux-arm-kernel, linux-kernel
Hey Will,
On Wed, Jan 08, 2025 at 12:38:41PM +0000, Will Deacon wrote:
> What's your plan for this series? I started looking at it and I can take
> the first four apple_m1 patches if you like?
I plan on posting a respin of it by next week, which should look pretty
much the same besides cleaning up the build error I introduced :)
Besides that, I think we need to decide on the KVM side of things
whether or not we want to support an event counter in addition to the
PMU cycle counter. Janne's FEX use case would certainly benefit from it.
Do you think you could grab patch #3? It is entirely unrelated to the
series at this point with the PMUv3 event remapping helper.
--
Thanks,
Oliver
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 00/18] KVM: arm64: Support FEAT_PMUv3 on Apple hardware
2025-01-08 20:14 ` Oliver Upton
@ 2025-01-08 21:26 ` Marc Zyngier
2025-01-08 23:06 ` [PATCH 00/18] KVM: arm64: Support FEAT_PMUv3 on Apple hardware\ Oliver Upton
0 siblings, 1 reply; 27+ messages in thread
From: Marc Zyngier @ 2025-01-08 21:26 UTC (permalink / raw)
To: Oliver Upton
Cc: Will Deacon, kvmarm, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
Mingwei Zhang, Colton Lewis, Raghavendra Rao Ananta,
Catalin Marinas, Mark Rutland, linux-arm-kernel, linux-kernel
On Wed, 08 Jan 2025 20:14:07 +0000,
Oliver Upton <oliver.upton@linux.dev> wrote:
>
> Hey Will,
>
> On Wed, Jan 08, 2025 at 12:38:41PM +0000, Will Deacon wrote:
> > What's your plan for this series? I started looking at it and I can take
> > the first four apple_m1 patches if you like?
>
> I plan on posting a respin of it by next week, which should look pretty
> much the same besides cleaning up the build error I introduced :)
>
> Besides that, I think we need to decide on the KVM side of things
> whether or not we want to support an event counter in addition to the
> PMU cycle counter. Janne's FEX use case would certainly benefit from it.
I think we should always be able to support *one* counter on top of
the cycle counter. Doing more than that would result in inconsistent
behaviours (some events only count on a single counter).
Unless we restrict ourselves to a very small set of events that we can
always schedule on any counter, but this doesn't sound very promising.
Thoughts?
M.
--
Without deviation from the norm, progress is not possible.
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 00/18] KVM: arm64: Support FEAT_PMUv3 on Apple hardware\
2025-01-08 21:26 ` Marc Zyngier
@ 2025-01-08 23:06 ` Oliver Upton
0 siblings, 0 replies; 27+ messages in thread
From: Oliver Upton @ 2025-01-08 23:06 UTC (permalink / raw)
To: Marc Zyngier
Cc: Will Deacon, kvmarm, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
Mingwei Zhang, Colton Lewis, Raghavendra Rao Ananta,
Catalin Marinas, Mark Rutland, linux-arm-kernel, linux-kernel
On Wed, Jan 08, 2025 at 09:26:54PM +0000, Marc Zyngier wrote:
> On Wed, 08 Jan 2025 20:14:07 +0000,
> Oliver Upton <oliver.upton@linux.dev> wrote:
> >
> > Hey Will,
> >
> > On Wed, Jan 08, 2025 at 12:38:41PM +0000, Will Deacon wrote:
> > > What's your plan for this series? I started looking at it and I can take
> > > the first four apple_m1 patches if you like?
> >
> > I plan on posting a respin of it by next week, which should look pretty
> > much the same besides cleaning up the build error I introduced :)
> >
> > Besides that, I think we need to decide on the KVM side of things
> > whether or not we want to support an event counter in addition to the
> > PMU cycle counter. Janne's FEX use case would certainly benefit from it.
>
> I think we should always be able to support *one* counter on top of
> the cycle counter. Doing more than that would result in inconsistent
> behaviours (some events only count on a single counter).
>
> Unless we restrict ourselves to a very small set of events that we can
> always schedule on any counter, but this doesn't sound very promising.
I definitely agree that a single event counter is the way to go. Dealing
with this IMPDEF crud is gross already, and coping with event affinities
would only make it worse.
I was more wanting to test the idea that we want programmable event
counters at all, although it isn't that much of a burden on top of the
cycle counter.
I'll un-RFC the tail of the series in v2 then.
--
Thanks,
Oliver
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 00/18] KVM: arm64: Support FEAT_PMUv3 on Apple hardware
2024-12-17 21:20 [PATCH 00/18] KVM: arm64: Support FEAT_PMUv3 on Apple hardware Oliver Upton
` (19 preceding siblings ...)
2025-01-08 12:38 ` Will Deacon
@ 2025-01-10 16:22 ` Will Deacon
20 siblings, 0 replies; 27+ messages in thread
From: Will Deacon @ 2025-01-10 16:22 UTC (permalink / raw)
To: kvmarm, Oliver Upton
Cc: catalin.marinas, kernel-team, Will Deacon, Marc Zyngier,
Joey Gouly, Suzuki K Poulose, Zenghui Yu, Mingwei Zhang,
Colton Lewis, Raghavendra Rao Ananta, Mark Rutland,
linux-arm-kernel, linux-kernel
On Tue, 17 Dec 2024 13:20:30 -0800, Oliver Upton wrote:
> One of the interesting features of some Apple M* parts is an IMPDEF trap
> that routes EL1/EL0 accesses of the PMUv3 registers to EL2. This allows
> a hypervisor to emulate an architectural PMUv3 on top of the IMPDEF PMU
> hardware present in the CPU.
>
> And if you squint, this _might_ look like a CPU erratum :-)
>
> [...]
Applied the branch events patch to will (for-next/perf), thanks!
[03/18] drivers/perf: apple_m1: Map generic branch events
https://git.kernel.org/will/c/4575353d82e2
Cheers,
--
Will
https://fixes.arm64.dev
https://next.arm64.dev
https://will.arm64.dev
^ permalink raw reply [flat|nested] 27+ messages in thread
end of thread, other threads:[~2025-01-10 16:23 UTC | newest]
Thread overview: 27+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-12-17 21:20 [PATCH 00/18] KVM: arm64: Support FEAT_PMUv3 on Apple hardware Oliver Upton
2024-12-17 21:20 ` [PATCH 01/18] drivers/perf: apple_m1: Refactor event select/filter configuration Oliver Upton
2024-12-17 21:20 ` [PATCH 02/18] drivers/perf: apple_m1: Support host/guest event filtering Oliver Upton
2024-12-17 21:20 ` [PATCH 03/18] drivers/perf: apple_m1: Map generic branch events Oliver Upton
2024-12-17 21:20 ` [PATCH 04/18] drivers/perf: apple_m1: Provide helper for mapping PMUv3 events Oliver Upton
2024-12-17 21:20 ` [PATCH 05/18] KVM: arm64: Compute PMCEID from arm_pmu's event bitmaps Oliver Upton
2024-12-17 21:20 ` [PATCH 06/18] KVM: arm64: Always support SW_INCR PMU event Oliver Upton
2024-12-17 21:20 ` [PATCH 07/18] KVM: arm64: Remap PMUv3 events onto hardware Oliver Upton
2024-12-17 21:20 ` [PATCH 08/18] KVM: arm64: Use a cpucap to determine if system supports FEAT_PMUv3 Oliver Upton
2024-12-17 21:20 ` [PATCH 09/18] KVM: arm64: Drop kvm_arm_pmu_available static key Oliver Upton
2024-12-18 23:23 ` kernel test robot
2024-12-17 21:20 ` [PATCH 10/18] KVM: arm64: Use guard() to cleanup usage of arm_pmus_lock Oliver Upton
2024-12-17 21:20 ` [PATCH 11/18] KVM: arm64: Move PMUVer filtering into KVM code Oliver Upton
2024-12-17 21:20 ` [PATCH 12/18] KVM: arm64: Compute synthetic sysreg ESR for Apple PMUv3 traps Oliver Upton
2024-12-17 21:20 ` [PATCH 13/18] KVM: arm64: Advertise PMUv3 if IMPDEF traps are present Oliver Upton
2024-12-17 21:22 ` [PATCH 14/18] KVM: arm64: Advertise 0 event counters for IMPDEF PMU Oliver Upton
2024-12-17 21:22 ` [PATCH 15/18] arm64: Enable IMP DEF PMUv3 traps on Apple M2 Oliver Upton
2024-12-17 21:23 ` [RFC PATCH 16/18] drivers/perf: apple_m1: Map a few more PMUv3 events Oliver Upton
2024-12-17 21:23 ` [RFC PATCH 17/18] KVM: arm64: Provide 1 event counter on IMPDEF hardware Oliver Upton
2024-12-17 21:23 ` [HACK PATCH 18/18] KVM: arm64: selftests: Add test for probing PMUv3 sysregs Oliver Upton
2024-12-21 13:45 ` [PATCH 00/18] KVM: arm64: Support FEAT_PMUv3 on Apple hardware Janne Grunau
2024-12-21 22:00 ` Oliver Upton
2025-01-08 12:38 ` Will Deacon
2025-01-08 20:14 ` Oliver Upton
2025-01-08 21:26 ` Marc Zyngier
2025-01-08 23:06 ` [PATCH 00/18] KVM: arm64: Support FEAT_PMUv3 on Apple hardware\ Oliver Upton
2025-01-10 16:22 ` [PATCH 00/18] KVM: arm64: Support FEAT_PMUv3 on Apple hardware Will Deacon
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).