2020-01-16 13:32:39 -08:00
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
|
|
|
/*
|
|
|
|
* Resctrl tests
|
|
|
|
*
|
|
|
|
* Copyright (C) 2018 Intel Corporation
|
|
|
|
*
|
|
|
|
* Authors:
|
|
|
|
* Sai Praneeth Prakhya <sai.praneeth.prakhya@intel.com>,
|
|
|
|
* Fenghua Yu <fenghua.yu@intel.com>
|
|
|
|
*/
|
|
|
|
#include "resctrl.h"
|
|
|
|
|
2023-12-15 17:05:06 +02:00
|
|
|
/* Volatile memory sink to prevent compiler optimizations */
|
|
|
|
static volatile int sink_target;
|
|
|
|
volatile int *value_sink = &sink_target;
|
|
|
|
|
2023-12-15 17:05:11 +02:00
|
|
|
static struct resctrl_test *resctrl_tests[] = {
|
|
|
|
&mbm_test,
|
|
|
|
&mba_test,
|
|
|
|
&cmt_test,
|
|
|
|
&l3_cat_test,
|
2024-02-16 09:35:52 +01:00
|
|
|
&l3_noncont_cat_test,
|
|
|
|
&l2_noncont_cat_test,
|
2023-12-15 17:05:11 +02:00
|
|
|
};
|
|
|
|
|
2022-03-23 17:09:27 +09:00
|
|
|
static int detect_vendor(void)
|
2020-01-16 13:32:43 -08:00
|
|
|
{
|
|
|
|
FILE *inf = fopen("/proc/cpuinfo", "r");
|
2022-03-23 17:09:27 +09:00
|
|
|
int vendor_id = 0;
|
|
|
|
char *s = NULL;
|
2020-01-16 13:32:43 -08:00
|
|
|
char *res;
|
|
|
|
|
|
|
|
if (!inf)
|
2022-03-23 17:09:27 +09:00
|
|
|
return vendor_id;
|
2020-01-16 13:32:43 -08:00
|
|
|
|
|
|
|
res = fgrep(inf, "vendor_id");
|
|
|
|
|
2022-03-23 17:09:27 +09:00
|
|
|
if (res)
|
|
|
|
s = strchr(res, ':');
|
|
|
|
|
|
|
|
if (s && !strcmp(s, ": GenuineIntel\n"))
|
|
|
|
vendor_id = ARCH_INTEL;
|
|
|
|
else if (s && !strcmp(s, ": AuthenticAMD\n"))
|
|
|
|
vendor_id = ARCH_AMD;
|
2020-01-16 13:32:43 -08:00
|
|
|
|
|
|
|
fclose(inf);
|
2022-03-23 17:09:27 +09:00
|
|
|
free(res);
|
|
|
|
return vendor_id;
|
|
|
|
}
|
|
|
|
|
|
|
|
int get_vendor(void)
|
|
|
|
{
|
|
|
|
static int vendor = -1;
|
|
|
|
|
|
|
|
if (vendor == -1)
|
|
|
|
vendor = detect_vendor();
|
|
|
|
if (vendor == 0)
|
|
|
|
ksft_print_msg("Can not get vendor info...\n");
|
|
|
|
|
|
|
|
return vendor;
|
2020-01-16 13:32:43 -08:00
|
|
|
}
|
|
|
|
|
2020-01-16 13:32:39 -08:00
|
|
|
static void cmd_help(void)
|
|
|
|
{
|
2023-12-15 17:05:11 +02:00
|
|
|
int i;
|
|
|
|
|
2023-09-04 12:53:33 +03:00
|
|
|
printf("usage: resctrl_tests [-h] [-t test list] [-n no_of_bits] [-b benchmark_cmd [option]...]\n");
|
|
|
|
printf("\t-b benchmark_cmd [option]...: run specified benchmark for MBM, MBA and CMT\n");
|
2021-03-17 02:22:44 +00:00
|
|
|
printf("\t default benchmark is builtin fill_buf\n");
|
2024-02-16 09:34:56 +01:00
|
|
|
printf("\t-t test list: run tests/groups specified by the list, ");
|
selftests/resctrl: Fix incorrect parsing of option "-t"
Resctrl test suite accepts command line argument "-t" to specify the
unit tests to run in the test list (e.g., -t mbm,mba,cmt,cat) as
documented in the help.
When calling strtok() to parse the option, the incorrect delimiters
argument ":\t" is used. As a result, passing "-t mbm,mba,cmt,cat" throws
an invalid option error.
Fix this by using delimiters argument "," instead of ":\t" for parsing
of unit tests list. At the same time, remove the unnecessary "spaces"
between the unit tests in help documentation to prevent confusion.
Fixes: 790bf585b0ee ("selftests/resctrl: Add Cache Allocation Technology (CAT) selftest")
Fixes: 78941183d1b1 ("selftests/resctrl: Add Cache QoS Monitoring (CQM) selftest")
Fixes: ecdbb911f22d ("selftests/resctrl: Add MBM test")
Fixes: 034c7678dd2c ("selftests/resctrl: Add README for resctrl tests")
Cc: stable@vger.kernel.org
Signed-off-by: Xiaochen Shen <xiaochen.shen@intel.com>
Reviewed-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
2021-05-27 17:31:53 +08:00
|
|
|
printf("e.g. -t mbm,mba,cmt,cat\n");
|
2024-02-16 09:34:56 +01:00
|
|
|
printf("\t\tSupported tests (group):\n");
|
|
|
|
for (i = 0; i < ARRAY_SIZE(resctrl_tests); i++) {
|
|
|
|
if (resctrl_tests[i]->group)
|
|
|
|
printf("\t\t\t%s (%s)\n", resctrl_tests[i]->name, resctrl_tests[i]->group);
|
|
|
|
else
|
|
|
|
printf("\t\t\t%s\n", resctrl_tests[i]->name);
|
|
|
|
}
|
2020-01-16 13:32:41 -08:00
|
|
|
printf("\t-n no_of_bits: run cache tests using specified no of bits in cache bit mask\n");
|
|
|
|
printf("\t-p cpu_no: specify CPU number to run the test. 1 is default\n");
|
2020-01-16 13:32:39 -08:00
|
|
|
printf("\t-h: help\n");
|
|
|
|
}
|
|
|
|
|
2024-02-27 08:21:42 +01:00
|
|
|
static int test_prepare(const struct resctrl_test *test)
|
2021-03-17 02:22:50 +00:00
|
|
|
{
|
|
|
|
int res;
|
|
|
|
|
2024-02-27 08:21:42 +01:00
|
|
|
res = signal_handler_register(test);
|
2023-10-02 12:48:08 +03:00
|
|
|
if (res) {
|
|
|
|
ksft_print_msg("Failed to register signal handler\n");
|
|
|
|
return res;
|
|
|
|
}
|
selftests/resctrl: Skip the test if requested resctrl feature is not supported
There could be two reasons why a resctrl feature might not be enabled on
the platform
1. H/W might not support the feature
2. Even if the H/W supports it, the user might have disabled the feature
through kernel command line arguments
Hence, any resctrl unit test (like cmt, cat, mbm and mba) before starting
the test will first check if the feature is enabled on the platform or not.
If the feature isn't enabled, then the test returns with an error status.
For example, if MBA isn't supported on a platform and if the user tries to
run MBA, the output will look like this
ok mounting resctrl to "/sys/fs/resctrl"
not ok MBA: schemata change
But, not supporting a feature isn't a test failure. So, instead of treating
it as an error, use the SKIP directive of the TAP protocol. With the
change, the output will look as below
ok MBA # SKIP Hardware does not support MBA or MBA is disabled
Suggested-by: Reinette Chatre <reinette.chatre@intel.com>
Tested-by: Babu Moger <babu.moger@amd.com>
Signed-off-by: Fenghua Yu <fenghua.yu@intel.com>
Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
2021-03-17 02:22:51 +00:00
|
|
|
|
2023-07-17 16:14:55 +03:00
|
|
|
res = mount_resctrlfs();
|
2023-07-17 16:14:54 +03:00
|
|
|
if (res) {
|
2023-10-02 12:48:08 +03:00
|
|
|
signal_handler_unregister();
|
|
|
|
ksft_print_msg("Failed to mount resctrl FS\n");
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2024-02-27 08:21:43 +01:00
|
|
|
static void test_cleanup(const struct resctrl_test *test)
|
2023-10-02 12:48:08 +03:00
|
|
|
{
|
2024-02-27 08:21:43 +01:00
|
|
|
if (test->cleanup)
|
|
|
|
test->cleanup();
|
2023-10-02 12:48:08 +03:00
|
|
|
umount_resctrlfs();
|
|
|
|
signal_handler_unregister();
|
|
|
|
}
|
|
|
|
|
2023-12-15 17:05:11 +02:00
|
|
|
static bool test_vendor_specific_check(const struct resctrl_test *test)
|
2023-10-02 12:48:08 +03:00
|
|
|
{
|
2023-12-15 17:05:11 +02:00
|
|
|
if (!test->vendor_specific)
|
|
|
|
return true;
|
2023-07-17 16:14:54 +03:00
|
|
|
|
2023-12-15 17:05:11 +02:00
|
|
|
return get_vendor() & test->vendor_specific;
|
2021-03-17 02:22:50 +00:00
|
|
|
}
|
|
|
|
|
2023-12-15 17:05:11 +02:00
|
|
|
static void run_single_test(const struct resctrl_test *test, const struct user_params *uparams)
|
2021-03-17 02:22:50 +00:00
|
|
|
{
|
2024-12-16 16:18:53 +01:00
|
|
|
int ret, snc_mode;
|
selftests/resctrl: Skip the test if requested resctrl feature is not supported
There could be two reasons why a resctrl feature might not be enabled on
the platform
1. H/W might not support the feature
2. Even if the H/W supports it, the user might have disabled the feature
through kernel command line arguments
Hence, any resctrl unit test (like cmt, cat, mbm and mba) before starting
the test will first check if the feature is enabled on the platform or not.
If the feature isn't enabled, then the test returns with an error status.
For example, if MBA isn't supported on a platform and if the user tries to
run MBA, the output will look like this
ok mounting resctrl to "/sys/fs/resctrl"
not ok MBA: schemata change
But, not supporting a feature isn't a test failure. So, instead of treating
it as an error, use the SKIP directive of the TAP protocol. With the
change, the output will look as below
ok MBA # SKIP Hardware does not support MBA or MBA is disabled
Suggested-by: Reinette Chatre <reinette.chatre@intel.com>
Tested-by: Babu Moger <babu.moger@amd.com>
Signed-off-by: Fenghua Yu <fenghua.yu@intel.com>
Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
2021-03-17 02:22:51 +00:00
|
|
|
|
2023-12-15 17:05:11 +02:00
|
|
|
if (test->disabled)
|
2023-07-17 16:14:54 +03:00
|
|
|
return;
|
|
|
|
|
2023-12-15 17:05:11 +02:00
|
|
|
if (!test_vendor_specific_check(test)) {
|
|
|
|
ksft_test_result_skip("Hardware does not support %s\n", test->name);
|
2023-07-17 16:14:54 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-12-16 16:18:53 +01:00
|
|
|
snc_mode = snc_nodes_per_l3_cache();
|
|
|
|
|
2023-12-15 17:05:11 +02:00
|
|
|
ksft_print_msg("Starting %s test ...\n", test->name);
|
selftests/resctrl: Skip the test if requested resctrl feature is not supported
There could be two reasons why a resctrl feature might not be enabled on
the platform
1. H/W might not support the feature
2. Even if the H/W supports it, the user might have disabled the feature
through kernel command line arguments
Hence, any resctrl unit test (like cmt, cat, mbm and mba) before starting
the test will first check if the feature is enabled on the platform or not.
If the feature isn't enabled, then the test returns with an error status.
For example, if MBA isn't supported on a platform and if the user tries to
run MBA, the output will look like this
ok mounting resctrl to "/sys/fs/resctrl"
not ok MBA: schemata change
But, not supporting a feature isn't a test failure. So, instead of treating
it as an error, use the SKIP directive of the TAP protocol. With the
change, the output will look as below
ok MBA # SKIP Hardware does not support MBA or MBA is disabled
Suggested-by: Reinette Chatre <reinette.chatre@intel.com>
Tested-by: Babu Moger <babu.moger@amd.com>
Signed-off-by: Fenghua Yu <fenghua.yu@intel.com>
Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
2021-03-17 02:22:51 +00:00
|
|
|
|
2024-12-16 16:18:53 +01:00
|
|
|
if (snc_mode == 1 && snc_unreliable && get_vendor() == ARCH_INTEL) {
|
|
|
|
ksft_test_result_skip("SNC detection unreliable due to offline CPUs. Test results may not be accurate if SNC enabled.\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-02-27 08:21:42 +01:00
|
|
|
if (test_prepare(test)) {
|
2023-10-02 12:48:08 +03:00
|
|
|
ksft_exit_fail_msg("Abnormal failure when preparing for the test\n");
|
2023-07-17 16:14:54 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-12-15 17:05:11 +02:00
|
|
|
if (!test->feature_check(test)) {
|
|
|
|
ksft_test_result_skip("Hardware does not support %s or %s is disabled\n",
|
|
|
|
test->name, test->name);
|
2023-10-02 12:48:08 +03:00
|
|
|
goto cleanup;
|
selftests/resctrl: Skip the test if requested resctrl feature is not supported
There could be two reasons why a resctrl feature might not be enabled on
the platform
1. H/W might not support the feature
2. Even if the H/W supports it, the user might have disabled the feature
through kernel command line arguments
Hence, any resctrl unit test (like cmt, cat, mbm and mba) before starting
the test will first check if the feature is enabled on the platform or not.
If the feature isn't enabled, then the test returns with an error status.
For example, if MBA isn't supported on a platform and if the user tries to
run MBA, the output will look like this
ok mounting resctrl to "/sys/fs/resctrl"
not ok MBA: schemata change
But, not supporting a feature isn't a test failure. So, instead of treating
it as an error, use the SKIP directive of the TAP protocol. With the
change, the output will look as below
ok MBA # SKIP Hardware does not support MBA or MBA is disabled
Suggested-by: Reinette Chatre <reinette.chatre@intel.com>
Tested-by: Babu Moger <babu.moger@amd.com>
Signed-off-by: Fenghua Yu <fenghua.yu@intel.com>
Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
2021-03-17 02:22:51 +00:00
|
|
|
}
|
|
|
|
|
2023-12-15 17:05:11 +02:00
|
|
|
ret = test->run_test(test, uparams);
|
|
|
|
ksft_test_result(!ret, "%s: test\n", test->name);
|
2023-07-17 16:14:54 +03:00
|
|
|
|
2023-10-02 12:48:08 +03:00
|
|
|
cleanup:
|
2024-02-27 08:21:43 +01:00
|
|
|
test_cleanup(test);
|
2021-03-17 02:22:50 +00:00
|
|
|
}
|
|
|
|
|
selftests/resctrl: Make benchmark parameter passing robust
The benchmark used during the CMT, MBM, and MBA tests can be provided by
the user via (-b) parameter, if not provided the default "fill_buf"
benchmark is used. The user is additionally able to override
any of the "fill_buf" default parameters when running the tests with
"-b fill_buf <fill_buf parameters>".
The "fill_buf" parameters are managed as an array of strings. Using an
array of strings is complex because it requires transformations to/from
strings at every producer and consumer. This is made worse for the
individual tests where the default benchmark parameters values may not
be appropriate and additional data wrangling is required. For example,
the CMT test duplicates the entire array of strings in order to replace
one of the parameters.
More issues appear when combining the usage of an array of strings with
the use case of user overriding default parameters by specifying
"-b fill_buf <parameters>". This use case is fragile with opportunities
to trigger a SIGSEGV because of opportunities for NULL pointers to exist
in the array of strings. For example, by running below (thus by specifying
"fill_buf" should be used but all parameters are NULL):
$ sudo resctrl_tests -t mbm -b fill_buf
Replace the "array of strings" parameters used for "fill_buf" with
new struct fill_buf_param that contains the "fill_buf" parameters that
can be used directly without transformations to/from strings. Two
instances of struct fill_buf_param may exist at any point in time:
* If the user provides new parameters to "fill_buf", the
user parameter structure (struct user_params) will point to a
fully initialized and immutable struct fill_buf_param
containing the user provided parameters.
* If "fill_buf" is the benchmark that should be used by a test,
then the test parameter structure (struct resctrl_val_param)
will point to a fully initialized struct fill_buf_param. The
latter may contain (a) the user provided parameters verbatim,
(b) user provided parameters adjusted to be appropriate for
the test, or (c) the default parameters for "fill_buf" that
is appropriate for the test if the user did not provide
"fill_buf" parameters nor an alternate benchmark.
The existing behavior of CMT test is to use test defined value for the
buffer size even if the user provides another value via command line.
This behavior is maintained since the test requires that the buffer size
matches the size of the cache allocated, and the amount of cache
allocated can instead be changed by the user with the "-n" command line
parameter.
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
2024-10-24 14:18:47 -07:00
|
|
|
/*
|
|
|
|
* Allocate and initialize a struct fill_buf_param with user provided
|
|
|
|
* (via "-b fill_buf <fill_buf parameters>") parameters.
|
|
|
|
*
|
|
|
|
* Use defaults (that may not be appropriate for all tests) for any
|
|
|
|
* fill_buf parameters omitted by the user.
|
|
|
|
*
|
|
|
|
* Historically it may have been possible for user space to provide
|
|
|
|
* additional parameters, "operation" ("read" vs "write") in
|
|
|
|
* benchmark_cmd[3] and "once" (run "once" or until terminated) in
|
|
|
|
* benchmark_cmd[4]. Changing these parameters have never been
|
|
|
|
* supported with the default of "read" operation and running until
|
|
|
|
* terminated built into the tests. Any unsupported values for
|
|
|
|
* (original) "fill_buf" parameters are treated as failure.
|
|
|
|
*
|
|
|
|
* Return: On failure, forcibly exits the test on any parsing failure,
|
|
|
|
* returns NULL if no parsing needed (user did not actually provide
|
|
|
|
* "-b fill_buf").
|
|
|
|
* On success, returns pointer to newly allocated and fully
|
|
|
|
* initialized struct fill_buf_param that caller must free.
|
|
|
|
*/
|
|
|
|
static struct fill_buf_param *alloc_fill_buf_param(struct user_params *uparams)
|
|
|
|
{
|
|
|
|
struct fill_buf_param *fill_param = NULL;
|
|
|
|
char *endptr = NULL;
|
|
|
|
|
|
|
|
if (!uparams->benchmark_cmd[0] || strcmp(uparams->benchmark_cmd[0], "fill_buf"))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
fill_param = malloc(sizeof(*fill_param));
|
|
|
|
if (!fill_param)
|
|
|
|
ksft_exit_skip("Unable to allocate memory for fill_buf parameters.\n");
|
|
|
|
|
|
|
|
if (uparams->benchmark_cmd[1] && *uparams->benchmark_cmd[1] != '\0') {
|
|
|
|
errno = 0;
|
|
|
|
fill_param->buf_size = strtoul(uparams->benchmark_cmd[1], &endptr, 10);
|
|
|
|
if (errno || *endptr != '\0') {
|
|
|
|
free(fill_param);
|
|
|
|
ksft_exit_skip("Unable to parse benchmark buffer size.\n");
|
|
|
|
}
|
|
|
|
} else {
|
2024-10-24 14:18:49 -07:00
|
|
|
fill_param->buf_size = MINIMUM_SPAN;
|
selftests/resctrl: Make benchmark parameter passing robust
The benchmark used during the CMT, MBM, and MBA tests can be provided by
the user via (-b) parameter, if not provided the default "fill_buf"
benchmark is used. The user is additionally able to override
any of the "fill_buf" default parameters when running the tests with
"-b fill_buf <fill_buf parameters>".
The "fill_buf" parameters are managed as an array of strings. Using an
array of strings is complex because it requires transformations to/from
strings at every producer and consumer. This is made worse for the
individual tests where the default benchmark parameters values may not
be appropriate and additional data wrangling is required. For example,
the CMT test duplicates the entire array of strings in order to replace
one of the parameters.
More issues appear when combining the usage of an array of strings with
the use case of user overriding default parameters by specifying
"-b fill_buf <parameters>". This use case is fragile with opportunities
to trigger a SIGSEGV because of opportunities for NULL pointers to exist
in the array of strings. For example, by running below (thus by specifying
"fill_buf" should be used but all parameters are NULL):
$ sudo resctrl_tests -t mbm -b fill_buf
Replace the "array of strings" parameters used for "fill_buf" with
new struct fill_buf_param that contains the "fill_buf" parameters that
can be used directly without transformations to/from strings. Two
instances of struct fill_buf_param may exist at any point in time:
* If the user provides new parameters to "fill_buf", the
user parameter structure (struct user_params) will point to a
fully initialized and immutable struct fill_buf_param
containing the user provided parameters.
* If "fill_buf" is the benchmark that should be used by a test,
then the test parameter structure (struct resctrl_val_param)
will point to a fully initialized struct fill_buf_param. The
latter may contain (a) the user provided parameters verbatim,
(b) user provided parameters adjusted to be appropriate for
the test, or (c) the default parameters for "fill_buf" that
is appropriate for the test if the user did not provide
"fill_buf" parameters nor an alternate benchmark.
The existing behavior of CMT test is to use test defined value for the
buffer size even if the user provides another value via command line.
This behavior is maintained since the test requires that the buffer size
matches the size of the cache allocated, and the amount of cache
allocated can instead be changed by the user with the "-n" command line
parameter.
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
2024-10-24 14:18:47 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (uparams->benchmark_cmd[2] && *uparams->benchmark_cmd[2] != '\0') {
|
|
|
|
errno = 0;
|
|
|
|
fill_param->memflush = strtol(uparams->benchmark_cmd[2], &endptr, 10) != 0;
|
|
|
|
if (errno || *endptr != '\0') {
|
|
|
|
free(fill_param);
|
|
|
|
ksft_exit_skip("Unable to parse benchmark memflush parameter.\n");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
fill_param->memflush = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (uparams->benchmark_cmd[3] && *uparams->benchmark_cmd[3] != '\0') {
|
|
|
|
if (strcmp(uparams->benchmark_cmd[3], "0")) {
|
|
|
|
free(fill_param);
|
|
|
|
ksft_exit_skip("Only read operations supported.\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (uparams->benchmark_cmd[4] && *uparams->benchmark_cmd[4] != '\0') {
|
|
|
|
if (strcmp(uparams->benchmark_cmd[4], "false")) {
|
|
|
|
free(fill_param);
|
|
|
|
ksft_exit_skip("fill_buf is required to run until termination.\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return fill_param;
|
|
|
|
}
|
|
|
|
|
2023-12-15 17:05:10 +02:00
|
|
|
static void init_user_params(struct user_params *uparams)
|
|
|
|
{
|
|
|
|
memset(uparams, 0, sizeof(*uparams));
|
|
|
|
|
|
|
|
uparams->cpu = 1;
|
|
|
|
uparams->bits = 0;
|
|
|
|
}
|
|
|
|
|
2020-01-16 13:32:39 -08:00
|
|
|
int main(int argc, char **argv)
|
|
|
|
{
|
selftests/resctrl: Make benchmark parameter passing robust
The benchmark used during the CMT, MBM, and MBA tests can be provided by
the user via (-b) parameter, if not provided the default "fill_buf"
benchmark is used. The user is additionally able to override
any of the "fill_buf" default parameters when running the tests with
"-b fill_buf <fill_buf parameters>".
The "fill_buf" parameters are managed as an array of strings. Using an
array of strings is complex because it requires transformations to/from
strings at every producer and consumer. This is made worse for the
individual tests where the default benchmark parameters values may not
be appropriate and additional data wrangling is required. For example,
the CMT test duplicates the entire array of strings in order to replace
one of the parameters.
More issues appear when combining the usage of an array of strings with
the use case of user overriding default parameters by specifying
"-b fill_buf <parameters>". This use case is fragile with opportunities
to trigger a SIGSEGV because of opportunities for NULL pointers to exist
in the array of strings. For example, by running below (thus by specifying
"fill_buf" should be used but all parameters are NULL):
$ sudo resctrl_tests -t mbm -b fill_buf
Replace the "array of strings" parameters used for "fill_buf" with
new struct fill_buf_param that contains the "fill_buf" parameters that
can be used directly without transformations to/from strings. Two
instances of struct fill_buf_param may exist at any point in time:
* If the user provides new parameters to "fill_buf", the
user parameter structure (struct user_params) will point to a
fully initialized and immutable struct fill_buf_param
containing the user provided parameters.
* If "fill_buf" is the benchmark that should be used by a test,
then the test parameter structure (struct resctrl_val_param)
will point to a fully initialized struct fill_buf_param. The
latter may contain (a) the user provided parameters verbatim,
(b) user provided parameters adjusted to be appropriate for
the test, or (c) the default parameters for "fill_buf" that
is appropriate for the test if the user did not provide
"fill_buf" parameters nor an alternate benchmark.
The existing behavior of CMT test is to use test defined value for the
buffer size even if the user provides another value via command line.
This behavior is maintained since the test requires that the buffer size
matches the size of the cache allocated, and the amount of cache
allocated can instead be changed by the user with the "-n" command line
parameter.
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
2024-10-24 14:18:47 -07:00
|
|
|
struct fill_buf_param *fill_param = NULL;
|
2023-12-15 17:05:11 +02:00
|
|
|
int tests = ARRAY_SIZE(resctrl_tests);
|
|
|
|
bool test_param_seen = false;
|
2023-12-15 17:05:10 +02:00
|
|
|
struct user_params uparams;
|
selftests/resctrl: Make benchmark parameter passing robust
The benchmark used during the CMT, MBM, and MBA tests can be provided by
the user via (-b) parameter, if not provided the default "fill_buf"
benchmark is used. The user is additionally able to override
any of the "fill_buf" default parameters when running the tests with
"-b fill_buf <fill_buf parameters>".
The "fill_buf" parameters are managed as an array of strings. Using an
array of strings is complex because it requires transformations to/from
strings at every producer and consumer. This is made worse for the
individual tests where the default benchmark parameters values may not
be appropriate and additional data wrangling is required. For example,
the CMT test duplicates the entire array of strings in order to replace
one of the parameters.
More issues appear when combining the usage of an array of strings with
the use case of user overriding default parameters by specifying
"-b fill_buf <parameters>". This use case is fragile with opportunities
to trigger a SIGSEGV because of opportunities for NULL pointers to exist
in the array of strings. For example, by running below (thus by specifying
"fill_buf" should be used but all parameters are NULL):
$ sudo resctrl_tests -t mbm -b fill_buf
Replace the "array of strings" parameters used for "fill_buf" with
new struct fill_buf_param that contains the "fill_buf" parameters that
can be used directly without transformations to/from strings. Two
instances of struct fill_buf_param may exist at any point in time:
* If the user provides new parameters to "fill_buf", the
user parameter structure (struct user_params) will point to a
fully initialized and immutable struct fill_buf_param
containing the user provided parameters.
* If "fill_buf" is the benchmark that should be used by a test,
then the test parameter structure (struct resctrl_val_param)
will point to a fully initialized struct fill_buf_param. The
latter may contain (a) the user provided parameters verbatim,
(b) user provided parameters adjusted to be appropriate for
the test, or (c) the default parameters for "fill_buf" that
is appropriate for the test if the user did not provide
"fill_buf" parameters nor an alternate benchmark.
The existing behavior of CMT test is to use test defined value for the
buffer size even if the user provides another value via command line.
This behavior is maintained since the test requires that the buffer size
matches the size of the cache allocated, and the amount of cache
allocated can instead be changed by the user with the "-n" command line
parameter.
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
2024-10-24 14:18:47 -07:00
|
|
|
int c, i;
|
2023-12-15 17:05:10 +02:00
|
|
|
|
|
|
|
init_user_params(&uparams);
|
2020-01-16 13:32:39 -08:00
|
|
|
|
2023-09-04 12:53:39 +03:00
|
|
|
while ((c = getopt(argc, argv, "ht:b:n:p:")) != -1) {
|
2020-01-16 13:32:39 -08:00
|
|
|
char *token;
|
|
|
|
|
|
|
|
switch (c) {
|
2023-09-04 12:53:39 +03:00
|
|
|
case 'b':
|
|
|
|
/*
|
|
|
|
* First move optind back to the (first) optarg and
|
|
|
|
* then build the benchmark command using the
|
|
|
|
* remaining arguments.
|
|
|
|
*/
|
|
|
|
optind--;
|
|
|
|
if (argc - optind >= BENCHMARK_ARGS)
|
|
|
|
ksft_exit_fail_msg("Too long benchmark command");
|
|
|
|
|
|
|
|
/* Extract benchmark command from command line. */
|
|
|
|
for (i = 0; i < argc - optind; i++)
|
2023-12-15 17:05:10 +02:00
|
|
|
uparams.benchmark_cmd[i] = argv[i + optind];
|
|
|
|
uparams.benchmark_cmd[i] = NULL;
|
2023-09-04 12:53:39 +03:00
|
|
|
|
|
|
|
goto last_arg;
|
2020-01-16 13:32:39 -08:00
|
|
|
case 't':
|
|
|
|
token = strtok(optarg, ",");
|
|
|
|
|
2023-12-15 17:05:11 +02:00
|
|
|
if (!test_param_seen) {
|
|
|
|
for (i = 0; i < ARRAY_SIZE(resctrl_tests); i++)
|
|
|
|
resctrl_tests[i]->disabled = true;
|
|
|
|
tests = 0;
|
|
|
|
test_param_seen = true;
|
|
|
|
}
|
2020-01-16 13:32:39 -08:00
|
|
|
while (token) {
|
2023-12-15 17:05:11 +02:00
|
|
|
bool found = false;
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(resctrl_tests); i++) {
|
2024-02-16 09:34:56 +01:00
|
|
|
if (!strcasecmp(token, resctrl_tests[i]->name) ||
|
|
|
|
(resctrl_tests[i]->group &&
|
|
|
|
!strcasecmp(token, resctrl_tests[i]->group))) {
|
2023-12-15 17:05:11 +02:00
|
|
|
if (resctrl_tests[i]->disabled)
|
|
|
|
tests++;
|
|
|
|
resctrl_tests[i]->disabled = false;
|
|
|
|
found = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!found) {
|
|
|
|
printf("invalid test: %s\n", token);
|
2020-01-16 13:32:39 -08:00
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
selftests/resctrl: Fix incorrect parsing of option "-t"
Resctrl test suite accepts command line argument "-t" to specify the
unit tests to run in the test list (e.g., -t mbm,mba,cmt,cat) as
documented in the help.
When calling strtok() to parse the option, the incorrect delimiters
argument ":\t" is used. As a result, passing "-t mbm,mba,cmt,cat" throws
an invalid option error.
Fix this by using delimiters argument "," instead of ":\t" for parsing
of unit tests list. At the same time, remove the unnecessary "spaces"
between the unit tests in help documentation to prevent confusion.
Fixes: 790bf585b0ee ("selftests/resctrl: Add Cache Allocation Technology (CAT) selftest")
Fixes: 78941183d1b1 ("selftests/resctrl: Add Cache QoS Monitoring (CQM) selftest")
Fixes: ecdbb911f22d ("selftests/resctrl: Add MBM test")
Fixes: 034c7678dd2c ("selftests/resctrl: Add README for resctrl tests")
Cc: stable@vger.kernel.org
Signed-off-by: Xiaochen Shen <xiaochen.shen@intel.com>
Reviewed-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
2021-05-27 17:31:53 +08:00
|
|
|
token = strtok(NULL, ",");
|
2020-01-16 13:32:39 -08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'p':
|
2023-12-15 17:05:10 +02:00
|
|
|
uparams.cpu = atoi(optarg);
|
2020-01-16 13:32:39 -08:00
|
|
|
break;
|
2020-01-16 13:32:41 -08:00
|
|
|
case 'n':
|
2023-12-15 17:05:10 +02:00
|
|
|
uparams.bits = atoi(optarg);
|
|
|
|
if (uparams.bits <= 0) {
|
2021-03-17 02:22:49 +00:00
|
|
|
printf("Bail out! invalid argument for no_of_bits\n");
|
|
|
|
return -1;
|
|
|
|
}
|
2020-01-16 13:32:41 -08:00
|
|
|
break;
|
2020-01-16 13:32:39 -08:00
|
|
|
case 'h':
|
|
|
|
cmd_help();
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
default:
|
|
|
|
printf("invalid argument\n");
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
2023-09-04 12:53:39 +03:00
|
|
|
last_arg:
|
2020-01-16 13:32:39 -08:00
|
|
|
|
selftests/resctrl: Make benchmark parameter passing robust
The benchmark used during the CMT, MBM, and MBA tests can be provided by
the user via (-b) parameter, if not provided the default "fill_buf"
benchmark is used. The user is additionally able to override
any of the "fill_buf" default parameters when running the tests with
"-b fill_buf <fill_buf parameters>".
The "fill_buf" parameters are managed as an array of strings. Using an
array of strings is complex because it requires transformations to/from
strings at every producer and consumer. This is made worse for the
individual tests where the default benchmark parameters values may not
be appropriate and additional data wrangling is required. For example,
the CMT test duplicates the entire array of strings in order to replace
one of the parameters.
More issues appear when combining the usage of an array of strings with
the use case of user overriding default parameters by specifying
"-b fill_buf <parameters>". This use case is fragile with opportunities
to trigger a SIGSEGV because of opportunities for NULL pointers to exist
in the array of strings. For example, by running below (thus by specifying
"fill_buf" should be used but all parameters are NULL):
$ sudo resctrl_tests -t mbm -b fill_buf
Replace the "array of strings" parameters used for "fill_buf" with
new struct fill_buf_param that contains the "fill_buf" parameters that
can be used directly without transformations to/from strings. Two
instances of struct fill_buf_param may exist at any point in time:
* If the user provides new parameters to "fill_buf", the
user parameter structure (struct user_params) will point to a
fully initialized and immutable struct fill_buf_param
containing the user provided parameters.
* If "fill_buf" is the benchmark that should be used by a test,
then the test parameter structure (struct resctrl_val_param)
will point to a fully initialized struct fill_buf_param. The
latter may contain (a) the user provided parameters verbatim,
(b) user provided parameters adjusted to be appropriate for
the test, or (c) the default parameters for "fill_buf" that
is appropriate for the test if the user did not provide
"fill_buf" parameters nor an alternate benchmark.
The existing behavior of CMT test is to use test defined value for the
buffer size even if the user provides another value via command line.
This behavior is maintained since the test requires that the buffer size
matches the size of the cache allocated, and the amount of cache
allocated can instead be changed by the user with the "-n" command line
parameter.
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
2024-10-24 14:18:47 -07:00
|
|
|
fill_param = alloc_fill_buf_param(&uparams);
|
|
|
|
if (fill_param)
|
|
|
|
uparams.fill_buf = fill_param;
|
|
|
|
|
2021-03-17 02:22:42 +00:00
|
|
|
ksft_print_header();
|
2020-01-16 13:32:39 -08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Typically we need root privileges, because:
|
|
|
|
* 1. We write to resctrl FS
|
|
|
|
* 2. We execute perf commands
|
|
|
|
*/
|
|
|
|
if (geteuid() != 0)
|
2024-04-24 10:24:09 -07:00
|
|
|
ksft_exit_skip("Not running as root. Skipping...\n");
|
2020-01-16 13:32:39 -08:00
|
|
|
|
2023-09-04 12:53:36 +03:00
|
|
|
if (!check_resctrlfs_support())
|
2024-04-24 10:24:09 -07:00
|
|
|
ksft_exit_skip("resctrl FS does not exist. Enable X86_CPU_RESCTRL config option.\n");
|
2023-09-04 12:53:36 +03:00
|
|
|
|
|
|
|
if (umount_resctrlfs())
|
2024-04-24 10:24:09 -07:00
|
|
|
ksft_exit_skip("resctrl FS unmount failed.\n");
|
2023-09-04 12:53:36 +03:00
|
|
|
|
|
|
|
filter_dmesg();
|
|
|
|
|
2023-12-15 17:05:11 +02:00
|
|
|
ksft_set_plan(tests);
|
2020-01-16 13:32:41 -08:00
|
|
|
|
2023-12-15 17:05:11 +02:00
|
|
|
for (i = 0; i < ARRAY_SIZE(resctrl_tests); i++)
|
|
|
|
run_single_test(resctrl_tests[i], &uparams);
|
2020-01-16 13:32:42 -08:00
|
|
|
|
selftests/resctrl: Make benchmark parameter passing robust
The benchmark used during the CMT, MBM, and MBA tests can be provided by
the user via (-b) parameter, if not provided the default "fill_buf"
benchmark is used. The user is additionally able to override
any of the "fill_buf" default parameters when running the tests with
"-b fill_buf <fill_buf parameters>".
The "fill_buf" parameters are managed as an array of strings. Using an
array of strings is complex because it requires transformations to/from
strings at every producer and consumer. This is made worse for the
individual tests where the default benchmark parameters values may not
be appropriate and additional data wrangling is required. For example,
the CMT test duplicates the entire array of strings in order to replace
one of the parameters.
More issues appear when combining the usage of an array of strings with
the use case of user overriding default parameters by specifying
"-b fill_buf <parameters>". This use case is fragile with opportunities
to trigger a SIGSEGV because of opportunities for NULL pointers to exist
in the array of strings. For example, by running below (thus by specifying
"fill_buf" should be used but all parameters are NULL):
$ sudo resctrl_tests -t mbm -b fill_buf
Replace the "array of strings" parameters used for "fill_buf" with
new struct fill_buf_param that contains the "fill_buf" parameters that
can be used directly without transformations to/from strings. Two
instances of struct fill_buf_param may exist at any point in time:
* If the user provides new parameters to "fill_buf", the
user parameter structure (struct user_params) will point to a
fully initialized and immutable struct fill_buf_param
containing the user provided parameters.
* If "fill_buf" is the benchmark that should be used by a test,
then the test parameter structure (struct resctrl_val_param)
will point to a fully initialized struct fill_buf_param. The
latter may contain (a) the user provided parameters verbatim,
(b) user provided parameters adjusted to be appropriate for
the test, or (c) the default parameters for "fill_buf" that
is appropriate for the test if the user did not provide
"fill_buf" parameters nor an alternate benchmark.
The existing behavior of CMT test is to use test defined value for the
buffer size even if the user provides another value via command line.
This behavior is maintained since the test requires that the buffer size
matches the size of the cache allocated, and the amount of cache
allocated can instead be changed by the user with the "-n" command line
parameter.
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
2024-10-24 14:18:47 -07:00
|
|
|
free(fill_param);
|
2023-03-09 15:57:57 +01:00
|
|
|
ksft_finished();
|
2020-01-16 13:32:39 -08:00
|
|
|
}
|