All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Add hypercall to expose physical CPU in xen hypervisor
@ 2009-11-06  8:20 Jiang, Yunhong
  2009-11-06 16:30 ` Keir Fraser
  0 siblings, 1 reply; 10+ messages in thread
From: Jiang, Yunhong @ 2009-11-06  8:20 UTC (permalink / raw)
  To: Jeremy Fitzhardinge, Keir Fraser; +Cc: xen-devel

[-- Attachment #1: Type: text/plain, Size: 8943 bytes --]

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@intel.com>


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 #2: xen_pcpu.patch --]
[-- Type: application/octet-stream, Size: 8111 bytes --]

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 #3: Type: text/plain, Size: 138 bytes --]

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

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Add hypercall to expose physical CPU in xen hypervisor
  2009-11-06  8:20 [PATCH] Add hypercall to expose physical CPU in xen hypervisor Jiang, Yunhong
@ 2009-11-06 16:30 ` Keir Fraser
  2009-11-08  1:59   ` Jiang, Yunhong
  0 siblings, 1 reply; 10+ messages in thread
From: Keir Fraser @ 2009-11-06 16:30 UTC (permalink / raw)
  To: Jiang, Yunhong, Jeremy Fitzhardinge; +Cc: xen-devel

On 06/11/2009 08:20, "Jiang, Yunhong" <yunhong.jiang@intel.com> wrote:

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

Is this and the accompanying Linux patch something that people really want?

The new platform hypercall will never be changeable for compatibility
reasons and looks kinda... arbitrary.

Personally I'd rather not take it.

 -- Keir

^ permalink raw reply	[flat|nested] 10+ messages in thread

* RE: [PATCH] Add hypercall to expose physical CPU in xen hypervisor
  2009-11-06 16:30 ` Keir Fraser
@ 2009-11-08  1:59   ` Jiang, Yunhong
  2009-11-08  7:46     ` Keir Fraser
  0 siblings, 1 reply; 10+ messages in thread
From: Jiang, Yunhong @ 2009-11-08  1:59 UTC (permalink / raw)
  To: Keir Fraser, Jeremy Fitzhardinge; +Cc: xen-devel

This patch 

Keir Fraser wrote:
> On 06/11/2009 08:20, "Jiang, Yunhong" <yunhong.jiang@intel.com> wrote:
> 
>> 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. 
> 
> Is this and the accompanying Linux patch something that people
> really want?

The Linux patch is initially part of patch for CPU hotplug. As stated when discussion with Jeremy before (http://lists.xensource.com/archives/html/xen-devel/2009-09/msg01111.html), we decided to take two step method for CPU hot-add. The first step, xen will set the CPU as present after get notification from dom0, in the second step, Xen will set the CPU online and put it to schedule. Through the sysfs interface, the step 2 is quite easy, simple echo "1" to an xen_pcpu entry in sysfs, which can be used by udev rules easily.

I assume Jeremy have agreed for the interface in sysfs for pcpu , as he stated "Yes, that makes sense.  Would it eventually be worth mirroring the normal cpu heirarchy as much as possible to add an interface for stats and power management?" in http://lists.xensource.com/archives/html/xen-devel/2009-09/msg01079.html. 

When I split the original CPU hotplug patch according to Jeremy's suggestion, I think this part is not related to CPU hotplug so much and in fact can be generalized.  The issue of this method is, the sysfs interface is async, so the tools may miss latest change. I assume it should be accptable since even with directly hypercall , the information may be changed still.

As for usefulness of the patch, I'd get more input from community. For Linux kernel patch, an central sysfs entry will be helpful IMO. 
For the hypercall patch, currently there are several methods to expose the physical CPU information to administrative tools or dom0, at least including: XEN_SYSCTL_getcpuinfo, XEN_SYSCTL_pm_op_get_cputopo, XEN_MC_physcpuinfo (The XEN_MC_physcpuinfo includes MCA information also), but none of them can meet my requirement, and none of them can be extended easily, so I have to create a new one. I tihnk if there is a central hypercall to provide all physical CPU information, it will be helpful.  

BTW, I really can't tell why XEN_SYSCTL_getcpuinfo will only provide idle_time while comments stated as "Get physical CPU information".

> 
> The new platform hypercall will never be changeable for compatibility
> reasons and looks kinda... arbitrary.

Yes, current interface is not flexible, and is only for CPU hotplug support. If needed and agreed, I'd happy to extent it as a general interface to fetch physical CPU information, including: 
1) Basic information like vendor/model/capability
2) Topo info, like initial APIC ID, the cores_per_package, thread_per_core etc.
3) CPU stat information,like online stat, idle_time etc.

As for make it extensible, I'd have a version number and leave space for future extenstion, how about it?

Thanks
Yunhong Jiang

> 
> Personally I'd rather not take it.
> 
> -- Keir

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Add hypercall to expose physical CPU in xen hypervisor
  2009-11-08  1:59   ` Jiang, Yunhong
@ 2009-11-08  7:46     ` Keir Fraser
  2009-11-09  0:45       ` Jiang, Yunhong
                         ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Keir Fraser @ 2009-11-08  7:46 UTC (permalink / raw)
  To: Jiang, Yunhong, Jeremy Fitzhardinge; +Cc: xen-devel

On 08/11/2009 01:59, "Jiang, Yunhong" <yunhong.jiang@intel.com> 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

^ permalink raw reply	[flat|nested] 10+ messages in thread

* RE: [PATCH] Add hypercall to expose physical CPU in xen hypervisor
  2009-11-08  7:46     ` Keir Fraser
@ 2009-11-09  0:45       ` Jiang, Yunhong
  2009-11-09 22:03       ` Jeremy Fitzhardinge
  2009-11-10 12:02       ` Jiang, Yunhong
  2 siblings, 0 replies; 10+ messages in thread
From: Jiang, Yunhong @ 2009-11-09  0:45 UTC (permalink / raw)
  To: Keir Fraser, Jeremy Fitzhardinge; +Cc: xen-devel

Sure, I will update the interface and resend both dom0 and xen hypervisor patch.

--jyh

Keir Fraser wrote:
> On 08/11/2009 01:59, "Jiang, Yunhong" <yunhong.jiang@intel.com> 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

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Add hypercall to expose physical CPU in xen hypervisor
  2009-11-08  7:46     ` Keir Fraser
  2009-11-09  0:45       ` Jiang, Yunhong
@ 2009-11-09 22:03       ` Jeremy Fitzhardinge
  2009-11-10 12:16         ` Jiang, Yunhong
  2009-11-10 12:02       ` Jiang, Yunhong
  2 siblings, 1 reply; 10+ messages in thread
From: Jeremy Fitzhardinge @ 2009-11-09 22:03 UTC (permalink / raw)
  To: Keir Fraser; +Cc: Jiang, Yunhong, xen-devel

On 11/07/09 23:46, Keir Fraser 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.
>   

The kernel patch looks nice and self-contained, so I'd have no problems
applying it based on its form.  I'll hold off applying it until you've
got a final extensible form for the ABI.

    J

^ permalink raw reply	[flat|nested] 10+ messages in thread

* RE: [PATCH] Add hypercall to expose physical CPU in xen hypervisor
  2009-11-08  7:46     ` Keir Fraser
  2009-11-09  0:45       ` Jiang, Yunhong
  2009-11-09 22:03       ` Jeremy Fitzhardinge
@ 2009-11-10 12:02       ` Jiang, Yunhong
  2 siblings, 0 replies; 10+ messages in thread
From: Jiang, Yunhong @ 2009-11-10 12:02 UTC (permalink / raw)
  To: Keir Fraser, Jeremy Fitzhardinge; +Cc: xen-devel

[-- Attachment #1: Type: text/plain, Size: 9735 bytes --]

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@intel.com>

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@intel.com> 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 #2: xen_pcpu.patch --]
[-- Type: application/octet-stream, Size: 8256 bytes --]

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

[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

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

^ permalink raw reply	[flat|nested] 10+ messages in thread

* RE: Re: [PATCH] Add hypercall to expose physical CPU in xen hypervisor
  2009-11-09 22:03       ` Jeremy Fitzhardinge
@ 2009-11-10 12:16         ` Jiang, Yunhong
  2009-11-10 16:36           ` Konrad Rzeszutek Wilk
  0 siblings, 1 reply; 10+ messages in thread
From: Jiang, Yunhong @ 2009-11-10 12:16 UTC (permalink / raw)
  To: Jeremy Fitzhardinge, Keir Fraser; +Cc: xen-devel

[-- Attachment #1: Type: text/plain, Size: 20689 bytes --]

Jeremy, here is the update patch according to the new interface, please have a look.
One changes in this patch is, the apic_id/acpi_id is exposed in sysfs also.

Thanks
yunhong Jiang

Export host physical CPU information to dom0

From: Jiang, Yunhong <yunhong.jiang@intel.com>

This patch expose host's physical CPU information to dom0 in sysfs, so that dom0's management tools can control the physical CPU if needed.

It also provides interface in sysfs to logical online/offline a physical CPU.

Notice: The information in dom0 is synced with xen hypervisor asynchronously.

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

 drivers/xen/Makefile             |    2
 drivers/xen/pcpu.c               |  462 ++++++++++++++++++++++++++++++++++++++
 include/xen/interface/platform.h |   48 ++++
 include/xen/interface/xen.h      |    1
 include/xen/pcpu.h               |   30 ++
 5 files changed, 542 insertions(+), 1 deletions(-)
 create mode 100644 drivers/xen/pcpu.c
 create mode 100644 include/xen/pcpu.h


diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile
index cddfffb..5d01856 100644
--- a/drivers/xen/Makefile
+++ b/drivers/xen/Makefile
@@ -1,4 +1,4 @@
-obj-y  += grant-table.o features.o events.o manage.o biomerge.o
+obj-y  += grant-table.o features.o events.o manage.o biomerge.o pcpu.o
 obj-y  += xenbus/ live_maps.o

 nostackp := $(call cc-option, -fno-stack-protector)
diff --git a/drivers/xen/pcpu.c b/drivers/xen/pcpu.c
new file mode 100644
index 0000000..fc2f70f
--- /dev/null
+++ b/drivers/xen/pcpu.c
@@ -0,0 +1,462 @@
+/*
+ * pcpu.c - management physical cpu in dom0 environment
+ */
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <asm/xen/hypervisor.h>
+#include <asm/xen/hypercall.h>
+#include <linux/cpu.h>
+#include <xen/xenbus.h>
+#include <xen/pcpu.h>
+#include <xen/events.h>
+#include <xen/acpi.h>
+
+static struct sysdev_class xen_pcpu_sysdev_class = {
+       .name = "xen_pcpu",
+};
+
+static DEFINE_SPINLOCK(xen_pcpu_spinlock);
+static RAW_NOTIFIER_HEAD(xen_pcpu_chain);
+
+/* No need for irq disable since hotplug notify is in workqueue context */
+#define get_pcpu_lock()  spin_lock(&xen_pcpu_spinlock);
+#define put_pcpu_lock()  spin_unlock(&xen_pcpu_spinlock);
+
+struct xen_pcpus {
+       struct list_head list;
+       int possible;
+       int present;
+};
+static struct xen_pcpus xen_pcpus;
+
+int register_xen_pcpu_notifier(struct notifier_block *nb)
+{
+       int ret;
+
+       /* All refer to the chain notifier is protected by the pcpu_lock */
+       get_pcpu_lock();
+       ret = raw_notifier_chain_register(&xen_pcpu_chain, nb);
+       put_pcpu_lock();
+       return ret;
+}
+EXPORT_SYMBOL_GPL(register_xen_pcpu_notifier);
+
+void unregister_xen_pcpu_notifier(struct notifier_block *nb)
+{
+       get_pcpu_lock();
+       raw_notifier_chain_unregister(&xen_pcpu_chain, nb);
+       put_pcpu_lock();
+}
+EXPORT_SYMBOL_GPL(unregister_xen_pcpu_notifier);
+
+static int xen_pcpu_down(uint32_t xen_id)
+{
+       int ret;
+       xen_platform_op_t op = {
+               .cmd                    = XENPF_resource_hotplug,
+               .interface_version      = XENPF_INTERFACE_VERSION,
+               .u.resource.u.cpu_ol.cpuid = xen_id,
+       };
+
+       op.u.resource.sub_cmd   = XEN_CPU_offline;
+       ret = HYPERVISOR_dom0_op(&op);
+       return ret;
+}
+
+static int xen_pcpu_up(uint32_t xen_id)
+{
+       int ret;
+       xen_platform_op_t op = {
+               .cmd                    = XENPF_resource_hotplug,
+               .interface_version      = XENPF_INTERFACE_VERSION,
+               .u.resource.u.cpu_ol.cpuid = xen_id,
+       };
+
+       op.u.resource.sub_cmd   = XEN_CPU_online;
+       ret = HYPERVISOR_dom0_op(&op);
+       return ret;
+}
+
+static ssize_t show_online(struct sys_device *dev,
+                       struct sysdev_attribute *attr,
+                       char *buf)
+{
+       struct pcpu *cpu = container_of(dev, struct pcpu, sysdev);
+
+       return sprintf(buf, "%u\n", !!(cpu->flags & XEN_PCPU_FLAGS_ONLINE));
+}
+
+static ssize_t __ref store_online(struct sys_device *dev,
+                                 struct sysdev_attribute *attr,
+                                 const char *buf, size_t count)
+{
+       struct pcpu *cpu = container_of(dev, struct pcpu, sysdev);
+       ssize_t ret;
+
+       switch (buf[0]) {
+       case '0':
+               ret = xen_pcpu_down(cpu->xen_id);
+               break;
+       case '1':
+               ret = xen_pcpu_up(cpu->xen_id);
+               break;
+       default:
+               ret = -EINVAL;
+       }
+
+       if (ret >= 0)
+               ret = count;
+       return ret;
+}
+
+static SYSDEV_ATTR(online, 0644, show_online, store_online);
+
+static ssize_t show_apicid(struct sys_device *dev,
+                       struct sysdev_attribute *attr,
+                       char *buf)
+{
+       struct pcpu *cpu = container_of(dev, struct pcpu, sysdev);
+
+       return sprintf(buf, "%u\n", cpu->apic_id);
+}
+
+static ssize_t show_acpiid(struct sys_device *dev,
+                       struct sysdev_attribute *attr,
+                       char *buf)
+{
+       struct pcpu *cpu = container_of(dev, struct pcpu, sysdev);
+
+       return sprintf(buf, "%u\n", cpu->acpi_id);
+}
+static SYSDEV_ATTR(apic_id, 0444, show_apicid, NULL);
+static SYSDEV_ATTR(acpi_id, 0444, show_acpiid, NULL);
+
+static int xen_pcpu_free(struct pcpu *pcpu)
+{
+       if (!pcpu)
+               return 0;
+
+       sysdev_remove_file(&pcpu->sysdev, &attr_online);
+       sysdev_unregister(&pcpu->sysdev);
+       list_del(&pcpu->pcpu_list);
+       kfree(pcpu);
+
+       return 0;
+}
+
+static struct pcpu *xen_pcpu_add(struct xen_physical_cpuinfo *info)
+{
+       struct pcpu *cpu;
+       int error;
+
+       printk(KERN_DEBUG "xen_pcpu_add:  xen_id %x apic_id %x acpi_id %x\n",
+                          info->xen_cpuid, info->apic_id, info->acpi_id);
+
+       if (info->flags & XEN_PCPU_FLAGS_INVALID)
+               return NULL;
+
+       cpu = kzalloc(sizeof(struct pcpu), GFP_KERNEL);
+       if (!cpu)
+               return NULL;
+
+       INIT_LIST_HEAD(&cpu->pcpu_list);
+       cpu->xen_id = info->xen_cpuid;
+       cpu->apic_id = info->apic_id;
+       cpu->acpi_id = info->acpi_id;
+       cpu->flags = info->flags;
+
+       cpu->sysdev.cls = &xen_pcpu_sysdev_class;
+       cpu->sysdev.id = info->xen_cpuid;
+
+       error = sysdev_register(&cpu->sysdev);
+       if (error) {
+               printk(KERN_WARNING "xen_pcpu_add: Failed to register pcpu\n");
+               kfree(cpu);
+               return NULL;
+       }
+       sysdev_create_file(&cpu->sysdev, &attr_online);
+       sysdev_create_file(&cpu->sysdev, &attr_apic_id);
+       sysdev_create_file(&cpu->sysdev, &attr_acpi_id);
+       list_add_tail(&cpu->pcpu_list, &xen_pcpus.list);
+
+       return cpu;
+}
+
+static struct xen_physical_cpuinfo *xen_pcpu_info_fetch(int *num,
+               int *possible)
+{
+       int cpu_num, ret = 0, i;
+       struct xen_physical_cpuinfo *info;
+       xen_platform_op_t op = {
+               .cmd            = XENPF_get_cpuinfo,
+               .interface_version  = XENPF_INTERFACE_VERSION,
+               .u.pcpu_info.info_num   = 0,
+       };
+
+       set_xen_guest_handle(op.u.pcpu_info.info, NULL);
+
+       ret = HYPERVISOR_dom0_op(&op);
+       if (ret)
+               return NULL;
+
+       cpu_num = op.u.pcpu_info.max_present;
+
+       info = kzalloc(cpu_num * sizeof(struct xen_physical_cpuinfo),
+               GFP_KERNEL);
+       if (!info)
+               return NULL;
+
+       op.u.pcpu_info.info_num = cpu_num;
+       for (i = 0; i < cpu_num; i++)
+               info[i].xen_cpuid = i;
+
+       set_xen_guest_handle(op.u.pcpu_info.info, info);
+
+       ret = HYPERVISOR_dom0_op(&op);
+       if (ret) {
+               kfree(info);
+               printk(KERN_WARNING "xen_pcpu_info_fetch: Error fetch pcpu info\n");
+               return NULL;
+       }
+
+       /* present cpus is changed, that mean hotplug may happen */
+       if (cpu_num != op.u.pcpu_info.max_present)
+               printk(KERN_WARNING "Max present cpus changed when fetch cpu info\n");
+
+       if (possible)
+               *possible = op.u.pcpu_info.max_possible;
+       if (num)
+               *num = cpu_num;
+
+       return info;
+}
+
+static inline int same_pcpu(struct xen_physical_cpuinfo *info,
+                           struct pcpu *pcpu)
+{
+       return (pcpu->apic_id == info->apic_id) &&
+               (pcpu->xen_id == info->xen_cpuid);
+}
+
+/*
+ * Return 1 if online status changed
+ */
+static int xen_pcpu_online_check(struct xen_physical_cpuinfo *info,
+                                struct pcpu *pcpu)
+{
+       int result = 0;
+
+       if (!same_pcpu(info, pcpu))
+               return 0;
+
+       if (xen_pcpu_online(info->flags) && !xen_pcpu_online(pcpu->flags)) {
+               /* the pcpu is onlined */
+               pcpu->flags |= XEN_PCPU_FLAGS_ONLINE;
+               kobject_uevent(&pcpu->sysdev.kobj, KOBJ_ONLINE);
+               raw_notifier_call_chain(&xen_pcpu_chain,
+                       XEN_PCPU_ONLINE, (void *)(long)pcpu->xen_id);
+               result = 1;
+       } else if (!xen_pcpu_online(info->flags) &&
+                xen_pcpu_online(pcpu->flags))  {
+               /* The pcpu is offlined now */
+               pcpu->flags &= ~XEN_PCPU_FLAGS_ONLINE;
+               kobject_uevent(&pcpu->sysdev.kobj, KOBJ_OFFLINE);
+               raw_notifier_call_chain(&xen_pcpu_chain,
+                       XEN_PCPU_OFFLINE, (void *)(long)pcpu->xen_id);
+               result = 1;
+       }
+
+       return result;
+}
+
+/*
+ * Sync dom0's pcpu information with xen hypervisor's
+ */
+static int xen_pcpu_sync(void)
+{
+       struct xen_physical_cpuinfo *info;
+       int cpu_num, i, ret = -1, possible, present = 0;
+       struct list_head *elem, *tmp;
+       struct pcpu *pcpu;
+
+       info = xen_pcpu_info_fetch(&cpu_num, &possible);
+       if (!info)
+               return -1;
+
+       get_pcpu_lock();
+
+       xen_pcpus.possible = possible;
+
+       /* Check for current cpu list */
+       for (i = 0; i < cpu_num; i++) {
+               int found = 0;
+
+               if (info[i].flags & XEN_PCPU_FLAGS_INVALID)
+                       continue;
+
+               present++;
+               list_for_each_entry(pcpu, &xen_pcpus.list, pcpu_list) {
+                       if (same_pcpu(&info[i], pcpu)) {
+                               xen_pcpu_online_check(&info[i], pcpu);
+                               pcpu->status |= PCPU_LOOPED;
+                               found = 1;
+                       }
+               }
+               if (!found) {
+                       struct pcpu *cpu;
+
+                       /*
+                        * Normally a physical cpu is onlined in two step
+                        * Firstly, the physical CPU is hot-added, secondly
+                        * it will be take online through sysfs writing
+                        * So a hot-added CPU should be offlined initially
+                        */
+                       if (xen_pcpu_online(info[i].flags))
+                               printk(KERN_WARNING "xen_pcpu_sync:"
+                                       "A hotadd cpu is onlined also\n");
+
+                       cpu = xen_pcpu_add(&info[i]);
+                       if (cpu == NULL)
+                               goto failed;
+                       raw_notifier_call_chain(&xen_pcpu_chain,
+                                       XEN_PCPU_ADD,
+                                       (void *)(long)cpu->xen_id);
+                       cpu->status |= PCPU_LOOPED;
+               }
+       }
+
+       list_for_each_safe(elem, tmp, &xen_pcpus.list) {
+               pcpu = list_entry(elem, struct pcpu, pcpu_list);
+               if (pcpu->status & PCPU_LOOPED)
+                       pcpu->status &= ~PCPU_LOOPED;
+               else {
+                       /* The pcpu does not exist any more, remove it */
+                       raw_notifier_call_chain(&xen_pcpu_chain,
+                                       XEN_PCPU_REMOVE,
+                                       (void *)(long)pcpu->xen_id);
+                       xen_pcpu_free(pcpu);
+               }
+       }
+
+       xen_pcpus.present = present;
+       ret = 0;
+failed:
+       put_pcpu_lock();
+       kfree(info);
+       return ret;
+}
+
+static int __init xen_pcpu_info_init(void)
+{
+       int possible, cpu_num, i;
+       struct xen_physical_cpuinfo *info = NULL;
+       struct list_head *elem, *tmp;
+       struct pcpu *pcpu;
+
+       info = xen_pcpu_info_fetch(&cpu_num, &possible);
+       if (!info) {
+               printk(KERN_WARNING
+                       "xen_pcpu_info_init: Failed to fetch pcpu_info\n");
+               return -1;
+       }
+
+       get_pcpu_lock();
+
+       INIT_LIST_HEAD(&xen_pcpus.list);
+       xen_pcpus.possible = possible;
+       xen_pcpus.present = 0;
+
+       for (i = 0; i < cpu_num; i++) {
+               if (info[i].flags & XEN_PCPU_FLAGS_INVALID)
+                       continue;
+               pcpu = xen_pcpu_add(&info[i]);
+               if (!pcpu)
+                       goto failed;
+               xen_pcpus.present++;
+       }
+
+       put_pcpu_lock();
+       kfree(info);
+
+       return 0;
+failed:
+       list_for_each_safe(elem, tmp, &xen_pcpus.list) {
+               pcpu = list_entry(elem, struct pcpu, pcpu_list);
+               xen_pcpu_free(pcpu);
+       }
+       xen_pcpus.possible = xen_pcpus.present = 0;
+       INIT_LIST_HEAD(&xen_pcpus.list);
+       put_pcpu_lock();
+
+       kfree(info);
+       return -1;
+}
+
+static void xen_pcpu_dpc(struct work_struct *work)
+{
+       if (xen_pcpu_sync() < 0)
+               printk(KERN_WARNING
+                       "xen_pcpu_dpc: Failed to sync pcpu information\n");
+}
+static DECLARE_WORK(xen_pcpu_work, xen_pcpu_dpc);
+
+/*
+ * type: 0 add, 1 remove
+ */
+int xen_pcpu_hotplug(int type, uint32_t apic_id)
+{
+       struct pcpu *pcpu;
+       int found = 0;
+
+       xen_pcpu_sync();
+       get_pcpu_lock();
+       list_for_each_entry(pcpu, &xen_pcpus.list, pcpu_list)
+       {
+               if (pcpu->apic_id == apic_id) {
+                       found = 1;
+                       break;
+               }
+       }
+       put_pcpu_lock();
+
+       if (!found && (type == HOTPLUG_TYPE_ADD))
+               printk(KERN_WARNING "The cpu is not added into Xen HV?\n");
+
+       if (found && (type == HOTPLUG_TYPE_REMOVE))
+               printk(KERN_WARNING "The cpu still exits in Xen HV?\n");
+       return 0;
+}
+EXPORT_SYMBOL(xen_pcpu_hotplug);
+
+static irqreturn_t xen_pcpu_interrupt(int irq, void *dev_id)
+{
+       schedule_work(&xen_pcpu_work);
+       return IRQ_HANDLED;
+}
+
+static int __init xen_pcpu_init(void)
+{
+       int err;
+
+       if (!xen_initial_domain())
+               return 0;
+
+       err = sysdev_class_register(&xen_pcpu_sysdev_class);
+       if (err) {
+               printk(KERN_WARNING
+                       "xen_pcpu_init: register xen_pcpu sysdev Failed!\n");
+               return err;
+       }
+
+       err = xen_pcpu_info_init();
+       if (!err)
+               err = bind_virq_to_irqhandler(VIRQ_PCPU_STATE,
+                       0, xen_pcpu_interrupt, 0, "pcpu", NULL);
+       if (err < 0)
+               printk(KERN_WARNING "xen_pcpu_init: "
+                       "Failed to bind pcpu_state virq\n"
+                       "You will lost latest information! \n");
+       return err;
+}
+
+subsys_initcall(xen_pcpu_init);
diff --git a/include/xen/interface/platform.h b/include/xen/interface/platform.h
index 6783fce..a9cf4e2 100644
--- a/include/xen/interface/platform.h
+++ b/include/xen/interface/platform.h
@@ -312,6 +312,52 @@ struct xenpf_set_processor_pminfo {
 typedef struct xenpf_set_processor_pminfo xenpf_set_processor_pminfo_t;
 DEFINE_GUEST_HANDLE_STRUCT(xenpf_set_processor_pminfo);

+#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_GUEST_HANDLE_STRUCT(xen_physical_cpuinfo);
+
+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;
+       GUEST_HANDLE(xen_physical_cpuinfo) info;
+};
+typedef struct xenpf_pcpu_info xenpf_pcpu_info_t;
+DEFINE_GUEST_HANDLE_STRUCT(xenpf_pcpu_info);
+
+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 +373,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 --git a/include/xen/interface/xen.h b/include/xen/interface/xen.h
index 812ffd5..9ffaee0 100644
--- a/include/xen/interface/xen.h
+++ b/include/xen/interface/xen.h
@@ -79,6 +79,7 @@
 #define VIRQ_CONSOLE    2  /* (DOM0) Bytes received on emergency console. */
 #define VIRQ_DOM_EXC    3  /* (DOM0) Exceptional event for some domain.   */
 #define VIRQ_DEBUGGER   6  /* (DOM0) A domain has paused for debugging.   */
+#define VIRQ_PCPU_STATE 9  /* (DOM0) PCPU state changed                   */

 /* Architecture-specific VIRQ definitions. */
 #define VIRQ_ARCH_0    16
diff --git a/include/xen/pcpu.h b/include/xen/pcpu.h
new file mode 100644
index 0000000..32fcb0d
--- /dev/null
+++ b/include/xen/pcpu.h
@@ -0,0 +1,30 @@
+#ifndef _XEN_PCPU_H
+#define _XEN_PCPU_H
+
+#include <xen/interface/platform.h>
+extern int xen_pcpu_hotplug(int type, uint32_t apic_id);
+#define XEN_PCPU_ONLINE     0x01
+#define XEN_PCPU_OFFLINE    0x02
+#define XEN_PCPU_ADD        0x04
+#define XEN_PCPU_REMOVE     0x08
+
+struct pcpu {
+       struct list_head pcpu_list;
+       struct sys_device sysdev;
+       uint32_t xen_id;
+       uint32_t apic_id;
+       uint32_t acpi_id;
+       uint32_t flags;
+#define PCPU_LOOPED 0x10000000
+       uint32_t status;
+};
+
+static inline int xen_pcpu_online(uint32_t flags)
+{
+       return !!(flags & XEN_PCPU_FLAGS_ONLINE);
+}
+
+extern int register_xen_pcpu_notifier(struct notifier_block *nb);
+
+extern void unregister_xen_pcpu_notifier(struct notifier_block *nb);
+#endif


xen-devel-bounces@lists.xensource.com wrote:
> On 11/07/09 23:46, Keir Fraser 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.
>>
>
> The kernel patch looks nice and self-contained, so I'd have no
> problems applying it based on its form.  I'll hold off applying it
> until you've got a final extensible form for the ABI.
>
>    J
>
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xensource.com
> http://lists.xensource.com/xen-devel

[-- Attachment #2: 01-dom0_pcpu.patch --]
[-- Type: application/octet-stream, Size: 15684 bytes --]

Export host physical CPU information to dom0

From: Jiang, Yunhong <yunhong.jiang@intel.com>

This patch expose host's physical CPU information to dom0 in sysfs, so that dom0's management tools can control the physical CPU if needed.

It also provides interface in sysfs to logical online/offline a physical CPU.

Notice: The information in dom0 is synced with xen hypervisor asynchronously.

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

 drivers/xen/Makefile             |    2 
 drivers/xen/pcpu.c               |  462 ++++++++++++++++++++++++++++++++++++++
 include/xen/interface/platform.h |   48 ++++
 include/xen/interface/xen.h      |    1 
 include/xen/pcpu.h               |   30 ++
 5 files changed, 542 insertions(+), 1 deletions(-)
 create mode 100644 drivers/xen/pcpu.c
 create mode 100644 include/xen/pcpu.h


diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile
index cddfffb..5d01856 100644
--- a/drivers/xen/Makefile
+++ b/drivers/xen/Makefile
@@ -1,4 +1,4 @@
-obj-y	+= grant-table.o features.o events.o manage.o biomerge.o
+obj-y	+= grant-table.o features.o events.o manage.o biomerge.o pcpu.o
 obj-y	+= xenbus/ live_maps.o
 
 nostackp := $(call cc-option, -fno-stack-protector)
diff --git a/drivers/xen/pcpu.c b/drivers/xen/pcpu.c
new file mode 100644
index 0000000..fc2f70f
--- /dev/null
+++ b/drivers/xen/pcpu.c
@@ -0,0 +1,462 @@
+/*
+ * pcpu.c - management physical cpu in dom0 environment
+ */
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <asm/xen/hypervisor.h>
+#include <asm/xen/hypercall.h>
+#include <linux/cpu.h>
+#include <xen/xenbus.h>
+#include <xen/pcpu.h>
+#include <xen/events.h>
+#include <xen/acpi.h>
+
+static struct sysdev_class xen_pcpu_sysdev_class = {
+	.name = "xen_pcpu",
+};
+
+static DEFINE_SPINLOCK(xen_pcpu_spinlock);
+static RAW_NOTIFIER_HEAD(xen_pcpu_chain);
+
+/* No need for irq disable since hotplug notify is in workqueue context */
+#define get_pcpu_lock()  spin_lock(&xen_pcpu_spinlock);
+#define put_pcpu_lock()  spin_unlock(&xen_pcpu_spinlock);
+
+struct xen_pcpus {
+	struct list_head list;
+	int possible;
+	int present;
+};
+static struct xen_pcpus xen_pcpus;
+
+int register_xen_pcpu_notifier(struct notifier_block *nb)
+{
+	int ret;
+
+	/* All refer to the chain notifier is protected by the pcpu_lock */
+	get_pcpu_lock();
+	ret = raw_notifier_chain_register(&xen_pcpu_chain, nb);
+	put_pcpu_lock();
+	return ret;
+}
+EXPORT_SYMBOL_GPL(register_xen_pcpu_notifier);
+
+void unregister_xen_pcpu_notifier(struct notifier_block *nb)
+{
+	get_pcpu_lock();
+	raw_notifier_chain_unregister(&xen_pcpu_chain, nb);
+	put_pcpu_lock();
+}
+EXPORT_SYMBOL_GPL(unregister_xen_pcpu_notifier);
+
+static int xen_pcpu_down(uint32_t xen_id)
+{
+	int ret;
+	xen_platform_op_t op = {
+		.cmd			= XENPF_resource_hotplug,
+		.interface_version	= XENPF_INTERFACE_VERSION,
+		.u.resource.u.cpu_ol.cpuid = xen_id,
+	};
+
+	op.u.resource.sub_cmd	= XEN_CPU_offline;
+	ret = HYPERVISOR_dom0_op(&op);
+	return ret;
+}
+
+static int xen_pcpu_up(uint32_t xen_id)
+{
+	int ret;
+	xen_platform_op_t op = {
+		.cmd			= XENPF_resource_hotplug,
+		.interface_version	= XENPF_INTERFACE_VERSION,
+		.u.resource.u.cpu_ol.cpuid = xen_id,
+	};
+
+	op.u.resource.sub_cmd	= XEN_CPU_online;
+	ret = HYPERVISOR_dom0_op(&op);
+	return ret;
+}
+
+static ssize_t show_online(struct sys_device *dev,
+			struct sysdev_attribute *attr,
+			char *buf)
+{
+	struct pcpu *cpu = container_of(dev, struct pcpu, sysdev);
+
+	return sprintf(buf, "%u\n", !!(cpu->flags & XEN_PCPU_FLAGS_ONLINE));
+}
+
+static ssize_t __ref store_online(struct sys_device *dev,
+				  struct sysdev_attribute *attr,
+				  const char *buf, size_t count)
+{
+	struct pcpu *cpu = container_of(dev, struct pcpu, sysdev);
+	ssize_t ret;
+
+	switch (buf[0]) {
+	case '0':
+		ret = xen_pcpu_down(cpu->xen_id);
+		break;
+	case '1':
+		ret = xen_pcpu_up(cpu->xen_id);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	if (ret >= 0)
+		ret = count;
+	return ret;
+}
+
+static SYSDEV_ATTR(online, 0644, show_online, store_online);
+
+static ssize_t show_apicid(struct sys_device *dev,
+			struct sysdev_attribute *attr,
+			char *buf)
+{
+	struct pcpu *cpu = container_of(dev, struct pcpu, sysdev);
+
+	return sprintf(buf, "%u\n", cpu->apic_id);
+}
+
+static ssize_t show_acpiid(struct sys_device *dev,
+			struct sysdev_attribute *attr,
+			char *buf)
+{
+	struct pcpu *cpu = container_of(dev, struct pcpu, sysdev);
+
+	return sprintf(buf, "%u\n", cpu->acpi_id);
+}
+static SYSDEV_ATTR(apic_id, 0444, show_apicid, NULL);
+static SYSDEV_ATTR(acpi_id, 0444, show_acpiid, NULL);
+
+static int xen_pcpu_free(struct pcpu *pcpu)
+{
+	if (!pcpu)
+		return 0;
+
+	sysdev_remove_file(&pcpu->sysdev, &attr_online);
+	sysdev_unregister(&pcpu->sysdev);
+	list_del(&pcpu->pcpu_list);
+	kfree(pcpu);
+
+	return 0;
+}
+
+static struct pcpu *xen_pcpu_add(struct xen_physical_cpuinfo *info)
+{
+	struct pcpu *cpu;
+	int error;
+
+	printk(KERN_DEBUG "xen_pcpu_add:  xen_id %x apic_id %x acpi_id %x\n",
+			   info->xen_cpuid, info->apic_id, info->acpi_id);
+
+	if (info->flags & XEN_PCPU_FLAGS_INVALID)
+		return NULL;
+
+	cpu = kzalloc(sizeof(struct pcpu), GFP_KERNEL);
+	if (!cpu)
+		return NULL;
+
+	INIT_LIST_HEAD(&cpu->pcpu_list);
+	cpu->xen_id = info->xen_cpuid;
+	cpu->apic_id = info->apic_id;
+	cpu->acpi_id = info->acpi_id;
+	cpu->flags = info->flags;
+
+	cpu->sysdev.cls = &xen_pcpu_sysdev_class;
+	cpu->sysdev.id = info->xen_cpuid;
+
+	error = sysdev_register(&cpu->sysdev);
+	if (error) {
+		printk(KERN_WARNING "xen_pcpu_add: Failed to register pcpu\n");
+		kfree(cpu);
+		return NULL;
+	}
+	sysdev_create_file(&cpu->sysdev, &attr_online);
+	sysdev_create_file(&cpu->sysdev, &attr_apic_id);
+	sysdev_create_file(&cpu->sysdev, &attr_acpi_id);
+	list_add_tail(&cpu->pcpu_list, &xen_pcpus.list);
+
+	return cpu;
+}
+
+static struct xen_physical_cpuinfo *xen_pcpu_info_fetch(int *num,
+		int *possible)
+{
+	int cpu_num, ret = 0, i;
+	struct xen_physical_cpuinfo *info;
+	xen_platform_op_t op = {
+		.cmd            = XENPF_get_cpuinfo,
+		.interface_version  = XENPF_INTERFACE_VERSION,
+		.u.pcpu_info.info_num   = 0,
+	};
+
+	set_xen_guest_handle(op.u.pcpu_info.info, NULL);
+
+	ret = HYPERVISOR_dom0_op(&op);
+	if (ret)
+		return NULL;
+
+	cpu_num = op.u.pcpu_info.max_present;
+
+	info = kzalloc(cpu_num * sizeof(struct xen_physical_cpuinfo),
+		GFP_KERNEL);
+	if (!info)
+		return NULL;
+
+	op.u.pcpu_info.info_num = cpu_num;
+	for (i = 0; i < cpu_num; i++)
+		info[i].xen_cpuid = i;
+
+	set_xen_guest_handle(op.u.pcpu_info.info, info);
+
+	ret = HYPERVISOR_dom0_op(&op);
+	if (ret) {
+		kfree(info);
+		printk(KERN_WARNING "xen_pcpu_info_fetch: Error fetch pcpu info\n");
+		return NULL;
+	}
+
+	/* present cpus is changed, that mean hotplug may happen */
+	if (cpu_num != op.u.pcpu_info.max_present)
+		printk(KERN_WARNING "Max present cpus changed when fetch cpu info\n");
+
+	if (possible)
+		*possible = op.u.pcpu_info.max_possible;
+	if (num)
+		*num = cpu_num;
+
+	return info;
+}
+
+static inline int same_pcpu(struct xen_physical_cpuinfo *info,
+			    struct pcpu *pcpu)
+{
+	return (pcpu->apic_id == info->apic_id) &&
+		(pcpu->xen_id == info->xen_cpuid);
+}
+
+/*
+ * Return 1 if online status changed
+ */
+static int xen_pcpu_online_check(struct xen_physical_cpuinfo *info,
+				 struct pcpu *pcpu)
+{
+	int result = 0;
+
+	if (!same_pcpu(info, pcpu))
+		return 0;
+
+	if (xen_pcpu_online(info->flags) && !xen_pcpu_online(pcpu->flags)) {
+		/* the pcpu is onlined */
+		pcpu->flags |= XEN_PCPU_FLAGS_ONLINE;
+		kobject_uevent(&pcpu->sysdev.kobj, KOBJ_ONLINE);
+		raw_notifier_call_chain(&xen_pcpu_chain,
+			XEN_PCPU_ONLINE, (void *)(long)pcpu->xen_id);
+		result = 1;
+	} else if (!xen_pcpu_online(info->flags) &&
+		 xen_pcpu_online(pcpu->flags))  {
+		/* The pcpu is offlined now */
+		pcpu->flags &= ~XEN_PCPU_FLAGS_ONLINE;
+		kobject_uevent(&pcpu->sysdev.kobj, KOBJ_OFFLINE);
+		raw_notifier_call_chain(&xen_pcpu_chain,
+			XEN_PCPU_OFFLINE, (void *)(long)pcpu->xen_id);
+		result = 1;
+	}
+
+	return result;
+}
+
+/*
+ * Sync dom0's pcpu information with xen hypervisor's
+ */
+static int xen_pcpu_sync(void)
+{
+	struct xen_physical_cpuinfo *info;
+	int cpu_num, i, ret = -1, possible, present = 0;
+	struct list_head *elem, *tmp;
+	struct pcpu *pcpu;
+
+	info = xen_pcpu_info_fetch(&cpu_num, &possible);
+	if (!info)
+		return -1;
+
+	get_pcpu_lock();
+
+	xen_pcpus.possible = possible;
+
+	/* Check for current cpu list */
+	for (i = 0; i < cpu_num; i++) {
+		int found = 0;
+
+		if (info[i].flags & XEN_PCPU_FLAGS_INVALID)
+			continue;
+
+		present++;
+		list_for_each_entry(pcpu, &xen_pcpus.list, pcpu_list) {
+			if (same_pcpu(&info[i], pcpu)) {
+				xen_pcpu_online_check(&info[i], pcpu);
+				pcpu->status |= PCPU_LOOPED;
+				found = 1;
+			}
+		}
+		if (!found) {
+			struct pcpu *cpu;
+
+			/*
+			 * Normally a physical cpu is onlined in two step
+			 * Firstly, the physical CPU is hot-added, secondly
+			 * it will be take online through sysfs writing
+			 * So a hot-added CPU should be offlined initially
+			 */
+			if (xen_pcpu_online(info[i].flags))
+				printk(KERN_WARNING "xen_pcpu_sync:"
+					"A hotadd cpu is onlined also\n");
+
+			cpu = xen_pcpu_add(&info[i]);
+			if (cpu == NULL)
+				goto failed;
+			raw_notifier_call_chain(&xen_pcpu_chain,
+					XEN_PCPU_ADD,
+					(void *)(long)cpu->xen_id);
+			cpu->status |= PCPU_LOOPED;
+		}
+	}
+
+	list_for_each_safe(elem, tmp, &xen_pcpus.list) {
+		pcpu = list_entry(elem, struct pcpu, pcpu_list);
+		if (pcpu->status & PCPU_LOOPED)
+			pcpu->status &= ~PCPU_LOOPED;
+		else {
+			/* The pcpu does not exist any more, remove it */
+			raw_notifier_call_chain(&xen_pcpu_chain,
+					XEN_PCPU_REMOVE,
+					(void *)(long)pcpu->xen_id);
+			xen_pcpu_free(pcpu);
+		}
+	}
+
+	xen_pcpus.present = present;
+	ret = 0;
+failed:
+	put_pcpu_lock();
+	kfree(info);
+	return ret;
+}
+
+static int __init xen_pcpu_info_init(void)
+{
+	int possible, cpu_num, i;
+	struct xen_physical_cpuinfo *info = NULL;
+	struct list_head *elem, *tmp;
+	struct pcpu *pcpu;
+
+	info = xen_pcpu_info_fetch(&cpu_num, &possible);
+	if (!info) {
+		printk(KERN_WARNING
+			"xen_pcpu_info_init: Failed to fetch pcpu_info\n");
+		return -1;
+	}
+
+	get_pcpu_lock();
+
+	INIT_LIST_HEAD(&xen_pcpus.list);
+	xen_pcpus.possible = possible;
+	xen_pcpus.present = 0;
+
+	for (i = 0; i < cpu_num; i++) {
+		if (info[i].flags & XEN_PCPU_FLAGS_INVALID)
+			continue;
+		pcpu = xen_pcpu_add(&info[i]);
+		if (!pcpu)
+			goto failed;
+		xen_pcpus.present++;
+	}
+
+	put_pcpu_lock();
+	kfree(info);
+
+	return 0;
+failed:
+	list_for_each_safe(elem, tmp, &xen_pcpus.list) {
+		pcpu = list_entry(elem, struct pcpu, pcpu_list);
+		xen_pcpu_free(pcpu);
+	}
+	xen_pcpus.possible = xen_pcpus.present = 0;
+	INIT_LIST_HEAD(&xen_pcpus.list);
+	put_pcpu_lock();
+
+	kfree(info);
+	return -1;
+}
+
+static void xen_pcpu_dpc(struct work_struct *work)
+{
+	if (xen_pcpu_sync() < 0)
+		printk(KERN_WARNING
+			"xen_pcpu_dpc: Failed to sync pcpu information\n");
+}
+static DECLARE_WORK(xen_pcpu_work, xen_pcpu_dpc);
+
+/*
+ * type: 0 add, 1 remove
+ */
+int xen_pcpu_hotplug(int type, uint32_t apic_id)
+{
+	struct pcpu *pcpu;
+	int found = 0;
+
+	xen_pcpu_sync();
+	get_pcpu_lock();
+	list_for_each_entry(pcpu, &xen_pcpus.list, pcpu_list)
+	{
+		if (pcpu->apic_id == apic_id) {
+			found = 1;
+			break;
+		}
+	}
+	put_pcpu_lock();
+
+	if (!found && (type == HOTPLUG_TYPE_ADD))
+		printk(KERN_WARNING "The cpu is not added into Xen HV?\n");
+
+	if (found && (type == HOTPLUG_TYPE_REMOVE))
+		printk(KERN_WARNING "The cpu still exits in Xen HV?\n");
+	return 0;
+}
+EXPORT_SYMBOL(xen_pcpu_hotplug);
+
+static irqreturn_t xen_pcpu_interrupt(int irq, void *dev_id)
+{
+	schedule_work(&xen_pcpu_work);
+	return IRQ_HANDLED;
+}
+
+static int __init xen_pcpu_init(void)
+{
+	int err;
+
+	if (!xen_initial_domain())
+		return 0;
+
+	err = sysdev_class_register(&xen_pcpu_sysdev_class);
+	if (err) {
+		printk(KERN_WARNING
+			"xen_pcpu_init: register xen_pcpu sysdev Failed!\n");
+		return err;
+	}
+
+	err = xen_pcpu_info_init();
+	if (!err)
+		err = bind_virq_to_irqhandler(VIRQ_PCPU_STATE,
+			0, xen_pcpu_interrupt, 0, "pcpu", NULL);
+	if (err < 0)
+		printk(KERN_WARNING "xen_pcpu_init: "
+			"Failed to bind pcpu_state virq\n"
+			"You will lost latest information! \n");
+	return err;
+}
+
+subsys_initcall(xen_pcpu_init);
diff --git a/include/xen/interface/platform.h b/include/xen/interface/platform.h
index 6783fce..a9cf4e2 100644
--- a/include/xen/interface/platform.h
+++ b/include/xen/interface/platform.h
@@ -312,6 +312,52 @@ struct xenpf_set_processor_pminfo {
 typedef struct xenpf_set_processor_pminfo xenpf_set_processor_pminfo_t;
 DEFINE_GUEST_HANDLE_STRUCT(xenpf_set_processor_pminfo);
 
+#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_GUEST_HANDLE_STRUCT(xen_physical_cpuinfo);
+
+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;
+	GUEST_HANDLE(xen_physical_cpuinfo) info;
+};
+typedef struct xenpf_pcpu_info xenpf_pcpu_info_t;
+DEFINE_GUEST_HANDLE_STRUCT(xenpf_pcpu_info);
+
+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 +373,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 --git a/include/xen/interface/xen.h b/include/xen/interface/xen.h
index 812ffd5..9ffaee0 100644
--- a/include/xen/interface/xen.h
+++ b/include/xen/interface/xen.h
@@ -79,6 +79,7 @@
 #define VIRQ_CONSOLE    2  /* (DOM0) Bytes received on emergency console. */
 #define VIRQ_DOM_EXC    3  /* (DOM0) Exceptional event for some domain.   */
 #define VIRQ_DEBUGGER   6  /* (DOM0) A domain has paused for debugging.   */
+#define VIRQ_PCPU_STATE 9  /* (DOM0) PCPU state changed                   */
 
 /* Architecture-specific VIRQ definitions. */
 #define VIRQ_ARCH_0    16
diff --git a/include/xen/pcpu.h b/include/xen/pcpu.h
new file mode 100644
index 0000000..32fcb0d
--- /dev/null
+++ b/include/xen/pcpu.h
@@ -0,0 +1,30 @@
+#ifndef _XEN_PCPU_H
+#define _XEN_PCPU_H
+
+#include <xen/interface/platform.h>
+extern int xen_pcpu_hotplug(int type, uint32_t apic_id);
+#define XEN_PCPU_ONLINE     0x01
+#define XEN_PCPU_OFFLINE    0x02
+#define XEN_PCPU_ADD        0x04
+#define XEN_PCPU_REMOVE     0x08
+
+struct pcpu {
+	struct list_head pcpu_list;
+	struct sys_device sysdev;
+	uint32_t xen_id;
+	uint32_t apic_id;
+	uint32_t acpi_id;
+	uint32_t flags;
+#define PCPU_LOOPED 0x10000000
+	uint32_t status;
+};
+
+static inline int xen_pcpu_online(uint32_t flags)
+{
+	return !!(flags & XEN_PCPU_FLAGS_ONLINE);
+}
+
+extern int register_xen_pcpu_notifier(struct notifier_block *nb);
+
+extern void unregister_xen_pcpu_notifier(struct notifier_block *nb);
+#endif

[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

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

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: Re: [PATCH] Add hypercall to expose physical CPU in xen hypervisor
  2009-11-10 12:16         ` Jiang, Yunhong
@ 2009-11-10 16:36           ` Konrad Rzeszutek Wilk
  2009-11-10 18:00             ` Jeremy Fitzhardinge
  0 siblings, 1 reply; 10+ messages in thread
From: Konrad Rzeszutek Wilk @ 2009-11-10 16:36 UTC (permalink / raw)
  To: Jiang, Yunhong; +Cc: Jeremy Fitzhardinge, xen-devel, Keir Fraser

On Tue, Nov 10, 2009 at 08:16:42PM +0800, Jiang, Yunhong wrote:
> Jeremy, here is the update patch according to the new interface, please have a look.
> One changes in this patch is, the apic_id/acpi_id is exposed in sysfs also.
> 
> Thanks
> yunhong Jiang
> 
> Export host physical CPU information to dom0
> 
> From: Jiang, Yunhong <yunhong.jiang@intel.com>
> 
> This patch expose host's physical CPU information to dom0 in sysfs, so that dom0's management tools can control the physical CPU if needed.
> 
> It also provides interface in sysfs to logical online/offline a physical CPU.
> 
> Notice: The information in dom0 is synced with xen hypervisor asynchronously.
> 
> Signed-off-by: Jiang, Yunhong <yunhong.jiang@intel.com>



Here is what checkpatch says:

WARNING: do not add new typedefs
#523: FILE: include/xen/interface/platform.h:328:
+typedef struct xen_physical_cpuinfo xen_physical_cpuinfo_t;

WARNING: do not add new typedefs
#537: FILE: include/xen/interface/platform.h:342:
+typedef struct xenpf_pcpu_info xenpf_pcpu_info_t;

total: 0 errors, 2 warnings, 564 lines checked

/home/konrad/01-dom0_pcpu.patch has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Re: [PATCH] Add hypercall to expose physical CPU in xen hypervisor
  2009-11-10 16:36           ` Konrad Rzeszutek Wilk
@ 2009-11-10 18:00             ` Jeremy Fitzhardinge
  0 siblings, 0 replies; 10+ messages in thread
From: Jeremy Fitzhardinge @ 2009-11-10 18:00 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk; +Cc: xen-devel, Jiang, Yunhong, Keir Fraser

On 11/10/09 08:36, Konrad Rzeszutek Wilk wrote:
> Here is what checkpatch says:
>
> WARNING: do not add new typedefs
> #523: FILE: include/xen/interface/platform.h:328:
> +typedef struct xen_physical_cpuinfo xen_physical_cpuinfo_t;
>
> WARNING: do not add new typedefs
> #537: FILE: include/xen/interface/platform.h:342:
> +typedef struct xenpf_pcpu_info xenpf_pcpu_info_t;
>
> total: 0 errors, 2 warnings, 564 lines checked
>
> /home/konrad/01-dom0_pcpu.patch has style problems, please review.  If any of these errors
> are false positives report them to the maintainer, see
> CHECKPATCH in MAINTAINERS.
>   

Unfortunately I think the typedefs are necessary for the GUEST_HANDLE stuff.

    J

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2009-11-10 18:00 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-11-06  8:20 [PATCH] Add hypercall to expose physical CPU in xen hypervisor Jiang, Yunhong
2009-11-06 16:30 ` Keir Fraser
2009-11-08  1:59   ` Jiang, Yunhong
2009-11-08  7:46     ` Keir Fraser
2009-11-09  0:45       ` Jiang, Yunhong
2009-11-09 22:03       ` Jeremy Fitzhardinge
2009-11-10 12:16         ` Jiang, Yunhong
2009-11-10 16:36           ` Konrad Rzeszutek Wilk
2009-11-10 18:00             ` Jeremy Fitzhardinge
2009-11-10 12:02       ` Jiang, Yunhong

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.