Allow domains to set a shutdown code without actually shutting down
authorKeir Fraser <keir.fraser@citrix.com>
Fri, 4 Jun 2010 08:33:11 +0000 (09:33 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Fri, 4 Jun 2010 08:33:11 +0000 (09:33 +0100)
Useful for Windows guests, since the PV drivers are notified that
the domain is about to crash just before the crash dump gets written.

Signed-off-by: Tim Deegan <Tim.Deegan@citrix.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
xen/common/domain.c
xen/common/schedule.c
xen/include/public/sched.h
xen/include/public/trace.h

index f8d8a25346da2be82dc5521eb25903c676fe87a6..c7928f94d6947da0022e215efaa33b023db8104e 100644 (file)
@@ -228,11 +228,13 @@ struct domain *domain_create(
     atomic_set(&d->refcnt, 1);
     spin_lock_init_prof(d, domain_lock);
     spin_lock_init_prof(d, page_alloc_lock);
-    spin_lock_init(&d->shutdown_lock);
     spin_lock_init(&d->hypercall_deadlock_mutex);
     INIT_PAGE_LIST_HEAD(&d->page_list);
     INIT_PAGE_LIST_HEAD(&d->xenpage_list);
 
+    spin_lock_init(&d->shutdown_lock);
+    d->shutdown_code = -1;
+
     if ( domcr_flags & DOMCRF_hvm )
         d->is_hvm = 1;
 
@@ -485,11 +487,15 @@ void domain_shutdown(struct domain *d, u8 reason)
 {
     struct vcpu *v;
 
+    spin_lock(&d->shutdown_lock);
+
+    if ( d->shutdown_code == -1 )
+        d->shutdown_code = reason;
+    reason = d->shutdown_code;
+
     if ( d->domain_id == 0 )
         dom0_shutdown(reason);
 
-    spin_lock(&d->shutdown_lock);
-
     if ( d->is_shutting_down )
     {
         spin_unlock(&d->shutdown_lock);
@@ -497,7 +503,6 @@ void domain_shutdown(struct domain *d, u8 reason)
     }
 
     d->is_shutting_down = 1;
-    d->shutdown_code = reason;
 
     smp_mb(); /* set shutdown status /then/ check for per-cpu deferrals */
 
@@ -529,6 +534,7 @@ void domain_resume(struct domain *d)
     spin_lock(&d->shutdown_lock);
 
     d->is_shutting_down = d->is_shut_down = 0;
+    d->shutdown_code = -1;
 
     for_each_vcpu ( d, v )
     {
index 01651b3d3b6ef0f0ac28d82286ed67e6852aa1d0..655dbd034ca6000456eda2ace60892c710e952d3 100644 (file)
@@ -704,6 +704,27 @@ ret_t do_sched_op(int cmd, XEN_GUEST_HANDLE(void) arg)
         break;
     }
 
+    case SCHEDOP_shutdown_code:
+    {
+        struct sched_shutdown sched_shutdown;
+        struct domain *d = current->domain;
+
+        ret = -EFAULT;
+        if ( copy_from_guest(&sched_shutdown, arg, 1) )
+            break;
+
+        TRACE_3D(TRC_SCHED_SHUTDOWN_CODE,
+                 d->domain_id, current->vcpu_id, sched_shutdown.reason);
+
+        spin_lock(&d->shutdown_lock);
+        if ( d->shutdown_code == -1 )
+            d->shutdown_code = (u8)sched_shutdown.reason;
+        spin_unlock(&d->shutdown_lock);
+
+        ret = 0;
+        break;
+    }
+
     case SCHEDOP_poll:
     {
         struct sched_poll sched_poll;
index 2227a95be625697da21fe54aeaf2c9b574094a7d..e498c3c501811c905eaeec38850340ad793fcf3d 100644 (file)
@@ -98,6 +98,13 @@ struct sched_remote_shutdown {
 typedef struct sched_remote_shutdown sched_remote_shutdown_t;
 DEFINE_XEN_GUEST_HANDLE(sched_remote_shutdown_t);
 
+/*
+ * Latch a shutdown code, so that when the domain later shuts down it
+ * reports this code to the control tools.
+ * @arg == as for SCHEDOP_shutdown.
+ */
+#define SCHEDOP_shutdown_code 5
+
 /*
  * Reason codes for SCHEDOP_shutdown. These may be interpreted by control
  * software to determine the appropriate action. For the most part, Xen does
index 0a8f1adfa3cd87e456f8a2d44493d5ab60f1bea1..c762c1858a5504d026010173ab6d75cee0aeb20c 100644 (file)
@@ -79,6 +79,7 @@
 #define TRC_SCHED_DOM_TIMER_FN   (TRC_SCHED_VERBOSE + 13)
 #define TRC_SCHED_SWITCH_INFPREV (TRC_SCHED_VERBOSE + 14)
 #define TRC_SCHED_SWITCH_INFNEXT (TRC_SCHED_VERBOSE + 15)
+#define TRC_SCHED_SHUTDOWN_CODE  (TRC_SCHED_VERBOSE + 16)
 
 #define TRC_MEM_PAGE_GRANT_MAP      (TRC_MEM + 1)
 #define TRC_MEM_PAGE_GRANT_UNMAP    (TRC_MEM + 2)