Jiang, Yunhong
2009-Dec-09 08:20 UTC
[Xen-devel] [PATCH] Add pcpu hotplug support to pvops dom0.
Base on branch: xen/dom0/acpi-parser. 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: Jiang, Yunhong <yunhong.jiang@intel.com> --- drivers/acpi/processor_core.c | 14 ++++--- drivers/xen/acpi_processor.c | 86 +++++++++++++++++++++++++++++++++++++- include/xen/interface/platform.h | 8 ++++ 3 files changed, 101 insertions(+), 7 deletions(-) diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index b75098d..3b13e65 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -1270,19 +1270,21 @@ static int xen_acpi_processor_get_info(struct acpi_device *device) cpu0_initialized = 1; + /* + * XXX TBD: We should use xen''s cpu_id for pr->id + */ pr->id = cpu_index; /* * Extra Processor objects may be enumerated on MP systems with * less than the max # of CPUs, or Xen vCPU < pCPU. * They should be ignored _iff they are physically not present. - * */ - if (pr->id == -1) { - if (ACPI_FAILURE(acpi_processor_hotadd_init(pr->handle, &pr->id)) - && !is_processor_apic_enabled(pr, device_declaration)) - return -ENODEV; - } + if (is_processor_apic_enabled(pr, device_declaration)) + processor_cntl_xen_notify(pr, + PROCESSOR_HOTPLUG, HOTPLUG_TYPE_ADD); + else + return -ENODEV; /* * On some boxes several processors use the same processor bus id. diff --git a/drivers/xen/acpi_processor.c b/drivers/xen/acpi_processor.c index 7348949..6e6d465 100644 --- a/drivers/xen/acpi_processor.c +++ b/drivers/xen/acpi_processor.c @@ -32,6 +32,7 @@ #include <linux/cpufreq.h> #include <acpi/processor.h> #include <xen/acpi.h> +#include <xen/pcpu.h> #include <asm/xen/hypercall.h> #include <asm/xen/hypervisor.h> @@ -93,6 +94,42 @@ int processor_cntl_xen_pmthr(void) } EXPORT_SYMBOL(processor_cntl_xen_pmthr); +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; +} + int processor_cntl_xen_notify(struct acpi_processor *pr, int event, int type) { int ret = -EINVAL; @@ -107,9 +144,17 @@ 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; @@ -308,9 +353,48 @@ static int xen_tx_notifier(struct acpi_processor *pr, int action) { return -EINVAL; } + static int xen_hotplug_notifier(struct acpi_processor *pr, int event) { - return -EINVAL; + 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; } static int __init xen_acpi_processor_extcntl_init(void) diff --git a/include/xen/interface/platform.h b/include/xen/interface/platform.h index 14df81d..bff3a65 100644 --- a/include/xen/interface/platform.h +++ b/include/xen/interface/platform.h @@ -337,6 +337,13 @@ struct xenpf_cpu_ol { 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 */ @@ -354,6 +361,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.5.4.2 _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel