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

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



I adjust the patch according to your feedback, please have a look. I leave some 
space in struct xen_physical_cpuinfo for future usage, like cpu topolonogy, or 
other stastic information.

Thanks
Yunhong Jiang

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 494ad84ad38c xen/arch/x86/platform_hypercall.c
--- a/xen/arch/x86/platform_hypercall.c Mon Nov 09 22:41:23 2009 +0000
+++ b/xen/arch/x86/platform_hypercall.c Tue Nov 10 05:18:25 2009 +0800
@@ -53,6 +53,12 @@ static long cpu_frequency_change_helper(
     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)
 {
     ret_t ret = 0;
@@ -385,7 +391,97 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xe
             break;
         }
         break;
- 
+
+    case XENPF_get_cpuinfo:
+    {
+        int i;
+        struct xenpf_pcpu_info *g_info;
+        struct xen_physical_cpuinfo pcpu;
+        XEN_GUEST_HANDLE(xen_physical_cpuinfo_t) g_cpus;
+
+        g_info = &op->u.pcpu_info;
+        if (g_info->info_num <= 0 )
+        {
+            op->u.pcpu_info.max_present = last_cpu(cpu_present_map);
+            op->u.pcpu_info.max_possible = last_cpu(cpu_possible_map);
+            goto done;
+        }
+
+        guest_from_compat_handle(g_cpus, g_info->info);
+
+        spin_lock(&cpu_add_remove_lock);
+
+        ret = -EFAULT;
+        for (i = 0; i < g_info->info_num; i++)
+        {
+            if (copy_from_guest_offset(&pcpu, g_cpus, i, 1) )
+                goto out;
+
+            if ( (pcpu.xen_cpuid >= NR_CPUS) ||
+                 (pcpu.xen_cpuid < 0) ||
+                 !cpu_present(pcpu.xen_cpuid) )
+            {
+                pcpu.flags |= XEN_PCPU_FLAGS_INVALID;
+            }
+            else
+            {
+                pcpu.apic_id = x86_cpu_to_apicid[pcpu.xen_cpuid];
+                pcpu.acpi_id = acpi_get_processor_id(pcpu.xen_cpuid);
+                ASSERT(pcpu.apic_id != BAD_APICID);
+                if (cpu_online(pcpu.xen_cpuid))
+                    pcpu.flags |= XEN_PCPU_FLAGS_ONLINE;
+            }
+
+            if ( copy_to_guest_offset(g_cpus, i, &pcpu, 1) )
+                goto out;
+        }
+        op->u.pcpu_info.max_present = last_cpu(cpu_present_map);
+        op->u.pcpu_info.max_possible = last_cpu(cpu_possible_map);
+        spin_unlock(&cpu_add_remove_lock);
+done:
+        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 494ad84ad38c xen/arch/x86/smpboot.c
--- a/xen/arch/x86/smpboot.c    Mon Nov 09 22:41:23 2009 +0000
+++ b/xen/arch/x86/smpboot.c    Tue Nov 10 05:18:25 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 494ad84ad38c xen/arch/x86/x86_64/platform_hypercall.c
--- a/xen/arch/x86/x86_64/platform_hypercall.c  Mon Nov 09 22:41:23 2009 +0000
+++ b/xen/arch/x86/x86_64/platform_hypercall.c  Tue Nov 10 05:18:25 2009 +0800
@@ -23,6 +23,12 @@ 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_GUEST_HANDLE(compat_physical_cpuinfo_t);
+#define xen_physical_cpuinfo compat_physical_cpuinfo
+#define xen_physical_cpuinfo_t 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 494ad84ad38c xen/include/asm-x86/smp.h
--- a/xen/include/asm-x86/smp.h Mon Nov 09 22:41:23 2009 +0000
+++ b/xen/include/asm-x86/smp.h Tue Nov 10 05:18:25 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 494ad84ad38c xen/include/public/platform.h
--- a/xen/include/public/platform.h     Mon Nov 09 22:41:23 2009 +0000
+++ b/xen/include/public/platform.h     Tue Nov 10 05:18:25 2009 +0800
@@ -312,6 +312,57 @@ 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 {
+    /* IN */
+    uint32_t xen_cpuid;
+    /* OUT */
+    uint32_t apic_id;
+    uint32_t acpi_id;
+#define XEN_PCPU_FLAGS_ONLINE   1
+    /* Correponding xen_cpuid is not present*/
+#define XEN_PCPU_FLAGS_INVALID  2
+    uint32_t flags;
+    uint8_t  pad[128];
+};
+typedef struct xen_physical_cpuinfo xen_physical_cpuinfo_t;
+DEFINE_XEN_GUEST_HANDLE(xen_physical_cpuinfo_t);
+
+/*
+ * Fetch physical CPUs information
+ */
+struct xenpf_pcpu_info
+{
+    /* OUT */
+    /* The maxium cpu_id that is present */
+    uint32_t max_present;
+    /* The maxium possible cpus */
+    uint32_t max_possible;
+
+    /* IN */
+    uint32_t info_num;
+
+    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;
+        uint8_t               pad[64];
+    }u;
+};
+
 struct xen_platform_op {
     uint32_t cmd;
     uint32_t interface_version; /* XENPF_INTERFACE_VERSION */
@@ -327,6 +378,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 494ad84ad38c xen/include/public/xen.h
--- a/xen/include/public/xen.h  Mon Nov 09 22:41:23 2009 +0000
+++ b/xen/include/public/xen.h  Tue Nov 10 05:18:25 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


Keir Fraser wrote:
> On 08/11/2009 01:59, "Jiang, Yunhong" <yunhong.jiang@xxxxxxxxx> wrote:
> 
>> The Linux patch is initially part of patch for CPU hotplug.
> 
> Ah, I see it's part of the phys hotplug stuff. It's okay with
> me if Jeremy
> will ack it. Also XENPF_get_cpuinfo should be made extensible,
> and should
> get a comment in public/platform.h, e.g., about what ncpus and
> max_cpus mean. 
> 
> -- Keir

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®.