]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
Merge tag 'kvm-x86-pmu-6.9' of https://github.com/kvm-x86/linux into HEAD
authorPaolo Bonzini <pbonzini@redhat.com>
Mon, 11 Mar 2024 14:41:09 +0000 (10:41 -0400)
committerPaolo Bonzini <pbonzini@redhat.com>
Mon, 11 Mar 2024 14:41:09 +0000 (10:41 -0400)
KVM x86 PMU changes for 6.9:

 - Fix several bugs where KVM speciously prevents the guest from utilizing
   fixed counters and architectural event encodings based on whether or not
   guest CPUID reports support for the _architectural_ encoding.

 - Fix a variety of bugs in KVM's emulation of RDPMC, e.g. for "fast" reads,
   priority of VMX interception vs #GP, PMC types in architectural PMUs, etc.

 - Add a selftest to verify KVM correctly emulates RDMPC, counter availability,
   and a variety of other PMC-related behaviors that depend on guest CPUID,
   i.e. are difficult to validate via KVM-Unit-Tests.

 - Zero out PMU metadata on AMD if the virtual PMU is disabled to avoid wasting
   cycles, e.g. when checking if a PMC event needs to be synthesized when
   skipping an instruction.

 - Optimize triggering of emulated events, e.g. for "count instructions" events
   when skipping an instruction, which yields a ~10% performance improvement in
   VM-Exit microbenchmarks when a vPMU is exposed to the guest.

 - Tighten the check for "PMI in guest" to reduce false positives if an NMI
   arrives in the host while KVM is handling an IRQ VM-Exit.

15 files changed:
1  2 
arch/x86/include/asm/kvm_host.h
arch/x86/kvm/emulate.c
arch/x86/kvm/kvm_emulate.h
arch/x86/kvm/vmx/nested.c
arch/x86/kvm/vmx/pmu_intel.c
arch/x86/kvm/x86.c
tools/testing/selftests/kvm/Makefile
tools/testing/selftests/kvm/include/kvm_util_base.h
tools/testing/selftests/kvm/include/x86_64/processor.h
tools/testing/selftests/kvm/lib/kvm_util.c
tools/testing/selftests/kvm/lib/x86_64/processor.c
tools/testing/selftests/kvm/x86_64/pmu_event_filter_test.c
tools/testing/selftests/kvm/x86_64/smaller_maxphyaddr_emulation_test.c
tools/testing/selftests/kvm/x86_64/userspace_msr_exit_test.c
tools/testing/selftests/kvm/x86_64/vmx_pmu_caps_test.c

Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index b0f13fafa1552d93630289813bce88c8957af459,ce58098d80fdadfc0c79a2d2f58474a18f82f7e2..19f5710bb456804db60d42a066a8c623562768b6
@@@ -36,8 -36,8 +36,9 @@@ LIBKVM_x86_64 += lib/x86_64/apic.
  LIBKVM_x86_64 += lib/x86_64/handlers.S
  LIBKVM_x86_64 += lib/x86_64/hyperv.c
  LIBKVM_x86_64 += lib/x86_64/memstress.c
+ LIBKVM_x86_64 += lib/x86_64/pmu.c
  LIBKVM_x86_64 += lib/x86_64/processor.c
 +LIBKVM_x86_64 += lib/x86_64/sev.c
  LIBKVM_x86_64 += lib/x86_64/svm.c
  LIBKVM_x86_64 += lib/x86_64/ucall.c
  LIBKVM_x86_64 += lib/x86_64/vmx.c
index d2534a4a077b76e8775fc90c913e2fdc738ddc71,abac816f6594ca5f8b6899d4ffdf72b72a85e0df..3bd03b088dda605348c7f85fc8d190ef63cf9e5e
  extern bool host_cpu_is_intel;
  extern bool host_cpu_is_amd;
  
 +enum vm_guest_x86_subtype {
 +      VM_SUBTYPE_NONE = 0,
 +      VM_SUBTYPE_SEV,
 +      VM_SUBTYPE_SEV_ES,
 +};
 +
+ /* Forced emulation prefix, used to invoke the emulator unconditionally. */
+ #define KVM_FEP "ud2; .byte 'k', 'v', 'm';"
  #define NMI_VECTOR            0x02
  
  #define X86_EFLAGS_FIXED       (1u << 1)
index 9591a5fd54d7ccc21d241d1bd41ffa06ea2bef2e,ab3a8c4f0b864332906f5ef07a3dfe32f9e71f10..f4f61a2d2464c1911efcf2dd9b02b1ff90af9e41
@@@ -528,13 -511,16 +512,16 @@@ static void run_guest_then_process_ucal
        process_ucall_done(vcpu);
  }
  
 -static void test_msr_filter_allow(void)
 +KVM_ONE_VCPU_TEST_SUITE(user_msr);
 +
 +KVM_ONE_VCPU_TEST(user_msr, msr_filter_allow, guest_code_filter_allow)
  {
 -      struct kvm_vcpu *vcpu;
 -      struct kvm_vm *vm;
 +      struct kvm_vm *vm = vcpu->vm;
+       uint64_t cmd;
        int rc;
  
 -      vm = vm_create_with_one_vcpu(&vcpu, guest_code_filter_allow);
+       sync_global_to_guest(vm, fep_available);
        rc = kvm_check_cap(KVM_CAP_X86_USER_SPACE_MSR);
        TEST_ASSERT(rc, "KVM_CAP_X86_USER_SPACE_MSR is available");
        vm_enable_cap(vm, KVM_CAP_X86_USER_SPACE_MSR, KVM_MSR_EXIT_REASON_FILTER);
                /* Confirm the guest completed without issues. */
                run_guest_then_process_ucall_done(vcpu);
        } else {
+               TEST_ASSERT_EQ(cmd, UCALL_DONE);
                printf("To run the instruction emulated tests set the module parameter 'kvm.force_emulation_prefix=1'\n");
        }
 -
 -      kvm_vm_free(vm);
  }
  
  static int handle_ucall(struct kvm_vcpu *vcpu)
@@@ -786,5 -791,15 +774,7 @@@ KVM_ONE_VCPU_TEST(user_msr, user_exit_m
  
  int main(int argc, char *argv[])
  {
 -      test_msr_filter_allow();
 -
 -      test_msr_filter_deny();
 -
 -      test_msr_permission_bitmap();
 -
 -      test_user_exit_msr_flags();
 -
 -      return 0;
+       fep_available = kvm_is_forced_emulation_enabled();
 +      return test_harness_run(argc, argv);
  }
index 876442fadada86553bb9da26f249171c36ba9a83,8ded194c5a6d2c53365211501127af81deb69bc5..ea0cb3cae0f759be3072b3facb92291edb8c2d55
@@@ -213,7 -235,9 +213,7 @@@ KVM_ONE_VCPU_TEST(vmx_pmu_caps, lbr_per
  
  int main(int argc, char *argv[])
  {
-       TEST_REQUIRE(get_kvm_param_bool("enable_pmu"));
 -      union perf_capabilities host_cap;
 -
+       TEST_REQUIRE(kvm_is_pmu_enabled());
        TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_PDCM));
  
        TEST_REQUIRE(kvm_cpu_has_p(X86_PROPERTY_PMU_VERSION));