Skip to content

Commit e840f42

Browse files
author
Marc Zyngier
committed
KVM: arm64: Fix PMU probe ordering
Russell reported that since 5.13, KVM's probing of the PMU has started to fail on his HW. As it turns out, there is an implicit ordering dependency between the architectural PMU probing code and and KVM's own probing. If, due to probe ordering reasons, KVM probes before the PMU driver, it will fail to detect the PMU and prevent it from being advertised to guests as well as the VMM. Obviously, this is one probing too many, and we should be able to deal with any ordering. Add a callback from the PMU code into KVM to advertise the registration of a host CPU PMU, allowing for any probing order. Fixes: 5421db1 ("KVM: arm64: Divorce the perf code from oprofile helpers") Reported-by: "Russell King (Oracle)" <[email protected]> Tested-by: Russell King (Oracle) <[email protected]> Signed-off-by: Marc Zyngier <[email protected]> Link: https://lore.kernel.org/r/[email protected] Cc: [email protected]
1 parent a49b50a commit e840f42

File tree

5 files changed

+16
-7
lines changed

5 files changed

+16
-7
lines changed

arch/arm64/kvm/perf.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,6 @@ static struct perf_guest_info_callbacks kvm_guest_cbs = {
5050

5151
int kvm_perf_init(void)
5252
{
53-
if (kvm_pmu_probe_pmuver() != ID_AA64DFR0_PMUVER_IMP_DEF && !is_protected_kvm_enabled())
54-
static_branch_enable(&kvm_arm_pmu_available);
55-
5653
return perf_register_guest_info_callbacks(&kvm_guest_cbs);
5754
}
5855

arch/arm64/kvm/pmu-emul.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -740,7 +740,14 @@ void kvm_pmu_set_counter_event_type(struct kvm_vcpu *vcpu, u64 data,
740740
kvm_pmu_create_perf_event(vcpu, select_idx);
741741
}
742742

743-
int kvm_pmu_probe_pmuver(void)
743+
void kvm_host_pmu_init(struct arm_pmu *pmu)
744+
{
745+
if (pmu->pmuver != 0 && pmu->pmuver != ID_AA64DFR0_PMUVER_IMP_DEF &&
746+
!kvm_arm_support_pmu_v3() && !is_protected_kvm_enabled())
747+
static_branch_enable(&kvm_arm_pmu_available);
748+
}
749+
750+
static int kvm_pmu_probe_pmuver(void)
744751
{
745752
struct perf_event_attr attr = { };
746753
struct perf_event *event;

drivers/perf/arm_pmu.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -952,6 +952,8 @@ int armpmu_register(struct arm_pmu *pmu)
952952
pmu->name, pmu->num_events,
953953
has_nmi ? ", using NMIs" : "");
954954

955+
kvm_host_pmu_init(pmu);
956+
955957
return 0;
956958

957959
out_destroy:

include/kvm/arm_pmu.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@ int kvm_arm_pmu_v3_get_attr(struct kvm_vcpu *vcpu,
6161
int kvm_arm_pmu_v3_has_attr(struct kvm_vcpu *vcpu,
6262
struct kvm_device_attr *attr);
6363
int kvm_arm_pmu_v3_enable(struct kvm_vcpu *vcpu);
64-
int kvm_pmu_probe_pmuver(void);
6564
#else
6665
struct kvm_pmu {
6766
};
@@ -118,8 +117,6 @@ static inline u64 kvm_pmu_get_pmceid(struct kvm_vcpu *vcpu, bool pmceid1)
118117
return 0;
119118
}
120119

121-
static inline int kvm_pmu_probe_pmuver(void) { return 0xf; }
122-
123120
#endif
124121

125122
#endif

include/linux/perf/arm_pmu.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,12 @@ int arm_pmu_acpi_probe(armpmu_init_fn init_fn);
163163
static inline int arm_pmu_acpi_probe(armpmu_init_fn init_fn) { return 0; }
164164
#endif
165165

166+
#ifdef CONFIG_KVM
167+
void kvm_host_pmu_init(struct arm_pmu *pmu);
168+
#else
169+
#define kvm_host_pmu_init(x) do { } while(0)
170+
#endif
171+
166172
/* Internal functions only for core arm_pmu code */
167173
struct arm_pmu *armpmu_alloc(void);
168174
struct arm_pmu *armpmu_alloc_atomic(void);

0 commit comments

Comments
 (0)