mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
linux-kselftest-next-6.1-rc1
This Kselftest update for Linux 6.1-rc1 consists of fixes and new tests. - Adds a amd-pstate-ut test module, this module is used by kselftest to unit test amd-pstate functionality - Fixes and cleanups to to cpu-hotplug to delete the fault injection test code - Improvements to vm test to use top_srcdir for builds -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEPZKym/RZuOCGeA/kCwJExA0NQxwFAmM912gACgkQCwJExA0N QxzfAhAAspak4B2FVZdXrb7ulGxCV2CSd49qXbv++7rBy3Ey17XlIO8pUj2FMPpx nBrD2UD+ET/6wHjSzkcSzU47N2BnhetuUWqN2vPmuYo4c8xDME9VSWeoKQ9Yw5rc 6r6TxNG/Jbxab4y9r8jibwkidVzcgfYO/Ecnj9HAZ6wDERkVG+LBxpX4HpxEnCsY c3frYFl0cdtLOSGbEA18qctG7ro2otgh4+cWVfSo9NDypL9UfF8bZ8DzqeMOwRLr z2S8L+kBPyQx+ZNdqUgNOfegVx2gKu/P43Xpg8WqRJG/42xxmRmftEOLoVKZ1cCe Rpjv+ZV+/u3QnbEejqJ7MU/QX9JzMG35O4mo7ojxpOJ+cZNXc1ycOm+IOvTCSUJE fiqM2idLvQNjKMVI+FHvkE+9us6K8fzquCYqgRLBKCnfnJJfgT6tWwZpw/G8OSZ6 Px37bfQhALzDj79OkxxoV96GdkR9a2L8GRvZG+7W4l6Oa00OM+rK1oQnjKVgmjT5 wtMwJAXGpwFYqnJagtXcg8dsxS/ZA+k4Eq/skd/yUlCmugmgeVltjk3UmEAYs6Nx ame3798/haptgR1u7ncqltqjx11YR2k9i0Sjf7iqQl8zJhjtDdePAlo2gB4mFUio mZ9BBxCD+oUnAZprA5AwN0ZxPKLWgvPS5rLqTtFt3Pf0agjHSpY= =O0Lh -----END PGP SIGNATURE----- Merge tag 'linux-kselftest-next-6.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest Pull Kselftest updates from Shuah Khan: "Fixes and new tests: - Add an amd-pstate-ut test module, used by kselftest to unit test amd-pstate functionality - Fixes and cleanups to to cpu-hotplug to delete the fault injection test code - Improvements to vm test to use top_srcdir for builds" * tag 'linux-kselftest-next-6.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest: docs:kselftest: fix kselftest_module.h path of example module cpufreq: amd-pstate: Add explanation for X86_AMD_PSTATE_UT selftests/cpu-hotplug: Add log info when test success selftests/cpu-hotplug: Reserve one cpu online at least selftests/cpu-hotplug: Delete fault injection related code selftests/cpu-hotplug: Use return instead of exit selftests/cpu-hotplug: Correct log info cpufreq: amd-pstate: modify type in argument 2 for filp_open Documentation: amd-pstate: Add unit test introduction selftests: amd-pstate: Add test trigger for amd-pstate driver cpufreq: amd-pstate: Add test module for amd-pstate driver cpufreq: amd-pstate: Expose struct amd_cpudata selftests/vm: use top_srcdir instead of recomputing relative paths
This commit is contained in:
commit
dd42d9c3f4
19 changed files with 574 additions and 171 deletions
|
@ -182,6 +182,7 @@ to the ``struct sugov_cpu`` that the utilization update belongs to.
|
||||||
Then, ``amd-pstate`` updates the desired performance according to the CPU
|
Then, ``amd-pstate`` updates the desired performance according to the CPU
|
||||||
scheduler assigned.
|
scheduler assigned.
|
||||||
|
|
||||||
|
.. _processor_support:
|
||||||
|
|
||||||
Processor Support
|
Processor Support
|
||||||
=======================
|
=======================
|
||||||
|
@ -282,6 +283,8 @@ efficiency frequency management method on AMD processors.
|
||||||
Kernel Module Options for ``amd-pstate``
|
Kernel Module Options for ``amd-pstate``
|
||||||
=========================================
|
=========================================
|
||||||
|
|
||||||
|
.. _shared_mem:
|
||||||
|
|
||||||
``shared_mem``
|
``shared_mem``
|
||||||
Use a module param (shared_mem) to enable related processors manually with
|
Use a module param (shared_mem) to enable related processors manually with
|
||||||
**amd_pstate.shared_mem=1**.
|
**amd_pstate.shared_mem=1**.
|
||||||
|
@ -393,6 +396,76 @@ about part of the output. ::
|
||||||
CPU_005 712 116384 39 49 166 0.7565 9645075 2214891 38431470 25.1 11.646 469 2.496 kworker/5:0-40
|
CPU_005 712 116384 39 49 166 0.7565 9645075 2214891 38431470 25.1 11.646 469 2.496 kworker/5:0-40
|
||||||
CPU_006 712 116408 39 49 166 0.6769 8950227 1839034 37192089 24.06 11.272 470 2.496 kworker/6:0-1264
|
CPU_006 712 116408 39 49 166 0.6769 8950227 1839034 37192089 24.06 11.272 470 2.496 kworker/6:0-1264
|
||||||
|
|
||||||
|
Unit Tests for amd-pstate
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
``amd-pstate-ut`` is a test module for testing the ``amd-pstate`` driver.
|
||||||
|
|
||||||
|
* It can help all users to verify their processor support (SBIOS/Firmware or Hardware).
|
||||||
|
|
||||||
|
* Kernel can have a basic function test to avoid the kernel regression during the update.
|
||||||
|
|
||||||
|
* We can introduce more functional or performance tests to align the result together, it will benefit power and performance scale optimization.
|
||||||
|
|
||||||
|
1. Test case decriptions
|
||||||
|
|
||||||
|
+---------+--------------------------------+------------------------------------------------------------------------------------+
|
||||||
|
| Index | Functions | Description |
|
||||||
|
+=========+================================+====================================================================================+
|
||||||
|
| 0 | amd_pstate_ut_acpi_cpc_valid || Check whether the _CPC object is present in SBIOS. |
|
||||||
|
| | || |
|
||||||
|
| | || The detail refer to `Processor Support <processor_support_>`_. |
|
||||||
|
+---------+--------------------------------+------------------------------------------------------------------------------------+
|
||||||
|
| 1 | amd_pstate_ut_check_enabled || Check whether AMD P-State is enabled. |
|
||||||
|
| | || |
|
||||||
|
| | || AMD P-States and ACPI hardware P-States always can be supported in one processor. |
|
||||||
|
| | | But AMD P-States has the higher priority and if it is enabled with |
|
||||||
|
| | | :c:macro:`MSR_AMD_CPPC_ENABLE` or ``cppc_set_enable``, it will respond to the |
|
||||||
|
| | | request from AMD P-States. |
|
||||||
|
+---------+--------------------------------+------------------------------------------------------------------------------------+
|
||||||
|
| 2 | amd_pstate_ut_check_perf || Check if the each performance values are reasonable. |
|
||||||
|
| | || highest_perf >= nominal_perf > lowest_nonlinear_perf > lowest_perf > 0. |
|
||||||
|
+---------+--------------------------------+------------------------------------------------------------------------------------+
|
||||||
|
| 3 | amd_pstate_ut_check_freq || Check if the each frequency values and max freq when set support boost mode |
|
||||||
|
| | | are reasonable. |
|
||||||
|
| | || max_freq >= nominal_freq > lowest_nonlinear_freq > min_freq > 0 |
|
||||||
|
| | || If boost is not active but supported, this maximum frequency will be larger than |
|
||||||
|
| | | the one in ``cpuinfo``. |
|
||||||
|
+---------+--------------------------------+------------------------------------------------------------------------------------+
|
||||||
|
|
||||||
|
#. How to execute the tests
|
||||||
|
|
||||||
|
We use test module in the kselftest frameworks to implement it.
|
||||||
|
We create amd-pstate-ut module and tie it into kselftest.(for
|
||||||
|
details refer to Linux Kernel Selftests [4]_).
|
||||||
|
|
||||||
|
1. Build
|
||||||
|
|
||||||
|
+ open the :c:macro:`CONFIG_X86_AMD_PSTATE` configuration option.
|
||||||
|
+ set the :c:macro:`CONFIG_X86_AMD_PSTATE_UT` configuration option to M.
|
||||||
|
+ make project
|
||||||
|
+ make selftest ::
|
||||||
|
|
||||||
|
$ cd linux
|
||||||
|
$ make -C tools/testing/selftests
|
||||||
|
|
||||||
|
#. Installation & Steps ::
|
||||||
|
|
||||||
|
$ make -C tools/testing/selftests install INSTALL_PATH=~/kselftest
|
||||||
|
$ sudo ./kselftest/run_kselftest.sh -c amd-pstate
|
||||||
|
TAP version 13
|
||||||
|
1..1
|
||||||
|
# selftests: amd-pstate: amd-pstate-ut.sh
|
||||||
|
# amd-pstate-ut: ok
|
||||||
|
ok 1 selftests: amd-pstate: amd-pstate-ut.sh
|
||||||
|
|
||||||
|
#. Results ::
|
||||||
|
|
||||||
|
$ dmesg | grep "amd_pstate_ut" | tee log.txt
|
||||||
|
[12977.570663] amd_pstate_ut: 1 amd_pstate_ut_acpi_cpc_valid success!
|
||||||
|
[12977.570673] amd_pstate_ut: 2 amd_pstate_ut_check_enabled success!
|
||||||
|
[12977.571207] amd_pstate_ut: 3 amd_pstate_ut_check_perf success!
|
||||||
|
[12977.571212] amd_pstate_ut: 4 amd_pstate_ut_check_freq success!
|
||||||
|
|
||||||
Reference
|
Reference
|
||||||
===========
|
===========
|
||||||
|
@ -405,3 +478,6 @@ Reference
|
||||||
|
|
||||||
.. [3] Processor Programming Reference (PPR) for AMD Family 19h Model 51h, Revision A1 Processors
|
.. [3] Processor Programming Reference (PPR) for AMD Family 19h Model 51h, Revision A1 Processors
|
||||||
https://www.amd.com/system/files/TechDocs/56569-A1-PUB.zip
|
https://www.amd.com/system/files/TechDocs/56569-A1-PUB.zip
|
||||||
|
|
||||||
|
.. [4] Linux Kernel Selftests,
|
||||||
|
https://www.kernel.org/doc/html/latest/dev-tools/kselftest.html
|
||||||
|
|
|
@ -320,7 +320,7 @@ A bare bones test module might look like this:
|
||||||
|
|
||||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
#include "../tools/testing/selftests/kselftest/module.h"
|
#include "../tools/testing/selftests/kselftest_module.h"
|
||||||
|
|
||||||
KSTM_MODULE_GLOBALS();
|
KSTM_MODULE_GLOBALS();
|
||||||
|
|
||||||
|
|
|
@ -1070,6 +1070,7 @@ L: linux-pm@vger.kernel.org
|
||||||
S: Supported
|
S: Supported
|
||||||
F: Documentation/admin-guide/pm/amd-pstate.rst
|
F: Documentation/admin-guide/pm/amd-pstate.rst
|
||||||
F: drivers/cpufreq/amd-pstate*
|
F: drivers/cpufreq/amd-pstate*
|
||||||
|
F: include/linux/amd-pstate.h
|
||||||
F: tools/power/x86/amd_pstate_tracer/amd_pstate_trace.py
|
F: tools/power/x86/amd_pstate_tracer/amd_pstate_trace.py
|
||||||
|
|
||||||
AMD PTDMA DRIVER
|
AMD PTDMA DRIVER
|
||||||
|
|
|
@ -51,6 +51,21 @@ config X86_AMD_PSTATE
|
||||||
|
|
||||||
If in doubt, say N.
|
If in doubt, say N.
|
||||||
|
|
||||||
|
config X86_AMD_PSTATE_UT
|
||||||
|
tristate "selftest for AMD Processor P-State driver"
|
||||||
|
depends on X86 && ACPI_PROCESSOR
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
This kernel module is used for testing. It's safe to say M here.
|
||||||
|
|
||||||
|
It can also be built-in without X86_AMD_PSTATE enabled.
|
||||||
|
Currently, only tests for amd-pstate are supported. If X86_AMD_PSTATE
|
||||||
|
is set disabled, it can tell the users test can only run on amd-pstate
|
||||||
|
driver, please set X86_AMD_PSTATE enabled.
|
||||||
|
In the future, comparison tests will be added. It can set amd-pstate
|
||||||
|
disabled and set acpi-cpufreq enabled to run test cases, then compare
|
||||||
|
the test results.
|
||||||
|
|
||||||
config X86_ACPI_CPUFREQ
|
config X86_ACPI_CPUFREQ
|
||||||
tristate "ACPI Processor P-States driver"
|
tristate "ACPI Processor P-States driver"
|
||||||
depends on ACPI_PROCESSOR
|
depends on ACPI_PROCESSOR
|
||||||
|
|
|
@ -30,6 +30,7 @@ amd_pstate-y := amd-pstate.o amd-pstate-trace.o
|
||||||
|
|
||||||
obj-$(CONFIG_X86_ACPI_CPUFREQ) += acpi-cpufreq.o
|
obj-$(CONFIG_X86_ACPI_CPUFREQ) += acpi-cpufreq.o
|
||||||
obj-$(CONFIG_X86_AMD_PSTATE) += amd_pstate.o
|
obj-$(CONFIG_X86_AMD_PSTATE) += amd_pstate.o
|
||||||
|
obj-$(CONFIG_X86_AMD_PSTATE_UT) += amd-pstate-ut.o
|
||||||
obj-$(CONFIG_X86_POWERNOW_K8) += powernow-k8.o
|
obj-$(CONFIG_X86_POWERNOW_K8) += powernow-k8.o
|
||||||
obj-$(CONFIG_X86_PCC_CPUFREQ) += pcc-cpufreq.o
|
obj-$(CONFIG_X86_PCC_CPUFREQ) += pcc-cpufreq.o
|
||||||
obj-$(CONFIG_X86_POWERNOW_K6) += powernow-k6.o
|
obj-$(CONFIG_X86_POWERNOW_K6) += powernow-k6.o
|
||||||
|
|
293
drivers/cpufreq/amd-pstate-ut.c
Normal file
293
drivers/cpufreq/amd-pstate-ut.c
Normal file
|
@ -0,0 +1,293 @@
|
||||||
|
// 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 <li.meng@amd.com>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* This driver implements basic framework with plans to enhance it with
|
||||||
|
* additional test cases to improve the depth and coverage of the test.
|
||||||
|
*
|
||||||
|
* See Documentation/admin-guide/pm/amd-pstate.rst Unit Tests for
|
||||||
|
* amd-pstate to get more detail.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
|
#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:
|
||||||
|
* amd_pstate_ut: used as a shortform for AMD P-State unit test.
|
||||||
|
* It helps to keep variable names smaller, simpler
|
||||||
|
*/
|
||||||
|
enum amd_pstate_ut_result {
|
||||||
|
AMD_PSTATE_UT_RESULT_PASS,
|
||||||
|
AMD_PSTATE_UT_RESULT_FAIL,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct amd_pstate_ut_struct {
|
||||||
|
const char *name;
|
||||||
|
void (*func)(u32 index);
|
||||||
|
enum amd_pstate_ut_result result;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Kernel module for testing the AMD P-State unit test
|
||||||
|
*/
|
||||||
|
static void amd_pstate_ut_acpi_cpc_valid(u32 index);
|
||||||
|
static void amd_pstate_ut_check_enabled(u32 index);
|
||||||
|
static void amd_pstate_ut_check_perf(u32 index);
|
||||||
|
static void amd_pstate_ut_check_freq(u32 index);
|
||||||
|
|
||||||
|
static struct amd_pstate_ut_struct amd_pstate_ut_cases[] = {
|
||||||
|
{"amd_pstate_ut_acpi_cpc_valid", amd_pstate_ut_acpi_cpc_valid },
|
||||||
|
{"amd_pstate_ut_check_enabled", amd_pstate_ut_check_enabled },
|
||||||
|
{"amd_pstate_ut_check_perf", amd_pstate_ut_check_perf },
|
||||||
|
{"amd_pstate_ut_check_freq", amd_pstate_ut_check_freq }
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool get_shared_mem(void)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
char path[] = "/sys/module/amd_pstate/parameters/shared_mem";
|
||||||
|
char buf[5] = {0};
|
||||||
|
struct file *filp = NULL;
|
||||||
|
loff_t pos = 0;
|
||||||
|
ssize_t ret;
|
||||||
|
|
||||||
|
if (!boot_cpu_has(X86_FEATURE_CPPC)) {
|
||||||
|
filp = filp_open(path, O_RDONLY, 0);
|
||||||
|
if (IS_ERR(filp))
|
||||||
|
pr_err("%s unable to open %s file!\n", __func__, path);
|
||||||
|
else {
|
||||||
|
ret = kernel_read(filp, &buf, sizeof(buf), &pos);
|
||||||
|
if (ret < 0)
|
||||||
|
pr_err("%s read %s file fail ret=%ld!\n",
|
||||||
|
__func__, path, (long)ret);
|
||||||
|
filp_close(filp, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('Y' == *buf)
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* check the _CPC object is present in SBIOS.
|
||||||
|
*/
|
||||||
|
static void amd_pstate_ut_acpi_cpc_valid(u32 index)
|
||||||
|
{
|
||||||
|
if (acpi_cpc_valid())
|
||||||
|
amd_pstate_ut_cases[index].result = AMD_PSTATE_UT_RESULT_PASS;
|
||||||
|
else {
|
||||||
|
amd_pstate_ut_cases[index].result = AMD_PSTATE_UT_RESULT_FAIL;
|
||||||
|
pr_err("%s the _CPC object is not present in SBIOS!\n", __func__);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void amd_pstate_ut_pstate_enable(u32 index)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
u64 cppc_enable = 0;
|
||||||
|
|
||||||
|
ret = rdmsrl_safe(MSR_AMD_CPPC_ENABLE, &cppc_enable);
|
||||||
|
if (ret) {
|
||||||
|
amd_pstate_ut_cases[index].result = AMD_PSTATE_UT_RESULT_FAIL;
|
||||||
|
pr_err("%s rdmsrl_safe MSR_AMD_CPPC_ENABLE ret=%d error!\n", __func__, ret);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (cppc_enable)
|
||||||
|
amd_pstate_ut_cases[index].result = AMD_PSTATE_UT_RESULT_PASS;
|
||||||
|
else {
|
||||||
|
amd_pstate_ut_cases[index].result = AMD_PSTATE_UT_RESULT_FAIL;
|
||||||
|
pr_err("%s amd pstate must be enabled!\n", __func__);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* check if amd pstate is enabled
|
||||||
|
*/
|
||||||
|
static void amd_pstate_ut_check_enabled(u32 index)
|
||||||
|
{
|
||||||
|
if (get_shared_mem())
|
||||||
|
amd_pstate_ut_cases[index].result = AMD_PSTATE_UT_RESULT_PASS;
|
||||||
|
else
|
||||||
|
amd_pstate_ut_pstate_enable(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* check if performance values are reasonable.
|
||||||
|
* highest_perf >= nominal_perf > lowest_nonlinear_perf > lowest_perf > 0
|
||||||
|
*/
|
||||||
|
static void amd_pstate_ut_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) {
|
||||||
|
amd_pstate_ut_cases[index].result = AMD_PSTATE_UT_RESULT_FAIL;
|
||||||
|
pr_err("%s cppc_get_perf_caps ret=%d 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) {
|
||||||
|
amd_pstate_ut_cases[index].result = AMD_PSTATE_UT_RESULT_FAIL;
|
||||||
|
pr_err("%s read CPPC_CAP1 ret=%d 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))) {
|
||||||
|
amd_pstate_ut_cases[index].result = AMD_PSTATE_UT_RESULT_FAIL;
|
||||||
|
pr_err("%s cpu%d highest=%d %d nominal=%d %d lowest_nonlinear=%d %d lowest=%d %d, they should be 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))) {
|
||||||
|
amd_pstate_ut_cases[index].result = AMD_PSTATE_UT_RESULT_FAIL;
|
||||||
|
pr_err("%s cpu%d highest=%d >= nominal=%d > lowest_nonlinear=%d > lowest=%d > 0, the formula is incorrect!\n",
|
||||||
|
__func__, cpu, highest_perf, nominal_perf,
|
||||||
|
lowest_nonlinear_perf, lowest_perf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
amd_pstate_ut_cases[index].result = AMD_PSTATE_UT_RESULT_PASS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if frequency values are reasonable.
|
||||||
|
* max_freq >= nominal_freq > lowest_nonlinear_freq > min_freq > 0
|
||||||
|
* check max freq when set support boost mode.
|
||||||
|
*/
|
||||||
|
static void amd_pstate_ut_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))) {
|
||||||
|
amd_pstate_ut_cases[index].result = AMD_PSTATE_UT_RESULT_FAIL;
|
||||||
|
pr_err("%s cpu%d max=%d >= nominal=%d > lowest_nonlinear=%d > min=%d > 0, the formula is incorrect!\n",
|
||||||
|
__func__, cpu, cpudata->max_freq, cpudata->nominal_freq,
|
||||||
|
cpudata->lowest_nonlinear_freq, cpudata->min_freq);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cpudata->min_freq != policy->min) {
|
||||||
|
amd_pstate_ut_cases[index].result = AMD_PSTATE_UT_RESULT_FAIL;
|
||||||
|
pr_err("%s cpu%d cpudata_min_freq=%d policy_min=%d, they should be equal!\n",
|
||||||
|
__func__, cpu, cpudata->min_freq, policy->min);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cpudata->boost_supported) {
|
||||||
|
if ((policy->max == cpudata->max_freq) ||
|
||||||
|
(policy->max == cpudata->nominal_freq))
|
||||||
|
amd_pstate_ut_cases[index].result = AMD_PSTATE_UT_RESULT_PASS;
|
||||||
|
else {
|
||||||
|
amd_pstate_ut_cases[index].result = AMD_PSTATE_UT_RESULT_FAIL;
|
||||||
|
pr_err("%s cpu%d policy_max=%d should be equal cpu_max=%d or cpu_nominal=%d !\n",
|
||||||
|
__func__, cpu, policy->max, cpudata->max_freq,
|
||||||
|
cpudata->nominal_freq);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
amd_pstate_ut_cases[index].result = AMD_PSTATE_UT_RESULT_FAIL;
|
||||||
|
pr_err("%s cpu%d must support boost!\n", __func__, cpu);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
amd_pstate_ut_cases[index].result = AMD_PSTATE_UT_RESULT_PASS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __init amd_pstate_ut_init(void)
|
||||||
|
{
|
||||||
|
u32 i = 0, arr_size = ARRAY_SIZE(amd_pstate_ut_cases);
|
||||||
|
|
||||||
|
for (i = 0; i < arr_size; i++) {
|
||||||
|
amd_pstate_ut_cases[i].func(i);
|
||||||
|
switch (amd_pstate_ut_cases[i].result) {
|
||||||
|
case AMD_PSTATE_UT_RESULT_PASS:
|
||||||
|
pr_info("%-4d %-20s\t success!\n", i+1, amd_pstate_ut_cases[i].name);
|
||||||
|
break;
|
||||||
|
case AMD_PSTATE_UT_RESULT_FAIL:
|
||||||
|
default:
|
||||||
|
pr_info("%-4d %-20s\t fail!\n", i+1, amd_pstate_ut_cases[i].name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit amd_pstate_ut_exit(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(amd_pstate_ut_init);
|
||||||
|
module_exit(amd_pstate_ut_exit);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Meng Li <li.meng@amd.com>");
|
||||||
|
MODULE_DESCRIPTION("AMD P-state driver Test module");
|
||||||
|
MODULE_LICENSE("GPL");
|
|
@ -36,6 +36,7 @@
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
#include <linux/static_call.h>
|
#include <linux/static_call.h>
|
||||||
|
#include <linux/amd-pstate.h>
|
||||||
|
|
||||||
#include <acpi/processor.h>
|
#include <acpi/processor.h>
|
||||||
#include <acpi/cppc_acpi.h>
|
#include <acpi/cppc_acpi.h>
|
||||||
|
@ -65,65 +66,6 @@ MODULE_PARM_DESC(shared_mem,
|
||||||
|
|
||||||
static struct cpufreq_driver amd_pstate_driver;
|
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)
|
static inline int pstate_enable(bool enable)
|
||||||
{
|
{
|
||||||
return wrmsrl_safe(MSR_AMD_CPPC_ENABLE, enable);
|
return wrmsrl_safe(MSR_AMD_CPPC_ENABLE, enable);
|
||||||
|
|
77
include/linux/amd-pstate.h
Normal file
77
include/linux/amd-pstate.h
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
/*
|
||||||
|
* linux/include/linux/amd-pstate.h
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Advanced Micro Devices, Inc.
|
||||||
|
*
|
||||||
|
* Author: Meng Li <li.meng@amd.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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 */
|
|
@ -1,5 +1,6 @@
|
||||||
# SPDX-License-Identifier: GPL-2.0
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
TARGETS += alsa
|
TARGETS += alsa
|
||||||
|
TARGETS += amd-pstate
|
||||||
TARGETS += arm64
|
TARGETS += arm64
|
||||||
TARGETS += bpf
|
TARGETS += bpf
|
||||||
TARGETS += breakpoints
|
TARGETS += breakpoints
|
||||||
|
|
9
tools/testing/selftests/amd-pstate/Makefile
Normal file
9
tools/testing/selftests/amd-pstate/Makefile
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
# Makefile for amd-pstate/ function selftests
|
||||||
|
|
||||||
|
# No binaries, but make sure arg-less "make" doesn't trigger "run_tests"
|
||||||
|
all:
|
||||||
|
|
||||||
|
TEST_PROGS := amd-pstate-ut.sh
|
||||||
|
|
||||||
|
include ../lib.mk
|
56
tools/testing/selftests/amd-pstate/amd-pstate-ut.sh
Executable file
56
tools/testing/selftests/amd-pstate/amd-pstate-ut.sh
Executable file
|
@ -0,0 +1,56 @@
|
||||||
|
#!/bin/sh
|
||||||
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
|
|
||||||
|
# amd-pstate-ut is a test module for testing the amd-pstate driver.
|
||||||
|
# It can only run on x86 architectures and current cpufreq driver
|
||||||
|
# must be amd-pstate.
|
||||||
|
# (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.
|
||||||
|
|
||||||
|
# Kselftest framework requirement - SKIP code is 4.
|
||||||
|
ksft_skip=4
|
||||||
|
|
||||||
|
# amd-pstate-ut only run on x86/x86_64 AMD systems.
|
||||||
|
ARCH=$(uname -m 2>/dev/null | sed -e 's/i.86/x86/' -e 's/x86_64/x86/')
|
||||||
|
VENDOR=$(cat /proc/cpuinfo | grep -m 1 'vendor_id' | awk '{print $NF}')
|
||||||
|
|
||||||
|
if ! echo "$ARCH" | grep -q x86; then
|
||||||
|
echo "$0 # Skipped: Test can only run on x86 architectures."
|
||||||
|
exit $ksft_skip
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! echo "$VENDOR" | grep -iq amd; then
|
||||||
|
echo "$0 # Skipped: Test can only run on AMD CPU."
|
||||||
|
echo "$0 # Current cpu vendor is $VENDOR."
|
||||||
|
exit $ksft_skip
|
||||||
|
fi
|
||||||
|
|
||||||
|
scaling_driver=$(cat /sys/devices/system/cpu/cpufreq/policy0/scaling_driver)
|
||||||
|
if [ "$scaling_driver" != "amd-pstate" ]; then
|
||||||
|
echo "$0 # Skipped: Test can only run on amd-pstate driver."
|
||||||
|
echo "$0 # Please set X86_AMD_PSTATE enabled."
|
||||||
|
echo "$0 # Current cpufreq scaling drvier is $scaling_driver."
|
||||||
|
exit $ksft_skip
|
||||||
|
fi
|
||||||
|
|
||||||
|
msg="Skip all tests:"
|
||||||
|
if [ ! -w /dev ]; then
|
||||||
|
echo $msg please run this as root >&2
|
||||||
|
exit $ksft_skip
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! /sbin/modprobe -q -n amd-pstate-ut; then
|
||||||
|
echo "amd-pstate-ut: module amd-pstate-ut is not found [SKIP]"
|
||||||
|
exit $ksft_skip
|
||||||
|
fi
|
||||||
|
if /sbin/modprobe -q amd-pstate-ut; then
|
||||||
|
/sbin/modprobe -q -r amd-pstate-ut
|
||||||
|
echo "amd-pstate-ut: ok"
|
||||||
|
else
|
||||||
|
echo "amd-pstate-ut: [FAIL]"
|
||||||
|
exit 1
|
||||||
|
fi
|
1
tools/testing/selftests/amd-pstate/config
Normal file
1
tools/testing/selftests/amd-pstate/config
Normal file
|
@ -0,0 +1 @@
|
||||||
|
CONFIG_X86_AMD_PSTATE_UT=m
|
|
@ -6,6 +6,6 @@ TEST_PROGS := cpu-on-off-test.sh
|
||||||
include ../lib.mk
|
include ../lib.mk
|
||||||
|
|
||||||
run_full_test:
|
run_full_test:
|
||||||
@/bin/bash ./cpu-on-off-test.sh -a || echo "cpu-hotplug selftests: [FAIL]"
|
@/bin/bash ./cpu-on-off-test.sh -a && echo "cpu-hotplug selftests: [PASS]" || echo "cpu-hotplug selftests: [FAIL]"
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
CONFIG_NOTIFIER_ERROR_INJECTION=y
|
|
|
@ -4,6 +4,7 @@
|
||||||
SYSFS=
|
SYSFS=
|
||||||
# Kselftest framework requirement - SKIP code is 4.
|
# Kselftest framework requirement - SKIP code is 4.
|
||||||
ksft_skip=4
|
ksft_skip=4
|
||||||
|
retval=0
|
||||||
|
|
||||||
prerequisite()
|
prerequisite()
|
||||||
{
|
{
|
||||||
|
@ -102,10 +103,10 @@ online_cpu_expect_success()
|
||||||
|
|
||||||
if ! online_cpu $cpu; then
|
if ! online_cpu $cpu; then
|
||||||
echo $FUNCNAME $cpu: unexpected fail >&2
|
echo $FUNCNAME $cpu: unexpected fail >&2
|
||||||
exit 1
|
retval=1
|
||||||
elif ! cpu_is_online $cpu; then
|
elif ! cpu_is_online $cpu; then
|
||||||
echo $FUNCNAME $cpu: unexpected offline >&2
|
echo $FUNCNAME $cpu: unexpected offline >&2
|
||||||
exit 1
|
retval=1
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,10 +116,10 @@ online_cpu_expect_fail()
|
||||||
|
|
||||||
if online_cpu $cpu 2> /dev/null; then
|
if online_cpu $cpu 2> /dev/null; then
|
||||||
echo $FUNCNAME $cpu: unexpected success >&2
|
echo $FUNCNAME $cpu: unexpected success >&2
|
||||||
exit 1
|
retval=1
|
||||||
elif ! cpu_is_offline $cpu; then
|
elif ! cpu_is_offline $cpu; then
|
||||||
echo $FUNCNAME $cpu: unexpected online >&2
|
echo $FUNCNAME $cpu: unexpected online >&2
|
||||||
exit 1
|
retval=1
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,10 +129,10 @@ offline_cpu_expect_success()
|
||||||
|
|
||||||
if ! offline_cpu $cpu; then
|
if ! offline_cpu $cpu; then
|
||||||
echo $FUNCNAME $cpu: unexpected fail >&2
|
echo $FUNCNAME $cpu: unexpected fail >&2
|
||||||
exit 1
|
retval=1
|
||||||
elif ! cpu_is_offline $cpu; then
|
elif ! cpu_is_offline $cpu; then
|
||||||
echo $FUNCNAME $cpu: unexpected offline >&2
|
echo $FUNCNAME $cpu: unexpected offline >&2
|
||||||
exit 1
|
retval=1
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,16 +142,33 @@ offline_cpu_expect_fail()
|
||||||
|
|
||||||
if offline_cpu $cpu 2> /dev/null; then
|
if offline_cpu $cpu 2> /dev/null; then
|
||||||
echo $FUNCNAME $cpu: unexpected success >&2
|
echo $FUNCNAME $cpu: unexpected success >&2
|
||||||
exit 1
|
retval=1
|
||||||
elif ! cpu_is_online $cpu; then
|
elif ! cpu_is_online $cpu; then
|
||||||
echo $FUNCNAME $cpu: unexpected offline >&2
|
echo $FUNCNAME $cpu: unexpected offline >&2
|
||||||
exit 1
|
retval=1
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
error=-12
|
online_all_hot_pluggable_cpus()
|
||||||
|
{
|
||||||
|
for cpu in `hotplaggable_offline_cpus`; do
|
||||||
|
online_cpu_expect_success $cpu
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
offline_all_hot_pluggable_cpus()
|
||||||
|
{
|
||||||
|
local reserve_cpu=$online_max
|
||||||
|
for cpu in `hotpluggable_online_cpus`; do
|
||||||
|
# Reserve one cpu oneline at least.
|
||||||
|
if [ $cpu -eq $reserve_cpu ];then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
offline_cpu_expect_success $cpu
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
allcpus=0
|
allcpus=0
|
||||||
priority=0
|
|
||||||
online_cpus=0
|
online_cpus=0
|
||||||
online_max=0
|
online_max=0
|
||||||
offline_cpus=0
|
offline_cpus=0
|
||||||
|
@ -158,31 +176,20 @@ offline_max=0
|
||||||
present_cpus=0
|
present_cpus=0
|
||||||
present_max=0
|
present_max=0
|
||||||
|
|
||||||
while getopts e:ahp: opt; do
|
while getopts ah opt; do
|
||||||
case $opt in
|
case $opt in
|
||||||
e)
|
|
||||||
error=$OPTARG
|
|
||||||
;;
|
|
||||||
a)
|
a)
|
||||||
allcpus=1
|
allcpus=1
|
||||||
;;
|
;;
|
||||||
h)
|
h)
|
||||||
echo "Usage $0 [ -a ] [ -e errno ] [ -p notifier-priority ]"
|
echo "Usage $0 [ -a ]"
|
||||||
echo -e "\t default offline one cpu"
|
echo -e "\t default offline one cpu"
|
||||||
echo -e "\t run with -a option to offline all cpus"
|
echo -e "\t run with -a option to offline all cpus"
|
||||||
exit
|
exit
|
||||||
;;
|
;;
|
||||||
p)
|
|
||||||
priority=$OPTARG
|
|
||||||
;;
|
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
if ! [ "$error" -ge -4095 -a "$error" -lt 0 ]; then
|
|
||||||
echo "error code must be -4095 <= errno < 0" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
prerequisite
|
prerequisite
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -196,12 +203,12 @@ if [ $allcpus -eq 0 ]; then
|
||||||
online_cpu_expect_success $online_max
|
online_cpu_expect_success $online_max
|
||||||
|
|
||||||
if [[ $offline_cpus -gt 0 ]]; then
|
if [[ $offline_cpus -gt 0 ]]; then
|
||||||
echo -e "\t offline to online to offline: cpu $present_max"
|
echo -e "\t online to offline to online: cpu $present_max"
|
||||||
online_cpu_expect_success $present_max
|
online_cpu_expect_success $present_max
|
||||||
offline_cpu_expect_success $present_max
|
offline_cpu_expect_success $present_max
|
||||||
online_cpu $present_max
|
online_cpu $present_max
|
||||||
fi
|
fi
|
||||||
exit 0
|
exit $retval
|
||||||
else
|
else
|
||||||
echo "Full scope test: all hotplug cpus"
|
echo "Full scope test: all hotplug cpus"
|
||||||
echo -e "\t online all offline cpus"
|
echo -e "\t online all offline cpus"
|
||||||
|
@ -209,85 +216,10 @@ else
|
||||||
echo -e "\t online all offline cpus"
|
echo -e "\t online all offline cpus"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
#
|
online_all_hot_pluggable_cpus
|
||||||
# Online all hot-pluggable CPUs
|
|
||||||
#
|
|
||||||
for cpu in `hotplaggable_offline_cpus`; do
|
|
||||||
online_cpu_expect_success $cpu
|
|
||||||
done
|
|
||||||
|
|
||||||
#
|
offline_all_hot_pluggable_cpus
|
||||||
# Offline all hot-pluggable CPUs
|
|
||||||
#
|
|
||||||
for cpu in `hotpluggable_online_cpus`; do
|
|
||||||
offline_cpu_expect_success $cpu
|
|
||||||
done
|
|
||||||
|
|
||||||
#
|
online_all_hot_pluggable_cpus
|
||||||
# Online all hot-pluggable CPUs again
|
|
||||||
#
|
|
||||||
for cpu in `hotplaggable_offline_cpus`; do
|
|
||||||
online_cpu_expect_success $cpu
|
|
||||||
done
|
|
||||||
|
|
||||||
#
|
exit $retval
|
||||||
# Test with cpu notifier error injection
|
|
||||||
#
|
|
||||||
|
|
||||||
DEBUGFS=`mount -t debugfs | head -1 | awk '{ print $3 }'`
|
|
||||||
NOTIFIER_ERR_INJECT_DIR=$DEBUGFS/notifier-error-inject/cpu
|
|
||||||
|
|
||||||
prerequisite_extra()
|
|
||||||
{
|
|
||||||
msg="skip extra tests:"
|
|
||||||
|
|
||||||
/sbin/modprobe -q -r cpu-notifier-error-inject
|
|
||||||
/sbin/modprobe -q cpu-notifier-error-inject priority=$priority
|
|
||||||
|
|
||||||
if [ ! -d "$DEBUGFS" ]; then
|
|
||||||
echo $msg debugfs is not mounted >&2
|
|
||||||
exit $ksft_skip
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -d $NOTIFIER_ERR_INJECT_DIR ]; then
|
|
||||||
echo $msg cpu-notifier-error-inject module is not available >&2
|
|
||||||
exit $ksft_skip
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
prerequisite_extra
|
|
||||||
|
|
||||||
#
|
|
||||||
# Offline all hot-pluggable CPUs
|
|
||||||
#
|
|
||||||
echo 0 > $NOTIFIER_ERR_INJECT_DIR/actions/CPU_DOWN_PREPARE/error
|
|
||||||
for cpu in `hotpluggable_online_cpus`; do
|
|
||||||
offline_cpu_expect_success $cpu
|
|
||||||
done
|
|
||||||
|
|
||||||
#
|
|
||||||
# Test CPU hot-add error handling (offline => online)
|
|
||||||
#
|
|
||||||
echo $error > $NOTIFIER_ERR_INJECT_DIR/actions/CPU_UP_PREPARE/error
|
|
||||||
for cpu in `hotplaggable_offline_cpus`; do
|
|
||||||
online_cpu_expect_fail $cpu
|
|
||||||
done
|
|
||||||
|
|
||||||
#
|
|
||||||
# Online all hot-pluggable CPUs
|
|
||||||
#
|
|
||||||
echo 0 > $NOTIFIER_ERR_INJECT_DIR/actions/CPU_UP_PREPARE/error
|
|
||||||
for cpu in `hotplaggable_offline_cpus`; do
|
|
||||||
online_cpu_expect_success $cpu
|
|
||||||
done
|
|
||||||
|
|
||||||
#
|
|
||||||
# Test CPU hot-remove error handling (online => offline)
|
|
||||||
#
|
|
||||||
echo $error > $NOTIFIER_ERR_INJECT_DIR/actions/CPU_DOWN_PREPARE/error
|
|
||||||
for cpu in `hotpluggable_online_cpus`; do
|
|
||||||
offline_cpu_expect_fail $cpu
|
|
||||||
done
|
|
||||||
|
|
||||||
echo 0 > $NOTIFIER_ERR_INJECT_DIR/actions/CPU_DOWN_PREPARE/error
|
|
||||||
/sbin/modprobe -q -r cpu-notifier-error-inject
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ MACHINE ?= $(shell echo $(uname_M) | sed -e 's/aarch64.*/arm64/' -e 's/ppc64.*/p
|
||||||
# LDLIBS.
|
# LDLIBS.
|
||||||
MAKEFLAGS += --no-builtin-rules
|
MAKEFLAGS += --no-builtin-rules
|
||||||
|
|
||||||
CFLAGS = -Wall -I ../../../../usr/include $(EXTRA_CFLAGS) $(KHDR_INCLUDES)
|
CFLAGS = -Wall -I $(top_srcdir) -I $(top_srcdir)/usr/include $(EXTRA_CFLAGS) $(KHDR_INCLUDES)
|
||||||
LDLIBS = -lrt -lpthread
|
LDLIBS = -lrt -lpthread
|
||||||
TEST_GEN_FILES = compaction_test
|
TEST_GEN_FILES = compaction_test
|
||||||
TEST_GEN_FILES += gup_test
|
TEST_GEN_FILES += gup_test
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include "../../../../mm/gup_test.h"
|
#include <mm/gup_test.h>
|
||||||
#include "../kselftest.h"
|
#include "../kselftest.h"
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
|
@ -35,8 +35,8 @@
|
||||||
* This is a private UAPI to the kernel test module so it isn't exported
|
* This is a private UAPI to the kernel test module so it isn't exported
|
||||||
* in the usual include/uapi/... directory.
|
* in the usual include/uapi/... directory.
|
||||||
*/
|
*/
|
||||||
#include "../../../../lib/test_hmm_uapi.h"
|
#include <lib/test_hmm_uapi.h>
|
||||||
#include "../../../../mm/gup_test.h"
|
#include <mm/gup_test.h>
|
||||||
|
|
||||||
struct hmm_buffer {
|
struct hmm_buffer {
|
||||||
void *ptr;
|
void *ptr;
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
|
|
||||||
#include "../kselftest.h"
|
#include "../kselftest.h"
|
||||||
#include "../../../../include/vdso/time64.h"
|
#include <include/vdso/time64.h>
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
#define KSM_SYSFS_PATH "/sys/kernel/mm/ksm/"
|
#define KSM_SYSFS_PATH "/sys/kernel/mm/ksm/"
|
||||||
|
|
Loading…
Add table
Reference in a new issue