KVM: VMX: Add helpers to query Intel PT mode
authorSean Christopherson <sean.j.christopherson@intel.com>
Mon, 2 Mar 2020 23:56:22 +0000 (15:56 -0800)
committerPaolo Bonzini <pbonzini@redhat.com>
Mon, 16 Mar 2020 16:58:08 +0000 (17:58 +0100)
Add helpers to query which of the (two) supported PT modes is active.
The primary motivation is to help document that there is a third PT mode
(host-only) that's currently not supported by KVM.  As is, it's not
obvious that PT_MODE_SYSTEM != !PT_MODE_HOST_GUEST and vice versa, e.g.
that "pt_mode == PT_MODE_SYSTEM" and "pt_mode != PT_MODE_HOST_GUEST" are
two distinct checks.

No functional change intended.

Reviewed-by: Vitaly Kuznetsov <vkuznets@redhat.com>
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/kvm/vmx/capabilities.h
arch/x86/kvm/vmx/nested.c
arch/x86/kvm/vmx/vmx.c
arch/x86/kvm/vmx/vmx.h

index f486e26..80eec8c 100644 (file)
@@ -354,4 +354,22 @@ static inline bool cpu_has_vmx_intel_pt(void)
                (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_RTIT_CTL);
 }
 
+/*
+ * Processor Trace can operate in one of three modes:
+ *  a. system-wide: trace both host/guest and output to host buffer
+ *  b. host-only:   only trace host and output to host buffer
+ *  c. host-guest:  trace host and guest simultaneously and output to their
+ *                  respective buffer
+ *
+ * KVM currently only supports (a) and (c).
+ */
+static inline bool vmx_pt_mode_is_system(void)
+{
+       return pt_mode == PT_MODE_SYSTEM;
+}
+static inline bool vmx_pt_mode_is_host_guest(void)
+{
+       return pt_mode == PT_MODE_HOST_GUEST;
+}
+
 #endif /* __KVM_X86_VMX_CAPS_H */
index 79c7764..e47eb7c 100644 (file)
@@ -4602,7 +4602,7 @@ static int enter_vmx_operation(struct kvm_vcpu *vcpu)
        vmx->nested.vmcs02_initialized = false;
        vmx->nested.vmxon = true;
 
-       if (pt_mode == PT_MODE_HOST_GUEST) {
+       if (vmx_pt_mode_is_host_guest()) {
                vmx->pt_desc.guest.ctl = 0;
                pt_update_intercept_for_msr(vmx);
        }
index 57742dd..af2acf1 100644 (file)
@@ -1059,7 +1059,7 @@ static unsigned long segment_base(u16 selector)
 
 static inline bool pt_can_write_msr(struct vcpu_vmx *vmx)
 {
-       return (pt_mode == PT_MODE_HOST_GUEST) &&
+       return vmx_pt_mode_is_host_guest() &&
               !(vmx->pt_desc.guest.ctl & RTIT_CTL_TRACEEN);
 }
 
@@ -1093,7 +1093,7 @@ static inline void pt_save_msr(struct pt_ctx *ctx, u32 addr_range)
 
 static void pt_guest_enter(struct vcpu_vmx *vmx)
 {
-       if (pt_mode == PT_MODE_SYSTEM)
+       if (vmx_pt_mode_is_system())
                return;
 
        /*
@@ -1110,7 +1110,7 @@ static void pt_guest_enter(struct vcpu_vmx *vmx)
 
 static void pt_guest_exit(struct vcpu_vmx *vmx)
 {
-       if (pt_mode == PT_MODE_SYSTEM)
+       if (vmx_pt_mode_is_system())
                return;
 
        if (vmx->pt_desc.guest.ctl & RTIT_CTL_TRACEEN) {
@@ -1904,24 +1904,24 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
                                                        &msr_info->data);
                break;
        case MSR_IA32_RTIT_CTL:
-               if (pt_mode != PT_MODE_HOST_GUEST)
+               if (!vmx_pt_mode_is_host_guest())
                        return 1;
                msr_info->data = vmx->pt_desc.guest.ctl;
                break;
        case MSR_IA32_RTIT_STATUS:
-               if (pt_mode != PT_MODE_HOST_GUEST)
+               if (!vmx_pt_mode_is_host_guest())
                        return 1;
                msr_info->data = vmx->pt_desc.guest.status;
                break;
        case MSR_IA32_RTIT_CR3_MATCH:
-               if ((pt_mode != PT_MODE_HOST_GUEST) ||
+               if (!vmx_pt_mode_is_host_guest() ||
                        !intel_pt_validate_cap(vmx->pt_desc.caps,
                                                PT_CAP_cr3_filtering))
                        return 1;
                msr_info->data = vmx->pt_desc.guest.cr3_match;
                break;
        case MSR_IA32_RTIT_OUTPUT_BASE:
-               if ((pt_mode != PT_MODE_HOST_GUEST) ||
+               if (!vmx_pt_mode_is_host_guest() ||
                        (!intel_pt_validate_cap(vmx->pt_desc.caps,
                                        PT_CAP_topa_output) &&
                         !intel_pt_validate_cap(vmx->pt_desc.caps,
@@ -1930,7 +1930,7 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
                msr_info->data = vmx->pt_desc.guest.output_base;
                break;
        case MSR_IA32_RTIT_OUTPUT_MASK:
-               if ((pt_mode != PT_MODE_HOST_GUEST) ||
+               if (!vmx_pt_mode_is_host_guest() ||
                        (!intel_pt_validate_cap(vmx->pt_desc.caps,
                                        PT_CAP_topa_output) &&
                         !intel_pt_validate_cap(vmx->pt_desc.caps,
@@ -1940,7 +1940,7 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
                break;
        case MSR_IA32_RTIT_ADDR0_A ... MSR_IA32_RTIT_ADDR3_B:
                index = msr_info->index - MSR_IA32_RTIT_ADDR0_A;
-               if ((pt_mode != PT_MODE_HOST_GUEST) ||
+               if (!vmx_pt_mode_is_host_guest() ||
                        (index >= 2 * intel_pt_validate_cap(vmx->pt_desc.caps,
                                        PT_CAP_num_address_ranges)))
                        return 1;
@@ -2146,7 +2146,7 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
                        return 1;
                return vmx_set_vmx_msr(vcpu, msr_index, data);
        case MSR_IA32_RTIT_CTL:
-               if ((pt_mode != PT_MODE_HOST_GUEST) ||
+               if (!vmx_pt_mode_is_host_guest() ||
                        vmx_rtit_ctl_check(vcpu, data) ||
                        vmx->nested.vmxon)
                        return 1;
@@ -4023,7 +4023,7 @@ static void vmx_compute_secondary_exec_control(struct vcpu_vmx *vmx)
 
        u32 exec_control = vmcs_config.cpu_based_2nd_exec_ctrl;
 
-       if (pt_mode == PT_MODE_SYSTEM)
+       if (vmx_pt_mode_is_system())
                exec_control &= ~(SECONDARY_EXEC_PT_USE_GPA | SECONDARY_EXEC_PT_CONCEAL_VMX);
        if (!cpu_need_virtualize_apic_accesses(vcpu))
                exec_control &= ~SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
@@ -4264,7 +4264,7 @@ static void init_vmcs(struct vcpu_vmx *vmx)
        if (cpu_has_vmx_encls_vmexit())
                vmcs_write64(ENCLS_EXITING_BITMAP, -1ull);
 
-       if (pt_mode == PT_MODE_HOST_GUEST) {
+       if (vmx_pt_mode_is_host_guest()) {
                memset(&vmx->pt_desc, 0, sizeof(vmx->pt_desc));
                /* Bit[6~0] are forced to 1, writes are ignored. */
                vmx->pt_desc.guest.output_mask = 0x7F;
@@ -6318,7 +6318,7 @@ static bool vmx_has_emulated_msr(int index)
 
 static bool vmx_pt_supported(void)
 {
-       return pt_mode == PT_MODE_HOST_GUEST;
+       return vmx_pt_mode_is_host_guest();
 }
 
 static void vmx_recover_nmi_blocking(struct vcpu_vmx *vmx)
index e64da06..9a51a3a 100644 (file)
@@ -452,7 +452,7 @@ static inline void vmx_segment_cache_clear(struct vcpu_vmx *vmx)
 static inline u32 vmx_vmentry_ctrl(void)
 {
        u32 vmentry_ctrl = vmcs_config.vmentry_ctrl;
-       if (pt_mode == PT_MODE_SYSTEM)
+       if (vmx_pt_mode_is_system())
                vmentry_ctrl &= ~(VM_ENTRY_PT_CONCEAL_PIP |
                                  VM_ENTRY_LOAD_IA32_RTIT_CTL);
        /* Loading of EFER and PERF_GLOBAL_CTRL are toggled dynamically */
@@ -463,7 +463,7 @@ static inline u32 vmx_vmentry_ctrl(void)
 static inline u32 vmx_vmexit_ctrl(void)
 {
        u32 vmexit_ctrl = vmcs_config.vmexit_ctrl;
-       if (pt_mode == PT_MODE_SYSTEM)
+       if (vmx_pt_mode_is_system())
                vmexit_ctrl &= ~(VM_EXIT_PT_CONCEAL_PIP |
                                 VM_EXIT_CLEAR_IA32_RTIT_CTL);
        /* Loading of EFER and PERF_GLOBAL_CTRL are toggled dynamically */