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] xen: Allow vcpus to defer a shutdown requ

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] xen: Allow vcpus to defer a shutdown request across critical
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Tue, 03 Apr 2007 06:50:08 -0700
Delivery-date: Tue, 03 Apr 2007 06:49:28 -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 kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1175597050 -3600
# Node ID a1b17c48fb403e9b8fd4fe136198eafa126a5cf7
# Parent  45e9f6d7e422156ec36d64dea817af2fb659ec1a
xen: Allow vcpus to defer a shutdown request across critical
asynchronous operations (in particular, hvm ioreq requests).
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
 xen/arch/x86/hvm/hvm.c         |    3 +
 xen/arch/x86/hvm/io.c          |   11 ++-
 xen/arch/x86/mm.c              |    3 -
 xen/arch/x86/mm/shadow/multi.c |    4 -
 xen/common/domain.c            |  118 +++++++++++++++++++++++++++++++++++++----
 xen/common/domctl.c            |    5 -
 xen/include/xen/sched.h        |   12 +++-
 7 files changed, 136 insertions(+), 20 deletions(-)

diff -r 45e9f6d7e422 -r a1b17c48fb40 xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c    Tue Apr 03 10:36:31 2007 +0100
+++ b/xen/arch/x86/hvm/hvm.c    Tue Apr 03 11:44:10 2007 +0100
@@ -372,6 +372,9 @@ void hvm_send_assist_req(struct vcpu *v)
 void hvm_send_assist_req(struct vcpu *v)
 {
     ioreq_t *p;
+
+    if ( unlikely(!vcpu_start_shutdown_deferral(v)) )
+        return; /* implicitly bins the i/o operation */
 
     p = &get_vio(v->domain, v->vcpu_id)->vp_ioreq;
     if ( unlikely(p->state != STATE_IOREQ_NONE) )
diff -r 45e9f6d7e422 -r a1b17c48fb40 xen/arch/x86/hvm/io.c
--- a/xen/arch/x86/hvm/io.c     Tue Apr 03 10:36:31 2007 +0100
+++ b/xen/arch/x86/hvm/io.c     Tue Apr 03 11:44:10 2007 +0100
@@ -771,10 +771,11 @@ void hvm_io_assist(struct vcpu *v)
     struct cpu_user_regs *regs;
     struct hvm_io_op *io_opp;
     unsigned long gmfn;
+    struct domain *d = v->domain;
 
     io_opp = &v->arch.hvm_vcpu.io_op;
     regs   = &io_opp->io_context;
-    vio    = get_vio(v->domain, v->vcpu_id);
+    vio    = get_vio(d, v->vcpu_id);
 
     p = &vio->vp_ioreq;
     if ( p->state != STATE_IORESP_READY )
@@ -797,11 +798,13 @@ void hvm_io_assist(struct vcpu *v)
     memcpy(guest_cpu_user_regs(), regs, HVM_CONTEXT_STACK_BYTES);
 
     /* Has memory been dirtied? */
-    if ( p->dir == IOREQ_READ && p->data_is_ptr )
+    if ( (p->dir == IOREQ_READ) && p->data_is_ptr )
     {
         gmfn = get_mfn_from_gpfn(paging_gva_to_gfn(v, p->data));
-        mark_dirty(v->domain, gmfn);
-    }
+        mark_dirty(d, gmfn);
+    }
+
+    vcpu_end_shutdown_deferral(v);
 }
 
 /*
diff -r 45e9f6d7e422 -r a1b17c48fb40 xen/arch/x86/mm.c
--- a/xen/arch/x86/mm.c Tue Apr 03 10:36:31 2007 +0100
+++ b/xen/arch/x86/mm.c Tue Apr 03 11:44:10 2007 +0100
@@ -806,7 +806,8 @@ void put_page_from_l1e(l1_pgentry_t l1e,
      * (Note that the undestroyable active grants are not a security hole in
      * Xen. All active grants can safely be cleaned up when the domain dies.)
      */
-    if ( (l1e_get_flags(l1e) & _PAGE_GNTTAB) && !d->is_shutdown && 
!d->is_dying )
+    if ( (l1e_get_flags(l1e) & _PAGE_GNTTAB) &&
+         !d->is_shutting_down && !d->is_dying )
     {
         MEM_LOG("Attempt to implicitly unmap a granted PTE %" PRIpte,
                 l1e_get_intpte(l1e));
diff -r 45e9f6d7e422 -r a1b17c48fb40 xen/arch/x86/mm/shadow/multi.c
--- a/xen/arch/x86/mm/shadow/multi.c    Tue Apr 03 10:36:31 2007 +0100
+++ b/xen/arch/x86/mm/shadow/multi.c    Tue Apr 03 11:44:10 2007 +0100
@@ -2823,8 +2823,8 @@ static int sh_page_fault(struct vcpu *v,
          * are OK, this can only have been caused by a failed
          * shadow_set_l*e(), which will have crashed the guest.
          * Get out of the fault handler immediately. */
-        ASSERT(d->is_shutdown);
-        unmap_walk(v, &gw); 
+        ASSERT(d->is_shutting_down);
+        unmap_walk(v, &gw);
         shadow_unlock(d);
         return 0;
     }
diff -r 45e9f6d7e422 -r a1b17c48fb40 xen/common/domain.c
--- a/xen/common/domain.c       Tue Apr 03 10:36:31 2007 +0100
+++ b/xen/common/domain.c       Tue Apr 03 11:44:10 2007 +0100
@@ -59,6 +59,7 @@ struct domain *alloc_domain(domid_t domi
     atomic_set(&d->refcnt, 1);
     spin_lock_init(&d->big_lock);
     spin_lock_init(&d->page_alloc_lock);
+    spin_lock_init(&d->shutdown_lock);
     INIT_LIST_HEAD(&d->page_list);
     INIT_LIST_HEAD(&d->xenpage_list);
 
@@ -83,6 +84,45 @@ void free_domain(struct domain *d)
     xfree(d);
 }
 
+static void __domain_finalise_shutdown(struct domain *d)
+{
+    struct vcpu *v;
+
+    BUG_ON(!spin_is_locked(&d->shutdown_lock));
+
+    if ( d->is_shut_down )
+        return;
+
+    for_each_vcpu ( d, v )
+        if ( !v->paused_for_shutdown )
+            return;
+
+    d->is_shut_down = 1;
+
+    for_each_vcpu ( d, v )
+        vcpu_sleep_nosync(v);
+
+    send_guest_global_virq(dom0, VIRQ_DOM_EXC);
+}
+
+static void vcpu_check_shutdown(struct vcpu *v)
+{
+    struct domain *d = v->domain;
+
+    spin_lock(&d->shutdown_lock);
+
+    if ( d->is_shutting_down )
+    {
+        if ( !v->paused_for_shutdown )
+            atomic_inc(&v->pause_count);
+        v->paused_for_shutdown = 1;
+        v->defer_shutdown = 0;
+        __domain_finalise_shutdown(d);
+    }
+
+    spin_unlock(&d->shutdown_lock);
+}
+
 struct vcpu *alloc_vcpu(
     struct domain *d, unsigned int vcpu_id, unsigned int cpu_id)
 {
@@ -121,6 +161,9 @@ struct vcpu *alloc_vcpu(
     d->vcpu[vcpu_id] = v;
     if ( vcpu_id != 0 )
         d->vcpu[v->vcpu_id-1]->next_in_list = v;
+
+    /* Must be called after making new vcpu visible to for_each_vcpu(). */
+    vcpu_check_shutdown(v);
 
     return v;
 }
@@ -286,7 +329,7 @@ void domain_kill(struct domain *d)
 
 void __domain_crash(struct domain *d)
 {
-    if ( d->is_shutdown )
+    if ( d->is_shutting_down )
     {
         /* Print nothing: the domain is already shutting down. */
     }
@@ -335,16 +378,73 @@ void domain_shutdown(struct domain *d, u
     if ( d->domain_id == 0 )
         dom0_shutdown(reason);
 
-    atomic_inc(&d->pause_count);
-    if ( !xchg(&d->is_shutdown, 1) )
-        d->shutdown_code = reason;
-    else
-        domain_unpause(d);
+    spin_lock(&d->shutdown_lock);
+
+    if ( d->is_shutting_down )
+    {
+        spin_unlock(&d->shutdown_lock);
+        return;
+    }
+
+    d->is_shutting_down = 1;
+    d->shutdown_code = reason;
+
+    smp_mb(); /* set shutdown status /then/ check for per-cpu deferrals */
 
     for_each_vcpu ( d, v )
-        vcpu_sleep_nosync(v);
-
-    send_guest_global_virq(dom0, VIRQ_DOM_EXC);
+    {
+        if ( v->defer_shutdown )
+            continue;
+        atomic_inc(&v->pause_count);
+        v->paused_for_shutdown = 1;
+    }
+
+    __domain_finalise_shutdown(d);
+
+    spin_unlock(&d->shutdown_lock);
+}
+
+void domain_resume(struct domain *d)
+{
+    struct vcpu *v;
+
+    /*
+     * Some code paths assume that shutdown status does not get reset under
+     * their feet (e.g., some assertions make this assumption).
+     */
+    domain_pause(d);
+
+    spin_lock(&d->shutdown_lock);
+
+    d->is_shutting_down = d->is_shut_down = 0;
+
+    for_each_vcpu ( d, v )
+    {
+        if ( v->paused_for_shutdown )
+            vcpu_unpause(v);
+        v->paused_for_shutdown = 0;
+    }
+
+    spin_unlock(&d->shutdown_lock);
+
+    domain_unpause(d);
+}
+
+int vcpu_start_shutdown_deferral(struct vcpu *v)
+{
+    v->defer_shutdown = 1;
+    smp_mb(); /* set deferral status /then/ check for shutdown */
+    if ( unlikely(v->domain->is_shutting_down) )
+        vcpu_check_shutdown(v);
+    return v->defer_shutdown;
+}
+
+void vcpu_end_shutdown_deferral(struct vcpu *v)
+{
+    v->defer_shutdown = 0;
+    smp_mb(); /* clear deferral status /then/ check for shutdown */
+    if ( unlikely(v->domain->is_shutting_down) )
+        vcpu_check_shutdown(v);
 }
 
 void domain_pause_for_debugger(void)
diff -r 45e9f6d7e422 -r a1b17c48fb40 xen/common/domctl.c
--- a/xen/common/domctl.c       Tue Apr 03 10:36:31 2007 +0100
+++ b/xen/common/domctl.c       Tue Apr 03 11:44:10 2007 +0100
@@ -115,7 +115,7 @@ void getdomaininfo(struct domain *d, str
 
     info->flags = flags |
         (d->is_dying                ? XEN_DOMINF_dying    : 0) |
-        (d->is_shutdown             ? XEN_DOMINF_shutdown : 0) |
+        (d->is_shut_down            ? XEN_DOMINF_shutdown : 0) |
         (d->is_paused_by_controller ? XEN_DOMINF_paused   : 0) |
         d->shutdown_code << XEN_DOMINF_shutdownshift;
 
@@ -287,8 +287,7 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domc
         if ( d == NULL )
             break;
 
-        if ( xchg(&d->is_shutdown, 0) )
-            domain_unpause(d);
+        domain_resume(d);
         rcu_unlock_domain(d);
         ret = 0;
     }
diff -r 45e9f6d7e422 -r a1b17c48fb40 xen/include/xen/sched.h
--- a/xen/include/xen/sched.h   Tue Apr 03 10:36:31 2007 +0100
+++ b/xen/include/xen/sched.h   Tue Apr 03 11:44:10 2007 +0100
@@ -114,6 +114,10 @@ struct vcpu
     bool_t           nmi_pending;
     /* Avoid NMI reentry by allowing NMIs to be masked for short periods. */
     bool_t           nmi_masked;
+    /* Require shutdown to be deferred for some asynchronous operation? */
+    bool_t           defer_shutdown;
+    /* VCPU is paused following shutdown request (d->is_shutting_down)? */
+    bool_t           paused_for_shutdown;
 
     unsigned long    pause_flags;
     atomic_t         pause_count;
@@ -193,7 +197,9 @@ struct domain
     bool_t           is_paused_by_controller;
 
     /* Guest has shut down (inc. reason code)? */
-    bool_t           is_shutdown;
+    spinlock_t       shutdown_lock;
+    bool_t           is_shutting_down; /* in process of shutting down? */
+    bool_t           is_shut_down;     /* fully shut down? */
     int              shutdown_code;
 
     atomic_t         pause_count;
@@ -331,7 +337,11 @@ void domain_destroy(struct domain *d);
 void domain_destroy(struct domain *d);
 void domain_kill(struct domain *d);
 void domain_shutdown(struct domain *d, u8 reason);
+void domain_resume(struct domain *d);
 void domain_pause_for_debugger(void);
+
+int vcpu_start_shutdown_deferral(struct vcpu *v);
+void vcpu_end_shutdown_deferral(struct vcpu *v);
 
 /*
  * Mark specified domain as crashed. This function always returns, even if the

_______________________________________________
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] xen: Allow vcpus to defer a shutdown request across critical, Xen patchbot-unstable <=