diff options
| -rw-r--r-- | arch/arm64/include/asm/kvm_host.h | 17 | ||||
| -rw-r--r-- | arch/arm64/kvm/Makefile | 2 | ||||
| -rw-r--r-- | arch/arm64/kvm/pmu.c | 45 |
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 | ||
| 236 | struct kvm_pmu_events { | ||
| 237 | u32 events_host; | ||
| 238 | u32 events_guest; | ||
| 239 | }; | ||
| 240 | |||
| 236 | struct kvm_host_data { | 241 | struct 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 | ||
| 240 | typedef struct kvm_host_data kvm_host_data_t; | 246 | typedef struct kvm_host_data kvm_host_data_t; |
| @@ -572,11 +578,22 @@ void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu); | |||
| 572 | void kvm_arch_vcpu_ctxsync_fp(struct kvm_vcpu *vcpu); | 578 | void kvm_arch_vcpu_ctxsync_fp(struct kvm_vcpu *vcpu); |
| 573 | void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu); | 579 | void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu); |
| 574 | 580 | ||
| 581 | static 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 */ |
| 576 | static inline int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu) | 587 | static 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 | |||
| 592 | void kvm_set_pmu_events(u32 set, struct perf_event_attr *attr); | ||
| 593 | void kvm_clr_pmu_events(u32 clr); | ||
| 594 | #else | ||
| 595 | static inline void kvm_set_pmu_events(u32 set, struct perf_event_attr *attr) {} | ||
| 596 | static inline void kvm_clr_pmu_events(u32 clr) {} | ||
| 580 | #endif | 597 | #endif |
| 581 | 598 | ||
| 582 | static inline void kvm_arm_vhe_guest_enter(void) | 599 | static 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 | |||
| 17 | kvm-$(CONFIG_KVM_ARM_HOST) += inject_fault.o regmap.o va_layout.o | 17 | kvm-$(CONFIG_KVM_ARM_HOST) += inject_fault.o regmap.o va_layout.o |
| 18 | kvm-$(CONFIG_KVM_ARM_HOST) += hyp.o hyp-init.o handle_exit.o | 18 | kvm-$(CONFIG_KVM_ARM_HOST) += hyp.o hyp-init.o handle_exit.o |
| 19 | kvm-$(CONFIG_KVM_ARM_HOST) += guest.o debug.o reset.o sys_regs.o sys_regs_generic_v8.o | 19 | kvm-$(CONFIG_KVM_ARM_HOST) += guest.o debug.o reset.o sys_regs.o sys_regs_generic_v8.o |
| 20 | kvm-$(CONFIG_KVM_ARM_HOST) += vgic-sys-reg-v3.o fpsimd.o | 20 | kvm-$(CONFIG_KVM_ARM_HOST) += vgic-sys-reg-v3.o fpsimd.o pmu.o |
| 21 | kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/aarch32.o | 21 | kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/aarch32.o |
| 22 | 22 | ||
| 23 | kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic.o | 23 | kvm-$(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 | */ | ||
| 13 | static 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 | */ | ||
| 23 | void 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 | */ | ||
| 39 | void 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 | } | ||
