mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-03-22 07:27:12 +08:00
KVM: arm64: Remap PMUv3 events onto hardware
Map PMUv3 event IDs onto hardware, if the driver exposes such a helper. This is expected to be quite rare, and only useful for non-PMUv3 hardware. Tested-by: Janne Grunau <j@jannau.net> Reviewed-by: Marc Zyngier <maz@kernel.org> Link: https://lore.kernel.org/r/20250305202641.428114-12-oliver.upton@linux.dev Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
This commit is contained in:
@@ -677,6 +677,20 @@ static bool kvm_pmc_counts_at_el2(struct kvm_pmc *pmc)
|
||||
return kvm_pmc_read_evtreg(pmc) & ARMV8_PMU_INCLUDE_EL2;
|
||||
}
|
||||
|
||||
static int kvm_map_pmu_event(struct kvm *kvm, unsigned int eventsel)
|
||||
{
|
||||
struct arm_pmu *pmu = kvm->arch.arm_pmu;
|
||||
|
||||
/*
|
||||
* The CPU PMU likely isn't PMUv3; let the driver provide a mapping
|
||||
* for the guest's PMUv3 event ID.
|
||||
*/
|
||||
if (unlikely(pmu->map_pmuv3_event))
|
||||
return pmu->map_pmuv3_event(eventsel);
|
||||
|
||||
return eventsel;
|
||||
}
|
||||
|
||||
/**
|
||||
* kvm_pmu_create_perf_event - create a perf event for a counter
|
||||
* @pmc: Counter context
|
||||
@@ -687,7 +701,8 @@ static void kvm_pmu_create_perf_event(struct kvm_pmc *pmc)
|
||||
struct arm_pmu *arm_pmu = vcpu->kvm->arch.arm_pmu;
|
||||
struct perf_event *event;
|
||||
struct perf_event_attr attr;
|
||||
u64 eventsel, evtreg;
|
||||
int eventsel;
|
||||
u64 evtreg;
|
||||
|
||||
evtreg = kvm_pmc_read_evtreg(pmc);
|
||||
|
||||
@@ -713,6 +728,14 @@ static void kvm_pmu_create_perf_event(struct kvm_pmc *pmc)
|
||||
!test_bit(eventsel, vcpu->kvm->arch.pmu_filter))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Don't create an event if we're running on hardware that requires
|
||||
* PMUv3 event translation and we couldn't find a valid mapping.
|
||||
*/
|
||||
eventsel = kvm_map_pmu_event(vcpu->kvm, eventsel);
|
||||
if (eventsel < 0)
|
||||
return;
|
||||
|
||||
memset(&attr, 0, sizeof(struct perf_event_attr));
|
||||
attr.type = arm_pmu->pmu.type;
|
||||
attr.size = sizeof(attr);
|
||||
|
||||
@@ -100,6 +100,10 @@ struct arm_pmu {
|
||||
void (*stop)(struct arm_pmu *);
|
||||
void (*reset)(void *);
|
||||
int (*map_event)(struct perf_event *event);
|
||||
/*
|
||||
* Called by KVM to map the PMUv3 event space onto non-PMUv3 hardware.
|
||||
*/
|
||||
int (*map_pmuv3_event)(unsigned int eventsel);
|
||||
DECLARE_BITMAP(cntr_mask, ARMPMU_MAX_HWEVENTS);
|
||||
bool secure_access; /* 32-bit ARM only */
|
||||
#define ARMV8_PMUV3_MAX_COMMON_EVENTS 0x40
|
||||
|
||||
Reference in New Issue
Block a user