lkml.org 
[lkml]   [2017]   [Nov]   [28]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v3 9/9] KVM: x86: Implement Intel Processor Trace context switch
    Date
    From: Chao Peng <chao.p.peng@linux.intel.com>

    Load/Store Intel processor trace register in context switch.
    MSR IA32_RTIT_CTL is loaded/stored automatically from VMCS.
    In HOST mode, we just need to restore the status of IA32_RTIT_CTL.
    In HOST_GUEST mode, we need load/resore PT MSRs only when PT is
    enabled in guest.

    Signed-off-by: Chao Peng <chao.p.peng@linux.intel.com>
    Signed-off-by: Luwei Kang <luwei.kang@intel.com>
    ---
    arch/x86/kvm/vmx.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
    1 file changed, 64 insertions(+)

    diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
    index b4ad8fc..fb0e54a 100644
    --- a/arch/x86/kvm/vmx.c
    +++ b/arch/x86/kvm/vmx.c
    @@ -2142,6 +2142,55 @@ static unsigned long segment_base(u16 selector)
    }
    #endif

    +static inline void pt_load_msr(struct pt_ctx *ctx, unsigned int addr_num)
    +{
    + u32 i;
    +
    + wrmsrl(MSR_IA32_RTIT_STATUS, ctx->status);
    + wrmsrl(MSR_IA32_RTIT_OUTPUT_BASE, ctx->output_base);
    + wrmsrl(MSR_IA32_RTIT_OUTPUT_MASK, ctx->output_mask);
    + wrmsrl(MSR_IA32_RTIT_CR3_MATCH, ctx->cr3_match);
    + for (i = 0; i < addr_num; i++)
    + wrmsrl(MSR_IA32_RTIT_ADDR0_A + i, ctx->addrs[i]);
    +}
    +
    +static inline void pt_save_msr(struct pt_ctx *ctx, unsigned int addr_num)
    +{
    + u32 i;
    +
    + rdmsrl(MSR_IA32_RTIT_STATUS, ctx->status);
    + rdmsrl(MSR_IA32_RTIT_OUTPUT_BASE, ctx->output_base);
    + rdmsrl(MSR_IA32_RTIT_OUTPUT_MASK, ctx->output_mask);
    + rdmsrl(MSR_IA32_RTIT_CR3_MATCH, ctx->cr3_match);
    + for (i = 0; i < addr_num; i++)
    + rdmsrl(MSR_IA32_RTIT_ADDR0_A + i, ctx->addrs[i]);
    +}
    +
    +static void pt_guest_enter(struct vcpu_vmx *vmx)
    +{
    + if (pt_mode == PT_MODE_HOST || PT_MODE_HOST_GUEST)
    + rdmsrl(MSR_IA32_RTIT_CTL, vmx->pt_desc.host.ctl);
    +
    + if (pt_mode == PT_MODE_HOST_GUEST &&
    + vmx->pt_desc.guest.ctl & RTIT_CTL_TRACEEN) {
    + wrmsrl(MSR_IA32_RTIT_CTL, 0);
    + pt_save_msr(&vmx->pt_desc.host, vmx->pt_desc.addr_num);
    + pt_load_msr(&vmx->pt_desc.guest, vmx->pt_desc.addr_num);
    + }
    +}
    +
    +static void pt_guest_exit(struct vcpu_vmx *vmx)
    +{
    + if (pt_mode == PT_MODE_HOST_GUEST &&
    + vmx->pt_desc.guest.ctl & RTIT_CTL_TRACEEN) {
    + pt_save_msr(&vmx->pt_desc.guest, vmx->pt_desc.addr_num);
    + pt_load_msr(&vmx->pt_desc.host, vmx->pt_desc.addr_num);
    + }
    +
    + if (pt_mode == PT_MODE_HOST || pt_mode == PT_MODE_HOST_GUEST)
    + wrmsrl(MSR_IA32_RTIT_CTL, vmx->pt_desc.host.ctl);
    +}
    +
    static void vmx_save_host_state(struct kvm_vcpu *vcpu)
    {
    struct vcpu_vmx *vmx = to_vmx(vcpu);
    @@ -5758,6 +5807,17 @@ static void vmx_vcpu_setup(struct vcpu_vmx *vmx)
    vmcs_write64(PML_ADDRESS, page_to_phys(vmx->pml_pg));
    vmcs_write16(GUEST_PML_INDEX, PML_ENTITY_NUM - 1);
    }
    +
    + if (pt_mode == PT_MODE_HOST_GUEST) {
    + u32 eax, ebx, ecx, edx;
    +
    + cpuid_count(0x14, 1, &eax, &ebx, &ecx, &edx);
    + memset(&vmx->pt_desc, 0, sizeof(vmx->pt_desc));
    + vmx->pt_desc.addr_num = eax & 0x7;
    + /* Bit[6~0] are forced to 1, writes are ignored. */
    + vmx->pt_desc.guest.output_mask = 0x7F;
    + vmcs_write64(GUEST_IA32_RTIT_CTL, 0);
    + }
    }

    static void vmx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
    @@ -9590,6 +9650,8 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
    vcpu->arch.pkru != vmx->host_pkru)
    __write_pkru(vcpu->arch.pkru);

    + pt_guest_enter(vmx);
    +
    atomic_switch_perf_msrs(vmx);
    debugctlmsr = get_debugctlmsr();

    @@ -9725,6 +9787,8 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
    | (1 << VCPU_EXREG_CR3));
    vcpu->arch.regs_dirty = 0;

    + pt_guest_exit(vmx);
    +
    /*
    * eager fpu is enabled if PKEY is supported and CR4 is switched
    * back on host, so it is safe to read guest PKRU from current
    --
    1.8.3.1
    \
     
     \ /
      Last update: 2017-11-28 11:11    [W:3.332 / U:1.244 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site