selftests/resctrl: Skip the test if requested resctrl feature is not supported
[linux-2.6-microblaze.git] / tools / testing / selftests / resctrl / mba_test.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Memory Bandwidth Allocation (MBA) test
4  *
5  * Copyright (C) 2018 Intel Corporation
6  *
7  * Authors:
8  *    Sai Praneeth Prakhya <sai.praneeth.prakhya@intel.com>,
9  *    Fenghua Yu <fenghua.yu@intel.com>
10  */
11 #include "resctrl.h"
12
13 #define RESULT_FILE_NAME        "result_mba"
14 #define NUM_OF_RUNS             5
15 #define MAX_DIFF_PERCENT        5
16 #define ALLOCATION_MAX          100
17 #define ALLOCATION_MIN          10
18 #define ALLOCATION_STEP         10
19
20 /*
21  * Change schemata percentage from 100 to 10%. Write schemata to specified
22  * con_mon grp, mon_grp in resctrl FS.
23  * For each allocation, run 5 times in order to get average values.
24  */
25 static int mba_setup(int num, ...)
26 {
27         static int runs_per_allocation, allocation = 100;
28         struct resctrl_val_param *p;
29         char allocation_str[64];
30         va_list param;
31
32         va_start(param, num);
33         p = va_arg(param, struct resctrl_val_param *);
34         va_end(param);
35
36         if (runs_per_allocation >= NUM_OF_RUNS)
37                 runs_per_allocation = 0;
38
39         /* Only set up schemata once every NUM_OF_RUNS of allocations */
40         if (runs_per_allocation++ != 0)
41                 return 0;
42
43         if (allocation < ALLOCATION_MIN || allocation > ALLOCATION_MAX)
44                 return -1;
45
46         sprintf(allocation_str, "%d", allocation);
47
48         write_schemata(p->ctrlgrp, allocation_str, p->cpu_no, p->resctrl_val);
49         allocation -= ALLOCATION_STEP;
50
51         return 0;
52 }
53
54 static void show_mba_info(unsigned long *bw_imc, unsigned long *bw_resc)
55 {
56         int allocation, runs;
57         bool failed = false;
58
59         ksft_print_msg("Results are displayed in (MB)\n");
60         /* Memory bandwidth from 100% down to 10% */
61         for (allocation = 0; allocation < ALLOCATION_MAX / ALLOCATION_STEP;
62              allocation++) {
63                 unsigned long avg_bw_imc, avg_bw_resc;
64                 unsigned long sum_bw_imc = 0, sum_bw_resc = 0;
65                 int avg_diff_per;
66                 float avg_diff;
67
68                 /*
69                  * The first run is discarded due to inaccurate value from
70                  * phase transition.
71                  */
72                 for (runs = NUM_OF_RUNS * allocation + 1;
73                      runs < NUM_OF_RUNS * allocation + NUM_OF_RUNS ; runs++) {
74                         sum_bw_imc += bw_imc[runs];
75                         sum_bw_resc += bw_resc[runs];
76                 }
77
78                 avg_bw_imc = sum_bw_imc / (NUM_OF_RUNS - 1);
79                 avg_bw_resc = sum_bw_resc / (NUM_OF_RUNS - 1);
80                 avg_diff = (float)labs(avg_bw_resc - avg_bw_imc) / avg_bw_imc;
81                 avg_diff_per = (int)(avg_diff * 100);
82
83                 ksft_print_msg("%s MBA: diff within %d%% for schemata %u\n",
84                                avg_diff_per > MAX_DIFF_PERCENT ?
85                                "Fail:" : "Pass:",
86                                MAX_DIFF_PERCENT,
87                                ALLOCATION_MAX - ALLOCATION_STEP * allocation);
88
89                 ksft_print_msg("avg_diff_per: %d%%\n", avg_diff_per);
90                 ksft_print_msg("avg_bw_imc: %lu\n", avg_bw_imc);
91                 ksft_print_msg("avg_bw_resc: %lu\n", avg_bw_resc);
92                 if (avg_diff_per > MAX_DIFF_PERCENT)
93                         failed = true;
94         }
95
96         ksft_print_msg("%s schemata change using MBA\n",
97                        failed ? "Fail:" : "Pass:");
98         if (failed)
99                 ksft_print_msg("At least one test failed");
100 }
101
102 static int check_results(void)
103 {
104         char *token_array[8], output[] = RESULT_FILE_NAME, temp[512];
105         unsigned long bw_imc[1024], bw_resc[1024];
106         int runs;
107         FILE *fp;
108
109         fp = fopen(output, "r");
110         if (!fp) {
111                 perror(output);
112
113                 return errno;
114         }
115
116         runs = 0;
117         while (fgets(temp, sizeof(temp), fp)) {
118                 char *token = strtok(temp, ":\t");
119                 int fields = 0;
120
121                 while (token) {
122                         token_array[fields++] = token;
123                         token = strtok(NULL, ":\t");
124                 }
125
126                 /* Field 3 is perf imc value */
127                 bw_imc[runs] = strtoul(token_array[3], NULL, 0);
128                 /* Field 5 is resctrl value */
129                 bw_resc[runs] = strtoul(token_array[5], NULL, 0);
130                 runs++;
131         }
132
133         fclose(fp);
134
135         show_mba_info(bw_imc, bw_resc);
136
137         return 0;
138 }
139
140 void mba_test_cleanup(void)
141 {
142         remove(RESULT_FILE_NAME);
143 }
144
145 int mba_schemata_change(int cpu_no, char *bw_report, char **benchmark_cmd)
146 {
147         struct resctrl_val_param param = {
148                 .resctrl_val    = MBA_STR,
149                 .ctrlgrp        = "c1",
150                 .mongrp         = "m1",
151                 .cpu_no         = cpu_no,
152                 .mum_resctrlfs  = 1,
153                 .filename       = RESULT_FILE_NAME,
154                 .bw_report      = bw_report,
155                 .setup          = mba_setup
156         };
157         int ret;
158
159         remove(RESULT_FILE_NAME);
160
161         ret = resctrl_val(benchmark_cmd, &param);
162         if (ret)
163                 return ret;
164
165         ret = check_results();
166         if (ret)
167                 return ret;
168
169         mba_test_cleanup();
170
171         return 0;
172 }