summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMete Durlu <meted@linux.ibm.com>2024-08-12 13:39:37 +0200
committerVasily Gorbik <gor@linux.ibm.com>2024-08-29 22:56:35 +0200
commitb9271a533433dd4049723d4668418709e1927e12 (patch)
tree4660459f8943dccb96a61b5055b6b93fe1c5a3ff
parent1e5aa12d470b1af613fca89a3069529fa9c92cfb (diff)
downloadlwn-b9271a533433dd4049723d4668418709e1927e12.tar.gz
lwn-b9271a533433dd4049723d4668418709e1927e12.zip
s390/hiperdispatch: Add hiperdispatch sysctl interface
Expose hiperdispatch controls via sysctl. The user can now toggle hiperdispatch via assigning 0 or 1 to s390.hiperdispatch attribute. When hiperdipatch is toggled on, it tries to adjust CPU capacities, while system is in vertical polarization to gain performance benefits from different CPU polarizations. Disabling hiperdispatch reverts the CPU capacities to their default (HIGH_CAPACITY) and stops the dynamic adjustments. Introduce a kconfig option HIPERDISPATCH_ON which allows users to use hiperdispatch by default on vertical polarization. Using the sysctl attribute s390.hiperdispatch would overwrite this behavior. Acked-by: Vasily Gorbik <gor@linux.ibm.com> Signed-off-by: Mete Durlu <meted@linux.ibm.com> Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
-rw-r--r--arch/s390/Kconfig12
-rw-r--r--arch/s390/kernel/hiperdispatch.c60
2 files changed, 72 insertions, 0 deletions
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 2ee634bab222..bc2aab60c1c8 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -521,6 +521,18 @@ config SCHED_TOPOLOGY_VERTICAL
Use vertical CPU polarization by default if available.
The default CPU polarization is horizontal.
+config HIPERDISPATCH_ON
+ def_bool y
+ bool "Use hiperdispatch on vertical polarization by default"
+ depends on SCHED_TOPOLOGY
+ depends on PROC_SYSCTL
+ help
+ Hiperdispatch aims to improve the CPU scheduler's decision
+ making when using vertical polarization by adjusting CPU
+ capacities dynamically. Set this option to use hiperdispatch
+ on vertical polarization by default. This can be overwritten
+ by sysctl's s390.hiperdispatch attribute later on.
+
source "kernel/Kconfig.hz"
config CERT_STORE
diff --git a/arch/s390/kernel/hiperdispatch.c b/arch/s390/kernel/hiperdispatch.c
index 3ba7a3492924..8ff4adab7402 100644
--- a/arch/s390/kernel/hiperdispatch.c
+++ b/arch/s390/kernel/hiperdispatch.c
@@ -48,8 +48,10 @@
#include <linux/cpumask.h>
#include <linux/kernel_stat.h>
#include <linux/ktime.h>
+#include <linux/sysctl.h>
#include <linux/workqueue.h>
#include <asm/hiperdispatch.h>
+#include <asm/setup.h>
#include <asm/smp.h>
#include <asm/topology.h>
@@ -69,9 +71,21 @@ static int hd_online_cores; /* Current online CORE count */
static unsigned long hd_previous_steal; /* Previous iteration's CPU steal timer total */
+static int hd_enabled;
+
static void hd_capacity_work_fn(struct work_struct *work);
static DECLARE_DELAYED_WORK(hd_capacity_work, hd_capacity_work_fn);
+static int hd_set_hiperdispatch_mode(int enable)
+{
+ if (!MACHINE_HAS_TOPOLOGY)
+ enable = 0;
+ if (hd_enabled == enable)
+ return 0;
+ hd_enabled = enable;
+ return 1;
+}
+
void hd_reset_state(void)
{
cpumask_clear(&hd_vl_coremask);
@@ -131,6 +145,8 @@ void hd_disable_hiperdispatch(void)
int hd_enable_hiperdispatch(void)
{
+ if (hd_enabled == 0)
+ return 0;
if (hd_entitled_cores == 0)
return 0;
if (hd_online_cores <= hd_entitled_cores)
@@ -211,3 +227,47 @@ static void hd_capacity_work_fn(struct work_struct *work)
mutex_unlock(&smp_cpu_state_mutex);
schedule_delayed_work(&hd_capacity_work, HD_DELAY_INTERVAL);
}
+
+static int hiperdispatch_ctl_handler(const struct ctl_table *ctl, int write,
+ void *buffer, size_t *lenp, loff_t *ppos)
+{
+ int hiperdispatch;
+ int rc;
+ struct ctl_table ctl_entry = {
+ .procname = ctl->procname,
+ .data = &hiperdispatch,
+ .maxlen = sizeof(int),
+ .extra1 = SYSCTL_ZERO,
+ .extra2 = SYSCTL_ONE,
+ };
+
+ hiperdispatch = hd_enabled;
+ rc = proc_douintvec_minmax(&ctl_entry, write, buffer, lenp, ppos);
+ if (rc < 0 || !write)
+ return rc;
+ mutex_lock(&smp_cpu_state_mutex);
+ if (hd_set_hiperdispatch_mode(hiperdispatch))
+ topology_schedule_update();
+ mutex_unlock(&smp_cpu_state_mutex);
+ return 0;
+}
+
+static struct ctl_table hiperdispatch_ctl_table[] = {
+ {
+ .procname = "hiperdispatch",
+ .mode = 0644,
+ .proc_handler = hiperdispatch_ctl_handler,
+ },
+};
+
+static int __init hd_init(void)
+{
+ if (IS_ENABLED(CONFIG_HIPERDISPATCH_ON)) {
+ hd_set_hiperdispatch_mode(1);
+ topology_schedule_update();
+ }
+ if (!register_sysctl("s390", hiperdispatch_ctl_table))
+ pr_warn("Failed to register s390.hiperdispatch sysctl attribute\n");
+ return 0;
+}
+late_initcall(hd_init);