Message ID | 20240126085444.324918-16-xiong.y.zhang@linux.intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | KVM: x86/pmu: Introduce passthrough vPM | expand |
On Fri, Jan 26, 2024, Xiong Zhang wrote: > + if (is_passthrough_pmu_enabled(&vmx->vcpu)) { > + /* > + * Setup auto restore guest PERF_GLOBAL_CTRL MSR at vm entry. > + */ > + if (vmentry_ctrl & VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL) > + vmcs_write64(GUEST_IA32_PERF_GLOBAL_CTRL, 0); > + else { > + i = vmx_find_loadstore_msr_slot(&vmx->msr_autoload.guest, > + MSR_CORE_PERF_GLOBAL_CTRL); > + if (i < 0) { > + i = vmx->msr_autoload.guest.nr++; > + vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, > + vmx->msr_autoload.guest.nr); > + } > + vmx->msr_autoload.guest.val[i].index = MSR_CORE_PERF_GLOBAL_CTRL; > + vmx->msr_autoload.guest.val[i].value = 0; Eww, no. Just make cpu_has_load_perf_global_ctrl() and VM_EXIT_SAVE_IA32_PERF_GLOBAL_CTRL hard requirements for enabling passthrough mode. And then have clear_atomic_switch_msr() yell if KVM tries to disable loading MSR_CORE_PERF_GLOBAL_CTRL.
On Thu, Apr 11, 2024 at 2:21 PM Sean Christopherson <seanjc@google.com> wrote: > > On Fri, Jan 26, 2024, Xiong Zhang wrote: > > + if (is_passthrough_pmu_enabled(&vmx->vcpu)) { > > + /* > > + * Setup auto restore guest PERF_GLOBAL_CTRL MSR at vm entry. > > + */ > > + if (vmentry_ctrl & VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL) > > + vmcs_write64(GUEST_IA32_PERF_GLOBAL_CTRL, 0); > > + else { > > + i = vmx_find_loadstore_msr_slot(&vmx->msr_autoload.guest, > > + MSR_CORE_PERF_GLOBAL_CTRL); > > + if (i < 0) { > > + i = vmx->msr_autoload.guest.nr++; > > + vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, > > + vmx->msr_autoload.guest.nr); > > + } > > + vmx->msr_autoload.guest.val[i].index = MSR_CORE_PERF_GLOBAL_CTRL; > > + vmx->msr_autoload.guest.val[i].value = 0; > > Eww, no. Just make cpu_has_load_perf_global_ctrl() and VM_EXIT_SAVE_IA32_PERF_GLOBAL_CTRL > hard requirements for enabling passthrough mode. And then have clear_atomic_switch_msr() > yell if KVM tries to disable loading MSR_CORE_PERF_GLOBAL_CTRL. Weren't you just complaining about the PMU version 4 constraint in another patch? And here, you are saying, "Don't support anything older than Sapphire Rapids." Sapphire Rapids has PMU version 4, so if we require VM_EXIT_SAVE_IA32_PERF_GLOBAL_CTRL, PMU version 4 is irrelevant.
On Thu, Apr 11, 2024, Jim Mattson wrote: > On Thu, Apr 11, 2024 at 2:21 PM Sean Christopherson <seanjc@google.com> wrote: > > > > On Fri, Jan 26, 2024, Xiong Zhang wrote: > > > + if (is_passthrough_pmu_enabled(&vmx->vcpu)) { > > > + /* > > > + * Setup auto restore guest PERF_GLOBAL_CTRL MSR at vm entry. > > > + */ > > > + if (vmentry_ctrl & VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL) > > > + vmcs_write64(GUEST_IA32_PERF_GLOBAL_CTRL, 0); > > > + else { > > > + i = vmx_find_loadstore_msr_slot(&vmx->msr_autoload.guest, > > > + MSR_CORE_PERF_GLOBAL_CTRL); > > > + if (i < 0) { > > > + i = vmx->msr_autoload.guest.nr++; > > > + vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, > > > + vmx->msr_autoload.guest.nr); > > > + } > > > + vmx->msr_autoload.guest.val[i].index = MSR_CORE_PERF_GLOBAL_CTRL; > > > + vmx->msr_autoload.guest.val[i].value = 0; > > > > Eww, no. Just make cpu_has_load_perf_global_ctrl() and VM_EXIT_SAVE_IA32_PERF_GLOBAL_CTRL > > hard requirements for enabling passthrough mode. And then have clear_atomic_switch_msr() > > yell if KVM tries to disable loading MSR_CORE_PERF_GLOBAL_CTRL. > > Weren't you just complaining about the PMU version 4 constraint in > another patch? And here, you are saying, "Don't support anything older > than Sapphire Rapids." Heh, I didn't realize VM_EXIT_SAVE_IA32_PERF_GLOBAL_CTRL was SPR+ when I wrote this, I thought it existed alongside the "load" controls. > Sapphire Rapids has PMU version 4, so if we require > VM_EXIT_SAVE_IA32_PERF_GLOBAL_CTRL, PMU version 4 is irrelevant.
On 4/12/2024 6:30 AM, Jim Mattson wrote: > On Thu, Apr 11, 2024 at 2:21 PM Sean Christopherson <seanjc@google.com> wrote: >> On Fri, Jan 26, 2024, Xiong Zhang wrote: >>> + if (is_passthrough_pmu_enabled(&vmx->vcpu)) { >>> + /* >>> + * Setup auto restore guest PERF_GLOBAL_CTRL MSR at vm entry. >>> + */ >>> + if (vmentry_ctrl & VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL) >>> + vmcs_write64(GUEST_IA32_PERF_GLOBAL_CTRL, 0); >>> + else { >>> + i = vmx_find_loadstore_msr_slot(&vmx->msr_autoload.guest, >>> + MSR_CORE_PERF_GLOBAL_CTRL); >>> + if (i < 0) { >>> + i = vmx->msr_autoload.guest.nr++; >>> + vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, >>> + vmx->msr_autoload.guest.nr); >>> + } >>> + vmx->msr_autoload.guest.val[i].index = MSR_CORE_PERF_GLOBAL_CTRL; >>> + vmx->msr_autoload.guest.val[i].value = 0; >> Eww, no. Just make cpu_has_load_perf_global_ctrl() and VM_EXIT_SAVE_IA32_PERF_GLOBAL_CTRL >> hard requirements for enabling passthrough mode. And then have clear_atomic_switch_msr() >> yell if KVM tries to disable loading MSR_CORE_PERF_GLOBAL_CTRL. > Weren't you just complaining about the PMU version 4 constraint in > another patch? And here, you are saying, "Don't support anything older > than Sapphire Rapids." > > Sapphire Rapids has PMU version 4, so if we require > VM_EXIT_SAVE_IA32_PERF_GLOBAL_CTRL, PMU version 4 is irrelevant. Just clarify Sapphire Rapids has PMU version 5 :). [ 2.687826] Performance Events: XSAVE Architectural LBR, PEBS fmt4+-baseline, AnyThread deprecated, *Sapphire Rapids events*, 32-deep LBR, full-width counters, Intel PMU driver. [ 2.687925] ... version: 5 [ 2.687928] ... bit width: 48 [ 2.687929] ... generic counters: 8 >
diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h index 0e73616b82f3..f574e7b429a3 100644 --- a/arch/x86/include/asm/vmx.h +++ b/arch/x86/include/asm/vmx.h @@ -104,6 +104,7 @@ #define VM_EXIT_CLEAR_BNDCFGS 0x00800000 #define VM_EXIT_PT_CONCEAL_PIP 0x01000000 #define VM_EXIT_CLEAR_IA32_RTIT_CTL 0x02000000 +#define VM_EXIT_SAVE_IA32_PERF_GLOBAL_CTRL 0x40000000 #define VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR 0x00036dff diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 33cb69ff0804..8ab266e1e2a7 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -4387,6 +4387,74 @@ static u32 vmx_pin_based_exec_ctrl(struct vcpu_vmx *vmx) return pin_based_exec_ctrl; } +static void vmx_set_perf_global_ctrl(struct vcpu_vmx *vmx) +{ + u32 vmentry_ctrl = vm_entry_controls_get(vmx); + u32 vmexit_ctrl = vm_exit_controls_get(vmx); + int i; + + /* + * PERF_GLOBAL_CTRL is toggled dynamically in emulated vPMU. + */ + if (cpu_has_perf_global_ctrl_bug() || + !is_passthrough_pmu_enabled(&vmx->vcpu)) { + vmentry_ctrl &= ~VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL; + vmexit_ctrl &= ~VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL; + vmexit_ctrl &= ~VM_EXIT_SAVE_IA32_PERF_GLOBAL_CTRL; + } + + if (is_passthrough_pmu_enabled(&vmx->vcpu)) { + /* + * Setup auto restore guest PERF_GLOBAL_CTRL MSR at vm entry. + */ + if (vmentry_ctrl & VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL) + vmcs_write64(GUEST_IA32_PERF_GLOBAL_CTRL, 0); + else { + i = vmx_find_loadstore_msr_slot(&vmx->msr_autoload.guest, + MSR_CORE_PERF_GLOBAL_CTRL); + if (i < 0) { + i = vmx->msr_autoload.guest.nr++; + vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, + vmx->msr_autoload.guest.nr); + } + vmx->msr_autoload.guest.val[i].index = MSR_CORE_PERF_GLOBAL_CTRL; + vmx->msr_autoload.guest.val[i].value = 0; + } + /* + * Setup auto clear host PERF_GLOBAL_CTRL msr at vm exit. + */ + if (vmexit_ctrl & VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL) + vmcs_write64(HOST_IA32_PERF_GLOBAL_CTRL, 0); + else { + i = vmx_find_loadstore_msr_slot(&vmx->msr_autoload.host, + MSR_CORE_PERF_GLOBAL_CTRL); + if (i < 0) { + i = vmx->msr_autoload.host.nr++; + vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, + vmx->msr_autoload.host.nr); + } + vmx->msr_autoload.host.val[i].index = MSR_CORE_PERF_GLOBAL_CTRL; + vmx->msr_autoload.host.val[i].value = 0; + } + /* + * Setup auto save guest PERF_GLOBAL_CTRL msr at vm exit + */ + if (!(vmexit_ctrl & VM_EXIT_SAVE_IA32_PERF_GLOBAL_CTRL)) { + i = vmx_find_loadstore_msr_slot(&vmx->msr_autostore.guest, + MSR_CORE_PERF_GLOBAL_CTRL); + if (i < 0) { + i = vmx->msr_autostore.guest.nr++; + vmcs_write32(VM_EXIT_MSR_STORE_COUNT, + vmx->msr_autostore.guest.nr); + } + vmx->msr_autostore.guest.val[i].index = MSR_CORE_PERF_GLOBAL_CTRL; + } + } + + vm_entry_controls_set(vmx, vmentry_ctrl); + vm_exit_controls_set(vmx, vmexit_ctrl); +} + static u32 vmx_vmentry_ctrl(void) { u32 vmentry_ctrl = vmcs_config.vmentry_ctrl; @@ -4394,15 +4462,9 @@ static u32 vmx_vmentry_ctrl(void) if (vmx_pt_mode_is_system()) vmentry_ctrl &= ~(VM_ENTRY_PT_CONCEAL_PIP | VM_ENTRY_LOAD_IA32_RTIT_CTL); - /* - * IA32e mode, and loading of EFER and PERF_GLOBAL_CTRL are toggled dynamically. - */ - vmentry_ctrl &= ~(VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | - VM_ENTRY_LOAD_IA32_EFER | - VM_ENTRY_IA32E_MODE); - if (cpu_has_perf_global_ctrl_bug()) - vmentry_ctrl &= ~VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL; + /* IA32e mode, and loading of EFER is toggled dynamically. */ + vmentry_ctrl &= ~(VM_ENTRY_LOAD_IA32_EFER | VM_ENTRY_IA32E_MODE); return vmentry_ctrl; } @@ -4422,12 +4484,8 @@ static u32 vmx_vmexit_ctrl(void) vmexit_ctrl &= ~(VM_EXIT_PT_CONCEAL_PIP | VM_EXIT_CLEAR_IA32_RTIT_CTL); - if (cpu_has_perf_global_ctrl_bug()) - vmexit_ctrl &= ~VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL; - - /* Loading of EFER and PERF_GLOBAL_CTRL are toggled dynamically */ - return vmexit_ctrl & - ~(VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | VM_EXIT_LOAD_IA32_EFER); + /* Loading of EFER is toggled dynamically */ + return vmexit_ctrl & ~VM_EXIT_LOAD_IA32_EFER; } static void vmx_refresh_apicv_exec_ctrl(struct kvm_vcpu *vcpu) @@ -4765,6 +4823,7 @@ static void init_vmcs(struct vcpu_vmx *vmx) vmcs_write64(VM_FUNCTION_CONTROL, 0); vmcs_write32(VM_EXIT_MSR_STORE_COUNT, 0); + vmcs_write64(VM_EXIT_MSR_STORE_ADDR, __pa(vmx->msr_autostore.guest.val)); vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, 0); vmcs_write64(VM_EXIT_MSR_LOAD_ADDR, __pa(vmx->msr_autoload.host.val)); vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, 0); @@ -7822,6 +7881,8 @@ static void vmx_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu) if (is_passthrough_pmu_enabled(&vmx->vcpu)) exec_controls_clearbit(vmx, CPU_BASED_RDPMC_EXITING); + vmx_set_perf_global_ctrl(vmx); + /* Refresh #PF interception to account for MAXPHYADDR changes. */ vmx_update_exception_bitmap(vcpu); } diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h index c2130d2c8e24..c89db35e1de8 100644 --- a/arch/x86/kvm/vmx/vmx.h +++ b/arch/x86/kvm/vmx/vmx.h @@ -502,7 +502,8 @@ static inline u8 vmx_get_rvi(void) VM_EXIT_LOAD_IA32_EFER | \ VM_EXIT_CLEAR_BNDCFGS | \ VM_EXIT_PT_CONCEAL_PIP | \ - VM_EXIT_CLEAR_IA32_RTIT_CTL) + VM_EXIT_CLEAR_IA32_RTIT_CTL | \ + VM_EXIT_SAVE_IA32_PERF_GLOBAL_CTRL) #define KVM_REQUIRED_VMX_PIN_BASED_VM_EXEC_CONTROL \ (PIN_BASED_EXT_INTR_MASK | \