Liu, Jinsong
2011-Dec-22 10:05 UTC
[PATCH 04/10] Xen: Add pcpu hotadd support to pvops dom0.
From 5f5eb7bf950836edb4910173d3be2f26ad737093 Mon Sep 17 00:00:00 2001 From: Liu Jinsong <jinsong.liu@intel.com> Date: Sun, 11 Dec 2011 15:42:03 +0800 Subject: [PATCH 04/10] Xen: Add pcpu hotadd support to pvops dom0. This patch rebased from Jeremy''s pvops commit 3129884bc75d7e6578be7499ac04a06d9fc5b31d This patch implement CPU hotplug callback in xen acpi_processor. User can later bring the pcpu online through sysfs interface. xen_get_apic_id() is mostly duplicated with the get_cpu_id() in driver/acpi/processor_core.c, but it should be ok since it has been duplicated in arch directory already by upstream kernel. One thing left is, currently the acpi_processor''s id is quite confusing (it is in fact with vcpu''s dom0 cpu_id). Will update it with xen''s cpuid through the pcpu interface. But to achieve it, we need investigate more on the pr->id, and also we need change the pcpu logic to use spin_lock, instead of mutex for the pcpu list. That will be next step. Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com> Signed-off-by: Jiang, Yunhong <yunhong.jiang@intel.com> Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com> --- drivers/xen/acpi_processor.c | 114 +++++++++++++++++++++++++++++++++++++- include/xen/interface/platform.h | 10 +++- 2 files changed, 122 insertions(+), 2 deletions(-) diff --git a/drivers/xen/acpi_processor.c b/drivers/xen/acpi_processor.c index 327a56e..acab49b 100644 --- a/drivers/xen/acpi_processor.c +++ b/drivers/xen/acpi_processor.c @@ -22,12 +22,19 @@ #include <linux/cpufreq.h> #include <acpi/processor.h> #include <xen/acpi.h> +#include <xen/pcpu.h> #include <xen/interface/platform.h> #include <asm/xen/hypercall.h> #include <asm/xen/hypervisor.h> -static struct processor_cntl_xen_ops xen_ops; +static int xen_get_apic_id(acpi_handle handle); +static int xen_cpu_hotplug_notifier(struct acpi_processor *pr, int event); + +static struct processor_cntl_xen_ops xen_ops = { + .hotplug = xen_cpu_hotplug_notifier, +}; + int processor_cntl_xen_notify(struct acpi_processor *pr, int event, int type) { int ret = -EINVAL; @@ -41,6 +48,18 @@ int processor_cntl_xen_notify(struct acpi_processor *pr, int event, int type) ret = xen_ops.pm_ops[type](pr, event); break; + case PROCESSOR_HOTPLUG: + { + int apic_id; + + apic_id = xen_get_apic_id(pr->handle); + if (apic_id < 0) + break; + if (xen_ops.hotplug) + ret = xen_ops.hotplug(pr, type); + xen_pcpu_hotplug(type, apic_id); + break; + } default: printk(KERN_ERR "Unsupport processor events %d.\n", event); break; @@ -50,6 +69,49 @@ int processor_cntl_xen_notify(struct acpi_processor *pr, int event, int type) } EXPORT_SYMBOL(processor_cntl_xen_notify); +#ifdef CONFIG_ACPI_HOTPLUG_CPU +static int xen_get_apic_id(acpi_handle handle) +{ + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + union acpi_object *obj; + struct acpi_madt_local_apic *lapic; + u8 physid; + + if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer))) + return -EINVAL; + + if (!buffer.length || !buffer.pointer) + return -EINVAL; + + obj = buffer.pointer; + if (obj->type != ACPI_TYPE_BUFFER || + obj->buffer.length < sizeof(*lapic)) { + kfree(buffer.pointer); + return -EINVAL; + } + + lapic = (struct acpi_madt_local_apic *)obj->buffer.pointer; + + if (lapic->header.type != ACPI_MADT_TYPE_LOCAL_APIC || + !(lapic->lapic_flags & ACPI_MADT_ENABLED)) { + kfree(buffer.pointer); + return -EINVAL; + } + + physid = lapic->id; + kfree(buffer.pointer); + buffer.length = ACPI_ALLOCATE_BUFFER; + buffer.pointer = NULL; + + return physid; +} +#else +static int xen_get_apic_id(acpi_handle handle) +{ + return -1; +} +#endif + static inline void xen_convert_pct_reg(struct xen_pct_register *xpct, struct acpi_pct_register *apct) { @@ -246,6 +308,56 @@ static int xen_px_notifier(struct acpi_processor *pr, int action) return ret; } +#ifdef CONFIG_ACPI_HOTPLUG_CPU +static int xen_cpu_hotplug_notifier(struct acpi_processor *pr, int event) +{ + int ret = -EINVAL; + uint32_t apic_id; + unsigned long long pxm; + acpi_status status = 0; + + xen_platform_op_t op = { + .interface_version = XENPF_INTERFACE_VERSION, + }; + + apic_id = xen_get_apic_id(pr->handle); + if (apic_id < 0) { + printk(KERN_WARNING "Can''t get apic_id for acpi_id %x\n", + pr->acpi_id); + return -1; + } + + status = acpi_evaluate_integer(pr->handle, "_PXM", + NULL, &pxm); + if (ACPI_FAILURE(status)) { + printk(KERN_WARNING "can''t get pxm for acpi_id %x\n", + pr->acpi_id); + return -1; + } + + switch (event) { + case HOTPLUG_TYPE_ADD: + op.cmd = XENPF_cpu_hotadd; + op.u.cpu_add.apic_id = apic_id; + op.u.cpu_add.acpi_id = pr->acpi_id; + op.u.cpu_add.pxm = pxm; + ret = HYPERVISOR_dom0_op(&op); + break; + case HOTPLUG_TYPE_REMOVE: + printk(KERN_WARNING "Xen not support CPU hotremove\n"); + ret = -ENOSYS; + break; + } + + return ret; +} +#else +static int xen_cpu_hotplug_notifier(struct acpi_processor *pr, int event) +{ + return -ENOSYS; +} +#endif + static int __init xen_acpi_processor_extcntl_init(void) { unsigned int pmbits; diff --git a/include/xen/interface/platform.h b/include/xen/interface/platform.h index 47ffe16..9fd6b07 100644 --- a/include/xen/interface/platform.h +++ b/include/xen/interface/platform.h @@ -317,11 +317,18 @@ DEFINE_GUEST_HANDLE_STRUCT(xenpf_pcpuinfo_t); #define XENPF_cpu_online 56 #define XENPF_cpu_offline 57 struct xenpf_cpu_ol { - uint32_t cpuid; + uint32_t cpuid; }; typedef struct xenpf_cpu_ol xenpf_cpu_ol_t; DEFINE_GUEST_HANDLE_STRUCT(xenpf_cpu_ol_t); +#define XENPF_cpu_hotadd 58 +struct xenpf_cpu_hotadd { + uint32_t apic_id; + uint32_t acpi_id; + uint32_t pxm; +}; + struct xen_platform_op { uint32_t cmd; uint32_t interface_version; /* XENPF_INTERFACE_VERSION */ @@ -339,6 +346,7 @@ struct xen_platform_op { struct xenpf_set_processor_pminfo set_pminfo; struct xenpf_pcpuinfo pcpu_info; struct xenpf_cpu_ol cpu_ol; + struct xenpf_cpu_hotadd cpu_add; uint8_t pad[128]; } u; }; -- 1.6.5.6 _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Liu, Jinsong
2011-Dec-23 10:26 UTC
[PATCH 04/10] Xen: Add pcpu hotadd support to pvops dom0.
From 5f5eb7bf950836edb4910173d3be2f26ad737093 Mon Sep 17 00:00:00 2001 From: Liu Jinsong <jinsong.liu@intel.com> Date: Sun, 11 Dec 2011 15:42:03 +0800 Subject: [PATCH 04/10] Xen: Add pcpu hotadd support to pvops dom0. This patch rebased from Jeremy''s pvops commit 3129884bc75d7e6578be7499ac04a06d9fc5b31d This patch implement CPU hotplug callback in xen acpi_processor. User can later bring the pcpu online through sysfs interface. xen_get_apic_id() is mostly duplicated with the get_cpu_id() in driver/acpi/processor_core.c, but it should be ok since it has been duplicated in arch directory already by upstream kernel. One thing left is, currently the acpi_processor''s id is quite confusing (it is in fact with vcpu''s dom0 cpu_id). Will update it with xen''s cpuid through the pcpu interface. But to achieve it, we need investigate more on the pr->id, and also we need change the pcpu logic to use spin_lock, instead of mutex for the pcpu list. That will be next step. Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com> Signed-off-by: Jiang, Yunhong <yunhong.jiang@intel.com> Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com> --- drivers/xen/acpi_processor.c | 114 +++++++++++++++++++++++++++++++++++++- include/xen/interface/platform.h | 10 +++- 2 files changed, 122 insertions(+), 2 deletions(-) diff --git a/drivers/xen/acpi_processor.c b/drivers/xen/acpi_processor.c index 327a56e..acab49b 100644 --- a/drivers/xen/acpi_processor.c +++ b/drivers/xen/acpi_processor.c @@ -22,12 +22,19 @@ #include <linux/cpufreq.h> #include <acpi/processor.h> #include <xen/acpi.h> +#include <xen/pcpu.h> #include <xen/interface/platform.h> #include <asm/xen/hypercall.h> #include <asm/xen/hypervisor.h> -static struct processor_cntl_xen_ops xen_ops; +static int xen_get_apic_id(acpi_handle handle); +static int xen_cpu_hotplug_notifier(struct acpi_processor *pr, int event); + +static struct processor_cntl_xen_ops xen_ops = { + .hotplug = xen_cpu_hotplug_notifier, +}; + int processor_cntl_xen_notify(struct acpi_processor *pr, int event, int type) { int ret = -EINVAL; @@ -41,6 +48,18 @@ int processor_cntl_xen_notify(struct acpi_processor *pr, int event, int type) ret = xen_ops.pm_ops[type](pr, event); break; + case PROCESSOR_HOTPLUG: + { + int apic_id; + + apic_id = xen_get_apic_id(pr->handle); + if (apic_id < 0) + break; + if (xen_ops.hotplug) + ret = xen_ops.hotplug(pr, type); + xen_pcpu_hotplug(type, apic_id); + break; + } default: printk(KERN_ERR "Unsupport processor events %d.\n", event); break; @@ -50,6 +69,49 @@ int processor_cntl_xen_notify(struct acpi_processor *pr, int event, int type) } EXPORT_SYMBOL(processor_cntl_xen_notify); +#ifdef CONFIG_ACPI_HOTPLUG_CPU +static int xen_get_apic_id(acpi_handle handle) +{ + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + union acpi_object *obj; + struct acpi_madt_local_apic *lapic; + u8 physid; + + if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer))) + return -EINVAL; + + if (!buffer.length || !buffer.pointer) + return -EINVAL; + + obj = buffer.pointer; + if (obj->type != ACPI_TYPE_BUFFER || + obj->buffer.length < sizeof(*lapic)) { + kfree(buffer.pointer); + return -EINVAL; + } + + lapic = (struct acpi_madt_local_apic *)obj->buffer.pointer; + + if (lapic->header.type != ACPI_MADT_TYPE_LOCAL_APIC || + !(lapic->lapic_flags & ACPI_MADT_ENABLED)) { + kfree(buffer.pointer); + return -EINVAL; + } + + physid = lapic->id; + kfree(buffer.pointer); + buffer.length = ACPI_ALLOCATE_BUFFER; + buffer.pointer = NULL; + + return physid; +} +#else +static int xen_get_apic_id(acpi_handle handle) +{ + return -1; +} +#endif + static inline void xen_convert_pct_reg(struct xen_pct_register *xpct, struct acpi_pct_register *apct) { @@ -246,6 +308,56 @@ static int xen_px_notifier(struct acpi_processor *pr, int action) return ret; } +#ifdef CONFIG_ACPI_HOTPLUG_CPU +static int xen_cpu_hotplug_notifier(struct acpi_processor *pr, int event) +{ + int ret = -EINVAL; + uint32_t apic_id; + unsigned long long pxm; + acpi_status status = 0; + + xen_platform_op_t op = { + .interface_version = XENPF_INTERFACE_VERSION, + }; + + apic_id = xen_get_apic_id(pr->handle); + if (apic_id < 0) { + printk(KERN_WARNING "Can''t get apic_id for acpi_id %x\n", + pr->acpi_id); + return -1; + } + + status = acpi_evaluate_integer(pr->handle, "_PXM", + NULL, &pxm); + if (ACPI_FAILURE(status)) { + printk(KERN_WARNING "can''t get pxm for acpi_id %x\n", + pr->acpi_id); + return -1; + } + + switch (event) { + case HOTPLUG_TYPE_ADD: + op.cmd = XENPF_cpu_hotadd; + op.u.cpu_add.apic_id = apic_id; + op.u.cpu_add.acpi_id = pr->acpi_id; + op.u.cpu_add.pxm = pxm; + ret = HYPERVISOR_dom0_op(&op); + break; + case HOTPLUG_TYPE_REMOVE: + printk(KERN_WARNING "Xen not support CPU hotremove\n"); + ret = -ENOSYS; + break; + } + + return ret; +} +#else +static int xen_cpu_hotplug_notifier(struct acpi_processor *pr, int event) +{ + return -ENOSYS; +} +#endif + static int __init xen_acpi_processor_extcntl_init(void) { unsigned int pmbits; diff --git a/include/xen/interface/platform.h b/include/xen/interface/platform.h index 47ffe16..9fd6b07 100644 --- a/include/xen/interface/platform.h +++ b/include/xen/interface/platform.h @@ -317,11 +317,18 @@ DEFINE_GUEST_HANDLE_STRUCT(xenpf_pcpuinfo_t); #define XENPF_cpu_online 56 #define XENPF_cpu_offline 57 struct xenpf_cpu_ol { - uint32_t cpuid; + uint32_t cpuid; }; typedef struct xenpf_cpu_ol xenpf_cpu_ol_t; DEFINE_GUEST_HANDLE_STRUCT(xenpf_cpu_ol_t); +#define XENPF_cpu_hotadd 58 +struct xenpf_cpu_hotadd { + uint32_t apic_id; + uint32_t acpi_id; + uint32_t pxm; +}; + struct xen_platform_op { uint32_t cmd; uint32_t interface_version; /* XENPF_INTERFACE_VERSION */ @@ -339,6 +346,7 @@ struct xen_platform_op { struct xenpf_set_processor_pminfo set_pminfo; struct xenpf_pcpuinfo pcpu_info; struct xenpf_cpu_ol cpu_ol; + struct xenpf_cpu_hotadd cpu_add; uint8_t pad[128]; } u; }; -- 1.6.5.6
Liu, Jinsong
2011-Dec-23 10:35 UTC
[PATCH 04/10] Xen: Add pcpu hotadd support to pvops dom0.
From 5f5eb7bf950836edb4910173d3be2f26ad737093 Mon Sep 17 00:00:00 2001 From: Liu Jinsong <jinsong.liu@intel.com> Date: Sun, 11 Dec 2011 15:42:03 +0800 Subject: [PATCH 04/10] Xen: Add pcpu hotadd support to pvops dom0. This patch rebased from Jeremy''s pvops commit 3129884bc75d7e6578be7499ac04a06d9fc5b31d This patch implement CPU hotplug callback in xen acpi_processor. User can later bring the pcpu online through sysfs interface. xen_get_apic_id() is mostly duplicated with the get_cpu_id() in driver/acpi/processor_core.c, but it should be ok since it has been duplicated in arch directory already by upstream kernel. One thing left is, currently the acpi_processor''s id is quite confusing (it is in fact with vcpu''s dom0 cpu_id). Will update it with xen''s cpuid through the pcpu interface. But to achieve it, we need investigate more on the pr->id, and also we need change the pcpu logic to use spin_lock, instead of mutex for the pcpu list. That will be next step. Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com> Signed-off-by: Jiang, Yunhong <yunhong.jiang@intel.com> Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com> --- drivers/xen/acpi_processor.c | 114 +++++++++++++++++++++++++++++++++++++- include/xen/interface/platform.h | 10 +++- 2 files changed, 122 insertions(+), 2 deletions(-) diff --git a/drivers/xen/acpi_processor.c b/drivers/xen/acpi_processor.c index 327a56e..acab49b 100644 --- a/drivers/xen/acpi_processor.c +++ b/drivers/xen/acpi_processor.c @@ -22,12 +22,19 @@ #include <linux/cpufreq.h> #include <acpi/processor.h> #include <xen/acpi.h> +#include <xen/pcpu.h> #include <xen/interface/platform.h> #include <asm/xen/hypercall.h> #include <asm/xen/hypervisor.h> -static struct processor_cntl_xen_ops xen_ops; +static int xen_get_apic_id(acpi_handle handle); +static int xen_cpu_hotplug_notifier(struct acpi_processor *pr, int event); + +static struct processor_cntl_xen_ops xen_ops = { + .hotplug = xen_cpu_hotplug_notifier, +}; + int processor_cntl_xen_notify(struct acpi_processor *pr, int event, int type) { int ret = -EINVAL; @@ -41,6 +48,18 @@ int processor_cntl_xen_notify(struct acpi_processor *pr, int event, int type) ret = xen_ops.pm_ops[type](pr, event); break; + case PROCESSOR_HOTPLUG: + { + int apic_id; + + apic_id = xen_get_apic_id(pr->handle); + if (apic_id < 0) + break; + if (xen_ops.hotplug) + ret = xen_ops.hotplug(pr, type); + xen_pcpu_hotplug(type, apic_id); + break; + } default: printk(KERN_ERR "Unsupport processor events %d.\n", event); break; @@ -50,6 +69,49 @@ int processor_cntl_xen_notify(struct acpi_processor *pr, int event, int type) } EXPORT_SYMBOL(processor_cntl_xen_notify); +#ifdef CONFIG_ACPI_HOTPLUG_CPU +static int xen_get_apic_id(acpi_handle handle) +{ + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + union acpi_object *obj; + struct acpi_madt_local_apic *lapic; + u8 physid; + + if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer))) + return -EINVAL; + + if (!buffer.length || !buffer.pointer) + return -EINVAL; + + obj = buffer.pointer; + if (obj->type != ACPI_TYPE_BUFFER || + obj->buffer.length < sizeof(*lapic)) { + kfree(buffer.pointer); + return -EINVAL; + } + + lapic = (struct acpi_madt_local_apic *)obj->buffer.pointer; + + if (lapic->header.type != ACPI_MADT_TYPE_LOCAL_APIC || + !(lapic->lapic_flags & ACPI_MADT_ENABLED)) { + kfree(buffer.pointer); + return -EINVAL; + } + + physid = lapic->id; + kfree(buffer.pointer); + buffer.length = ACPI_ALLOCATE_BUFFER; + buffer.pointer = NULL; + + return physid; +} +#else +static int xen_get_apic_id(acpi_handle handle) +{ + return -1; +} +#endif + static inline void xen_convert_pct_reg(struct xen_pct_register *xpct, struct acpi_pct_register *apct) { @@ -246,6 +308,56 @@ static int xen_px_notifier(struct acpi_processor *pr, int action) return ret; } +#ifdef CONFIG_ACPI_HOTPLUG_CPU +static int xen_cpu_hotplug_notifier(struct acpi_processor *pr, int event) +{ + int ret = -EINVAL; + uint32_t apic_id; + unsigned long long pxm; + acpi_status status = 0; + + xen_platform_op_t op = { + .interface_version = XENPF_INTERFACE_VERSION, + }; + + apic_id = xen_get_apic_id(pr->handle); + if (apic_id < 0) { + printk(KERN_WARNING "Can''t get apic_id for acpi_id %x\n", + pr->acpi_id); + return -1; + } + + status = acpi_evaluate_integer(pr->handle, "_PXM", + NULL, &pxm); + if (ACPI_FAILURE(status)) { + printk(KERN_WARNING "can''t get pxm for acpi_id %x\n", + pr->acpi_id); + return -1; + } + + switch (event) { + case HOTPLUG_TYPE_ADD: + op.cmd = XENPF_cpu_hotadd; + op.u.cpu_add.apic_id = apic_id; + op.u.cpu_add.acpi_id = pr->acpi_id; + op.u.cpu_add.pxm = pxm; + ret = HYPERVISOR_dom0_op(&op); + break; + case HOTPLUG_TYPE_REMOVE: + printk(KERN_WARNING "Xen not support CPU hotremove\n"); + ret = -ENOSYS; + break; + } + + return ret; +} +#else +static int xen_cpu_hotplug_notifier(struct acpi_processor *pr, int event) +{ + return -ENOSYS; +} +#endif + static int __init xen_acpi_processor_extcntl_init(void) { unsigned int pmbits; diff --git a/include/xen/interface/platform.h b/include/xen/interface/platform.h index 47ffe16..9fd6b07 100644 --- a/include/xen/interface/platform.h +++ b/include/xen/interface/platform.h @@ -317,11 +317,18 @@ DEFINE_GUEST_HANDLE_STRUCT(xenpf_pcpuinfo_t); #define XENPF_cpu_online 56 #define XENPF_cpu_offline 57 struct xenpf_cpu_ol { - uint32_t cpuid; + uint32_t cpuid; }; typedef struct xenpf_cpu_ol xenpf_cpu_ol_t; DEFINE_GUEST_HANDLE_STRUCT(xenpf_cpu_ol_t); +#define XENPF_cpu_hotadd 58 +struct xenpf_cpu_hotadd { + uint32_t apic_id; + uint32_t acpi_id; + uint32_t pxm; +}; + struct xen_platform_op { uint32_t cmd; uint32_t interface_version; /* XENPF_INTERFACE_VERSION */ @@ -339,6 +346,7 @@ struct xen_platform_op { struct xenpf_set_processor_pminfo set_pminfo; struct xenpf_pcpuinfo pcpu_info; struct xenpf_cpu_ol cpu_ol; + struct xenpf_cpu_hotadd cpu_add; uint8_t pad[128]; } u; }; -- 1.6.5.6