]> xenbits.xensource.com Git - xen.git/commitdiff
Add CPU status info and a status call to the CPU on/offline sysctls.
authorKeir Fraser <keir.fraser@citrix.com>
Tue, 17 Mar 2009 14:25:41 +0000 (14:25 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Tue, 17 Mar 2009 14:25:41 +0000 (14:25 +0000)
Signed-off-by: Frank van der Linden <frank.vanderlinden@sun.com>
xen/arch/x86/smpboot.c
xen/arch/x86/sysctl.c
xen/include/public/sysctl.h

index 2842fa6a579f1d8fb0af1f5f413a904f55ef360c..64b55ebc86cb0c345224e1acc5e89551d9a4f0f9 100644 (file)
@@ -1426,8 +1426,10 @@ int __devinit __cpu_up(unsigned int cpu)
         * cpu_callin_map is set during AP kickstart process. Its reset
         * when a cpu is taken offline from cpu_exit_clear().
         */
-       if (!cpu_isset(cpu, cpu_callin_map))
+       if (!cpu_isset(cpu, cpu_callin_map)) {
                ret = __smp_prepare_cpu(cpu);
+               smpboot_restore_warm_reset_vector();
+       }
 
        if (ret)
                return -EIO;
index dbb54ede0985f2a8781ebd1d3aeb073b5c8e736f..faf3f5157c71bdd4d9a8ae86e510246862f9f175 100644 (file)
@@ -38,7 +38,7 @@ static long cpu_down_helper(void *data)
 long arch_do_sysctl(
     struct xen_sysctl *sysctl, XEN_GUEST_HANDLE(xen_sysctl_t) u_sysctl)
 {
-    long ret = 0;
+    long ret = 0, status;
 
     switch ( sysctl->cmd )
     {
@@ -102,19 +102,41 @@ long arch_do_sysctl(
     {
         unsigned int cpu = sysctl->u.cpu_hotplug.cpu;
 
+        if (cpu_present(cpu)) {
+            status = cpu_online(cpu) ? XEN_CPU_HOTPLUG_STATUS_ONLINE :
+                XEN_CPU_HOTPLUG_STATUS_OFFLINE;
+        } else {
+            status = -EINVAL;
+        }
+
         switch ( sysctl->u.cpu_hotplug.op )
         {
         case XEN_SYSCTL_CPU_HOTPLUG_ONLINE:
             ret = cpu_up(cpu);
+            /*
+             * In the case of a true hotplug, this CPU wasn't present
+             * before, so return the 'new' status for it.
+             */
+            if (ret == 0 && status == -EINVAL)
+                status = XEN_CPU_HOTPLUG_STATUS_NEW;
             break;
         case XEN_SYSCTL_CPU_HOTPLUG_OFFLINE:
             ret = continue_hypercall_on_cpu(
                 0, cpu_down_helper, (void *)(unsigned long)cpu);
             break;
+        case XEN_SYSCTL_CPU_HOTPLUG_STATUS:
+            ret = 0;
+            break;
         default:
             ret = -EINVAL;
             break;
         }
+
+        /*
+         * If the operation was successful, return the old status.
+         */
+        if (ret >= 0)
+            ret = status;
     }
     break;
 
index 7e1a4968f62cdb334b16e492978f81b5620b1455..fe9f4b56115c5ee5938f8b3234bcbe788746aae1 100644 (file)
@@ -262,12 +262,21 @@ struct xen_sysctl_get_pmstat {
 typedef struct xen_sysctl_get_pmstat xen_sysctl_get_pmstat_t;
 DEFINE_XEN_GUEST_HANDLE(xen_sysctl_get_pmstat_t);
 
+/*
+ * Status codes. Must be greater than 0 to avoid confusing
+ * sysctl callers that see 0 as a plain successful return.
+ */
+#define XEN_CPU_HOTPLUG_STATUS_OFFLINE 1
+#define XEN_CPU_HOTPLUG_STATUS_ONLINE  2
+#define XEN_CPU_HOTPLUG_STATUS_NEW     3
+
 #define XEN_SYSCTL_cpu_hotplug       11
 struct xen_sysctl_cpu_hotplug {
     /* IN variables */
     uint32_t cpu;   /* Physical cpu. */
 #define XEN_SYSCTL_CPU_HOTPLUG_ONLINE  0
 #define XEN_SYSCTL_CPU_HOTPLUG_OFFLINE 1
+#define XEN_SYSCTL_CPU_HOTPLUG_STATUS 2
     uint32_t op;    /* hotplug opcode */
 };
 typedef struct xen_sysctl_cpu_hotplug xen_sysctl_cpu_hotplug_t;