[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] [XEN] Support VCPU reset via DOMCTL_setvcpucontext.



# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1169229329 0
# Node ID 0bf0672528cff1dbe666971b99201e3ba89fc286
# Parent  62e2e515febe4ccdfa60056f0e4210e051bdc3e6
[XEN] Support VCPU reset via DOMCTL_setvcpucontext.
Signed-off-by: Andrei Petrov <andrei.petrov@xxxxxxxxxxxxx>
---
 tools/libxc/xc_domain.c  |    5 +-
 xen/arch/x86/domain.c    |  109 +++++++++++++++++++++++++++--------------------
 xen/common/domain.c      |   38 +++++++++++++++-
 xen/include/xen/compat.h |    2 
 xen/include/xen/domain.h |    3 +
 5 files changed, 109 insertions(+), 48 deletions(-)

diff -r 62e2e515febe -r 0bf0672528cf tools/libxc/xc_domain.c
--- a/tools/libxc/xc_domain.c   Fri Jan 19 17:20:57 2007 +0000
+++ b/tools/libxc/xc_domain.c   Fri Jan 19 17:55:29 2007 +0000
@@ -602,12 +602,13 @@ int xc_vcpu_setcontext(int xc_handle,
     domctl.u.vcpucontext.vcpu = vcpu;
     set_xen_guest_handle(domctl.u.vcpucontext.ctxt, ctxt);
 
-    if ( (rc = lock_pages(ctxt, sizeof(*ctxt))) != 0 )
+    if ( (ctxt != NULL) && ((rc = lock_pages(ctxt, sizeof(*ctxt))) != 0) )
         return rc;
 
     rc = do_domctl(xc_handle, &domctl);
 
-    unlock_pages(ctxt, sizeof(*ctxt));
+    if ( ctxt != NULL )
+        unlock_pages(ctxt, sizeof(*ctxt));
 
     return rc;
 
diff -r 62e2e515febe -r 0bf0672528cf xen/arch/x86/domain.c
--- a/xen/arch/x86/domain.c     Fri Jan 19 17:20:57 2007 +0000
+++ b/xen/arch/x86/domain.c     Fri Jan 19 17:55:29 2007 +0000
@@ -50,6 +50,8 @@ static void paravirt_ctxt_switch_from(st
 static void paravirt_ctxt_switch_from(struct vcpu *v);
 static void paravirt_ctxt_switch_to(struct vcpu *v);
 
+static void vcpu_destroy_pagetables(struct vcpu *v);
+
 static void continue_idle_domain(struct vcpu *v)
 {
     reset_stack_and_jump(idle_loop);
@@ -656,6 +658,13 @@ int arch_set_info_guest(
 
     return 0;
 #undef c
+}
+
+int arch_vcpu_reset(struct vcpu *v)
+{
+    destroy_gdt(v);
+    vcpu_destroy_pagetables(v);
+    return 0;
 }
 
 long
@@ -1380,63 +1389,73 @@ static void relinquish_memory(struct dom
     spin_unlock_recursive(&d->page_alloc_lock);
 }
 
-void domain_relinquish_resources(struct domain *d)
-{
-    struct vcpu *v;
+static void vcpu_destroy_pagetables(struct vcpu *v)
+{
+    struct domain *d = v->domain;
     unsigned long pfn;
 
-    BUG_ON(!cpus_empty(d->domain_dirty_cpumask));
-
-    /* Drop the in-use references to page-table bases. */
-    for_each_vcpu ( d, v )
-    {
-        /* Drop ref to guest_table (from new_guest_cr3(), svm/vmx cr3 handling,
-         * or sh_update_paging_modes()) */
 #ifdef CONFIG_COMPAT
-        if ( IS_COMPAT(d) )
-        {
-            if ( is_hvm_vcpu(v) )
-                pfn = pagetable_get_pfn(v->arch.guest_table);
-            else
-                pfn = l4e_get_pfn(*(l4_pgentry_t 
*)__va(pagetable_get_paddr(v->arch.guest_table)));
-
-            if ( pfn != 0 )
-            {
-                if ( shadow_mode_refcounts(d) )
-                    put_page(mfn_to_page(pfn));
-                else
-                    put_page_and_type(mfn_to_page(pfn));
-            }
-            continue;
-        }
-#endif
-        pfn = pagetable_get_pfn(v->arch.guest_table);
+    if ( IS_COMPAT(d) )
+    {
+        if ( is_hvm_vcpu(v) )
+            pfn = pagetable_get_pfn(v->arch.guest_table);
+        else
+            pfn = l4e_get_pfn(*(l4_pgentry_t *)
+                              __va(pagetable_get_paddr(v->arch.guest_table)));
+
         if ( pfn != 0 )
         {
             if ( shadow_mode_refcounts(d) )
                 put_page(mfn_to_page(pfn));
             else
                 put_page_and_type(mfn_to_page(pfn));
+        }
+
+        v->arch.guest_table = pagetable_null();
+        v->arch.cr3 = 0;
+        return;
+    }
+#endif
+
+    pfn = pagetable_get_pfn(v->arch.guest_table);
+    if ( pfn != 0 )
+    {
+        if ( shadow_mode_refcounts(d) )
+            put_page(mfn_to_page(pfn));
+        else
+            put_page_and_type(mfn_to_page(pfn));
 #ifdef __x86_64__
-            if ( pfn == pagetable_get_pfn(v->arch.guest_table_user) )
-                v->arch.guest_table_user = pagetable_null();
-#endif
-            v->arch.guest_table = pagetable_null();
-        }
+        if ( pfn == pagetable_get_pfn(v->arch.guest_table_user) )
+            v->arch.guest_table_user = pagetable_null();
+#endif
+        v->arch.guest_table = pagetable_null();
+    }
 
 #ifdef __x86_64__
-        /* Drop ref to guest_table_user (from MMUEXT_NEW_USER_BASEPTR) */
-        pfn = pagetable_get_pfn(v->arch.guest_table_user);
-        if ( pfn != 0 )
-        {
-            if ( shadow_mode_refcounts(d) )
-                put_page(mfn_to_page(pfn));
-            else
-                put_page_and_type(mfn_to_page(pfn));
-            v->arch.guest_table_user = pagetable_null();
-        }
-#endif
-    }
+    /* Drop ref to guest_table_user (from MMUEXT_NEW_USER_BASEPTR) */
+    pfn = pagetable_get_pfn(v->arch.guest_table_user);
+    if ( pfn != 0 )
+    {
+        if ( shadow_mode_refcounts(d) )
+            put_page(mfn_to_page(pfn));
+        else
+            put_page_and_type(mfn_to_page(pfn));
+        v->arch.guest_table_user = pagetable_null();
+    }
+#endif
+
+    v->arch.cr3 = 0;
+}
+
+void domain_relinquish_resources(struct domain *d)
+{
+    struct vcpu *v;
+
+    BUG_ON(!cpus_empty(d->domain_dirty_cpumask));
+
+    /* Drop the in-use references to page-table bases. */
+    for_each_vcpu ( d, v )
+        vcpu_destroy_pagetables(v);
 
     /* Tear down shadow mode stuff. */
     shadow_teardown(d);
diff -r 62e2e515febe -r 0bf0672528cf xen/common/domain.c
--- a/xen/common/domain.c       Fri Jan 19 17:20:57 2007 +0000
+++ b/xen/common/domain.c       Fri Jan 19 17:55:29 2007 +0000
@@ -5,6 +5,7 @@
  */
 
 #include <xen/config.h>
+#include <xen/compat.h>
 #include <xen/init.h>
 #include <xen/lib.h>
 #include <xen/errno.h>
@@ -467,7 +468,12 @@ int set_info_guest(struct domain *d,
 
     if ( (vcpu >= MAX_VIRT_CPUS) || ((v = d->vcpu[vcpu]) == NULL) )
         return -EINVAL;
-    
+
+    if ( IS_COMPAT(v->domain)
+         ? compat_handle_is_null(vcpucontext.cmp->ctxt)
+         : guest_handle_is_null(vcpucontext.nat->ctxt) )
+        return vcpu_reset(v);
+
 #ifdef CONFIG_COMPAT
     BUILD_BUG_ON(sizeof(struct vcpu_guest_context)
                  < sizeof(struct compat_vcpu_guest_context));
@@ -521,6 +527,36 @@ int boot_vcpu(struct domain *d, int vcpu
     return arch_set_info_guest(v, ctxt);
 }
 
+int vcpu_reset(struct vcpu *v)
+{
+    struct domain *d = v->domain;
+    int rc;
+
+    domain_pause(d);
+    LOCK_BIGLOCK(d);
+
+    rc = arch_vcpu_reset(v);
+    if ( rc != 0 )
+        goto out;
+
+    set_bit(_VCPUF_down, &v->vcpu_flags);
+
+    clear_bit(_VCPUF_fpu_initialised, &v->vcpu_flags);
+    clear_bit(_VCPUF_fpu_dirtied, &v->vcpu_flags);
+    clear_bit(_VCPUF_blocked, &v->vcpu_flags);
+    clear_bit(_VCPUF_initialised, &v->vcpu_flags);
+    clear_bit(_VCPUF_nmi_pending, &v->vcpu_flags);
+    clear_bit(_VCPUF_nmi_masked, &v->vcpu_flags);
+    clear_bit(_VCPUF_polling, &v->vcpu_flags);
+
+ out:
+    UNLOCK_BIGLOCK(v->domain);
+    domain_unpause(d);
+
+    return rc;
+}
+
+
 long do_vcpu_op(int cmd, int vcpuid, XEN_GUEST_HANDLE(void) arg)
 {
     struct domain *d = current->domain;
diff -r 62e2e515febe -r 0bf0672528cf xen/include/xen/compat.h
--- a/xen/include/xen/compat.h  Fri Jan 19 17:20:57 2007 +0000
+++ b/xen/include/xen/compat.h  Fri Jan 19 17:55:29 2007 +0000
@@ -173,6 +173,8 @@ int switch_native(struct domain *);
 
 #else
 
+#define compat_handle_is_null(hnd) 0
+
 #define BITS_PER_GUEST_LONG(d) BITS_PER_LONG
 
 #endif
diff -r 62e2e515febe -r 0bf0672528cf xen/include/xen/domain.h
--- a/xen/include/xen/domain.h  Fri Jan 19 17:20:57 2007 +0000
+++ b/xen/include/xen/domain.h  Fri Jan 19 17:55:29 2007 +0000
@@ -12,6 +12,7 @@ int boot_vcpu(
 int boot_vcpu(
     struct domain *d, int vcpuid, vcpu_guest_context_u ctxt);
 struct vcpu *alloc_idle_vcpu(unsigned int cpu_id);
+int vcpu_reset(struct vcpu *v);
 
 struct domain *alloc_domain(domid_t domid);
 void free_domain(struct domain *d);
@@ -56,4 +57,6 @@ void arch_dump_vcpu_info(struct vcpu *v)
 
 void arch_dump_domain_info(struct domain *d);
 
+int arch_vcpu_reset(struct vcpu *v);
+
 #endif /* __XEN_DOMAIN_H__ */

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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.