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
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
|