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

Mark Rutland
2025-07-07T16:13:17Z

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.

>
> * 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.

> 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
>