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

[Xen-devel] [PATCH] Add hypercall to expose physical CPU in xen hypervisor



This patch add hypercall to xen hypervisor to expose physical CPU information. 
It also make some changes to current cpu online/offline logic:
1) Firstly, cpu online/offline will trigger a vIRQ to dom0 for status changes 
notification.
2) It also add an interface to platform operation to online/offline physical 
CPU. Currently the cpu online/offline interface is in sysctl, which can't be 
triggered in kernel. With this change, it is possible to trigger cpu 
online/offline in dom0 through sysfs interface.

Signed-off-by: Jiang, Yunhong <yunhong.jiang@xxxxxxxxx>


diff -r bd60c77071eb xen/arch/x86/platform_hypercall.c
--- a/xen/arch/x86/platform_hypercall.c Tue Nov 03 12:41:54 2009 +0000
+++ b/xen/arch/x86/platform_hypercall.c Fri Nov 06 01:29:00 2009 +0800
@@ -39,6 +39,8 @@ DEFINE_SPINLOCK(xenpf_lock);
 # define copy_to_compat copy_to_guest
 # undef guest_from_compat_handle
 # define guest_from_compat_handle(x,y) ((x)=(y))
+# undef compat_handle_is_null
+# define compat_handle_is_null guest_handle_is_null
 #else
 extern spinlock_t xenpf_lock;
 #endif
@@ -51,6 +53,12 @@ static long cpu_frequency_change_helper(
 static long cpu_frequency_change_helper(void *data)
 {
     return cpu_frequency_change(this_cpu(freq));
+}
+
+static long cpu_down_helper(void *data)
+{
+    int cpu = (unsigned long)data;
+    return cpu_down(cpu);
 }
 
 ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op)
@@ -385,7 +393,100 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xe
             break;
         }
         break;
- 
+
+    case XENPF_get_cpuinfo:
+    {
+        int ncpu = num_present_cpus(), cpu, i;
+        struct xen_physical_cpuinfo *pcpus, *pcpu;
+        struct xenpf_pcpu_info *g_info;
+
+        ret = -EINVAL;
+        g_info = &op->u.pcpu_info;
+
+        if (op->u.pcpu_info.ncpus <= 0)
+            goto done;
+
+        if ( compat_handle_is_null(g_info->info) )
+        {
+            ret = -EINVAL;
+            goto out;
+        }
+
+        ncpu = min(ncpu, (int)op->u.pcpu_info.ncpus);
+        pcpus = xmalloc_array(struct xen_physical_cpuinfo, ncpu);
+        ret = -ENOMEM;
+        if (pcpus == NULL)
+            goto out;
+
+        memset(pcpus, 0, sizeof(struct xen_physical_cpuinfo) * ncpu);
+
+        pcpu = pcpus;
+
+        i = 0;
+        spin_lock(&cpu_add_remove_lock);
+        for_each_present_cpu(cpu)
+        {
+            pcpu->xen_cpuid = cpu;
+            pcpu->apic_id = x86_cpu_to_apicid[cpu];
+            pcpu->acpi_id = acpi_get_processor_id(cpu);
+            ASSERT(pcpu->apic_id != BAD_APICID);
+            if (cpu_online(cpu))
+                pcpu->flags |= XEN_PCPU_FLAGS_ONLINE;
+            pcpu++;
+            if (i++ == ncpu)
+                break;
+        }
+        spin_unlock(&cpu_add_remove_lock);
+        ret = -EFAULT;
+        if( copy_to_compat(g_info->info, pcpus, ncpu))
+            goto out;
+        xfree(pcpus);
+done:
+        op->u.pcpu_info.max_cpus = num_possible_cpus();
+        op->u.pcpu_info.ncpus = ncpu;
+        ret = copy_to_guest(u_xenpf_op, op, 1) ? -EFAULT : 0;
+    }
+    break;
+
+    case XENPF_resource_hotplug:
+    {
+        int cpu;
+
+        switch ( op->u.resource.sub_cmd)
+        {
+        case XEN_CPU_online:
+            cpu = op->u.resource.u.cpu_ol.cpuid;
+            if (!cpu_present(cpu))
+            {
+                ret = -EINVAL;
+                break;
+            }
+            else if (cpu_online(cpu))
+            {
+                ret = 0;
+                break;
+            }
+
+            ret = cpu_up(cpu);
+            break;
+        case XEN_CPU_offline:
+            cpu = op->u.resource.u.cpu_ol.cpuid;
+            if (!cpu_present(cpu))
+            {
+                ret = -EINVAL;
+                break;
+            } else if (!cpu_online(cpu))
+            {
+                ret = 0;
+                break;
+            }
+            ret = continue_hypercall_on_cpu(
+                0, cpu_down_helper, (void *)(unsigned long)cpu);
+            break;
+        }
+    }
+    break;
+
     default:
         ret = -ENOSYS;
         break;
diff -r bd60c77071eb xen/arch/x86/smpboot.c
--- a/xen/arch/x86/smpboot.c    Tue Nov 03 12:41:54 2009 +0000
+++ b/xen/arch/x86/smpboot.c    Fri Nov 06 01:29:00 2009 +0800
@@ -44,6 +44,7 @@
 #include <xen/softirq.h>
 #include <xen/serial.h>
 #include <xen/numa.h>
+#include <xen/event.h>
 #include <asm/current.h>
 #include <asm/mc146818rtc.h>
 #include <asm/desc.h>
@@ -104,7 +105,7 @@ DEFINE_PER_CPU(int, cpu_state) = { 0 };
 DEFINE_PER_CPU(int, cpu_state) = { 0 };
 
 static void *stack_base[NR_CPUS];
-static DEFINE_SPINLOCK(cpu_add_remove_lock);
+DEFINE_SPINLOCK(cpu_add_remove_lock);
 
 /*
  * The bootstrap kernel entry code has set these up. Save them for
@@ -1342,6 +1343,8 @@ int cpu_down(unsigned int cpu)
        cpu_mcheck_distribute_cmci();
 
 out:
+    if (!err)
+        send_guest_global_virq(dom0, VIRQ_PCPU_STATE);
        spin_unlock(&cpu_add_remove_lock);
        return err;
 }
@@ -1362,6 +1365,8 @@ int cpu_up(unsigned int cpu)
                goto out;
 
 out:
+    if (!err)
+        send_guest_global_virq(dom0, VIRQ_PCPU_STATE);
        spin_unlock(&cpu_add_remove_lock);
        return err;
 }
diff -r bd60c77071eb xen/arch/x86/x86_64/platform_hypercall.c
--- a/xen/arch/x86/x86_64/platform_hypercall.c  Tue Nov 03 12:41:54 2009 +0000
+++ b/xen/arch/x86/x86_64/platform_hypercall.c  Fri Nov 06 00:29:38 2009 +0800
@@ -23,6 +23,11 @@ DEFINE_XEN_GUEST_HANDLE(compat_platform_
 #define xen_processor_power_t   compat_processor_power_t
 #define set_cx_pminfo           compat_set_cx_pminfo
 
+#define xen_physical_cpuinfo compat_physical_cpuinfo
+#define xen_physical_cpuinfo_ compat_physical_cpuinfo_t
+#define xenpf_pcpu_info compat_pf_pcpu_info
+#define xenpf_pcpu_info_t compat_pf_pcpu_info_t
+
 #define xenpf_enter_acpi_sleep compat_pf_enter_acpi_sleep
 
 #define COMPAT
diff -r bd60c77071eb xen/include/asm-x86/smp.h
--- a/xen/include/asm-x86/smp.h Tue Nov 03 12:41:54 2009 +0000
+++ b/xen/include/asm-x86/smp.h Fri Nov 06 01:29:00 2009 +0800
@@ -56,6 +56,7 @@ extern u32 cpu_2_logical_apicid[];
 #define CPU_ONLINE     0x0002  /* CPU is up */
 #define CPU_DEAD       0x0004  /* CPU is dead */
 DECLARE_PER_CPU(int, cpu_state);
+extern spinlock_t(cpu_add_remove_lock);
 
 #ifdef CONFIG_HOTPLUG_CPU
 #define cpu_is_offline(cpu) unlikely(!cpu_online(cpu))
diff -r bd60c77071eb xen/include/public/platform.h
--- a/xen/include/public/platform.h     Tue Nov 03 12:41:54 2009 +0000
+++ b/xen/include/public/platform.h     Fri Nov 06 01:29:00 2009 +0800
@@ -312,6 +312,44 @@ typedef struct xenpf_set_processor_pminf
 typedef struct xenpf_set_processor_pminfo xenpf_set_processor_pminfo_t;
 DEFINE_XEN_GUEST_HANDLE(xenpf_set_processor_pminfo_t);
 
+#define XENPF_get_cpuinfo 55
+struct xen_physical_cpuinfo {
+    uint32_t xen_cpuid;
+    uint32_t apic_id;
+    uint32_t acpi_id;
+#define XEN_PCPU_FLAGS_ONLINE 1
+    uint32_t flags;
+};
+typedef struct xen_physical_cpuinfo xen_physical_cpuinfo_t;
+DEFINE_XEN_GUEST_HANDLE(xen_physical_cpuinfo_t);
+
+struct xenpf_pcpu_info
+{
+    /* IN/OUT */
+    uint32_t ncpus;
+    /* OUT */
+    /* The possible CPU */
+    uint32_t max_cpus;
+    XEN_GUEST_HANDLE(xen_physical_cpuinfo_t) info;
+};
+typedef struct xenpf_pcpu_info xenpf_pcpu_info_t;
+DEFINE_XEN_GUEST_HANDLE(xenpf_pcpu_info_t);
+
+struct xenpf_cpu_ol
+{
+    uint32_t cpuid;
+};
+
+#define XENPF_resource_hotplug 56
+struct xenpf_resource_hotplug {
+    uint32_t sub_cmd;
+#define XEN_CPU_online      1
+#define XEN_CPU_offline     2
+    union {
+        struct xenpf_cpu_ol   cpu_ol;
+    }u;
+};
+
 struct xen_platform_op {
     uint32_t cmd;
     uint32_t interface_version; /* XENPF_INTERFACE_VERSION */
@@ -327,6 +365,8 @@ struct xen_platform_op {
         struct xenpf_change_freq       change_freq;
         struct xenpf_getidletime       getidletime;
         struct xenpf_set_processor_pminfo set_pminfo;
+        struct xenpf_pcpu_info          pcpu_info;
+        struct xenpf_resource_hotplug   resource;
         uint8_t                        pad[128];
     } u;
 };
diff -r bd60c77071eb xen/include/public/xen.h
--- a/xen/include/public/xen.h  Tue Nov 03 12:41:54 2009 +0000
+++ b/xen/include/public/xen.h  Fri Nov 06 00:55:32 2009 +0800
@@ -145,6 +145,7 @@ DEFINE_XEN_GUEST_HANDLE(xen_pfn_t);
 #define VIRQ_DEBUGGER   6  /* G. (DOM0) A domain has paused for debugging.   */
 #define VIRQ_XENOPROF   7  /* V. XenOprofile interrupt: new sample available */
 #define VIRQ_CON_RING   8  /* G. (DOM0) Bytes received on console            */
+#define VIRQ_PCPU_STATE 9  /* G. (DOM0) PCPU state changed                   */
 
 /* Architecture-specific VIRQ definitions. */
 #define VIRQ_ARCH_0    16

Attachment: xen_pcpu.patch
Description: xen_pcpu.patch

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel

 


Rackspace

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