lkml.org 
[lkml]   [2024]   [Jan]   [26]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[RFC PATCH 15/41] KVM: x86/pmu: Manage MSR interception for IA32_PERF_GLOBAL_CTRL
    Date
    From: Xiong Zhang <xiong.y.zhang@intel.com>

    In PMU passthrough mode, there are three requirements to manage
    IA32_PERF_GLOBAL_CTRL:
    - guest IA32_PERF_GLOBAL_CTRL MSR must be saved at vm exit.
    - IA32_PERF_GLOBAL_CTRL MSR must be cleared at vm exit to avoid any
    counter of running within KVM runloop.
    - guest IA32_PERF_GLOBAL_CTRL MSR must be restored at vm entry.

    Introduce vmx_set_perf_global_ctrl() function to auto switching
    IA32_PERF_GLOBAL_CTR and invoke it after the VMM finishes setting up the
    CPUID bits.

    Signed-off-by: Xiong Zhang <xiong.y.zhang@intel.com>
    Signed-off-by: Mingwei Zhang <mizhang@google.com>
    ---
    arch/x86/include/asm/vmx.h | 1 +
    arch/x86/kvm/vmx/vmx.c | 89 ++++++++++++++++++++++++++++++++------
    arch/x86/kvm/vmx/vmx.h | 3 +-
    3 files changed, 78 insertions(+), 15 deletions(-)

    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 | \
    --
    2.34.1

    \
     
     \ /
      Last update: 2024-05-27 14:34    [W:7.044 / U:0.020 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site