WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] hvm vmx: Various cleanups and clarificati

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] hvm vmx: Various cleanups and clarifications around event injection.
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Thu, 14 Jun 2007 12:59:19 -0700
Delivery-date: Thu, 14 Jun 2007 15:25:34 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Keir Fraser <keir@xxxxxxxxxxxxx>
# Date 1181769868 -3600
# Node ID 4d838167960694f1b9fcaec54590aef0e1f0a7ee
# Parent  b643179d7452a91cd874ee713c78bf30f8df3d2d
hvm vmx: Various cleanups and clarifications around event injection.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
 xen/arch/x86/hvm/vmx/intr.c        |   73 +++++++++++++++++++++----------------
 xen/arch/x86/hvm/vmx/vmcs.c        |    5 +-
 xen/arch/x86/hvm/vmx/vmx.c         |   18 +++++++--
 xen/include/asm-x86/hvm/vmx/vmcs.h |   10 ++++-
 xen/include/asm-x86/hvm/vmx/vmx.h  |   14 +++++--
 5 files changed, 80 insertions(+), 40 deletions(-)

diff -r b643179d7452 -r 4d8381679606 xen/arch/x86/hvm/vmx/intr.c
--- a/xen/arch/x86/hvm/vmx/intr.c       Wed Jun 13 11:28:13 2007 +0100
+++ b/xen/arch/x86/hvm/vmx/intr.c       Wed Jun 13 22:24:28 2007 +0100
@@ -1,6 +1,7 @@
 /*
- * io.c: handling I/O, interrupts related VMX entry/exit
+ * intr.c: handling I/O, interrupts related VMX entry/exit
  * Copyright (c) 2004, Intel Corporation.
+ * Copyright (c) 2004-2007, XenSource Inc.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -14,7 +15,6 @@
  * You should have received a copy of the GNU General Public License along with
  * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
  * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
  */
 
 #include <xen/config.h>
@@ -24,7 +24,6 @@
 #include <xen/errno.h>
 #include <xen/trace.h>
 #include <xen/event.h>
-
 #include <asm/current.h>
 #include <asm/cpufeature.h>
 #include <asm/processor.h>
@@ -39,32 +38,48 @@
 #include <public/hvm/ioreq.h>
 #include <asm/hvm/trace.h>
 
+/*
+ * A few notes on virtual NMI and INTR delivery, and interactions with
+ * interruptibility states:
+ * 
+ * We can only inject an ExtInt if EFLAGS.IF = 1 and no blocking by
+ * STI nor MOV SS. Otherwise the VM entry fails. The 'virtual interrupt
+ * pending' control causes a VM exit when all these checks succeed. It will
+ * exit immediately after VM entry if the checks succeed at that point.
+ * 
+ * We can only inject an NMI if no blocking by MOV SS (also, depending on
+ * implementation, if no blocking by STI). If pin-based 'virtual NMIs'
+ * control is specified then the NMI-blocking interruptibility flag is
+ * also checked. The 'virtual NMI pending' control (available only in
+ * conjunction with 'virtual NMIs') causes a VM exit when all these checks
+ * succeed. It will exit immediately after VM entry if the checks succeed
+ * at that point.
+ * 
+ * Because a processor may or may not check blocking-by-STI when injecting
+ * a virtual NMI, it will be necessary to convert that to block-by-MOV-SS
+ * before specifying the 'virtual NMI pending' control. Otherwise we could
+ * enter an infinite loop where we check blocking-by-STI in software and
+ * thus delay delivery of a virtual NMI, but the processor causes immediate
+ * VM exit because it does not check blocking-by-STI.
+ * 
+ * Injecting a virtual NMI sets the NMI-blocking interruptibility flag only
+ * if the 'virtual NMIs' control is set. Injecting *any* kind of event clears
+ * the STI- and MOV-SS-blocking interruptibility-state flags.
+ * 
+ * If MOV/POP SS is executed while MOV-SS-blocking is in effect, the effect
+ * is cleared. If STI is executed while MOV-SS- or STI-blocking is in effect,
+ * the effect is cleared. (i.e., MOV-SS-blocking 'dominates' STI-blocking).
+ */
 
-static inline void
-enable_irq_window(struct vcpu *v)
+static void enable_irq_window(struct vcpu *v)
 {
     u32  *cpu_exec_control = &v->arch.hvm_vcpu.u.vmx.exec_control;
     
-    if (!(*cpu_exec_control & CPU_BASED_VIRTUAL_INTR_PENDING)) {
+    if ( !(*cpu_exec_control & CPU_BASED_VIRTUAL_INTR_PENDING) )
+    {
         *cpu_exec_control |= CPU_BASED_VIRTUAL_INTR_PENDING;
         __vmwrite(CPU_BASED_VM_EXEC_CONTROL, *cpu_exec_control);
     }
-}
-
-static inline void
-disable_irq_window(struct vcpu *v)
-{
-    u32  *cpu_exec_control = &v->arch.hvm_vcpu.u.vmx.exec_control;
-    
-    if ( *cpu_exec_control & CPU_BASED_VIRTUAL_INTR_PENDING ) {
-        *cpu_exec_control &= ~CPU_BASED_VIRTUAL_INTR_PENDING;
-        __vmwrite(CPU_BASED_VM_EXEC_CONTROL, *cpu_exec_control);
-    }
-}
-
-static inline int is_interruptibility_state(void)
-{
-    return __vmread(GUEST_INTERRUPTIBILITY_INFO);
 }
 
 static void update_tpr_threshold(struct vlapic *vlapic)
@@ -87,13 +102,11 @@ static void update_tpr_threshold(struct 
 
 asmlinkage void vmx_intr_assist(void)
 {
-    int intr_type = 0;
-    int intr_vector;
-    unsigned long eflags;
+    int has_ext_irq, intr_vector, intr_type = 0;
+    unsigned long eflags, intr_shadow;
     struct vcpu *v = current;
     unsigned int idtv_info_field;
     unsigned long inst_len;
-    int    has_ext_irq;
 
     pt_update_irq(v);
 
@@ -125,10 +138,10 @@ asmlinkage void vmx_intr_assist(void)
         inst_len = __vmread(VM_EXIT_INSTRUCTION_LEN); /* Safe */
         __vmwrite(VM_ENTRY_INSTRUCTION_LEN, inst_len);
 
-        if (unlikely(idtv_info_field & 0x800)) /* valid error code */
+        if ( unlikely(idtv_info_field & 0x800) ) /* valid error code */
             __vmwrite(VM_ENTRY_EXCEPTION_ERROR_CODE,
                       __vmread(IDT_VECTORING_ERROR_CODE));
-        if (unlikely(has_ext_irq))
+        if ( unlikely(has_ext_irq) )
             enable_irq_window(v);
 
         HVM_DBG_LOG(DBG_LEVEL_1, "idtv_info_field=%x", idtv_info_field);
@@ -138,9 +151,9 @@ asmlinkage void vmx_intr_assist(void)
     if ( likely(!has_ext_irq) )
         return;
 
-    if ( unlikely(is_interruptibility_state()) )
+    intr_shadow = __vmread(GUEST_INTERRUPTIBILITY_INFO);
+    if ( unlikely(intr_shadow & (VMX_INTR_SHADOW_STI|VMX_INTR_SHADOW_MOV_SS)) )
     {
-        /* pre-cleared for emulated instruction */
         enable_irq_window(v);
         HVM_DBG_LOG(DBG_LEVEL_1, "interruptibility");
         return;
diff -r b643179d7452 -r 4d8381679606 xen/arch/x86/hvm/vmx/vmcs.c
--- a/xen/arch/x86/hvm/vmx/vmcs.c       Wed Jun 13 11:28:13 2007 +0100
+++ b/xen/arch/x86/hvm/vmx/vmcs.c       Wed Jun 13 22:24:28 2007 +0100
@@ -70,8 +70,9 @@ void vmx_init_vmcs_config(void)
     u32 _vmx_vmexit_control;
     u32 _vmx_vmentry_control;
 
-    min = PIN_BASED_EXT_INTR_MASK | PIN_BASED_NMI_EXITING;
-    opt = 0;
+    min = (PIN_BASED_EXT_INTR_MASK |
+           PIN_BASED_NMI_EXITING);
+    opt = 0; /*PIN_BASED_VIRTUAL_NMIS*/
     _vmx_pin_based_exec_control = adjust_vmx_controls(
         min, opt, MSR_IA32_VMX_PINBASED_CTLS);
 
diff -r b643179d7452 -r 4d8381679606 xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c        Wed Jun 13 11:28:13 2007 +0100
+++ b/xen/arch/x86/hvm/vmx/vmx.c        Wed Jun 13 22:24:28 2007 +0100
@@ -1300,11 +1300,17 @@ static int __get_instruction_length(void
 
 static void inline __update_guest_eip(unsigned long inst_len)
 {
-    unsigned long current_eip;
+    unsigned long current_eip, intr_shadow;
 
     current_eip = __vmread(GUEST_RIP);
     __vmwrite(GUEST_RIP, current_eip + inst_len);
-    __vmwrite(GUEST_INTERRUPTIBILITY_INFO, 0);
+
+    intr_shadow = __vmread(GUEST_INTERRUPTIBILITY_INFO);
+    if ( intr_shadow & (VMX_INTR_SHADOW_STI | VMX_INTR_SHADOW_MOV_SS) )
+    {
+        intr_shadow &= ~(VMX_INTR_SHADOW_STI | VMX_INTR_SHADOW_MOV_SS);
+        __vmwrite(GUEST_INTERRUPTIBILITY_INFO, intr_shadow);
+    }
 }
 
 static void vmx_do_no_device_fault(void)
@@ -2902,9 +2908,15 @@ asmlinkage void vmx_vmexit_handler(struc
     case EXIT_REASON_TRIPLE_FAULT:
         hvm_triple_fault();
         break;
-    case EXIT_REASON_PENDING_INTERRUPT:
+    case EXIT_REASON_PENDING_VIRT_INTR:
         /* Disable the interrupt window. */
         v->arch.hvm_vcpu.u.vmx.exec_control &= ~CPU_BASED_VIRTUAL_INTR_PENDING;
+        __vmwrite(CPU_BASED_VM_EXEC_CONTROL,
+                  v->arch.hvm_vcpu.u.vmx.exec_control);
+        break;
+    case EXIT_REASON_PENDING_VIRT_NMI:
+        /* Disable the NMI window. */
+        v->arch.hvm_vcpu.u.vmx.exec_control &= ~CPU_BASED_VIRTUAL_NMI_PENDING;
         __vmwrite(CPU_BASED_VM_EXEC_CONTROL,
                   v->arch.hvm_vcpu.u.vmx.exec_control);
         break;
diff -r b643179d7452 -r 4d8381679606 xen/include/asm-x86/hvm/vmx/vmcs.h
--- a/xen/include/asm-x86/hvm/vmx/vmcs.h        Wed Jun 13 11:28:13 2007 +0100
+++ b/xen/include/asm-x86/hvm/vmx/vmcs.h        Wed Jun 13 22:24:28 2007 +0100
@@ -104,6 +104,7 @@ void vmx_vmcs_exit(struct vcpu *v);
 #define CPU_BASED_CR8_LOAD_EXITING            0x00080000
 #define CPU_BASED_CR8_STORE_EXITING           0x00100000
 #define CPU_BASED_TPR_SHADOW                  0x00200000
+#define CPU_BASED_VIRTUAL_NMI_PENDING         0x00400000
 #define CPU_BASED_MOV_DR_EXITING              0x00800000
 #define CPU_BASED_UNCOND_IO_EXITING           0x01000000
 #define CPU_BASED_ACTIVATE_IO_BITMAP          0x02000000
@@ -115,6 +116,7 @@ extern u32 vmx_cpu_based_exec_control;
 
 #define PIN_BASED_EXT_INTR_MASK         0x00000001
 #define PIN_BASED_NMI_EXITING           0x00000008
+#define PIN_BASED_VIRTUAL_NMIS          0x00000020
 extern u32 vmx_pin_based_exec_control;
 
 #define VM_EXIT_IA32E_MODE              0x00000200
@@ -137,7 +139,13 @@ extern u32 vmx_secondary_exec_control;
     (vmx_cpu_based_exec_control & CPU_BASED_ACTIVATE_MSR_BITMAP)
 extern char *vmx_msr_bitmap;
 
-/* VMCS Encordings */
+/* GUEST_INTERRUPTIBILITY_INFO flags. */
+#define VMX_INTR_SHADOW_STI             0x00000001
+#define VMX_INTR_SHADOW_MOV_SS          0x00000002
+#define VMX_INTR_SHADOW_SMI             0x00000004
+#define VMX_INTR_SHADOW_NMI             0x00000008
+
+/* VMCS field encodings. */
 enum vmcs_field {
     GUEST_ES_SELECTOR               = 0x00000800,
     GUEST_CS_SELECTOR               = 0x00000802,
diff -r b643179d7452 -r 4d8381679606 xen/include/asm-x86/hvm/vmx/vmx.h
--- a/xen/include/asm-x86/hvm/vmx/vmx.h Wed Jun 13 11:28:13 2007 +0100
+++ b/xen/include/asm-x86/hvm/vmx/vmx.h Wed Jun 13 22:24:28 2007 +0100
@@ -46,8 +46,8 @@ void vmx_vlapic_msr_changed(struct vcpu 
 #define EXIT_REASON_SIPI                4
 #define EXIT_REASON_IO_SMI              5
 #define EXIT_REASON_OTHER_SMI           6
-#define EXIT_REASON_PENDING_INTERRUPT   7
-
+#define EXIT_REASON_PENDING_VIRT_INTR   7
+#define EXIT_REASON_PENDING_VIRT_NMI    8
 #define EXIT_REASON_TASK_SWITCH         9
 #define EXIT_REASON_CPUID               10
 #define EXIT_REASON_HLT                 12
@@ -295,7 +295,14 @@ static inline void __vmx_inject_exceptio
 {
     unsigned long intr_fields;
 
-    /* Reflect it back into the guest */
+    /*
+     * NB. Callers do not need to worry about clearing STI/MOV-SS blocking:
+     *  "If the VM entry is injecting, there is no blocking by STI or by
+     *   MOV SS following the VM entry, regardless of the contents of the
+     *   interruptibility-state field [in the guest-state area before the
+     *   VM entry]", PRM Vol. 3, 22.6.1 (Interruptibility State).
+     */
+
     intr_fields = (INTR_INFO_VALID_MASK | type | trap);
     if ( error_code != VMX_DELIVER_NO_ERROR_CODE ) {
         __vmwrite(VM_ENTRY_EXCEPTION_ERROR_CODE, error_code);
@@ -332,7 +339,6 @@ static inline void vmx_inject_extint(str
 static inline void vmx_inject_extint(struct vcpu *v, int trap, int error_code)
 {
     __vmx_inject_exception(v, trap, INTR_TYPE_EXT_INTR, error_code, 0);
-    __vmwrite(GUEST_INTERRUPTIBILITY_INFO, 0);
 }
 
 #endif /* __ASM_X86_HVM_VMX_VMX_H__ */

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] hvm vmx: Various cleanups and clarifications around event injection., Xen patchbot-unstable <=