[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[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@xxxxxxxxx>
---
 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



Attachment: 0001-Add-pcpu-hotplug-support-to-pvops-dom0.patch
Description: 0001-Add-pcpu-hotplug-support-to-pvops-dom0.patch

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.