The following patch makes the CPU off/online sysctl hypercalls return
the old status, and also adds a call to retrieve the status only.
Having the status is useful, and this matches the Solaris p_online call
more closely, which is what the Solaris FMA code likes to have.
This patch also makes sure to restore the warm boot vector (as the
normal boot code does after bringing up CPU(s)), since not doing that
can result in problems at the next reboot, with the CPU jumping back
into Xen instead of into the BIOS to reboot.
- Frank
Add CPU status info and a status call to the CPU on/offline sysctls.
Signed-off-by: Frank van der Linden <frank.vanderlinden@xxxxxxx>
diff --git a/xen/arch/x86/smpboot.c b/xen/arch/x86/smpboot.c
--- a/xen/arch/x86/smpboot.c
+++ b/xen/arch/x86/smpboot.c
@@ -1426,8 +1426,10 @@ int __devinit __cpu_up(unsigned int cpu)
* cpu_callin_map is set during AP kickstart process. Its reset
* when a cpu is taken offline from cpu_exit_clear().
*/
- if (!cpu_isset(cpu, cpu_callin_map))
+ if (!cpu_isset(cpu, cpu_callin_map)) {
ret = __smp_prepare_cpu(cpu);
+ smpboot_restore_warm_reset_vector();
+ }
if (ret)
return -EIO;
diff --git a/xen/arch/x86/sysctl.c b/xen/arch/x86/sysctl.c
--- a/xen/arch/x86/sysctl.c
+++ b/xen/arch/x86/sysctl.c
@@ -38,7 +38,7 @@ long arch_do_sysctl(
long arch_do_sysctl(
struct xen_sysctl *sysctl, XEN_GUEST_HANDLE(xen_sysctl_t) u_sysctl)
{
- long ret = 0;
+ long ret = 0, status;
switch ( sysctl->cmd )
{
@@ -102,19 +102,41 @@ long arch_do_sysctl(
{
unsigned int cpu = sysctl->u.cpu_hotplug.cpu;
+ if (cpu_present(cpu)) {
+ status = cpu_online(cpu) ? XEN_CPU_HOTPLUG_STATUS_ONLINE :
+ XEN_CPU_HOTPLUG_STATUS_OFFLINE;
+ } else {
+ status = -EINVAL;
+ }
+
switch ( sysctl->u.cpu_hotplug.op )
{
case XEN_SYSCTL_CPU_HOTPLUG_ONLINE:
ret = cpu_up(cpu);
+ /*
+ * In the case of a true hotplug, this CPU wasn't present
+ * before, so return the 'new' status for it.
+ */
+ if (ret == 0 && status == -EINVAL)
+ status = XEN_CPU_HOTPLUG_STATUS_NEW;
break;
case XEN_SYSCTL_CPU_HOTPLUG_OFFLINE:
ret = continue_hypercall_on_cpu(
0, cpu_down_helper, (void *)(unsigned long)cpu);
break;
+ case XEN_SYSCTL_CPU_HOTPLUG_STATUS:
+ ret = 0;
+ break;
default:
ret = -EINVAL;
break;
}
+
+ /*
+ * If the operation was successful, return the old status.
+ */
+ if (ret >= 0)
+ ret = status;
}
break;
diff --git a/xen/include/public/sysctl.h b/xen/include/public/sysctl.h
--- a/xen/include/public/sysctl.h
+++ b/xen/include/public/sysctl.h
@@ -262,12 +262,21 @@ typedef struct xen_sysctl_get_pmstat xen
typedef struct xen_sysctl_get_pmstat xen_sysctl_get_pmstat_t;
DEFINE_XEN_GUEST_HANDLE(xen_sysctl_get_pmstat_t);
+/*
+ * Status codes. Must be greater than 0 to avoid confusing
+ * sysctl callers that see 0 as a plain successful return.
+ */
+#define XEN_CPU_HOTPLUG_STATUS_OFFLINE 1
+#define XEN_CPU_HOTPLUG_STATUS_ONLINE 2
+#define XEN_CPU_HOTPLUG_STATUS_NEW 3
+
#define XEN_SYSCTL_cpu_hotplug 11
struct xen_sysctl_cpu_hotplug {
/* IN variables */
uint32_t cpu; /* Physical cpu. */
#define XEN_SYSCTL_CPU_HOTPLUG_ONLINE 0
#define XEN_SYSCTL_CPU_HOTPLUG_OFFLINE 1
+#define XEN_SYSCTL_CPU_HOTPLUG_STATUS 2
uint32_t op; /* hotplug opcode */
};
typedef struct xen_sysctl_cpu_hotplug xen_sysctl_cpu_hotplug_t;
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|