diff options
-rw-r--r-- | virt/kvm/arm/pmu.c | 20 |
1 files changed, 20 insertions, 0 deletions
diff --git a/virt/kvm/arm/pmu.c b/virt/kvm/arm/pmu.c index f291d4ac3519..8731dfeced8b 100644 --- a/virt/kvm/arm/pmu.c +++ b/virt/kvm/arm/pmu.c | |||
@@ -8,6 +8,7 @@ | |||
8 | #include <linux/kvm.h> | 8 | #include <linux/kvm.h> |
9 | #include <linux/kvm_host.h> | 9 | #include <linux/kvm_host.h> |
10 | #include <linux/perf_event.h> | 10 | #include <linux/perf_event.h> |
11 | #include <linux/perf/arm_pmu.h> | ||
11 | #include <linux/uaccess.h> | 12 | #include <linux/uaccess.h> |
12 | #include <asm/kvm_emulate.h> | 13 | #include <asm/kvm_emulate.h> |
13 | #include <kvm/arm_pmu.h> | 14 | #include <kvm/arm_pmu.h> |
@@ -442,8 +443,25 @@ static void kvm_pmu_perf_overflow(struct perf_event *perf_event, | |||
442 | struct pt_regs *regs) | 443 | struct pt_regs *regs) |
443 | { | 444 | { |
444 | struct kvm_pmc *pmc = perf_event->overflow_handler_context; | 445 | struct kvm_pmc *pmc = perf_event->overflow_handler_context; |
446 | struct arm_pmu *cpu_pmu = to_arm_pmu(perf_event->pmu); | ||
445 | struct kvm_vcpu *vcpu = kvm_pmc_to_vcpu(pmc); | 447 | struct kvm_vcpu *vcpu = kvm_pmc_to_vcpu(pmc); |
446 | int idx = pmc->idx; | 448 | int idx = pmc->idx; |
449 | u64 period; | ||
450 | |||
451 | cpu_pmu->pmu.stop(perf_event, PERF_EF_UPDATE); | ||
452 | |||
453 | /* | ||
454 | * Reset the sample period to the architectural limit, | ||
455 | * i.e. the point where the counter overflows. | ||
456 | */ | ||
457 | period = -(local64_read(&perf_event->count)); | ||
458 | |||
459 | if (!kvm_pmu_idx_is_64bit(vcpu, pmc->idx)) | ||
460 | period &= GENMASK(31, 0); | ||
461 | |||
462 | local64_set(&perf_event->hw.period_left, 0); | ||
463 | perf_event->attr.sample_period = period; | ||
464 | perf_event->hw.sample_period = period; | ||
447 | 465 | ||
448 | __vcpu_sys_reg(vcpu, PMOVSSET_EL0) |= BIT(idx); | 466 | __vcpu_sys_reg(vcpu, PMOVSSET_EL0) |= BIT(idx); |
449 | 467 | ||
@@ -451,6 +469,8 @@ static void kvm_pmu_perf_overflow(struct perf_event *perf_event, | |||
451 | kvm_make_request(KVM_REQ_IRQ_PENDING, vcpu); | 469 | kvm_make_request(KVM_REQ_IRQ_PENDING, vcpu); |
452 | kvm_vcpu_kick(vcpu); | 470 | kvm_vcpu_kick(vcpu); |
453 | } | 471 | } |
472 | |||
473 | cpu_pmu->pmu.start(perf_event, PERF_EF_RELOAD); | ||
454 | } | 474 | } |
455 | 475 | ||
456 | /** | 476 | /** |