Re: [PATCH v3 04/22] KVM: arm64: Cleanup PMU includes

Colton Lewis
2025-07-08T22:38:00Z

Mark Rutland <mark.rutland@arm.com> writes:

> On Thu, Jun 26, 2025 at 08:04:40PM +0000, Colton Lewis wrote:
>> From: Marc Zyngier <maz@kernel.org>

>> Reorganize these tangled headers.

> In prior versions of this series, there was some earlier text explaining
> that
> there was a circular header dependency. In v2:

>
> https://lore.kernel.org/linux-arm-kernel/20250620221326.1261128-6-coltonlewis@google.com/

> ... it said:

> | asm/kvm_host.h includes asm/arm_pmu.h which includes perf/arm_pmuv3.h
> | which includes asm/arm_pmuv3.h which includes asm/kvm_host.h This
> | causes compilation problems why trying to use anything defined in any
> | of the headers in any other headers.

> Was there some reason for dropping that? It's a bit odd to start without a
> problem statement.

When I rebased on top of kvm/queue, that included a patch from Sean that
changed the the problem. I thought I wrote a new description but I guess
not. I'll include in my next reroll.

The core issue is still that including *all* of kvm_host.h in
arm_pmuv3.h is a circular dependency.

asm/kvm_host.h includes asm/kvm_pmu.h includes perf/arm_pmuv3.h includes
asm/arm_pmuv3.h includes asm/kvm_host.h

Some other things in this patch are vestigial or needed later, so I
should put them in the patches where they are used.

>> * Respect the move defining the interface between KVM and PMU in its
>> own header asm/kvm_pmu.h

>> * Define an empty struct arm_pmu so it is defined for those interface
>> functions when compiling with CONFIG_KVM but not CONFIG_ARM_PMU

> Which functions in particular are those? What prevents them from
> depending on
> CONFIG_ARM_PMU?

> Mark.

Functions I introduce later. So this hunk should be in a later patch if
I need to keep it.

bool kvm_pmu_is_partitioned(struct arm_pmu *pmu);
u64 kvm_pmu_host_counter_mask(struct arm_pmu *pmu);
u64 kvm_pmu_guest_counter_mask(struct arm_pmu *pmu);

The first, at least, has to be called in non-PMU KVM code to check if we
can use my ioctl later.

I suppose in that case it's only calling a dummy definition that returns
false, so I don't need struct arm_pmu * in the argument and can just use
void *

>> Signed-off-by: Marc Zyngier <maz@kernel.org>
>> Signed-off-by: Colton Lewis <coltonlewis@google.com>
>> ---
>> arch/arm64/include/asm/arm_pmuv3.h | 2 +-
>> arch/arm64/include/asm/kvm_host.h | 15 +--------------
>> arch/arm64/include/asm/kvm_pmu.h | 15 +++++++++++++++
>> arch/arm64/kvm/debug.c | 1 +
>> arch/arm64/kvm/hyp/include/hyp/switch.h | 1 +
>> arch/arm64/kvm/pmu.c | 2 ++
>> arch/arm64/kvm/sys_regs.c | 1 +
>> include/linux/perf/arm_pmu.h | 5 +++++
>> virt/kvm/kvm_main.c | 1 +
>> 9 files changed, 28 insertions(+), 15 deletions(-)

>> diff --git a/arch/arm64/include/asm/arm_pmuv3.h
>> b/arch/arm64/include/asm/arm_pmuv3.h
>> index 8a777dec8d88..32c003a7b810 100644
>> --- a/arch/arm64/include/asm/arm_pmuv3.h
>> +++ b/arch/arm64/include/asm/arm_pmuv3.h
>> @@ -6,7 +6,7 @@
>> #ifndef __ASM_PMUV3_H
>> #define __ASM_PMUV3_H

>> -#include <asm/kvm_host.h>
>> +#include <asm/kvm_pmu.h>

>> #include <asm/cpufeature.h>
>> #include <asm/sysreg.h>
>> diff --git a/arch/arm64/include/asm/kvm_host.h
>> b/arch/arm64/include/asm/kvm_host.h
>> index 27ed26bd4381..2df76689381a 100644
>> --- a/arch/arm64/include/asm/kvm_host.h
>> +++ b/arch/arm64/include/asm/kvm_host.h
>> @@ -14,6 +14,7 @@
>> #include <linux/arm-smccc.h>
>> #include <linux/bitmap.h>
>> #include <linux/types.h>
>> +#include <linux/irq_work.h>
>> #include <linux/jump_label.h>
>> #include <linux/kvm_types.h>
>> #include <linux/maple_tree.h>
>> @@ -1487,25 +1488,11 @@ void kvm_arch_vcpu_ctxflush_fp(struct kvm_vcpu
>> *vcpu);
>> void kvm_arch_vcpu_ctxsync_fp(struct kvm_vcpu *vcpu);
>> void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu);

>> -static inline bool kvm_pmu_counter_deferred(struct perf_event_attr
>> *attr)
>> -{
>> - return (!has_vhe() && attr->exclude_host);
>> -}
>> -
>> #ifdef CONFIG_KVM
>> -void kvm_set_pmu_events(u64 set, struct perf_event_attr *attr);
>> -void kvm_clr_pmu_events(u64 clr);
>> -bool kvm_set_pmuserenr(u64 val);
>> void kvm_enable_trbe(void);
>> void kvm_disable_trbe(void);
>> void kvm_tracing_set_el1_configuration(u64 trfcr_while_in_guest);
>> #else
>> -static inline void kvm_set_pmu_events(u64 set, struct perf_event_attr
>> *attr) {}
>> -static inline void kvm_clr_pmu_events(u64 clr) {}
>> -static inline bool kvm_set_pmuserenr(u64 val)
>> -{
>> - return false;
>> -}
>> static inline void kvm_enable_trbe(void) {}
>> static inline void kvm_disable_trbe(void) {}
>> static inline void kvm_tracing_set_el1_configuration(u64
>> trfcr_while_in_guest) {}
>> diff --git a/arch/arm64/include/asm/kvm_pmu.h
>> b/arch/arm64/include/asm/kvm_pmu.h
>> index baf028d19dfc..ad3247b46838 100644
>> --- a/arch/arm64/include/asm/kvm_pmu.h
>> +++ b/arch/arm64/include/asm/kvm_pmu.h
>> @@ -11,9 +11,15 @@
>> #include <linux/kvm_types.h>
>> #include <linux/perf_event.h>
>> #include <linux/perf/arm_pmuv3.h>
>> +#include <linux/perf/arm_pmu.h>

>> #define KVM_ARMV8_PMU_MAX_COUNTERS 32

>> +#define kvm_pmu_counter_deferred(attr) \
>> + ({ \
>> + !has_vhe() && (attr)->exclude_host; \
>> + })
>> +
>> #if IS_ENABLED(CONFIG_HW_PERF_EVENTS) && IS_ENABLED(CONFIG_KVM)
>> struct kvm_pmc {
>> u8 idx; /* index into the pmu->pmc array */
>> @@ -68,6 +74,9 @@ int kvm_arm_pmu_v3_has_attr(struct kvm_vcpu *vcpu,
>> int kvm_arm_pmu_v3_enable(struct kvm_vcpu *vcpu);

>> struct kvm_pmu_events *kvm_get_pmu_events(void);
>> +void kvm_set_pmu_events(u64 set, struct perf_event_attr *attr);
>> +void kvm_clr_pmu_events(u64 clr);
>> +bool kvm_set_pmuserenr(u64 val);
>> void kvm_vcpu_pmu_restore_guest(struct kvm_vcpu *vcpu);
>> void kvm_vcpu_pmu_restore_host(struct kvm_vcpu *vcpu);
>> void kvm_vcpu_pmu_resync_el0(void);
>> @@ -161,6 +170,12 @@ static inline u64 kvm_pmu_get_pmceid(struct
>> kvm_vcpu *vcpu, bool pmceid1)

>> #define kvm_vcpu_has_pmu(vcpu) ({ false; })
>> static inline void kvm_pmu_update_vcpu_events(struct kvm_vcpu *vcpu) {}
>> +static inline void kvm_set_pmu_events(u64 set, struct perf_event_attr
>> *attr) {}
>> +static inline void kvm_clr_pmu_events(u64 clr) {}
>> +static inline bool kvm_set_pmuserenr(u64 val)
>> +{
>> + return false;
>> +}
>> static inline void kvm_vcpu_pmu_restore_guest(struct kvm_vcpu *vcpu) {}
>> static inline void kvm_vcpu_pmu_restore_host(struct kvm_vcpu *vcpu) {}
>> static inline void kvm_vcpu_reload_pmu(struct kvm_vcpu *vcpu) {}
>> diff --git a/arch/arm64/kvm/debug.c b/arch/arm64/kvm/debug.c
>> index 1a7dab333f55..a554c3e368dc 100644
>> --- a/arch/arm64/kvm/debug.c
>> +++ b/arch/arm64/kvm/debug.c
>> @@ -9,6 +9,7 @@

>> #include <linux/kvm_host.h>
>> #include <linux/hw_breakpoint.h>
>> +#include <linux/perf/arm_pmuv3.h>

>> #include <asm/debug-monitors.h>
>> #include <asm/kvm_asm.h>
>> diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h
>> b/arch/arm64/kvm/hyp/include/hyp/switch.h
>> index 7599844908c0..825b81749972 100644
>> --- a/arch/arm64/kvm/hyp/include/hyp/switch.h
>> +++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
>> @@ -14,6 +14,7 @@
>> #include <linux/kvm_host.h>
>> #include <linux/types.h>
>> #include <linux/jump_label.h>
>> +#include <linux/perf/arm_pmuv3.h>
>> #include <uapi/linux/psci.h>

>> #include <asm/barrier.h>
>> diff --git a/arch/arm64/kvm/pmu.c b/arch/arm64/kvm/pmu.c
>> index 6b48a3d16d0d..8bfc6b0a85f6 100644
>> --- a/arch/arm64/kvm/pmu.c
>> +++ b/arch/arm64/kvm/pmu.c
>> @@ -8,6 +8,8 @@
>> #include <linux/perf/arm_pmu.h>
>> #include <linux/perf/arm_pmuv3.h>

>> +#include <asm/kvm_pmu.h>
>> +
>> static DEFINE_PER_CPU(struct kvm_pmu_events, kvm_pmu_events);

>> /*
>> diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
>> index 99fdbe174202..eaff6d63ef77 100644
>> --- a/arch/arm64/kvm/sys_regs.c
>> +++ b/arch/arm64/kvm/sys_regs.c
>> @@ -18,6 +18,7 @@
>> #include <linux/printk.h>
>> #include <linux/uaccess.h>
>> #include <linux/irqchip/arm-gic-v3.h>
>> +#include <linux/perf/arm_pmuv3.h>

>> #include <asm/arm_pmuv3.h>
>> #include <asm/cacheflush.h>
>> diff --git a/include/linux/perf/arm_pmu.h b/include/linux/perf/arm_pmu.h
>> index 6dc5e0cd76ca..fb382bcd4f4b 100644
>> --- a/include/linux/perf/arm_pmu.h
>> +++ b/include/linux/perf/arm_pmu.h
>> @@ -187,6 +187,11 @@ void armpmu_free_irq(int irq, int cpu);

>> #define ARMV8_PMU_PDEV_NAME "armv8-pmu"

>> +#else
>> +
>> +struct arm_pmu {
>> +};
>> +
>> #endif /* CONFIG_ARM_PMU */

>> #define ARMV8_SPE_PDEV_NAME "arm,spe-v1"
>> diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
>> index e2f6344256ce..25259fcf3115 100644
>> --- a/virt/kvm/kvm_main.c
>> +++ b/virt/kvm/kvm_main.c
>> @@ -48,6 +48,7 @@
>> #include <linux/lockdep.h>
>> #include <linux/kthread.h>
>> #include <linux/suspend.h>
>> +#include <linux/perf_event.h>

>> #include <asm/processor.h>
>> #include <asm/ioctl.h>
>> --
>> 2.50.0.727.gbf7dc18ff4-goog