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-devel

[Xen-devel] [PATCH 10/17] vmx: nest: VMExit handler in L2

To: xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [PATCH 10/17] vmx: nest: VMExit handler in L2
From: Qing He <qing.he@xxxxxxxxx>
Date: Thu, 22 Apr 2010 17:41:22 +0800
Cc: Qing He <qing.he@xxxxxxxxx>
Delivery-date: Thu, 22 Apr 2010 03:03:51 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
In-reply-to: <1271929289-18572-1-git-send-email-qing.he@xxxxxxxxx>
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
References: <1271929289-18572-1-git-send-email-qing.he@xxxxxxxxx>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
Handles VMExits happened in L2

Signed-off-by: Qing He <qing.he@xxxxxxxxx>

---
 arch/x86/hvm/vmx/nest.c        |  182 +++++++++++++++++++++++++++++++++++++++++
 arch/x86/hvm/vmx/vmx.c         |    6 +
 include/asm-x86/hvm/vmx/nest.h |    3 
 include/asm-x86/hvm/vmx/vmx.h  |    1 
 4 files changed, 192 insertions(+)

diff -r a7de30ed250d -r 2f9ba6dbbe62 xen/arch/x86/hvm/vmx/nest.c
--- a/xen/arch/x86/hvm/vmx/nest.c       Thu Apr 22 22:30:09 2010 +0800
+++ b/xen/arch/x86/hvm/vmx/nest.c       Thu Apr 22 22:30:09 2010 +0800
@@ -976,3 +976,185 @@
 
     /* TODO: NMI */
 }
+
+/*
+ * L2 VMExit handling
+ */
+
+static struct control_bit_for_reason {
+    int reason;
+    unsigned long bit;
+} control_bit_for_reason [] = {
+    {EXIT_REASON_PENDING_VIRT_INTR, CPU_BASED_VIRTUAL_INTR_PENDING},
+    {EXIT_REASON_HLT, CPU_BASED_HLT_EXITING},
+    {EXIT_REASON_INVLPG, CPU_BASED_INVLPG_EXITING},
+    {EXIT_REASON_MWAIT_INSTRUCTION, CPU_BASED_MWAIT_EXITING},
+    {EXIT_REASON_RDPMC, CPU_BASED_RDPMC_EXITING},
+    {EXIT_REASON_RDTSC, CPU_BASED_RDTSC_EXITING},
+    {EXIT_REASON_PENDING_VIRT_NMI, CPU_BASED_VIRTUAL_NMI_PENDING},
+    {EXIT_REASON_DR_ACCESS, CPU_BASED_MOV_DR_EXITING},
+    {EXIT_REASON_MONITOR_INSTRUCTION, CPU_BASED_MONITOR_EXITING},
+    {EXIT_REASON_PAUSE_INSTRUCTION, CPU_BASED_PAUSE_EXITING},
+};
+
+int vmx_nest_l2_vmexit_handler(struct cpu_user_regs *regs,
+                               unsigned int exit_reason)
+{
+    struct vcpu *v = current;
+    struct vmx_nest_struct *nest = &v->arch.hvm_vmx.nest;
+    u32 ctrl;
+    int bypass_l0 = 0;
+
+    nest->vmexit_pending = 0;
+    nest->intr_info = 0;
+    nest->error_code = 0;
+
+    switch (exit_reason) {
+    case EXIT_REASON_EXCEPTION_NMI:
+    {
+        u32 intr_info = __vmread(VM_EXIT_INTR_INFO);
+        u32 valid_mask = (X86_EVENTTYPE_HW_EXCEPTION << 8) |
+                         INTR_INFO_VALID_MASK;
+        u64 exec_bitmap;
+        int vector = intr_info & INTR_INFO_VECTOR_MASK;
+
+        /*
+         * decided by L0 and L1 exception bitmap, if the vetor is set by
+         * both, L0 has priority on #PF, L1 has priority on others
+         */
+        if ( vector == TRAP_page_fault )
+        {
+            if ( paging_mode_hap(v->domain) )
+                nest->vmexit_pending = 1;
+        }
+        else if ( (intr_info & valid_mask) == valid_mask )
+        {
+            exec_bitmap =__get_vvmcs(nest->vvmcs, EXCEPTION_BITMAP);
+
+            if ( exec_bitmap & (1 << vector) )
+                nest->vmexit_pending = 1;
+        }
+        break;
+    }
+
+    case EXIT_REASON_WBINVD:
+    case EXIT_REASON_EPT_VIOLATION:
+    case EXIT_REASON_EPT_MISCONFIG:
+    case EXIT_REASON_EXTERNAL_INTERRUPT:
+        /* pass to L0 handler */
+        break;
+
+    case VMX_EXIT_REASONS_FAILED_VMENTRY:
+    case EXIT_REASON_TRIPLE_FAULT:
+    case EXIT_REASON_TASK_SWITCH:
+    case EXIT_REASON_IO_INSTRUCTION:
+    case EXIT_REASON_CPUID:
+    case EXIT_REASON_MSR_READ:
+    case EXIT_REASON_MSR_WRITE:
+    case EXIT_REASON_VMCALL:
+    case EXIT_REASON_VMCLEAR:
+    case EXIT_REASON_VMLAUNCH:
+    case EXIT_REASON_VMPTRLD:
+    case EXIT_REASON_VMPTRST:
+    case EXIT_REASON_VMREAD:
+    case EXIT_REASON_VMRESUME:
+    case EXIT_REASON_VMWRITE:
+    case EXIT_REASON_VMXOFF:
+    case EXIT_REASON_VMXON:
+    case EXIT_REASON_INVEPT:
+        /* inject to L1 */
+        nest->vmexit_pending = 1;
+        break;
+
+    case EXIT_REASON_PENDING_VIRT_INTR:
+    {
+        ctrl = v->arch.hvm_vmx.exec_control;
+
+        /*
+         * if both open intr/nmi window, L0 has priority.
+         *
+         * Note that this is not strictly correct, in L2 context,
+         * L0's intr/nmi window flag should be replaced to MTF,
+         * causing an imediate VMExit, but MTF may not be available
+         * on all hardware.
+         */
+        if ( !(ctrl & CPU_BASED_VIRTUAL_INTR_PENDING) )
+            nest->vmexit_pending = 1;
+
+        break;
+    }
+    case EXIT_REASON_PENDING_VIRT_NMI:
+    {
+        ctrl = v->arch.hvm_vmx.exec_control;
+
+        if ( !(ctrl & CPU_BASED_VIRTUAL_NMI_PENDING) )
+            nest->vmexit_pending = 1;
+
+        break;
+    }
+
+    case EXIT_REASON_HLT:
+    case EXIT_REASON_RDTSC:
+    case EXIT_REASON_RDPMC:
+    case EXIT_REASON_MWAIT_INSTRUCTION:
+    case EXIT_REASON_PAUSE_INSTRUCTION:
+    case EXIT_REASON_MONITOR_INSTRUCTION:
+    case EXIT_REASON_DR_ACCESS:
+    case EXIT_REASON_INVLPG:
+    {
+        int i;
+
+        /* exit according to guest exec_control */
+        ctrl = __get_vvmcs(nest->vvmcs, CPU_BASED_VM_EXEC_CONTROL);
+
+        for ( i = 0; i < ARRAY_SIZE(control_bit_for_reason); i++ )
+            if ( control_bit_for_reason[i].reason == exit_reason )
+                break;
+
+        if ( i == ARRAY_SIZE(control_bit_for_reason) )
+            break;
+
+        if ( control_bit_for_reason[i].bit & ctrl )
+            nest->vmexit_pending = 1;
+
+        break;
+    }
+    case EXIT_REASON_CR_ACCESS:
+    {
+        u64 exit_qualification = __vmread(EXIT_QUALIFICATION);
+        int cr = exit_qualification & 15;
+        int write = (exit_qualification >> 4) & 3;
+        u32 mask = 0;
+
+        /* also according to guest exec_control */
+        ctrl = __get_vvmcs(nest->vvmcs, CPU_BASED_VM_EXEC_CONTROL);
+
+        if ( cr == 3 )
+        {
+            mask = write? CPU_BASED_CR3_STORE_EXITING:
+                          CPU_BASED_CR3_LOAD_EXITING;
+            if ( ctrl & mask )
+                nest->vmexit_pending = 1;
+        }
+        else if ( cr == 8 )
+        {
+            mask = write? CPU_BASED_CR8_STORE_EXITING:
+                          CPU_BASED_CR8_LOAD_EXITING;
+            if ( ctrl & mask )
+                nest->vmexit_pending = 1;
+        }
+        else  /* CR0, CR4, CLTS, LMSW */
+            nest->vmexit_pending = 1;
+
+        break;
+    }
+    default:
+        gdprintk(XENLOG_WARNING, "Unknown nested vmexit reason %x.\n",
+                 exit_reason);
+    }
+
+    if ( nest->vmexit_pending )
+        bypass_l0 = 1;
+
+    return bypass_l0;
+}
diff -r a7de30ed250d -r 2f9ba6dbbe62 xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c        Thu Apr 22 22:30:09 2010 +0800
+++ b/xen/arch/x86/hvm/vmx/vmx.c        Thu Apr 22 22:30:09 2010 +0800
@@ -2397,6 +2397,11 @@
     local_irq_enable();
 
     v->arch.hvm_vmx.nest.vmresume_in_progress = 0;
+    if ( v->arch.hvm_vcpu.in_nesting )
+    {
+        if ( vmx_nest_l2_vmexit_handler(regs, exit_reason) )
+            goto out;
+    }
 
     if ( unlikely(exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY) )
         return vmx_failed_vmentry(exit_reason, regs);
@@ -2760,6 +2765,7 @@
         break;
     }
 
+out:
     if ( v->arch.hvm_vcpu.in_nesting )
         vmx_nest_idtv_handling();
 }
diff -r a7de30ed250d -r 2f9ba6dbbe62 xen/include/asm-x86/hvm/vmx/nest.h
--- a/xen/include/asm-x86/hvm/vmx/nest.h        Thu Apr 22 22:30:09 2010 +0800
+++ b/xen/include/asm-x86/hvm/vmx/nest.h        Thu Apr 22 22:30:09 2010 +0800
@@ -71,4 +71,7 @@
 
 void vmx_nest_idtv_handling(void);
 
+int vmx_nest_l2_vmexit_handler(struct cpu_user_regs *regs,
+                               unsigned int exit_reason);
+
 #endif /* __ASM_X86_HVM_NEST_H__ */
diff -r a7de30ed250d -r 2f9ba6dbbe62 xen/include/asm-x86/hvm/vmx/vmx.h
--- a/xen/include/asm-x86/hvm/vmx/vmx.h Thu Apr 22 22:30:09 2010 +0800
+++ b/xen/include/asm-x86/hvm/vmx/vmx.h Thu Apr 22 22:30:09 2010 +0800
@@ -112,6 +112,7 @@
 #define EXIT_REASON_APIC_ACCESS         44
 #define EXIT_REASON_EPT_VIOLATION       48
 #define EXIT_REASON_EPT_MISCONFIG       49
+#define EXIT_REASON_INVEPT              50
 #define EXIT_REASON_RDTSCP              51
 #define EXIT_REASON_WBINVD              54
 #define EXIT_REASON_XSETBV              55

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