[PATCH 2/2] pseries/hotplug-cpu: Add sysfs attribute for cede_offline

Gautham R. Shenoy
2019-09-12T10:36:10Z

From: "Gautham R. Shenoy" <ego@linux.vnet.ibm.com>

Define a new sysfs attribute
"/sys/device/system/cpu/cede_offline_enabled" on PSeries Linux guests
to allow userspace programs to change the state into which the
offlined CPU need to be put to at runtime. This is intended for
userspace programs that fold CPUs for the purpose of saving energy
when the utilization is low.

Setting the value of this attribute ensures that subsequent CPU
offline operations will put the offlined CPUs to extended
cede. However, it will cause inconsistencies in the PURR accounting.

Clearing the attribute will make the offlined CPUs call the RTAS
"stop-self" call thereby returning the CPU to the hypervisor.

Signed-off-by: Gautham R. Shenoy <ego@linux.vnet.ibm.com>
---
Documentation/ABI/testing/sysfs-devices-system-cpu | 14 +++++
arch/powerpc/platforms/pseries/hotplug-cpu.c | 68 ++++++++++++++++++++--
2 files changed, 76 insertions(+), 6 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-devices-system-cpu b/Documentation/ABI/testing/sysfs-devices-system-cpu
index 06d0931..b3c52cd 100644
--- a/Documentation/ABI/testing/sysfs-devices-system-cpu
+++ b/Documentation/ABI/testing/sysfs-devices-system-cpu
@@ -572,3 +572,17 @@ Description: Secure Virtual Machine
If 1, it means the system is using the Protected Execution
Facility in POWER9 and newer processors. i.e., it is a Secure
Virtual Machine.
+
+What: /sys/devices/system/cpu/cede_offline_enabled
+Date: August 2019
+Contact: Linux kernel mailing list <linux-kernel@vger.kernel.org>
+ Linux for PowerPC mailing list <linuxppc-dev@ozlabs.org>
+Description: Offline CPU state control
+
+ If 1, it means that offline CPUs on PSeries guests
+ will be made to call an extended CEDE which provides
+ energy savings but at the expense of accuracy of PURR
+ accounting. If 0, the offline CPUs on PSeries guests
+ will be made to call RTAS "stop-self" call which will
+ return the CPUs to the Hypervisor and provide accurate
+ values of PURR. The value is 0 by default.
diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c
index f9d0366..4a04cf7 100644
--- a/arch/powerpc/platforms/pseries/hotplug-cpu.c
+++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c
@@ -943,9 +943,64 @@ static int parse_cede_parameters(void)
CEDE_LATENCY_PARAM_MAX_LENGTH);
}

-static int __init pseries_cpu_hotplug_init(void)
+/*
+ * Must be guarded by
+ * cpu_maps_update_begin()...cpu_maps_update_done()
+ */
+static void update_default_offline_state(void)
{
int cpu;
+
+ if (cede_offline_enabled)
+ default_offline_state = CPU_STATE_INACTIVE;
+ else
+ default_offline_state = CPU_STATE_OFFLINE;
+
+ for_each_possible_cpu(cpu)
+ set_default_offline_state(cpu);
+}
+
+static ssize_t show_cede_offline_enabled(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ unsigned long ret = 0;
+
+ if (cede_offline_enabled)
+ ret = 1;
+
+ return sprintf(buf, "%lx\n", ret);
+}
+
+static ssize_t store_cede_offline_enabled(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ bool val;
+ int ret = 0;
+
+ ret = kstrtobool(buf, &val);
+ if (ret)
+ return -EINVAL;
+
+ cpu_maps_update_begin();
+ /* Check if anything needs to be done */
+ if (val == cede_offline_enabled)
+ goto done;
+ cede_offline_enabled = val;
+ update_default_offline_state();
+done:
+ cpu_maps_update_done();
+
+ return count;
+}
+
+static DEVICE_ATTR(cede_offline_enabled, 0600,
+ show_cede_offline_enabled,
+ store_cede_offline_enabled);
+
+static int __init pseries_cpu_hotplug_init(void)
+{
int qcss_tok;

#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
@@ -971,11 +1026,12 @@ static int __init pseries_cpu_hotplug_init(void)
if (firmware_has_feature(FW_FEATURE_LPAR)) {
of_reconfig_notifier_register(&pseries_smp_nb);
cpu_maps_update_begin();
- if (cede_offline_enabled && parse_cede_parameters() == 0) {
- default_offline_state = CPU_STATE_INACTIVE;
- for_each_online_cpu(cpu)
- set_default_offline_state(cpu);
- }
+ if (parse_cede_parameters() == 0)
+ device_create_file(cpu_subsys.dev_root,
+ &dev_attr_cede_offline_enabled);
+ else /* Extended cede is not supported */
+ cede_offline_enabled = false;
+ update_default_offline_state();
cpu_maps_update_done();
}

--
1.9.4