Skip to content

Commit

Permalink
arm64: KVM: Add accessors to track guest/host only counters
Browse files Browse the repository at this point in the history
In order to effeciently switch events_{guest,host} perf counters at
guest entry/exit we add bitfields to kvm_cpu_context for guest and host
events as well as accessors for updating them.

A function is also provided which allows the PMU driver to determine
if a counter should start counting when it is enabled. With exclude_host,
we may only start counting when entering the guest.

Signed-off-by: Andrew Murray <[email protected]>
Signed-off-by: Marc Zyngier <[email protected]>
  • Loading branch information
Andrew Murray authored and Marc Zyngier committed Apr 24, 2019
1 parent 630a168 commit eb41238
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 1 deletion.
17 changes: 17 additions & 0 deletions arch/arm64/include/asm/kvm_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -233,8 +233,14 @@ struct kvm_cpu_context {
struct kvm_vcpu *__hyp_running_vcpu;
};

struct kvm_pmu_events {
u32 events_host;
u32 events_guest;
};

struct kvm_host_data {
struct kvm_cpu_context host_ctxt;
struct kvm_pmu_events pmu_events;
};

typedef struct kvm_host_data kvm_host_data_t;
Expand Down Expand Up @@ -572,11 +578,22 @@ void kvm_arch_vcpu_load_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 attr->exclude_host;
}

#ifdef CONFIG_KVM /* Avoid conflicts with core headers if CONFIG_KVM=n */
static inline int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu)
{
return kvm_arch_vcpu_run_map_fp(vcpu);
}

void kvm_set_pmu_events(u32 set, struct perf_event_attr *attr);
void kvm_clr_pmu_events(u32 clr);
#else
static inline void kvm_set_pmu_events(u32 set, struct perf_event_attr *attr) {}
static inline void kvm_clr_pmu_events(u32 clr) {}
#endif

static inline void kvm_arm_vhe_guest_enter(void)
Expand Down
2 changes: 1 addition & 1 deletion arch/arm64/kvm/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/psci.o $(KVM)/arm/perf.o
kvm-$(CONFIG_KVM_ARM_HOST) += inject_fault.o regmap.o va_layout.o
kvm-$(CONFIG_KVM_ARM_HOST) += hyp.o hyp-init.o handle_exit.o
kvm-$(CONFIG_KVM_ARM_HOST) += guest.o debug.o reset.o sys_regs.o sys_regs_generic_v8.o
kvm-$(CONFIG_KVM_ARM_HOST) += vgic-sys-reg-v3.o fpsimd.o
kvm-$(CONFIG_KVM_ARM_HOST) += vgic-sys-reg-v3.o fpsimd.o pmu.o
kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/aarch32.o

kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic.o
Expand Down
45 changes: 45 additions & 0 deletions arch/arm64/kvm/pmu.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright 2019 Arm Limited
* Author: Andrew Murray <[email protected]>
*/
#include <linux/kvm_host.h>
#include <linux/perf_event.h>

/*
* Given the exclude_{host,guest} attributes, determine if we are going
* to need to switch counters at guest entry/exit.
*/
static bool kvm_pmu_switch_needed(struct perf_event_attr *attr)
{
/* Only switch if attributes are different */
return (attr->exclude_host != attr->exclude_guest);
}

/*
* Add events to track that we may want to switch at guest entry/exit
* time.
*/
void kvm_set_pmu_events(u32 set, struct perf_event_attr *attr)
{
struct kvm_host_data *ctx = this_cpu_ptr(&kvm_host_data);

if (!kvm_pmu_switch_needed(attr))
return;

if (!attr->exclude_host)
ctx->pmu_events.events_host |= set;
if (!attr->exclude_guest)
ctx->pmu_events.events_guest |= set;
}

/*
* Stop tracking events
*/
void kvm_clr_pmu_events(u32 clr)
{
struct kvm_host_data *ctx = this_cpu_ptr(&kvm_host_data);

ctx->pmu_events.events_host &= ~clr;
ctx->pmu_events.events_guest &= ~clr;
}

0 comments on commit eb41238

Please sign in to comment.