Unverified Commit 1cd6a0f2 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!13340 cpufreq: Add SEEP governor for hardware-managed P-states

Merge Pull Request from: @heppen 
 
1. Add sysfs interfaces for CPPC auto_act_window and energy_perf in the cppc_cpufreq driver.
2. cpufreq: Add SEEP governor for hardware-managed P-states 
 
Link:https://gitee.com/openeuler/kernel/pulls/13340

 

Reviewed-by: default avatarLuo Shengwei <luoshengwei@huawei.com>
Reviewed-by: default avatarXiongfeng Wang <wangxiongfeng2@huawei.com>
Signed-off-by: default avatarZhang Peng <zhangpeng362@huawei.com>
parents e1ace816 0cdbb920
Loading
Loading
Loading
Loading
+39 −0
Original line number Diff line number Diff line
@@ -268,6 +268,45 @@ Description: Discover CPUs in the same CPU frequency coordination domain
		This file is only present if the acpi-cpufreq or the cppc-cpufreq
		drivers are in use.

What:		/sys/devices/system/cpu/cpuX/cpufreq/auto_act_window
Date:		October 2024
Contact:	linux-pm@vger.kernel.org
Description:	Autonomous activity window

		This file indicates a moving utilization sensitivity window to
		the platform's autonomous selection policy.

		Read/write an integer represents autonomous activity window (in
		microseconds) from/to this file. The max value to write is
		1270000000 but the max significand is 127. This means that if 128
		is written to this file, 127 will be stored. If the value is
		greater than 130, only the first two digits will be saved as
		significand.

		Writing a zero value to this file enable the platform to
		determine an appropriate Activity Window depending on the workload.

		Writing to this file only has meaning when Autonomous Selection is
		enabled.

		This file only presents if the cppc-cpufreq driver is in use.

What:		/sys/devices/system/cpu/cpuX/cpufreq/energy_perf
Date:		October 2024
Contact:	linux-pm@vger.kernel.org
Description:	Energy performance preference

		Read/write an 8-bit integer from/to this file. This file
		represents a range of values from 0 (performance preference) to
		0xFF (energy efficiency preference) that influences the rate of
		performance increase/decrease and the result of the hardware's
		energy efficiency and performance optimization policies.

		Writing to this file only has meaning when Autonomous Selection is
		enabled.

		This file only presents if the cppc-cpufreq driver is in use.


What:		/sys/devices/system/cpu/cpu*/cache/index3/cache_disable_{0,1}
Date:		August 2008
+42 −0
Original line number Diff line number Diff line
@@ -590,6 +590,48 @@ This governor exposes the following tunables:
	It effectively causes the frequency to go down ``sampling_down_factor``
	times slower than it ramps up.

``seep``
------------

This governor is specifically designed for platforms with hardware-managed P-states
through CPPC (Collaborative Processor Performance Control). Unlike other governors
that implement their own frequency scaling algorithms, the ``seep`` governor
delegates the P-state selection to the hardware/firmware by enabling CPPC
autonomous mode.

The governor requires the ``cppc_cpufreq`` driver and the platform must support
three key CPPC capabilities:
 * Autonomous selection (auto_sel)
 * Autonomous activity window (auto_act_window)
 * Energy-Performance Preference (EPP)

When this governor is attached to a policy, it enables the hardware autonomous
mode, allowing the processor's firmware to directly manage frequency scaling based
on workload characteristics. The actual P-state selection algorithms are
implemented in firmware/hardware rather than in the operating system.

This governor exposes the following tunables (per-policy):

``auto_act_window``
	The time window (in microseconds) used by the hardware/firmware to observe
	and evaluate workload characteristics before making P-state decisions.
	A smaller window makes the algorithm more responsive but potentially less
	stable, while a larger window provides more stable but less responsive
	frequency scaling.

``energy_perf``
	A value between 0 and 255 that biases the hardware's frequency scaling
	decisions between performance and energy efficiency. Lower values (closer
	to 0) favor performance at the expense of power consumption, while higher
	values (closer to 255) favor energy efficiency but may impact performance.

The ``seep`` governor is particularly suitable for platforms where the hardware
has more accurate and fine-grained information about the system's power and
thermal constraints than the operating system. It can potentially provide better
energy efficiency than software-based governors while maintaining good
performance, as the hardware can make faster and more informed P-state
decisions.


Frequency Boost Support
=======================
+1 −0
Original line number Diff line number Diff line
@@ -669,6 +669,7 @@ CONFIG_CPU_FREQ_GOV_USERSPACE=y
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y
CONFIG_CPU_FREQ_GOV_SEEP=m

#
# CPU frequency scaling drivers
+147 −5
Original line number Diff line number Diff line
@@ -1142,7 +1142,6 @@ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val)
			return -EFAULT;
		}
		val = MASK_VAL_WRITE(reg, prev_val, val);
		val |= prev_val;
	}

	switch (size) {
@@ -1210,6 +1209,11 @@ static int cppc_get_perf(int cpunum, enum cppc_regs reg_idx, u64 *perf)
		return ret;
	}

	if (!CPC_SUPPORTED(reg)) {
		pr_debug("CPC register %d is not supported\n", reg_idx);
		return -EOPNOTSUPP;
	}

	cpc_read(cpunum, reg, perf);

	return 0;
@@ -1535,6 +1539,139 @@ int cppc_set_epp_perf(int cpu, struct cppc_perf_ctrls *perf_ctrls, bool enable)
}
EXPORT_SYMBOL_GPL(cppc_set_epp_perf);

static int cppc_get_reg(int cpunum, enum cppc_regs reg_idx, u64 *val)
{
	struct cpc_desc *cpc_desc = per_cpu(cpc_desc_ptr, cpunum);
	struct cppc_pcc_data *pcc_ss_data = NULL;
	struct cpc_register_resource *reg;
	int pcc_ss_id;
	int ret = 0;

	if (!cpc_desc) {
		pr_debug("No CPC descriptor for CPU:%d\n", cpunum);
		return -ENODEV;
	}

	reg = &cpc_desc->cpc_regs[reg_idx];

	if (!CPC_SUPPORTED(reg)) {
		pr_debug("CPC register (reg_idx=%u) is not supported\n", reg_idx);
		return -EOPNOTSUPP;
	}

	if (CPC_IN_PCC(reg)) {
		pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpunum);

		if (pcc_ss_id < 0)
			return -ENODEV;

		pcc_ss_data = pcc_data[pcc_ss_id];

		down_write(&pcc_ss_data->pcc_lock);

		if (send_pcc_cmd(pcc_ss_id, CMD_READ) >= 0)
			cpc_read(cpunum, reg, val);
		else
			ret = -EIO;

		up_write(&pcc_ss_data->pcc_lock);

		return ret;
	}

	cpc_read(cpunum, reg, val);

	return 0;
}

static int cppc_set_reg(int cpu, enum cppc_regs reg_idx, u64 val)
{
	struct cpc_desc *cpc_desc = per_cpu(cpc_desc_ptr, cpu);
	struct cppc_pcc_data *pcc_ss_data = NULL;
	struct cpc_register_resource *reg;
	int pcc_ss_id;
	int ret;

	if (!cpc_desc) {
		pr_debug("No CPC descriptor for CPU:%d\n", cpu);
		return -ENODEV;
	}

	reg = &cpc_desc->cpc_regs[reg_idx];

	if (!CPC_SUPPORTED(reg)) {
		pr_debug("CPC register (reg_idx=%u) is not supported\n", reg_idx);
		return -EOPNOTSUPP;
	}

	if (CPC_IN_PCC(reg)) {
		pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpu);

		if (pcc_ss_id < 0) {
			pr_debug("Invalid pcc_ss_id\n");
			return -ENODEV;
		}

		ret = cpc_write(cpu, reg, val);
		if (ret)
			return ret;

		pcc_ss_data = pcc_data[pcc_ss_id];

		down_write(&pcc_ss_data->pcc_lock);
		/* after writing CPC, transfer the ownership of PCC to platform */
		ret = send_pcc_cmd(pcc_ss_id, CMD_WRITE);
		up_write(&pcc_ss_data->pcc_lock);
		return ret;
	}

	return cpc_write(cpu, reg, val);
}

/**
 * cppc_set_epp() - Write the EPP register
 * @cpu:CPU on which to write register.
 * @epp_val:Value to write to the EPP register.
*/
int cppc_set_epp(int cpu, u64 epp_val)
{
	return cppc_set_reg(cpu, ENERGY_PERF, epp_val);
}
EXPORT_SYMBOL_GPL(cppc_set_epp);

/**
 * cppc_get_auto_act_window() - Read autonomous activity window register.
 * @cpunum:CPU from which to read register.
 * @auto_act_window:Return address.
*/
int cppc_get_auto_act_window(int cpunum, u64 *auto_act_window)
{
	return cppc_get_reg(cpunum, AUTO_ACT_WINDOW, auto_act_window);
}
EXPORT_SYMBOL_GPL(cppc_get_auto_act_window);

/**
 * cppc_set_auto_act_window() - Write autonomous activity window register.
 * @cpu:CPU on which to write register.
 * @auto_act_window:Value to write to the autonomous activity window register.
*/
int cppc_set_auto_act_window(int cpu, u64 auto_act_window)
{
	return cppc_set_reg(cpu, AUTO_ACT_WINDOW, auto_act_window);
}
EXPORT_SYMBOL_GPL(cppc_set_auto_act_window);

/**
 * cppc_get_auto_sel() - Read autonomous selection register.
 * @cpunum:CPU from which to read register.
 * @auto_act_window:Return address.
*/
int cppc_get_auto_sel(int cpunum, u64 *auto_sel)
{
	return cppc_get_reg(cpunum, AUTO_SEL_ENABLE, auto_sel);
}
EXPORT_SYMBOL_GPL(cppc_get_auto_sel);

/**
 * cppc_get_auto_sel_caps - Read autonomous selection register.
 * @cpunum : CPU from which to read register.
@@ -1622,13 +1759,18 @@ int cppc_set_auto_sel(int cpu, bool enable)
		/* after writing CPC, transfer the ownership of PCC to platform */
		ret = send_pcc_cmd(pcc_ss_id, CMD_WRITE);
		up_write(&pcc_ss_data->pcc_lock);
	} else {
		ret = -ENOTSUPP;
		pr_debug("_CPC in PCC is not supported\n");
	}

		return ret;
	}

	if (!CPC_SUPPORTED(auto_sel_reg)) {
		pr_debug("CPC register (reg_idx=%u) is not supported\n",
			 AUTO_SEL_ENABLE);
		return -EOPNOTSUPP;
	}

	return cpc_write(cpu, auto_sel_reg, enable);
}
EXPORT_SYMBOL_GPL(cppc_set_auto_sel);

/**
+20 −0
Original line number Diff line number Diff line
@@ -203,6 +203,26 @@ config CPU_FREQ_GOV_SCHEDUTIL

	  If in doubt, say N.

config CPU_FREQ_GOV_SEEP
	tristate "'seep' cpufreq policy governor"
	depends on ACPI_CPPC_CPUFREQ && ARM64
	select CPPC_CPUFREQ_SYSFS_INTERFACE
	select CPU_FREQ_GOV_COMMON
	help
	  'seep' - This governor is designed for platforms with hardware-managed
	  P-states through CPPC (Collaborative Processor Performance Control).
	  It enables the hardware's autonomous frequency selection capability,
	  allowing the processor to manage its own frequency based on workload.

	  This governor requires the cppc_cpufreq driver and platform support
	  for CPPC features including auto-selection, autonomous activity window,
	  and energy-performance preference.

	  To compile this driver as a module, choose M here: the
	  module will be called cpufreq_seep.

	  If in doubt, say N.

comment "CPU frequency scaling drivers"

config CPUFREQ_DT
Loading