Instead of hardcoding the PERF_CAPABILITIES rules in this loop, this could become a FeatureWordInfo field. It would be very useful for other features like intel-pt, where we need some bits to match the host bits too.
Suggested-by: Eduardo Habkost <ehabk...@redhat.com> Signed-off-by: Like Xu <like...@linux.intel.com> --- target/i386/cpu.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/target/i386/cpu.c b/target/i386/cpu.c index eee6da3ad8..56a486b498 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -708,6 +708,8 @@ typedef struct FeatureWordInfo { uint64_t migratable_flags; /* Feature flags known to be migratable */ /* Features that shouldn't be auto-enabled by "-cpu host" */ uint64_t no_autoenable_flags; + /* Bits that must match host exactly when using KVM */ + uint64_t kvm_exact_match_flags; } FeatureWordInfo; static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { @@ -1147,6 +1149,11 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { .msr = { .index = MSR_IA32_PERF_CAPABILITIES, }, + /* + * KVM is not able to emulate a VCPU with LBR_FMT different + * from the host, so LBR_FMT must match the host exactly. + */ + .kvm_exact_match_flags = PERF_CAP_LBR_FMT, }, [FEAT_VMX_PROCBASED_CTLS] = { @@ -6623,16 +6630,18 @@ static void x86_cpu_filter_features(X86CPU *cpu, bool verbose) } for (w = 0; w < FEATURE_WORDS; w++) { + FeatureWordInfo *fi = &feature_word_info[w]; + uint64_t match_flags = fi->kvm_exact_match_flags; uint64_t host_feat = x86_cpu_get_supported_feature_word(w, false); uint64_t requested_features = env->features[w]; uint64_t unavailable_features = requested_features & ~host_feat; - if (kvm_enabled() && w == FEAT_PERF_CAPABILITIES && - (requested_features & PERF_CAP_LBR_FMT)) { - if ((host_feat & PERF_CAP_LBR_FMT) != - (requested_features & PERF_CAP_LBR_FMT)) { - unavailable_features |= PERF_CAP_LBR_FMT; - } + if (kvm_enabled() && match_flags) { + uint64_t mismatches = (requested_features & match_flags) && + (requested_features ^ host_feat) & match_flags; + mark_unavailable_features(cpu, w, + mismatches, "feature doesn't match host"); + unavailable_features &= ~match_flags; } mark_unavailable_features(cpu, w, unavailable_features, prefix); } -- 2.30.2