* [PATCH 08/10] xen/acpi: add cpu hotadd support
@ 2011-12-22 10:08 Liu, Jinsong
2012-10-03 13:31 ` Konrad Rzeszutek Wilk
0 siblings, 1 reply; 3+ messages in thread
From: Liu, Jinsong @ 2011-12-22 10:08 UTC (permalink / raw)
To: konrad.wilk@oracle.com, xen-devel@lists.xensource.com
Cc: Jiang, Yunhong, jeremy.fitzhardinge@citrix.com
[-- Attachment #1: Type: text/plain, Size: 10396 bytes --]
>From 282958be3a33b2f2b888e1ed3ac022bf8a199ec9 Mon Sep 17 00:00:00 2001
From: Liu Jinsong <jinsong.liu@intel.com>
Date: Wed, 14 Dec 2011 11:38:11 +0800
Subject: [PATCH 08/10] xen/acpi: add cpu hotadd support
This patch add cpu hotadd support.
It keep similar cpu hotadd logic as native, w/ some changes according
to xen requirement, hypercalling hypervisor related logic to hotadd cpu.
Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com>
Signed-off-by: Jiang, Yunhong <yunhong.jiang@intel.com>
---
drivers/acpi/processor_driver.c | 4 +-
drivers/acpi/processor_xen.c | 242 ++++++++++++++++++++++++++++++++++++++-
include/acpi/processor.h | 2 +
include/xen/pcpu.h | 2 +
4 files changed, 246 insertions(+), 4 deletions(-)
diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c
index 8a367d7..d473fd5 100644
--- a/drivers/acpi/processor_driver.c
+++ b/drivers/acpi/processor_driver.c
@@ -221,7 +221,7 @@ static int acpi_processor_errata_piix4(struct pci_dev *dev)
return 0;
}
-static int acpi_processor_errata(struct acpi_processor *pr)
+int acpi_processor_errata(struct acpi_processor *pr)
{
int result = 0;
struct pci_dev *dev = NULL;
@@ -378,7 +378,7 @@ static int acpi_processor_get_info(struct acpi_device *device)
return 0;
}
-static DEFINE_PER_CPU(void *, processor_device_array);
+DEFINE_PER_CPU(void *, processor_device_array);
void acpi_processor_notify(struct acpi_device *device, u32 event)
{
diff --git a/drivers/acpi/processor_xen.c b/drivers/acpi/processor_xen.c
index 38a1c05..3af1f73 100644
--- a/drivers/acpi/processor_xen.c
+++ b/drivers/acpi/processor_xen.c
@@ -24,6 +24,7 @@
#define PREFIX "ACPI: "
#define ACPI_PROCESSOR_CLASS "processor"
+#define ACPI_PROCESSOR_DEVICE_NAME "Processor"
#define ACPI_PROCESSOR_NOTIFY_PERFORMANCE 0x80
#define ACPI_PROCESSOR_NOTIFY_POWER 0x81
#define ACPI_PROCESSOR_NOTIFY_THROTTLING 0x82
@@ -88,6 +89,8 @@ xen_acpi_processor_hotadd_init(struct acpi_processor *pr, int *p_cpu)
PROCESSOR_HOTPLUG, HOTPLUG_TYPE_ADD))
return AE_ERROR;
+ *p_cpu = xen_pcpu_index(pr->acpi_id, 1);
+
return AE_OK;
}
@@ -149,13 +152,248 @@ err_out:
}
#endif /* CONFIG_CPU_FREQ */
+static int xen_acpi_processor_get_info(struct acpi_device *device)
+{
+ acpi_status status = 0;
+ union acpi_object object = { 0 };
+ struct acpi_buffer buffer = { sizeof(union acpi_object), &object };
+ struct acpi_processor *pr;
+ int cpu_index, device_declaration = 0;
+ static int cpu0_initialized;
+
+ pr = acpi_driver_data(device);
+ if (!pr)
+ return -EINVAL;
+
+ if (num_online_cpus() > 1)
+ errata.smp = TRUE;
+
+ acpi_processor_errata(pr);
+
+ /*
+ * Check to see if we have bus mastering arbitration control. This
+ * is required for proper C3 usage (to maintain cache coherency).
+ */
+ if (acpi_gbl_FADT.pm2_control_block && acpi_gbl_FADT.pm2_control_length) {
+ pr->flags.bm_control = 1;
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Bus mastering arbitration control present\n"));
+ } else
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "No bus mastering arbitration control\n"));
+
+ if (!strcmp(acpi_device_hid(device), ACPI_PROCESSOR_OBJECT_HID)) {
+ /* Declared with "Processor" statement; match ProcessorID */
+ status = acpi_evaluate_object(pr->handle, NULL, NULL, &buffer);
+ if (ACPI_FAILURE(status)) {
+ printk(KERN_ERR PREFIX "Evaluating processor object\n");
+ return -ENODEV;
+ }
+
+ /*
+ * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP.
+ * >>> 'acpi_get_processor_id(acpi_id, &id)' in
+ * arch/xxx/acpi.c
+ */
+ pr->acpi_id = object.processor.proc_id;
+ } else {
+ /*
+ * Declared with "Device" statement; match _UID.
+ * Note that we don't handle string _UIDs yet.
+ */
+ unsigned long long value;
+ status = acpi_evaluate_integer(pr->handle, METHOD_NAME__UID,
+ NULL, &value);
+ if (ACPI_FAILURE(status)) {
+ printk(KERN_ERR PREFIX
+ "Evaluating processor _UID [%#x]\n", status);
+ return -ENODEV;
+ }
+ device_declaration = 1;
+ pr->acpi_id = value;
+ }
+
+ cpu_index = xen_pcpu_index(pr->acpi_id, 1);
+
+ /* Handle UP system running SMP kernel, with no LAPIC in MADT */
+ if (!cpu0_initialized && (cpu_index == -1) &&
+ (num_online_cpus() == 1)) {
+ cpu_index = 0;
+ }
+
+ cpu0_initialized = 1;
+
+ pr->id = cpu_index;
+
+ /*
+ * Extra Processor objects may be enumerated on MP systems with
+ * less than the max # of CPUs. They should be ignored _iff
+ * they are physically not present.
+ */
+ if (pr->id == -1) {
+ if (ACPI_FAILURE
+ (xen_acpi_processor_hotadd_init(pr, &pr->id))) {
+ return -ENODEV;
+ }
+ }
+ /*
+ * On some boxes several processors use the same processor bus id.
+ * But they are located in different scope. For example:
+ * \_SB.SCK0.CPU0
+ * \_SB.SCK1.CPU0
+ * Rename the processor device bus id. And the new bus id will be
+ * generated as the following format:
+ * CPU+CPU ID.
+ */
+ sprintf(acpi_device_bid(device), "CPU%X", pr->id);
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d:%d]\n", pr->id,
+ pr->acpi_id));
+
+ if (!object.processor.pblk_address)
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No PBLK (NULL address)\n"));
+ else if (object.processor.pblk_length != 6)
+ printk(KERN_ERR PREFIX "Invalid PBLK length [%d]\n",
+ object.processor.pblk_length);
+ else {
+ pr->throttling.address = object.processor.pblk_address;
+ pr->throttling.duty_offset = acpi_gbl_FADT.duty_offset;
+ pr->throttling.duty_width = acpi_gbl_FADT.duty_width;
+
+ pr->pblk = object.processor.pblk_address;
+
+ /*
+ * We don't care about error returns - we just try to mark
+ * these reserved so that nobody else is confused into thinking
+ * that this region might be unused..
+ *
+ * (In particular, allocating the IO range for Cardbus)
+ */
+ request_region(pr->throttling.address, 6, "ACPI CPU throttle");
+ }
+
+ /*
+ * If ACPI describes a slot number for this CPU, we can use it
+ * ensure we get the right value in the "physical id" field
+ * of /proc/cpuinfo
+ */
+ status = acpi_evaluate_object(pr->handle, "_SUN", NULL, &buffer);
+ if (ACPI_SUCCESS(status))
+ arch_fix_phys_package_id(pr->id, object.integer.value);
+
+ return 0;
+}
+
+static int __cpuinit __xen_acpi_processor_add(struct acpi_device *device)
+{
+ struct acpi_processor *pr = NULL;
+ int result = 0;
+ struct sys_device *sysdev;
+
+ pr = kzalloc(sizeof(struct acpi_processor), GFP_KERNEL);
+ if (!pr)
+ return -ENOMEM;
+
+ if (!zalloc_cpumask_var(&pr->throttling.shared_cpu_map, GFP_KERNEL)) {
+ kfree(pr);
+ return -ENOMEM;
+ }
+
+ pr->handle = device->handle;
+ strcpy(acpi_device_name(device), ACPI_PROCESSOR_DEVICE_NAME);
+ strcpy(acpi_device_class(device), ACPI_PROCESSOR_CLASS);
+ device->driver_data = pr;
+
+ result = xen_acpi_processor_get_info(device);
+ if (result) {
+ /* Processor is physically not present */
+ return 0;
+ }
+
+#ifdef CONFIG_SMP
+ if (pr->id >= setup_max_cpus && pr->id != 0)
+ return 0;
+#endif
+
+ BUG_ON((pr->id >= nr_cpu_ids) || (pr->id < 0));
+
+ /*
+ * Buggy BIOS check
+ * ACPI id of processors can be reported wrongly by the BIOS.
+ * Don't trust it blindly
+ */
+ if (per_cpu(processor_device_array, pr->id) != NULL &&
+ per_cpu(processor_device_array, pr->id) != device) {
+ printk(KERN_WARNING "BIOS reported wrong ACPI id "
+ "for the processor\n");
+ result = -ENODEV;
+ goto err_free_cpumask;
+ }
+ per_cpu(processor_device_array, pr->id) = device;
+
+ per_cpu(processors, pr->id) = pr;
+
+ sysdev = get_cpu_sysdev(pr->id);
+ if (sysfs_create_link(&device->dev.kobj, &sysdev->kobj, "sysdev")) {
+ result = -EFAULT;
+ goto err_free_cpumask;
+ }
+
+#ifdef CONFIG_CPU_FREQ
+ acpi_processor_ppc_has_changed(pr, 0);
+#endif
+ acpi_processor_get_throttling_info(pr);
+ acpi_processor_get_limit_info(pr);
+
+
+ if (cpuidle_get_driver() == &acpi_idle_driver)
+ acpi_processor_power_init(pr, device);
+
+ pr->cdev = thermal_cooling_device_register("Processor", device,
+ &processor_cooling_ops);
+ if (IS_ERR(pr->cdev)) {
+ result = PTR_ERR(pr->cdev);
+ goto err_power_exit;
+ }
+
+ dev_dbg(&device->dev, "registered as cooling_device%d\n",
+ pr->cdev->id);
+
+ result = sysfs_create_link(&device->dev.kobj,
+ &pr->cdev->device.kobj,
+ "thermal_cooling");
+ if (result) {
+ printk(KERN_ERR PREFIX "Create sysfs link\n");
+ goto err_thermal_unregister;
+ }
+ result = sysfs_create_link(&pr->cdev->device.kobj,
+ &device->dev.kobj,
+ "device");
+ if (result) {
+ printk(KERN_ERR PREFIX "Create sysfs link\n");
+ goto err_remove_sysfs;
+ }
+
+ return 0;
+
+err_remove_sysfs:
+ sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
+err_thermal_unregister:
+ thermal_cooling_device_unregister(pr->cdev);
+err_power_exit:
+ acpi_processor_power_exit(pr, device);
+err_free_cpumask:
+ free_cpumask_var(pr->throttling.shared_cpu_map);
+
+ return result;
+}
+
static int __cpuinit xen_acpi_processor_add(struct acpi_device *device)
{
struct acpi_processor *pr = NULL;
int result = 0;
- result = acpi_processor_add(device);
- if (result < 0)
+ result = __xen_acpi_processor_add(device);
+ if (result)
return result;
pr = acpi_driver_data(device);
diff --git a/include/acpi/processor.h b/include/acpi/processor.h
index c48e2f9..3a1ee01 100644
--- a/include/acpi/processor.h
+++ b/include/acpi/processor.h
@@ -225,6 +225,8 @@ struct acpi_processor_errata {
} piix4;
};
+extern int acpi_processor_errata(struct acpi_processor *pr);
+
extern int acpi_processor_preregister_performance(struct
acpi_processor_performance
__percpu *performance);
diff --git a/include/xen/pcpu.h b/include/xen/pcpu.h
index 7e8f9d1..3e99db9 100644
--- a/include/xen/pcpu.h
+++ b/include/xen/pcpu.h
@@ -4,6 +4,8 @@
#include <xen/interface/platform.h>
#include <linux/sysdev.h>
+extern DEFINE_PER_CPU(void *, processor_device_array);
+
extern int xen_pcpu_hotplug(int type, uint32_t apic_id);
#define XEN_PCPU_ONLINE 0x01
#define XEN_PCPU_OFFLINE 0x02
--
1.6.5.6
[-- Attachment #2: 0008-xen-acpi-add-cpu-hotadd-support.patch --]
[-- Type: application/octet-stream, Size: 10056 bytes --]
From 282958be3a33b2f2b888e1ed3ac022bf8a199ec9 Mon Sep 17 00:00:00 2001
From: Liu Jinsong <jinsong.liu@intel.com>
Date: Wed, 14 Dec 2011 11:38:11 +0800
Subject: [PATCH 08/10] xen/acpi: add cpu hotadd support
This patch add cpu hotadd support.
It keep similar cpu hotadd logic as native, w/ some changes according
to xen requirement, hypercalling hypervisor related logic to hotadd cpu.
Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com>
Signed-off-by: Jiang, Yunhong <yunhong.jiang@intel.com>
---
drivers/acpi/processor_driver.c | 4 +-
drivers/acpi/processor_xen.c | 242 ++++++++++++++++++++++++++++++++++++++-
include/acpi/processor.h | 2 +
include/xen/pcpu.h | 2 +
4 files changed, 246 insertions(+), 4 deletions(-)
diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c
index 8a367d7..d473fd5 100644
--- a/drivers/acpi/processor_driver.c
+++ b/drivers/acpi/processor_driver.c
@@ -221,7 +221,7 @@ static int acpi_processor_errata_piix4(struct pci_dev *dev)
return 0;
}
-static int acpi_processor_errata(struct acpi_processor *pr)
+int acpi_processor_errata(struct acpi_processor *pr)
{
int result = 0;
struct pci_dev *dev = NULL;
@@ -378,7 +378,7 @@ static int acpi_processor_get_info(struct acpi_device *device)
return 0;
}
-static DEFINE_PER_CPU(void *, processor_device_array);
+DEFINE_PER_CPU(void *, processor_device_array);
void acpi_processor_notify(struct acpi_device *device, u32 event)
{
diff --git a/drivers/acpi/processor_xen.c b/drivers/acpi/processor_xen.c
index 38a1c05..3af1f73 100644
--- a/drivers/acpi/processor_xen.c
+++ b/drivers/acpi/processor_xen.c
@@ -24,6 +24,7 @@
#define PREFIX "ACPI: "
#define ACPI_PROCESSOR_CLASS "processor"
+#define ACPI_PROCESSOR_DEVICE_NAME "Processor"
#define ACPI_PROCESSOR_NOTIFY_PERFORMANCE 0x80
#define ACPI_PROCESSOR_NOTIFY_POWER 0x81
#define ACPI_PROCESSOR_NOTIFY_THROTTLING 0x82
@@ -88,6 +89,8 @@ xen_acpi_processor_hotadd_init(struct acpi_processor *pr, int *p_cpu)
PROCESSOR_HOTPLUG, HOTPLUG_TYPE_ADD))
return AE_ERROR;
+ *p_cpu = xen_pcpu_index(pr->acpi_id, 1);
+
return AE_OK;
}
@@ -149,13 +152,248 @@ err_out:
}
#endif /* CONFIG_CPU_FREQ */
+static int xen_acpi_processor_get_info(struct acpi_device *device)
+{
+ acpi_status status = 0;
+ union acpi_object object = { 0 };
+ struct acpi_buffer buffer = { sizeof(union acpi_object), &object };
+ struct acpi_processor *pr;
+ int cpu_index, device_declaration = 0;
+ static int cpu0_initialized;
+
+ pr = acpi_driver_data(device);
+ if (!pr)
+ return -EINVAL;
+
+ if (num_online_cpus() > 1)
+ errata.smp = TRUE;
+
+ acpi_processor_errata(pr);
+
+ /*
+ * Check to see if we have bus mastering arbitration control. This
+ * is required for proper C3 usage (to maintain cache coherency).
+ */
+ if (acpi_gbl_FADT.pm2_control_block && acpi_gbl_FADT.pm2_control_length) {
+ pr->flags.bm_control = 1;
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Bus mastering arbitration control present\n"));
+ } else
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "No bus mastering arbitration control\n"));
+
+ if (!strcmp(acpi_device_hid(device), ACPI_PROCESSOR_OBJECT_HID)) {
+ /* Declared with "Processor" statement; match ProcessorID */
+ status = acpi_evaluate_object(pr->handle, NULL, NULL, &buffer);
+ if (ACPI_FAILURE(status)) {
+ printk(KERN_ERR PREFIX "Evaluating processor object\n");
+ return -ENODEV;
+ }
+
+ /*
+ * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP.
+ * >>> 'acpi_get_processor_id(acpi_id, &id)' in
+ * arch/xxx/acpi.c
+ */
+ pr->acpi_id = object.processor.proc_id;
+ } else {
+ /*
+ * Declared with "Device" statement; match _UID.
+ * Note that we don't handle string _UIDs yet.
+ */
+ unsigned long long value;
+ status = acpi_evaluate_integer(pr->handle, METHOD_NAME__UID,
+ NULL, &value);
+ if (ACPI_FAILURE(status)) {
+ printk(KERN_ERR PREFIX
+ "Evaluating processor _UID [%#x]\n", status);
+ return -ENODEV;
+ }
+ device_declaration = 1;
+ pr->acpi_id = value;
+ }
+
+ cpu_index = xen_pcpu_index(pr->acpi_id, 1);
+
+ /* Handle UP system running SMP kernel, with no LAPIC in MADT */
+ if (!cpu0_initialized && (cpu_index == -1) &&
+ (num_online_cpus() == 1)) {
+ cpu_index = 0;
+ }
+
+ cpu0_initialized = 1;
+
+ pr->id = cpu_index;
+
+ /*
+ * Extra Processor objects may be enumerated on MP systems with
+ * less than the max # of CPUs. They should be ignored _iff
+ * they are physically not present.
+ */
+ if (pr->id == -1) {
+ if (ACPI_FAILURE
+ (xen_acpi_processor_hotadd_init(pr, &pr->id))) {
+ return -ENODEV;
+ }
+ }
+ /*
+ * On some boxes several processors use the same processor bus id.
+ * But they are located in different scope. For example:
+ * \_SB.SCK0.CPU0
+ * \_SB.SCK1.CPU0
+ * Rename the processor device bus id. And the new bus id will be
+ * generated as the following format:
+ * CPU+CPU ID.
+ */
+ sprintf(acpi_device_bid(device), "CPU%X", pr->id);
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d:%d]\n", pr->id,
+ pr->acpi_id));
+
+ if (!object.processor.pblk_address)
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No PBLK (NULL address)\n"));
+ else if (object.processor.pblk_length != 6)
+ printk(KERN_ERR PREFIX "Invalid PBLK length [%d]\n",
+ object.processor.pblk_length);
+ else {
+ pr->throttling.address = object.processor.pblk_address;
+ pr->throttling.duty_offset = acpi_gbl_FADT.duty_offset;
+ pr->throttling.duty_width = acpi_gbl_FADT.duty_width;
+
+ pr->pblk = object.processor.pblk_address;
+
+ /*
+ * We don't care about error returns - we just try to mark
+ * these reserved so that nobody else is confused into thinking
+ * that this region might be unused..
+ *
+ * (In particular, allocating the IO range for Cardbus)
+ */
+ request_region(pr->throttling.address, 6, "ACPI CPU throttle");
+ }
+
+ /*
+ * If ACPI describes a slot number for this CPU, we can use it
+ * ensure we get the right value in the "physical id" field
+ * of /proc/cpuinfo
+ */
+ status = acpi_evaluate_object(pr->handle, "_SUN", NULL, &buffer);
+ if (ACPI_SUCCESS(status))
+ arch_fix_phys_package_id(pr->id, object.integer.value);
+
+ return 0;
+}
+
+static int __cpuinit __xen_acpi_processor_add(struct acpi_device *device)
+{
+ struct acpi_processor *pr = NULL;
+ int result = 0;
+ struct sys_device *sysdev;
+
+ pr = kzalloc(sizeof(struct acpi_processor), GFP_KERNEL);
+ if (!pr)
+ return -ENOMEM;
+
+ if (!zalloc_cpumask_var(&pr->throttling.shared_cpu_map, GFP_KERNEL)) {
+ kfree(pr);
+ return -ENOMEM;
+ }
+
+ pr->handle = device->handle;
+ strcpy(acpi_device_name(device), ACPI_PROCESSOR_DEVICE_NAME);
+ strcpy(acpi_device_class(device), ACPI_PROCESSOR_CLASS);
+ device->driver_data = pr;
+
+ result = xen_acpi_processor_get_info(device);
+ if (result) {
+ /* Processor is physically not present */
+ return 0;
+ }
+
+#ifdef CONFIG_SMP
+ if (pr->id >= setup_max_cpus && pr->id != 0)
+ return 0;
+#endif
+
+ BUG_ON((pr->id >= nr_cpu_ids) || (pr->id < 0));
+
+ /*
+ * Buggy BIOS check
+ * ACPI id of processors can be reported wrongly by the BIOS.
+ * Don't trust it blindly
+ */
+ if (per_cpu(processor_device_array, pr->id) != NULL &&
+ per_cpu(processor_device_array, pr->id) != device) {
+ printk(KERN_WARNING "BIOS reported wrong ACPI id "
+ "for the processor\n");
+ result = -ENODEV;
+ goto err_free_cpumask;
+ }
+ per_cpu(processor_device_array, pr->id) = device;
+
+ per_cpu(processors, pr->id) = pr;
+
+ sysdev = get_cpu_sysdev(pr->id);
+ if (sysfs_create_link(&device->dev.kobj, &sysdev->kobj, "sysdev")) {
+ result = -EFAULT;
+ goto err_free_cpumask;
+ }
+
+#ifdef CONFIG_CPU_FREQ
+ acpi_processor_ppc_has_changed(pr, 0);
+#endif
+ acpi_processor_get_throttling_info(pr);
+ acpi_processor_get_limit_info(pr);
+
+
+ if (cpuidle_get_driver() == &acpi_idle_driver)
+ acpi_processor_power_init(pr, device);
+
+ pr->cdev = thermal_cooling_device_register("Processor", device,
+ &processor_cooling_ops);
+ if (IS_ERR(pr->cdev)) {
+ result = PTR_ERR(pr->cdev);
+ goto err_power_exit;
+ }
+
+ dev_dbg(&device->dev, "registered as cooling_device%d\n",
+ pr->cdev->id);
+
+ result = sysfs_create_link(&device->dev.kobj,
+ &pr->cdev->device.kobj,
+ "thermal_cooling");
+ if (result) {
+ printk(KERN_ERR PREFIX "Create sysfs link\n");
+ goto err_thermal_unregister;
+ }
+ result = sysfs_create_link(&pr->cdev->device.kobj,
+ &device->dev.kobj,
+ "device");
+ if (result) {
+ printk(KERN_ERR PREFIX "Create sysfs link\n");
+ goto err_remove_sysfs;
+ }
+
+ return 0;
+
+err_remove_sysfs:
+ sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
+err_thermal_unregister:
+ thermal_cooling_device_unregister(pr->cdev);
+err_power_exit:
+ acpi_processor_power_exit(pr, device);
+err_free_cpumask:
+ free_cpumask_var(pr->throttling.shared_cpu_map);
+
+ return result;
+}
+
static int __cpuinit xen_acpi_processor_add(struct acpi_device *device)
{
struct acpi_processor *pr = NULL;
int result = 0;
- result = acpi_processor_add(device);
- if (result < 0)
+ result = __xen_acpi_processor_add(device);
+ if (result)
return result;
pr = acpi_driver_data(device);
diff --git a/include/acpi/processor.h b/include/acpi/processor.h
index c48e2f9..3a1ee01 100644
--- a/include/acpi/processor.h
+++ b/include/acpi/processor.h
@@ -225,6 +225,8 @@ struct acpi_processor_errata {
} piix4;
};
+extern int acpi_processor_errata(struct acpi_processor *pr);
+
extern int acpi_processor_preregister_performance(struct
acpi_processor_performance
__percpu *performance);
diff --git a/include/xen/pcpu.h b/include/xen/pcpu.h
index 7e8f9d1..3e99db9 100644
--- a/include/xen/pcpu.h
+++ b/include/xen/pcpu.h
@@ -4,6 +4,8 @@
#include <xen/interface/platform.h>
#include <linux/sysdev.h>
+extern DEFINE_PER_CPU(void *, processor_device_array);
+
extern int xen_pcpu_hotplug(int type, uint32_t apic_id);
#define XEN_PCPU_ONLINE 0x01
#define XEN_PCPU_OFFLINE 0x02
--
1.6.5.6
[-- 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] 3+ messages in thread
* [PATCH 08/10] xen/acpi: add cpu hotadd support
@ 2011-12-23 10:30 Liu, Jinsong
0 siblings, 0 replies; 3+ messages in thread
From: Liu, Jinsong @ 2011-12-23 10:30 UTC (permalink / raw)
To: konrad.wilk@oracle.com
Cc: Jiang, Yunhong, jeremy.fitzhardinge@citrix.com, Shan, Haitao,
Zhao, Yakui, Brown, Len, Luck, Tony, Kleen, Andi,
xen-devel@lists.xensource.com, Kernel development list
[-- Attachment #1: Type: text/plain, Size: 10396 bytes --]
>From 282958be3a33b2f2b888e1ed3ac022bf8a199ec9 Mon Sep 17 00:00:00 2001
From: Liu Jinsong <jinsong.liu@intel.com>
Date: Wed, 14 Dec 2011 11:38:11 +0800
Subject: [PATCH 08/10] xen/acpi: add cpu hotadd support
This patch add cpu hotadd support.
It keep similar cpu hotadd logic as native, w/ some changes according
to xen requirement, hypercalling hypervisor related logic to hotadd cpu.
Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com>
Signed-off-by: Jiang, Yunhong <yunhong.jiang@intel.com>
---
drivers/acpi/processor_driver.c | 4 +-
drivers/acpi/processor_xen.c | 242 ++++++++++++++++++++++++++++++++++++++-
include/acpi/processor.h | 2 +
include/xen/pcpu.h | 2 +
4 files changed, 246 insertions(+), 4 deletions(-)
diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c
index 8a367d7..d473fd5 100644
--- a/drivers/acpi/processor_driver.c
+++ b/drivers/acpi/processor_driver.c
@@ -221,7 +221,7 @@ static int acpi_processor_errata_piix4(struct pci_dev *dev)
return 0;
}
-static int acpi_processor_errata(struct acpi_processor *pr)
+int acpi_processor_errata(struct acpi_processor *pr)
{
int result = 0;
struct pci_dev *dev = NULL;
@@ -378,7 +378,7 @@ static int acpi_processor_get_info(struct acpi_device *device)
return 0;
}
-static DEFINE_PER_CPU(void *, processor_device_array);
+DEFINE_PER_CPU(void *, processor_device_array);
void acpi_processor_notify(struct acpi_device *device, u32 event)
{
diff --git a/drivers/acpi/processor_xen.c b/drivers/acpi/processor_xen.c
index 38a1c05..3af1f73 100644
--- a/drivers/acpi/processor_xen.c
+++ b/drivers/acpi/processor_xen.c
@@ -24,6 +24,7 @@
#define PREFIX "ACPI: "
#define ACPI_PROCESSOR_CLASS "processor"
+#define ACPI_PROCESSOR_DEVICE_NAME "Processor"
#define ACPI_PROCESSOR_NOTIFY_PERFORMANCE 0x80
#define ACPI_PROCESSOR_NOTIFY_POWER 0x81
#define ACPI_PROCESSOR_NOTIFY_THROTTLING 0x82
@@ -88,6 +89,8 @@ xen_acpi_processor_hotadd_init(struct acpi_processor *pr, int *p_cpu)
PROCESSOR_HOTPLUG, HOTPLUG_TYPE_ADD))
return AE_ERROR;
+ *p_cpu = xen_pcpu_index(pr->acpi_id, 1);
+
return AE_OK;
}
@@ -149,13 +152,248 @@ err_out:
}
#endif /* CONFIG_CPU_FREQ */
+static int xen_acpi_processor_get_info(struct acpi_device *device)
+{
+ acpi_status status = 0;
+ union acpi_object object = { 0 };
+ struct acpi_buffer buffer = { sizeof(union acpi_object), &object };
+ struct acpi_processor *pr;
+ int cpu_index, device_declaration = 0;
+ static int cpu0_initialized;
+
+ pr = acpi_driver_data(device);
+ if (!pr)
+ return -EINVAL;
+
+ if (num_online_cpus() > 1)
+ errata.smp = TRUE;
+
+ acpi_processor_errata(pr);
+
+ /*
+ * Check to see if we have bus mastering arbitration control. This
+ * is required for proper C3 usage (to maintain cache coherency).
+ */
+ if (acpi_gbl_FADT.pm2_control_block && acpi_gbl_FADT.pm2_control_length) {
+ pr->flags.bm_control = 1;
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Bus mastering arbitration control present\n"));
+ } else
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "No bus mastering arbitration control\n"));
+
+ if (!strcmp(acpi_device_hid(device), ACPI_PROCESSOR_OBJECT_HID)) {
+ /* Declared with "Processor" statement; match ProcessorID */
+ status = acpi_evaluate_object(pr->handle, NULL, NULL, &buffer);
+ if (ACPI_FAILURE(status)) {
+ printk(KERN_ERR PREFIX "Evaluating processor object\n");
+ return -ENODEV;
+ }
+
+ /*
+ * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP.
+ * >>> 'acpi_get_processor_id(acpi_id, &id)' in
+ * arch/xxx/acpi.c
+ */
+ pr->acpi_id = object.processor.proc_id;
+ } else {
+ /*
+ * Declared with "Device" statement; match _UID.
+ * Note that we don't handle string _UIDs yet.
+ */
+ unsigned long long value;
+ status = acpi_evaluate_integer(pr->handle, METHOD_NAME__UID,
+ NULL, &value);
+ if (ACPI_FAILURE(status)) {
+ printk(KERN_ERR PREFIX
+ "Evaluating processor _UID [%#x]\n", status);
+ return -ENODEV;
+ }
+ device_declaration = 1;
+ pr->acpi_id = value;
+ }
+
+ cpu_index = xen_pcpu_index(pr->acpi_id, 1);
+
+ /* Handle UP system running SMP kernel, with no LAPIC in MADT */
+ if (!cpu0_initialized && (cpu_index == -1) &&
+ (num_online_cpus() == 1)) {
+ cpu_index = 0;
+ }
+
+ cpu0_initialized = 1;
+
+ pr->id = cpu_index;
+
+ /*
+ * Extra Processor objects may be enumerated on MP systems with
+ * less than the max # of CPUs. They should be ignored _iff
+ * they are physically not present.
+ */
+ if (pr->id == -1) {
+ if (ACPI_FAILURE
+ (xen_acpi_processor_hotadd_init(pr, &pr->id))) {
+ return -ENODEV;
+ }
+ }
+ /*
+ * On some boxes several processors use the same processor bus id.
+ * But they are located in different scope. For example:
+ * \_SB.SCK0.CPU0
+ * \_SB.SCK1.CPU0
+ * Rename the processor device bus id. And the new bus id will be
+ * generated as the following format:
+ * CPU+CPU ID.
+ */
+ sprintf(acpi_device_bid(device), "CPU%X", pr->id);
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d:%d]\n", pr->id,
+ pr->acpi_id));
+
+ if (!object.processor.pblk_address)
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No PBLK (NULL address)\n"));
+ else if (object.processor.pblk_length != 6)
+ printk(KERN_ERR PREFIX "Invalid PBLK length [%d]\n",
+ object.processor.pblk_length);
+ else {
+ pr->throttling.address = object.processor.pblk_address;
+ pr->throttling.duty_offset = acpi_gbl_FADT.duty_offset;
+ pr->throttling.duty_width = acpi_gbl_FADT.duty_width;
+
+ pr->pblk = object.processor.pblk_address;
+
+ /*
+ * We don't care about error returns - we just try to mark
+ * these reserved so that nobody else is confused into thinking
+ * that this region might be unused..
+ *
+ * (In particular, allocating the IO range for Cardbus)
+ */
+ request_region(pr->throttling.address, 6, "ACPI CPU throttle");
+ }
+
+ /*
+ * If ACPI describes a slot number for this CPU, we can use it
+ * ensure we get the right value in the "physical id" field
+ * of /proc/cpuinfo
+ */
+ status = acpi_evaluate_object(pr->handle, "_SUN", NULL, &buffer);
+ if (ACPI_SUCCESS(status))
+ arch_fix_phys_package_id(pr->id, object.integer.value);
+
+ return 0;
+}
+
+static int __cpuinit __xen_acpi_processor_add(struct acpi_device *device)
+{
+ struct acpi_processor *pr = NULL;
+ int result = 0;
+ struct sys_device *sysdev;
+
+ pr = kzalloc(sizeof(struct acpi_processor), GFP_KERNEL);
+ if (!pr)
+ return -ENOMEM;
+
+ if (!zalloc_cpumask_var(&pr->throttling.shared_cpu_map, GFP_KERNEL)) {
+ kfree(pr);
+ return -ENOMEM;
+ }
+
+ pr->handle = device->handle;
+ strcpy(acpi_device_name(device), ACPI_PROCESSOR_DEVICE_NAME);
+ strcpy(acpi_device_class(device), ACPI_PROCESSOR_CLASS);
+ device->driver_data = pr;
+
+ result = xen_acpi_processor_get_info(device);
+ if (result) {
+ /* Processor is physically not present */
+ return 0;
+ }
+
+#ifdef CONFIG_SMP
+ if (pr->id >= setup_max_cpus && pr->id != 0)
+ return 0;
+#endif
+
+ BUG_ON((pr->id >= nr_cpu_ids) || (pr->id < 0));
+
+ /*
+ * Buggy BIOS check
+ * ACPI id of processors can be reported wrongly by the BIOS.
+ * Don't trust it blindly
+ */
+ if (per_cpu(processor_device_array, pr->id) != NULL &&
+ per_cpu(processor_device_array, pr->id) != device) {
+ printk(KERN_WARNING "BIOS reported wrong ACPI id "
+ "for the processor\n");
+ result = -ENODEV;
+ goto err_free_cpumask;
+ }
+ per_cpu(processor_device_array, pr->id) = device;
+
+ per_cpu(processors, pr->id) = pr;
+
+ sysdev = get_cpu_sysdev(pr->id);
+ if (sysfs_create_link(&device->dev.kobj, &sysdev->kobj, "sysdev")) {
+ result = -EFAULT;
+ goto err_free_cpumask;
+ }
+
+#ifdef CONFIG_CPU_FREQ
+ acpi_processor_ppc_has_changed(pr, 0);
+#endif
+ acpi_processor_get_throttling_info(pr);
+ acpi_processor_get_limit_info(pr);
+
+
+ if (cpuidle_get_driver() == &acpi_idle_driver)
+ acpi_processor_power_init(pr, device);
+
+ pr->cdev = thermal_cooling_device_register("Processor", device,
+ &processor_cooling_ops);
+ if (IS_ERR(pr->cdev)) {
+ result = PTR_ERR(pr->cdev);
+ goto err_power_exit;
+ }
+
+ dev_dbg(&device->dev, "registered as cooling_device%d\n",
+ pr->cdev->id);
+
+ result = sysfs_create_link(&device->dev.kobj,
+ &pr->cdev->device.kobj,
+ "thermal_cooling");
+ if (result) {
+ printk(KERN_ERR PREFIX "Create sysfs link\n");
+ goto err_thermal_unregister;
+ }
+ result = sysfs_create_link(&pr->cdev->device.kobj,
+ &device->dev.kobj,
+ "device");
+ if (result) {
+ printk(KERN_ERR PREFIX "Create sysfs link\n");
+ goto err_remove_sysfs;
+ }
+
+ return 0;
+
+err_remove_sysfs:
+ sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
+err_thermal_unregister:
+ thermal_cooling_device_unregister(pr->cdev);
+err_power_exit:
+ acpi_processor_power_exit(pr, device);
+err_free_cpumask:
+ free_cpumask_var(pr->throttling.shared_cpu_map);
+
+ return result;
+}
+
static int __cpuinit xen_acpi_processor_add(struct acpi_device *device)
{
struct acpi_processor *pr = NULL;
int result = 0;
- result = acpi_processor_add(device);
- if (result < 0)
+ result = __xen_acpi_processor_add(device);
+ if (result)
return result;
pr = acpi_driver_data(device);
diff --git a/include/acpi/processor.h b/include/acpi/processor.h
index c48e2f9..3a1ee01 100644
--- a/include/acpi/processor.h
+++ b/include/acpi/processor.h
@@ -225,6 +225,8 @@ struct acpi_processor_errata {
} piix4;
};
+extern int acpi_processor_errata(struct acpi_processor *pr);
+
extern int acpi_processor_preregister_performance(struct
acpi_processor_performance
__percpu *performance);
diff --git a/include/xen/pcpu.h b/include/xen/pcpu.h
index 7e8f9d1..3e99db9 100644
--- a/include/xen/pcpu.h
+++ b/include/xen/pcpu.h
@@ -4,6 +4,8 @@
#include <xen/interface/platform.h>
#include <linux/sysdev.h>
+extern DEFINE_PER_CPU(void *, processor_device_array);
+
extern int xen_pcpu_hotplug(int type, uint32_t apic_id);
#define XEN_PCPU_ONLINE 0x01
#define XEN_PCPU_OFFLINE 0x02
--
1.6.5.6
[-- Attachment #2: 0008-xen-acpi-add-cpu-hotadd-support.patch --]
[-- Type: application/octet-stream, Size: 10056 bytes --]
From 282958be3a33b2f2b888e1ed3ac022bf8a199ec9 Mon Sep 17 00:00:00 2001
From: Liu Jinsong <jinsong.liu@intel.com>
Date: Wed, 14 Dec 2011 11:38:11 +0800
Subject: [PATCH 08/10] xen/acpi: add cpu hotadd support
This patch add cpu hotadd support.
It keep similar cpu hotadd logic as native, w/ some changes according
to xen requirement, hypercalling hypervisor related logic to hotadd cpu.
Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com>
Signed-off-by: Jiang, Yunhong <yunhong.jiang@intel.com>
---
drivers/acpi/processor_driver.c | 4 +-
drivers/acpi/processor_xen.c | 242 ++++++++++++++++++++++++++++++++++++++-
include/acpi/processor.h | 2 +
include/xen/pcpu.h | 2 +
4 files changed, 246 insertions(+), 4 deletions(-)
diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c
index 8a367d7..d473fd5 100644
--- a/drivers/acpi/processor_driver.c
+++ b/drivers/acpi/processor_driver.c
@@ -221,7 +221,7 @@ static int acpi_processor_errata_piix4(struct pci_dev *dev)
return 0;
}
-static int acpi_processor_errata(struct acpi_processor *pr)
+int acpi_processor_errata(struct acpi_processor *pr)
{
int result = 0;
struct pci_dev *dev = NULL;
@@ -378,7 +378,7 @@ static int acpi_processor_get_info(struct acpi_device *device)
return 0;
}
-static DEFINE_PER_CPU(void *, processor_device_array);
+DEFINE_PER_CPU(void *, processor_device_array);
void acpi_processor_notify(struct acpi_device *device, u32 event)
{
diff --git a/drivers/acpi/processor_xen.c b/drivers/acpi/processor_xen.c
index 38a1c05..3af1f73 100644
--- a/drivers/acpi/processor_xen.c
+++ b/drivers/acpi/processor_xen.c
@@ -24,6 +24,7 @@
#define PREFIX "ACPI: "
#define ACPI_PROCESSOR_CLASS "processor"
+#define ACPI_PROCESSOR_DEVICE_NAME "Processor"
#define ACPI_PROCESSOR_NOTIFY_PERFORMANCE 0x80
#define ACPI_PROCESSOR_NOTIFY_POWER 0x81
#define ACPI_PROCESSOR_NOTIFY_THROTTLING 0x82
@@ -88,6 +89,8 @@ xen_acpi_processor_hotadd_init(struct acpi_processor *pr, int *p_cpu)
PROCESSOR_HOTPLUG, HOTPLUG_TYPE_ADD))
return AE_ERROR;
+ *p_cpu = xen_pcpu_index(pr->acpi_id, 1);
+
return AE_OK;
}
@@ -149,13 +152,248 @@ err_out:
}
#endif /* CONFIG_CPU_FREQ */
+static int xen_acpi_processor_get_info(struct acpi_device *device)
+{
+ acpi_status status = 0;
+ union acpi_object object = { 0 };
+ struct acpi_buffer buffer = { sizeof(union acpi_object), &object };
+ struct acpi_processor *pr;
+ int cpu_index, device_declaration = 0;
+ static int cpu0_initialized;
+
+ pr = acpi_driver_data(device);
+ if (!pr)
+ return -EINVAL;
+
+ if (num_online_cpus() > 1)
+ errata.smp = TRUE;
+
+ acpi_processor_errata(pr);
+
+ /*
+ * Check to see if we have bus mastering arbitration control. This
+ * is required for proper C3 usage (to maintain cache coherency).
+ */
+ if (acpi_gbl_FADT.pm2_control_block && acpi_gbl_FADT.pm2_control_length) {
+ pr->flags.bm_control = 1;
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Bus mastering arbitration control present\n"));
+ } else
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "No bus mastering arbitration control\n"));
+
+ if (!strcmp(acpi_device_hid(device), ACPI_PROCESSOR_OBJECT_HID)) {
+ /* Declared with "Processor" statement; match ProcessorID */
+ status = acpi_evaluate_object(pr->handle, NULL, NULL, &buffer);
+ if (ACPI_FAILURE(status)) {
+ printk(KERN_ERR PREFIX "Evaluating processor object\n");
+ return -ENODEV;
+ }
+
+ /*
+ * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP.
+ * >>> 'acpi_get_processor_id(acpi_id, &id)' in
+ * arch/xxx/acpi.c
+ */
+ pr->acpi_id = object.processor.proc_id;
+ } else {
+ /*
+ * Declared with "Device" statement; match _UID.
+ * Note that we don't handle string _UIDs yet.
+ */
+ unsigned long long value;
+ status = acpi_evaluate_integer(pr->handle, METHOD_NAME__UID,
+ NULL, &value);
+ if (ACPI_FAILURE(status)) {
+ printk(KERN_ERR PREFIX
+ "Evaluating processor _UID [%#x]\n", status);
+ return -ENODEV;
+ }
+ device_declaration = 1;
+ pr->acpi_id = value;
+ }
+
+ cpu_index = xen_pcpu_index(pr->acpi_id, 1);
+
+ /* Handle UP system running SMP kernel, with no LAPIC in MADT */
+ if (!cpu0_initialized && (cpu_index == -1) &&
+ (num_online_cpus() == 1)) {
+ cpu_index = 0;
+ }
+
+ cpu0_initialized = 1;
+
+ pr->id = cpu_index;
+
+ /*
+ * Extra Processor objects may be enumerated on MP systems with
+ * less than the max # of CPUs. They should be ignored _iff
+ * they are physically not present.
+ */
+ if (pr->id == -1) {
+ if (ACPI_FAILURE
+ (xen_acpi_processor_hotadd_init(pr, &pr->id))) {
+ return -ENODEV;
+ }
+ }
+ /*
+ * On some boxes several processors use the same processor bus id.
+ * But they are located in different scope. For example:
+ * \_SB.SCK0.CPU0
+ * \_SB.SCK1.CPU0
+ * Rename the processor device bus id. And the new bus id will be
+ * generated as the following format:
+ * CPU+CPU ID.
+ */
+ sprintf(acpi_device_bid(device), "CPU%X", pr->id);
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d:%d]\n", pr->id,
+ pr->acpi_id));
+
+ if (!object.processor.pblk_address)
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No PBLK (NULL address)\n"));
+ else if (object.processor.pblk_length != 6)
+ printk(KERN_ERR PREFIX "Invalid PBLK length [%d]\n",
+ object.processor.pblk_length);
+ else {
+ pr->throttling.address = object.processor.pblk_address;
+ pr->throttling.duty_offset = acpi_gbl_FADT.duty_offset;
+ pr->throttling.duty_width = acpi_gbl_FADT.duty_width;
+
+ pr->pblk = object.processor.pblk_address;
+
+ /*
+ * We don't care about error returns - we just try to mark
+ * these reserved so that nobody else is confused into thinking
+ * that this region might be unused..
+ *
+ * (In particular, allocating the IO range for Cardbus)
+ */
+ request_region(pr->throttling.address, 6, "ACPI CPU throttle");
+ }
+
+ /*
+ * If ACPI describes a slot number for this CPU, we can use it
+ * ensure we get the right value in the "physical id" field
+ * of /proc/cpuinfo
+ */
+ status = acpi_evaluate_object(pr->handle, "_SUN", NULL, &buffer);
+ if (ACPI_SUCCESS(status))
+ arch_fix_phys_package_id(pr->id, object.integer.value);
+
+ return 0;
+}
+
+static int __cpuinit __xen_acpi_processor_add(struct acpi_device *device)
+{
+ struct acpi_processor *pr = NULL;
+ int result = 0;
+ struct sys_device *sysdev;
+
+ pr = kzalloc(sizeof(struct acpi_processor), GFP_KERNEL);
+ if (!pr)
+ return -ENOMEM;
+
+ if (!zalloc_cpumask_var(&pr->throttling.shared_cpu_map, GFP_KERNEL)) {
+ kfree(pr);
+ return -ENOMEM;
+ }
+
+ pr->handle = device->handle;
+ strcpy(acpi_device_name(device), ACPI_PROCESSOR_DEVICE_NAME);
+ strcpy(acpi_device_class(device), ACPI_PROCESSOR_CLASS);
+ device->driver_data = pr;
+
+ result = xen_acpi_processor_get_info(device);
+ if (result) {
+ /* Processor is physically not present */
+ return 0;
+ }
+
+#ifdef CONFIG_SMP
+ if (pr->id >= setup_max_cpus && pr->id != 0)
+ return 0;
+#endif
+
+ BUG_ON((pr->id >= nr_cpu_ids) || (pr->id < 0));
+
+ /*
+ * Buggy BIOS check
+ * ACPI id of processors can be reported wrongly by the BIOS.
+ * Don't trust it blindly
+ */
+ if (per_cpu(processor_device_array, pr->id) != NULL &&
+ per_cpu(processor_device_array, pr->id) != device) {
+ printk(KERN_WARNING "BIOS reported wrong ACPI id "
+ "for the processor\n");
+ result = -ENODEV;
+ goto err_free_cpumask;
+ }
+ per_cpu(processor_device_array, pr->id) = device;
+
+ per_cpu(processors, pr->id) = pr;
+
+ sysdev = get_cpu_sysdev(pr->id);
+ if (sysfs_create_link(&device->dev.kobj, &sysdev->kobj, "sysdev")) {
+ result = -EFAULT;
+ goto err_free_cpumask;
+ }
+
+#ifdef CONFIG_CPU_FREQ
+ acpi_processor_ppc_has_changed(pr, 0);
+#endif
+ acpi_processor_get_throttling_info(pr);
+ acpi_processor_get_limit_info(pr);
+
+
+ if (cpuidle_get_driver() == &acpi_idle_driver)
+ acpi_processor_power_init(pr, device);
+
+ pr->cdev = thermal_cooling_device_register("Processor", device,
+ &processor_cooling_ops);
+ if (IS_ERR(pr->cdev)) {
+ result = PTR_ERR(pr->cdev);
+ goto err_power_exit;
+ }
+
+ dev_dbg(&device->dev, "registered as cooling_device%d\n",
+ pr->cdev->id);
+
+ result = sysfs_create_link(&device->dev.kobj,
+ &pr->cdev->device.kobj,
+ "thermal_cooling");
+ if (result) {
+ printk(KERN_ERR PREFIX "Create sysfs link\n");
+ goto err_thermal_unregister;
+ }
+ result = sysfs_create_link(&pr->cdev->device.kobj,
+ &device->dev.kobj,
+ "device");
+ if (result) {
+ printk(KERN_ERR PREFIX "Create sysfs link\n");
+ goto err_remove_sysfs;
+ }
+
+ return 0;
+
+err_remove_sysfs:
+ sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
+err_thermal_unregister:
+ thermal_cooling_device_unregister(pr->cdev);
+err_power_exit:
+ acpi_processor_power_exit(pr, device);
+err_free_cpumask:
+ free_cpumask_var(pr->throttling.shared_cpu_map);
+
+ return result;
+}
+
static int __cpuinit xen_acpi_processor_add(struct acpi_device *device)
{
struct acpi_processor *pr = NULL;
int result = 0;
- result = acpi_processor_add(device);
- if (result < 0)
+ result = __xen_acpi_processor_add(device);
+ if (result)
return result;
pr = acpi_driver_data(device);
diff --git a/include/acpi/processor.h b/include/acpi/processor.h
index c48e2f9..3a1ee01 100644
--- a/include/acpi/processor.h
+++ b/include/acpi/processor.h
@@ -225,6 +225,8 @@ struct acpi_processor_errata {
} piix4;
};
+extern int acpi_processor_errata(struct acpi_processor *pr);
+
extern int acpi_processor_preregister_performance(struct
acpi_processor_performance
__percpu *performance);
diff --git a/include/xen/pcpu.h b/include/xen/pcpu.h
index 7e8f9d1..3e99db9 100644
--- a/include/xen/pcpu.h
+++ b/include/xen/pcpu.h
@@ -4,6 +4,8 @@
#include <xen/interface/platform.h>
#include <linux/sysdev.h>
+extern DEFINE_PER_CPU(void *, processor_device_array);
+
extern int xen_pcpu_hotplug(int type, uint32_t apic_id);
#define XEN_PCPU_ONLINE 0x01
#define XEN_PCPU_OFFLINE 0x02
--
1.6.5.6
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH 08/10] xen/acpi: add cpu hotadd support
2011-12-22 10:08 [PATCH 08/10] xen/acpi: add cpu hotadd support Liu, Jinsong
@ 2012-10-03 13:31 ` Konrad Rzeszutek Wilk
0 siblings, 0 replies; 3+ messages in thread
From: Konrad Rzeszutek Wilk @ 2012-10-03 13:31 UTC (permalink / raw)
To: Liu, Jinsong
Cc: xen-devel@lists.xensource.com, jeremy.fitzhardinge@citrix.com,
Jiang, Yunhong
On Thu, Dec 22, 2011 at 10:08:34AM +0000, Liu, Jinsong wrote:
> >From 282958be3a33b2f2b888e1ed3ac022bf8a199ec9 Mon Sep 17 00:00:00 2001
> From: Liu Jinsong <jinsong.liu@intel.com>
> Date: Wed, 14 Dec 2011 11:38:11 +0800
> Subject: [PATCH 08/10] xen/acpi: add cpu hotadd support
>
> This patch add cpu hotadd support.
> It keep similar cpu hotadd logic as native, w/ some changes according
> to xen requirement, hypercalling hypervisor related logic to hotadd cpu.
Is this needed anymore? Or is the existing code in the upstream
kernel sufficient enough for this? Or do we need a hotplug CPU notifier
in the xen-acpi-processor?
>
> Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com>
> Signed-off-by: Jiang, Yunhong <yunhong.jiang@intel.com>
> ---
> drivers/acpi/processor_driver.c | 4 +-
> drivers/acpi/processor_xen.c | 242 ++++++++++++++++++++++++++++++++++++++-
> include/acpi/processor.h | 2 +
> include/xen/pcpu.h | 2 +
> 4 files changed, 246 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c
> index 8a367d7..d473fd5 100644
> --- a/drivers/acpi/processor_driver.c
> +++ b/drivers/acpi/processor_driver.c
> @@ -221,7 +221,7 @@ static int acpi_processor_errata_piix4(struct pci_dev *dev)
> return 0;
> }
>
> -static int acpi_processor_errata(struct acpi_processor *pr)
> +int acpi_processor_errata(struct acpi_processor *pr)
> {
> int result = 0;
> struct pci_dev *dev = NULL;
> @@ -378,7 +378,7 @@ static int acpi_processor_get_info(struct acpi_device *device)
> return 0;
> }
>
> -static DEFINE_PER_CPU(void *, processor_device_array);
> +DEFINE_PER_CPU(void *, processor_device_array);
>
> void acpi_processor_notify(struct acpi_device *device, u32 event)
> {
> diff --git a/drivers/acpi/processor_xen.c b/drivers/acpi/processor_xen.c
> index 38a1c05..3af1f73 100644
> --- a/drivers/acpi/processor_xen.c
> +++ b/drivers/acpi/processor_xen.c
> @@ -24,6 +24,7 @@
> #define PREFIX "ACPI: "
>
> #define ACPI_PROCESSOR_CLASS "processor"
> +#define ACPI_PROCESSOR_DEVICE_NAME "Processor"
> #define ACPI_PROCESSOR_NOTIFY_PERFORMANCE 0x80
> #define ACPI_PROCESSOR_NOTIFY_POWER 0x81
> #define ACPI_PROCESSOR_NOTIFY_THROTTLING 0x82
> @@ -88,6 +89,8 @@ xen_acpi_processor_hotadd_init(struct acpi_processor *pr, int *p_cpu)
> PROCESSOR_HOTPLUG, HOTPLUG_TYPE_ADD))
> return AE_ERROR;
>
> + *p_cpu = xen_pcpu_index(pr->acpi_id, 1);
> +
> return AE_OK;
> }
>
> @@ -149,13 +152,248 @@ err_out:
> }
> #endif /* CONFIG_CPU_FREQ */
>
> +static int xen_acpi_processor_get_info(struct acpi_device *device)
> +{
> + acpi_status status = 0;
> + union acpi_object object = { 0 };
> + struct acpi_buffer buffer = { sizeof(union acpi_object), &object };
> + struct acpi_processor *pr;
> + int cpu_index, device_declaration = 0;
> + static int cpu0_initialized;
> +
> + pr = acpi_driver_data(device);
> + if (!pr)
> + return -EINVAL;
> +
> + if (num_online_cpus() > 1)
> + errata.smp = TRUE;
> +
> + acpi_processor_errata(pr);
> +
> + /*
> + * Check to see if we have bus mastering arbitration control. This
> + * is required for proper C3 usage (to maintain cache coherency).
> + */
> + if (acpi_gbl_FADT.pm2_control_block && acpi_gbl_FADT.pm2_control_length) {
> + pr->flags.bm_control = 1;
> + ACPI_DEBUG_PRINT((ACPI_DB_INFO,
> + "Bus mastering arbitration control present\n"));
> + } else
> + ACPI_DEBUG_PRINT((ACPI_DB_INFO,
> + "No bus mastering arbitration control\n"));
> +
> + if (!strcmp(acpi_device_hid(device), ACPI_PROCESSOR_OBJECT_HID)) {
> + /* Declared with "Processor" statement; match ProcessorID */
> + status = acpi_evaluate_object(pr->handle, NULL, NULL, &buffer);
> + if (ACPI_FAILURE(status)) {
> + printk(KERN_ERR PREFIX "Evaluating processor object\n");
> + return -ENODEV;
> + }
> +
> + /*
> + * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP.
> + * >>> 'acpi_get_processor_id(acpi_id, &id)' in
> + * arch/xxx/acpi.c
> + */
> + pr->acpi_id = object.processor.proc_id;
> + } else {
> + /*
> + * Declared with "Device" statement; match _UID.
> + * Note that we don't handle string _UIDs yet.
> + */
> + unsigned long long value;
> + status = acpi_evaluate_integer(pr->handle, METHOD_NAME__UID,
> + NULL, &value);
> + if (ACPI_FAILURE(status)) {
> + printk(KERN_ERR PREFIX
> + "Evaluating processor _UID [%#x]\n", status);
> + return -ENODEV;
> + }
> + device_declaration = 1;
> + pr->acpi_id = value;
> + }
> +
> + cpu_index = xen_pcpu_index(pr->acpi_id, 1);
> +
> + /* Handle UP system running SMP kernel, with no LAPIC in MADT */
> + if (!cpu0_initialized && (cpu_index == -1) &&
> + (num_online_cpus() == 1)) {
> + cpu_index = 0;
> + }
> +
> + cpu0_initialized = 1;
> +
> + pr->id = cpu_index;
> +
> + /*
> + * Extra Processor objects may be enumerated on MP systems with
> + * less than the max # of CPUs. They should be ignored _iff
> + * they are physically not present.
> + */
> + if (pr->id == -1) {
> + if (ACPI_FAILURE
> + (xen_acpi_processor_hotadd_init(pr, &pr->id))) {
> + return -ENODEV;
> + }
> + }
> + /*
> + * On some boxes several processors use the same processor bus id.
> + * But they are located in different scope. For example:
> + * \_SB.SCK0.CPU0
> + * \_SB.SCK1.CPU0
> + * Rename the processor device bus id. And the new bus id will be
> + * generated as the following format:
> + * CPU+CPU ID.
> + */
> + sprintf(acpi_device_bid(device), "CPU%X", pr->id);
> + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d:%d]\n", pr->id,
> + pr->acpi_id));
> +
> + if (!object.processor.pblk_address)
> + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No PBLK (NULL address)\n"));
> + else if (object.processor.pblk_length != 6)
> + printk(KERN_ERR PREFIX "Invalid PBLK length [%d]\n",
> + object.processor.pblk_length);
> + else {
> + pr->throttling.address = object.processor.pblk_address;
> + pr->throttling.duty_offset = acpi_gbl_FADT.duty_offset;
> + pr->throttling.duty_width = acpi_gbl_FADT.duty_width;
> +
> + pr->pblk = object.processor.pblk_address;
> +
> + /*
> + * We don't care about error returns - we just try to mark
> + * these reserved so that nobody else is confused into thinking
> + * that this region might be unused..
> + *
> + * (In particular, allocating the IO range for Cardbus)
> + */
> + request_region(pr->throttling.address, 6, "ACPI CPU throttle");
> + }
> +
> + /*
> + * If ACPI describes a slot number for this CPU, we can use it
> + * ensure we get the right value in the "physical id" field
> + * of /proc/cpuinfo
> + */
> + status = acpi_evaluate_object(pr->handle, "_SUN", NULL, &buffer);
> + if (ACPI_SUCCESS(status))
> + arch_fix_phys_package_id(pr->id, object.integer.value);
> +
> + return 0;
> +}
> +
> +static int __cpuinit __xen_acpi_processor_add(struct acpi_device *device)
> +{
> + struct acpi_processor *pr = NULL;
> + int result = 0;
> + struct sys_device *sysdev;
> +
> + pr = kzalloc(sizeof(struct acpi_processor), GFP_KERNEL);
> + if (!pr)
> + return -ENOMEM;
> +
> + if (!zalloc_cpumask_var(&pr->throttling.shared_cpu_map, GFP_KERNEL)) {
> + kfree(pr);
> + return -ENOMEM;
> + }
> +
> + pr->handle = device->handle;
> + strcpy(acpi_device_name(device), ACPI_PROCESSOR_DEVICE_NAME);
> + strcpy(acpi_device_class(device), ACPI_PROCESSOR_CLASS);
> + device->driver_data = pr;
> +
> + result = xen_acpi_processor_get_info(device);
> + if (result) {
> + /* Processor is physically not present */
> + return 0;
> + }
> +
> +#ifdef CONFIG_SMP
> + if (pr->id >= setup_max_cpus && pr->id != 0)
> + return 0;
> +#endif
> +
> + BUG_ON((pr->id >= nr_cpu_ids) || (pr->id < 0));
> +
> + /*
> + * Buggy BIOS check
> + * ACPI id of processors can be reported wrongly by the BIOS.
> + * Don't trust it blindly
> + */
> + if (per_cpu(processor_device_array, pr->id) != NULL &&
> + per_cpu(processor_device_array, pr->id) != device) {
> + printk(KERN_WARNING "BIOS reported wrong ACPI id "
> + "for the processor\n");
> + result = -ENODEV;
> + goto err_free_cpumask;
> + }
> + per_cpu(processor_device_array, pr->id) = device;
> +
> + per_cpu(processors, pr->id) = pr;
> +
> + sysdev = get_cpu_sysdev(pr->id);
> + if (sysfs_create_link(&device->dev.kobj, &sysdev->kobj, "sysdev")) {
> + result = -EFAULT;
> + goto err_free_cpumask;
> + }
> +
> +#ifdef CONFIG_CPU_FREQ
> + acpi_processor_ppc_has_changed(pr, 0);
> +#endif
> + acpi_processor_get_throttling_info(pr);
> + acpi_processor_get_limit_info(pr);
> +
> +
> + if (cpuidle_get_driver() == &acpi_idle_driver)
> + acpi_processor_power_init(pr, device);
> +
> + pr->cdev = thermal_cooling_device_register("Processor", device,
> + &processor_cooling_ops);
> + if (IS_ERR(pr->cdev)) {
> + result = PTR_ERR(pr->cdev);
> + goto err_power_exit;
> + }
> +
> + dev_dbg(&device->dev, "registered as cooling_device%d\n",
> + pr->cdev->id);
> +
> + result = sysfs_create_link(&device->dev.kobj,
> + &pr->cdev->device.kobj,
> + "thermal_cooling");
> + if (result) {
> + printk(KERN_ERR PREFIX "Create sysfs link\n");
> + goto err_thermal_unregister;
> + }
> + result = sysfs_create_link(&pr->cdev->device.kobj,
> + &device->dev.kobj,
> + "device");
> + if (result) {
> + printk(KERN_ERR PREFIX "Create sysfs link\n");
> + goto err_remove_sysfs;
> + }
> +
> + return 0;
> +
> +err_remove_sysfs:
> + sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
> +err_thermal_unregister:
> + thermal_cooling_device_unregister(pr->cdev);
> +err_power_exit:
> + acpi_processor_power_exit(pr, device);
> +err_free_cpumask:
> + free_cpumask_var(pr->throttling.shared_cpu_map);
> +
> + return result;
> +}
> +
> static int __cpuinit xen_acpi_processor_add(struct acpi_device *device)
> {
> struct acpi_processor *pr = NULL;
> int result = 0;
>
> - result = acpi_processor_add(device);
> - if (result < 0)
> + result = __xen_acpi_processor_add(device);
> + if (result)
> return result;
>
> pr = acpi_driver_data(device);
> diff --git a/include/acpi/processor.h b/include/acpi/processor.h
> index c48e2f9..3a1ee01 100644
> --- a/include/acpi/processor.h
> +++ b/include/acpi/processor.h
> @@ -225,6 +225,8 @@ struct acpi_processor_errata {
> } piix4;
> };
>
> +extern int acpi_processor_errata(struct acpi_processor *pr);
> +
> extern int acpi_processor_preregister_performance(struct
> acpi_processor_performance
> __percpu *performance);
> diff --git a/include/xen/pcpu.h b/include/xen/pcpu.h
> index 7e8f9d1..3e99db9 100644
> --- a/include/xen/pcpu.h
> +++ b/include/xen/pcpu.h
> @@ -4,6 +4,8 @@
> #include <xen/interface/platform.h>
> #include <linux/sysdev.h>
>
> +extern DEFINE_PER_CPU(void *, processor_device_array);
> +
> extern int xen_pcpu_hotplug(int type, uint32_t apic_id);
> #define XEN_PCPU_ONLINE 0x01
> #define XEN_PCPU_OFFLINE 0x02
> --
> 1.6.5.6
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2012-10-03 13:31 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-12-22 10:08 [PATCH 08/10] xen/acpi: add cpu hotadd support Liu, Jinsong
2012-10-03 13:31 ` Konrad Rzeszutek Wilk
-- strict thread matches above, loose matches on Subject: below --
2011-12-23 10:30 Liu, Jinsong
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.