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
