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

[Xen-devel] [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@xxxxxxxxx>
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@xxxxxxxxx>
Signed-off-by: Jiang, Yunhong <yunhong.jiang@xxxxxxxxx>
Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@xxxxxxxxxx>
---
 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

Attachment: 0004-Xen-Add-pcpu-hotadd-support-to-pvops-dom0.patch
Description: 0004-Xen-Add-pcpu-hotadd-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®.