Skip to content

Commit 8a34979

Browse files
committed
KVM: arm64: nv: Apply EL2 event filtering when in hyp context
It hopefully comes as no surprise when I say that vEL2 actually runs at EL1. So, the guest hypervisor's EL2 event filter (NSH) needs to actually be applied to EL1 in the perf event. In addition to this, the disable bit for the guest counter range (HPMD) needs to have the effect of stopping the affected counters. Do exactly that by stuffing ::exclude_kernel with the combined effect of these controls. This isn't quite enough yet, as the backing perf events need to be reprogrammed upon nested ERET/exception entry to remap the effective filter onto ::exclude_kernel. Reviewed-by: Marc Zyngier <maz@kernel.org> Link: https://lore.kernel.org/r/20241025182354.3364124-18-oliver.upton@linux.dev Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
1 parent 16535d5 commit 8a34979

File tree

1 file changed

+20
-1
lines changed

1 file changed

+20
-1
lines changed

arch/arm64/kvm/pmu-emul.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,17 @@ static bool kvm_pmc_counts_at_el1(struct kvm_pmc *pmc)
653653
return p == nsk;
654654
}
655655

656+
static bool kvm_pmc_counts_at_el2(struct kvm_pmc *pmc)
657+
{
658+
struct kvm_vcpu *vcpu = kvm_pmc_to_vcpu(pmc);
659+
u64 mdcr = __vcpu_sys_reg(vcpu, MDCR_EL2);
660+
661+
if (!kvm_pmu_counter_is_hyp(vcpu, pmc->idx) && (mdcr & MDCR_EL2_HPMD))
662+
return false;
663+
664+
return kvm_pmc_read_evtreg(pmc) & ARMV8_PMU_INCLUDE_EL2;
665+
}
666+
656667
/**
657668
* kvm_pmu_create_perf_event - create a perf event for a counter
658669
* @pmc: Counter context
@@ -695,11 +706,19 @@ static void kvm_pmu_create_perf_event(struct kvm_pmc *pmc)
695706
attr.pinned = 1;
696707
attr.disabled = !kvm_pmu_counter_is_enabled(pmc);
697708
attr.exclude_user = !kvm_pmc_counts_at_el0(pmc);
698-
attr.exclude_kernel = !kvm_pmc_counts_at_el1(pmc);
699709
attr.exclude_hv = 1; /* Don't count EL2 events */
700710
attr.exclude_host = 1; /* Don't count host events */
701711
attr.config = eventsel;
702712

713+
/*
714+
* Filter events at EL1 (i.e. vEL2) when in a hyp context based on the
715+
* guest's EL2 filter.
716+
*/
717+
if (unlikely(is_hyp_ctxt(vcpu)))
718+
attr.exclude_kernel = !kvm_pmc_counts_at_el2(pmc);
719+
else
720+
attr.exclude_kernel = !kvm_pmc_counts_at_el1(pmc);
721+
703722
/*
704723
* If counting with a 64bit counter, advertise it to the perf
705724
* code, carefully dealing with the initial sample period

0 commit comments

Comments
 (0)