Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.10.11.
  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	8
 16#define ALLOCATION_MAX		100
 17#define ALLOCATION_MIN		10
 18#define ALLOCATION_STEP		10
 19
 20static int mba_init(const struct resctrl_val_param *param, int domain_id)
 21{
 22	int ret;
 23
 24	ret = initialize_read_mem_bw_imc();
 25	if (ret)
 26		return ret;
 27
 28	initialize_mem_bw_resctrl(param, domain_id);
 29
 30	return 0;
 31}
 32
 33/*
 34 * Change schemata percentage from 100 to 10%. Write schemata to specified
 35 * con_mon grp, mon_grp in resctrl FS.
 36 * For each allocation, run 5 times in order to get average values.
 37 */
 38static int mba_setup(const struct resctrl_test *test,
 39		     const struct user_params *uparams,
 40		     struct resctrl_val_param *p)
 41{
 42	static unsigned int allocation = ALLOCATION_MIN;
 43	static int runs_per_allocation;
 44	char allocation_str[64];
 45	int ret;
 46
 47	if (runs_per_allocation >= NUM_OF_RUNS)
 48		runs_per_allocation = 0;
 49
 50	/* Only set up schemata once every NUM_OF_RUNS of allocations */
 51	if (runs_per_allocation++ != 0)
 52		return 0;
 53
 54	if (allocation > ALLOCATION_MAX)
 55		return END_OF_TESTS;
 56
 57	sprintf(allocation_str, "%d", allocation);
 58
 59	ret = write_schemata(p->ctrlgrp, allocation_str, uparams->cpu, test->resource);
 60	if (ret < 0)
 61		return ret;
 62
 63	allocation += ALLOCATION_STEP;
 64
 65	return 0;
 66}
 67
 68static int mba_measure(const struct user_params *uparams,
 69		       struct resctrl_val_param *param, pid_t bm_pid)
 70{
 71	return measure_read_mem_bw(uparams, param, bm_pid);
 72}
 73
 74static bool show_mba_info(unsigned long *bw_imc, unsigned long *bw_resc)
 75{
 76	unsigned int allocation;
 77	bool ret = false;
 78	int runs;
 79
 80	ksft_print_msg("Results are displayed in (MB)\n");
 81	/* Memory bandwidth from 100% down to 10% */
 82	for (allocation = 0; allocation < ALLOCATION_MAX / ALLOCATION_STEP;
 83	     allocation++) {
 84		unsigned long sum_bw_imc = 0, sum_bw_resc = 0;
 85		long avg_bw_imc, avg_bw_resc;
 86		int avg_diff_per;
 87		float avg_diff;
 88
 89		for (runs = NUM_OF_RUNS * allocation;
 90		     runs < NUM_OF_RUNS * allocation + NUM_OF_RUNS ; runs++) {
 91			sum_bw_imc += bw_imc[runs];
 92			sum_bw_resc += bw_resc[runs];
 93		}
 94
 95		avg_bw_imc = sum_bw_imc / NUM_OF_RUNS;
 96		avg_bw_resc = sum_bw_resc / NUM_OF_RUNS;
 97		if (avg_bw_imc < THROTTLE_THRESHOLD || avg_bw_resc < THROTTLE_THRESHOLD) {
 98			ksft_print_msg("Bandwidth below threshold (%d MiB). Dropping results from MBA schemata %u.\n",
 99				       THROTTLE_THRESHOLD,
100				       ALLOCATION_MIN + ALLOCATION_STEP * allocation);
101			continue;
102		}
103
104		avg_diff = (float)labs(avg_bw_resc - avg_bw_imc) / avg_bw_imc;
105		avg_diff_per = (int)(avg_diff * 100);
106
107		ksft_print_msg("%s Check MBA diff within %d%% for schemata %u\n",
108			       avg_diff_per > MAX_DIFF_PERCENT ?
109			       "Fail:" : "Pass:",
110			       MAX_DIFF_PERCENT,
111			       ALLOCATION_MIN + ALLOCATION_STEP * allocation);
112
113		ksft_print_msg("avg_diff_per: %d%%\n", avg_diff_per);
114		ksft_print_msg("avg_bw_imc: %lu\n", avg_bw_imc);
115		ksft_print_msg("avg_bw_resc: %lu\n", avg_bw_resc);
116		if (avg_diff_per > MAX_DIFF_PERCENT)
117			ret = true;
118	}
119
120	ksft_print_msg("%s Check schemata change using MBA\n",
121		       ret ? "Fail:" : "Pass:");
122	if (ret)
123		ksft_print_msg("At least one test failed\n");
124
125	return ret;
126}
127
128static int check_results(void)
129{
130	unsigned long bw_resc[NUM_OF_RUNS * ALLOCATION_MAX / ALLOCATION_STEP];
131	unsigned long bw_imc[NUM_OF_RUNS * ALLOCATION_MAX / ALLOCATION_STEP];
132	char *token_array[8], output[] = RESULT_FILE_NAME, temp[512];
133	int runs;
134	FILE *fp;
135
136	fp = fopen(output, "r");
137	if (!fp) {
138		ksft_perror(output);
139
140		return -1;
141	}
142
143	runs = 0;
144	while (fgets(temp, sizeof(temp), fp)) {
145		char *token = strtok(temp, ":\t");
146		int fields = 0;
147
148		while (token) {
149			token_array[fields++] = token;
150			token = strtok(NULL, ":\t");
151		}
152
153		/* Field 3 is perf imc value */
154		bw_imc[runs] = strtoul(token_array[3], NULL, 0);
155		/* Field 5 is resctrl value */
156		bw_resc[runs] = strtoul(token_array[5], NULL, 0);
157		runs++;
158	}
159
160	fclose(fp);
161
162	return show_mba_info(bw_imc, bw_resc);
163}
164
165static void mba_test_cleanup(void)
166{
167	remove(RESULT_FILE_NAME);
168}
169
170static int mba_run_test(const struct resctrl_test *test, const struct user_params *uparams)
171{
172	struct resctrl_val_param param = {
173		.ctrlgrp	= "c1",
174		.filename	= RESULT_FILE_NAME,
175		.init		= mba_init,
176		.setup		= mba_setup,
177		.measure	= mba_measure,
178	};
179	struct fill_buf_param fill_buf = {};
180	int ret;
181
182	remove(RESULT_FILE_NAME);
183
184	if (uparams->fill_buf) {
185		fill_buf.buf_size = uparams->fill_buf->buf_size;
186		fill_buf.memflush = uparams->fill_buf->memflush;
187		param.fill_buf = &fill_buf;
188	} else if (!uparams->benchmark_cmd[0]) {
189		ssize_t buf_size;
190
191		buf_size = get_fill_buf_size(uparams->cpu, "L3");
192		if (buf_size < 0)
193			return buf_size;
194		fill_buf.buf_size = buf_size;
195		fill_buf.memflush = true;
196		param.fill_buf = &fill_buf;
197	}
198
199	ret = resctrl_val(test, uparams, &param);
200	if (ret)
201		return ret;
202
203	ret = check_results();
204
205	return ret;
206}
207
208static bool mba_feature_check(const struct resctrl_test *test)
209{
210	return test_resource_feature_check(test) &&
211	       resctrl_mon_feature_exists("L3_MON", "mbm_local_bytes");
212}
213
214struct resctrl_test mba_test = {
215	.name = "MBA",
216	.resource = "MB",
217	.vendor_specific = ARCH_INTEL,
218	.feature_check = mba_feature_check,
219	.run_test = mba_run_test,
220	.cleanup = mba_test_cleanup,
221};