KVM: x86: Add KVM_GET/SET_VCPU_EVENTS
Subsystems (4)
PATCH 1/1 KVM: x86: Add KVM_GET/SET_VCPU_EVENTS
This new IOCTL exports all yet user-invisible states related to exceptions, interrupts, and NMIs. Together with appropriate user space changes, this fixes sporadic problems of vmsave/restore, live migration and system reset.
---
Documentation/kvm/api.txt | 48 ++++++++++++++++++++++++++ arch/x86/include/asm/kvm.h | 26 ++++++++++++++ arch/x86/include/asm/kvm_host.h | 2 + arch/x86/kvm/svm.c | 22 ++++++++++++ arch/x86/kvm/vmx.c | 30 ++++++++++++++++ arch/x86/kvm/x86.c | 72 +++++++++++++++++++++++++++++++++++++++ include/linux/kvm.h | 6 +++ 7 files changed, 206 insertions(+), 0 deletions(-)
Documentation/kvm/api.txt +48 -0
@@ -653,6 +653,54 @@ struct kvm_clock_data { __u32 pad[9]; }; +4.29 KVM_GET_VCPU_EVENTS + +Capability: KVM_CAP_VCPU_EVENTS +Architectures: x86 +Type: vm ioctl +Parameters: struct kvm_vcpu_event (out) +Returns: 0 on success, -1 on error + +Gets currently pending exceptions, interrupts, and NMIs as well as related +states of the vcpu. + +struct kvm_vcpu_events { + struct { + __u8 injected; + __u8 nr; + __u8 has_error_code; + __u8 pad; + __u32 error_code; + } exception; + struct { + __u8 injected; + __u8 nr; + __u8 soft; + __u8 pad; + } interrupt; + struct { + __u8 injected; + __u8 pending; + __u8 masked; + __u8 pad; + } nmi; + __u32 sipi_vector; +}; + +4.30 KVM_SET_VCPU_EVENTS + +Capability: KVM_CAP_VCPU_EVENTS +Architectures: x86 +Type: vm ioctl +Parameters: struct kvm_vcpu_event (in) +Returns: 0 on success, -1 on error + +Set pending exceptions, interrupts, and NMIs as well as related states of the +vcpu. + +See KVM_GET_VCPU_EVENTS for the data structure. + + 5. The kvm_run structure Application code obtains a pointer to the kvm_run structure by
arch/x86/include/asm/kvm.h +26 -0
@@ -20,6 +20,7 @@#define __KVM_HAVE_MCE#define __KVM_HAVE_PIT_STATE2#define __KVM_HAVE_XEN_HVM +#define __KVM_HAVE_VCPU_EVENTS/* Architectural interrupt line count. */ #define KVM_NR_INTERRUPTS 256
@@ -252,4 +253,29 @@ struct kvm_reinject_control {__u8 pit_reinject; __u8 reserved[31]; }; + +/* for KVM_GET/SET_VCPU_EVENTS */ +struct kvm_vcpu_events { +struct { +__u8 injected; +__u8 nr; +__u8 has_error_code; +__u8 pad; +__u32 error_code; + } exception; +struct { +__u8 injected; +__u8 nr; +__u8 soft; +__u8 pad; + } interrupt; +struct { +__u8 injected; +__u8 pending; +__u8 masked; +__u8 pad; + } nmi; +__u32 sipi_vector; +}; +#endif /* _ASM_X86_KVM_H */
arch/x86/include/asm/kvm_host.h +2 -0
@@ -523,6 +523,8 @@ struct kvm_x86_ops { bool has_error_code, u32 error_code);int (*interrupt_allowed)(struct kvm_vcpu *vcpu);int (*nmi_allowed)(struct kvm_vcpu *vcpu); +bool (*get_nmi_mask)(struct kvm_vcpu *vcpu); +void (*set_nmi_mask)(struct kvm_vcpu *vcpu,bool masked);void (*enable_nmi_window)(struct kvm_vcpu *vcpu);void (*enable_irq_window)(struct kvm_vcpu *vcpu);void (*update_cr8_intercept)(struct kvm_vcpu *vcpu,int tpr,int irr);
arch/x86/kvm/svm.c +22 -0
@@ -2499,6 +2499,26 @@ static int svm_nmi_allowed(struct kvm_vcpu *vcpu) !(svm->vcpu.arch.hflags &HF_NMI_MASK ); } +static bool svm_get_nmi_mask (struct kvm_vcpu *vcpu) +{ +struct vcpu_svm *svm =to_svm (vcpu); + +return !!(svm->vcpu.arch.hflags &HF_NMI_MASK ); +} + +static void svm_set_nmi_mask (struct kvm_vcpu *vcpu,bool masked) +{ +struct vcpu_svm *svm =to_svm (vcpu); + +if (masked) { + svm->vcpu.arch.hflags |=HF_NMI_MASK ; + svm->vmcb->control.intercept |= (1UL <<INTERCEPT_IRET ); + }else { + svm->vcpu.arch.hflags &= ~HF_NMI_MASK ; + svm->vmcb->control.intercept &= ~(1UL <<INTERCEPT_IRET ); + } +} +static int svm_interrupt_allowed (struct kvm_vcpu *vcpu) {struct vcpu_svm *svm =to_svm (vcpu);
@@ -2946,6 +2966,8 @@ static struct kvm_x86_ops svm_x86_ops = { .queue_exception = svm_queue_exception, .interrupt_allowed = svm_interrupt_allowed, .nmi_allowed = svm_nmi_allowed, + .get_nmi_mask = svm_get_nmi_mask, + .set_nmi_mask = svm_set_nmi_mask, .enable_nmi_window = enable_nmi_window, .enable_irq_window = enable_irq_window, .update_cr8_intercept = update_cr8_intercept,
arch/x86/kvm/vmx.c +30 -0
@@ -2633,6 +2633,34 @@ static int vmx_nmi_allowed(struct kvm_vcpu *vcpu) GUEST_INTR_STATE_NMI)); } +static bool vmx_get_nmi_mask (struct kvm_vcpu *vcpu) +{ +if (!cpu_has_virtual_nmis ()) +return to_vmx (vcpu)->soft_vnmi_blocked; +else +return !!(vmcs_read32 (GUEST_INTERRUPTIBILITY_INFO ) & +GUEST_INTR_STATE_NMI ); +} + +static void vmx_set_nmi_mask (struct kvm_vcpu *vcpu,bool masked) +{ +struct vcpu_vmx *vmx =to_vmx (vcpu); + +if (!cpu_has_virtual_nmis ()) { +if (vmx->soft_vnmi_blocked != masked) { + vmx->soft_vnmi_blocked = masked; + vmx->vnmi_blocked_time =0 ; + } + }else { +if (masked) +vmcs_set_bits (GUEST_INTERRUPTIBILITY_INFO , +GUEST_INTR_STATE_NMI ); +else +vmcs_clear_bits (GUEST_INTERRUPTIBILITY_INFO , +GUEST_INTR_STATE_NMI ); + } +} +static int vmx_interrupt_allowed (struct kvm_vcpu *vcpu) { return (vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_IF) &&
@@ -3973,6 +4001,8 @@ static struct kvm_x86_ops vmx_x86_ops = { .queue_exception = vmx_queue_exception, .interrupt_allowed = vmx_interrupt_allowed, .nmi_allowed = vmx_nmi_allowed, + .get_nmi_mask = vmx_get_nmi_mask, + .set_nmi_mask = vmx_set_nmi_mask, .enable_nmi_window = enable_nmi_window, .enable_irq_window = enable_irq_window, .update_cr8_intercept = update_cr8_intercept,
arch/x86/kvm/x86.c +72 -0
90 lines not on this page · raw message
include/linux/kvm.h +6 -0
@@ -484,6 +484,9 @@ struct kvm_ioeventfd {#define KVM_CAP_XEN_HVM 38#endif #define KVM_CAP_ADJUST_CLOCK 39 +#ifdef __KVM_HAVE_VCPU_EVENTS +#define KVM_CAP_VCPU_EVENTS 40 +#endif #ifdef KVM_CAP_IRQ_ROUTING
@@ -667,6 +670,9 @@ struct kvm_clock_data {/* IA64 stack access */ #define KVM_IA64_VCPU_GET_STACK _IOR(KVMIO, 0x9a, void *)#define KVM_IA64_VCPU_SET_STACK _IOW(KVMIO, 0x9b, void *) +/* Available with KVM_CAP_VCPU_EVENTS */ +#define KVM_GET_VCPU_EVENTS _IOR(KVMIO, 0x9f, struct kvm_vcpu_events) +#define KVM_SET_VCPU_EVENTS _IOW(KVMIO, 0xa0, struct kvm_vcpu_events)#define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0)
Quoted 6 lines · Jan Kiszka
This new IOCTL exports all yet user-invisible states related to exceptions, interrupts, and NMIs. Together with appropriate user space changes, this fixes sporadic problems of vmsave/restore, live migration and system reset.
Applied, thanks. I added a flags field to the structure in case we discover a new bit that needs to fit in there. Please take a look (separate commit in kvm-next).
Signature · 1 line
error compiling committee.c: too many arguments to function
Quoted 8 lines · Avi Kivity
Quoted 6 lines · Jan Kiszka
This new IOCTL exports all yet user-invisible states related to exceptions, interrupts, and NMIs. Together with appropriate user space changes, this fixes sporadic problems of vmsave/restore, live migration and system reset.
Quoted 4 lines
Applied, thanks. I added a flags field to the structure in case we discover a new bit that needs to fit in there. Please take a look (separate commit in kvm-next).
Looks ok.
Jan
Quoted 8 lines · Avi Kivity
Quoted 6 lines · Jan Kiszka
This new IOCTL exports all yet user-invisible states related to exceptions, interrupts, and NMIs. Together with appropriate user space changes, this fixes sporadic problems of vmsave/restore, live migration and system reset.
Quoted 4 lines
Applied, thanks. I added a flags field to the structure in case we discover a new bit that needs to fit in there. Please take a look (separate commit in kvm-next).
So without this patch migration fails? Sounds like a stable candidate to me. Same goes for the follow-up that adds the shadow field.
Alex