Merge remote-tracking branch 'regmap/for-5.7' into regmap-linus
[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                300
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         printf("# 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                 unsigned long avg_diff;
66
67                 /*
68                  * The first run is discarded due to inaccurate value from
69                  * phase transition.
70                  */
71                 for (runs = NUM_OF_RUNS * allocation + 1;
72                      runs < NUM_OF_RUNS * allocation + NUM_OF_RUNS ; runs++) {
73                         sum_bw_imc += bw_imc[runs];
74                         sum_bw_resc += bw_resc[runs];
75                 }
76
77                 avg_bw_imc = sum_bw_imc / (NUM_OF_RUNS - 1);
78                 avg_bw_resc = sum_bw_resc / (NUM_OF_RUNS - 1);
79                 avg_diff = labs((long)(avg_bw_resc - avg_bw_imc));
80
81                 printf("%sok MBA schemata percentage %u smaller than %d %%\n",
82                        avg_diff > MAX_DIFF ? "not " : "",
83                        ALLOCATION_MAX - ALLOCATION_STEP * allocation,
84                        MAX_DIFF);
85                 tests_run++;
86                 printf("# avg_diff: %lu\n", avg_diff);
87                 printf("# avg_bw_imc: %lu\n", avg_bw_imc);
88                 printf("# avg_bw_resc: %lu\n", avg_bw_resc);
89                 if (avg_diff > MAX_DIFF)
90                         failed = true;
91         }
92
93         printf("%sok schemata change using MBA%s\n", failed ? "not " : "",
94                failed ? " # at least one test failed" : "");
95         tests_run++;
96 }
97
98 static int check_results(void)
99 {
100         char *token_array[8], output[] = RESULT_FILE_NAME, temp[512];
101         unsigned long bw_imc[1024], bw_resc[1024];
102         int runs;
103         FILE *fp;
104
105         fp = fopen(output, "r");
106         if (!fp) {
107                 perror(output);
108
109                 return errno;
110         }
111
112         runs = 0;
113         while (fgets(temp, sizeof(temp), fp)) {
114                 char *token = strtok(temp, ":\t");
115                 int fields = 0;
116
117                 while (token) {
118                         token_array[fields++] = token;
119                         token = strtok(NULL, ":\t");
120                 }
121
122                 /* Field 3 is perf imc value */
123                 bw_imc[runs] = strtoul(token_array[3], NULL, 0);
124                 /* Field 5 is resctrl value */
125                 bw_resc[runs] = strtoul(token_array[5], NULL, 0);
126                 runs++;
127         }
128
129         fclose(fp);
130
131         show_mba_info(bw_imc, bw_resc);
132
133         return 0;
134 }
135
136 void mba_test_cleanup(void)
137 {
138         remove(RESULT_FILE_NAME);
139 }
140
141 int mba_schemata_change(int cpu_no, char *bw_report, char **benchmark_cmd)
142 {
143         struct resctrl_val_param param = {
144                 .resctrl_val    = "mba",
145                 .ctrlgrp        = "c1",
146                 .mongrp         = "m1",
147                 .cpu_no         = cpu_no,
148                 .mum_resctrlfs  = 1,
149                 .filename       = RESULT_FILE_NAME,
150                 .bw_report      = bw_report,
151                 .setup          = mba_setup
152         };
153         int ret;
154
155         remove(RESULT_FILE_NAME);
156
157         if (!validate_resctrl_feature_request("mba"))
158                 return -1;
159
160         ret = resctrl_val(benchmark_cmd, &param);
161         if (ret)
162                 return ret;
163
164         ret = check_results();
165         if (ret)
166                 return ret;
167
168         mba_test_cleanup();
169
170         return 0;
171 }