linux/arch/x86/kvm/vmx/capabilities.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2#ifndef __KVM_X86_VMX_CAPS_H
   3#define __KVM_X86_VMX_CAPS_H
   4
   5#include <asm/vmx.h>
   6
   7#include "lapic.h"
   8
   9extern bool __read_mostly enable_vpid;
  10extern bool __read_mostly flexpriority_enabled;
  11extern bool __read_mostly enable_ept;
  12extern bool __read_mostly enable_unrestricted_guest;
  13extern bool __read_mostly enable_ept_ad_bits;
  14extern bool __read_mostly enable_pml;
  15extern int __read_mostly pt_mode;
  16
  17#define PT_MODE_SYSTEM          0
  18#define PT_MODE_HOST_GUEST      1
  19
  20#define PMU_CAP_FW_WRITES       (1ULL << 13)
  21#define PMU_CAP_LBR_FMT         0x3f
  22
  23#define DEBUGCTLMSR_LBR_MASK            (DEBUGCTLMSR_LBR | DEBUGCTLMSR_FREEZE_LBRS_ON_PMI)
  24
  25struct nested_vmx_msrs {
  26        /*
  27         * We only store the "true" versions of the VMX capability MSRs. We
  28         * generate the "non-true" versions by setting the must-be-1 bits
  29         * according to the SDM.
  30         */
  31        u32 procbased_ctls_low;
  32        u32 procbased_ctls_high;
  33        u32 secondary_ctls_low;
  34        u32 secondary_ctls_high;
  35        u32 pinbased_ctls_low;
  36        u32 pinbased_ctls_high;
  37        u32 exit_ctls_low;
  38        u32 exit_ctls_high;
  39        u32 entry_ctls_low;
  40        u32 entry_ctls_high;
  41        u32 misc_low;
  42        u32 misc_high;
  43        u32 ept_caps;
  44        u32 vpid_caps;
  45        u64 basic;
  46        u64 cr0_fixed0;
  47        u64 cr0_fixed1;
  48        u64 cr4_fixed0;
  49        u64 cr4_fixed1;
  50        u64 vmcs_enum;
  51        u64 vmfunc_controls;
  52};
  53
  54struct vmcs_config {
  55        int size;
  56        int order;
  57        u32 basic_cap;
  58        u32 revision_id;
  59        u32 pin_based_exec_ctrl;
  60        u32 cpu_based_exec_ctrl;
  61        u32 cpu_based_2nd_exec_ctrl;
  62        u32 vmexit_ctrl;
  63        u32 vmentry_ctrl;
  64        struct nested_vmx_msrs nested;
  65};
  66extern struct vmcs_config vmcs_config;
  67
  68struct vmx_capability {
  69        u32 ept;
  70        u32 vpid;
  71};
  72extern struct vmx_capability vmx_capability;
  73
  74static inline bool cpu_has_vmx_basic_inout(void)
  75{
  76        return  (((u64)vmcs_config.basic_cap << 32) & VMX_BASIC_INOUT);
  77}
  78
  79static inline bool cpu_has_virtual_nmis(void)
  80{
  81        return vmcs_config.pin_based_exec_ctrl & PIN_BASED_VIRTUAL_NMIS;
  82}
  83
  84static inline bool cpu_has_vmx_preemption_timer(void)
  85{
  86        return vmcs_config.pin_based_exec_ctrl &
  87                PIN_BASED_VMX_PREEMPTION_TIMER;
  88}
  89
  90static inline bool cpu_has_vmx_posted_intr(void)
  91{
  92        return vmcs_config.pin_based_exec_ctrl & PIN_BASED_POSTED_INTR;
  93}
  94
  95static inline bool cpu_has_load_ia32_efer(void)
  96{
  97        return (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_EFER) &&
  98               (vmcs_config.vmexit_ctrl & VM_EXIT_LOAD_IA32_EFER);
  99}
 100
 101static inline bool cpu_has_load_perf_global_ctrl(void)
 102{
 103        return (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL) &&
 104               (vmcs_config.vmexit_ctrl & VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL);
 105}
 106
 107static inline bool cpu_has_vmx_mpx(void)
 108{
 109        return (vmcs_config.vmexit_ctrl & VM_EXIT_CLEAR_BNDCFGS) &&
 110                (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_BNDCFGS);
 111}
 112
 113static inline bool cpu_has_vmx_tpr_shadow(void)
 114{
 115        return vmcs_config.cpu_based_exec_ctrl & CPU_BASED_TPR_SHADOW;
 116}
 117
 118static inline bool cpu_need_tpr_shadow(struct kvm_vcpu *vcpu)
 119{
 120        return cpu_has_vmx_tpr_shadow() && lapic_in_kernel(vcpu);
 121}
 122
 123static inline bool cpu_has_vmx_msr_bitmap(void)
 124{
 125        return vmcs_config.cpu_based_exec_ctrl & CPU_BASED_USE_MSR_BITMAPS;
 126}
 127
 128static inline bool cpu_has_secondary_exec_ctrls(void)
 129{
 130        return vmcs_config.cpu_based_exec_ctrl &
 131                CPU_BASED_ACTIVATE_SECONDARY_CONTROLS;
 132}
 133
 134static inline bool cpu_has_vmx_virtualize_apic_accesses(void)
 135{
 136        return vmcs_config.cpu_based_2nd_exec_ctrl &
 137                SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
 138}
 139
 140static inline bool cpu_has_vmx_ept(void)
 141{
 142        return vmcs_config.cpu_based_2nd_exec_ctrl &
 143                SECONDARY_EXEC_ENABLE_EPT;
 144}
 145
 146static inline bool vmx_umip_emulated(void)
 147{
 148        return vmcs_config.cpu_based_2nd_exec_ctrl &
 149                SECONDARY_EXEC_DESC;
 150}
 151
 152static inline bool cpu_has_vmx_rdtscp(void)
 153{
 154        return vmcs_config.cpu_based_2nd_exec_ctrl &
 155                SECONDARY_EXEC_ENABLE_RDTSCP;
 156}
 157
 158static inline bool cpu_has_vmx_virtualize_x2apic_mode(void)
 159{
 160        return vmcs_config.cpu_based_2nd_exec_ctrl &
 161                SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE;
 162}
 163
 164static inline bool cpu_has_vmx_vpid(void)
 165{
 166        return vmcs_config.cpu_based_2nd_exec_ctrl &
 167                SECONDARY_EXEC_ENABLE_VPID;
 168}
 169
 170static inline bool cpu_has_vmx_wbinvd_exit(void)
 171{
 172        return vmcs_config.cpu_based_2nd_exec_ctrl &
 173                SECONDARY_EXEC_WBINVD_EXITING;
 174}
 175
 176static inline bool cpu_has_vmx_unrestricted_guest(void)
 177{
 178        return vmcs_config.cpu_based_2nd_exec_ctrl &
 179                SECONDARY_EXEC_UNRESTRICTED_GUEST;
 180}
 181
 182static inline bool cpu_has_vmx_apic_register_virt(void)
 183{
 184        return vmcs_config.cpu_based_2nd_exec_ctrl &
 185                SECONDARY_EXEC_APIC_REGISTER_VIRT;
 186}
 187
 188static inline bool cpu_has_vmx_virtual_intr_delivery(void)
 189{
 190        return vmcs_config.cpu_based_2nd_exec_ctrl &
 191                SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY;
 192}
 193
 194static inline bool cpu_has_vmx_ple(void)
 195{
 196        return vmcs_config.cpu_based_2nd_exec_ctrl &
 197                SECONDARY_EXEC_PAUSE_LOOP_EXITING;
 198}
 199
 200static inline bool cpu_has_vmx_rdrand(void)
 201{
 202        return vmcs_config.cpu_based_2nd_exec_ctrl &
 203                SECONDARY_EXEC_RDRAND_EXITING;
 204}
 205
 206static inline bool cpu_has_vmx_invpcid(void)
 207{
 208        return vmcs_config.cpu_based_2nd_exec_ctrl &
 209                SECONDARY_EXEC_ENABLE_INVPCID;
 210}
 211
 212static inline bool cpu_has_vmx_vmfunc(void)
 213{
 214        return vmcs_config.cpu_based_2nd_exec_ctrl &
 215                SECONDARY_EXEC_ENABLE_VMFUNC;
 216}
 217
 218static inline bool cpu_has_vmx_shadow_vmcs(void)
 219{
 220        u64 vmx_msr;
 221
 222        /* check if the cpu supports writing r/o exit information fields */
 223        rdmsrl(MSR_IA32_VMX_MISC, vmx_msr);
 224        if (!(vmx_msr & MSR_IA32_VMX_MISC_VMWRITE_SHADOW_RO_FIELDS))
 225                return false;
 226
 227        return vmcs_config.cpu_based_2nd_exec_ctrl &
 228                SECONDARY_EXEC_SHADOW_VMCS;
 229}
 230
 231static inline bool cpu_has_vmx_encls_vmexit(void)
 232{
 233        return vmcs_config.cpu_based_2nd_exec_ctrl &
 234                SECONDARY_EXEC_ENCLS_EXITING;
 235}
 236
 237static inline bool cpu_has_vmx_rdseed(void)
 238{
 239        return vmcs_config.cpu_based_2nd_exec_ctrl &
 240                SECONDARY_EXEC_RDSEED_EXITING;
 241}
 242
 243static inline bool cpu_has_vmx_pml(void)
 244{
 245        return vmcs_config.cpu_based_2nd_exec_ctrl & SECONDARY_EXEC_ENABLE_PML;
 246}
 247
 248static inline bool cpu_has_vmx_xsaves(void)
 249{
 250        return vmcs_config.cpu_based_2nd_exec_ctrl &
 251                SECONDARY_EXEC_XSAVES;
 252}
 253
 254static inline bool cpu_has_vmx_waitpkg(void)
 255{
 256        return vmcs_config.cpu_based_2nd_exec_ctrl &
 257                SECONDARY_EXEC_ENABLE_USR_WAIT_PAUSE;
 258}
 259
 260static inline bool cpu_has_vmx_tsc_scaling(void)
 261{
 262        return vmcs_config.cpu_based_2nd_exec_ctrl &
 263                SECONDARY_EXEC_TSC_SCALING;
 264}
 265
 266static inline bool cpu_has_vmx_bus_lock_detection(void)
 267{
 268        return vmcs_config.cpu_based_2nd_exec_ctrl &
 269            SECONDARY_EXEC_BUS_LOCK_DETECTION;
 270}
 271
 272static inline bool cpu_has_vmx_apicv(void)
 273{
 274        return cpu_has_vmx_apic_register_virt() &&
 275                cpu_has_vmx_virtual_intr_delivery() &&
 276                cpu_has_vmx_posted_intr();
 277}
 278
 279static inline bool cpu_has_vmx_flexpriority(void)
 280{
 281        return cpu_has_vmx_tpr_shadow() &&
 282                cpu_has_vmx_virtualize_apic_accesses();
 283}
 284
 285static inline bool cpu_has_vmx_ept_execute_only(void)
 286{
 287        return vmx_capability.ept & VMX_EPT_EXECUTE_ONLY_BIT;
 288}
 289
 290static inline bool cpu_has_vmx_ept_4levels(void)
 291{
 292        return vmx_capability.ept & VMX_EPT_PAGE_WALK_4_BIT;
 293}
 294
 295static inline bool cpu_has_vmx_ept_5levels(void)
 296{
 297        return vmx_capability.ept & VMX_EPT_PAGE_WALK_5_BIT;
 298}
 299
 300static inline bool cpu_has_vmx_ept_mt_wb(void)
 301{
 302        return vmx_capability.ept & VMX_EPTP_WB_BIT;
 303}
 304
 305static inline bool cpu_has_vmx_ept_2m_page(void)
 306{
 307        return vmx_capability.ept & VMX_EPT_2MB_PAGE_BIT;
 308}
 309
 310static inline bool cpu_has_vmx_ept_1g_page(void)
 311{
 312        return vmx_capability.ept & VMX_EPT_1GB_PAGE_BIT;
 313}
 314
 315static inline bool cpu_has_vmx_ept_ad_bits(void)
 316{
 317        return vmx_capability.ept & VMX_EPT_AD_BIT;
 318}
 319
 320static inline bool cpu_has_vmx_invept_context(void)
 321{
 322        return vmx_capability.ept & VMX_EPT_EXTENT_CONTEXT_BIT;
 323}
 324
 325static inline bool cpu_has_vmx_invept_global(void)
 326{
 327        return vmx_capability.ept & VMX_EPT_EXTENT_GLOBAL_BIT;
 328}
 329
 330static inline bool cpu_has_vmx_invvpid(void)
 331{
 332        return vmx_capability.vpid & VMX_VPID_INVVPID_BIT;
 333}
 334
 335static inline bool cpu_has_vmx_invvpid_individual_addr(void)
 336{
 337        return vmx_capability.vpid & VMX_VPID_EXTENT_INDIVIDUAL_ADDR_BIT;
 338}
 339
 340static inline bool cpu_has_vmx_invvpid_single(void)
 341{
 342        return vmx_capability.vpid & VMX_VPID_EXTENT_SINGLE_CONTEXT_BIT;
 343}
 344
 345static inline bool cpu_has_vmx_invvpid_global(void)
 346{
 347        return vmx_capability.vpid & VMX_VPID_EXTENT_GLOBAL_CONTEXT_BIT;
 348}
 349
 350static inline bool cpu_has_vmx_intel_pt(void)
 351{
 352        u64 vmx_msr;
 353
 354        rdmsrl(MSR_IA32_VMX_MISC, vmx_msr);
 355        return (vmx_msr & MSR_IA32_VMX_MISC_INTEL_PT) &&
 356                (vmcs_config.cpu_based_2nd_exec_ctrl & SECONDARY_EXEC_PT_USE_GPA) &&
 357                (vmcs_config.vmexit_ctrl & VM_EXIT_CLEAR_IA32_RTIT_CTL) &&
 358                (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_RTIT_CTL);
 359}
 360
 361/*
 362 * Processor Trace can operate in one of three modes:
 363 *  a. system-wide: trace both host/guest and output to host buffer
 364 *  b. host-only:   only trace host and output to host buffer
 365 *  c. host-guest:  trace host and guest simultaneously and output to their
 366 *                  respective buffer
 367 *
 368 * KVM currently only supports (a) and (c).
 369 */
 370static inline bool vmx_pt_mode_is_system(void)
 371{
 372        return pt_mode == PT_MODE_SYSTEM;
 373}
 374static inline bool vmx_pt_mode_is_host_guest(void)
 375{
 376        return pt_mode == PT_MODE_HOST_GUEST;
 377}
 378
 379static inline u64 vmx_get_perf_capabilities(void)
 380{
 381        u64 perf_cap = 0;
 382
 383        if (boot_cpu_has(X86_FEATURE_PDCM))
 384                rdmsrl(MSR_IA32_PERF_CAPABILITIES, perf_cap);
 385
 386        perf_cap &= PMU_CAP_LBR_FMT;
 387
 388        /*
 389         * Since counters are virtualized, KVM would support full
 390         * width counting unconditionally, even if the host lacks it.
 391         */
 392        return PMU_CAP_FW_WRITES | perf_cap;
 393}
 394
 395static inline u64 vmx_supported_debugctl(void)
 396{
 397        u64 debugctl = 0;
 398
 399        if (boot_cpu_has(X86_FEATURE_BUS_LOCK_DETECT))
 400                debugctl |= DEBUGCTLMSR_BUS_LOCK_DETECT;
 401
 402        if (vmx_get_perf_capabilities() & PMU_CAP_LBR_FMT)
 403                debugctl |= DEBUGCTLMSR_LBR_MASK;
 404
 405        return debugctl;
 406}
 407
 408#endif /* __KVM_X86_VMX_CAPS_H */
 409