Signed-off-by: Gregory Haskins <[EMAIL PROTECTED]> --- drivers/kvm/vmx.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++---- drivers/kvm/vmx.h | 3 +++ 2 files changed, 55 insertions(+), 4 deletions(-)
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c index 82e40c9..7923a42 100644 --- a/drivers/kvm/vmx.c +++ b/drivers/kvm/vmx.c @@ -1301,7 +1301,14 @@ static int vmx_vcpu_setup(struct kvm_vcpu *vcpu) PIN_BASED_VM_EXEC_CONTROL, PIN_BASED_EXT_INTR_MASK /* 20.6.1 */ | PIN_BASED_NMI_EXITING /* 20.6.1 */ + | PIN_BASED_VIRTUAL_NMI /* 20.6.1 */ ); + + if (!(vmcs_read32(PIN_BASED_VM_EXEC_CONTROL) & PIN_BASED_VIRTUAL_NMI)) + printk(KERN_DEBUG "KVM: Warning - Host processor does " \ + "not support virtual-NMI injection. Using IRQ " \ + "method\n"); + vmcs_write32_fixedbits(MSR_IA32_VMX_PROCBASED_CTLS, CPU_BASED_VM_EXEC_CONTROL, CPU_BASED_HLT_EXITING /* 20.6.2 */ @@ -1450,6 +1457,37 @@ static void inject_rmode_irq(struct kvm_vcpu *vcpu, int irq) vmcs_writel(GUEST_RSP, (vmcs_readl(GUEST_RSP) & ~0xffff) | (sp - 6)); } +static void do_nmi_requests(struct kvm_vcpu *vcpu) +{ + int nmi_window = 0; + + BUG_ON(!(test_bit(kvm_irqpin_nmi, &vcpu->irq.pending))); + + nmi_window = + (((vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & 0xb) == 0) + && (vmcs_read32(VM_ENTRY_INTR_INFO_FIELD) + & INTR_INFO_VALID_MASK)); + + if (nmi_window) { + if (vcpu->rmode.active) + inject_rmode_irq(vcpu, 2); + else + vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, + 2 | + INTR_TYPE_NMI | + INTR_INFO_VALID_MASK); + + __clear_bit(kvm_irqpin_nmi, &vcpu->irq.pending); + } else { + /* + * NMIs blocked. Wait for unblock. + */ + u32 cbvec = vmcs_read32(CPU_BASED_VM_EXEC_CONTROL); + cbvec |= CPU_BASED_NMI_EXITING; + vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, cbvec); + } +} + static void do_intr_requests(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run, kvm_irqpin_t pin) @@ -1482,9 +1520,11 @@ static void do_intr_requests(struct kvm_vcpu *vcpu, break; case kvm_irqpin_nmi: /* - * FIXME: Someday we will handle this using the - * specific VMX NMI features. For now, just inject - * the NMI as a standard interrupt on vector 2 + * We should only get here if the processor does + * not support virtual NMIs. Inject the NMI as a + * standard interrupt on vector 2. The implication is + * that NMIs are going to be subject to RFLAGS.IF + * masking, unfortunately. */ ack.flags |= KVM_IRQACKDATA_VECTOR_VALID; ack.vector = 2; @@ -1534,6 +1574,8 @@ static void clear_pending_controls(struct kvm_vcpu *vcpu, else cbvec &= ~CPU_BASED_VIRTUAL_INTR_PENDING; + cbvec &= ~CPU_BASED_NMI_EXITING; + vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, cbvec); } @@ -1550,7 +1592,6 @@ static void do_interrupt_requests(struct kvm_vcpu *vcpu, switch (pin) { case kvm_irqpin_localint: case kvm_irqpin_extint: - case kvm_irqpin_nmi: do_intr_requests(vcpu, kvm_run, pin); break; case kvm_irqpin_smi: @@ -1558,6 +1599,13 @@ static void do_interrupt_requests(struct kvm_vcpu *vcpu, printk(KERN_WARNING "KVM: dropping unhandled SMI\n"); __clear_bit(pin, &vcpu->irq.pending); break; + case kvm_irqpin_nmi: + if (vmcs_read32(PIN_BASED_VM_EXEC_CONTROL) + & PIN_BASED_VIRTUAL_NMI) + do_nmi_requests(vcpu); + else + do_intr_requests(vcpu, kvm_run, pin); + break; case kvm_irqpin_invalid: /* drop */ break; diff --git a/drivers/kvm/vmx.h b/drivers/kvm/vmx.h index d0dc93d..d3fe017 100644 --- a/drivers/kvm/vmx.h +++ b/drivers/kvm/vmx.h @@ -35,6 +35,7 @@ #define CPU_BASED_CR8_LOAD_EXITING 0x00080000 #define CPU_BASED_CR8_STORE_EXITING 0x00100000 #define CPU_BASED_TPR_SHADOW 0x00200000 +#define CPU_BASED_NMI_EXITING 0x00400000 #define CPU_BASED_MOV_DR_EXITING 0x00800000 #define CPU_BASED_UNCOND_IO_EXITING 0x01000000 #define CPU_BASED_ACTIVATE_IO_BITMAP 0x02000000 @@ -44,6 +45,7 @@ #define PIN_BASED_EXT_INTR_MASK 0x1 #define PIN_BASED_NMI_EXITING 0x8 +#define PIN_BASED_VIRTUAL_NMI 0x20 #define VM_EXIT_ACK_INTR_ON_EXIT 0x00008000 #define VM_EXIT_HOST_ADD_SPACE_SIZE 0x00000200 @@ -221,6 +223,7 @@ enum vmcs_field { #define VECTORING_INFO_VALID_MASK INTR_INFO_VALID_MASK #define INTR_TYPE_EXT_INTR (0 << 8) /* external interrupt */ +#define INTR_TYPE_NMI (2 << 8) /* non-maskable interrupt */ #define INTR_TYPE_EXCEPTION (3 << 8) /* processor exception */ /* ------------------------------------------------------------------------- This SF.net email is sponsored by DB2 Express Download DB2 Express C - the FREE version of DB2 express and take control of your XML. No limits. Just data. Click to get it now. http://sourceforge.net/powerbar/db2/ _______________________________________________ kvm-devel mailing list kvm-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/kvm-devel