Skip to content

Commit 5dfd498

Browse files
committed
KVM: x86/pmu: Calculate set of to-be-emulated PMCs at time of WRMSRs
Calculate and track PMCs that are counting instructions/branches retired when the PMC's event selector (or fixed counter control) is modified instead evaluating the event selector on-demand. Immediately recalc a PMC's configuration on writes to avoid false negatives/positives when KVM skips an emulated WRMSR, which is guaranteed to occur before the main run loop processes KVM_REQ_PMU. Out of an abundance of caution, and because it's relatively cheap, recalc reprogrammed PMCs in kvm_pmu_handle_event() as well. Recalculating in response to KVM_REQ_PMU _should_ be unnecessary, but for now be paranoid to avoid introducing easily-avoidable bugs in edge cases. The code can be removed in the future if necessary, e.g. in the unlikely event that the overhead of recalculating to-be-emulated PMCs is noticeable. Note! Deliberately don't check the PMU event filters, as doing so could result in KVM consuming stale information. Tracking which PMCs are counting branches/instructions will allow grabbing SRCU in the fastpath VM-Exit handlers if and only if a PMC event might be triggered (to consult the event filters), and will also allow the upcoming mediated PMU to do the right thing with respect to counting instructions (the mediated PMU won't be able to update PMCs in the VM-Exit fastpath). Reviewed-by: Dapeng Mi <dapeng1.mi@linux.intel.com> Link: https://lore.kernel.org/r/20250805190526.1453366-12-seanjc@google.com Signed-off-by: Sean Christopherson <seanjc@google.com>
1 parent 43f5bea commit 5dfd498

File tree

3 files changed

+61
-21
lines changed

3 files changed

+61
-21
lines changed

arch/x86/include/asm/kvm_host.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,9 @@ struct kvm_pmu {
579579
DECLARE_BITMAP(all_valid_pmc_idx, X86_PMC_IDX_MAX);
580580
DECLARE_BITMAP(pmc_in_use, X86_PMC_IDX_MAX);
581581

582+
DECLARE_BITMAP(pmc_counting_instructions, X86_PMC_IDX_MAX);
583+
DECLARE_BITMAP(pmc_counting_branches, X86_PMC_IDX_MAX);
584+
582585
u64 ds_area;
583586
u64 pebs_enable;
584587
u64 pebs_enable_rsvd;

arch/x86/kvm/pmu.c

Lines changed: 54 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,47 @@ static int reprogram_counter(struct kvm_pmc *pmc)
542542
eventsel & ARCH_PERFMON_EVENTSEL_INT);
543543
}
544544

545+
static bool pmc_is_event_match(struct kvm_pmc *pmc, u64 eventsel)
546+
{
547+
/*
548+
* Ignore checks for edge detect (all events currently emulated by KVM
549+
* are always rising edges), pin control (unsupported by modern CPUs),
550+
* and counter mask and its invert flag (KVM doesn't emulate multiple
551+
* events in a single clock cycle).
552+
*
553+
* Note, the uppermost nibble of AMD's mask overlaps Intel's IN_TX (bit
554+
* 32) and IN_TXCP (bit 33), as well as two reserved bits (bits 35:34).
555+
* Checking the "in HLE/RTM transaction" flags is correct as the vCPU
556+
* can't be in a transaction if KVM is emulating an instruction.
557+
*
558+
* Checking the reserved bits might be wrong if they are defined in the
559+
* future, but so could ignoring them, so do the simple thing for now.
560+
*/
561+
return !((pmc->eventsel ^ eventsel) & AMD64_RAW_EVENT_MASK_NB);
562+
}
563+
564+
void kvm_pmu_recalc_pmc_emulation(struct kvm_pmu *pmu, struct kvm_pmc *pmc)
565+
{
566+
bitmap_clear(pmu->pmc_counting_instructions, pmc->idx, 1);
567+
bitmap_clear(pmu->pmc_counting_branches, pmc->idx, 1);
568+
569+
/*
570+
* Do NOT consult the PMU event filters, as the filters must be checked
571+
* at the time of emulation to ensure KVM uses fresh information, e.g.
572+
* omitting a PMC from a bitmap could result in a missed event if the
573+
* filter is changed to allow counting the event.
574+
*/
575+
if (!pmc_speculative_in_use(pmc))
576+
return;
577+
578+
if (pmc_is_event_match(pmc, kvm_pmu_eventsel.INSTRUCTIONS_RETIRED))
579+
bitmap_set(pmu->pmc_counting_instructions, pmc->idx, 1);
580+
581+
if (pmc_is_event_match(pmc, kvm_pmu_eventsel.BRANCH_INSTRUCTIONS_RETIRED))
582+
bitmap_set(pmu->pmc_counting_branches, pmc->idx, 1);
583+
}
584+
EXPORT_SYMBOL_GPL(kvm_pmu_recalc_pmc_emulation);
585+
545586
void kvm_pmu_handle_event(struct kvm_vcpu *vcpu)
546587
{
547588
DECLARE_BITMAP(bitmap, X86_PMC_IDX_MAX);
@@ -577,6 +618,9 @@ void kvm_pmu_handle_event(struct kvm_vcpu *vcpu)
577618
*/
578619
if (unlikely(pmu->need_cleanup))
579620
kvm_pmu_cleanup(vcpu);
621+
622+
kvm_for_each_pmc(pmu, pmc, bit, bitmap)
623+
kvm_pmu_recalc_pmc_emulation(pmu, pmc);
580624
}
581625

582626
int kvm_pmu_check_rdpmc_early(struct kvm_vcpu *vcpu, unsigned int idx)
@@ -915,7 +959,8 @@ static inline bool cpl_is_matched(struct kvm_pmc *pmc)
915959
select_user;
916960
}
917961

918-
static void kvm_pmu_trigger_event(struct kvm_vcpu *vcpu, u64 eventsel)
962+
static void kvm_pmu_trigger_event(struct kvm_vcpu *vcpu,
963+
const unsigned long *event_pmcs)
919964
{
920965
DECLARE_BITMAP(bitmap, X86_PMC_IDX_MAX);
921966
struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
@@ -924,29 +969,17 @@ static void kvm_pmu_trigger_event(struct kvm_vcpu *vcpu, u64 eventsel)
924969

925970
BUILD_BUG_ON(sizeof(pmu->global_ctrl) * BITS_PER_BYTE != X86_PMC_IDX_MAX);
926971

972+
if (bitmap_empty(event_pmcs, X86_PMC_IDX_MAX))
973+
return;
974+
927975
if (!kvm_pmu_has_perf_global_ctrl(pmu))
928-
bitmap_copy(bitmap, pmu->all_valid_pmc_idx, X86_PMC_IDX_MAX);
929-
else if (!bitmap_and(bitmap, pmu->all_valid_pmc_idx,
976+
bitmap_copy(bitmap, event_pmcs, X86_PMC_IDX_MAX);
977+
else if (!bitmap_and(bitmap, event_pmcs,
930978
(unsigned long *)&pmu->global_ctrl, X86_PMC_IDX_MAX))
931979
return;
932980

933981
kvm_for_each_pmc(pmu, pmc, i, bitmap) {
934-
/*
935-
* Ignore checks for edge detect (all events currently emulated
936-
* but KVM are always rising edges), pin control (unsupported
937-
* by modern CPUs), and counter mask and its invert flag (KVM
938-
* doesn't emulate multiple events in a single clock cycle).
939-
*
940-
* Note, the uppermost nibble of AMD's mask overlaps Intel's
941-
* IN_TX (bit 32) and IN_TXCP (bit 33), as well as two reserved
942-
* bits (bits 35:34). Checking the "in HLE/RTM transaction"
943-
* flags is correct as the vCPU can't be in a transaction if
944-
* KVM is emulating an instruction. Checking the reserved bits
945-
* might be wrong if they are defined in the future, but so
946-
* could ignoring them, so do the simple thing for now.
947-
*/
948-
if (((pmc->eventsel ^ eventsel) & AMD64_RAW_EVENT_MASK_NB) ||
949-
!pmc_event_is_allowed(pmc) || !cpl_is_matched(pmc))
982+
if (!pmc_event_is_allowed(pmc) || !cpl_is_matched(pmc))
950983
continue;
951984

952985
kvm_pmu_incr_counter(pmc);
@@ -955,13 +988,13 @@ static void kvm_pmu_trigger_event(struct kvm_vcpu *vcpu, u64 eventsel)
955988

956989
void kvm_pmu_instruction_retired(struct kvm_vcpu *vcpu)
957990
{
958-
kvm_pmu_trigger_event(vcpu, kvm_pmu_eventsel.INSTRUCTIONS_RETIRED);
991+
kvm_pmu_trigger_event(vcpu, vcpu_to_pmu(vcpu)->pmc_counting_instructions);
959992
}
960993
EXPORT_SYMBOL_GPL(kvm_pmu_instruction_retired);
961994

962995
void kvm_pmu_branch_retired(struct kvm_vcpu *vcpu)
963996
{
964-
kvm_pmu_trigger_event(vcpu, kvm_pmu_eventsel.BRANCH_INSTRUCTIONS_RETIRED);
997+
kvm_pmu_trigger_event(vcpu, vcpu_to_pmu(vcpu)->pmc_counting_branches);
965998
}
966999
EXPORT_SYMBOL_GPL(kvm_pmu_branch_retired);
9671000

arch/x86/kvm/pmu.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,8 +176,12 @@ extern struct x86_pmu_capability kvm_pmu_cap;
176176

177177
void kvm_init_pmu_capability(const struct kvm_pmu_ops *pmu_ops);
178178

179+
void kvm_pmu_recalc_pmc_emulation(struct kvm_pmu *pmu, struct kvm_pmc *pmc);
180+
179181
static inline void kvm_pmu_request_counter_reprogram(struct kvm_pmc *pmc)
180182
{
183+
kvm_pmu_recalc_pmc_emulation(pmc_to_pmu(pmc), pmc);
184+
181185
set_bit(pmc->idx, pmc_to_pmu(pmc)->reprogram_pmi);
182186
kvm_make_request(KVM_REQ_PMU, pmc->vcpu);
183187
}

0 commit comments

Comments
 (0)