Messages in this thread Patch in this message | | | Date | Tue, 17 May 2022 08:59:04 +0800 | Subject | Re: [PATCH v6 3/3] KVM: VMX: Enable Notify VM exit | From | Chenyi Qiang <> |
| |
On 4/21/2022 3:29 PM, Chenyi Qiang wrote: > From: Tao Xu <tao3.xu@intel.com> > > There are cases that malicious virtual machines can cause CPU stuck (due > to event windows don't open up), e.g., infinite loop in microcode when > nested #AC (CVE-2015-5307). No event window means no event (NMI, SMI and > IRQ) can be delivered. It leads the CPU to be unavailable to host or > other VMs. > > VMM can enable notify VM exit that a VM exit generated if no event > window occurs in VM non-root mode for a specified amount of time (notify > window). > > Feature enabling: > - The new vmcs field SECONDARY_EXEC_NOTIFY_VM_EXITING is introduced to > enable this feature. VMM can set NOTIFY_WINDOW vmcs field to adjust > the expected notify window. > - Add a new KVM capability KVM_CAP_X86_NOTIFY_VMEXIT so that user space > can query and enable this feature in per-VM scope. The argument is a > 64bit value: bits 63:32 are used for notify window, and bits 31:0 are > for flags. Current supported flags: > - KVM_X86_NOTIFY_VMEXIT_ENABLED: enable the feature with the notify > window provided. > - KVM_X86_NOTIFY_VMEXIT_USER: exit to userspace once the exits happen. > - It's safe to even set notify window to zero since an internal hardware > threshold is added to vmcs.notify_window. > > VM exit handling: > - Introduce a vcpu state notify_window_exits to records the count of > notify VM exits and expose it through the debugfs. > - Notify VM exit can happen incident to delivery of a vector event. > Allow it in KVM. > - Exit to userspace unconditionally for handling when VM_CONTEXT_INVALID > bit is set. > > Nested handling > - Nested notify VM exits are not supported yet. Keep the same notify > window control in vmcs02 as vmcs01, so that L1 can't escape the > restriction of notify VM exits through launching L2 VM. > - When L2 VM is context invalid and user space should synthesize a shutdown > event to a vcpu. KVM makes KVM_REQ_TRIPLE_FAULT request accordingly > and it would synthesize a nested triple fault exit to L1 hypervisor to > kill L2. > > Notify VM exit is defined in latest Intel Architecture Instruction Set > Extensions Programming Reference, chapter 9.2. > > Co-developed-by: Xiaoyao Li <xiaoyao.li@intel.com> > Signed-off-by: Xiaoyao Li <xiaoyao.li@intel.com> > Signed-off-by: Tao Xu <tao3.xu@intel.com> > Co-developed-by: Chenyi Qiang <chenyi.qiang@intel.com> > Signed-off-by: Chenyi Qiang <chenyi.qiang@intel.com> > --- > Documentation/virt/kvm/api.rst | 48 ++++++++++++++++++++++++++++++ > arch/x86/include/asm/kvm_host.h | 9 ++++++ > arch/x86/include/asm/vmx.h | 7 +++++ > arch/x86/include/asm/vmxfeatures.h | 1 + > arch/x86/include/uapi/asm/vmx.h | 4 ++- > arch/x86/kvm/vmx/capabilities.h | 6 ++++ > arch/x86/kvm/vmx/nested.c | 8 +++++ > arch/x86/kvm/vmx/vmx.c | 48 ++++++++++++++++++++++++++++-- > arch/x86/kvm/x86.c | 18 ++++++++++- > arch/x86/kvm/x86.h | 5 ++++ > include/uapi/linux/kvm.h | 10 +++++++ > 11 files changed, 159 insertions(+), 5 deletions(-) > > diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst > index e09ce3cb49c5..821ca979234d 100644 > --- a/Documentation/virt/kvm/api.rst > +++ b/Documentation/virt/kvm/api.rst > @@ -6321,6 +6321,26 @@ array field represents return values. The userspace should update the return > values of SBI call before resuming the VCPU. For more details on RISC-V SBI > spec refer, https://github.com/riscv/riscv-sbi-doc. > > +:: > + > + /* KVM_EXIT_NOTIFY */ > + struct { > + #define KVM_NOTIFY_CONTEXT_INVALID (1 << 0) > + __u32 flags; > + } notify; > + > +Used on x86 systems. When the VM capability KVM_CAP_X86_NOTIFY_VMEXIT is > +enabled, a VM exit generated if no event window occurs in VM non-root mode > +for a specified amount of time. Once KVM_X86_NOTIFY_VMEXIT_USER is set when > +enabling the cap, it would exit to userspace with the exit reason > +KVM_EXIT_NOTIFY for further handling. The "flags" field contains more > +detailed info. > + > +The valid value for 'data' is: > + > + - KVM_NOTIFY_CONTEXT_INVALID -- the VM context is corrupted and not valid > + in VMCS. It would run into unknown result if resume the target VM. > + > :: > > /* Fix the size of the union. */ > @@ -7266,6 +7286,34 @@ The valid bits in cap.args[0] are: > generate a #UD within the guest. > =================================== ============================================ > > +7.31 KVM_CAP_X86_NOTIFY_VMEXIT > +------------------------------ > + > +:Architectures: x86 > +:Target: VM > +:Parameters: args[0] is the value of notify window as well as some flags > +:Returns: 0 on success, -EINVAL if hardware doesn't support notify VM exit. > + > +Bits 63:32 of args[0] are used for notify window. > +Bits 31:0 of args[0] are for some flags. Valid bits are:: > + > + #define KVM_X86_NOTIFY_VMEXIT_ENABLED (1 << 0) > + #define KVM_X86_NOTIFY_VMEXIT_USER (1 << 1) > + > +This capability allows userspace to configure the notify VM exit on/off > +in per-VM scope during VM creation. Notify VM exit is disabled by default. > +When userspace sets KVM_X86_NOTIFY_VMEXIT_ENABLED bit in args[0], VMM would > +enable this feature with the notify window provided, which will generate > +a VM exit if no event window occurs in VM non-root mode for a specified of > +time (notify window). > + > +If KVM_X86_NOTIFY_VMEXIT_USER is set in args[0], upon notify VM exits happen, > +KVM would exit to userspace for handling. > + > +This capability is aimed to mitigate the threat that malicious VMs can > +cause CPU stuck (due to event windows don't open up) and make the CPU > +unavailable to host or other VMs. > + > 8. Other capabilities. > ====================== > > diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h > index 2c20f715f009..28a42658eec5 100644 > --- a/arch/x86/include/asm/kvm_host.h > +++ b/arch/x86/include/asm/kvm_host.h > @@ -65,6 +65,9 @@ > #define KVM_BUS_LOCK_DETECTION_VALID_MODE (KVM_BUS_LOCK_DETECTION_OFF | \ > KVM_BUS_LOCK_DETECTION_EXIT) > > +#define KVM_X86_NOTIFY_VMEXIT_VALID_BITS (KVM_X86_NOTIFY_VMEXIT_ENABLED | \ > + KVM_X86_NOTIFY_VMEXIT_USER) > + > /* x86-specific vcpu->requests bit members */ > #define KVM_REQ_MIGRATE_TIMER KVM_ARCH_REQ(0) > #define KVM_REQ_REPORT_TPR_ACCESS KVM_ARCH_REQ(1) > @@ -1157,6 +1160,9 @@ struct kvm_arch { > > bool bus_lock_detection_enabled; > bool enable_pmu; > + > + u32 notify_window; > + u32 notify_vmexit_flags; > /* > * If exit_on_emulation_error is set, and the in-kernel instruction > * emulator fails to emulate an instruction, allow userspace > @@ -1293,6 +1299,7 @@ struct kvm_vcpu_stat { > u64 directed_yield_attempted; > u64 directed_yield_successful; > u64 guest_mode; > + u64 notify_window_exits; > }; > > struct x86_instruction_info; > @@ -1504,6 +1511,8 @@ struct kvm_x86_ops { > * Returns vCPU specific APICv inhibit reasons > */ > unsigned long (*vcpu_get_apicv_inhibit_reasons)(struct kvm_vcpu *vcpu); > + > + bool has_notify_vmexit; > }; > > struct kvm_x86_nested_ops { > diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h > index 6c343c6a1855..2aa266007873 100644 > --- a/arch/x86/include/asm/vmx.h > +++ b/arch/x86/include/asm/vmx.h > @@ -74,6 +74,7 @@ > #define SECONDARY_EXEC_TSC_SCALING VMCS_CONTROL_BIT(TSC_SCALING) > #define SECONDARY_EXEC_ENABLE_USR_WAIT_PAUSE VMCS_CONTROL_BIT(USR_WAIT_PAUSE) > #define SECONDARY_EXEC_BUS_LOCK_DETECTION VMCS_CONTROL_BIT(BUS_LOCK_DETECTION) > +#define SECONDARY_EXEC_NOTIFY_VM_EXITING VMCS_CONTROL_BIT(NOTIFY_VM_EXITING) > > #define PIN_BASED_EXT_INTR_MASK VMCS_CONTROL_BIT(INTR_EXITING) > #define PIN_BASED_NMI_EXITING VMCS_CONTROL_BIT(NMI_EXITING) > @@ -269,6 +270,7 @@ enum vmcs_field { > SECONDARY_VM_EXEC_CONTROL = 0x0000401e, > PLE_GAP = 0x00004020, > PLE_WINDOW = 0x00004022, > + NOTIFY_WINDOW = 0x00004024, > VM_INSTRUCTION_ERROR = 0x00004400, > VM_EXIT_REASON = 0x00004402, > VM_EXIT_INTR_INFO = 0x00004404, > @@ -553,6 +555,11 @@ enum vm_entry_failure_code { > #define EPT_VIOLATION_GVA_IS_VALID (1 << EPT_VIOLATION_GVA_IS_VALID_BIT) > #define EPT_VIOLATION_GVA_TRANSLATED (1 << EPT_VIOLATION_GVA_TRANSLATED_BIT) > > +/* > + * Exit Qualifications for NOTIFY VM EXIT > + */ > +#define NOTIFY_VM_CONTEXT_INVALID BIT(0) > + > /* > * VM-instruction error numbers > */ > diff --git a/arch/x86/include/asm/vmxfeatures.h b/arch/x86/include/asm/vmxfeatures.h > index d9a74681a77d..15f0f2ab4f95 100644 > --- a/arch/x86/include/asm/vmxfeatures.h > +++ b/arch/x86/include/asm/vmxfeatures.h > @@ -84,5 +84,6 @@ > #define VMX_FEATURE_USR_WAIT_PAUSE ( 2*32+ 26) /* Enable TPAUSE, UMONITOR, UMWAIT in guest */ > #define VMX_FEATURE_ENCLV_EXITING ( 2*32+ 28) /* "" VM-Exit on ENCLV (leaf dependent) */ > #define VMX_FEATURE_BUS_LOCK_DETECTION ( 2*32+ 30) /* "" VM-Exit when bus lock caused */ > +#define VMX_FEATURE_NOTIFY_VM_EXITING ( 2*32+ 31) /* VM-Exit when no event windows after notify window */ > > #endif /* _ASM_X86_VMXFEATURES_H */ > diff --git a/arch/x86/include/uapi/asm/vmx.h b/arch/x86/include/uapi/asm/vmx.h > index 946d761adbd3..a5faf6d88f1b 100644 > --- a/arch/x86/include/uapi/asm/vmx.h > +++ b/arch/x86/include/uapi/asm/vmx.h > @@ -91,6 +91,7 @@ > #define EXIT_REASON_UMWAIT 67 > #define EXIT_REASON_TPAUSE 68 > #define EXIT_REASON_BUS_LOCK 74 > +#define EXIT_REASON_NOTIFY 75 > > #define VMX_EXIT_REASONS \ > { EXIT_REASON_EXCEPTION_NMI, "EXCEPTION_NMI" }, \ > @@ -153,7 +154,8 @@ > { EXIT_REASON_XRSTORS, "XRSTORS" }, \ > { EXIT_REASON_UMWAIT, "UMWAIT" }, \ > { EXIT_REASON_TPAUSE, "TPAUSE" }, \ > - { EXIT_REASON_BUS_LOCK, "BUS_LOCK" } > + { EXIT_REASON_BUS_LOCK, "BUS_LOCK" }, \ > + { EXIT_REASON_NOTIFY, "NOTIFY" } > > #define VMX_EXIT_REASON_FLAGS \ > { VMX_EXIT_REASONS_FAILED_VMENTRY, "FAILED_VMENTRY" } > diff --git a/arch/x86/kvm/vmx/capabilities.h b/arch/x86/kvm/vmx/capabilities.h > index 3f430e218375..0102a6e8a194 100644 > --- a/arch/x86/kvm/vmx/capabilities.h > +++ b/arch/x86/kvm/vmx/capabilities.h > @@ -417,4 +417,10 @@ static inline u64 vmx_supported_debugctl(void) > return debugctl; > } > > +static inline bool cpu_has_notify_vmexit(void) > +{ > + return vmcs_config.cpu_based_2nd_exec_ctrl & > + SECONDARY_EXEC_NOTIFY_VM_EXITING; > +} > + > #endif /* __KVM_X86_VMX_CAPS_H */ > diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c > index a6688663da4d..5f74aae96031 100644 > --- a/arch/x86/kvm/vmx/nested.c > +++ b/arch/x86/kvm/vmx/nested.c > @@ -2133,6 +2133,8 @@ static u64 nested_vmx_calc_efer(struct vcpu_vmx *vmx, struct vmcs12 *vmcs12) > > static void prepare_vmcs02_constant_state(struct vcpu_vmx *vmx) > { > + struct kvm *kvm = vmx->vcpu.kvm; > + > /* > * If vmcs02 hasn't been initialized, set the constant vmcs02 state > * according to L0's settings (vmcs12 is irrelevant here). Host > @@ -2175,6 +2177,9 @@ static void prepare_vmcs02_constant_state(struct vcpu_vmx *vmx) > if (cpu_has_vmx_encls_vmexit()) > vmcs_write64(ENCLS_EXITING_BITMAP, INVALID_GPA); > > + if (kvm_notify_vmexit_enabled(kvm)) > + vmcs_write32(NOTIFY_WINDOW, kvm->arch.notify_window); > + > /* > * Set the MSR load/store lists to match L0's settings. Only the > * addresses are constant (for vmcs02), the counts can change based > @@ -6107,6 +6112,9 @@ static bool nested_vmx_l1_wants_exit(struct kvm_vcpu *vcpu, > SECONDARY_EXEC_ENABLE_USR_WAIT_PAUSE); > case EXIT_REASON_ENCLS: > return nested_vmx_exit_handled_encls(vcpu, vmcs12); > + case EXIT_REASON_NOTIFY: > + /* Notify VM exit is not exposed to L1 */ > + return false; > default: > return true; > } > diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c > index cf8581978bce..4ecfca00ff9e 100644 > --- a/arch/x86/kvm/vmx/vmx.c > +++ b/arch/x86/kvm/vmx/vmx.c > @@ -2472,7 +2472,8 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf, > SECONDARY_EXEC_PT_USE_GPA | > SECONDARY_EXEC_PT_CONCEAL_VMX | > SECONDARY_EXEC_ENABLE_VMFUNC | > - SECONDARY_EXEC_BUS_LOCK_DETECTION; > + SECONDARY_EXEC_BUS_LOCK_DETECTION | > + SECONDARY_EXEC_NOTIFY_VM_EXITING; > if (cpu_has_sgx()) > opt2 |= SECONDARY_EXEC_ENCLS_EXITING; > if (adjust_vmx_controls(min2, opt2, > @@ -4357,6 +4358,9 @@ static u32 vmx_secondary_exec_control(struct vcpu_vmx *vmx) > if (!vcpu->kvm->arch.bus_lock_detection_enabled) > exec_control &= ~SECONDARY_EXEC_BUS_LOCK_DETECTION; > > + if (!kvm_notify_vmexit_enabled(vcpu->kvm)) > + exec_control &= ~SECONDARY_EXEC_NOTIFY_VM_EXITING; > + > return exec_control; > } > > @@ -4364,6 +4368,8 @@ static u32 vmx_secondary_exec_control(struct vcpu_vmx *vmx) > > static void init_vmcs(struct vcpu_vmx *vmx) > { > + struct kvm *kvm = vmx->vcpu.kvm; > + > if (nested) > nested_vmx_set_vmcs_shadowing_bitmap(); > > @@ -4392,12 +4398,15 @@ static void init_vmcs(struct vcpu_vmx *vmx) > vmcs_write64(POSTED_INTR_DESC_ADDR, __pa((&vmx->pi_desc))); > } > > - if (!kvm_pause_in_guest(vmx->vcpu.kvm)) { > + if (!kvm_pause_in_guest(kvm)) { > vmcs_write32(PLE_GAP, ple_gap); > vmx->ple_window = ple_window; > vmx->ple_window_dirty = true; > } > > + if (kvm_notify_vmexit_enabled(kvm)) > + vmcs_write32(NOTIFY_WINDOW, kvm->arch.notify_window); > + > vmcs_write32(PAGE_FAULT_ERROR_CODE_MASK, 0); > vmcs_write32(PAGE_FAULT_ERROR_CODE_MATCH, 0); > vmcs_write32(CR3_TARGET_COUNT, 0); /* 22.2.1 */ > @@ -5684,6 +5693,32 @@ static int handle_bus_lock_vmexit(struct kvm_vcpu *vcpu) > return 1; > } > > +static int handle_notify(struct kvm_vcpu *vcpu) > +{ > + unsigned long exit_qual = vmx_get_exit_qual(vcpu); > + bool context_invalid = exit_qual & NOTIFY_VM_CONTEXT_INVALID; > + > + ++vcpu->stat.notify_window_exits; > + > + /* > + * Notify VM exit happened while executing iret from NMI, > + * "blocked by NMI" bit has to be set before next VM entry. > + */ > + if (enable_vnmi && (exit_qual & INTR_INFO_UNBLOCK_NMI)) > + vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO, > + GUEST_INTR_STATE_NMI); > + > + if (vcpu->kvm->arch.notify_vmexit_flags & KVM_X86_NOTIFY_VMEXIT_USER || > + context_invalid) { > + vcpu->run->exit_reason = KVM_EXIT_NOTIFY; > + vcpu->run->notify.flags = context_invalid ? > + KVM_NOTIFY_CONTEXT_INVALID : 0; > + return 0; > + } > + > + return 1; > +} > + > /* > * The exit handlers return 1 if the exit was handled fully and guest execution > * may resume. Otherwise they set the kvm_run parameter to indicate what needs > @@ -5741,6 +5776,7 @@ static int (*kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu) = { > [EXIT_REASON_PREEMPTION_TIMER] = handle_preemption_timer, > [EXIT_REASON_ENCLS] = handle_encls, > [EXIT_REASON_BUS_LOCK] = handle_bus_lock_vmexit, > + [EXIT_REASON_NOTIFY] = handle_notify, > }; > > static const int kvm_vmx_max_exit_handlers = > @@ -6105,7 +6141,8 @@ static int __vmx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t exit_fastpath) > exit_reason.basic != EXIT_REASON_EPT_VIOLATION && > exit_reason.basic != EXIT_REASON_PML_FULL && > exit_reason.basic != EXIT_REASON_APIC_ACCESS && > - exit_reason.basic != EXIT_REASON_TASK_SWITCH)) { > + exit_reason.basic != EXIT_REASON_TASK_SWITCH && > + exit_reason.basic != EXIT_REASON_NOTIFY)) { > int ndata = 3; > > vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR; > @@ -7841,6 +7878,8 @@ static struct kvm_x86_ops vmx_x86_ops __initdata = { > .complete_emulated_msr = kvm_complete_insn_gp, > > .vcpu_deliver_sipi_vector = kvm_vcpu_deliver_sipi_vector, > + > + .has_notify_vmexit = false, > }; > > static unsigned int vmx_handle_intel_pt_intr(void) > @@ -7979,6 +8018,9 @@ static __init int hardware_setup(void) > kvm_tsc_scaling_ratio_frac_bits = 48; > kvm_has_bus_lock_exit = cpu_has_vmx_bus_lock_detection(); > > + if (cpu_has_notify_vmexit()) > + vmx_x86_ops.has_notify_vmexit = true; > + > set_bit(0, vmx_vpid_bitmap); /* 0 is reserved for host */ > > if (enable_ept) > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c > index c8b9b0bc42aa..ad8a05349614 100644 > --- a/arch/x86/kvm/x86.c > +++ b/arch/x86/kvm/x86.c > @@ -291,7 +291,8 @@ const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = { > STATS_DESC_COUNTER(VCPU, nested_run), > STATS_DESC_COUNTER(VCPU, directed_yield_attempted), > STATS_DESC_COUNTER(VCPU, directed_yield_successful), > - STATS_DESC_ICOUNTER(VCPU, guest_mode) > + STATS_DESC_ICOUNTER(VCPU, guest_mode), > + STATS_DESC_COUNTER(VCPU, notify_window_exits), > }; > > const struct kvm_stats_header kvm_vcpu_stats_header = { > @@ -4389,6 +4390,9 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) > case KVM_CAP_DISABLE_QUIRKS2: > r = KVM_X86_VALID_QUIRKS; > break; > + case KVM_CAP_X86_NOTIFY_VMEXIT: > + r = kvm_x86_ops.has_notify_vmexit; > + break; > default: > break; > } > @@ -6090,6 +6094,18 @@ int kvm_vm_ioctl_enable_cap(struct kvm *kvm, > } > mutex_unlock(&kvm->lock); > break; > + case KVM_CAP_X86_NOTIFY_VMEXIT: > + r = -EINVAL; > + if ((u32)cap->args[0] & ~KVM_X86_NOTIFY_VMEXIT_VALID_BITS) > + break; > + if (!kvm_x86_ops.has_notify_vmexit) > + break; > + if (!(u32)cap->args[0] & KVM_X86_NOTIFY_VMEXIT_ENABLED)
Miss the parentheses here, should be !((u32)cap->args[0] & KVM_X86_NOTIFY_VMEXIT_ENABLED)
> + break; > + kvm->arch.notify_window = cap->args[0] >> 32; > + kvm->arch.notify_vmexit_flags = (u32)cap->args[0]; > + r = 0; > + break; > default: > r = -EINVAL; > break; > diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h > index 588792f00334..6e1e2159cbd4 100644 > --- a/arch/x86/kvm/x86.h > +++ b/arch/x86/kvm/x86.h > @@ -344,6 +344,11 @@ static inline bool kvm_cstate_in_guest(struct kvm *kvm) > return kvm->arch.cstate_in_guest; > } > > +static inline bool kvm_notify_vmexit_enabled(struct kvm *kvm) > +{ > + return kvm->arch.notify_vmexit_flags & KVM_X86_NOTIFY_VMEXIT_ENABLED; > +} > + > enum kvm_intr_type { > /* Values are arbitrary, but must be non-zero. */ > KVM_HANDLING_IRQ = 1, > diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h > index dd1d8167e71f..86f1ca9c1514 100644 > --- a/include/uapi/linux/kvm.h > +++ b/include/uapi/linux/kvm.h > @@ -270,6 +270,7 @@ struct kvm_xen_exit { > #define KVM_EXIT_X86_BUS_LOCK 33 > #define KVM_EXIT_XEN 34 > #define KVM_EXIT_RISCV_SBI 35 > +#define KVM_EXIT_NOTIFY 36 > > /* For KVM_EXIT_INTERNAL_ERROR */ > /* Emulate instruction failed. */ > @@ -490,6 +491,11 @@ struct kvm_run { > unsigned long args[6]; > unsigned long ret[2]; > } riscv_sbi; > + /* KVM_EXIT_NOTIFY */ > + struct { > +#define KVM_NOTIFY_CONTEXT_INVALID (1 << 0) > + __u32 flags; > + } notify; > /* Fix the size of the union. */ > char padding[256]; > }; > @@ -1148,6 +1154,7 @@ struct kvm_ppc_resize_hpt { > #define KVM_CAP_PMU_CAPABILITY 212 > #define KVM_CAP_DISABLE_QUIRKS2 213 > #define KVM_CAP_VM_TSC_CONTROL 214 > +#define KVM_CAP_X86_NOTIFY_VMEXIT 215 > > #ifdef KVM_CAP_IRQ_ROUTING > > @@ -2109,4 +2116,7 @@ struct kvm_stats_desc { > /* Available with KVM_CAP_XSAVE2 */ > #define KVM_GET_XSAVE2 _IOR(KVMIO, 0xcf, struct kvm_xsave) > > +#define KVM_X86_NOTIFY_VMEXIT_ENABLED (1ULL << 0) > +#define KVM_X86_NOTIFY_VMEXIT_USER (1ULL << 1) > + > #endif /* __LINUX_KVM_H */
| |