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

[Xen-devel] [PATCH v2 53/62] xen/pvshim: support vCPU hotplug



From: Roger Pau Monne <roger.pau@xxxxxxxxxx>

Signed-off-by: Roger Pau Monné <roger.pau@xxxxxxxxxx>
---
Changes since v1:
 - Fix hotplug so that v->initialized is checked before attempting to
   bring up the physical CPU.
 - Fix ARM compilation.
---
 xen/arch/x86/pv/shim.c        | 63 +++++++++++++++++++++++++++++++++++++++++++
 xen/common/domain.c           | 38 +++++++++++++++++---------
 xen/include/asm-x86/pv/shim.h | 12 +++++++++
 xen/include/xen/domain.h      |  1 +
 4 files changed, 102 insertions(+), 12 deletions(-)

diff --git a/xen/arch/x86/pv/shim.c b/xen/arch/x86/pv/shim.c
index e3e101a5b1..68ec7bed8e 100644
--- a/xen/arch/x86/pv/shim.c
+++ b/xen/arch/x86/pv/shim.c
@@ -751,6 +751,69 @@ static long pv_shim_grant_table_op(unsigned int cmd,
     return rc;
 }
 
+long pv_shim_cpu_up(void *data)
+{
+    struct vcpu *v = data;
+    struct domain *d = v->domain;
+    bool wake;
+
+    BUG_ON(smp_processor_id() != 0);
+
+    domain_lock(d);
+    if ( !v->is_initialised )
+    {
+        domain_unlock(d);
+        return -EINVAL;
+    }
+
+    if ( !cpu_online(v->vcpu_id) )
+    {
+        long rc = cpu_up_helper((void *)(unsigned long)v->vcpu_id);
+
+        if ( rc )
+        {
+            domain_unlock(d);
+            gprintk(XENLOG_ERR, "Failed to bring up CPU#%u: %ld\n",
+                    v->vcpu_id, rc);
+            return rc;
+        }
+    }
+
+    wake = test_and_clear_bit(_VPF_down, &v->pause_flags);
+    domain_unlock(d);
+    if ( wake )
+        vcpu_wake(v);
+
+    return 0;
+}
+
+long pv_shim_cpu_down(void *data)
+{
+    struct vcpu *v = data;
+    long rc;
+
+    BUG_ON(smp_processor_id() != 0);
+
+    if ( !test_and_set_bit(_VPF_down, &v->pause_flags) )
+        vcpu_sleep_sync(v);
+
+    if ( cpu_online(v->vcpu_id) )
+    {
+        rc = cpu_down_helper((void *)(unsigned long)v->vcpu_id);
+        if ( rc )
+            gprintk(XENLOG_ERR, "Failed to bring down CPU#%u: %ld\n",
+                    v->vcpu_id, rc);
+        /*
+         * NB: do not propagate errors from cpu_down_helper failing. The shim
+         * is going to run with extra CPUs, but that's not going to prevent
+         * normal operation. OTOH most guests are not prepared to handle an
+         * error on VCPUOP_down failing, and will likely panic.
+         */
+    }
+
+    return 0;
+}
+
 domid_t get_initial_domain_id(void)
 {
     uint32_t eax, ebx, ecx, edx;
diff --git a/xen/common/domain.c b/xen/common/domain.c
index 6ed21b2536..558318e852 100644
--- a/xen/common/domain.c
+++ b/xen/common/domain.c
@@ -1301,22 +1301,36 @@ long do_vcpu_op(int cmd, unsigned int vcpuid, 
XEN_GUEST_HANDLE_PARAM(void) arg)
 
         break;
 
-    case VCPUOP_up: {
-        bool_t wake = 0;
-        domain_lock(d);
-        if ( !v->is_initialised )
-            rc = -EINVAL;
+    case VCPUOP_up:
+#ifdef CONFIG_X86
+        if ( pv_shim )
+            rc = continue_hypercall_on_cpu(0, pv_shim_cpu_up, v);
         else
-            wake = test_and_clear_bit(_VPF_down, &v->pause_flags);
-        domain_unlock(d);
-        if ( wake )
-            vcpu_wake(v);
+#endif
+        {
+            bool wake = false;
+
+            domain_lock(d);
+            if ( !v->is_initialised )
+                rc = -EINVAL;
+            else
+                wake = test_and_clear_bit(_VPF_down, &v->pause_flags);
+            domain_unlock(d);
+            if ( wake )
+                vcpu_wake(v);
+        }
+
         break;
-    }
 
     case VCPUOP_down:
-        if ( !test_and_set_bit(_VPF_down, &v->pause_flags) )
-            vcpu_sleep_nosync(v);
+#ifdef CONFIG_X86
+        if ( pv_shim )
+            rc = continue_hypercall_on_cpu(0, pv_shim_cpu_down, v);
+        else
+#endif
+            if ( !test_and_set_bit(_VPF_down, &v->pause_flags) )
+                vcpu_sleep_nosync(v);
+
         break;
 
     case VCPUOP_is_up:
diff --git a/xen/include/asm-x86/pv/shim.h b/xen/include/asm-x86/pv/shim.h
index 0ef452158e..eb59ddd38a 100644
--- a/xen/include/asm-x86/pv/shim.h
+++ b/xen/include/asm-x86/pv/shim.h
@@ -37,6 +37,8 @@ void pv_shim_setup_dom(struct domain *d, l4_pgentry_t 
*l4start,
                        start_info_t *si);
 int pv_shim_shutdown(uint8_t reason);
 void pv_shim_inject_evtchn(unsigned int port);
+long pv_shim_cpu_up(void *data);
+long pv_shim_cpu_down(void *data);
 domid_t get_initial_domain_id(void);
 uint64_t pv_shim_mem(uint64_t avail);
 
@@ -60,6 +62,16 @@ static inline void pv_shim_inject_evtchn(unsigned int port)
 {
     ASSERT_UNREACHABLE();
 }
+static inline long pv_shim_cpu_up(void *data)
+{
+    ASSERT_UNREACHABLE();
+    return 0;
+}
+static inline long pv_shim_cpu_down(void *data)
+{
+    ASSERT_UNREACHABLE();
+    return 0;
+}
 static inline domid_t get_initial_domain_id(void)
 {
     return 0;
diff --git a/xen/include/xen/domain.h b/xen/include/xen/domain.h
index 347f264047..eb62f1dab1 100644
--- a/xen/include/xen/domain.h
+++ b/xen/include/xen/domain.h
@@ -17,6 +17,7 @@ struct vcpu *alloc_vcpu(
     struct domain *d, unsigned int vcpu_id, unsigned int cpu_id);
 struct vcpu *alloc_dom0_vcpu0(struct domain *dom0);
 int vcpu_reset(struct vcpu *);
+int vcpu_up(struct vcpu *v);
 
 struct xen_domctl_getdomaininfo;
 void getdomaininfo(struct domain *d, struct xen_domctl_getdomaininfo *info);
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

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