From: Keir Fraser Date: Tue, 17 Mar 2009 14:25:41 +0000 (+0000) Subject: Add CPU status info and a status call to the CPU on/offline sysctls. X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~13992^2~57 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=b44d50121f8afef94704ff639617d1e32056802e;p=xen.git Add CPU status info and a status call to the CPU on/offline sysctls. Signed-off-by: Frank van der Linden --- diff --git a/xen/arch/x86/smpboot.c b/xen/arch/x86/smpboot.c index 2842fa6a57..64b55ebc86 100644 --- 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 index dbb54ede09..faf3f5157c 100644 --- a/xen/arch/x86/sysctl.c +++ b/xen/arch/x86/sysctl.c @@ -38,7 +38,7 @@ static long cpu_down_helper(void *data) 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 index 7e1a4968f6..fe9f4b5611 100644 --- a/xen/include/public/sysctl.h +++ b/xen/include/public/sysctl.h @@ -262,12 +262,21 @@ struct xen_sysctl_get_pmstat { 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;