From a84a0c6a6d40b73f01033249ebe45c9484558539 Mon Sep 17 00:00:00 2001 From: John Hubbard Date: Fri, 31 May 2024 11:37:51 -0700 Subject: selftests/lib.mk: silence some clang warnings that gcc already ignores gcc defaults to silence (off) for the following warnings, but clang defaults to the opposite. The warnings are not useful for the kernel itself, which is why they have remained disabled in gcc for the main kernel build. And it is only due to including kernel data structures in the selftests, that we get the warnings from clang. -Waddress-of-packed-member -Wgnu-variable-sized-type-not-at-end In other words, the warnings are not unique to the selftests: there is nothing that the selftests' code does that triggers these warnings, other than the act of including the kernel's data structures. Therefore, silence them for the clang builds as well. This eliminates warnings for the net/ and user_events/ kselftest subsystems, in these files: ./net/af_unix/scm_rights.c ./net/timestamping.c ./net/ipsec.c ./user_events/perf_test.c Cc: Nathan Chancellor Signed-off-by: John Hubbard Acked-by: Nathan Chancellor Signed-off-by: Shuah Khan --- tools/testing/selftests/lib.mk | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tools/testing/selftests/lib.mk b/tools/testing/selftests/lib.mk index 429535816dbd..7b299ed5ff45 100644 --- a/tools/testing/selftests/lib.mk +++ b/tools/testing/selftests/lib.mk @@ -38,6 +38,14 @@ else CLANG_FLAGS += --target=$(notdir $(CROSS_COMPILE:%-=%)) endif # CROSS_COMPILE +# gcc defaults to silence (off) for the following warnings, but clang defaults +# to the opposite. The warnings are not useful for the kernel itself, which is +# why they have remained disabled in gcc for the main kernel build. And it is +# only due to including kernel data structures in the selftests, that we get the +# warnings from clang. Therefore, disable the warnings for clang builds. +CFLAGS += -Wno-address-of-packed-member +CFLAGS += -Wno-gnu-variable-sized-type-not-at-end + CC := $(CLANG) $(CLANG_FLAGS) -fintegrated-as else CC := $(CROSS_COMPILE)gcc -- cgit v1.2.3-58-ga151 From b47619a3a3f79f75edf774275798aad1a37609ad Mon Sep 17 00:00:00 2001 From: aigourensheng Date: Tue, 11 Jun 2024 01:18:34 -0400 Subject: selftests/sched: fix code format issues There are extra spaces in the middle of #define. It is recommended to delete the spaces to make the code look more comfortable. Signed-off-by: aigourensheng Signed-off-by: Shuah Khan --- tools/testing/selftests/sched/cs_prctl_test.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/testing/selftests/sched/cs_prctl_test.c b/tools/testing/selftests/sched/cs_prctl_test.c index 62fba7356af2..52d97fae4dbd 100644 --- a/tools/testing/selftests/sched/cs_prctl_test.c +++ b/tools/testing/selftests/sched/cs_prctl_test.c @@ -42,11 +42,11 @@ static pid_t gettid(void) #ifndef PR_SCHED_CORE #define PR_SCHED_CORE 62 -# define PR_SCHED_CORE_GET 0 -# define PR_SCHED_CORE_CREATE 1 /* create unique core_sched cookie */ -# define PR_SCHED_CORE_SHARE_TO 2 /* push core_sched cookie to pid */ -# define PR_SCHED_CORE_SHARE_FROM 3 /* pull core_sched cookie to pid */ -# define PR_SCHED_CORE_MAX 4 +#define PR_SCHED_CORE_GET 0 +#define PR_SCHED_CORE_CREATE 1 /* create unique core_sched cookie */ +#define PR_SCHED_CORE_SHARE_TO 2 /* push core_sched cookie to pid */ +#define PR_SCHED_CORE_SHARE_FROM 3 /* pull core_sched cookie to pid */ +#define PR_SCHED_CORE_MAX 4 #endif #define MAX_PROCESSES 128 -- cgit v1.2.3-58-ga151 From c44000b6535dc9806b9128d1aed403862b2adab9 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 10 Jun 2024 18:14:42 +0300 Subject: selftests/resctrl: Fix closing IMC fds on error and open-code R+W instead of loops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The imc perf fd close() calls are missing from all error paths. In addition, get_mem_bw_imc() handles fds in a for loop but close() is based on two fixed indexes READ and WRITE. Open code inner for loops to READ+WRITE entries for clarity and add a function to close() IMC fds properly in all cases. Fixes: 7f4d257e3a2a ("selftests/resctrl: Add callback to start a benchmark") Suggested-by: Reinette Chatre Signed-off-by: Ilpo Järvinen Tested-by: Babu Moger Reviewed-by: Reinette Chatre Signed-off-by: Shuah Khan --- tools/testing/selftests/resctrl/resctrl_val.c | 54 ++++++++++++++++++--------- 1 file changed, 36 insertions(+), 18 deletions(-) diff --git a/tools/testing/selftests/resctrl/resctrl_val.c b/tools/testing/selftests/resctrl/resctrl_val.c index 445f306d4c2f..f55f5989de72 100644 --- a/tools/testing/selftests/resctrl/resctrl_val.c +++ b/tools/testing/selftests/resctrl/resctrl_val.c @@ -293,6 +293,18 @@ static int initialize_mem_bw_imc(void) return 0; } +static void perf_close_imc_mem_bw(void) +{ + int mc; + + for (mc = 0; mc < imcs; mc++) { + if (imc_counters_config[mc][READ].fd != -1) + close(imc_counters_config[mc][READ].fd); + if (imc_counters_config[mc][WRITE].fd != -1) + close(imc_counters_config[mc][WRITE].fd); + } +} + /* * get_mem_bw_imc: Memory band width as reported by iMC counters * @cpu_no: CPU number that the benchmark PID is binded to @@ -306,26 +318,33 @@ static int initialize_mem_bw_imc(void) static int get_mem_bw_imc(int cpu_no, char *bw_report, float *bw_imc) { float reads, writes, of_mul_read, of_mul_write; - int imc, j, ret; + int imc, ret; + + for (imc = 0; imc < imcs; imc++) { + imc_counters_config[imc][READ].fd = -1; + imc_counters_config[imc][WRITE].fd = -1; + } /* Start all iMC counters to log values (both read and write) */ reads = 0, writes = 0, of_mul_read = 1, of_mul_write = 1; for (imc = 0; imc < imcs; imc++) { - for (j = 0; j < 2; j++) { - ret = open_perf_event(imc, cpu_no, j); - if (ret) - return -1; - } - for (j = 0; j < 2; j++) - membw_ioctl_perf_event_ioc_reset_enable(imc, j); + ret = open_perf_event(imc, cpu_no, READ); + if (ret) + goto close_fds; + ret = open_perf_event(imc, cpu_no, WRITE); + if (ret) + goto close_fds; + + membw_ioctl_perf_event_ioc_reset_enable(imc, READ); + membw_ioctl_perf_event_ioc_reset_enable(imc, WRITE); } sleep(1); /* Stop counters after a second to get results (both read and write) */ for (imc = 0; imc < imcs; imc++) { - for (j = 0; j < 2; j++) - membw_ioctl_perf_event_ioc_disable(imc, j); + membw_ioctl_perf_event_ioc_disable(imc, READ); + membw_ioctl_perf_event_ioc_disable(imc, WRITE); } /* @@ -341,15 +360,13 @@ static int get_mem_bw_imc(int cpu_no, char *bw_report, float *bw_imc) if (read(r->fd, &r->return_value, sizeof(struct membw_read_format)) == -1) { ksft_perror("Couldn't get read b/w through iMC"); - - return -1; + goto close_fds; } if (read(w->fd, &w->return_value, sizeof(struct membw_read_format)) == -1) { ksft_perror("Couldn't get write bw through iMC"); - - return -1; + goto close_fds; } __u64 r_time_enabled = r->return_value.time_enabled; @@ -369,10 +386,7 @@ static int get_mem_bw_imc(int cpu_no, char *bw_report, float *bw_imc) writes += w->return_value.value * of_mul_write * SCALE; } - for (imc = 0; imc < imcs; imc++) { - close(imc_counters_config[imc][READ].fd); - close(imc_counters_config[imc][WRITE].fd); - } + perf_close_imc_mem_bw(); if (strcmp(bw_report, "reads") == 0) { *bw_imc = reads; @@ -386,6 +400,10 @@ static int get_mem_bw_imc(int cpu_no, char *bw_report, float *bw_imc) *bw_imc = reads + writes; return 0; + +close_fds: + perf_close_imc_mem_bw(); + return -1; } void set_mbm_path(const char *ctrlgrp, const char *mongrp, int domain_id) -- cgit v1.2.3-58-ga151 From da50de0a92f31605423e39e6ccf3ce7508e88a7a Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 10 Jun 2024 18:14:43 +0300 Subject: selftests/resctrl: Calculate resctrl FS derived mem bw over sleep(1) only MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For MBM/MBA tests, measure_vals() calls get_mem_bw_imc() that performs the measurement over a duration of sleep(1) call. The memory bandwidth numbers from IMC are derived over this duration. The resctrl FS derived memory bandwidth, however, is calculated inside measure_vals() and only takes delta between the previous value and the current one which besides the actual test, also samples inter-test noise. Rework the logic in measure_vals() and get_mem_bw_imc() such that the resctrl FS memory bandwidth section covers much shorter duration closely matching that of the IMC perf counters to improve measurement accuracy. For the second read after rewind() to return a fresh value, also newline has to be consumed by the fscanf(). Suggested-by: Reinette Chatre Signed-off-by: Ilpo Järvinen Tested-by: Babu Moger Reviewed-by: Reinette Chatre Signed-off-by: Shuah Khan --- tools/testing/selftests/resctrl/resctrl_val.c | 141 +++++++++++++++++--------- 1 file changed, 91 insertions(+), 50 deletions(-) diff --git a/tools/testing/selftests/resctrl/resctrl_val.c b/tools/testing/selftests/resctrl/resctrl_val.c index f55f5989de72..3c7f6793c261 100644 --- a/tools/testing/selftests/resctrl/resctrl_val.c +++ b/tools/testing/selftests/resctrl/resctrl_val.c @@ -306,18 +306,13 @@ static void perf_close_imc_mem_bw(void) } /* - * get_mem_bw_imc: Memory band width as reported by iMC counters - * @cpu_no: CPU number that the benchmark PID is binded to - * @bw_report: Bandwidth report type (reads, writes) - * - * Memory B/W utilized by a process on a socket can be calculated using - * iMC counters. Perf events are used to read these counters. + * perf_open_imc_mem_bw - Open perf fds for IMCs + * @cpu_no: CPU number that the benchmark PID is bound to * * Return: = 0 on success. < 0 on failure. */ -static int get_mem_bw_imc(int cpu_no, char *bw_report, float *bw_imc) +static int perf_open_imc_mem_bw(int cpu_no) { - float reads, writes, of_mul_read, of_mul_write; int imc, ret; for (imc = 0; imc < imcs; imc++) { @@ -325,8 +320,6 @@ static int get_mem_bw_imc(int cpu_no, char *bw_report, float *bw_imc) imc_counters_config[imc][WRITE].fd = -1; } - /* Start all iMC counters to log values (both read and write) */ - reads = 0, writes = 0, of_mul_read = 1, of_mul_write = 1; for (imc = 0; imc < imcs; imc++) { ret = open_perf_event(imc, cpu_no, READ); if (ret) @@ -334,7 +327,26 @@ static int get_mem_bw_imc(int cpu_no, char *bw_report, float *bw_imc) ret = open_perf_event(imc, cpu_no, WRITE); if (ret) goto close_fds; + } + + return 0; +close_fds: + perf_close_imc_mem_bw(); + return -1; +} + +/* + * do_mem_bw_test - Perform memory bandwidth test + * + * Runs memory bandwidth test over one second period. Also, handles starting + * and stopping of the IMC perf counters around the test. + */ +static void do_imc_mem_bw_test(void) +{ + int imc; + + for (imc = 0; imc < imcs; imc++) { membw_ioctl_perf_event_ioc_reset_enable(imc, READ); membw_ioctl_perf_event_ioc_reset_enable(imc, WRITE); } @@ -346,6 +358,24 @@ static int get_mem_bw_imc(int cpu_no, char *bw_report, float *bw_imc) membw_ioctl_perf_event_ioc_disable(imc, READ); membw_ioctl_perf_event_ioc_disable(imc, WRITE); } +} + +/* + * get_mem_bw_imc - Memory band width as reported by iMC counters + * @bw_report: Bandwidth report type (reads, writes) + * + * Memory B/W utilized by a process on a socket can be calculated using + * iMC counters. Perf events are used to read these counters. + * + * Return: = 0 on success. < 0 on failure. + */ +static int get_mem_bw_imc(char *bw_report, float *bw_imc) +{ + float reads, writes, of_mul_read, of_mul_write; + int imc; + + /* Start all iMC counters to log values (both read and write) */ + reads = 0, writes = 0, of_mul_read = 1, of_mul_write = 1; /* * Get results which are stored in struct type imc_counter_config @@ -360,13 +390,13 @@ static int get_mem_bw_imc(int cpu_no, char *bw_report, float *bw_imc) if (read(r->fd, &r->return_value, sizeof(struct membw_read_format)) == -1) { ksft_perror("Couldn't get read b/w through iMC"); - goto close_fds; + return -1; } if (read(w->fd, &w->return_value, sizeof(struct membw_read_format)) == -1) { ksft_perror("Couldn't get write bw through iMC"); - goto close_fds; + return -1; } __u64 r_time_enabled = r->return_value.time_enabled; @@ -386,8 +416,6 @@ static int get_mem_bw_imc(int cpu_no, char *bw_report, float *bw_imc) writes += w->return_value.value * of_mul_write * SCALE; } - perf_close_imc_mem_bw(); - if (strcmp(bw_report, "reads") == 0) { *bw_imc = reads; return 0; @@ -400,10 +428,6 @@ static int get_mem_bw_imc(int cpu_no, char *bw_report, float *bw_imc) *bw_imc = reads + writes; return 0; - -close_fds: - perf_close_imc_mem_bw(); - return -1; } void set_mbm_path(const char *ctrlgrp, const char *mongrp, int domain_id) @@ -462,24 +486,23 @@ static void initialize_mem_bw_resctrl(const char *ctrlgrp, const char *mongrp, * 1. If con_mon grp is given, then read from it * 2. If con_mon grp is not given, then read from root con_mon grp */ -static int get_mem_bw_resctrl(unsigned long *mbm_total) +static FILE *open_mem_bw_resctrl(const char *mbm_bw_file) { FILE *fp; - fp = fopen(mbm_total_path, "r"); - if (!fp) { + fp = fopen(mbm_bw_file, "r"); + if (!fp) ksft_perror("Failed to open total bw file"); - return -1; - } - if (fscanf(fp, "%lu", mbm_total) <= 0) { - ksft_perror("Could not get mbm local bytes"); - fclose(fp); + return fp; +} +static int get_mem_bw_resctrl(FILE *fp, unsigned long *mbm_total) +{ + if (fscanf(fp, "%lu\n", mbm_total) <= 0) { + ksft_perror("Could not get MBM local bytes"); return -1; } - fclose(fp); - return 0; } @@ -615,37 +638,56 @@ static void initialize_llc_occu_resctrl(const char *ctrlgrp, const char *mongrp, set_cmt_path(ctrlgrp, mongrp, domain_id); } +/* + * Measure memory bandwidth from resctrl and from another source which is + * perf imc value or could be something else if perf imc event is not + * available. Compare the two values to validate resctrl value. It takes + * 1 sec to measure the data. + */ static int measure_vals(const struct user_params *uparams, - struct resctrl_val_param *param, - unsigned long *bw_resc_start) + struct resctrl_val_param *param) { - unsigned long bw_resc, bw_resc_end; + unsigned long bw_resc, bw_resc_start, bw_resc_end; + FILE *mem_bw_fp; float bw_imc; int ret; - /* - * Measure memory bandwidth from resctrl and from - * another source which is perf imc value or could - * be something else if perf imc event is not available. - * Compare the two values to validate resctrl value. - * It takes 1sec to measure the data. - */ - ret = get_mem_bw_imc(uparams->cpu, param->bw_report, &bw_imc); + mem_bw_fp = open_mem_bw_resctrl(mbm_total_path); + if (!mem_bw_fp) + return -1; + + ret = perf_open_imc_mem_bw(uparams->cpu); if (ret < 0) - return ret; + goto close_fp; - ret = get_mem_bw_resctrl(&bw_resc_end); + ret = get_mem_bw_resctrl(mem_bw_fp, &bw_resc_start); if (ret < 0) - return ret; + goto close_imc; - bw_resc = (bw_resc_end - *bw_resc_start) / MB; - ret = print_results_bw(param->filename, bm_pid, bw_imc, bw_resc); - if (ret) - return ret; + rewind(mem_bw_fp); - *bw_resc_start = bw_resc_end; + do_imc_mem_bw_test(); - return 0; + ret = get_mem_bw_resctrl(mem_bw_fp, &bw_resc_end); + if (ret < 0) + goto close_imc; + + ret = get_mem_bw_imc(param->bw_report, &bw_imc); + if (ret < 0) + goto close_imc; + + perf_close_imc_mem_bw(); + fclose(mem_bw_fp); + + bw_resc = (bw_resc_end - bw_resc_start) / MB; + + return print_results_bw(param->filename, bm_pid, bw_imc, bw_resc); + +close_imc: + perf_close_imc_mem_bw(); +close_fp: + fclose(mem_bw_fp); + return ret; } /* @@ -719,7 +761,6 @@ int resctrl_val(const struct resctrl_test *test, struct resctrl_val_param *param) { char *resctrl_val = param->resctrl_val; - unsigned long bw_resc_start = 0; struct sigaction sigact; int ret = 0, pipefd[2]; char pipe_message = 0; @@ -861,7 +902,7 @@ int resctrl_val(const struct resctrl_test *test, if (!strncmp(resctrl_val, MBM_STR, sizeof(MBM_STR)) || !strncmp(resctrl_val, MBA_STR, sizeof(MBA_STR))) { - ret = measure_vals(uparams, param, &bw_resc_start); + ret = measure_vals(uparams, param); if (ret) break; } else if (!strncmp(resctrl_val, CMT_STR, sizeof(CMT_STR))) { -- cgit v1.2.3-58-ga151 From 2704b2d117c52cd156bcdcad1eefd9c2dad1794d Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 10 Jun 2024 18:14:44 +0300 Subject: selftests/resctrl: Make "bandwidth" consistent in comments & prints MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resctrl selftests refer to "bandwidth" currently in two other forms in the code ("B/W" and "band width"). Use "bandwidth" consistently everywhere. While at it, fix also one "over flow" -> "overflow" on a line that is touched by the change. Suggested-by: Reinette Chatre Signed-off-by: Ilpo Järvinen Tested-by: Babu Moger Reviewed-by: Reinette Chatre Signed-off-by: Shuah Khan --- tools/testing/selftests/resctrl/resctrl_val.c | 14 +++++++------- tools/testing/selftests/resctrl/resctrlfs.c | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tools/testing/selftests/resctrl/resctrl_val.c b/tools/testing/selftests/resctrl/resctrl_val.c index 3c7f6793c261..5fad7e757af3 100644 --- a/tools/testing/selftests/resctrl/resctrl_val.c +++ b/tools/testing/selftests/resctrl/resctrl_val.c @@ -361,11 +361,11 @@ static void do_imc_mem_bw_test(void) } /* - * get_mem_bw_imc - Memory band width as reported by iMC counters + * get_mem_bw_imc - Memory bandwidth as reported by iMC counters * @bw_report: Bandwidth report type (reads, writes) * - * Memory B/W utilized by a process on a socket can be calculated using - * iMC counters. Perf events are used to read these counters. + * Memory bandwidth utilized by a process on a socket can be calculated + * using iMC counters. Perf events are used to read these counters. * * Return: = 0 on success. < 0 on failure. */ @@ -379,7 +379,7 @@ static int get_mem_bw_imc(char *bw_report, float *bw_imc) /* * Get results which are stored in struct type imc_counter_config - * Take over flow into consideration before calculating total b/w + * Take overflow into consideration before calculating total bandwidth. */ for (imc = 0; imc < imcs; imc++) { struct imc_counter_config *r = @@ -389,13 +389,13 @@ static int get_mem_bw_imc(char *bw_report, float *bw_imc) if (read(r->fd, &r->return_value, sizeof(struct membw_read_format)) == -1) { - ksft_perror("Couldn't get read b/w through iMC"); + ksft_perror("Couldn't get read bandwidth through iMC"); return -1; } if (read(w->fd, &w->return_value, sizeof(struct membw_read_format)) == -1) { - ksft_perror("Couldn't get write bw through iMC"); + ksft_perror("Couldn't get write bandwidth through iMC"); return -1; } @@ -492,7 +492,7 @@ static FILE *open_mem_bw_resctrl(const char *mbm_bw_file) fp = fopen(mbm_bw_file, "r"); if (!fp) - ksft_perror("Failed to open total bw file"); + ksft_perror("Failed to open total memory bandwidth file"); return fp; } diff --git a/tools/testing/selftests/resctrl/resctrlfs.c b/tools/testing/selftests/resctrl/resctrlfs.c index 1cade75176eb..9b86f826a40c 100644 --- a/tools/testing/selftests/resctrl/resctrlfs.c +++ b/tools/testing/selftests/resctrl/resctrlfs.c @@ -850,7 +850,7 @@ int validate_bw_report_request(char *bw_report) if (strcmp(bw_report, "total") == 0) return 0; - fprintf(stderr, "Requested iMC B/W report type unavailable\n"); + fprintf(stderr, "Requested iMC bandwidth report type unavailable\n"); return -1; } -- cgit v1.2.3-58-ga151 From 9224db5180f244f169fb81a3c88c48bf612ba238 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 10 Jun 2024 18:14:45 +0300 Subject: selftests/resctrl: Consolidate get_domain_id() into resctrl_val() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both initialize_mem_bw_resctrl() and initialize_llc_occu_resctrl() that are called from resctrl_val() need to determine domain ID to construct resctrl fs related paths. Both functions do it by taking CPU ID which neither needs for any other purpose than determining the domain ID. Consolidate determining the domain ID into resctrl_val() and pass the domain ID instead of CPU ID to initialize_mem_bw_resctrl() and initialize_llc_occu_resctrl(). Signed-off-by: Ilpo Järvinen Tested-by: Babu Moger Reviewed-by: Reinette Chatre Signed-off-by: Shuah Khan --- tools/testing/selftests/resctrl/resctrl_val.c | 33 +++++++++++---------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/tools/testing/selftests/resctrl/resctrl_val.c b/tools/testing/selftests/resctrl/resctrl_val.c index 5fad7e757af3..cccf6b80f3f3 100644 --- a/tools/testing/selftests/resctrl/resctrl_val.c +++ b/tools/testing/selftests/resctrl/resctrl_val.c @@ -450,19 +450,12 @@ void set_mbm_path(const char *ctrlgrp, const char *mongrp, int domain_id) * initialize_mem_bw_resctrl: Appropriately populate "mbm_total_path" * @ctrlgrp: Name of the control monitor group (con_mon grp) * @mongrp: Name of the monitor group (mon grp) - * @cpu_no: CPU number that the benchmark PID is binded to + * @domain_id: Domain ID (cache ID; for MB, L3 cache ID) * @resctrl_val: Resctrl feature (Eg: mbm, mba.. etc) */ static void initialize_mem_bw_resctrl(const char *ctrlgrp, const char *mongrp, - int cpu_no, char *resctrl_val) + int domain_id, char *resctrl_val) { - int domain_id; - - if (get_domain_id("MB", cpu_no, &domain_id) < 0) { - ksft_print_msg("Could not get domain ID\n"); - return; - } - if (!strncmp(resctrl_val, MBM_STR, sizeof(MBM_STR))) set_mbm_path(ctrlgrp, mongrp, domain_id); @@ -621,19 +614,12 @@ static void set_cmt_path(const char *ctrlgrp, const char *mongrp, char sock_num) * initialize_llc_occu_resctrl: Appropriately populate "llc_occup_path" * @ctrlgrp: Name of the control monitor group (con_mon grp) * @mongrp: Name of the monitor group (mon grp) - * @cpu_no: CPU number that the benchmark PID is binded to + * @domain_id: Domain ID (cache ID; for MB, L3 cache ID) * @resctrl_val: Resctrl feature (Eg: cat, cmt.. etc) */ static void initialize_llc_occu_resctrl(const char *ctrlgrp, const char *mongrp, - int cpu_no, char *resctrl_val) + int domain_id, char *resctrl_val) { - int domain_id; - - if (get_domain_id("L3", cpu_no, &domain_id) < 0) { - ksft_print_msg("Could not get domain ID\n"); - return; - } - if (!strncmp(resctrl_val, CMT_STR, sizeof(CMT_STR))) set_cmt_path(ctrlgrp, mongrp, domain_id); } @@ -765,10 +751,17 @@ int resctrl_val(const struct resctrl_test *test, int ret = 0, pipefd[2]; char pipe_message = 0; union sigval value; + int domain_id; if (strcmp(param->filename, "") == 0) sprintf(param->filename, "stdio"); + ret = get_domain_id(test->resource, uparams->cpu, &domain_id); + if (ret < 0) { + ksft_print_msg("Could not get domain ID\n"); + return ret; + } + if (!strncmp(resctrl_val, MBA_STR, sizeof(MBA_STR)) || !strncmp(resctrl_val, MBM_STR, sizeof(MBM_STR))) { ret = validate_bw_report_request(param->bw_report); @@ -863,10 +856,10 @@ int resctrl_val(const struct resctrl_test *test, goto out; initialize_mem_bw_resctrl(param->ctrlgrp, param->mongrp, - uparams->cpu, resctrl_val); + domain_id, resctrl_val); } else if (!strncmp(resctrl_val, CMT_STR, sizeof(CMT_STR))) initialize_llc_occu_resctrl(param->ctrlgrp, param->mongrp, - uparams->cpu, resctrl_val); + domain_id, resctrl_val); /* Parent waits for child to be ready. */ close(pipefd[1]); -- cgit v1.2.3-58-ga151 From 8245a70edad18e5eba479c5ea91beb590590b237 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 10 Jun 2024 18:14:46 +0300 Subject: selftests/resctrl: Use correct type for pids MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A few functions receive PIDs through int arguments. PIDs variables should be of type pid_t, not int. Convert pid arguments from int to pid_t. Before printing PID, match the type to %d by casting to int which is enough for Linux (standard would allow using a longer integer type but generalizing for that would complicate the code unnecessarily, the selftest code does not need to be portable). Signed-off-by: Ilpo Järvinen Tested-by: Babu Moger Reviewed-by: Reinette Chatre Signed-off-by: Shuah Khan --- tools/testing/selftests/resctrl/cache.c | 10 +++++----- tools/testing/selftests/resctrl/resctrl.h | 4 ++-- tools/testing/selftests/resctrl/resctrl_val.c | 8 ++++---- tools/testing/selftests/resctrl/resctrlfs.c | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/tools/testing/selftests/resctrl/cache.c b/tools/testing/selftests/resctrl/cache.c index 1b339d6bbff1..1ff1104e6575 100644 --- a/tools/testing/selftests/resctrl/cache.c +++ b/tools/testing/selftests/resctrl/cache.c @@ -101,12 +101,12 @@ static int get_llc_occu_resctrl(unsigned long *llc_occupancy) * * Return: 0 on success, < 0 on error. */ -static int print_results_cache(const char *filename, int bm_pid, __u64 llc_value) +static int print_results_cache(const char *filename, pid_t bm_pid, __u64 llc_value) { FILE *fp; if (strcmp(filename, "stdio") == 0 || strcmp(filename, "stderr") == 0) { - printf("Pid: %d \t LLC_value: %llu\n", bm_pid, llc_value); + printf("Pid: %d \t LLC_value: %llu\n", (int)bm_pid, llc_value); } else { fp = fopen(filename, "a"); if (!fp) { @@ -114,7 +114,7 @@ static int print_results_cache(const char *filename, int bm_pid, __u64 llc_value return -1; } - fprintf(fp, "Pid: %d \t llc_value: %llu\n", bm_pid, llc_value); + fprintf(fp, "Pid: %d \t llc_value: %llu\n", (int)bm_pid, llc_value); fclose(fp); } @@ -133,7 +133,7 @@ static int print_results_cache(const char *filename, int bm_pid, __u64 llc_value * Return: =0 on success. <0 on failure. */ int perf_event_measure(int pe_fd, struct perf_event_read *pe_read, - const char *filename, int bm_pid) + const char *filename, pid_t bm_pid) { int ret; @@ -161,7 +161,7 @@ int perf_event_measure(int pe_fd, struct perf_event_read *pe_read, * * Return: =0 on success. <0 on failure. */ -int measure_llc_resctrl(const char *filename, int bm_pid) +int measure_llc_resctrl(const char *filename, pid_t bm_pid) { unsigned long llc_occu_resc = 0; int ret; diff --git a/tools/testing/selftests/resctrl/resctrl.h b/tools/testing/selftests/resctrl/resctrl.h index 00d51fa7531c..e6f221236c79 100644 --- a/tools/testing/selftests/resctrl/resctrl.h +++ b/tools/testing/selftests/resctrl/resctrl.h @@ -174,8 +174,8 @@ void perf_event_initialize_read_format(struct perf_event_read *pe_read); int perf_open(struct perf_event_attr *pea, pid_t pid, int cpu_no); int perf_event_reset_enable(int pe_fd); int perf_event_measure(int pe_fd, struct perf_event_read *pe_read, - const char *filename, int bm_pid); -int measure_llc_resctrl(const char *filename, int bm_pid); + const char *filename, pid_t bm_pid); +int measure_llc_resctrl(const char *filename, pid_t bm_pid); void show_cache_info(int no_of_bits, __u64 avg_llc_val, size_t cache_span, bool lines); /* diff --git a/tools/testing/selftests/resctrl/resctrl_val.c b/tools/testing/selftests/resctrl/resctrl_val.c index cccf6b80f3f3..5704fa3ba202 100644 --- a/tools/testing/selftests/resctrl/resctrl_val.c +++ b/tools/testing/selftests/resctrl/resctrl_val.c @@ -566,14 +566,14 @@ void signal_handler_unregister(void) * * Return: 0 on success, < 0 on error. */ -static int print_results_bw(char *filename, int bm_pid, float bw_imc, +static int print_results_bw(char *filename, pid_t bm_pid, float bw_imc, unsigned long bw_resc) { unsigned long diff = fabs(bw_imc - bw_resc); FILE *fp; if (strcmp(filename, "stdio") == 0 || strcmp(filename, "stderr") == 0) { - printf("Pid: %d \t Mem_BW_iMC: %f \t ", bm_pid, bw_imc); + printf("Pid: %d \t Mem_BW_iMC: %f \t ", (int)bm_pid, bw_imc); printf("Mem_BW_resc: %lu \t Difference: %lu\n", bw_resc, diff); } else { fp = fopen(filename, "a"); @@ -583,7 +583,7 @@ static int print_results_bw(char *filename, int bm_pid, float bw_imc, return -1; } if (fprintf(fp, "Pid: %d \t Mem_BW_iMC: %f \t Mem_BW_resc: %lu \t Difference: %lu\n", - bm_pid, bw_imc, bw_resc, diff) <= 0) { + (int)bm_pid, bw_imc, bw_resc, diff) <= 0) { ksft_print_msg("Could not log results\n"); fclose(fp); @@ -828,7 +828,7 @@ int resctrl_val(const struct resctrl_test *test, PARENT_EXIT(); } - ksft_print_msg("Benchmark PID: %d\n", bm_pid); + ksft_print_msg("Benchmark PID: %d\n", (int)bm_pid); /* * The cast removes constness but nothing mutates benchmark_cmd within diff --git a/tools/testing/selftests/resctrl/resctrlfs.c b/tools/testing/selftests/resctrl/resctrlfs.c index 9b86f826a40c..917d677adbba 100644 --- a/tools/testing/selftests/resctrl/resctrlfs.c +++ b/tools/testing/selftests/resctrl/resctrlfs.c @@ -508,7 +508,7 @@ static int write_pid_to_tasks(char *tasks, pid_t pid) return -1; } - if (fprintf(fp, "%d\n", pid) < 0) { + if (fprintf(fp, "%d\n", (int)pid) < 0) { ksft_print_msg("Failed to write pid to tasks file\n"); fclose(fp); -- cgit v1.2.3-58-ga151 From b0bd742a1379dff238efcf67c2cb0c518ee0b691 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 10 Jun 2024 18:14:47 +0300 Subject: selftests/resctrl: Cleanup bm_pid and ppid usage & limit scope MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 'bm_pid' and 'ppid' are global variables. As they are used by different processes and in signal handler, they cannot be entirely converted into local variables. The scope of those variables can still be reduced into resctrl_val.c only. As PARENT_EXIT() macro is using 'ppid', make it a function in resctrl_val.c and pass ppid to it as an argument because it is easier to understand than using the global variable directly. Pass 'bm_pid' into measure_vals() instead of relying on the global variable which helps to make the call signatures of measure_vals() and measure_llc_resctrl() more similar to each other. Signed-off-by: Ilpo Järvinen Tested-by: Babu Moger Reviewed-by: Reinette Chatre Signed-off-by: Shuah Khan --- tools/testing/selftests/resctrl/resctrl.h | 9 --------- tools/testing/selftests/resctrl/resctrl_val.c | 23 +++++++++++++++-------- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/tools/testing/selftests/resctrl/resctrl.h b/tools/testing/selftests/resctrl/resctrl.h index e6f221236c79..e4b6dc672ecc 100644 --- a/tools/testing/selftests/resctrl/resctrl.h +++ b/tools/testing/selftests/resctrl/resctrl.h @@ -43,13 +43,6 @@ #define DEFAULT_SPAN (250 * MB) -#define PARENT_EXIT() \ - do { \ - kill(ppid, SIGKILL); \ - umount_resctrlfs(); \ - exit(EXIT_FAILURE); \ - } while (0) - /* * user_params: User supplied parameters * @cpu: CPU number to which the benchmark will be bound to @@ -127,8 +120,6 @@ struct perf_event_read { */ extern volatile int *value_sink; -extern pid_t bm_pid, ppid; - extern char llc_occup_path[1024]; int get_vendor(void); diff --git a/tools/testing/selftests/resctrl/resctrl_val.c b/tools/testing/selftests/resctrl/resctrl_val.c index 5704fa3ba202..3cf671cbb7a2 100644 --- a/tools/testing/selftests/resctrl/resctrl_val.c +++ b/tools/testing/selftests/resctrl/resctrl_val.c @@ -499,7 +499,7 @@ static int get_mem_bw_resctrl(FILE *fp, unsigned long *mbm_total) return 0; } -pid_t bm_pid, ppid; +static pid_t bm_pid, ppid; void ctrlc_handler(int signum, siginfo_t *info, void *ptr) { @@ -557,6 +557,13 @@ void signal_handler_unregister(void) } } +static void parent_exit(pid_t ppid) +{ + kill(ppid, SIGKILL); + umount_resctrlfs(); + exit(EXIT_FAILURE); +} + /* * print_results_bw: the memory bandwidth results are stored in a file * @filename: file that stores the results @@ -631,7 +638,7 @@ static void initialize_llc_occu_resctrl(const char *ctrlgrp, const char *mongrp, * 1 sec to measure the data. */ static int measure_vals(const struct user_params *uparams, - struct resctrl_val_param *param) + struct resctrl_val_param *param, pid_t bm_pid) { unsigned long bw_resc, bw_resc_start, bw_resc_end; FILE *mem_bw_fp; @@ -700,7 +707,7 @@ static void run_benchmark(int signum, siginfo_t *info, void *ucontext) fp = freopen("/dev/null", "w", stdout); if (!fp) { ksft_perror("Unable to direct benchmark status to /dev/null"); - PARENT_EXIT(); + parent_exit(ppid); } if (strcmp(benchmark_cmd[0], "fill_buf") == 0) { @@ -714,7 +721,7 @@ static void run_benchmark(int signum, siginfo_t *info, void *ucontext) once = false; } else { ksft_print_msg("Invalid once parameter\n"); - PARENT_EXIT(); + parent_exit(ppid); } if (run_fill_buf(span, memflush, operation, once)) @@ -728,7 +735,7 @@ static void run_benchmark(int signum, siginfo_t *info, void *ucontext) fclose(stdout); ksft_print_msg("Unable to run specified benchmark\n"); - PARENT_EXIT(); + parent_exit(ppid); } /* @@ -807,7 +814,7 @@ int resctrl_val(const struct resctrl_test *test, /* Register for "SIGUSR1" signal from parent */ if (sigaction(SIGUSR1, &sigact, NULL)) { ksft_perror("Can't register child for signal"); - PARENT_EXIT(); + parent_exit(ppid); } /* Tell parent that child is ready */ @@ -825,7 +832,7 @@ int resctrl_val(const struct resctrl_test *test, sigsuspend(&sigact.sa_mask); ksft_perror("Child is done"); - PARENT_EXIT(); + parent_exit(ppid); } ksft_print_msg("Benchmark PID: %d\n", (int)bm_pid); @@ -895,7 +902,7 @@ int resctrl_val(const struct resctrl_test *test, if (!strncmp(resctrl_val, MBM_STR, sizeof(MBM_STR)) || !strncmp(resctrl_val, MBA_STR, sizeof(MBA_STR))) { - ret = measure_vals(uparams, param); + ret = measure_vals(uparams, param, bm_pid); if (ret) break; } else if (!strncmp(resctrl_val, CMT_STR, sizeof(CMT_STR))) { -- cgit v1.2.3-58-ga151 From bc074b6321d73295dcfe8c450c8f5245c530bb4e Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 10 Jun 2024 18:14:48 +0300 Subject: selftests/resctrl: Rename measure_vals() to measure_mem_bw_vals() & document MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit measure_vals() is awfully generic name so rename it to measure_mem_bw() to describe better what it does and document the function parameters. Signed-off-by: Ilpo Järvinen Tested-by: Babu Moger Reviewed-by: Reinette Chatre Signed-off-by: Shuah Khan --- tools/testing/selftests/resctrl/resctrl_val.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tools/testing/selftests/resctrl/resctrl_val.c b/tools/testing/selftests/resctrl/resctrl_val.c index 3cf671cbb7a2..b33cb1de295b 100644 --- a/tools/testing/selftests/resctrl/resctrl_val.c +++ b/tools/testing/selftests/resctrl/resctrl_val.c @@ -632,13 +632,18 @@ static void initialize_llc_occu_resctrl(const char *ctrlgrp, const char *mongrp, } /* + * measure_mem_bw - Measures memory bandwidth numbers while benchmark runs + * @uparams: User supplied parameters + * @param: Parameters passed to resctrl_val() + * @bm_pid: PID that runs the benchmark + * * Measure memory bandwidth from resctrl and from another source which is * perf imc value or could be something else if perf imc event is not * available. Compare the two values to validate resctrl value. It takes * 1 sec to measure the data. */ -static int measure_vals(const struct user_params *uparams, - struct resctrl_val_param *param, pid_t bm_pid) +static int measure_mem_bw(const struct user_params *uparams, + struct resctrl_val_param *param, pid_t bm_pid) { unsigned long bw_resc, bw_resc_start, bw_resc_end; FILE *mem_bw_fp; @@ -902,7 +907,7 @@ int resctrl_val(const struct resctrl_test *test, if (!strncmp(resctrl_val, MBM_STR, sizeof(MBM_STR)) || !strncmp(resctrl_val, MBA_STR, sizeof(MBA_STR))) { - ret = measure_vals(uparams, param, bm_pid); + ret = measure_mem_bw(uparams, param, bm_pid); if (ret) break; } else if (!strncmp(resctrl_val, CMT_STR, sizeof(CMT_STR))) { -- cgit v1.2.3-58-ga151 From 711d27b05a97cd5c8e62c858c2c940d79f8445e1 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 10 Jun 2024 18:14:49 +0300 Subject: selftests/resctrl: Simplify mem bandwidth file code for MBA & MBM tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit initialize_mem_bw_resctrl() and set_mbm_path() contain complicated set of conditions, each yielding different file to be opened to measure memory bandwidth through resctrl FS. In practice, only two of them are used. For MBA test, ctrlgrp is always provided, and for MBM test both ctrlgrp and mongrp are set. The file used differ between MBA/MBM test, however, MBM test unnecessarily create monitor group because resctrl FS already provides monitoring interface underneath any ctrlgrp too, which is what the MBA selftest uses. Consolidate memory bandwidth file used to the one used by the MBA selftest. Remove all unused branches opening other files to simplify the code. Suggested-by: Reinette Chatre Signed-off-by: Ilpo Järvinen Tested-by: Babu Moger Reviewed-by: Reinette Chatre Signed-off-by: Shuah Khan --- tools/testing/selftests/resctrl/mbm_test.c | 1 - tools/testing/selftests/resctrl/resctrl_val.c | 45 +++------------------------ 2 files changed, 4 insertions(+), 42 deletions(-) diff --git a/tools/testing/selftests/resctrl/mbm_test.c b/tools/testing/selftests/resctrl/mbm_test.c index 6fec51e1ff46..9fc162a0d563 100644 --- a/tools/testing/selftests/resctrl/mbm_test.c +++ b/tools/testing/selftests/resctrl/mbm_test.c @@ -115,7 +115,6 @@ static int mbm_run_test(const struct resctrl_test *test, const struct user_param struct resctrl_val_param param = { .resctrl_val = MBM_STR, .ctrlgrp = "c1", - .mongrp = "m1", .filename = RESULT_FILE_NAME, .bw_report = "reads", .setup = mbm_setup diff --git a/tools/testing/selftests/resctrl/resctrl_val.c b/tools/testing/selftests/resctrl/resctrl_val.c index b33cb1de295b..277c13b7a4c5 100644 --- a/tools/testing/selftests/resctrl/resctrl_val.c +++ b/tools/testing/selftests/resctrl/resctrl_val.c @@ -19,18 +19,10 @@ #define MAX_TOKENS 5 #define READ 0 #define WRITE 1 -#define CON_MON_MBM_LOCAL_BYTES_PATH \ - "%s/%s/mon_groups/%s/mon_data/mon_L3_%02d/mbm_local_bytes" #define CON_MBM_LOCAL_BYTES_PATH \ "%s/%s/mon_data/mon_L3_%02d/mbm_local_bytes" -#define MON_MBM_LOCAL_BYTES_PATH \ - "%s/mon_groups/%s/mon_data/mon_L3_%02d/mbm_local_bytes" - -#define MBM_LOCAL_BYTES_PATH \ - "%s/mon_data/mon_L3_%02d/mbm_local_bytes" - #define CON_MON_LCC_OCCUP_PATH \ "%s/%s/mon_groups/%s/mon_data/mon_L3_%02d/llc_occupancy" @@ -430,43 +422,15 @@ static int get_mem_bw_imc(char *bw_report, float *bw_imc) return 0; } -void set_mbm_path(const char *ctrlgrp, const char *mongrp, int domain_id) -{ - if (ctrlgrp && mongrp) - sprintf(mbm_total_path, CON_MON_MBM_LOCAL_BYTES_PATH, - RESCTRL_PATH, ctrlgrp, mongrp, domain_id); - else if (!ctrlgrp && mongrp) - sprintf(mbm_total_path, MON_MBM_LOCAL_BYTES_PATH, RESCTRL_PATH, - mongrp, domain_id); - else if (ctrlgrp && !mongrp) - sprintf(mbm_total_path, CON_MBM_LOCAL_BYTES_PATH, RESCTRL_PATH, - ctrlgrp, domain_id); - else if (!ctrlgrp && !mongrp) - sprintf(mbm_total_path, MBM_LOCAL_BYTES_PATH, RESCTRL_PATH, - domain_id); -} - /* * initialize_mem_bw_resctrl: Appropriately populate "mbm_total_path" * @ctrlgrp: Name of the control monitor group (con_mon grp) - * @mongrp: Name of the monitor group (mon grp) * @domain_id: Domain ID (cache ID; for MB, L3 cache ID) - * @resctrl_val: Resctrl feature (Eg: mbm, mba.. etc) */ -static void initialize_mem_bw_resctrl(const char *ctrlgrp, const char *mongrp, - int domain_id, char *resctrl_val) +static void initialize_mem_bw_resctrl(const char *ctrlgrp, int domain_id) { - if (!strncmp(resctrl_val, MBM_STR, sizeof(MBM_STR))) - set_mbm_path(ctrlgrp, mongrp, domain_id); - - if (!strncmp(resctrl_val, MBA_STR, sizeof(MBA_STR))) { - if (ctrlgrp) - sprintf(mbm_total_path, CON_MBM_LOCAL_BYTES_PATH, - RESCTRL_PATH, ctrlgrp, domain_id); - else - sprintf(mbm_total_path, MBM_LOCAL_BYTES_PATH, - RESCTRL_PATH, domain_id); - } + sprintf(mbm_total_path, CON_MBM_LOCAL_BYTES_PATH, RESCTRL_PATH, + ctrlgrp, domain_id); } /* @@ -867,8 +831,7 @@ int resctrl_val(const struct resctrl_test *test, if (ret) goto out; - initialize_mem_bw_resctrl(param->ctrlgrp, param->mongrp, - domain_id, resctrl_val); + initialize_mem_bw_resctrl(param->ctrlgrp, domain_id); } else if (!strncmp(resctrl_val, CMT_STR, sizeof(CMT_STR))) initialize_llc_occu_resctrl(param->ctrlgrp, param->mongrp, domain_id, resctrl_val); -- cgit v1.2.3-58-ga151 From 0e251816995a1972062fc7ad32047c1aee9cd704 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 10 Jun 2024 18:14:50 +0300 Subject: selftests/resctrl: Add ->measure() callback to resctrl_val_param MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The measurement done in resctrl_val() varies depending on test type. The decision for how to measure is decided based on the string compare to test name which is quite inflexible. Add ->measure() callback into the struct resctrl_val_param to allow each test to provide necessary code as a function which simplifies what resctrl_val() has to do. Signed-off-by: Ilpo Järvinen Tested-by: Babu Moger Reviewed-by: Reinette Chatre Signed-off-by: Shuah Khan --- tools/testing/selftests/resctrl/cmt_test.c | 8 ++++++++ tools/testing/selftests/resctrl/mba_test.c | 9 ++++++++- tools/testing/selftests/resctrl/mbm_test.c | 9 ++++++++- tools/testing/selftests/resctrl/resctrl.h | 6 ++++++ tools/testing/selftests/resctrl/resctrl_val.c | 18 +++++------------- 5 files changed, 35 insertions(+), 15 deletions(-) diff --git a/tools/testing/selftests/resctrl/cmt_test.c b/tools/testing/selftests/resctrl/cmt_test.c index 0105afec6188..f6cb258f873d 100644 --- a/tools/testing/selftests/resctrl/cmt_test.c +++ b/tools/testing/selftests/resctrl/cmt_test.c @@ -29,6 +29,13 @@ static int cmt_setup(const struct resctrl_test *test, return 0; } +static int cmt_measure(const struct user_params *uparams, + struct resctrl_val_param *param, pid_t bm_pid) +{ + sleep(1); + return measure_llc_resctrl(param->filename, bm_pid); +} + static int show_results_info(unsigned long sum_llc_val, int no_of_bits, unsigned long cache_span, unsigned long max_diff, unsigned long max_diff_percent, unsigned long num_of_runs, @@ -133,6 +140,7 @@ static int cmt_run_test(const struct resctrl_test *test, const struct user_param .mask = ~(long_mask << n) & long_mask, .num_of_runs = 0, .setup = cmt_setup, + .measure = cmt_measure, }; span = cache_portion_size(cache_total_size, param.mask, long_mask); diff --git a/tools/testing/selftests/resctrl/mba_test.c b/tools/testing/selftests/resctrl/mba_test.c index a6ad39aae162..68d92c7c1cab 100644 --- a/tools/testing/selftests/resctrl/mba_test.c +++ b/tools/testing/selftests/resctrl/mba_test.c @@ -51,6 +51,12 @@ static int mba_setup(const struct resctrl_test *test, return 0; } +static int mba_measure(const struct user_params *uparams, + struct resctrl_val_param *param, pid_t bm_pid) +{ + return measure_mem_bw(uparams, param, bm_pid); +} + static bool show_mba_info(unsigned long *bw_imc, unsigned long *bw_resc) { int allocation, runs; @@ -150,7 +156,8 @@ static int mba_run_test(const struct resctrl_test *test, const struct user_param .mongrp = "m1", .filename = RESULT_FILE_NAME, .bw_report = "reads", - .setup = mba_setup + .setup = mba_setup, + .measure = mba_measure, }; int ret; diff --git a/tools/testing/selftests/resctrl/mbm_test.c b/tools/testing/selftests/resctrl/mbm_test.c index 9fc162a0d563..7c6f60b1dd18 100644 --- a/tools/testing/selftests/resctrl/mbm_test.c +++ b/tools/testing/selftests/resctrl/mbm_test.c @@ -105,6 +105,12 @@ static int mbm_setup(const struct resctrl_test *test, return ret; } +static int mbm_measure(const struct user_params *uparams, + struct resctrl_val_param *param, pid_t bm_pid) +{ + return measure_mem_bw(uparams, param, bm_pid); +} + static void mbm_test_cleanup(void) { remove(RESULT_FILE_NAME); @@ -117,7 +123,8 @@ static int mbm_run_test(const struct resctrl_test *test, const struct user_param .ctrlgrp = "c1", .filename = RESULT_FILE_NAME, .bw_report = "reads", - .setup = mbm_setup + .setup = mbm_setup, + .measure = mbm_measure, }; int ret; diff --git a/tools/testing/selftests/resctrl/resctrl.h b/tools/testing/selftests/resctrl/resctrl.h index e4b6dc672ecc..5dc3def70669 100644 --- a/tools/testing/selftests/resctrl/resctrl.h +++ b/tools/testing/selftests/resctrl/resctrl.h @@ -87,6 +87,7 @@ struct resctrl_test { * @filename: Name of file to which the o/p should be written * @bw_report: Bandwidth report type (reads vs writes) * @setup: Call back function to setup test environment + * @measure: Callback that performs the measurement (a single test) */ struct resctrl_val_param { char *resctrl_val; @@ -99,6 +100,9 @@ struct resctrl_val_param { int (*setup)(const struct resctrl_test *test, const struct user_params *uparams, struct resctrl_val_param *param); + int (*measure)(const struct user_params *uparams, + struct resctrl_val_param *param, + pid_t bm_pid); }; struct perf_event_read { @@ -145,6 +149,8 @@ unsigned char *alloc_buffer(size_t buf_size, int memflush); void mem_flush(unsigned char *buf, size_t buf_size); void fill_cache_read(unsigned char *buf, size_t buf_size, bool once); int run_fill_buf(size_t buf_size, int memflush, int op, bool once); +int measure_mem_bw(const struct user_params *uparams, + struct resctrl_val_param *param, pid_t bm_pid); int resctrl_val(const struct resctrl_test *test, const struct user_params *uparams, const char * const *benchmark_cmd, diff --git a/tools/testing/selftests/resctrl/resctrl_val.c b/tools/testing/selftests/resctrl/resctrl_val.c index 277c13b7a4c5..590fc74cb88f 100644 --- a/tools/testing/selftests/resctrl/resctrl_val.c +++ b/tools/testing/selftests/resctrl/resctrl_val.c @@ -606,8 +606,8 @@ static void initialize_llc_occu_resctrl(const char *ctrlgrp, const char *mongrp, * available. Compare the two values to validate resctrl value. It takes * 1 sec to measure the data. */ -static int measure_mem_bw(const struct user_params *uparams, - struct resctrl_val_param *param, pid_t bm_pid) +int measure_mem_bw(const struct user_params *uparams, + struct resctrl_val_param *param, pid_t bm_pid) { unsigned long bw_resc, bw_resc_start, bw_resc_end; FILE *mem_bw_fp; @@ -868,17 +868,9 @@ int resctrl_val(const struct resctrl_test *test, if (ret < 0) break; - if (!strncmp(resctrl_val, MBM_STR, sizeof(MBM_STR)) || - !strncmp(resctrl_val, MBA_STR, sizeof(MBA_STR))) { - ret = measure_mem_bw(uparams, param, bm_pid); - if (ret) - break; - } else if (!strncmp(resctrl_val, CMT_STR, sizeof(CMT_STR))) { - sleep(1); - ret = measure_llc_resctrl(param->filename, bm_pid); - if (ret) - break; - } + ret = param->measure(uparams, param, bm_pid); + if (ret) + break; } out: -- cgit v1.2.3-58-ga151 From aef5efa64426396cac5b0126cbb6071e92d5da24 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 10 Jun 2024 18:14:51 +0300 Subject: selftests/resctrl: Add ->init() callback into resctrl_val_param MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The struct resctrl_val_param is there to customize behavior inside resctrl_val() which is currently not used to full extent and there are number of strcmp()s for test name in resctrl_val done by resctrl_val(). Create ->init() hook into the struct resctrl_val_param to cleanly do per test initialization. Remove also unused branches to setup paths and the related #defines for CMT test. While touching kerneldoc, make the adjacent line consistent with the newly added form (callback vs call back). Signed-off-by: Ilpo Järvinen Tested-by: Babu Moger Reviewed-by: Reinette Chatre Signed-off-by: Shuah Khan --- tools/testing/selftests/resctrl/cmt_test.c | 12 +++++ tools/testing/selftests/resctrl/mba_test.c | 14 +++++ tools/testing/selftests/resctrl/mbm_test.c | 14 +++++ tools/testing/selftests/resctrl/resctrl.h | 8 ++- tools/testing/selftests/resctrl/resctrl_val.c | 75 +++++---------------------- 5 files changed, 60 insertions(+), 63 deletions(-) diff --git a/tools/testing/selftests/resctrl/cmt_test.c b/tools/testing/selftests/resctrl/cmt_test.c index f6cb258f873d..491574c11805 100644 --- a/tools/testing/selftests/resctrl/cmt_test.c +++ b/tools/testing/selftests/resctrl/cmt_test.c @@ -16,6 +16,17 @@ #define MAX_DIFF 2000000 #define MAX_DIFF_PERCENT 15 +#define CON_MON_LCC_OCCUP_PATH \ + "%s/%s/mon_groups/%s/mon_data/mon_L3_%02d/llc_occupancy" + +static int cmt_init(const struct resctrl_val_param *param, int domain_id) +{ + sprintf(llc_occup_path, CON_MON_LCC_OCCUP_PATH, RESCTRL_PATH, + param->ctrlgrp, param->mongrp, domain_id); + + return 0; +} + static int cmt_setup(const struct resctrl_test *test, const struct user_params *uparams, struct resctrl_val_param *p) @@ -139,6 +150,7 @@ static int cmt_run_test(const struct resctrl_test *test, const struct user_param .filename = RESULT_FILE_NAME, .mask = ~(long_mask << n) & long_mask, .num_of_runs = 0, + .init = cmt_init, .setup = cmt_setup, .measure = cmt_measure, }; diff --git a/tools/testing/selftests/resctrl/mba_test.c b/tools/testing/selftests/resctrl/mba_test.c index 68d92c7c1cab..20427bdb5c6d 100644 --- a/tools/testing/selftests/resctrl/mba_test.c +++ b/tools/testing/selftests/resctrl/mba_test.c @@ -17,6 +17,19 @@ #define ALLOCATION_MIN 10 #define ALLOCATION_STEP 10 +static int mba_init(const struct resctrl_val_param *param, int domain_id) +{ + int ret; + + ret = initialize_mem_bw_imc(); + if (ret) + return ret; + + initialize_mem_bw_resctrl(param, domain_id); + + return 0; +} + /* * Change schemata percentage from 100 to 10%. Write schemata to specified * con_mon grp, mon_grp in resctrl FS. @@ -156,6 +169,7 @@ static int mba_run_test(const struct resctrl_test *test, const struct user_param .mongrp = "m1", .filename = RESULT_FILE_NAME, .bw_report = "reads", + .init = mba_init, .setup = mba_setup, .measure = mba_measure, }; diff --git a/tools/testing/selftests/resctrl/mbm_test.c b/tools/testing/selftests/resctrl/mbm_test.c index 7c6f60b1dd18..adc205bf9e51 100644 --- a/tools/testing/selftests/resctrl/mbm_test.c +++ b/tools/testing/selftests/resctrl/mbm_test.c @@ -86,6 +86,19 @@ static int check_results(size_t span) return ret; } +static int mbm_init(const struct resctrl_val_param *param, int domain_id) +{ + int ret; + + ret = initialize_mem_bw_imc(); + if (ret) + return ret; + + initialize_mem_bw_resctrl(param, domain_id); + + return 0; +} + static int mbm_setup(const struct resctrl_test *test, const struct user_params *uparams, struct resctrl_val_param *p) @@ -123,6 +136,7 @@ static int mbm_run_test(const struct resctrl_test *test, const struct user_param .ctrlgrp = "c1", .filename = RESULT_FILE_NAME, .bw_report = "reads", + .init = mbm_init, .setup = mbm_setup, .measure = mbm_measure, }; diff --git a/tools/testing/selftests/resctrl/resctrl.h b/tools/testing/selftests/resctrl/resctrl.h index 5dc3def70669..d3fbb957309d 100644 --- a/tools/testing/selftests/resctrl/resctrl.h +++ b/tools/testing/selftests/resctrl/resctrl.h @@ -86,7 +86,8 @@ struct resctrl_test { * @mongrp: Name of the monitor group (mon grp) * @filename: Name of file to which the o/p should be written * @bw_report: Bandwidth report type (reads vs writes) - * @setup: Call back function to setup test environment + * @init: Callback function to initialize test environment + * @setup: Callback function to setup per test run environment * @measure: Callback that performs the measurement (a single test) */ struct resctrl_val_param { @@ -97,6 +98,8 @@ struct resctrl_val_param { char *bw_report; unsigned long mask; int num_of_runs; + int (*init)(const struct resctrl_val_param *param, + int domain_id); int (*setup)(const struct resctrl_test *test, const struct user_params *uparams, struct resctrl_val_param *param); @@ -149,8 +152,11 @@ unsigned char *alloc_buffer(size_t buf_size, int memflush); void mem_flush(unsigned char *buf, size_t buf_size); void fill_cache_read(unsigned char *buf, size_t buf_size, bool once); int run_fill_buf(size_t buf_size, int memflush, int op, bool once); +int initialize_mem_bw_imc(void); int measure_mem_bw(const struct user_params *uparams, struct resctrl_val_param *param, pid_t bm_pid); +void initialize_mem_bw_resctrl(const struct resctrl_val_param *param, + int domain_id); int resctrl_val(const struct resctrl_test *test, const struct user_params *uparams, const char * const *benchmark_cmd, diff --git a/tools/testing/selftests/resctrl/resctrl_val.c b/tools/testing/selftests/resctrl/resctrl_val.c index 590fc74cb88f..ecbf46c4f3ea 100644 --- a/tools/testing/selftests/resctrl/resctrl_val.c +++ b/tools/testing/selftests/resctrl/resctrl_val.c @@ -23,18 +23,6 @@ #define CON_MBM_LOCAL_BYTES_PATH \ "%s/%s/mon_data/mon_L3_%02d/mbm_local_bytes" -#define CON_MON_LCC_OCCUP_PATH \ - "%s/%s/mon_groups/%s/mon_data/mon_L3_%02d/llc_occupancy" - -#define CON_LCC_OCCUP_PATH \ - "%s/%s/mon_data/mon_L3_%02d/llc_occupancy" - -#define MON_LCC_OCCUP_PATH \ - "%s/mon_groups/%s/mon_data/mon_L3_%02d/llc_occupancy" - -#define LCC_OCCUP_PATH \ - "%s/mon_data/mon_L3_%02d/llc_occupancy" - struct membw_read_format { __u64 value; /* The value of the event */ __u64 time_enabled; /* if PERF_FORMAT_TOTAL_TIME_ENABLED */ @@ -268,7 +256,7 @@ static int num_of_imcs(void) return count; } -static int initialize_mem_bw_imc(void) +int initialize_mem_bw_imc(void) { int imc, j; @@ -424,24 +412,18 @@ static int get_mem_bw_imc(char *bw_report, float *bw_imc) /* * initialize_mem_bw_resctrl: Appropriately populate "mbm_total_path" - * @ctrlgrp: Name of the control monitor group (con_mon grp) - * @domain_id: Domain ID (cache ID; for MB, L3 cache ID) + * @param: Parameters passed to resctrl_val() + * @domain_id: Domain ID (cache ID; for MB, L3 cache ID) */ -static void initialize_mem_bw_resctrl(const char *ctrlgrp, int domain_id) +void initialize_mem_bw_resctrl(const struct resctrl_val_param *param, + int domain_id) { sprintf(mbm_total_path, CON_MBM_LOCAL_BYTES_PATH, RESCTRL_PATH, - ctrlgrp, domain_id); + param->ctrlgrp, domain_id); } /* - * Get MBM Local bytes as reported by resctrl FS - * For MBM, - * 1. If con_mon grp and mon grp are given, then read from con_mon grp's mon grp - * 2. If only con_mon grp is given, then read from con_mon grp - * 3. If both are not given, then read from root con_mon grp - * For MBA, - * 1. If con_mon grp is given, then read from it - * 2. If con_mon grp is not given, then read from root con_mon grp + * Open file to read MBM local bytes from resctrl FS */ static FILE *open_mem_bw_resctrl(const char *mbm_bw_file) { @@ -454,6 +436,9 @@ static FILE *open_mem_bw_resctrl(const char *mbm_bw_file) return fp; } +/* + * Get MBM Local bytes as reported by resctrl FS + */ static int get_mem_bw_resctrl(FILE *fp, unsigned long *mbm_total) { if (fscanf(fp, "%lu\n", mbm_total) <= 0) { @@ -566,35 +551,6 @@ static int print_results_bw(char *filename, pid_t bm_pid, float bw_imc, return 0; } -static void set_cmt_path(const char *ctrlgrp, const char *mongrp, char sock_num) -{ - if (strlen(ctrlgrp) && strlen(mongrp)) - sprintf(llc_occup_path, CON_MON_LCC_OCCUP_PATH, RESCTRL_PATH, - ctrlgrp, mongrp, sock_num); - else if (!strlen(ctrlgrp) && strlen(mongrp)) - sprintf(llc_occup_path, MON_LCC_OCCUP_PATH, RESCTRL_PATH, - mongrp, sock_num); - else if (strlen(ctrlgrp) && !strlen(mongrp)) - sprintf(llc_occup_path, CON_LCC_OCCUP_PATH, RESCTRL_PATH, - ctrlgrp, sock_num); - else if (!strlen(ctrlgrp) && !strlen(mongrp)) - sprintf(llc_occup_path, LCC_OCCUP_PATH, RESCTRL_PATH, sock_num); -} - -/* - * initialize_llc_occu_resctrl: Appropriately populate "llc_occup_path" - * @ctrlgrp: Name of the control monitor group (con_mon grp) - * @mongrp: Name of the monitor group (mon grp) - * @domain_id: Domain ID (cache ID; for MB, L3 cache ID) - * @resctrl_val: Resctrl feature (Eg: cat, cmt.. etc) - */ -static void initialize_llc_occu_resctrl(const char *ctrlgrp, const char *mongrp, - int domain_id, char *resctrl_val) -{ - if (!strncmp(resctrl_val, CMT_STR, sizeof(CMT_STR))) - set_cmt_path(ctrlgrp, mongrp, domain_id); -} - /* * measure_mem_bw - Measures memory bandwidth numbers while benchmark runs * @uparams: User supplied parameters @@ -825,16 +781,11 @@ int resctrl_val(const struct resctrl_test *test, if (ret) goto out; - if (!strncmp(resctrl_val, MBM_STR, sizeof(MBM_STR)) || - !strncmp(resctrl_val, MBA_STR, sizeof(MBA_STR))) { - ret = initialize_mem_bw_imc(); + if (param->init) { + ret = param->init(param, domain_id); if (ret) goto out; - - initialize_mem_bw_resctrl(param->ctrlgrp, domain_id); - } else if (!strncmp(resctrl_val, CMT_STR, sizeof(CMT_STR))) - initialize_llc_occu_resctrl(param->ctrlgrp, param->mongrp, - domain_id, resctrl_val); + } /* Parent waits for child to be ready. */ close(pipefd[1]); -- cgit v1.2.3-58-ga151 From fa1116d06ebc4673c4e8ca23d8e7ef73db544480 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 10 Jun 2024 18:14:52 +0300 Subject: selftests/resctrl: Simplify bandwidth report type handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit bw_report is only needed for selecting the correct value from the values IMC measured. It is a member in the resctrl_val_param struct and is always set to "reads". The value is then checked in resctrl_val() using validate_bw_report_request() that besides validating the input, assumes it can mutate the string which is questionable programming practice. Simplify handling bw_report: - Convert validate_bw_report_request() into get_bw_report_type() that inputs and returns const char *. Use NULL to indicate error. - Validate the report types inside measure_mem_bw(), not in resctrl_val(). - Pass bw_report to measure_mem_bw() from ->measure() hook because resctrl_val() no longer needs bw_report for anything. Signed-off-by: Ilpo Järvinen Tested-by: Babu Moger Reviewed-by: Reinette Chatre Signed-off-by: Shuah Khan --- tools/testing/selftests/resctrl/mba_test.c | 3 +-- tools/testing/selftests/resctrl/mbm_test.c | 3 +-- tools/testing/selftests/resctrl/resctrl.h | 7 +++---- tools/testing/selftests/resctrl/resctrl_val.c | 19 +++++++++---------- tools/testing/selftests/resctrl/resctrlfs.c | 13 ++++++------- 5 files changed, 20 insertions(+), 25 deletions(-) diff --git a/tools/testing/selftests/resctrl/mba_test.c b/tools/testing/selftests/resctrl/mba_test.c index 20427bdb5c6d..5538a0032c0e 100644 --- a/tools/testing/selftests/resctrl/mba_test.c +++ b/tools/testing/selftests/resctrl/mba_test.c @@ -67,7 +67,7 @@ static int mba_setup(const struct resctrl_test *test, static int mba_measure(const struct user_params *uparams, struct resctrl_val_param *param, pid_t bm_pid) { - return measure_mem_bw(uparams, param, bm_pid); + return measure_mem_bw(uparams, param, bm_pid, "reads"); } static bool show_mba_info(unsigned long *bw_imc, unsigned long *bw_resc) @@ -168,7 +168,6 @@ static int mba_run_test(const struct resctrl_test *test, const struct user_param .ctrlgrp = "c1", .mongrp = "m1", .filename = RESULT_FILE_NAME, - .bw_report = "reads", .init = mba_init, .setup = mba_setup, .measure = mba_measure, diff --git a/tools/testing/selftests/resctrl/mbm_test.c b/tools/testing/selftests/resctrl/mbm_test.c index adc205bf9e51..40eca4a9eec9 100644 --- a/tools/testing/selftests/resctrl/mbm_test.c +++ b/tools/testing/selftests/resctrl/mbm_test.c @@ -121,7 +121,7 @@ static int mbm_setup(const struct resctrl_test *test, static int mbm_measure(const struct user_params *uparams, struct resctrl_val_param *param, pid_t bm_pid) { - return measure_mem_bw(uparams, param, bm_pid); + return measure_mem_bw(uparams, param, bm_pid, "reads"); } static void mbm_test_cleanup(void) @@ -135,7 +135,6 @@ static int mbm_run_test(const struct resctrl_test *test, const struct user_param .resctrl_val = MBM_STR, .ctrlgrp = "c1", .filename = RESULT_FILE_NAME, - .bw_report = "reads", .init = mbm_init, .setup = mbm_setup, .measure = mbm_measure, diff --git a/tools/testing/selftests/resctrl/resctrl.h b/tools/testing/selftests/resctrl/resctrl.h index d3fbb957309d..4446a0e493ef 100644 --- a/tools/testing/selftests/resctrl/resctrl.h +++ b/tools/testing/selftests/resctrl/resctrl.h @@ -85,7 +85,6 @@ struct resctrl_test { * @ctrlgrp: Name of the control monitor group (con_mon grp) * @mongrp: Name of the monitor group (mon grp) * @filename: Name of file to which the o/p should be written - * @bw_report: Bandwidth report type (reads vs writes) * @init: Callback function to initialize test environment * @setup: Callback function to setup per test run environment * @measure: Callback that performs the measurement (a single test) @@ -95,7 +94,6 @@ struct resctrl_val_param { char ctrlgrp[64]; char mongrp[64]; char filename[64]; - char *bw_report; unsigned long mask; int num_of_runs; int (*init)(const struct resctrl_val_param *param, @@ -135,7 +133,7 @@ int filter_dmesg(void); int get_domain_id(const char *resource, int cpu_no, int *domain_id); int mount_resctrlfs(void); int umount_resctrlfs(void); -int validate_bw_report_request(char *bw_report); +const char *get_bw_report_type(const char *bw_report); bool resctrl_resource_exists(const char *resource); bool resctrl_mon_feature_exists(const char *resource, const char *feature); bool resource_info_file_exists(const char *resource, const char *file); @@ -154,7 +152,8 @@ void fill_cache_read(unsigned char *buf, size_t buf_size, bool once); int run_fill_buf(size_t buf_size, int memflush, int op, bool once); int initialize_mem_bw_imc(void); int measure_mem_bw(const struct user_params *uparams, - struct resctrl_val_param *param, pid_t bm_pid); + struct resctrl_val_param *param, pid_t bm_pid, + const char *bw_report); void initialize_mem_bw_resctrl(const struct resctrl_val_param *param, int domain_id); int resctrl_val(const struct resctrl_test *test, diff --git a/tools/testing/selftests/resctrl/resctrl_val.c b/tools/testing/selftests/resctrl/resctrl_val.c index ecbf46c4f3ea..0a0abc860a7f 100644 --- a/tools/testing/selftests/resctrl/resctrl_val.c +++ b/tools/testing/selftests/resctrl/resctrl_val.c @@ -349,7 +349,7 @@ static void do_imc_mem_bw_test(void) * * Return: = 0 on success. < 0 on failure. */ -static int get_mem_bw_imc(char *bw_report, float *bw_imc) +static int get_mem_bw_imc(const char *bw_report, float *bw_imc) { float reads, writes, of_mul_read, of_mul_write; int imc; @@ -556,6 +556,7 @@ static int print_results_bw(char *filename, pid_t bm_pid, float bw_imc, * @uparams: User supplied parameters * @param: Parameters passed to resctrl_val() * @bm_pid: PID that runs the benchmark + * @bw_report: Bandwidth report type (reads, writes) * * Measure memory bandwidth from resctrl and from another source which is * perf imc value or could be something else if perf imc event is not @@ -563,13 +564,18 @@ static int print_results_bw(char *filename, pid_t bm_pid, float bw_imc, * 1 sec to measure the data. */ int measure_mem_bw(const struct user_params *uparams, - struct resctrl_val_param *param, pid_t bm_pid) + struct resctrl_val_param *param, pid_t bm_pid, + const char *bw_report) { unsigned long bw_resc, bw_resc_start, bw_resc_end; FILE *mem_bw_fp; float bw_imc; int ret; + bw_report = get_bw_report_type(bw_report); + if (!bw_report) + return -1; + mem_bw_fp = open_mem_bw_resctrl(mbm_total_path); if (!mem_bw_fp) return -1; @@ -590,7 +596,7 @@ int measure_mem_bw(const struct user_params *uparams, if (ret < 0) goto close_imc; - ret = get_mem_bw_imc(param->bw_report, &bw_imc); + ret = get_mem_bw_imc(bw_report, &bw_imc); if (ret < 0) goto close_imc; @@ -694,13 +700,6 @@ int resctrl_val(const struct resctrl_test *test, return ret; } - if (!strncmp(resctrl_val, MBA_STR, sizeof(MBA_STR)) || - !strncmp(resctrl_val, MBM_STR, sizeof(MBM_STR))) { - ret = validate_bw_report_request(param->bw_report); - if (ret) - return ret; - } - /* * If benchmark wasn't successfully started by child, then child should * kill parent, so save parent's pid diff --git a/tools/testing/selftests/resctrl/resctrlfs.c b/tools/testing/selftests/resctrl/resctrlfs.c index 917d677adbba..9e4cda154d66 100644 --- a/tools/testing/selftests/resctrl/resctrlfs.c +++ b/tools/testing/selftests/resctrl/resctrlfs.c @@ -837,22 +837,21 @@ int filter_dmesg(void) return 0; } -int validate_bw_report_request(char *bw_report) +const char *get_bw_report_type(const char *bw_report) { if (strcmp(bw_report, "reads") == 0) - return 0; + return bw_report; if (strcmp(bw_report, "writes") == 0) - return 0; + return bw_report; if (strcmp(bw_report, "nt-writes") == 0) { - strcpy(bw_report, "writes"); - return 0; + return "writes"; } if (strcmp(bw_report, "total") == 0) - return 0; + return bw_report; fprintf(stderr, "Requested iMC bandwidth report type unavailable\n"); - return -1; + return NULL; } int perf_event_open(struct perf_event_attr *hw_event, pid_t pid, int cpu, -- cgit v1.2.3-58-ga151 From 909592b5dafa3680994b1d5144b6d5781eb49ab8 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 10 Jun 2024 18:14:53 +0300 Subject: selftests/resctrl: Make some strings passed to resctrlfs functions const MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Control group, monitor group and resctrl_val are not mutated and should not be mutated within resctrlfs.c functions. Mark this by using const char * for the arguments. Signed-off-by: Ilpo Järvinen Tested-by: Babu Moger Reviewed-by: Reinette Chatre Signed-off-by: Shuah Khan --- tools/testing/selftests/resctrl/resctrl.h | 7 ++++--- tools/testing/selftests/resctrl/resctrlfs.c | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/tools/testing/selftests/resctrl/resctrl.h b/tools/testing/selftests/resctrl/resctrl.h index 4446a0e493ef..5967389038d4 100644 --- a/tools/testing/selftests/resctrl/resctrl.h +++ b/tools/testing/selftests/resctrl/resctrl.h @@ -141,9 +141,10 @@ bool test_resource_feature_check(const struct resctrl_test *test); char *fgrep(FILE *inf, const char *str); int taskset_benchmark(pid_t bm_pid, int cpu_no, cpu_set_t *old_affinity); int taskset_restore(pid_t bm_pid, cpu_set_t *old_affinity); -int write_schemata(char *ctrlgrp, char *schemata, int cpu_no, const char *resource); -int write_bm_pid_to_resctrl(pid_t bm_pid, char *ctrlgrp, char *mongrp, - char *resctrl_val); +int write_schemata(const char *ctrlgrp, char *schemata, int cpu_no, + const char *resource); +int write_bm_pid_to_resctrl(pid_t bm_pid, const char *ctrlgrp, + const char *mongrp, const char *resctrl_val); int perf_event_open(struct perf_event_attr *hw_event, pid_t pid, int cpu, int group_fd, unsigned long flags); unsigned char *alloc_buffer(size_t buf_size, int memflush); diff --git a/tools/testing/selftests/resctrl/resctrlfs.c b/tools/testing/selftests/resctrl/resctrlfs.c index 9e4cda154d66..f4dc8ef23a8c 100644 --- a/tools/testing/selftests/resctrl/resctrlfs.c +++ b/tools/testing/selftests/resctrl/resctrlfs.c @@ -534,8 +534,8 @@ static int write_pid_to_tasks(char *tasks, pid_t pid) * * Return: 0 on success, < 0 on error. */ -int write_bm_pid_to_resctrl(pid_t bm_pid, char *ctrlgrp, char *mongrp, - char *resctrl_val) +int write_bm_pid_to_resctrl(pid_t bm_pid, const char *ctrlgrp, + const char *mongrp, const char *resctrl_val) { char controlgroup[128], monitorgroup[512], monitorgroup_p[256]; char tasks[1024]; @@ -593,7 +593,8 @@ out: * * Return: 0 on success, < 0 on error. */ -int write_schemata(char *ctrlgrp, char *schemata, int cpu_no, const char *resource) +int write_schemata(const char *ctrlgrp, char *schemata, int cpu_no, + const char *resource) { char controlgroup[1024], reason[128], schema[1024] = {}; int domain_id, fd, schema_len, ret = 0; -- cgit v1.2.3-58-ga151 From d14d94da0e3f1d7e598f88204cf37ee41a06f900 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 10 Jun 2024 18:14:54 +0300 Subject: selftests/resctrl: Convert ctrlgrp & mongrp to pointers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The struct resctrl_val_param has control and monitor groups as char arrays but they are not supposed to be mutated within resctrl_val(). Convert the ctrlgrp and mongrp char array within resctrl_val_param to plain const char pointers and adjust the strlen() based checks to check NULL instead. Signed-off-by: Ilpo Järvinen Tested-by: Babu Moger Reviewed-by: Reinette Chatre Signed-off-by: Shuah Khan --- tools/testing/selftests/resctrl/resctrl.h | 4 ++-- tools/testing/selftests/resctrl/resctrlfs.c | 16 +++++++--------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/tools/testing/selftests/resctrl/resctrl.h b/tools/testing/selftests/resctrl/resctrl.h index 5967389038d4..a999fbc13fd3 100644 --- a/tools/testing/selftests/resctrl/resctrl.h +++ b/tools/testing/selftests/resctrl/resctrl.h @@ -91,8 +91,8 @@ struct resctrl_test { */ struct resctrl_val_param { char *resctrl_val; - char ctrlgrp[64]; - char mongrp[64]; + const char *ctrlgrp; + const char *mongrp; char filename[64]; unsigned long mask; int num_of_runs; diff --git a/tools/testing/selftests/resctrl/resctrlfs.c b/tools/testing/selftests/resctrl/resctrlfs.c index f4dc8ef23a8c..e2d1ecb55d51 100644 --- a/tools/testing/selftests/resctrl/resctrlfs.c +++ b/tools/testing/selftests/resctrl/resctrlfs.c @@ -456,6 +456,9 @@ int taskset_restore(pid_t bm_pid, cpu_set_t *old_affinity) * @grp: Full path and name of the group * @parent_grp: Full path and name of the parent group * + * Creates a group @grp_name if it does not exist yet. If @grp_name is NULL, + * it is interpreted as the root group which always results in success. + * * Return: 0 on success, < 0 on error. */ static int create_grp(const char *grp_name, char *grp, const char *parent_grp) @@ -464,12 +467,7 @@ static int create_grp(const char *grp_name, char *grp, const char *parent_grp) struct dirent *ep; DIR *dp; - /* - * At this point, we are guaranteed to have resctrl FS mounted and if - * length of grp_name == 0, it means, user wants to use root con_mon - * grp, so do nothing - */ - if (strlen(grp_name) == 0) + if (!grp_name) return 0; /* Check if requested grp exists or not */ @@ -541,7 +539,7 @@ int write_bm_pid_to_resctrl(pid_t bm_pid, const char *ctrlgrp, char tasks[1024]; int ret = 0; - if (strlen(ctrlgrp)) + if (ctrlgrp) sprintf(controlgroup, "%s/%s", RESCTRL_PATH, ctrlgrp); else sprintf(controlgroup, "%s", RESCTRL_PATH); @@ -558,7 +556,7 @@ int write_bm_pid_to_resctrl(pid_t bm_pid, const char *ctrlgrp, /* Create mon grp and write pid into it for "mbm" and "cmt" test */ if (!strncmp(resctrl_val, CMT_STR, sizeof(CMT_STR)) || !strncmp(resctrl_val, MBM_STR, sizeof(MBM_STR))) { - if (strlen(mongrp)) { + if (mongrp) { sprintf(monitorgroup_p, "%s/mon_groups", controlgroup); sprintf(monitorgroup, "%s/%s", monitorgroup_p, mongrp); ret = create_grp(mongrp, monitorgroup, monitorgroup_p); @@ -612,7 +610,7 @@ int write_schemata(const char *ctrlgrp, char *schemata, int cpu_no, goto out; } - if (strlen(ctrlgrp) != 0) + if (ctrlgrp) sprintf(controlgroup, "%s/%s/schemata", RESCTRL_PATH, ctrlgrp); else sprintf(controlgroup, "%s/schemata", RESCTRL_PATH); -- cgit v1.2.3-58-ga151 From 64b0795192a8f7fa6baaeda2631a4134aa2c7e12 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 10 Jun 2024 18:14:55 +0300 Subject: selftests/resctrl: Remove mongrp from MBA test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Nothing during MBA test uses mongrp even if it has been defined ever since the introduction of the MBA test in the commit 01fee6b4d1f9 ("selftests/resctrl: Add MBA test"). Remove the mongrp from MBA test. Signed-off-by: Ilpo Järvinen Tested-by: Babu Moger Reviewed-by: Reinette Chatre Signed-off-by: Shuah Khan --- tools/testing/selftests/resctrl/mba_test.c | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/testing/selftests/resctrl/mba_test.c b/tools/testing/selftests/resctrl/mba_test.c index 5538a0032c0e..725227caf1c7 100644 --- a/tools/testing/selftests/resctrl/mba_test.c +++ b/tools/testing/selftests/resctrl/mba_test.c @@ -166,7 +166,6 @@ static int mba_run_test(const struct resctrl_test *test, const struct user_param struct resctrl_val_param param = { .resctrl_val = MBA_STR, .ctrlgrp = "c1", - .mongrp = "m1", .filename = RESULT_FILE_NAME, .init = mba_init, .setup = mba_setup, -- cgit v1.2.3-58-ga151 From f58e66bed1b4563c8afd35d43dbd4fd361705789 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 10 Jun 2024 18:14:56 +0300 Subject: selftests/resctrl: Remove mongrp from CMT test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The CMT selftest instantiates a monitor group to read LLC occupancy. Since the test also creates a control group, it is unnecessary to create another one for monitoring because control groups already provide monitoring too. Remove the unnecessary monitor group from the CMT selftest. Suggested-by: Reinette Chatre Signed-off-by: Ilpo Järvinen Tested-by: Babu Moger Reviewed-by: Reinette Chatre Signed-off-by: Shuah Khan --- tools/testing/selftests/resctrl/cmt_test.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tools/testing/selftests/resctrl/cmt_test.c b/tools/testing/selftests/resctrl/cmt_test.c index 491574c11805..2713263a001e 100644 --- a/tools/testing/selftests/resctrl/cmt_test.c +++ b/tools/testing/selftests/resctrl/cmt_test.c @@ -17,12 +17,12 @@ #define MAX_DIFF_PERCENT 15 #define CON_MON_LCC_OCCUP_PATH \ - "%s/%s/mon_groups/%s/mon_data/mon_L3_%02d/llc_occupancy" + "%s/%s/mon_data/mon_L3_%02d/llc_occupancy" static int cmt_init(const struct resctrl_val_param *param, int domain_id) { sprintf(llc_occup_path, CON_MON_LCC_OCCUP_PATH, RESCTRL_PATH, - param->ctrlgrp, param->mongrp, domain_id); + param->ctrlgrp, domain_id); return 0; } @@ -146,7 +146,6 @@ static int cmt_run_test(const struct resctrl_test *test, const struct user_param struct resctrl_val_param param = { .resctrl_val = CMT_STR, .ctrlgrp = "c1", - .mongrp = "m1", .filename = RESULT_FILE_NAME, .mask = ~(long_mask << n) & long_mask, .num_of_runs = 0, -- cgit v1.2.3-58-ga151 From 0d66ddb296cc46d7b72d67cfaef0de03da092fcd Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 10 Jun 2024 18:14:57 +0300 Subject: selftests/resctrl: Remove test name comparing from write_bm_pid_to_resctrl() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit write_bm_pid_to_resctrl() uses resctrl_val to check test name which is not a good interface generic resctrl FS functions should provide. Tests define mongrp when needed. Remove the test name check in write_bm_pid_to_resctrl() to only rely on the mongrp parameter being non-NULL. Remove write_bm_pid_to_resctrl() resctrl_val parameter and resctrl_val member from the struct resctrl_val_param that are not used anymore. Similarly, remove the test name constants that are no longer used. Signed-off-by: Ilpo Järvinen Tested-by: Babu Moger Reviewed-by: Reinette Chatre Signed-off-by: Shuah Khan --- tools/testing/selftests/resctrl/cat_test.c | 5 +--- tools/testing/selftests/resctrl/cmt_test.c | 1 - tools/testing/selftests/resctrl/mba_test.c | 1 - tools/testing/selftests/resctrl/mbm_test.c | 1 - tools/testing/selftests/resctrl/resctrl.h | 10 +------- tools/testing/selftests/resctrl/resctrl_val.c | 4 +--- tools/testing/selftests/resctrl/resctrlfs.c | 33 ++++++++++++--------------- 7 files changed, 17 insertions(+), 38 deletions(-) diff --git a/tools/testing/selftests/resctrl/cat_test.c b/tools/testing/selftests/resctrl/cat_test.c index 55315ed695f4..742782438ca3 100644 --- a/tools/testing/selftests/resctrl/cat_test.c +++ b/tools/testing/selftests/resctrl/cat_test.c @@ -158,7 +158,6 @@ static int cat_test(const struct resctrl_test *test, struct resctrl_val_param *param, size_t span, unsigned long current_mask) { - char *resctrl_val = param->resctrl_val; struct perf_event_read pe_read; struct perf_event_attr pea; cpu_set_t old_affinity; @@ -178,8 +177,7 @@ static int cat_test(const struct resctrl_test *test, return ret; /* Write benchmark to specified con_mon grp, mon_grp in resctrl FS*/ - ret = write_bm_pid_to_resctrl(bm_pid, param->ctrlgrp, param->mongrp, - resctrl_val); + ret = write_bm_pid_to_resctrl(bm_pid, param->ctrlgrp, param->mongrp); if (ret) goto reset_affinity; @@ -272,7 +270,6 @@ static int cat_run_test(const struct resctrl_test *test, const struct user_param start_mask = create_bit_mask(start, n); struct resctrl_val_param param = { - .resctrl_val = CAT_STR, .ctrlgrp = "c1", .filename = RESULT_FILE_NAME, .num_of_runs = 0, diff --git a/tools/testing/selftests/resctrl/cmt_test.c b/tools/testing/selftests/resctrl/cmt_test.c index 2713263a001e..0c045080d808 100644 --- a/tools/testing/selftests/resctrl/cmt_test.c +++ b/tools/testing/selftests/resctrl/cmt_test.c @@ -144,7 +144,6 @@ static int cmt_run_test(const struct resctrl_test *test, const struct user_param } struct resctrl_val_param param = { - .resctrl_val = CMT_STR, .ctrlgrp = "c1", .filename = RESULT_FILE_NAME, .mask = ~(long_mask << n) & long_mask, diff --git a/tools/testing/selftests/resctrl/mba_test.c b/tools/testing/selftests/resctrl/mba_test.c index 725227caf1c7..ab8496a4925b 100644 --- a/tools/testing/selftests/resctrl/mba_test.c +++ b/tools/testing/selftests/resctrl/mba_test.c @@ -164,7 +164,6 @@ static void mba_test_cleanup(void) static int mba_run_test(const struct resctrl_test *test, const struct user_params *uparams) { struct resctrl_val_param param = { - .resctrl_val = MBA_STR, .ctrlgrp = "c1", .filename = RESULT_FILE_NAME, .init = mba_init, diff --git a/tools/testing/selftests/resctrl/mbm_test.c b/tools/testing/selftests/resctrl/mbm_test.c index 40eca4a9eec9..6b5a3b52d861 100644 --- a/tools/testing/selftests/resctrl/mbm_test.c +++ b/tools/testing/selftests/resctrl/mbm_test.c @@ -132,7 +132,6 @@ static void mbm_test_cleanup(void) static int mbm_run_test(const struct resctrl_test *test, const struct user_params *uparams) { struct resctrl_val_param param = { - .resctrl_val = MBM_STR, .ctrlgrp = "c1", .filename = RESULT_FILE_NAME, .init = mbm_init, diff --git a/tools/testing/selftests/resctrl/resctrl.h b/tools/testing/selftests/resctrl/resctrl.h index a999fbc13fd3..2dda56084588 100644 --- a/tools/testing/selftests/resctrl/resctrl.h +++ b/tools/testing/selftests/resctrl/resctrl.h @@ -81,7 +81,6 @@ struct resctrl_test { /* * resctrl_val_param: resctrl test parameters - * @resctrl_val: Resctrl feature (Eg: mbm, mba.. etc) * @ctrlgrp: Name of the control monitor group (con_mon grp) * @mongrp: Name of the monitor group (mon grp) * @filename: Name of file to which the o/p should be written @@ -90,7 +89,6 @@ struct resctrl_test { * @measure: Callback that performs the measurement (a single test) */ struct resctrl_val_param { - char *resctrl_val; const char *ctrlgrp; const char *mongrp; char filename[64]; @@ -113,11 +111,6 @@ struct perf_event_read { } values[2]; }; -#define MBM_STR "mbm" -#define MBA_STR "mba" -#define CMT_STR "cmt" -#define CAT_STR "cat" - /* * Memory location that consumes values compiler must not optimize away. * Volatile ensures writes to this location cannot be optimized away by @@ -143,8 +136,7 @@ int taskset_benchmark(pid_t bm_pid, int cpu_no, cpu_set_t *old_affinity); int taskset_restore(pid_t bm_pid, cpu_set_t *old_affinity); int write_schemata(const char *ctrlgrp, char *schemata, int cpu_no, const char *resource); -int write_bm_pid_to_resctrl(pid_t bm_pid, const char *ctrlgrp, - const char *mongrp, const char *resctrl_val); +int write_bm_pid_to_resctrl(pid_t bm_pid, const char *ctrlgrp, const char *mongrp); int perf_event_open(struct perf_event_attr *hw_event, pid_t pid, int cpu, int group_fd, unsigned long flags); unsigned char *alloc_buffer(size_t buf_size, int memflush); diff --git a/tools/testing/selftests/resctrl/resctrl_val.c b/tools/testing/selftests/resctrl/resctrl_val.c index 0a0abc860a7f..8c275f6b4dd7 100644 --- a/tools/testing/selftests/resctrl/resctrl_val.c +++ b/tools/testing/selftests/resctrl/resctrl_val.c @@ -684,7 +684,6 @@ int resctrl_val(const struct resctrl_test *test, const char * const *benchmark_cmd, struct resctrl_val_param *param) { - char *resctrl_val = param->resctrl_val; struct sigaction sigact; int ret = 0, pipefd[2]; char pipe_message = 0; @@ -775,8 +774,7 @@ int resctrl_val(const struct resctrl_test *test, goto out; /* Write benchmark to specified control&monitoring grp in resctrl FS */ - ret = write_bm_pid_to_resctrl(bm_pid, param->ctrlgrp, param->mongrp, - resctrl_val); + ret = write_bm_pid_to_resctrl(bm_pid, param->ctrlgrp, param->mongrp); if (ret) goto out; diff --git a/tools/testing/selftests/resctrl/resctrlfs.c b/tools/testing/selftests/resctrl/resctrlfs.c index e2d1ecb55d51..250c320349a7 100644 --- a/tools/testing/selftests/resctrl/resctrlfs.c +++ b/tools/testing/selftests/resctrl/resctrlfs.c @@ -522,7 +522,6 @@ static int write_pid_to_tasks(char *tasks, pid_t pid) * @bm_pid: PID that should be written * @ctrlgrp: Name of the control monitor group (con_mon grp) * @mongrp: Name of the monitor group (mon grp) - * @resctrl_val: Resctrl feature (Eg: mbm, mba.. etc) * * If a con_mon grp is requested, create it and write pid to it, otherwise * write pid to root con_mon grp. @@ -532,8 +531,7 @@ static int write_pid_to_tasks(char *tasks, pid_t pid) * * Return: 0 on success, < 0 on error. */ -int write_bm_pid_to_resctrl(pid_t bm_pid, const char *ctrlgrp, - const char *mongrp, const char *resctrl_val) +int write_bm_pid_to_resctrl(pid_t bm_pid, const char *ctrlgrp, const char *mongrp) { char controlgroup[128], monitorgroup[512], monitorgroup_p[256]; char tasks[1024]; @@ -553,22 +551,19 @@ int write_bm_pid_to_resctrl(pid_t bm_pid, const char *ctrlgrp, if (ret) goto out; - /* Create mon grp and write pid into it for "mbm" and "cmt" test */ - if (!strncmp(resctrl_val, CMT_STR, sizeof(CMT_STR)) || - !strncmp(resctrl_val, MBM_STR, sizeof(MBM_STR))) { - if (mongrp) { - sprintf(monitorgroup_p, "%s/mon_groups", controlgroup); - sprintf(monitorgroup, "%s/%s", monitorgroup_p, mongrp); - ret = create_grp(mongrp, monitorgroup, monitorgroup_p); - if (ret) - goto out; - - sprintf(tasks, "%s/mon_groups/%s/tasks", - controlgroup, mongrp); - ret = write_pid_to_tasks(tasks, bm_pid); - if (ret) - goto out; - } + /* Create monitor group and write pid into if it is used */ + if (mongrp) { + sprintf(monitorgroup_p, "%s/mon_groups", controlgroup); + sprintf(monitorgroup, "%s/%s", monitorgroup_p, mongrp); + ret = create_grp(mongrp, monitorgroup, monitorgroup_p); + if (ret) + goto out; + + sprintf(tasks, "%s/mon_groups/%s/tasks", + controlgroup, mongrp); + ret = write_pid_to_tasks(tasks, bm_pid); + if (ret) + goto out; } out: -- cgit v1.2.3-58-ga151 From b00db6fd2a301c5057d63c19d596818845c9a603 Mon Sep 17 00:00:00 2001 From: Muhammad Usama Anjum Date: Wed, 12 Jun 2024 12:27:23 +0500 Subject: selftests: Add information about TAP conformance in tests Although "TAP" word is being used already in documentation, but it hasn't been defined in informative way for developers that how to write TAP conformant tests and what are the benefits. Write a short brief about it. Signed-off-by: Muhammad Usama Anjum Signed-off-by: Shuah Khan --- Documentation/dev-tools/kselftest.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Documentation/dev-tools/kselftest.rst b/Documentation/dev-tools/kselftest.rst index dcf634e411bd..f3766e326d1e 100644 --- a/Documentation/dev-tools/kselftest.rst +++ b/Documentation/dev-tools/kselftest.rst @@ -228,6 +228,13 @@ In general, the rules for selftests are * Don't cause the top-level "make run_tests" to fail if your feature is unconfigured. + * The output of tests must conform to the TAP standard to ensure high + testing quality and to capture failures/errors with specific details. + The kselftest.h and kselftest_harness.h headers provide wrappers for + outputting test results. These wrappers should be used for pass, + fail, exit, and skip messages. CI systems can easily parse TAP output + messages to detect test results. + Contributing new tests (details) ================================ -- cgit v1.2.3-58-ga151 From 4eddfafc902b28119c24189c5ba9469bd1607878 Mon Sep 17 00:00:00 2001 From: John Hubbard Date: Wed, 3 Jul 2024 19:42:02 -0700 Subject: selftests/timers: remove unused irqcount variable When building with clang, via: make LLVM=1 -C tools/testing/selftest ...clang warns about an unused irqcount variable. clang is correct: the variable is incremented and then ignored. Fix this by deleting the irqcount variable. Signed-off-by: John Hubbard Acked-by: John Stultz Reviewed-by: Muhammad Usama Anjum Signed-off-by: Shuah Khan --- tools/testing/selftests/timers/rtcpie.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tools/testing/selftests/timers/rtcpie.c b/tools/testing/selftests/timers/rtcpie.c index 4ef2184f1558..7c07edd0d450 100644 --- a/tools/testing/selftests/timers/rtcpie.c +++ b/tools/testing/selftests/timers/rtcpie.c @@ -29,7 +29,7 @@ static const char default_rtc[] = "/dev/rtc0"; int main(int argc, char **argv) { - int i, fd, retval, irqcount = 0; + int i, fd, retval; unsigned long tmp, data, old_pie_rate; const char *rtc = default_rtc; struct timeval start, end, diff; @@ -120,7 +120,6 @@ int main(int argc, char **argv) fprintf(stderr, " %d",i); fflush(stderr); - irqcount++; } /* Disable periodic interrupts */ -- cgit v1.2.3-58-ga151 From 825658b790330ed474547d2b1f87436879ca7da6 Mon Sep 17 00:00:00 2001 From: John Hubbard Date: Thu, 4 Jul 2024 00:24:25 -0700 Subject: selftests/x86: fix Makefile dependencies to work with clang When building with clang, via: make LLVM=1 -C tools/testing/selftests ...the following build failure occurs in selftests/x86: clang: error: cannot specify -o when generating multiple output files This happens because, although gcc doesn't complain if you invoke it like this: gcc file1.c header2.h ...clang won't accept that form--it rejects the .h file(s). Also, the above approach is inaccurate anyway, because file.c includes header2.h in this case, and the inclusion of header2.h on the invocation is an artifact of the Makefile's desire to maintain dependencies. In Makefiles of this type, a better way to do it is to use Makefile dependencies to trigger the appropriate incremental rebuilds, and separately use file lists (see EXTRA_FILES in this commit) to track what to pass to the compiler. This commit splits those concepts up, by setting up both EXTRA_FILES and the Makefile dependencies with a single call to the new Makefile function extra-files. That fixes the build failure, while still providing the correct dependencies in all cases. Acked-by: Muhammad Usama Anjum Signed-off-by: John Hubbard Signed-off-by: Shuah Khan --- tools/testing/selftests/x86/Makefile | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/tools/testing/selftests/x86/Makefile b/tools/testing/selftests/x86/Makefile index 0b872c0a42d2..c1269466e0f8 100644 --- a/tools/testing/selftests/x86/Makefile +++ b/tools/testing/selftests/x86/Makefile @@ -73,10 +73,10 @@ all_64: $(BINARIES_64) EXTRA_CLEAN := $(BINARIES_32) $(BINARIES_64) $(BINARIES_32): $(OUTPUT)/%_32: %.c helpers.h - $(CC) -m32 -o $@ $(CFLAGS) $(EXTRA_CFLAGS) $^ -lrt -ldl -lm + $(CC) -m32 -o $@ $(CFLAGS) $(EXTRA_CFLAGS) $< $(EXTRA_FILES) -lrt -ldl -lm $(BINARIES_64): $(OUTPUT)/%_64: %.c helpers.h - $(CC) -m64 -o $@ $(CFLAGS) $(EXTRA_CFLAGS) $^ -lrt -ldl + $(CC) -m64 -o $@ $(CFLAGS) $(EXTRA_CFLAGS) $< $(EXTRA_FILES) -lrt -ldl # x86_64 users should be encouraged to install 32-bit libraries ifeq ($(CAN_BUILD_I386)$(CAN_BUILD_X86_64),01) @@ -100,10 +100,19 @@ warn_32bit_failure: exit 0; endif -# Some tests have additional dependencies. -$(OUTPUT)/sysret_ss_attrs_64: thunks.S -$(OUTPUT)/ptrace_syscall_32: raw_syscall_helper_32.S -$(OUTPUT)/test_syscall_vdso_32: thunks_32.S +# Add an additional file to the source file list for a given target, and also +# add a Makefile dependency on that same file. However, do these separately, so +# that the compiler invocation ("$(CC) file1.c file2.S") is not combined with +# the dependencies ("header3.h"), because clang, unlike gcc, will not accept +# header files as an input to the compiler invocation. +define extra-files +$(OUTPUT)/$(1): EXTRA_FILES := $(2) +$(OUTPUT)/$(1): $(2) +endef + +$(eval $(call extra-files,sysret_ss_attrs_64,thunks.S)) +$(eval $(call extra-files,ptrace_syscall_32,raw_syscall_helper_32.S)) +$(eval $(call extra-files,test_syscall_vdso_32,thunks_32.S)) # check_initial_reg_state is special: it needs a custom entry, and it # needs to be static so that its interpreter doesn't destroy its initial -- cgit v1.2.3-58-ga151 From bf967fb39e020f4426d13e634d21283758aea3c8 Mon Sep 17 00:00:00 2001 From: Muhammad Usama Anjum Date: Thu, 4 Jul 2024 00:24:26 -0700 Subject: selftests: x86: test_FISTTP: use fisttps instead of ambiguous fisttp Use fisttps instead of fisttp to specify correctly that the output variable is of size short. test_FISTTP.c:28:3: error: ambiguous instructions require an explicit suffix (could be 'fisttps', or 'fisttpl') 28 | " fisttp res16""\n" | ^ :3:2: note: instantiated into assembly here 3 | fisttp res16 | ^ ...followed by three more cases of the same warning for other lines. [jh: removed a bit of duplication from the warnings report, above, and fixed a typo in the title] Signed-off-by: Muhammad Usama Anjum Signed-off-by: John Hubbard Signed-off-by: Shuah Khan --- tools/testing/selftests/x86/test_FISTTP.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/testing/selftests/x86/test_FISTTP.c b/tools/testing/selftests/x86/test_FISTTP.c index 09789c0ce3e9..b9ae9d8cebcb 100644 --- a/tools/testing/selftests/x86/test_FISTTP.c +++ b/tools/testing/selftests/x86/test_FISTTP.c @@ -25,7 +25,7 @@ int test(void) feclearexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW); asm volatile ("\n" " fld1""\n" - " fisttp res16""\n" + " fisttps res16""\n" " fld1""\n" " fisttpl res32""\n" " fld1""\n" @@ -45,7 +45,7 @@ int test(void) feclearexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW); asm volatile ("\n" " fldpi""\n" - " fisttp res16""\n" + " fisttps res16""\n" " fldpi""\n" " fisttpl res32""\n" " fldpi""\n" @@ -66,7 +66,7 @@ int test(void) asm volatile ("\n" " fldpi""\n" " fchs""\n" - " fisttp res16""\n" + " fisttps res16""\n" " fldpi""\n" " fchs""\n" " fisttpl res32""\n" @@ -88,7 +88,7 @@ int test(void) feclearexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW); asm volatile ("\n" " fldln2""\n" - " fisttp res16""\n" + " fisttps res16""\n" " fldln2""\n" " fisttpl res32""\n" " fldln2""\n" -- cgit v1.2.3-58-ga151 From 1158655317b6b6e71980533939dce9ab91d9716b Mon Sep 17 00:00:00 2001 From: John Hubbard Date: Thu, 4 Jul 2024 00:24:27 -0700 Subject: selftests/x86: build fsgsbase_restore.c with clang When building with clang, via: make LLVM=1 -C tools/testing/selftests Fix this by moving the inline asm to "pure" assembly, in two new files: clang_helpers_32.S, clang_helpers_64.S. As a bonus, the pure asm avoids the need for ifdefs, and is now very simple and easy on the eyes. Acked-by: Muhammad Usama Anjum Signed-off-by: John Hubbard Signed-off-by: Shuah Khan --- tools/testing/selftests/x86/Makefile | 2 ++ tools/testing/selftests/x86/clang_helpers_32.S | 11 +++++++++++ tools/testing/selftests/x86/clang_helpers_64.S | 12 ++++++++++++ tools/testing/selftests/x86/fsgsbase_restore.c | 11 +++++------ 4 files changed, 30 insertions(+), 6 deletions(-) create mode 100644 tools/testing/selftests/x86/clang_helpers_32.S create mode 100644 tools/testing/selftests/x86/clang_helpers_64.S diff --git a/tools/testing/selftests/x86/Makefile b/tools/testing/selftests/x86/Makefile index c1269466e0f8..99bc2ef84f5a 100644 --- a/tools/testing/selftests/x86/Makefile +++ b/tools/testing/selftests/x86/Makefile @@ -113,6 +113,8 @@ endef $(eval $(call extra-files,sysret_ss_attrs_64,thunks.S)) $(eval $(call extra-files,ptrace_syscall_32,raw_syscall_helper_32.S)) $(eval $(call extra-files,test_syscall_vdso_32,thunks_32.S)) +$(eval $(call extra-files,fsgsbase_restore_64,clang_helpers_64.S)) +$(eval $(call extra-files,fsgsbase_restore_32,clang_helpers_32.S)) # check_initial_reg_state is special: it needs a custom entry, and it # needs to be static so that its interpreter doesn't destroy its initial diff --git a/tools/testing/selftests/x86/clang_helpers_32.S b/tools/testing/selftests/x86/clang_helpers_32.S new file mode 100644 index 000000000000..dc16271bac70 --- /dev/null +++ b/tools/testing/selftests/x86/clang_helpers_32.S @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * 32-bit assembly helpers for asm operations that lack support in both gcc and + * clang. For example, clang asm does not support segment prefixes. + */ +.global dereference_seg_base +dereference_seg_base: + mov %fs:(0), %eax + ret + +.section .note.GNU-stack,"",%progbits diff --git a/tools/testing/selftests/x86/clang_helpers_64.S b/tools/testing/selftests/x86/clang_helpers_64.S new file mode 100644 index 000000000000..0d81c71cad97 --- /dev/null +++ b/tools/testing/selftests/x86/clang_helpers_64.S @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * 64-bit assembly helpers for asm operations that lack support in both gcc and + * clang. For example, clang asm does not support segment prefixes. + */ +.global dereference_seg_base + +dereference_seg_base: + mov %gs:(0), %rax + ret + +.section .note.GNU-stack,"",%progbits diff --git a/tools/testing/selftests/x86/fsgsbase_restore.c b/tools/testing/selftests/x86/fsgsbase_restore.c index 6fffadc51579..224058c1e4b2 100644 --- a/tools/testing/selftests/x86/fsgsbase_restore.c +++ b/tools/testing/selftests/x86/fsgsbase_restore.c @@ -39,12 +39,11 @@ # define SEG "%fs" #endif -static unsigned int dereference_seg_base(void) -{ - int ret; - asm volatile ("mov %" SEG ":(0), %0" : "=rm" (ret)); - return ret; -} +/* + * Defined in clang_helpers_[32|64].S, because unlike gcc, clang inline asm does + * not support segmentation prefixes. + */ +unsigned int dereference_seg_base(void); static void init_seg(void) { -- cgit v1.2.3-58-ga151 From 2ab9c93d6104e36110754d0778103f7f8719d969 Mon Sep 17 00:00:00 2001 From: John Hubbard Date: Thu, 4 Jul 2024 00:24:28 -0700 Subject: selftests/x86: build sysret_rip.c with clang When building with clang, via: make LLVM=1 -C tools/testing/selftests ...the build fails because clang's inline asm doesn't support all of the features that are used in the asm() snippet in sysret_rip.c. Fix this by moving the asm code into the clang_helpers_64.S file, where it can be built with the assembler's full set of features. Acked-by: Muhammad Usama Anjum Signed-off-by: John Hubbard Signed-off-by: Shuah Khan --- tools/testing/selftests/x86/Makefile | 1 + tools/testing/selftests/x86/clang_helpers_64.S | 16 ++++++++++++++++ tools/testing/selftests/x86/sysret_rip.c | 20 ++++++-------------- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/tools/testing/selftests/x86/Makefile b/tools/testing/selftests/x86/Makefile index 99bc2ef84f5a..d0bb32bd5538 100644 --- a/tools/testing/selftests/x86/Makefile +++ b/tools/testing/selftests/x86/Makefile @@ -115,6 +115,7 @@ $(eval $(call extra-files,ptrace_syscall_32,raw_syscall_helper_32.S)) $(eval $(call extra-files,test_syscall_vdso_32,thunks_32.S)) $(eval $(call extra-files,fsgsbase_restore_64,clang_helpers_64.S)) $(eval $(call extra-files,fsgsbase_restore_32,clang_helpers_32.S)) +$(eval $(call extra-files,sysret_rip_64,clang_helpers_64.S)) # check_initial_reg_state is special: it needs a custom entry, and it # needs to be static so that its interpreter doesn't destroy its initial diff --git a/tools/testing/selftests/x86/clang_helpers_64.S b/tools/testing/selftests/x86/clang_helpers_64.S index 0d81c71cad97..185a69dbf39c 100644 --- a/tools/testing/selftests/x86/clang_helpers_64.S +++ b/tools/testing/selftests/x86/clang_helpers_64.S @@ -9,4 +9,20 @@ dereference_seg_base: mov %gs:(0), %rax ret +.global test_page +.global test_syscall_insn + +.pushsection ".text", "ax" +.balign 4096 +test_page: .globl test_page + .fill 4094,1,0xcc + +test_syscall_insn: + syscall + +.ifne . - test_page - 4096 + .error "test page is not one page long" +.endif +.popsection + .section .note.GNU-stack,"",%progbits diff --git a/tools/testing/selftests/x86/sysret_rip.c b/tools/testing/selftests/x86/sysret_rip.c index 84d74be1d902..b30de9aaa6d4 100644 --- a/tools/testing/selftests/x86/sysret_rip.c +++ b/tools/testing/selftests/x86/sysret_rip.c @@ -22,21 +22,13 @@ #include #include - -asm ( - ".pushsection \".text\", \"ax\"\n\t" - ".balign 4096\n\t" - "test_page: .globl test_page\n\t" - ".fill 4094,1,0xcc\n\t" - "test_syscall_insn:\n\t" - "syscall\n\t" - ".ifne . - test_page - 4096\n\t" - ".error \"test page is not one page long\"\n\t" - ".endif\n\t" - ".popsection" - ); - +/* + * These items are in clang_helpers_64.S, in order to avoid clang inline asm + * limitations: + */ +void test_syscall_ins(void); extern const char test_page[]; + static void const *current_test_page_addr = test_page; static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *), -- cgit v1.2.3-58-ga151 From a89e589051d48f605c11662c35c56be65e1bca64 Mon Sep 17 00:00:00 2001 From: John Hubbard Date: Thu, 4 Jul 2024 00:24:29 -0700 Subject: selftests/x86: avoid -no-pie warnings from clang during compilation When building with clang, via: make LLVM=1 -C tools/testing/selftests ...clang warns that -no-pie is "unused during compilation". This occurs because clang only wants to see -no-pie during linking. Here, we don't have a separate linking stage, so a compiler warning is unavoidable without (wastefully) restructuring the Makefile. Avoid the warning by simply disabling that warning, for clang builds. Acked-by: Muhammad Usama Anjum Signed-off-by: John Hubbard Signed-off-by: Shuah Khan --- tools/testing/selftests/x86/Makefile | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tools/testing/selftests/x86/Makefile b/tools/testing/selftests/x86/Makefile index d0bb32bd5538..5c8757a25998 100644 --- a/tools/testing/selftests/x86/Makefile +++ b/tools/testing/selftests/x86/Makefile @@ -40,6 +40,13 @@ CFLAGS := -O2 -g -std=gnu99 -pthread -Wall $(KHDR_INCLUDES) # call32_from_64 in thunks.S uses absolute addresses. ifeq ($(CAN_BUILD_WITH_NOPIE),1) CFLAGS += -no-pie + +ifneq ($(LLVM),) +# clang only wants to see -no-pie during linking. Here, we don't have a separate +# linking stage, so a compiler warning is unavoidable without (wastefully) +# restructuring the Makefile. Avoid this by simply disabling that warning. +CFLAGS += -Wno-unused-command-line-argument +endif endif define gen-target-rule-32 -- cgit v1.2.3-58-ga151 From 7d17b29b0e4b9a97426873f72e9cc6d35cfaf88f Mon Sep 17 00:00:00 2001 From: John Hubbard Date: Thu, 4 Jul 2024 00:24:30 -0700 Subject: selftests/x86: remove (or use) unused variables and functions When building with clang, via: make LLVM=1 -C tools/testing/selftests ...quite a few functions are variables are generating "unused" warnings. Fix the warnings by deleting the unused items. One item, the "nerrs" variable in vsdo_restorer.c's main(), is unused but probably wants to be returned from main(), as a non-zero result. That result is also unused right now, so another option would be to delete it entirely, but this way, main() also gets fixed. It was missing a return value. Acked-by: Muhammad Usama Anjum Signed-off-by: John Hubbard Signed-off-by: Shuah Khan --- tools/testing/selftests/x86/amx.c | 16 ---------------- tools/testing/selftests/x86/fsgsbase.c | 6 ------ tools/testing/selftests/x86/syscall_arg_fault.c | 1 - tools/testing/selftests/x86/test_vsyscall.c | 5 ----- tools/testing/selftests/x86/vdso_restorer.c | 2 ++ 5 files changed, 2 insertions(+), 28 deletions(-) diff --git a/tools/testing/selftests/x86/amx.c b/tools/testing/selftests/x86/amx.c index 95aad6d8849b..1fdf35a4d7f6 100644 --- a/tools/testing/selftests/x86/amx.c +++ b/tools/testing/selftests/x86/amx.c @@ -39,16 +39,6 @@ struct xsave_buffer { }; }; -static inline uint64_t xgetbv(uint32_t index) -{ - uint32_t eax, edx; - - asm volatile("xgetbv;" - : "=a" (eax), "=d" (edx) - : "c" (index)); - return eax + ((uint64_t)edx << 32); -} - static inline void xsave(struct xsave_buffer *xbuf, uint64_t rfbm) { uint32_t rfbm_lo = rfbm; @@ -164,12 +154,6 @@ static inline void clear_xstate_header(struct xsave_buffer *buffer) memset(&buffer->header, 0, sizeof(buffer->header)); } -static inline uint64_t get_xstatebv(struct xsave_buffer *buffer) -{ - /* XSTATE_BV is at the beginning of the header: */ - return *(uint64_t *)&buffer->header; -} - static inline void set_xstatebv(struct xsave_buffer *buffer, uint64_t bv) { /* XSTATE_BV is at the beginning of the header: */ diff --git a/tools/testing/selftests/x86/fsgsbase.c b/tools/testing/selftests/x86/fsgsbase.c index 8c780cce941d..50cf32de6313 100644 --- a/tools/testing/selftests/x86/fsgsbase.c +++ b/tools/testing/selftests/x86/fsgsbase.c @@ -109,11 +109,6 @@ static inline void wrgsbase(unsigned long gsbase) asm volatile("wrgsbase %0" :: "r" (gsbase) : "memory"); } -static inline void wrfsbase(unsigned long fsbase) -{ - asm volatile("wrfsbase %0" :: "r" (fsbase) : "memory"); -} - enum which_base { FS, GS }; static unsigned long read_base(enum which_base which) @@ -212,7 +207,6 @@ static void mov_0_gs(unsigned long initial_base, bool schedule) } static volatile unsigned long remote_base; -static volatile bool remote_hard_zero; static volatile unsigned int ftx; /* diff --git a/tools/testing/selftests/x86/syscall_arg_fault.c b/tools/testing/selftests/x86/syscall_arg_fault.c index 461fa41a4d02..48ab065a76f9 100644 --- a/tools/testing/selftests/x86/syscall_arg_fault.c +++ b/tools/testing/selftests/x86/syscall_arg_fault.c @@ -29,7 +29,6 @@ static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *), err(1, "sigaction"); } -static volatile sig_atomic_t sig_traps; static sigjmp_buf jmpbuf; static volatile sig_atomic_t n_errs; diff --git a/tools/testing/selftests/x86/test_vsyscall.c b/tools/testing/selftests/x86/test_vsyscall.c index d4c8e8d79d38..1c9895cfc660 100644 --- a/tools/testing/selftests/x86/test_vsyscall.c +++ b/tools/testing/selftests/x86/test_vsyscall.c @@ -97,11 +97,6 @@ static inline long sys_gtod(struct timeval *tv, struct timezone *tz) return syscall(SYS_gettimeofday, tv, tz); } -static inline int sys_clock_gettime(clockid_t id, struct timespec *ts) -{ - return syscall(SYS_clock_gettime, id, ts); -} - static inline long sys_time(time_t *t) { return syscall(SYS_time, t); diff --git a/tools/testing/selftests/x86/vdso_restorer.c b/tools/testing/selftests/x86/vdso_restorer.c index fe99f2434155..ac8d8e1e9805 100644 --- a/tools/testing/selftests/x86/vdso_restorer.c +++ b/tools/testing/selftests/x86/vdso_restorer.c @@ -92,4 +92,6 @@ int main() printf("[FAIL]\t!SA_SIGINFO handler was not called\n"); nerrs++; } + + return nerrs; } -- cgit v1.2.3-58-ga151 From b84111cda99845b2ff248bae37b34f57882d513c Mon Sep 17 00:00:00 2001 From: John Hubbard Date: Thu, 4 Jul 2024 00:24:31 -0700 Subject: selftests/x86: fix printk warnings reported by clang These warnings are all of the form, "the format specified a short (signed or unsigned) int, but the value is a full length int". Acked-by: Muhammad Usama Anjum Signed-off-by: John Hubbard Signed-off-by: Shuah Khan --- tools/testing/selftests/x86/sigreturn.c | 2 +- tools/testing/selftests/x86/test_vsyscall.c | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/testing/selftests/x86/sigreturn.c b/tools/testing/selftests/x86/sigreturn.c index 5d7961a5f7f6..0b75b29f794b 100644 --- a/tools/testing/selftests/x86/sigreturn.c +++ b/tools/testing/selftests/x86/sigreturn.c @@ -487,7 +487,7 @@ static void sigtrap(int sig, siginfo_t *info, void *ctx_void) greg_t asm_ss = ctx->uc_mcontext.gregs[REG_CX]; if (asm_ss != sig_ss && sig == SIGTRAP) { /* Sanity check failure. */ - printf("[FAIL]\tSIGTRAP: ss = %hx, frame ss = %hx, ax = %llx\n", + printf("[FAIL]\tSIGTRAP: ss = %hx, frame ss = %x, ax = %llx\n", ss, *ssptr(ctx), (unsigned long long)asm_ss); nerrs++; } diff --git a/tools/testing/selftests/x86/test_vsyscall.c b/tools/testing/selftests/x86/test_vsyscall.c index 1c9895cfc660..6de11b4df458 100644 --- a/tools/testing/selftests/x86/test_vsyscall.c +++ b/tools/testing/selftests/x86/test_vsyscall.c @@ -247,7 +247,7 @@ static void test_getcpu(int cpu) if (ret_sys == 0) { if (cpu_sys != cpu) - ksft_print_msg("syscall reported CPU %hu but should be %d\n", + ksft_print_msg("syscall reported CPU %u but should be %d\n", cpu_sys, cpu); have_node = true; @@ -265,10 +265,10 @@ static void test_getcpu(int cpu) if (cpu_vdso != cpu || node_vdso != node) { if (cpu_vdso != cpu) - ksft_print_msg("vDSO reported CPU %hu but should be %d\n", + ksft_print_msg("vDSO reported CPU %u but should be %d\n", cpu_vdso, cpu); if (node_vdso != node) - ksft_print_msg("vDSO reported node %hu but should be %hu\n", + ksft_print_msg("vDSO reported node %u but should be %u\n", node_vdso, node); ksft_test_result_fail("Wrong values\n"); } else { @@ -290,10 +290,10 @@ static void test_getcpu(int cpu) if (cpu_vsys != cpu || node_vsys != node) { if (cpu_vsys != cpu) - ksft_print_msg("vsyscall reported CPU %hu but should be %d\n", + ksft_print_msg("vsyscall reported CPU %u but should be %d\n", cpu_vsys, cpu); if (node_vsys != node) - ksft_print_msg("vsyscall reported node %hu but should be %hu\n", + ksft_print_msg("vsyscall reported node %u but should be %u\n", node_vsys, node); ksft_test_result_fail("Wrong values\n"); } else { -- cgit v1.2.3-58-ga151 From e23b1e6a2b9c88c2a69c43f5e525fafec6d6bba0 Mon Sep 17 00:00:00 2001 From: Zhu Jun Date: Tue, 9 Jul 2024 19:11:36 -0700 Subject: selftests/breakpoints:Remove unused variable This variable is never referenced in the code, just remove them that this problem was discovered by reading the code Signed-off-by: Zhu Jun Signed-off-by: Shuah Khan --- tools/testing/selftests/breakpoints/step_after_suspend_test.c | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/testing/selftests/breakpoints/step_after_suspend_test.c b/tools/testing/selftests/breakpoints/step_after_suspend_test.c index b8703c499d28..dfec31fb9b30 100644 --- a/tools/testing/selftests/breakpoints/step_after_suspend_test.c +++ b/tools/testing/selftests/breakpoints/step_after_suspend_test.c @@ -130,7 +130,6 @@ int run_test(int cpu) void suspend(void) { int power_state_fd; - struct sigevent event = {}; int timerfd; int err; struct itimerspec spec = {}; -- cgit v1.2.3-58-ga151 From df09b0bb09ea9775b66a5d24dc0fe0f86855efb5 Mon Sep 17 00:00:00 2001 From: Zhu Jun Date: Tue, 9 Jul 2024 23:57:59 -0700 Subject: selftests/dma:remove unused variable The variable are never referenced in the code, just remove it that this problem was discovered by reading code Signed-off-by: Zhu Jun Signed-off-by: Shuah Khan --- tools/testing/selftests/dma/dma_map_benchmark.c | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/testing/selftests/dma/dma_map_benchmark.c b/tools/testing/selftests/dma/dma_map_benchmark.c index 5c997f17fcbd..b12f1f9babf8 100644 --- a/tools/testing/selftests/dma/dma_map_benchmark.c +++ b/tools/testing/selftests/dma/dma_map_benchmark.c @@ -33,7 +33,6 @@ int main(int argc, char **argv) int granule = 1; int cmd = DMA_MAP_BENCHMARK; - char *p; while ((opt = getopt(argc, argv, "t:s:n:b:d:x:g:")) != -1) { switch (opt) { -- cgit v1.2.3-58-ga151 From 8e51106d02d32cd83807fa56c602020c2309ace0 Mon Sep 17 00:00:00 2001 From: Pengfei Xu Date: Fri, 31 May 2024 15:53:47 +0800 Subject: selftests: ifs: verify test interfaces are created by the driver IFS (In Field Scan) driver exposes its functionality via sysfs interfaces. Applications prepare and exercise the tests by interacting with the aforementioned sysfs files. Verify that the necessary sysfs entries are created after loading the IFS driver. Initialize test variables needed for building subsequent kself-test cases. Reviewed-by: Jithu Joseph Reviewed-by: Kuppuswamy Sathyanarayanan Co-developed-by: Ashok Raj Signed-off-by: Ashok Raj Signed-off-by: Pengfei Xu Acked-by: Jithu Joseph Signed-off-by: Shuah Khan --- MAINTAINERS | 1 + tools/testing/selftests/Makefile | 1 + .../drivers/platform/x86/intel/ifs/Makefile | 6 + .../drivers/platform/x86/intel/ifs/test_ifs.sh | 179 +++++++++++++++++++++ 4 files changed, 187 insertions(+) create mode 100644 tools/testing/selftests/drivers/platform/x86/intel/ifs/Makefile create mode 100755 tools/testing/selftests/drivers/platform/x86/intel/ifs/test_ifs.sh diff --git a/MAINTAINERS b/MAINTAINERS index da5352dbd4f3..e25d391433ae 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11142,6 +11142,7 @@ R: Tony Luck S: Maintained F: drivers/platform/x86/intel/ifs F: include/trace/events/intel_ifs.h +F: tools/testing/selftests/drivers/platform/x86/intel/ifs/ INTEL INTEGRATED SENSOR HUB DRIVER M: Srinivas Pandruvada diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile index 9039f3709aff..06eed383fdc0 100644 --- a/tools/testing/selftests/Makefile +++ b/tools/testing/selftests/Makefile @@ -21,6 +21,7 @@ TARGETS += drivers/net TARGETS += drivers/net/bonding TARGETS += drivers/net/team TARGETS += drivers/net/virtio_net +TARGETS += drivers/platform/x86/intel/ifs TARGETS += dt TARGETS += efivarfs TARGETS += exec diff --git a/tools/testing/selftests/drivers/platform/x86/intel/ifs/Makefile b/tools/testing/selftests/drivers/platform/x86/intel/ifs/Makefile new file mode 100644 index 000000000000..03d0449d307c --- /dev/null +++ b/tools/testing/selftests/drivers/platform/x86/intel/ifs/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0 +# Makefile for ifs(In Field Scan) selftests + +TEST_PROGS := test_ifs.sh + +include ../../../../../lib.mk diff --git a/tools/testing/selftests/drivers/platform/x86/intel/ifs/test_ifs.sh b/tools/testing/selftests/drivers/platform/x86/intel/ifs/test_ifs.sh new file mode 100755 index 000000000000..90d099578199 --- /dev/null +++ b/tools/testing/selftests/drivers/platform/x86/intel/ifs/test_ifs.sh @@ -0,0 +1,179 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# +# Test the functionality of the Intel IFS(In Field Scan) driver. +# + +# Matched with kselftest framework: tools/testing/selftests/kselftest.h +readonly KSFT_PASS=0 +readonly KSFT_FAIL=1 +readonly KSFT_XFAIL=2 +readonly KSFT_SKIP=4 + +readonly IFS_SCAN_MODE="0" +readonly IFS_PATH="/sys/devices/virtual/misc/intel_ifs" +readonly IFS_SCAN_SYSFS_PATH="${IFS_PATH}_${IFS_SCAN_MODE}" +readonly PASS="PASS" +readonly FAIL="FAIL" +readonly INFO="INFO" +readonly XFAIL="XFAIL" +readonly SKIP="SKIP" +readonly IFS_NAME="intel_ifs" + +# Matches arch/x86/include/asm/intel-family.h and +# drivers/platform/x86/intel/ifs/core.c requirement as follows +readonly SAPPHIRERAPIDS_X="8f" +readonly EMERALDRAPIDS_X="cf" + +readonly INTEL_FAM6="06" + +FML="" +MODEL="" + +TRUE="true" +FALSE="false" +RESULT=$KSFT_PASS +export INTERVAL_TIME=1 +# For IFS cleanup tags +ORIGIN_IFS_LOADED="" +IFS_LOG="/tmp/ifs_logs.$$" + +append_log() +{ + echo -e "$1" | tee -a "$IFS_LOG" +} + +ifs_scan_result_summary() +{ + local failed_info pass_num skip_num fail_num + + if [[ -e "$IFS_LOG" ]]; then + failed_info=$(grep ^"\[${FAIL}\]" "$IFS_LOG") + fail_num=$(grep -c ^"\[${FAIL}\]" "$IFS_LOG") + skip_num=$(grep -c ^"\[${SKIP}\]" "$IFS_LOG") + pass_num=$(grep -c ^"\[${PASS}\]" "$IFS_LOG") + + if [[ "$fail_num" -ne 0 ]]; then + RESULT=$KSFT_FAIL + echo "[$INFO] IFS test failure summary:" + echo "$failed_info" + elif [[ "$skip_num" -ne 0 ]]; then + RESULT=$KSFT_SKIP + fi + echo "[$INFO] IFS test pass:$pass_num, skip:$skip_num, fail:$fail_num" + else + echo "[$INFO] No file $IFS_LOG for IFS scan summary" + fi +} + +ifs_cleanup() +{ + lsmod | grep -q "$IFS_NAME" && [[ "$ORIGIN_IFS_LOADED" == "$FALSE" ]] && { + echo "[$INFO] modprobe -r $IFS_NAME" + modprobe -r "$IFS_NAME" + } + + ifs_scan_result_summary + [[ -e "$IFS_LOG" ]] && rm -rf "$IFS_LOG" + + echo "[RESULT] IFS test exit with $RESULT" + exit "$RESULT" +} + +test_exit() +{ + local info=$1 + RESULT=$2 + + declare -A EXIT_MAP + EXIT_MAP[$KSFT_PASS]=$PASS + EXIT_MAP[$KSFT_FAIL]=$FAIL + EXIT_MAP[$KSFT_XFAIL]=$XFAIL + EXIT_MAP[$KSFT_SKIP]=$SKIP + + append_log "[${EXIT_MAP[$RESULT]}] $info" + ifs_cleanup +} + +get_cpu_fms() +{ + FML=$(grep -m 1 "family" /proc/cpuinfo | awk -F ":" '{printf "%02x",$2;}') + MODEL=$(grep -m 1 "model" /proc/cpuinfo | awk -F ":" '{printf "%02x",$2;}') +} + +check_cpu_ifs_support_interval_time() +{ + get_cpu_fms + + if [[ "$FML" != "$INTEL_FAM6" ]]; then + test_exit "CPU family:$FML does not support IFS" "$KSFT_SKIP" + fi + + # Ucode has time interval requirement for IFS scan on same CPU as follows: + case $MODEL in + "$SAPPHIRERAPIDS_X") + INTERVAL_TIME=180; + ;; + "$EMERALDRAPIDS_X") + INTERVAL_TIME=30; + ;; + *) + # Set default interval time for other platforms + INTERVAL_TIME=1; + append_log "[$INFO] CPU FML:$FML model:0x$MODEL, default: 1s interval time" + ;; + esac +} + +check_ifs_loaded() +{ + local ifs_info="" + + ifs_info=$(lsmod | grep "$IFS_NAME") + if [[ -z "$ifs_info" ]]; then + append_log "[$INFO] modprobe $IFS_NAME" + modprobe "$IFS_NAME" || { + test_exit "Check if CONFIG_INTEL_IFS is set to m or \ +platform doesn't support ifs" "$KSFT_SKIP" + } + ifs_info=$(lsmod | grep "$IFS_NAME") + [[ -n "$ifs_info" ]] || test_exit "No ifs module listed by lsmod" "$KSFT_FAIL" + fi +} + +test_ifs_scan_entry() +{ + local ifs_info="" + + ifs_info=$(lsmod | grep "$IFS_NAME") + + if [[ -z "$ifs_info" ]]; then + ORIGIN_IFS_LOADED="$FALSE" + check_ifs_loaded + else + ORIGIN_IFS_LOADED="$TRUE" + append_log "[$INFO] Module $IFS_NAME is already loaded" + fi + + if [[ -d "$IFS_SCAN_SYSFS_PATH" ]]; then + append_log "[$PASS] IFS sysfs $IFS_SCAN_SYSFS_PATH entry is created\n" + else + test_exit "No sysfs entry in $IFS_SCAN_SYSFS_PATH" "$KSFT_FAIL" + fi +} + +prepare_ifs_test_env() +{ + check_cpu_ifs_support_interval_time +} + +test_ifs() +{ + prepare_ifs_test_env + + test_ifs_scan_entry +} + +trap ifs_cleanup SIGTERM SIGINT +test_ifs +ifs_cleanup -- cgit v1.2.3-58-ga151 From 20cef3039dcd6930e1a08c948a360eac5c0fce88 Mon Sep 17 00:00:00 2001 From: Pengfei Xu Date: Fri, 31 May 2024 15:53:48 +0800 Subject: selftests: ifs: verify test image loading functionality Scan test image files have to be loaded before starting IFS test. Verify that In Field scan driver is able to load valid test image files. Also check if loading an invalid test image file fails. Reviewed-by: Jithu Joseph Reviewed-by: Kuppuswamy Sathyanarayanan Co-developed-by: Ashok Raj Signed-off-by: Ashok Raj Signed-off-by: Pengfei Xu Acked-by: Jithu Joseph Signed-off-by: Shuah Khan --- .../drivers/platform/x86/intel/ifs/test_ifs.sh | 121 ++++++++++++++++++++- 1 file changed, 120 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/drivers/platform/x86/intel/ifs/test_ifs.sh b/tools/testing/selftests/drivers/platform/x86/intel/ifs/test_ifs.sh index 90d099578199..dc78ad9100ca 100755 --- a/tools/testing/selftests/drivers/platform/x86/intel/ifs/test_ifs.sh +++ b/tools/testing/selftests/drivers/platform/x86/intel/ifs/test_ifs.sh @@ -10,6 +10,7 @@ readonly KSFT_FAIL=1 readonly KSFT_XFAIL=2 readonly KSFT_SKIP=4 +readonly IMG_PATH="/lib/firmware/intel/ifs_0" readonly IFS_SCAN_MODE="0" readonly IFS_PATH="/sys/devices/virtual/misc/intel_ifs" readonly IFS_SCAN_SYSFS_PATH="${IFS_PATH}_${IFS_SCAN_MODE}" @@ -29,14 +30,18 @@ readonly INTEL_FAM6="06" FML="" MODEL="" - +STEPPING="" +CPU_FMS="" TRUE="true" FALSE="false" RESULT=$KSFT_PASS +IMAGE_NAME="" export INTERVAL_TIME=1 # For IFS cleanup tags ORIGIN_IFS_LOADED="" +IFS_IMAGE_NEED_RESTORE=$FALSE IFS_LOG="/tmp/ifs_logs.$$" +DEFAULT_IMG_ID="" append_log() { @@ -68,6 +73,13 @@ ifs_scan_result_summary() ifs_cleanup() { + echo "[$INFO] Restore environment after IFS test" + + # Restore ifs origin image if origin image backup step is needed + [[ "$IFS_IMAGE_NEED_RESTORE" == "$TRUE" ]] && { + mv -f "$IMG_PATH"/"$IMAGE_NAME"_origin "$IMG_PATH"/"$IMAGE_NAME" + } + lsmod | grep -q "$IFS_NAME" && [[ "$ORIGIN_IFS_LOADED" == "$FALSE" ]] && { echo "[$INFO] modprobe -r $IFS_NAME" modprobe -r "$IFS_NAME" @@ -80,6 +92,21 @@ ifs_cleanup() exit "$RESULT" } +do_cmd() +{ + local cmd=$* + local ret="" + + append_log "[$INFO] $cmd" + eval "$cmd" + ret=$? + if [[ $ret -ne 0 ]]; then + append_log "[$FAIL] $cmd failed. Return code is $ret" + RESULT=$KSFT_XFAIL + ifs_cleanup + fi +} + test_exit() { local info=$1 @@ -99,6 +126,8 @@ get_cpu_fms() { FML=$(grep -m 1 "family" /proc/cpuinfo | awk -F ":" '{printf "%02x",$2;}') MODEL=$(grep -m 1 "model" /proc/cpuinfo | awk -F ":" '{printf "%02x",$2;}') + STEPPING=$(grep -m 1 "stepping" /proc/cpuinfo | awk -F ":" '{printf "%02x",$2;}') + CPU_FMS="${FML}-${MODEL}-${STEPPING}" } check_cpu_ifs_support_interval_time() @@ -162,9 +191,93 @@ test_ifs_scan_entry() fi } +load_image() +{ + local image_id=$1 + local image_info="" + local ret="" + + check_ifs_loaded + if [[ -e "${IMG_PATH}/${IMAGE_NAME}" ]]; then + append_log "[$INFO] echo 0x$image_id > ${IFS_SCAN_SYSFS_PATH}/current_batch" + echo "0x$image_id" > "$IFS_SCAN_SYSFS_PATH"/current_batch 2>/dev/null + ret=$? + [[ "$ret" -eq 0 ]] || { + append_log "[$FAIL] Load ifs image $image_id failed with ret:$ret\n" + return "$ret" + } + image_info=$(cat ${IFS_SCAN_SYSFS_PATH}/current_batch) + if [[ "$image_info" == 0x"$image_id" ]]; then + append_log "[$PASS] load IFS current_batch:$image_info" + else + append_log "[$FAIL] current_batch:$image_info is not expected:$image_id" + return "$KSFT_FAIL" + fi + else + append_log "[$FAIL] No IFS image file ${IMG_PATH}/${IMAGE_NAME}"\ + return "$KSFT_FAIL" + fi + return 0 +} + +test_load_origin_ifs_image() +{ + local image_id=$1 + + IMAGE_NAME="${CPU_FMS}-${image_id}.scan" + + load_image "$image_id" || return $? + return 0 +} + +test_load_bad_ifs_image() +{ + local image_id=$1 + + IMAGE_NAME="${CPU_FMS}-${image_id}.scan" + + do_cmd "mv -f ${IMG_PATH}/${IMAGE_NAME} ${IMG_PATH}/${IMAGE_NAME}_origin" + + # Set IFS_IMAGE_NEED_RESTORE to true before corrupt the origin ifs image file + IFS_IMAGE_NEED_RESTORE=$TRUE + do_cmd "dd if=/dev/urandom of=${IMG_PATH}/${IMAGE_NAME} bs=1K count=6 2>/dev/null" + + # Use the specified judgment for negative testing + append_log "[$INFO] echo 0x$image_id > ${IFS_SCAN_SYSFS_PATH}/current_batch" + echo "0x$image_id" > "$IFS_SCAN_SYSFS_PATH"/current_batch 2>/dev/null + ret=$? + if [[ "$ret" -ne 0 ]]; then + append_log "[$PASS] Load invalid ifs image failed with ret:$ret not 0 as expected" + else + append_log "[$FAIL] Load invalid ifs image ret:$ret unexpectedly" + fi + + do_cmd "mv -f ${IMG_PATH}/${IMAGE_NAME}_origin ${IMG_PATH}/${IMAGE_NAME}" + IFS_IMAGE_NEED_RESTORE=$FALSE +} + +test_bad_and_origin_ifs_image() +{ + local image_id=$1 + + append_log "[$INFO] Test loading bad and then loading original IFS image:" + test_load_origin_ifs_image "$image_id" || return $? + test_load_bad_ifs_image "$image_id" + # Load origin image again and make sure it's worked + test_load_origin_ifs_image "$image_id" || return $? + append_log "[$INFO] Loading invalid IFS image and then loading initial image passed.\n" +} + prepare_ifs_test_env() { check_cpu_ifs_support_interval_time + + DEFAULT_IMG_ID=$(find $IMG_PATH -maxdepth 1 -name "${CPU_FMS}-[0-9a-fA-F][0-9a-fA-F].scan" \ + 2>/dev/null \ + | sort \ + | head -n 1 \ + | awk -F "-" '{print $NF}' \ + | cut -d "." -f 1) } test_ifs() @@ -172,6 +285,12 @@ test_ifs() prepare_ifs_test_env test_ifs_scan_entry + + if [[ -z "$DEFAULT_IMG_ID" ]]; then + append_log "[$SKIP] No proper ${IMG_PATH}/${CPU_FMS}-*.scan, skip ifs_0 scan" + else + test_bad_and_origin_ifs_image "$DEFAULT_IMG_ID" + fi } trap ifs_cleanup SIGTERM SIGINT -- cgit v1.2.3-58-ga151 From 3170f7acfba15895844dc2c0f2d2ff6fd77ad2e1 Mon Sep 17 00:00:00 2001 From: Pengfei Xu Date: Fri, 31 May 2024 15:53:49 +0800 Subject: selftests: ifs: verify IFS scan test functionality Two selftests are added to verify IFS scan test feature: 1. Perform IFS scan test once on each CPU using all the available image files. 2. Perform IFS scan test with the default image on a random cpu for 3 rounds. Reviewed-by: Jithu Joseph Reviewed-by: Kuppuswamy Sathyanarayanan Co-developed-by: Ashok Raj Signed-off-by: Ashok Raj Signed-off-by: Pengfei Xu Acked-by: Jithu Joseph Signed-off-by: Shuah Khan --- .../drivers/platform/x86/intel/ifs/test_ifs.sh | 190 ++++++++++++++++++++- 1 file changed, 189 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/drivers/platform/x86/intel/ifs/test_ifs.sh b/tools/testing/selftests/drivers/platform/x86/intel/ifs/test_ifs.sh index dc78ad9100ca..82fc5a461b12 100755 --- a/tools/testing/selftests/drivers/platform/x86/intel/ifs/test_ifs.sh +++ b/tools/testing/selftests/drivers/platform/x86/intel/ifs/test_ifs.sh @@ -10,16 +10,25 @@ readonly KSFT_FAIL=1 readonly KSFT_XFAIL=2 readonly KSFT_SKIP=4 +readonly CPU_SYSFS="/sys/devices/system/cpu" +readonly CPU_OFFLINE_SYSFS="${CPU_SYSFS}/offline" readonly IMG_PATH="/lib/firmware/intel/ifs_0" readonly IFS_SCAN_MODE="0" +readonly IFS_ARRAY_BIST_SCAN_MODE="1" readonly IFS_PATH="/sys/devices/virtual/misc/intel_ifs" readonly IFS_SCAN_SYSFS_PATH="${IFS_PATH}_${IFS_SCAN_MODE}" +readonly RUN_TEST="run_test" +readonly STATUS="status" +readonly DETAILS="details" +readonly STATUS_PASS="pass" readonly PASS="PASS" readonly FAIL="FAIL" readonly INFO="INFO" readonly XFAIL="XFAIL" readonly SKIP="SKIP" readonly IFS_NAME="intel_ifs" +readonly ALL="all" +readonly SIBLINGS="siblings" # Matches arch/x86/include/asm/intel-family.h and # drivers/platform/x86/intel/ifs/core.c requirement as follows @@ -28,6 +37,7 @@ readonly EMERALDRAPIDS_X="cf" readonly INTEL_FAM6="06" +LOOP_TIMES=3 FML="" MODEL="" STEPPING="" @@ -36,11 +46,13 @@ TRUE="true" FALSE="false" RESULT=$KSFT_PASS IMAGE_NAME="" -export INTERVAL_TIME=1 +INTERVAL_TIME=1 +OFFLINE_CPUS="" # For IFS cleanup tags ORIGIN_IFS_LOADED="" IFS_IMAGE_NEED_RESTORE=$FALSE IFS_LOG="/tmp/ifs_logs.$$" +RANDOM_CPU="" DEFAULT_IMG_ID="" append_log() @@ -48,6 +60,35 @@ append_log() echo -e "$1" | tee -a "$IFS_LOG" } +online_offline_cpu_list() +{ + local on_off=$1 + local target_cpus=$2 + local cpu="" + local cpu_start="" + local cpu_end="" + local i="" + + if [[ -n "$target_cpus" ]]; then + for cpu in $(echo "$target_cpus" | tr ',' ' '); do + if [[ "$cpu" == *"-"* ]]; then + cpu_start="" + cpu_end="" + i="" + cpu_start=$(echo "$cpu" | cut -d "-" -f 1) + cpu_end=$(echo "$cpu" | cut -d "-" -f 2) + for((i=cpu_start;i<=cpu_end;i++)); do + append_log "[$INFO] echo $on_off > \ +${CPU_SYSFS}/cpu${i}/online" + echo "$on_off" > "$CPU_SYSFS"/cpu"$i"/online + done + else + set_target_cpu "$on_off" "$cpu" + fi + done + fi +} + ifs_scan_result_summary() { local failed_info pass_num skip_num fail_num @@ -80,6 +121,9 @@ ifs_cleanup() mv -f "$IMG_PATH"/"$IMAGE_NAME"_origin "$IMG_PATH"/"$IMAGE_NAME" } + # Restore the CPUs to the state before testing + [[ -z "$OFFLINE_CPUS" ]] || online_offline_cpu_list "0" "$OFFLINE_CPUS" + lsmod | grep -q "$IFS_NAME" && [[ "$ORIGIN_IFS_LOADED" == "$FALSE" ]] && { echo "[$INFO] modprobe -r $IFS_NAME" modprobe -r "$IFS_NAME" @@ -122,6 +166,23 @@ test_exit() ifs_cleanup } +online_all_cpus() +{ + local off_cpus="" + + OFFLINE_CPUS=$(cat "$CPU_OFFLINE_SYSFS") + online_offline_cpu_list "1" "$OFFLINE_CPUS" + + off_cpus=$(cat "$CPU_OFFLINE_SYSFS") + if [[ -z "$off_cpus" ]]; then + append_log "[$INFO] All CPUs are online." + else + append_log "[$XFAIL] There is offline cpu:$off_cpus after online all cpu!" + RESULT=$KSFT_XFAIL + ifs_cleanup + fi +} + get_cpu_fms() { FML=$(grep -m 1 "family" /proc/cpuinfo | awk -F ":" '{printf "%02x",$2;}') @@ -268,10 +329,135 @@ test_bad_and_origin_ifs_image() append_log "[$INFO] Loading invalid IFS image and then loading initial image passed.\n" } +ifs_test_cpu() +{ + local ifs_mode=$1 + local cpu_num=$2 + local image_id status details ret result result_info + + echo "$cpu_num" > "$IFS_PATH"_"$ifs_mode"/"$RUN_TEST" + ret=$? + + status=$(cat "${IFS_PATH}_${ifs_mode}/${STATUS}") + details=$(cat "${IFS_PATH}_${ifs_mode}/${DETAILS}") + + if [[ "$ret" -eq 0 && "$status" == "$STATUS_PASS" ]]; then + result="$PASS" + else + result="$FAIL" + fi + + cpu_num=$(cat "${CPU_SYSFS}/cpu${cpu_num}/topology/thread_siblings_list") + + # There is no image file for IFS ARRAY BIST scan + if [[ -e "${IFS_PATH}_${ifs_mode}/current_batch" ]]; then + image_id=$(cat "${IFS_PATH}_${ifs_mode}/current_batch") + result_info=$(printf "[%s] ifs_%1d cpu(s):%s, current_batch:0x%02x, \ +ret:%2d, status:%s, details:0x%016x" \ + "$result" "$ifs_mode" "$cpu_num" "$image_id" "$ret" \ + "$status" "$details") + else + result_info=$(printf "[%s] ifs_%1d cpu(s):%s, ret:%2d, status:%s, details:0x%016x" \ + "$result" "$ifs_mode" "$cpu_num" "$ret" "$status" "$details") + fi + + append_log "$result_info" +} + +ifs_test_cpus() +{ + local cpus_type=$1 + local ifs_mode=$2 + local image_id=$3 + local cpu_max_num="" + local cpu_num="" + + case "$cpus_type" in + "$ALL") + cpu_max_num=$(($(nproc) - 1)) + cpus=$(seq 0 $cpu_max_num) + ;; + "$SIBLINGS") + cpus=$(cat ${CPU_SYSFS}/cpu*/topology/thread_siblings_list \ + | sed -e 's/,.*//' \ + | sed -e 's/-.*//' \ + | sort -n \ + | uniq) + ;; + *) + test_exit "Invalid cpus_type:$cpus_type" "$KSFT_XFAIL" + ;; + esac + + for cpu_num in $cpus; do + ifs_test_cpu "$ifs_mode" "$cpu_num" + done + + if [[ -z "$image_id" ]]; then + append_log "[$INFO] ifs_$ifs_mode test $cpus_type cpus completed\n" + else + append_log "[$INFO] ifs_$ifs_mode $cpus_type cpus with $CPU_FMS-$image_id.scan \ +completed\n" + fi +} + +test_ifs_same_cpu_loop() +{ + local ifs_mode=$1 + local cpu_num=$2 + local loop_times=$3 + + append_log "[$INFO] Test ifs mode $ifs_mode on CPU:$cpu_num for $loop_times rounds:" + [[ "$ifs_mode" == "$IFS_SCAN_MODE" ]] && { + load_image "$DEFAULT_IMG_ID" || return $? + } + for (( i=1; i<=loop_times; i++ )); do + append_log "[$INFO] Loop iteration: $i in total of $loop_times" + # Only IFS scan needs the interval time + if [[ "$ifs_mode" == "$IFS_SCAN_MODE" ]]; then + do_cmd "sleep $INTERVAL_TIME" + elif [[ "$ifs_mode" == "$IFS_ARRAY_BIST_SCAN_MODE" ]]; then + true + else + test_exit "Invalid ifs_mode:$ifs_mode" "$KSFT_XFAIL" + fi + + ifs_test_cpu "$ifs_mode" "$cpu_num" + done + append_log "[$INFO] $loop_times rounds of ifs_$ifs_mode test on CPU:$cpu_num completed.\n" +} + +test_ifs_scan_available_imgs() +{ + local image_ids="" + local image_id="" + + append_log "[$INFO] Test ifs scan with available images:" + image_ids=$(find "$IMG_PATH" -maxdepth 1 -name "${CPU_FMS}-[0-9a-fA-F][0-9a-fA-F].scan" \ + 2>/dev/null \ + | sort \ + | awk -F "-" '{print $NF}' \ + | cut -d "." -f 1) + + for image_id in $image_ids; do + load_image "$image_id" || return $? + + ifs_test_cpus "$SIBLINGS" "$IFS_SCAN_MODE" "$image_id" + # IFS scan requires time interval for the scan on the same CPU + do_cmd "sleep $INTERVAL_TIME" + done +} + prepare_ifs_test_env() { + local max_cpu="" + check_cpu_ifs_support_interval_time + online_all_cpus + max_cpu=$(($(nproc) - 1)) + RANDOM_CPU=$(shuf -i 0-$max_cpu -n 1) + DEFAULT_IMG_ID=$(find $IMG_PATH -maxdepth 1 -name "${CPU_FMS}-[0-9a-fA-F][0-9a-fA-F].scan" \ 2>/dev/null \ | sort \ @@ -290,6 +476,8 @@ test_ifs() append_log "[$SKIP] No proper ${IMG_PATH}/${CPU_FMS}-*.scan, skip ifs_0 scan" else test_bad_and_origin_ifs_image "$DEFAULT_IMG_ID" + test_ifs_scan_available_imgs + test_ifs_same_cpu_loop "$IFS_SCAN_MODE" "$RANDOM_CPU" "$LOOP_TIMES" fi } -- cgit v1.2.3-58-ga151 From bb408dae9e73803eab8a648115d6c4a1bca4dba3 Mon Sep 17 00:00:00 2001 From: Pengfei Xu Date: Fri, 31 May 2024 15:53:50 +0800 Subject: selftests: ifs: verify IFS ARRAY BIST functionality There are two selftest scenarios for ARRAY BIST(Board Integrated System Test) tests: 1. Perform IFS ARRAY BIST tests once on each CPU. 2. Perform IFS ARRAY BIST tests on a random CPU with 3 rounds. These are not meant to be exhaustive, but are some minimal tests for for checking IFS ARRAY BIST. Reviewed-by: Jithu Joseph Reviewed-by: Kuppuswamy Sathyanarayanan Co-developed-by: Ashok Raj Signed-off-by: Ashok Raj Signed-off-by: Pengfei Xu Acked-by: Jithu Joseph Signed-off-by: Shuah Khan --- .../testing/selftests/drivers/platform/x86/intel/ifs/test_ifs.sh | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tools/testing/selftests/drivers/platform/x86/intel/ifs/test_ifs.sh b/tools/testing/selftests/drivers/platform/x86/intel/ifs/test_ifs.sh index 82fc5a461b12..8b68964b29f4 100755 --- a/tools/testing/selftests/drivers/platform/x86/intel/ifs/test_ifs.sh +++ b/tools/testing/selftests/drivers/platform/x86/intel/ifs/test_ifs.sh @@ -17,6 +17,7 @@ readonly IFS_SCAN_MODE="0" readonly IFS_ARRAY_BIST_SCAN_MODE="1" readonly IFS_PATH="/sys/devices/virtual/misc/intel_ifs" readonly IFS_SCAN_SYSFS_PATH="${IFS_PATH}_${IFS_SCAN_MODE}" +readonly IFS_ARRAY_BIST_SYSFS_PATH="${IFS_PATH}_${IFS_ARRAY_BIST_SCAN_MODE}" readonly RUN_TEST="run_test" readonly STATUS="status" readonly DETAILS="details" @@ -479,6 +480,13 @@ test_ifs() test_ifs_scan_available_imgs test_ifs_same_cpu_loop "$IFS_SCAN_MODE" "$RANDOM_CPU" "$LOOP_TIMES" fi + + if [[ -d "$IFS_ARRAY_BIST_SYSFS_PATH" ]]; then + ifs_test_cpus "$SIBLINGS" "$IFS_ARRAY_BIST_SCAN_MODE" + test_ifs_same_cpu_loop "$IFS_ARRAY_BIST_SCAN_MODE" "$RANDOM_CPU" "$LOOP_TIMES" + else + append_log "[$SKIP] No $IFS_ARRAY_BIST_SYSFS_PATH, skip IFS ARRAY BIST scan" + fi } trap ifs_cleanup SIGTERM SIGINT -- cgit v1.2.3-58-ga151