-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
MBM (Memory Bandwidth Monitoring) test is the first implemented selftest. It starts a stressful memory bandwidth benchmark and assigns the bandwidth pid in a resctrl monitoring group. Read and compare perf IMC counter and MBM total bytes for the benchmark. The numbers should be close enough to pass the test. Default benchmark is built-in fill_buf. But users can specify their own benchmark by option "-b". We can add memory bandwidth monitoring for multiple processes in the future. Co-developed-by: Sai Praneeth Prakhya <sai.praneeth.prakhya@intel.com> Signed-off-by: Sai Praneeth Prakhya <sai.praneeth.prakhya@intel.com> Co-developed-by: Babu Moger <babu.moger@amd.com> Signed-off-by: Babu Moger <babu.moger@amd.com> Signed-off-by: Fenghua Yu <fenghua.yu@intel.com> Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
- Loading branch information
Fenghua Yu
authored and
Shuah Khan
committed
Feb 11, 2020
1 parent
a2561b1
commit ecdbb91
Showing
6 changed files
with
368 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
/* | ||
* Memory Bandwidth Monitoring (MBM) test | ||
* | ||
* Copyright (C) 2018 Intel Corporation | ||
* | ||
* Authors: | ||
* Sai Praneeth Prakhya <sai.praneeth.prakhya@intel.com>, | ||
* Fenghua Yu <fenghua.yu@intel.com> | ||
*/ | ||
#include "resctrl.h" | ||
|
||
#define RESULT_FILE_NAME "result_mbm" | ||
#define MAX_DIFF 300 | ||
#define NUM_OF_RUNS 5 | ||
|
||
static void | ||
show_bw_info(unsigned long *bw_imc, unsigned long *bw_resc, int span) | ||
{ | ||
unsigned long avg_bw_imc = 0, avg_bw_resc = 0; | ||
unsigned long sum_bw_imc = 0, sum_bw_resc = 0; | ||
long avg_diff = 0; | ||
int runs; | ||
|
||
/* | ||
* Discard the first value which is inaccurate due to monitoring setup | ||
* transition phase. | ||
*/ | ||
for (runs = 1; runs < NUM_OF_RUNS ; runs++) { | ||
sum_bw_imc += bw_imc[runs]; | ||
sum_bw_resc += bw_resc[runs]; | ||
} | ||
|
||
avg_bw_imc = sum_bw_imc / 4; | ||
avg_bw_resc = sum_bw_resc / 4; | ||
avg_diff = avg_bw_resc - avg_bw_imc; | ||
|
||
printf("%sok MBM: diff within %d%%\n", | ||
labs(avg_diff) > MAX_DIFF ? "not " : "", MAX_DIFF); | ||
tests_run++; | ||
printf("# avg_diff: %lu\n", labs(avg_diff)); | ||
printf("# Span (MB): %d\n", span); | ||
printf("# avg_bw_imc: %lu\n", avg_bw_imc); | ||
printf("# avg_bw_resc: %lu\n", avg_bw_resc); | ||
} | ||
|
||
static int check_results(int span) | ||
{ | ||
unsigned long bw_imc[NUM_OF_RUNS], bw_resc[NUM_OF_RUNS]; | ||
char temp[1024], *token_array[8]; | ||
char output[] = RESULT_FILE_NAME; | ||
int runs; | ||
FILE *fp; | ||
|
||
printf("# Checking for pass/fail\n"); | ||
|
||
fp = fopen(output, "r"); | ||
if (!fp) { | ||
perror(output); | ||
|
||
return errno; | ||
} | ||
|
||
runs = 0; | ||
while (fgets(temp, sizeof(temp), fp)) { | ||
char *token = strtok(temp, ":\t"); | ||
int i = 0; | ||
|
||
while (token) { | ||
token_array[i++] = token; | ||
token = strtok(NULL, ":\t"); | ||
} | ||
|
||
bw_resc[runs] = strtoul(token_array[5], NULL, 0); | ||
bw_imc[runs] = strtoul(token_array[3], NULL, 0); | ||
runs++; | ||
} | ||
|
||
show_bw_info(bw_imc, bw_resc, span); | ||
|
||
fclose(fp); | ||
|
||
return 0; | ||
} | ||
|
||
static int mbm_setup(int num, ...) | ||
{ | ||
struct resctrl_val_param *p; | ||
static int num_of_runs; | ||
va_list param; | ||
int ret = 0; | ||
|
||
/* Run NUM_OF_RUNS times */ | ||
if (num_of_runs++ >= NUM_OF_RUNS) | ||
return -1; | ||
|
||
va_start(param, num); | ||
p = va_arg(param, struct resctrl_val_param *); | ||
va_end(param); | ||
|
||
/* Set up shemata with 100% allocation on the first run. */ | ||
if (num_of_runs == 0) | ||
ret = write_schemata(p->ctrlgrp, "100", p->cpu_no, | ||
p->resctrl_val); | ||
|
||
return ret; | ||
} | ||
|
||
void mbm_test_cleanup(void) | ||
{ | ||
remove(RESULT_FILE_NAME); | ||
} | ||
|
||
int mbm_bw_change(int span, int cpu_no, char *bw_report, char **benchmark_cmd) | ||
{ | ||
struct resctrl_val_param param = { | ||
.resctrl_val = "mbm", | ||
.ctrlgrp = "c1", | ||
.mongrp = "m1", | ||
.span = span, | ||
.cpu_no = cpu_no, | ||
.mum_resctrlfs = 1, | ||
.filename = RESULT_FILE_NAME, | ||
.bw_report = bw_report, | ||
.setup = mbm_setup | ||
}; | ||
int ret; | ||
|
||
remove(RESULT_FILE_NAME); | ||
|
||
if (!validate_resctrl_feature_request("mbm")) | ||
return -1; | ||
|
||
ret = resctrl_val(benchmark_cmd, ¶m); | ||
if (ret) | ||
return ret; | ||
|
||
ret = check_results(span); | ||
if (ret) | ||
return ret; | ||
|
||
mbm_test_cleanup(); | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
/* | ||
* Resctrl tests | ||
* | ||
* Copyright (C) 2018 Intel Corporation | ||
* | ||
* Authors: | ||
* Sai Praneeth Prakhya <sai.praneeth.prakhya@intel.com>, | ||
* Fenghua Yu <fenghua.yu@intel.com> | ||
*/ | ||
#include "resctrl.h" | ||
|
||
#define BENCHMARK_ARGS 64 | ||
#define BENCHMARK_ARG_SIZE 64 | ||
|
||
static void cmd_help(void) | ||
{ | ||
printf("usage: resctrl_tests [-h] [-b \"benchmark_cmd [options]\"] [-t test list]\n"); | ||
printf("\t-b benchmark_cmd [options]: run specified benchmark\n"); | ||
printf("\t default benchmark is builtin fill_buf\n"); | ||
printf("\t-t test list: run tests specified in the test list, "); | ||
printf("e.g. -t mbm,mba\n"); | ||
printf("\t-h: help\n"); | ||
} | ||
|
||
void tests_cleanup(void) | ||
{ | ||
mbm_test_cleanup(); | ||
} | ||
|
||
int main(int argc, char **argv) | ||
{ | ||
int res, c, cpu_no = 1, span = 250, argc_new = argc, i, ben_ind; | ||
char *benchmark_cmd[BENCHMARK_ARGS], bw_report[64], bm_type[64]; | ||
char benchmark_cmd_area[BENCHMARK_ARGS][BENCHMARK_ARG_SIZE]; | ||
bool has_ben = false, mbm_test = true; | ||
int ben_count; | ||
|
||
for (i = 0; i < argc; i++) { | ||
if (strcmp(argv[i], "-b") == 0) { | ||
ben_ind = i + 1; | ||
ben_count = argc - ben_ind; | ||
argc_new = ben_ind - 1; | ||
has_ben = true; | ||
break; | ||
} | ||
} | ||
|
||
while ((c = getopt(argc_new, argv, "ht:b:")) != -1) { | ||
char *token; | ||
|
||
switch (c) { | ||
case 't': | ||
token = strtok(optarg, ","); | ||
|
||
mbm_test = false; | ||
while (token) { | ||
if (!strcmp(token, "mbm")) { | ||
mbm_test = true; | ||
} else { | ||
printf("invalid argument\n"); | ||
|
||
return -1; | ||
} | ||
token = strtok(NULL, ":\t"); | ||
} | ||
break; | ||
case 'p': | ||
cpu_no = atoi(optarg); | ||
break; | ||
case 'h': | ||
cmd_help(); | ||
|
||
return 0; | ||
default: | ||
printf("invalid argument\n"); | ||
|
||
return -1; | ||
} | ||
} | ||
|
||
printf("TAP version 13\n"); | ||
|
||
/* | ||
* Typically we need root privileges, because: | ||
* 1. We write to resctrl FS | ||
* 2. We execute perf commands | ||
*/ | ||
if (geteuid() != 0) | ||
printf("# WARNING: not running as root, tests may fail.\n"); | ||
|
||
if (has_ben) { | ||
/* Extract benchmark command from command line. */ | ||
for (i = ben_ind; i < argc; i++) { | ||
benchmark_cmd[i - ben_ind] = benchmark_cmd_area[i]; | ||
sprintf(benchmark_cmd[i - ben_ind], "%s", argv[i]); | ||
} | ||
benchmark_cmd[ben_count] = NULL; | ||
} else { | ||
/* If no benchmark is given by "-b" argument, use fill_buf. */ | ||
for (i = 0; i < 6; i++) | ||
benchmark_cmd[i] = benchmark_cmd_area[i]; | ||
|
||
strcpy(benchmark_cmd[0], "fill_buf"); | ||
sprintf(benchmark_cmd[1], "%d", span); | ||
strcpy(benchmark_cmd[2], "1"); | ||
strcpy(benchmark_cmd[3], "1"); | ||
strcpy(benchmark_cmd[4], "0"); | ||
strcpy(benchmark_cmd[5], ""); | ||
benchmark_cmd[6] = NULL; | ||
} | ||
|
||
sprintf(bw_report, "reads"); | ||
sprintf(bm_type, "fill_buf"); | ||
|
||
check_resctrlfs_support(); | ||
filter_dmesg(); | ||
|
||
if (mbm_test) { | ||
printf("# Starting MBM BW change ...\n"); | ||
if (!has_ben) | ||
sprintf(benchmark_cmd[5], "%s", "mba"); | ||
res = mbm_bw_change(span, cpu_no, bw_report, benchmark_cmd); | ||
printf("%sok MBM: bw change\n", res ? "not " : ""); | ||
mbm_test_cleanup(); | ||
tests_run++; | ||
} | ||
|
||
printf("1..%d\n", tests_run); | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.