diff --git a/arch/x86/kvm/vmx/evmcs.c b/arch/x86/kvm/vmx/evmcs.c
index 47f6d1cbd428..89d7b9537ada 100644
--- a/arch/x86/kvm/vmx/evmcs.c
+++ b/arch/x86/kvm/vmx/evmcs.c
@@ -1,5 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 
+#define pr_fmt(fmt) "kvm/hyper-v: " fmt
+
 #include <linux/errno.h>
 #include <linux/smp.h>
 
@@ -362,6 +364,7 @@ uint16_t nested_get_evmcs_version(struct kvm_vcpu *vcpu)
 
 enum evmcs_revision {
 	EVMCSv1_LEGACY,
+	EVMCSv1_STRICT,
 	NR_EVMCS_REVISIONS,
 };
 
@@ -379,31 +382,36 @@ enum evmcs_ctrl_type {
 static const u32 evmcs_supported_ctrls[NR_EVMCS_CTRLS][NR_EVMCS_REVISIONS] = {
 	[EVMCS_EXIT_CTRLS] = {
 		[EVMCSv1_LEGACY] = EVMCS1_SUPPORTED_VMEXIT_CTRL,
+		[EVMCSv1_STRICT] = EVMCS1_SUPPORTED_VMEXIT_CTRL,
 	},
 	[EVMCS_ENTRY_CTRLS] = {
 		[EVMCSv1_LEGACY] = EVMCS1_SUPPORTED_VMENTRY_CTRL,
+		[EVMCSv1_STRICT] = EVMCS1_SUPPORTED_VMENTRY_CTRL,
 	},
 	[EVMCS_EXEC_CTRL] = {
 		[EVMCSv1_LEGACY] = EVMCS1_SUPPORTED_EXEC_CTRL,
+		[EVMCSv1_STRICT] = EVMCS1_SUPPORTED_EXEC_CTRL,
 	},
 	[EVMCS_2NDEXEC] = {
 		[EVMCSv1_LEGACY] = EVMCS1_SUPPORTED_2NDEXEC & ~SECONDARY_EXEC_TSC_SCALING,
+		[EVMCSv1_STRICT] = EVMCS1_SUPPORTED_2NDEXEC,
 	},
 	[EVMCS_3RDEXEC] = {
 		[EVMCSv1_LEGACY] = EVMCS1_SUPPORTED_3RDEXEC,
 	},
 	[EVMCS_PINCTRL] = {
 		[EVMCSv1_LEGACY] = EVMCS1_SUPPORTED_PINCTRL,
+		[EVMCSv1_STRICT] = EVMCS1_SUPPORTED_PINCTRL,
 	},
 	[EVMCS_VMFUNC] = {
 		[EVMCSv1_LEGACY] = EVMCS1_SUPPORTED_VMFUNC,
+		[EVMCSv1_STRICT] = EVMCS1_SUPPORTED_VMFUNC,
 	},
 };
 
-static u32 evmcs_get_supported_ctls(enum evmcs_ctrl_type ctrl_type)
+static u32 evmcs_get_supported_ctls(enum evmcs_ctrl_type ctrl_type,
+				    enum evmcs_revision evmcs_rev)
 {
-	enum evmcs_revision evmcs_rev = EVMCSv1_LEGACY;
-
 	return evmcs_supported_ctrls[ctrl_type][evmcs_rev];
 }
 
@@ -437,31 +445,37 @@ void nested_evmcs_filter_control_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *
 	switch (msr_index) {
 	case MSR_IA32_VMX_EXIT_CTLS:
 	case MSR_IA32_VMX_TRUE_EXIT_CTLS:
-		supported_ctrls = evmcs_get_supported_ctls(EVMCS_EXIT_CTRLS);
+		supported_ctrls = evmcs_get_supported_ctls(EVMCS_EXIT_CTRLS,
+							   EVMCSv1_LEGACY);
 		if (!evmcs_has_perf_global_ctrl(vcpu))
 			supported_ctrls &= ~VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL;
 		ctl_high &= supported_ctrls;
 		break;
 	case MSR_IA32_VMX_ENTRY_CTLS:
 	case MSR_IA32_VMX_TRUE_ENTRY_CTLS:
-		supported_ctrls = evmcs_get_supported_ctls(EVMCS_ENTRY_CTRLS);
+		supported_ctrls = evmcs_get_supported_ctls(EVMCS_ENTRY_CTRLS,
+							   EVMCSv1_LEGACY);
 		if (!evmcs_has_perf_global_ctrl(vcpu))
 			supported_ctrls &= ~VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL;
 		ctl_high &= supported_ctrls;
 		break;
 	case MSR_IA32_VMX_PROCBASED_CTLS:
 	case MSR_IA32_VMX_TRUE_PROCBASED_CTLS:
-		ctl_high &= evmcs_get_supported_ctls(EVMCS_EXEC_CTRL);
+		ctl_high &= evmcs_get_supported_ctls(EVMCS_EXEC_CTRL,
+						     EVMCSv1_LEGACY);
 		break;
 	case MSR_IA32_VMX_PROCBASED_CTLS2:
-		ctl_high &= evmcs_get_supported_ctls(EVMCS_2NDEXEC);
+		ctl_high &= evmcs_get_supported_ctls(EVMCS_2NDEXEC,
+						     EVMCSv1_LEGACY);
 		break;
 	case MSR_IA32_VMX_TRUE_PINBASED_CTLS:
 	case MSR_IA32_VMX_PINBASED_CTLS:
-		ctl_high &= evmcs_get_supported_ctls(EVMCS_PINCTRL);
+		ctl_high &= evmcs_get_supported_ctls(EVMCS_PINCTRL,
+						     EVMCSv1_LEGACY);
 		break;
 	case MSR_IA32_VMX_VMFUNC:
-		ctl_low &= evmcs_get_supported_ctls(EVMCS_VMFUNC);
+		ctl_low &= evmcs_get_supported_ctls(EVMCS_VMFUNC,
+						    EVMCSv1_LEGACY);
 		break;
 	}
 
@@ -471,7 +485,7 @@ void nested_evmcs_filter_control_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *
 static bool nested_evmcs_is_valid_controls(enum evmcs_ctrl_type ctrl_type,
 					   u32 val)
 {
-	return !(val & ~evmcs_get_supported_ctls(ctrl_type));
+	return !(val & ~evmcs_get_supported_ctls(ctrl_type, EVMCSv1_LEGACY));
 }
 
 int nested_evmcs_check_controls(struct vmcs12 *vmcs12)
@@ -511,6 +525,52 @@ int nested_evmcs_check_controls(struct vmcs12 *vmcs12)
 	return 0;
 }
 
+#if IS_ENABLED(CONFIG_HYPERV)
+/*
+ * KVM on Hyper-V always uses the newest known eVMCSv1 revision, the assumption
+ * is: in case a feature has corresponding fields in eVMCS described and it was
+ * exposed in VMX feature MSRs, KVM is free to use it. Warn if KVM meets a
+ * feature which has no corresponding eVMCS field, this likely means that KVM
+ * needs to be updated.
+ */
+#define evmcs_check_vmcs_conf32(field, ctrl)					\
+	{									\
+		u32 supported, unsupported32;					\
+										\
+		supported = evmcs_get_supported_ctls(ctrl, EVMCSv1_STRICT);	\
+		unsupported32 = vmcs_conf->field & ~supported;			\
+		if (unsupported32) {						\
+			pr_warn_once(#field " unsupported with eVMCS: 0x%x\n",	\
+				     unsupported32);				\
+			vmcs_conf->field &= supported;				\
+		}								\
+	}
+
+#define evmcs_check_vmcs_conf64(field, ctrl)					\
+	{									\
+		u32 supported;							\
+		u64 unsupported64;						\
+										\
+		supported = evmcs_get_supported_ctls(ctrl, EVMCSv1_STRICT);	\
+		unsupported64 = vmcs_conf->field & ~supported;			\
+		if (unsupported64) {						\
+			pr_warn_once(#field " unsupported with eVMCS: 0x%llx\n",\
+				     unsupported64);				\
+			vmcs_conf->field &= supported;				\
+		}								\
+	}
+
+__init void evmcs_sanitize_exec_ctrls(struct vmcs_config *vmcs_conf)
+{
+	evmcs_check_vmcs_conf32(cpu_based_exec_ctrl, EVMCS_EXEC_CTRL);
+	evmcs_check_vmcs_conf32(pin_based_exec_ctrl, EVMCS_PINCTRL);
+	evmcs_check_vmcs_conf32(cpu_based_2nd_exec_ctrl, EVMCS_2NDEXEC);
+	evmcs_check_vmcs_conf64(cpu_based_3rd_exec_ctrl, EVMCS_3RDEXEC);
+	evmcs_check_vmcs_conf32(vmentry_ctrl, EVMCS_ENTRY_CTRLS);
+	evmcs_check_vmcs_conf32(vmexit_ctrl, EVMCS_EXIT_CTRLS);
+}
+#endif
+
 int nested_enable_evmcs(struct kvm_vcpu *vcpu,
 			uint16_t *vmcs_version)
 {
diff --git a/arch/x86/kvm/vmx/evmcs.h b/arch/x86/kvm/vmx/evmcs.h
index 205b5b467617..300e50d52042 100644
--- a/arch/x86/kvm/vmx/evmcs.h
+++ b/arch/x86/kvm/vmx/evmcs.h
@@ -271,6 +271,7 @@ static inline void evmcs_load(u64 phys_addr)
 	vp_ap->enlighten_vmentry = 1;
 }
 
+__init void evmcs_sanitize_exec_ctrls(struct vmcs_config *vmcs_conf);
 #else /* !IS_ENABLED(CONFIG_HYPERV) */
 static __always_inline void evmcs_write64(unsigned long field, u64 value) {}
 static inline void evmcs_write32(unsigned long field, u32 value) {}
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index 9dba04b6b019..7fd21b1fae1d 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -2720,6 +2720,11 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf,
 	vmcs_conf->vmentry_ctrl        = _vmentry_control;
 	vmcs_conf->misc	= misc_msr;
 
+#if IS_ENABLED(CONFIG_HYPERV)
+	if (enlightened_vmcs)
+		evmcs_sanitize_exec_ctrls(vmcs_conf);
+#endif
+
 	return 0;
 }
 
