All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Add pcpu hotplug support to pvops dom0.
@ 2009-12-09  8:20 Jiang, Yunhong
  0 siblings, 0 replies; only message in thread
From: Jiang, Yunhong @ 2009-12-09  8:20 UTC (permalink / raw)
  To: Jeremy Fitzhardinge; +Cc: xen-devel

[-- Attachment #1: Type: text/plain, Size: 6091 bytes --]

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




[-- Attachment #2: 0001-Add-pcpu-hotplug-support-to-pvops-dom0.patch --]
[-- Type: application/octet-stream, Size: 6062 bytes --]

From 71f18c803d823a0a715e01170e30e4524a940914 Mon Sep 17 00:00:00 2001
From: Jiang, Yunhong <yunhong.jiang@intel.com>
Date: Wed, 9 Dec 2009 01:43:02 +0800
Subject: [PATCH] Add pcpu hotplug support to pvops dom0.

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


[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

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

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2009-12-09  8:20 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-12-09  8:20 [PATCH] Add pcpu hotplug support to pvops dom0 Jiang, Yunhong

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.