KVM
Macros | Enumerations | Functions | Variables
hyperv.c File Reference
#include <linux/errno.h>
#include <linux/smp.h>
#include "../cpuid.h"
#include "hyperv.h"
#include "nested.h"
#include "vmcs.h"
#include "vmx.h"
#include "trace.h"
Include dependency graph for hyperv.c:

Go to the source code of this file.

Macros

#define pr_fmt(fmt)   KBUILD_MODNAME ": " fmt
 
#define CC   KVM_NESTED_VMENTER_CONSISTENCY_CHECK
 

Enumerations

enum  evmcs_revision { EVMCSv1_LEGACY , NR_EVMCS_REVISIONS }
 
enum  evmcs_ctrl_type {
  EVMCS_EXIT_CTRLS , EVMCS_ENTRY_CTRLS , EVMCS_EXEC_CTRL , EVMCS_2NDEXEC ,
  EVMCS_3RDEXEC , EVMCS_PINCTRL , EVMCS_VMFUNC , NR_EVMCS_CTRLS
}
 

Functions

u64 nested_get_evmptr (struct kvm_vcpu *vcpu)
 
uint16_t nested_get_evmcs_version (struct kvm_vcpu *vcpu)
 
static u32 evmcs_get_supported_ctls (enum evmcs_ctrl_type ctrl_type)
 
static bool evmcs_has_perf_global_ctrl (struct kvm_vcpu *vcpu)
 
void nested_evmcs_filter_control_msr (struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata)
 
static bool nested_evmcs_is_valid_controls (enum evmcs_ctrl_type ctrl_type, u32 val)
 
int nested_evmcs_check_controls (struct vmcs12 *vmcs12)
 
int nested_enable_evmcs (struct kvm_vcpu *vcpu, uint16_t *vmcs_version)
 
bool nested_evmcs_l2_tlb_flush_enabled (struct kvm_vcpu *vcpu)
 
void vmx_hv_inject_synthetic_vmexit_post_tlb_flush (struct kvm_vcpu *vcpu)
 

Variables

static const u32 evmcs_supported_ctrls [NR_EVMCS_CTRLS][NR_EVMCS_REVISIONS]
 

Macro Definition Documentation

◆ CC

Definition at line 14 of file hyperv.c.

◆ pr_fmt

#define pr_fmt (   fmt)    KBUILD_MODNAME ": " fmt

Definition at line 2 of file hyperv.c.

Enumeration Type Documentation

◆ evmcs_ctrl_type

Enumerator
EVMCS_EXIT_CTRLS 
EVMCS_ENTRY_CTRLS 
EVMCS_EXEC_CTRL 
EVMCS_2NDEXEC 
EVMCS_3RDEXEC 
EVMCS_PINCTRL 
EVMCS_VMFUNC 
NR_EVMCS_CTRLS 

Definition at line 52 of file hyperv.c.

52  {
61 };
@ EVMCS_VMFUNC
Definition: hyperv.c:59
@ NR_EVMCS_CTRLS
Definition: hyperv.c:60
@ EVMCS_PINCTRL
Definition: hyperv.c:58
@ EVMCS_EXEC_CTRL
Definition: hyperv.c:55
@ EVMCS_EXIT_CTRLS
Definition: hyperv.c:53
@ EVMCS_3RDEXEC
Definition: hyperv.c:57
@ EVMCS_ENTRY_CTRLS
Definition: hyperv.c:54
@ EVMCS_2NDEXEC
Definition: hyperv.c:56

◆ evmcs_revision

Enumerator
EVMCSv1_LEGACY 
NR_EVMCS_REVISIONS 

Definition at line 47 of file hyperv.c.

47  {
50 };
@ NR_EVMCS_REVISIONS
Definition: hyperv.c:49
@ EVMCSv1_LEGACY
Definition: hyperv.c:48

Function Documentation

◆ evmcs_get_supported_ctls()

static u32 evmcs_get_supported_ctls ( enum evmcs_ctrl_type  ctrl_type)
static

Definition at line 87 of file hyperv.c.

88 {
89  enum evmcs_revision evmcs_rev = EVMCSv1_LEGACY;
90 
91  return evmcs_supported_ctrls[ctrl_type][evmcs_rev];
92 }
static const u32 evmcs_supported_ctrls[NR_EVMCS_CTRLS][NR_EVMCS_REVISIONS]
Definition: hyperv.c:63
evmcs_revision
Definition: hyperv.c:47
Here is the caller graph for this function:

◆ evmcs_has_perf_global_ctrl()

static bool evmcs_has_perf_global_ctrl ( struct kvm_vcpu *  vcpu)
static

Definition at line 94 of file hyperv.c.

95 {
96  struct kvm_vcpu_hv *hv_vcpu = to_hv_vcpu(vcpu);
97 
98  /*
99  * PERF_GLOBAL_CTRL has a quirk where some Windows guests may fail to
100  * boot if a PV CPUID feature flag is not also set. Treat the fields
101  * as unsupported if the flag is not set in guest CPUID. This should
102  * be called only for guest accesses, and all guest accesses should be
103  * gated on Hyper-V being enabled and initialized.
104  */
105  if (WARN_ON_ONCE(!hv_vcpu))
106  return false;
107 
108  return hv_vcpu->cpuid_cache.nested_ebx & HV_X64_NESTED_EVMCS1_PERF_GLOBAL_CTRL;
109 }
Here is the caller graph for this function:

◆ nested_enable_evmcs()

int nested_enable_evmcs ( struct kvm_vcpu *  vcpu,
uint16_t *  vmcs_version 
)

Definition at line 198 of file hyperv.c.

200 {
201  struct vcpu_vmx *vmx = to_vmx(vcpu);
202 
203  vmx->nested.enlightened_vmcs_enabled = true;
204 
205  if (vmcs_version)
206  *vmcs_version = nested_get_evmcs_version(vcpu);
207 
208  return 0;
209 }
bool enlightened_vmcs_enabled
Definition: vmx.h:186
Definition: vmx.h:251
struct kvm_vcpu vcpu
Definition: vmx.h:252
struct nested_vmx nested
Definition: vmx.h:329
uint16_t nested_get_evmcs_version(struct kvm_vcpu *vcpu)
Definition: hyperv.c:29
static __always_inline struct vcpu_vmx * to_vmx(struct kvm_vcpu *vcpu)
Definition: vmx.h:657
Here is the call graph for this function:

◆ nested_evmcs_check_controls()

int nested_evmcs_check_controls ( struct vmcs12 vmcs12)

Definition at line 161 of file hyperv.c.

162 {
165  return -EINVAL;
166 
169  return -EINVAL;
170 
173  return -EINVAL;
174 
177  return -EINVAL;
178 
181  return -EINVAL;
182 
183  /*
184  * VM-Func controls are 64-bit, but KVM currently doesn't support any
185  * controls in bits 63:32, i.e. dropping those bits on the consistency
186  * check is intentional.
187  */
188  if (WARN_ON_ONCE(vmcs12->vm_function_control >> 32))
189  return -EINVAL;
190 
193  return -EINVAL;
194 
195  return 0;
196 }
Definition: vmcs12.h:27
u32 vm_entry_controls
Definition: vmcs12.h:130
u32 cpu_based_vm_exec_control
Definition: vmcs12.h:122
u32 vm_exit_controls
Definition: vmcs12.h:127
u32 secondary_vm_exec_control
Definition: vmcs12.h:136
u32 pin_based_vm_exec_control
Definition: vmcs12.h:121
u64 vm_function_control
Definition: vmcs12.h:69
static bool nested_evmcs_is_valid_controls(enum evmcs_ctrl_type ctrl_type, u32 val)
Definition: hyperv.c:155
#define CC
Definition: hyperv.c:14
Here is the call graph for this function:
Here is the caller graph for this function:

◆ nested_evmcs_filter_control_msr()

void nested_evmcs_filter_control_msr ( struct kvm_vcpu *  vcpu,
u32  msr_index,
u64 *  pdata 
)

Definition at line 111 of file hyperv.c.

112 {
113  u32 ctl_low = (u32)*pdata;
114  u32 ctl_high = (u32)(*pdata >> 32);
115  u32 supported_ctrls;
116 
117  /*
118  * Hyper-V 2016 and 2019 try using these features even when eVMCS
119  * is enabled but there are no corresponding fields.
120  */
121  switch (msr_index) {
122  case MSR_IA32_VMX_EXIT_CTLS:
123  case MSR_IA32_VMX_TRUE_EXIT_CTLS:
124  supported_ctrls = evmcs_get_supported_ctls(EVMCS_EXIT_CTRLS);
125  if (!evmcs_has_perf_global_ctrl(vcpu))
126  supported_ctrls &= ~VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL;
127  ctl_high &= supported_ctrls;
128  break;
129  case MSR_IA32_VMX_ENTRY_CTLS:
130  case MSR_IA32_VMX_TRUE_ENTRY_CTLS:
131  supported_ctrls = evmcs_get_supported_ctls(EVMCS_ENTRY_CTRLS);
132  if (!evmcs_has_perf_global_ctrl(vcpu))
133  supported_ctrls &= ~VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL;
134  ctl_high &= supported_ctrls;
135  break;
136  case MSR_IA32_VMX_PROCBASED_CTLS:
137  case MSR_IA32_VMX_TRUE_PROCBASED_CTLS:
139  break;
140  case MSR_IA32_VMX_PROCBASED_CTLS2:
142  break;
143  case MSR_IA32_VMX_TRUE_PINBASED_CTLS:
144  case MSR_IA32_VMX_PINBASED_CTLS:
146  break;
147  case MSR_IA32_VMX_VMFUNC:
149  break;
150  }
151 
152  *pdata = ctl_low | ((u64)ctl_high << 32);
153 }
static u32 evmcs_get_supported_ctls(enum evmcs_ctrl_type ctrl_type)
Definition: hyperv.c:87
static bool evmcs_has_perf_global_ctrl(struct kvm_vcpu *vcpu)
Definition: hyperv.c:94
Here is the call graph for this function:
Here is the caller graph for this function:

◆ nested_evmcs_is_valid_controls()

static bool nested_evmcs_is_valid_controls ( enum evmcs_ctrl_type  ctrl_type,
u32  val 
)
static

Definition at line 155 of file hyperv.c.

157 {
158  return !(val & ~evmcs_get_supported_ctls(ctrl_type));
159 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ nested_evmcs_l2_tlb_flush_enabled()

bool nested_evmcs_l2_tlb_flush_enabled ( struct kvm_vcpu *  vcpu)

Definition at line 211 of file hyperv.c.

212 {
213  struct kvm_vcpu_hv *hv_vcpu = to_hv_vcpu(vcpu);
214  struct vcpu_vmx *vmx = to_vmx(vcpu);
215  struct hv_enlightened_vmcs *evmcs = vmx->nested.hv_evmcs;
216 
217  if (!hv_vcpu || !evmcs)
218  return false;
219 
220  if (!evmcs->hv_enlightenments_control.nested_flush_hypercall)
221  return false;
222 
223  return hv_vcpu->vp_assist_page.nested_control.features.directhypercall;
224 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ nested_get_evmcs_version()

uint16_t nested_get_evmcs_version ( struct kvm_vcpu *  vcpu)

Definition at line 29 of file hyperv.c.

30 {
31  /*
32  * vmcs_version represents the range of supported Enlightened VMCS
33  * versions: lower 8 bits is the minimal version, higher 8 bits is the
34  * maximum supported version. KVM supports versions from 1 to
35  * KVM_EVMCS_VERSION.
36  *
37  * Note, do not check the Hyper-V is fully enabled in guest CPUID, this
38  * helper is used to _get_ the vCPU's supported CPUID.
39  */
40  if (kvm_cpu_cap_get(X86_FEATURE_VMX) &&
41  (!vcpu || to_vmx(vcpu)->nested.enlightened_vmcs_enabled))
42  return (KVM_EVMCS_VERSION << 8) | 1;
43 
44  return 0;
45 }
static __always_inline u32 kvm_cpu_cap_get(unsigned int x86_feature)
Definition: cpuid.h:213
#define KVM_EVMCS_VERSION
Definition: hyperv_evmcs.h:14
static int nested
Definition: svm.c:202
Here is the call graph for this function:
Here is the caller graph for this function:

◆ nested_get_evmptr()

u64 nested_get_evmptr ( struct kvm_vcpu *  vcpu)

Definition at line 16 of file hyperv.c.

17 {
18  struct kvm_vcpu_hv *hv_vcpu = to_hv_vcpu(vcpu);
19 
20  if (unlikely(kvm_hv_get_assist_page(vcpu)))
21  return EVMPTR_INVALID;
22 
23  if (unlikely(!hv_vcpu->vp_assist_page.enlighten_vmentry))
24  return EVMPTR_INVALID;
25 
26  return hv_vcpu->vp_assist_page.current_nested_vmcs;
27 }
int kvm_hv_get_assist_page(struct kvm_vcpu *vcpu)
Definition: hyperv.c:924
#define EVMPTR_INVALID
Definition: hyperv.h:9
Here is the call graph for this function:
Here is the caller graph for this function:

◆ vmx_hv_inject_synthetic_vmexit_post_tlb_flush()

void vmx_hv_inject_synthetic_vmexit_post_tlb_flush ( struct kvm_vcpu *  vcpu)

Definition at line 226 of file hyperv.c.

227 {
228  nested_vmx_vmexit(vcpu, HV_VMX_SYNTHETIC_EXIT_REASON_TRAP_AFTER_FLUSH, 0, 0);
229 }
void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 vm_exit_reason, u32 exit_intr_info, unsigned long exit_qualification)
Definition: nested.c:4767
Here is the call graph for this function:

Variable Documentation

◆ evmcs_supported_ctrls

const u32 evmcs_supported_ctrls[NR_EVMCS_CTRLS][NR_EVMCS_REVISIONS]
static
Initial value:
= {
},
},
},
[EVMCSv1_LEGACY] = EVMCS1_SUPPORTED_2NDEXEC & ~SECONDARY_EXEC_TSC_SCALING,
},
},
},
},
}
#define EVMCS1_SUPPORTED_2NDEXEC
Definition: hyperv_evmcs.h:72
#define EVMCS1_SUPPORTED_VMFUNC
Definition: hyperv_evmcs.h:119
#define EVMCS1_SUPPORTED_3RDEXEC
Definition: hyperv_evmcs.h:92
#define EVMCS1_SUPPORTED_EXEC_CTRL
Definition: hyperv_evmcs.h:48
#define EVMCS1_SUPPORTED_PINCTRL
Definition: hyperv_evmcs.h:42
#define EVMCS1_SUPPORTED_VMEXIT_CTRL
Definition: hyperv_evmcs.h:94
#define EVMCS1_SUPPORTED_VMENTRY_CTRL
Definition: hyperv_evmcs.h:108

Definition at line 63 of file hyperv.c.