aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm64/include/asm/kvm_host.h17
-rw-r--r--arch/arm64/kvm/Makefile2
-rw-r--r--arch/arm64/kvm/pmu.c45
3 files changed, 63 insertions, 1 deletions
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 9ba59832b71a..655ad08edc3a 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -233,8 +233,14 @@ struct kvm_cpu_context {
233 struct kvm_vcpu *__hyp_running_vcpu; 233 struct kvm_vcpu *__hyp_running_vcpu;
234}; 234};
235 235
236struct kvm_pmu_events {
237 u32 events_host;
238 u32 events_guest;
239};
240
236struct kvm_host_data { 241struct kvm_host_data {
237 struct kvm_cpu_context host_ctxt; 242 struct kvm_cpu_context host_ctxt;
243 struct kvm_pmu_events pmu_events;
238}; 244};
239 245
240typedef struct kvm_host_data kvm_host_data_t; 246typedef struct kvm_host_data kvm_host_data_t;
@@ -572,11 +578,22 @@ void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu);
572void kvm_arch_vcpu_ctxsync_fp(struct kvm_vcpu *vcpu); 578void kvm_arch_vcpu_ctxsync_fp(struct kvm_vcpu *vcpu);
573void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu); 579void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu);
574 580
581static inline bool kvm_pmu_counter_deferred(struct perf_event_attr *attr)
582{
583 return attr->exclude_host;
584}
585
575#ifdef CONFIG_KVM /* Avoid conflicts with core headers if CONFIG_KVM=n */ 586#ifdef CONFIG_KVM /* Avoid conflicts with core headers if CONFIG_KVM=n */
576static inline int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu) 587static inline int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu)
577{ 588{
578 return kvm_arch_vcpu_run_map_fp(vcpu); 589 return kvm_arch_vcpu_run_map_fp(vcpu);
579} 590}
591
592void kvm_set_pmu_events(u32 set, struct perf_event_attr *attr);
593void kvm_clr_pmu_events(u32 clr);
594#else
595static inline void kvm_set_pmu_events(u32 set, struct perf_event_attr *attr) {}
596static inline void kvm_clr_pmu_events(u32 clr) {}
580#endif 597#endif
581 598
582static inline void kvm_arm_vhe_guest_enter(void) 599static inline void kvm_arm_vhe_guest_enter(void)
diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile
index 690e033a91c0..3ac1a64d2fb9 100644
--- a/arch/arm64/kvm/Makefile
+++ b/arch/arm64/kvm/Makefile
@@ -17,7 +17,7 @@ kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/psci.o $(KVM)/arm/perf.o
17kvm-$(CONFIG_KVM_ARM_HOST) += inject_fault.o regmap.o va_layout.o 17kvm-$(CONFIG_KVM_ARM_HOST) += inject_fault.o regmap.o va_layout.o
18kvm-$(CONFIG_KVM_ARM_HOST) += hyp.o hyp-init.o handle_exit.o 18kvm-$(CONFIG_KVM_ARM_HOST) += hyp.o hyp-init.o handle_exit.o
19kvm-$(CONFIG_KVM_ARM_HOST) += guest.o debug.o reset.o sys_regs.o sys_regs_generic_v8.o 19kvm-$(CONFIG_KVM_ARM_HOST) += guest.o debug.o reset.o sys_regs.o sys_regs_generic_v8.o
20kvm-$(CONFIG_KVM_ARM_HOST) += vgic-sys-reg-v3.o fpsimd.o 20kvm-$(CONFIG_KVM_ARM_HOST) += vgic-sys-reg-v3.o fpsimd.o pmu.o
21kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/aarch32.o 21kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/aarch32.o
22 22
23kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic.o 23kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic.o
diff --git a/arch/arm64/kvm/pmu.c b/arch/arm64/kvm/pmu.c
new file mode 100644
index 000000000000..5414b134f99a
--- /dev/null
+++ b/arch/arm64/kvm/pmu.c
@@ -0,0 +1,45 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright 2019 Arm Limited
4 * Author: Andrew Murray <Andrew.Murray@arm.com>
5 */
6#include <linux/kvm_host.h>
7#include <linux/perf_event.h>
8
9/*
10 * Given the exclude_{host,guest} attributes, determine if we are going
11 * to need to switch counters at guest entry/exit.
12 */
13static bool kvm_pmu_switch_needed(struct perf_event_attr *attr)
14{
15 /* Only switch if attributes are different */
16 return (attr->exclude_host != attr->exclude_guest);
17}
18
19/*
20 * Add events to track that we may want to switch at guest entry/exit
21 * time.
22 */
23void kvm_set_pmu_events(u32 set, struct perf_event_attr *attr)
24{
25 struct kvm_host_data *ctx = this_cpu_ptr(&kvm_host_data);
26
27 if (!kvm_pmu_switch_needed(attr))
28 return;
29
30 if (!attr->exclude_host)
31 ctx->pmu_events.events_host |= set;
32 if (!attr->exclude_guest)
33 ctx->pmu_events.events_guest |= set;
34}
35
36/*
37 * Stop tracking events
38 */
39void kvm_clr_pmu_events(u32 clr)
40{
41 struct kvm_host_data *ctx = this_cpu_ptr(&kvm_host_data);
42
43 ctx->pmu_events.events_host &= ~clr;
44 ctx->pmu_events.events_guest &= ~clr;
45}