cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

capabilities.h (9819B)


      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#include "x86.h"
      9
     10extern bool __read_mostly enable_vpid;
     11extern bool __read_mostly flexpriority_enabled;
     12extern bool __read_mostly enable_ept;
     13extern bool __read_mostly enable_unrestricted_guest;
     14extern bool __read_mostly enable_ept_ad_bits;
     15extern bool __read_mostly enable_pml;
     16extern int __read_mostly pt_mode;
     17
     18#define PT_MODE_SYSTEM		0
     19#define PT_MODE_HOST_GUEST	1
     20
     21#define PMU_CAP_FW_WRITES	(1ULL << 13)
     22#define PMU_CAP_LBR_FMT		0x3f
     23
     24#define DEBUGCTLMSR_LBR_MASK		(DEBUGCTLMSR_LBR | DEBUGCTLMSR_FREEZE_LBRS_ON_PMI)
     25
     26struct nested_vmx_msrs {
     27	/*
     28	 * We only store the "true" versions of the VMX capability MSRs. We
     29	 * generate the "non-true" versions by setting the must-be-1 bits
     30	 * according to the SDM.
     31	 */
     32	u32 procbased_ctls_low;
     33	u32 procbased_ctls_high;
     34	u32 secondary_ctls_low;
     35	u32 secondary_ctls_high;
     36	u32 pinbased_ctls_low;
     37	u32 pinbased_ctls_high;
     38	u32 exit_ctls_low;
     39	u32 exit_ctls_high;
     40	u32 entry_ctls_low;
     41	u32 entry_ctls_high;
     42	u32 misc_low;
     43	u32 misc_high;
     44	u32 ept_caps;
     45	u32 vpid_caps;
     46	u64 basic;
     47	u64 cr0_fixed0;
     48	u64 cr0_fixed1;
     49	u64 cr4_fixed0;
     50	u64 cr4_fixed1;
     51	u64 vmcs_enum;
     52	u64 vmfunc_controls;
     53};
     54
     55struct vmcs_config {
     56	int size;
     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 int ept_caps_to_lpage_level(u32 ept_caps)
    316{
    317	if (ept_caps & VMX_EPT_1GB_PAGE_BIT)
    318		return PG_LEVEL_1G;
    319	if (ept_caps & VMX_EPT_2MB_PAGE_BIT)
    320		return PG_LEVEL_2M;
    321	return PG_LEVEL_4K;
    322}
    323
    324static inline bool cpu_has_vmx_ept_ad_bits(void)
    325{
    326	return vmx_capability.ept & VMX_EPT_AD_BIT;
    327}
    328
    329static inline bool cpu_has_vmx_invept_context(void)
    330{
    331	return vmx_capability.ept & VMX_EPT_EXTENT_CONTEXT_BIT;
    332}
    333
    334static inline bool cpu_has_vmx_invept_global(void)
    335{
    336	return vmx_capability.ept & VMX_EPT_EXTENT_GLOBAL_BIT;
    337}
    338
    339static inline bool cpu_has_vmx_invvpid(void)
    340{
    341	return vmx_capability.vpid & VMX_VPID_INVVPID_BIT;
    342}
    343
    344static inline bool cpu_has_vmx_invvpid_individual_addr(void)
    345{
    346	return vmx_capability.vpid & VMX_VPID_EXTENT_INDIVIDUAL_ADDR_BIT;
    347}
    348
    349static inline bool cpu_has_vmx_invvpid_single(void)
    350{
    351	return vmx_capability.vpid & VMX_VPID_EXTENT_SINGLE_CONTEXT_BIT;
    352}
    353
    354static inline bool cpu_has_vmx_invvpid_global(void)
    355{
    356	return vmx_capability.vpid & VMX_VPID_EXTENT_GLOBAL_CONTEXT_BIT;
    357}
    358
    359static inline bool cpu_has_vmx_intel_pt(void)
    360{
    361	u64 vmx_msr;
    362
    363	rdmsrl(MSR_IA32_VMX_MISC, vmx_msr);
    364	return (vmx_msr & MSR_IA32_VMX_MISC_INTEL_PT) &&
    365		(vmcs_config.cpu_based_2nd_exec_ctrl & SECONDARY_EXEC_PT_USE_GPA) &&
    366		(vmcs_config.vmexit_ctrl & VM_EXIT_CLEAR_IA32_RTIT_CTL) &&
    367		(vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_RTIT_CTL);
    368}
    369
    370/*
    371 * Processor Trace can operate in one of three modes:
    372 *  a. system-wide: trace both host/guest and output to host buffer
    373 *  b. host-only:   only trace host and output to host buffer
    374 *  c. host-guest:  trace host and guest simultaneously and output to their
    375 *                  respective buffer
    376 *
    377 * KVM currently only supports (a) and (c).
    378 */
    379static inline bool vmx_pt_mode_is_system(void)
    380{
    381	return pt_mode == PT_MODE_SYSTEM;
    382}
    383static inline bool vmx_pt_mode_is_host_guest(void)
    384{
    385	return pt_mode == PT_MODE_HOST_GUEST;
    386}
    387
    388static inline u64 vmx_get_perf_capabilities(void)
    389{
    390	u64 perf_cap = 0;
    391
    392	if (!enable_pmu)
    393		return perf_cap;
    394
    395	if (boot_cpu_has(X86_FEATURE_PDCM))
    396		rdmsrl(MSR_IA32_PERF_CAPABILITIES, perf_cap);
    397
    398	perf_cap &= PMU_CAP_LBR_FMT;
    399
    400	/*
    401	 * Since counters are virtualized, KVM would support full
    402	 * width counting unconditionally, even if the host lacks it.
    403	 */
    404	return PMU_CAP_FW_WRITES | perf_cap;
    405}
    406
    407static inline u64 vmx_supported_debugctl(void)
    408{
    409	u64 debugctl = 0;
    410
    411	if (boot_cpu_has(X86_FEATURE_BUS_LOCK_DETECT))
    412		debugctl |= DEBUGCTLMSR_BUS_LOCK_DETECT;
    413
    414	if (vmx_get_perf_capabilities() & PMU_CAP_LBR_FMT)
    415		debugctl |= DEBUGCTLMSR_LBR_MASK;
    416
    417	return debugctl;
    418}
    419
    420#endif /* __KVM_X86_VMX_CAPS_H */