]> xenbits.xensource.com Git - people/iwj/xen.git/commitdiff
xen/dom0: Fix latent dom0 construction bugs on all architectures
authorAndrew Cooper <andrew.cooper3@citrix.com>
Mon, 16 Oct 2017 13:20:00 +0000 (13:20 +0000)
committerAndrew Cooper <andrew.cooper3@citrix.com>
Tue, 17 Oct 2017 13:47:05 +0000 (14:47 +0100)
 * x86 PV and ARM dom0's must not clear _VPF_down from v->pause_flags until
   all state is actually set up.  As it currently stands, d0v0 is eligible for
   scheduling before its registers have been set.  This is latent as we also
   hold a systemcontroller pause reference at the time which prevents d0 from
   being scheduled.

 * x86 PVH previously was not setting v->is_initialised for d0v0, despite
   setting the vcpu running eventually.  Therefore, a later VCPUOP_initialise
   hypercall will modify state under the feet of the running vcpu.  This is
   latent as PVH dom0 construction don't yet function.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
Release-acked-by: Julien Grall <julien.grall@linaro.org>
xen/arch/arm/domain_build.c
xen/arch/x86/dom0_build.c
xen/arch/x86/hvm/dom0_build.c
xen/arch/x86/pv/dom0_build.c

index 4636b17aa6bca6619090c2996f16316b0c26775b..bf29299707b45bc0667cd8813c05dab3d770cb9a 100644 (file)
@@ -2197,9 +2197,6 @@ int construct_dom0(struct domain *d)
 
     discard_initial_modules();
 
-    v->is_initialised = 1;
-    clear_bit(_VPF_down, &v->pause_flags);
-
     memset(regs, 0, sizeof(*regs));
 
     regs->pc = (register_t)kinfo.entry;
@@ -2247,6 +2244,9 @@ int construct_dom0(struct domain *d)
             vcpu_switch_to_aarch64_mode(d->vcpu[i]);
     }
 
+    v->is_initialised = 1;
+    clear_bit(_VPF_down, &v->pause_flags);
+
     return 0;
 }
 
index e4bffd5d9ea4b0fd44ca8aac2410707d48f10648..bf992fef6d4baa37625052a3eb5fe3ee8d914a98 100644 (file)
@@ -466,6 +466,8 @@ int __init construct_dom0(struct domain *d, const module_t *image,
                           void *(*bootstrap_map)(const module_t *),
                           char *cmdline)
 {
+    int rc;
+
     /* Sanity! */
     BUG_ON(d->domain_id != 0);
     BUG_ON(d->vcpu[0] == NULL);
@@ -481,8 +483,15 @@ int __init construct_dom0(struct domain *d, const module_t *image,
     }
 #endif
 
-    return (is_hvm_domain(d) ? dom0_construct_pvh : dom0_construct_pv)
-           (d, image, image_headroom, initrd,bootstrap_map, cmdline);
+    rc = (is_hvm_domain(d) ? dom0_construct_pvh : dom0_construct_pv)
+         (d, image, image_headroom, initrd, bootstrap_map, cmdline);
+    if ( rc )
+        return rc;
+
+    /* Sanity! */
+    BUG_ON(!d->vcpu[0]->is_initialised);
+
+    return 0;
 }
 
 /*
index e8f746c70b8a3fb3cfa7fe876d6d771e0ebe4550..a67071c739baa67469c4f498482200f79ca96127 100644 (file)
@@ -614,6 +614,7 @@ static int __init pvh_setup_cpus(struct domain *d, paddr_t entry,
 
     update_domain_wallclock_time(d);
 
+    v->is_initialised = 1;
     clear_bit(_VPF_down, &v->pause_flags);
 
     return 0;
index dcbee43e8ff02e8e329726750bf5758fc81d1f3f..8ad7e3df1489b281cbe39e273bd30ce34cd6ffe3 100644 (file)
@@ -847,9 +847,6 @@ int __init dom0_construct_pv(struct domain *d,
 
     update_domain_wallclock_time(d);
 
-    v->is_initialised = 1;
-    clear_bit(_VPF_down, &v->pause_flags);
-
     /*
      * Initial register values:
      *  DS,ES,FS,GS = FLAT_KERNEL_DS
@@ -883,6 +880,9 @@ int __init dom0_construct_pv(struct domain *d,
     if ( d->domain_id == hardware_domid )
         iommu_hwdom_init(d);
 
+    v->is_initialised = 1;
+    clear_bit(_VPF_down, &v->pause_flags);
+
     return 0;
 
 out: