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