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

Reply via email to