# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1257858222 0
# Node ID d492ebacff21f7f8458bbbbbaa22336a1865487b
# Parent 50d33023051db488c5c50b317522b09f824ce7ab
Hypercall 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>
---
xen/arch/x86/platform_hypercall.c | 98 ++++++++++++++++++++++++++++++-
xen/arch/x86/smpboot.c | 7 +-
xen/arch/x86/x86_64/platform_hypercall.c | 6 +
xen/include/asm-x86/smp.h | 1
xen/include/public/platform.h | 53 ++++++++++++++++
xen/include/public/xen.h | 1
6 files changed, 164 insertions(+), 2 deletions(-)
diff -r 50d33023051d -r d492ebacff21 xen/arch/x86/platform_hypercall.c
--- a/xen/arch/x86/platform_hypercall.c Tue Nov 10 13:01:09 2009 +0000
+++ b/xen/arch/x86/platform_hypercall.c Tue Nov 10 13:03:42 2009 +0000
@@ -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 50d33023051d -r d492ebacff21 xen/arch/x86/smpboot.c
--- a/xen/arch/x86/smpboot.c Tue Nov 10 13:01:09 2009 +0000
+++ b/xen/arch/x86/smpboot.c Tue Nov 10 13:03:42 2009 +0000
@@ -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 50d33023051d -r d492ebacff21 xen/arch/x86/x86_64/platform_hypercall.c
--- a/xen/arch/x86/x86_64/platform_hypercall.c Tue Nov 10 13:01:09 2009 +0000
+++ b/xen/arch/x86/x86_64/platform_hypercall.c Tue Nov 10 13:03:42 2009 +0000
@@ -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 50d33023051d -r d492ebacff21 xen/include/asm-x86/smp.h
--- a/xen/include/asm-x86/smp.h Tue Nov 10 13:01:09 2009 +0000
+++ b/xen/include/asm-x86/smp.h Tue Nov 10 13:03:42 2009 +0000
@@ -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 50d33023051d -r d492ebacff21 xen/include/public/platform.h
--- a/xen/include/public/platform.h Tue Nov 10 13:01:09 2009 +0000
+++ b/xen/include/public/platform.h Tue Nov 10 13:03:42 2009 +0000
@@ -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 50d33023051d -r d492ebacff21 xen/include/public/xen.h
--- a/xen/include/public/xen.h Tue Nov 10 13:01:09 2009 +0000
+++ b/xen/include/public/xen.h Tue Nov 10 13:03:42 2009 +0000
@@ -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-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|