Hi all:
AMD P-State unit test(amd_pstate_testmod) is a kernel module for testing
the functions of amd-pstate driver.
It could import as a module to launch some test tasks.
1) It can help all users to verify their processor support (SBIOS/Firmware
or Hardware).
2) Kernel can have a basic function test to avoid the kernel regression
during the update.
3) We can introduce more functional or performance tests to align the
together, it will benefit power and performance scale optimization.
We upstream out AMD P-state driver into Linux kernel and use this unit
test module to verify the required conditions and basic functions of
amd-pstate before integration test.
We use test module in the kselftest frameworks to implement it.
We create amd_pstate_testmod module and tie it into kselftest.
For example: The test case aput_acpi_cpc is used to check whether the
_CPC object is exist in SBIOS.
The amd-pstate initialization will fail if the _CPC in ACPI SBIOS is not
existed at the detected processor, so it is a necessary condition.
At present, it only implements the basic framework and some simple test
cases.
TODO : 1) we will add a rst document.
2) we will add more test cases to improve the depth and coverage of
the test.
See patch series in below git repo:
V1: https://lore.kernel.org/linux-pm/[email protected]/
V2: https://lore.kernel.org/lkml/[email protected]/
Changes from V1 -> V2:
- cpufreq: amd-pstate:
- - add a trailing of amd-pstate.h to MAINTAINER AMD PSTATE DRIVER.
- selftests: cpufreq:
- - add a wrapper shell script for the amd_pstate_testmod module.
- selftests: cpufreq:
- - remove amd_pstate_testmod kernel module to .../cpufreq/amd_pstate_testmod.
- Documentation: amd-pstate:
- - amd_pstate_testmod rst document is not provided at present.
Changes from V2 -> V3:
- cpufreq: amd-pstate:
- - adjust the order of add amd-pstate.h in MAINTAINERS.
- selftests: cpufreq:
- - remove the call of amd_pstate_testmod.sh from cpufreq Makefile to main.sh.
- selftests: cpufreq:
- - add explain the goal or intention of the AMD P-State Unit Test module.
- - modify comments.
- - use the checkpatch.pl to check my patches.
- - add conditions judgment before formal test.
- - delete some unnecessary test cases.
- - modify test cases about perf and performance etc.
Thanks,
Jasmine
Meng Li (3):
cpufreq: amd-pstate: Expose struct amd_cpudata
selftests: cpufreq: Add wapper script for test AMD P-State
selftests: cpufreq: Add amd_pstate_testmod kernel module for testing
MAINTAINERS | 1 +
drivers/cpufreq/amd-pstate.c | 60 +---
include/linux/amd-pstate.h | 77 ++++
.../selftests/cpufreq/amd_pstate_testmod.sh | 4 +
.../cpufreq/amd_pstate_testmod/Makefile | 20 ++
.../amd_pstate_testmod/amd_pstate_testmod.c | 329 ++++++++++++++++++
tools/testing/selftests/cpufreq/config | 1 +
tools/testing/selftests/cpufreq/main.sh | 1 +
8 files changed, 434 insertions(+), 59 deletions(-)
create mode 100644 include/linux/amd-pstate.h
create mode 100755 tools/testing/selftests/cpufreq/amd_pstate_testmod.sh
create mode 100644 tools/testing/selftests/cpufreq/amd_pstate_testmod/Makefile
create mode 100644 tools/testing/selftests/cpufreq/amd_pstate_testmod/amd_pstate_testmod.c
--
2.25.1
Add amd_pstate_testmod module, which is conceptually out-of-tree module
and provides ways for selftests/cpufreq amd pstate driver to test various
kernel module-related functionality. This module will be expected by
some of selftests to be present and loaded.
Signed-off-by: Meng Li <[email protected]>
---
.../cpufreq/amd_pstate_testmod/Makefile | 20 ++
.../amd_pstate_testmod/amd_pstate_testmod.c | 329 ++++++++++++++++++
2 files changed, 349 insertions(+)
create mode 100644 tools/testing/selftests/cpufreq/amd_pstate_testmod/Makefile
create mode 100644 tools/testing/selftests/cpufreq/amd_pstate_testmod/amd_pstate_testmod.c
diff --git a/tools/testing/selftests/cpufreq/amd_pstate_testmod/Makefile b/tools/testing/selftests/cpufreq/amd_pstate_testmod/Makefile
new file mode 100644
index 000000000000..8a5596cb2c18
--- /dev/null
+++ b/tools/testing/selftests/cpufreq/amd_pstate_testmod/Makefile
@@ -0,0 +1,20 @@
+AMD_PSTATE_TESTMOD_DIR := $(realpath $(dir $(abspath $(lastword $(MAKEFILE_LIST)))))
+KDIR ?= $(abspath $(AMD_PSATE_TESTMOD_DIR)/../../../../..)
+
+ifeq ($(V),1)
+Q =
+else
+Q = @
+endif
+
+MODULES = amd_pstate_testmod.ko
+
+obj-m += amd_pstate_testmod.o
+CFLAGS_amd_pstate_testmod.o = -I$(src)
+
+all:
+ +$(Q)make -C $(KDIR) M=$(AMD_PSTATE_TESTMOD_DIR) modules
+
+clean:
+ +$(Q)make -C $(KDIR) M=$(AMD_PSTATE_TESTMOD_DIR) clean
+
diff --git a/tools/testing/selftests/cpufreq/amd_pstate_testmod/amd_pstate_testmod.c b/tools/testing/selftests/cpufreq/amd_pstate_testmod/amd_pstate_testmod.c
new file mode 100644
index 000000000000..5391412a49c4
--- /dev/null
+++ b/tools/testing/selftests/cpufreq/amd_pstate_testmod/amd_pstate_testmod.c
@@ -0,0 +1,329 @@
+// SPDX-License-Identifier: GPL-1.0-or-later
+/*
+ * AMD Processor P-state Frequency Driver Unit Test
+ *
+ * Copyright (C) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
+ *
+ * Author: Meng Li <[email protected]>
+ *
+ * The AMD P-State Unit Test is a test module for testing the amd-pstate
+ * driver. 1) It can help all users to verify their processor support
+ * (SBIOS/Firmware or Hardware). 2) Kernel can have a basic function
+ * test to avoid the kernel regression during the update. 3) We can
+ * introduce more functional or performance tests to align the result
+ * together, it will benefit power and performance scale optimization.
+ *
+ * At present, it only implements the basic framework and some simple
+ * test cases. Next, 1) we will add a rst document. 2) we will add more
+ * test cases to improve the depth and coverage of the test.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "../../kselftest_module.h"
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/fs.h>
+#include <linux/amd-pstate.h>
+
+#include <acpi/cppc_acpi.h>
+
+/*
+ * Abbreviations:
+ * aput: used as a shortform for AMD P-State unit test.
+ * It helps to keep variable names smaller, simpler
+ */
+
+KSTM_MODULE_GLOBALS();
+
+/*
+ * Kernel module for testing the AMD P-State unit test
+ */
+enum aput_result {
+ APUT_RESULT_PASS,
+ APUT_RESULT_FAIL,
+ MAX_APUT_RESULT,
+};
+
+struct aput_struct {
+ const char *name;
+ void (*func)(u32 index);
+ enum aput_result result;
+};
+
+static const char ap_drv[] = "amd-pstate";
+
+static void aput_x86_vendor(u32 index);
+static void aput_modprobed_driver(u32 index);
+static void aput_acpi_cpc(u32 index);
+static void aput_check_enabled(u32 index);
+static void aput_check_perf(u32 index);
+static void aput_check_freq(u32 index);
+
+static struct aput_struct aput_conditions[] = {
+ {"x86_vendor", aput_x86_vendor },
+ {"modprobed_amd_pstate", aput_modprobed_driver },
+};
+
+static struct aput_struct aput_cases[] = {
+ {"acpi_cpc_valid", aput_acpi_cpc },
+ {"check_enabled", aput_check_enabled },
+ {"check_perf", aput_check_perf },
+ {"check_freq", aput_check_freq }
+};
+
+static bool get_shared_mem(void)
+{
+ bool result = false;
+ char buf[5] = {0};
+ struct file *filp = NULL;
+ loff_t pos = 0;
+ ssize_t ret;
+
+ filp = filp_open("/sys/module/amd_pstate/parameters/shared_mem", FMODE_PREAD, 0);
+ if (IS_ERR(filp))
+ pr_err("%s Open param file fail!\n", __func__);
+ else {
+ ret = kernel_read(filp, &buf, sizeof(buf), &pos);
+ if (ret < 0)
+ pr_err("%s ret=%ld unable to read from param file!\n", __func__, ret);
+ filp_close(filp, NULL);
+ }
+
+ if ('Y' == *buf)
+ result = true;
+
+ return result;
+}
+
+static void aput_x86_vendor(u32 index)
+{
+ if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
+ aput_conditions[index].result = APUT_RESULT_PASS;
+ else {
+ aput_conditions[index].result = APUT_RESULT_FAIL;
+ pr_warn("Exit test: the vendor is not X86_VENDOR_AMD!\n");
+ }
+}
+
+static void aput_modprobed_driver(u32 index)
+{
+ const char *cur_drv;
+
+ cur_drv = cpufreq_get_current_driver();
+ if (cur_drv) {
+ if (!strncmp(cur_drv, ap_drv, min_t(size_t, strlen(cur_drv), strlen(ap_drv))))
+ aput_conditions[index].result = APUT_RESULT_PASS;
+ else {
+ aput_conditions[index].result = APUT_RESULT_FAIL;
+ pr_warn("Exit test: current driver %s is not amd-pstate!\n", cur_drv);
+ }
+ } else {
+ aput_conditions[index].result = APUT_RESULT_FAIL;
+ pr_warn("Exit test: this cpu is not supported anymore!\n");
+ }
+}
+
+static void aput_acpi_cpc(u32 index)
+{
+ if (acpi_cpc_valid())
+ aput_cases[index].result = APUT_RESULT_PASS;
+ else
+ aput_cases[index].result = APUT_RESULT_FAIL;
+}
+
+static void aput_pstate_enable(u32 index)
+{
+ int ret = 0;
+ u64 cppc_enable = 0;
+
+ ret = rdmsrl_safe(MSR_AMD_CPPC_ENABLE, &cppc_enable);
+ if (ret) {
+ aput_cases[index].result = APUT_RESULT_FAIL;
+ pr_err("%s rdmsrl_safe MSR_AMD_CPPC_ENABLE ret=%d is error!\n", __func__, ret);
+ return;
+ }
+ if (cppc_enable)
+ aput_cases[index].result = APUT_RESULT_PASS;
+ else
+ aput_cases[index].result = APUT_RESULT_FAIL;
+}
+
+/*
+ *Check if enabled amd pstate
+ */
+static void aput_check_enabled(u32 index)
+{
+ if (get_shared_mem())
+ aput_cases[index].result = APUT_RESULT_PASS;
+ else
+ aput_pstate_enable(index);
+}
+
+/*
+ * Check if the each performance values are reasonable.
+ * highest_perf >= nominal_perf > lowest_nonlinear_perf > lowest_perf > 0
+ */
+static void aput_check_perf(u32 index)
+{
+ int cpu = 0, ret = 0;
+ u32 highest_perf = 0, nominal_perf = 0, lowest_nonlinear_perf = 0, lowest_perf = 0;
+ u64 cap1 = 0;
+ struct cppc_perf_caps cppc_perf;
+ struct cpufreq_policy *policy = NULL;
+ struct amd_cpudata *cpudata = NULL;
+
+ highest_perf = amd_get_highest_perf();
+
+ for_each_possible_cpu(cpu) {
+ policy = cpufreq_cpu_get(cpu);
+ if (!policy)
+ break;
+ cpudata = policy->driver_data;
+
+ if (get_shared_mem()) {
+ ret = cppc_get_perf_caps(cpu, &cppc_perf);
+ if (ret) {
+ aput_cases[index].result = APUT_RESULT_FAIL;
+ pr_err("%s cppc_get_perf_caps ret=%d is error!\n", __func__, ret);
+ return;
+ }
+
+ nominal_perf = cppc_perf.nominal_perf;
+ lowest_nonlinear_perf = cppc_perf.lowest_nonlinear_perf;
+ lowest_perf = cppc_perf.lowest_perf;
+ } else {
+ ret = rdmsrl_safe_on_cpu(cpu, MSR_AMD_CPPC_CAP1, &cap1);
+ if (ret) {
+ aput_cases[index].result = APUT_RESULT_FAIL;
+ pr_err("%s read CPPC_CAP1 ret=%d is error!\n", __func__, ret);
+ return;
+ }
+
+ nominal_perf = AMD_CPPC_NOMINAL_PERF(cap1);
+ lowest_nonlinear_perf = AMD_CPPC_LOWNONLIN_PERF(cap1);
+ lowest_perf = AMD_CPPC_LOWEST_PERF(cap1);
+ }
+
+ if ((highest_perf != READ_ONCE(cpudata->highest_perf)) ||
+ (nominal_perf != READ_ONCE(cpudata->nominal_perf)) ||
+ (lowest_nonlinear_perf != READ_ONCE(cpudata->lowest_nonlinear_perf)) ||
+ (lowest_perf != READ_ONCE(cpudata->lowest_perf))) {
+ aput_cases[index].result = APUT_RESULT_FAIL;
+ pr_err("%s cpu%d highest=%d %d nominal=%d %d lowest_nonlinear=%d %d lowest=%d %d are not equal!\n",
+ __func__, cpu, highest_perf, cpudata->highest_perf,
+ nominal_perf, cpudata->nominal_perf,
+ lowest_nonlinear_perf, cpudata->lowest_nonlinear_perf,
+ lowest_perf, cpudata->lowest_perf);
+ return;
+ }
+
+ if (!((highest_perf >= nominal_perf) &&
+ (nominal_perf > lowest_nonlinear_perf) &&
+ (lowest_nonlinear_perf > lowest_perf) &&
+ (lowest_perf > 0))) {
+ aput_cases[index].result = APUT_RESULT_FAIL;
+ pr_err("%s cpu%d highest=%d nominal=%d lowest_nonlinear=%d lowest=%d have error!\n",
+ __func__, cpu, highest_perf, nominal_perf,
+ lowest_nonlinear_perf, lowest_perf);
+ return;
+ }
+ }
+
+ aput_cases[index].result = APUT_RESULT_PASS;
+}
+
+/*
+ * Check if the each frequency values are reasonable.
+ * max_freq >= nominal_freq > lowest_nonlinear_freq > min_freq > 0
+ * check max freq when set support boost mode.
+ */
+static void aput_check_freq(u32 index)
+{
+ int cpu = 0;
+ struct cpufreq_policy *policy = NULL;
+ struct amd_cpudata *cpudata = NULL;
+
+ for_each_possible_cpu(cpu) {
+ policy = cpufreq_cpu_get(cpu);
+ if (!policy)
+ break;
+ cpudata = policy->driver_data;
+
+ if (!((cpudata->max_freq >= cpudata->nominal_freq) &&
+ (cpudata->nominal_freq > cpudata->lowest_nonlinear_freq) &&
+ (cpudata->lowest_nonlinear_freq > cpudata->min_freq) &&
+ (cpudata->min_freq > 0))) {
+ aput_cases[index].result = APUT_RESULT_FAIL;
+ pr_err("%s cpu%d max=%d nominal=%d lowest_nonlinear=%d min=%d have error!\n",
+ __func__, cpu, cpudata->max_freq, cpudata->nominal_freq,
+ cpudata->lowest_nonlinear_freq, cpudata->min_freq);
+ return;
+ }
+
+ if (cpudata->min_freq != policy->min) {
+ aput_cases[index].result = APUT_RESULT_FAIL;
+ pr_err("%s cpu%d cpudata_min_freq=%d policy_min=%d have error!\n",
+ __func__, cpu, cpudata->min_freq, policy->min);
+ return;
+ }
+
+ if (cpudata->boost_supported) {
+ if ((policy->max == cpudata->max_freq) ||
+ (policy->max == cpudata->nominal_freq))
+ aput_cases[index].result = APUT_RESULT_PASS;
+ else {
+ aput_cases[index].result = APUT_RESULT_FAIL;
+ pr_err("%s cpu%d policy_max=%d cpu_max=%d cpu_nominal=%d have error!\n",
+ __func__, cpu, policy->max, cpudata->max_freq,
+ cpudata->nominal_freq);
+ return;
+ }
+ } else {
+ aput_cases[index].result = APUT_RESULT_FAIL;
+ pr_err("%s cpu%d not support boost!\n", __func__, cpu);
+ return;
+ }
+ }
+}
+
+static bool aput_check_conditions(void)
+{
+ bool result = true;
+ u32 i = 0, arr_size = ARRAY_SIZE(aput_conditions);
+
+ for (i = 0; i < arr_size; i++) {
+ aput_conditions[i].func(i);
+ if (aput_conditions[i].result != APUT_RESULT_PASS) {
+ result = false;
+ break;
+ }
+ }
+
+ return result;
+}
+
+static void aput_do_test_case(void)
+{
+ u32 i = 0, arr_size = ARRAY_SIZE(aput_cases);
+
+ for (i = 0; i < arr_size; i++) {
+ pr_info("****** Begin %-5d\t %-20s\t ******\n", i+1, aput_cases[i].name);
+ aput_cases[i].func(i);
+ KSTM_CHECK_ZERO(aput_cases[i].result);
+ pr_info("****** End %-5d\t %-20s\t ******\n", i+1, aput_cases[i].name);
+ }
+}
+
+static void __init selftest(void)
+{
+ if (aput_check_conditions())
+ aput_do_test_case();
+}
+
+KSTM_MODULE_LOADERS(amd_pstate_testmod);
+MODULE_AUTHOR("Meng Li <[email protected]>");
+MODULE_DESCRIPTION("Unit test for AMD P-state driver");
+MODULE_LICENSE("GPL");
--
2.25.1
Adds a wrapper shell script for the amd_pstate_testmod module.
Signed-off-by: Meng Li <[email protected]>
---
tools/testing/selftests/cpufreq/amd_pstate_testmod.sh | 4 ++++
tools/testing/selftests/cpufreq/config | 1 +
tools/testing/selftests/cpufreq/main.sh | 1 +
3 files changed, 6 insertions(+)
create mode 100755 tools/testing/selftests/cpufreq/amd_pstate_testmod.sh
diff --git a/tools/testing/selftests/cpufreq/amd_pstate_testmod.sh b/tools/testing/selftests/cpufreq/amd_pstate_testmod.sh
new file mode 100755
index 000000000000..5398ad568885
--- /dev/null
+++ b/tools/testing/selftests/cpufreq/amd_pstate_testmod.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+# Tests the AMD P-State unit test infrastructure using amd_pstate_testmod kernel module.
+$(dirname $0)/../kselftest/module.sh "amd_pstate_testmod" amd_pstate_testmod
diff --git a/tools/testing/selftests/cpufreq/config b/tools/testing/selftests/cpufreq/config
index 75e900793e8a..374a8adbb34c 100644
--- a/tools/testing/selftests/cpufreq/config
+++ b/tools/testing/selftests/cpufreq/config
@@ -13,3 +13,4 @@ CONFIG_DEBUG_LOCK_ALLOC=y
CONFIG_PROVE_LOCKING=y
CONFIG_LOCKDEP=y
CONFIG_DEBUG_ATOMIC_SLEEP=y
+CONFIG_AMD_PSTATE_TESTMOD=m
diff --git a/tools/testing/selftests/cpufreq/main.sh b/tools/testing/selftests/cpufreq/main.sh
index 60ce18ed0666..d3602fa11392 100755
--- a/tools/testing/selftests/cpufreq/main.sh
+++ b/tools/testing/selftests/cpufreq/main.sh
@@ -6,6 +6,7 @@ source cpufreq.sh
source governor.sh
source module.sh
source special-tests.sh
+source amd_pstate_testmod.sh
FUNC=basic # do basic tests by default
OUTFILE=cpufreq_selftest
--
2.25.1
Expose struct amd_cpudata to AMD P-State unit test module.
This data struct will be used on the following AMD P-State unit test
(amd_pstate_testmod) module. The amd_pstate_testmod module can get
some AMD infomations by this data struct. For example: highest perf,
nominal perf, boost supported etc.
Signed-off-by: Meng Li <[email protected]>
---
MAINTAINERS | 1 +
drivers/cpufreq/amd-pstate.c | 60 +---------------------------
include/linux/amd-pstate.h | 77 ++++++++++++++++++++++++++++++++++++
3 files changed, 79 insertions(+), 59 deletions(-)
create mode 100644 include/linux/amd-pstate.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 61d9f114c37f..6f814eda95b5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1020,6 +1020,7 @@ L: [email protected]
S: Supported
F: Documentation/admin-guide/pm/amd-pstate.rst
F: drivers/cpufreq/amd-pstate*
+F: include/linux/amd-pstate.h
F: tools/power/x86/amd_pstate_tracer/amd_pstate_trace.py
AMD PTDMA DRIVER
diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
index 7be38bc6a673..5f7a00a64f76 100644
--- a/drivers/cpufreq/amd-pstate.c
+++ b/drivers/cpufreq/amd-pstate.c
@@ -36,6 +36,7 @@
#include <linux/delay.h>
#include <linux/uaccess.h>
#include <linux/static_call.h>
+#include <linux/amd-pstate.h>
#include <acpi/processor.h>
#include <acpi/cppc_acpi.h>
@@ -65,65 +66,6 @@ MODULE_PARM_DESC(shared_mem,
static struct cpufreq_driver amd_pstate_driver;
-/**
- * struct amd_aperf_mperf
- * @aperf: actual performance frequency clock count
- * @mperf: maximum performance frequency clock count
- * @tsc: time stamp counter
- */
-struct amd_aperf_mperf {
- u64 aperf;
- u64 mperf;
- u64 tsc;
-};
-
-/**
- * struct amd_cpudata - private CPU data for AMD P-State
- * @cpu: CPU number
- * @req: constraint request to apply
- * @cppc_req_cached: cached performance request hints
- * @highest_perf: the maximum performance an individual processor may reach,
- * assuming ideal conditions
- * @nominal_perf: the maximum sustained performance level of the processor,
- * assuming ideal operating conditions
- * @lowest_nonlinear_perf: the lowest performance level at which nonlinear power
- * savings are achieved
- * @lowest_perf: the absolute lowest performance level of the processor
- * @max_freq: the frequency that mapped to highest_perf
- * @min_freq: the frequency that mapped to lowest_perf
- * @nominal_freq: the frequency that mapped to nominal_perf
- * @lowest_nonlinear_freq: the frequency that mapped to lowest_nonlinear_perf
- * @cur: Difference of Aperf/Mperf/tsc count between last and current sample
- * @prev: Last Aperf/Mperf/tsc count value read from register
- * @freq: current cpu frequency value
- * @boost_supported: check whether the Processor or SBIOS supports boost mode
- *
- * The amd_cpudata is key private data for each CPU thread in AMD P-State, and
- * represents all the attributes and goals that AMD P-State requests at runtime.
- */
-struct amd_cpudata {
- int cpu;
-
- struct freq_qos_request req[2];
- u64 cppc_req_cached;
-
- u32 highest_perf;
- u32 nominal_perf;
- u32 lowest_nonlinear_perf;
- u32 lowest_perf;
-
- u32 max_freq;
- u32 min_freq;
- u32 nominal_freq;
- u32 lowest_nonlinear_freq;
-
- struct amd_aperf_mperf cur;
- struct amd_aperf_mperf prev;
-
- u64 freq;
- bool boost_supported;
-};
-
static inline int pstate_enable(bool enable)
{
return wrmsrl_safe(MSR_AMD_CPPC_ENABLE, enable);
diff --git a/include/linux/amd-pstate.h b/include/linux/amd-pstate.h
new file mode 100644
index 000000000000..4dffb7db3807
--- /dev/null
+++ b/include/linux/amd-pstate.h
@@ -0,0 +1,77 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * linux/include/linux/amd-pstate.h
+ *
+ * Copyright (C) 2007-2010 Advanced Micro Devices, Inc.
+ *
+ * Author: Meng Li <[email protected]>
+ */
+
+#ifndef _LINUX_AMD_PSTATE_H
+#define _LINUX_AMD_PSTATE_H
+
+#include <linux/pm_qos.h>
+
+/*********************************************************************
+ * AMD P-state INTERFACE *
+ *********************************************************************/
+/**
+ * struct amd_aperf_mperf
+ * @aperf: actual performance frequency clock count
+ * @mperf: maximum performance frequency clock count
+ * @tsc: time stamp counter
+ */
+struct amd_aperf_mperf {
+ u64 aperf;
+ u64 mperf;
+ u64 tsc;
+};
+
+/**
+ * struct amd_cpudata - private CPU data for AMD P-State
+ * @cpu: CPU number
+ * @req: constraint request to apply
+ * @cppc_req_cached: cached performance request hints
+ * @highest_perf: the maximum performance an individual processor may reach,
+ * assuming ideal conditions
+ * @nominal_perf: the maximum sustained performance level of the processor,
+ * assuming ideal operating conditions
+ * @lowest_nonlinear_perf: the lowest performance level at which nonlinear power
+ * savings are achieved
+ * @lowest_perf: the absolute lowest performance level of the processor
+ * @max_freq: the frequency that mapped to highest_perf
+ * @min_freq: the frequency that mapped to lowest_perf
+ * @nominal_freq: the frequency that mapped to nominal_perf
+ * @lowest_nonlinear_freq: the frequency that mapped to lowest_nonlinear_perf
+ * @cur: Difference of Aperf/Mperf/tsc count between last and current sample
+ * @prev: Last Aperf/Mperf/tsc count value read from register
+ * @freq: current cpu frequency value
+ * @boost_supported: check whether the Processor or SBIOS supports boost mode
+ *
+ * The amd_cpudata is key private data for each CPU thread in AMD P-State, and
+ * represents all the attributes and goals that AMD P-State requests at runtime.
+ */
+struct amd_cpudata {
+ int cpu;
+
+ struct freq_qos_request req[2];
+ u64 cppc_req_cached;
+
+ u32 highest_perf;
+ u32 nominal_perf;
+ u32 lowest_nonlinear_perf;
+ u32 lowest_perf;
+
+ u32 max_freq;
+ u32 min_freq;
+ u32 nominal_freq;
+ u32 lowest_nonlinear_freq;
+
+ struct amd_aperf_mperf cur;
+ struct amd_aperf_mperf prev;
+
+ u64 freq;
+ bool boost_supported;
+};
+
+#endif /* _LINUX_AMD_PSTATE_H */
--
2.25.1
On 4/21/22 1:41 AM, Meng Li wrote:
> Adds a wrapper shell script for the amd_pstate_testmod module.
>
> Signed-off-by: Meng Li <[email protected]>
> ---
> tools/testing/selftests/cpufreq/amd_pstate_testmod.sh | 4 ++++
> tools/testing/selftests/cpufreq/config | 1 +
> tools/testing/selftests/cpufreq/main.sh | 1 +
> 3 files changed, 6 insertions(+)
> create mode 100755 tools/testing/selftests/cpufreq/amd_pstate_testmod.sh
>
> diff --git a/tools/testing/selftests/cpufreq/amd_pstate_testmod.sh b/tools/testing/selftests/cpufreq/amd_pstate_testmod.sh
> new file mode 100755
> index 000000000000..5398ad568885
> --- /dev/null
> +++ b/tools/testing/selftests/cpufreq/amd_pstate_testmod.sh
> @@ -0,0 +1,4 @@
> +#!/bin/sh
> +# SPDX-License-Identifier: GPL-2.0
> +# Tests the AMD P-State unit test infrastructure using amd_pstate_testmod kernel module.
> +$(dirname $0)/../kselftest/module.sh "amd_pstate_testmod" amd_pstate_testmod
The script could load the module and unload once the test is complete.
> diff --git a/tools/testing/selftests/cpufreq/config b/tools/testing/selftests/cpufreq/config
> index 75e900793e8a..374a8adbb34c 100644
> --- a/tools/testing/selftests/cpufreq/config
> +++ b/tools/testing/selftests/cpufreq/config
> @@ -13,3 +13,4 @@ CONFIG_DEBUG_LOCK_ALLOC=y
> CONFIG_PROVE_LOCKING=y
> CONFIG_LOCKDEP=y
> CONFIG_DEBUG_ATOMIC_SLEEP=y
> +CONFIG_AMD_PSTATE_TESTMOD=m
> diff --git a/tools/testing/selftests/cpufreq/main.sh b/tools/testing/selftests/cpufreq/main.sh
> index 60ce18ed0666..d3602fa11392 100755
> --- a/tools/testing/selftests/cpufreq/main.sh
> +++ b/tools/testing/selftests/cpufreq/main.sh
> @@ -6,6 +6,7 @@ source cpufreq.sh
> source governor.sh
> source module.sh
> source special-tests.sh
> +source amd_pstate_testmod.sh
>
Does the script check if the test module is loaded and bail out?
I don't see the check for CONFIG_AMD_PSTATE_TESTMOD enable and
module load.
> FUNC=basic # do basic tests by default
> OUTFILE=cpufreq_selftest
>
thanks,
-- Shuah
On 4/21/22 1:41 AM, Meng Li wrote:
> Hi all:
>
> AMD P-State unit test(amd_pstate_testmod) is a kernel module for testing
> the functions of amd-pstate driver.
> It could import as a module to launch some test tasks.
> 1) It can help all users to verify their processor support (SBIOS/Firmware
> or Hardware).
> 2) Kernel can have a basic function test to avoid the kernel regression
> during the update.
> 3) We can introduce more functional or performance tests to align the
> together, it will benefit power and performance scale optimization.
>
> We upstream out AMD P-state driver into Linux kernel and use this unit
> test module to verify the required conditions and basic functions of
> amd-pstate before integration test.
>
> We use test module in the kselftest frameworks to implement it.
> We create amd_pstate_testmod module and tie it into kselftest.
>
> For example: The test case aput_acpi_cpc is used to check whether the
> _CPC object is exist in SBIOS.
> The amd-pstate initialization will fail if the _CPC in ACPI SBIOS is not
> existed at the detected processor, so it is a necessary condition.
>
> At present, it only implements the basic framework and some simple test
> cases.
>
> TODO : 1) we will add a rst document.
Please include document in this series and describe how the test can be run.
It is not clear to me how use should go about running this test especially
since the script depends on a test module which will need to be compiled
and loaded.
I would like to see clear details in the document on the steps involved in
running the test.
> 2) we will add more test cases to improve the depth and coverage of
> the test.
>
thanks,
-- Shuah