mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-16 17:57:38 -04:00
Merge tag 'linux_kselftest-next-7.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest
Pull kselftest updates from Shuah Khan: "Several fixes and improvements to resctrl tests and a change to kselftest document to clarify the use of FORCE_TARGETS build variable" * tag 'linux_kselftest-next-7.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest: kselftest: fix doc for ksft_test_result_report() selftests/resctrl: Reduce L2 impact on CAT test selftests/resctrl: Simplify perf usage in CAT test selftests/resctrl: Remove requirement on cache miss rate selftests/resctrl: Raise threshold at which MBM and PMU values are compared selftests/resctrl: Increase size of buffer used in MBM and MBA tests selftests/resctrl: Support multiple events associated with iMC selftests/resctrl: Prepare for parsing multiple events per iMC selftests/resctrl: Do not store iMC counter value in counter config structure selftests/resctrl: Reduce interference from L2 occupancy during cache occupancy test selftests/resctrl: Improve accuracy of cache occupancy test docs: kselftest: Document the FORCE_TARGETS build variable
This commit is contained in:
@@ -126,6 +126,18 @@ dedicated skiplist::
|
||||
See the top-level tools/testing/selftests/Makefile for the list of all
|
||||
possible targets.
|
||||
|
||||
Requiring all targets to build successfully
|
||||
===========================================
|
||||
|
||||
By default, the build succeeds as long as at least one target builds
|
||||
without error. Set ``FORCE_TARGETS=1`` to instead require every target to
|
||||
build successfully; make will abort as soon as any target fails::
|
||||
|
||||
$ make -C tools/testing/selftests FORCE_TARGETS=1
|
||||
|
||||
This applies to both the ``all`` and ``install`` targets and is useful in
|
||||
CI environments where a silent partial build would be misleading.
|
||||
|
||||
Running the full range hotplug selftests
|
||||
========================================
|
||||
|
||||
|
||||
@@ -346,9 +346,9 @@ void ksft_test_result_code(int exit_code, const char *test_name,
|
||||
}
|
||||
|
||||
/**
|
||||
* ksft_test_result() - Report test success based on truth of condition
|
||||
* ksft_test_result_report() - Report test result based on a kselftest exit code
|
||||
*
|
||||
* @condition: if true, report test success, otherwise failure.
|
||||
* @result: a kselftest exit code
|
||||
*/
|
||||
#define ksft_test_result_report(result, fmt, ...) do { \
|
||||
switch (result) { \
|
||||
|
||||
@@ -10,7 +10,6 @@ void perf_event_attr_initialize(struct perf_event_attr *pea, __u64 config)
|
||||
memset(pea, 0, sizeof(*pea));
|
||||
pea->type = PERF_TYPE_HARDWARE;
|
||||
pea->size = sizeof(*pea);
|
||||
pea->read_format = PERF_FORMAT_GROUP;
|
||||
pea->exclude_kernel = 1;
|
||||
pea->exclude_hv = 1;
|
||||
pea->exclude_idle = 1;
|
||||
@@ -37,19 +36,13 @@ int perf_event_reset_enable(int pe_fd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void perf_event_initialize_read_format(struct perf_event_read *pe_read)
|
||||
{
|
||||
memset(pe_read, 0, sizeof(*pe_read));
|
||||
pe_read->nr = 1;
|
||||
}
|
||||
|
||||
int perf_open(struct perf_event_attr *pea, pid_t pid, int cpu_no)
|
||||
{
|
||||
int pe_fd;
|
||||
|
||||
pe_fd = perf_event_open(pea, pid, cpu_no, -1, PERF_FLAG_FD_CLOEXEC);
|
||||
if (pe_fd == -1) {
|
||||
ksft_perror("Error opening leader");
|
||||
ksft_perror("Unable to set up performance monitoring");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -132,9 +125,9 @@ static int print_results_cache(const char *filename, pid_t bm_pid, __u64 llc_val
|
||||
*
|
||||
* Return: =0 on success. <0 on failure.
|
||||
*/
|
||||
int perf_event_measure(int pe_fd, struct perf_event_read *pe_read,
|
||||
const char *filename, pid_t bm_pid)
|
||||
int perf_event_measure(int pe_fd, const char *filename, pid_t bm_pid)
|
||||
{
|
||||
__u64 value;
|
||||
int ret;
|
||||
|
||||
/* Stop counters after one span to get miss rate */
|
||||
@@ -142,13 +135,13 @@ int perf_event_measure(int pe_fd, struct perf_event_read *pe_read,
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = read(pe_fd, pe_read, sizeof(*pe_read));
|
||||
ret = read(pe_fd, &value, sizeof(value));
|
||||
if (ret == -1) {
|
||||
ksft_perror("Could not get perf value");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return print_results_cache(filename, bm_pid, pe_read->values[0].value);
|
||||
return print_results_cache(filename, bm_pid, value);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -173,6 +166,19 @@ int measure_llc_resctrl(const char *filename, pid_t bm_pid)
|
||||
return print_results_cache(filename, bm_pid, llc_occu_resc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Reduce L2 allocation to minimum when testing L3 cache allocation.
|
||||
*/
|
||||
int minimize_l2_occupancy(const struct resctrl_test *test,
|
||||
const struct user_params *uparams,
|
||||
const struct resctrl_val_param *param)
|
||||
{
|
||||
if (!strcmp(test->resource, "L3") && resctrl_resource_exists("L2"))
|
||||
return write_schemata(param->ctrlgrp, "0x1", uparams->cpu, "L2");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* show_cache_info - Show generic cache test information
|
||||
* @no_of_bits: Number of bits
|
||||
|
||||
@@ -14,42 +14,20 @@
|
||||
#define RESULT_FILE_NAME "result_cat"
|
||||
#define NUM_OF_RUNS 5
|
||||
|
||||
/*
|
||||
* Minimum difference in LLC misses between a test with n+1 bits CBM to the
|
||||
* test with n bits is MIN_DIFF_PERCENT_PER_BIT * (n - 1). With e.g. 5 vs 4
|
||||
* bits in the CBM mask, the minimum difference must be at least
|
||||
* MIN_DIFF_PERCENT_PER_BIT * (4 - 1) = 3 percent.
|
||||
*
|
||||
* The relationship between number of used CBM bits and difference in LLC
|
||||
* misses is not expected to be linear. With a small number of bits, the
|
||||
* margin is smaller than with larger number of bits. For selftest purposes,
|
||||
* however, linear approach is enough because ultimately only pass/fail
|
||||
* decision has to be made and distinction between strong and stronger
|
||||
* signal is irrelevant.
|
||||
*/
|
||||
#define MIN_DIFF_PERCENT_PER_BIT 1UL
|
||||
|
||||
static int show_results_info(__u64 sum_llc_val, int no_of_bits,
|
||||
unsigned long cache_span,
|
||||
unsigned long min_diff_percent,
|
||||
unsigned long num_of_runs, bool platform,
|
||||
__s64 *prev_avg_llc_val)
|
||||
{
|
||||
__u64 avg_llc_val = 0;
|
||||
float avg_diff;
|
||||
int ret = 0;
|
||||
|
||||
avg_llc_val = sum_llc_val / num_of_runs;
|
||||
if (*prev_avg_llc_val) {
|
||||
float delta = (__s64)(avg_llc_val - *prev_avg_llc_val);
|
||||
ret = platform && (avg_llc_val < *prev_avg_llc_val);
|
||||
|
||||
avg_diff = delta / *prev_avg_llc_val;
|
||||
ret = platform && (avg_diff * 100) < (float)min_diff_percent;
|
||||
|
||||
ksft_print_msg("%s Check cache miss rate changed more than %.1f%%\n",
|
||||
ret ? "Fail:" : "Pass:", (float)min_diff_percent);
|
||||
|
||||
ksft_print_msg("Percent diff=%.1f\n", avg_diff * 100);
|
||||
ksft_print_msg("%s Check cache miss rate increased\n",
|
||||
ret ? "Fail:" : "Pass:");
|
||||
}
|
||||
*prev_avg_llc_val = avg_llc_val;
|
||||
|
||||
@@ -58,10 +36,10 @@ static int show_results_info(__u64 sum_llc_val, int no_of_bits,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Remove the highest bit from CBM */
|
||||
/* Remove the highest bits from CBM */
|
||||
static unsigned long next_mask(unsigned long current_mask)
|
||||
{
|
||||
return current_mask & (current_mask >> 1);
|
||||
return current_mask & (current_mask >> 2);
|
||||
}
|
||||
|
||||
static int check_results(struct resctrl_val_param *param, const char *cache_type,
|
||||
@@ -112,7 +90,6 @@ static int check_results(struct resctrl_val_param *param, const char *cache_type
|
||||
|
||||
ret = show_results_info(sum_llc_perf_miss, bits,
|
||||
alloc_size / 64,
|
||||
MIN_DIFF_PERCENT_PER_BIT * (bits - 1),
|
||||
runs, get_vendor() == ARCH_INTEL,
|
||||
&prev_avg_llc_val);
|
||||
if (ret)
|
||||
@@ -158,7 +135,6 @@ static int cat_test(const struct resctrl_test *test,
|
||||
struct resctrl_val_param *param,
|
||||
size_t span, unsigned long current_mask)
|
||||
{
|
||||
struct perf_event_read pe_read;
|
||||
struct perf_event_attr pea;
|
||||
cpu_set_t old_affinity;
|
||||
unsigned char *buf;
|
||||
@@ -181,8 +157,11 @@ static int cat_test(const struct resctrl_test *test,
|
||||
if (ret)
|
||||
goto reset_affinity;
|
||||
|
||||
ret = minimize_l2_occupancy(test, uparams, param);
|
||||
if (ret)
|
||||
goto reset_affinity;
|
||||
|
||||
perf_event_attr_initialize(&pea, PERF_COUNT_HW_CACHE_MISSES);
|
||||
perf_event_initialize_read_format(&pe_read);
|
||||
pe_fd = perf_open(&pea, bm_pid, uparams->cpu);
|
||||
if (pe_fd < 0) {
|
||||
ret = -1;
|
||||
@@ -215,7 +194,7 @@ static int cat_test(const struct resctrl_test *test,
|
||||
|
||||
fill_cache_read(buf, span, true);
|
||||
|
||||
ret = perf_event_measure(pe_fd, &pe_read, param->filename, bm_pid);
|
||||
ret = perf_event_measure(pe_fd, param->filename, bm_pid);
|
||||
if (ret)
|
||||
goto free_buf;
|
||||
}
|
||||
|
||||
@@ -19,12 +19,40 @@
|
||||
#define CON_MON_LCC_OCCUP_PATH \
|
||||
"%s/%s/mon_data/mon_L3_%02d/llc_occupancy"
|
||||
|
||||
static int cmt_init(const struct resctrl_val_param *param, int domain_id)
|
||||
/*
|
||||
* Initialize capacity bitmasks (CBMs) of:
|
||||
* - control group being tested per test parameters,
|
||||
* - default resource group as inverse of control group being tested to prevent
|
||||
* other tasks from interfering with test,
|
||||
* - L2 resource of control group being tested to minimize allocations into
|
||||
* L2 if possible to better predict L3 occupancy.
|
||||
*/
|
||||
static int cmt_init(const struct resctrl_test *test,
|
||||
const struct user_params *uparams,
|
||||
const struct resctrl_val_param *param, int domain_id)
|
||||
{
|
||||
unsigned long full_mask;
|
||||
char schemata[64];
|
||||
int ret;
|
||||
|
||||
sprintf(llc_occup_path, CON_MON_LCC_OCCUP_PATH, RESCTRL_PATH,
|
||||
param->ctrlgrp, domain_id);
|
||||
|
||||
return 0;
|
||||
ret = get_full_cbm(test->resource, &full_mask);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
snprintf(schemata, sizeof(schemata), "%lx", ~param->mask & full_mask);
|
||||
ret = write_schemata("", schemata, uparams->cpu, test->resource);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
snprintf(schemata, sizeof(schemata), "%lx", param->mask);
|
||||
ret = write_schemata(param->ctrlgrp, schemata, uparams->cpu, test->resource);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return minimize_l2_occupancy(test, uparams, param);
|
||||
}
|
||||
|
||||
static int cmt_setup(const struct resctrl_test *test,
|
||||
@@ -153,11 +181,11 @@ static int cmt_run_test(const struct resctrl_test *test, const struct user_param
|
||||
span = cache_portion_size(cache_total_size, param.mask, long_mask);
|
||||
|
||||
if (uparams->fill_buf) {
|
||||
fill_buf.buf_size = span;
|
||||
fill_buf.buf_size = span * 2;
|
||||
fill_buf.memflush = uparams->fill_buf->memflush;
|
||||
param.fill_buf = &fill_buf;
|
||||
} else if (!uparams->benchmark_cmd[0]) {
|
||||
fill_buf.buf_size = span;
|
||||
fill_buf.buf_size = span * 2;
|
||||
fill_buf.memflush = true;
|
||||
param.fill_buf = &fill_buf;
|
||||
}
|
||||
|
||||
@@ -139,6 +139,6 @@ ssize_t get_fill_buf_size(int cpu_no, const char *cache_type)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return cache_total_size * 2 > MINIMUM_SPAN ?
|
||||
cache_total_size * 2 : MINIMUM_SPAN;
|
||||
return cache_total_size * 4 > MINIMUM_SPAN ?
|
||||
cache_total_size * 4 : MINIMUM_SPAN;
|
||||
}
|
||||
|
||||
@@ -12,12 +12,14 @@
|
||||
|
||||
#define RESULT_FILE_NAME "result_mba"
|
||||
#define NUM_OF_RUNS 5
|
||||
#define MAX_DIFF_PERCENT 8
|
||||
#define MAX_DIFF_PERCENT 15
|
||||
#define ALLOCATION_MAX 100
|
||||
#define ALLOCATION_MIN 10
|
||||
#define ALLOCATION_STEP 10
|
||||
|
||||
static int mba_init(const struct resctrl_val_param *param, int domain_id)
|
||||
static int mba_init(const struct resctrl_test *test,
|
||||
const struct user_params *uparams,
|
||||
const struct resctrl_val_param *param, int domain_id)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#include "resctrl.h"
|
||||
|
||||
#define RESULT_FILE_NAME "result_mbm"
|
||||
#define MAX_DIFF_PERCENT 8
|
||||
#define MAX_DIFF_PERCENT 15
|
||||
#define NUM_OF_RUNS 5
|
||||
|
||||
static int
|
||||
@@ -83,7 +83,9 @@ static int check_results(size_t span)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mbm_init(const struct resctrl_val_param *param, int domain_id)
|
||||
static int mbm_init(const struct resctrl_test *test,
|
||||
const struct user_params *uparams,
|
||||
const struct resctrl_val_param *param, int domain_id)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
* and MBM respectively, for instance generating "overhead" traffic which
|
||||
* is not counted against any specific RMID.
|
||||
*/
|
||||
#define THROTTLE_THRESHOLD 750
|
||||
#define THROTTLE_THRESHOLD 2500
|
||||
|
||||
/*
|
||||
* fill_buf_param: "fill_buf" benchmark parameters
|
||||
@@ -135,7 +135,9 @@ struct resctrl_val_param {
|
||||
char filename[64];
|
||||
unsigned long mask;
|
||||
int num_of_runs;
|
||||
int (*init)(const struct resctrl_val_param *param,
|
||||
int (*init)(const struct resctrl_test *test,
|
||||
const struct user_params *uparams,
|
||||
const struct resctrl_val_param *param,
|
||||
int domain_id);
|
||||
int (*setup)(const struct resctrl_test *test,
|
||||
const struct user_params *uparams,
|
||||
@@ -146,13 +148,6 @@ struct resctrl_val_param {
|
||||
struct fill_buf_param *fill_buf;
|
||||
};
|
||||
|
||||
struct perf_event_read {
|
||||
__u64 nr; /* The number of events */
|
||||
struct {
|
||||
__u64 value; /* The value of the event */
|
||||
} values[2];
|
||||
};
|
||||
|
||||
/*
|
||||
* Memory location that consumes values compiler must not optimize away.
|
||||
* Volatile ensures writes to this location cannot be optimized away by
|
||||
@@ -208,12 +203,13 @@ unsigned int count_bits(unsigned long n);
|
||||
int snc_kernel_support(void);
|
||||
|
||||
void perf_event_attr_initialize(struct perf_event_attr *pea, __u64 config);
|
||||
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, pid_t bm_pid);
|
||||
int perf_event_measure(int pe_fd, const char *filename, pid_t bm_pid);
|
||||
int measure_llc_resctrl(const char *filename, pid_t bm_pid);
|
||||
int minimize_l2_occupancy(const struct resctrl_test *test,
|
||||
const struct user_params *uparams,
|
||||
const struct resctrl_val_param *param);
|
||||
void show_cache_info(int no_of_bits, __u64 avg_llc_val, size_t cache_span, bool lines);
|
||||
|
||||
/*
|
||||
|
||||
@@ -11,10 +11,10 @@
|
||||
#include "resctrl.h"
|
||||
|
||||
#define UNCORE_IMC "uncore_imc"
|
||||
#define READ_FILE_NAME "events/cas_count_read"
|
||||
#define READ_FILE_NAME "cas_count_read"
|
||||
#define DYN_PMU_PATH "/sys/bus/event_source/devices"
|
||||
#define SCALE 0.00006103515625
|
||||
#define MAX_IMCS 20
|
||||
#define MAX_IMCS 40
|
||||
#define MAX_TOKENS 5
|
||||
|
||||
#define CON_MBM_LOCAL_BYTES_PATH \
|
||||
@@ -32,7 +32,6 @@ struct imc_counter_config {
|
||||
__u64 event;
|
||||
__u64 umask;
|
||||
struct perf_event_attr pe;
|
||||
struct membw_read_format return_value;
|
||||
int fd;
|
||||
};
|
||||
|
||||
@@ -74,7 +73,7 @@ static void read_mem_bw_ioctl_perf_event_ioc_disable(int i)
|
||||
* @cas_count_cfg: Config
|
||||
* @count: iMC number
|
||||
*/
|
||||
static void get_read_event_and_umask(char *cas_count_cfg, int count)
|
||||
static void get_read_event_and_umask(char *cas_count_cfg, unsigned int count)
|
||||
{
|
||||
char *token[MAX_TOKENS];
|
||||
int i = 0;
|
||||
@@ -110,45 +109,114 @@ static int open_perf_read_event(int i, int cpu_no)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get type and config of an iMC counter's read event. */
|
||||
static int read_from_imc_dir(char *imc_dir, int count)
|
||||
static int parse_imc_read_bw_events(char *imc_dir, unsigned int type,
|
||||
unsigned int *count)
|
||||
{
|
||||
char cas_count_cfg[1024], imc_counter_cfg[1024], imc_counter_type[1024];
|
||||
char imc_events_dir[PATH_MAX], imc_counter_cfg[PATH_MAX];
|
||||
unsigned int orig_count = *count;
|
||||
char cas_count_cfg[1024];
|
||||
struct dirent *ep;
|
||||
int path_len;
|
||||
int ret = -1;
|
||||
int num_cfg;
|
||||
FILE *fp;
|
||||
DIR *dp;
|
||||
|
||||
path_len = snprintf(imc_events_dir, sizeof(imc_events_dir), "%sevents",
|
||||
imc_dir);
|
||||
if (path_len >= sizeof(imc_events_dir)) {
|
||||
ksft_print_msg("Unable to create path to %sevents\n", imc_dir);
|
||||
return -1;
|
||||
}
|
||||
|
||||
dp = opendir(imc_events_dir);
|
||||
if (!dp) {
|
||||
ksft_perror("Unable to open PMU events directory");
|
||||
return -1;
|
||||
}
|
||||
|
||||
while ((ep = readdir(dp))) {
|
||||
/*
|
||||
* Parse all event files with READ_FILE_NAME prefix that
|
||||
* contain the event number and umask. Skip files containing
|
||||
* "." that contain unused properties of event.
|
||||
*/
|
||||
if (!strstr(ep->d_name, READ_FILE_NAME) ||
|
||||
strchr(ep->d_name, '.'))
|
||||
continue;
|
||||
|
||||
path_len = snprintf(imc_counter_cfg, sizeof(imc_counter_cfg),
|
||||
"%s/%s", imc_events_dir, ep->d_name);
|
||||
if (path_len >= sizeof(imc_counter_cfg)) {
|
||||
ksft_print_msg("Unable to create path to %s/%s\n",
|
||||
imc_events_dir, ep->d_name);
|
||||
goto out_close;
|
||||
}
|
||||
fp = fopen(imc_counter_cfg, "r");
|
||||
if (!fp) {
|
||||
ksft_perror("Failed to open iMC config file");
|
||||
goto out_close;
|
||||
}
|
||||
num_cfg = fscanf(fp, "%1023s", cas_count_cfg);
|
||||
fclose(fp);
|
||||
if (num_cfg <= 0) {
|
||||
ksft_perror("Could not get iMC cas count read");
|
||||
goto out_close;
|
||||
}
|
||||
if (*count >= MAX_IMCS) {
|
||||
ksft_print_msg("Maximum iMC count exceeded\n");
|
||||
goto out_close;
|
||||
}
|
||||
|
||||
imc_counters_config[*count].type = type;
|
||||
get_read_event_and_umask(cas_count_cfg, *count);
|
||||
/* Do not fail after incrementing *count. */
|
||||
*count += 1;
|
||||
}
|
||||
if (*count == orig_count) {
|
||||
ksft_print_msg("Unable to find events in %s\n", imc_events_dir);
|
||||
goto out_close;
|
||||
}
|
||||
ret = 0;
|
||||
out_close:
|
||||
closedir(dp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Get type and config of an iMC counter's read event. */
|
||||
static int read_from_imc_dir(char *imc_dir, unsigned int *count)
|
||||
{
|
||||
char imc_counter_type[PATH_MAX];
|
||||
unsigned int type;
|
||||
int path_len;
|
||||
FILE *fp;
|
||||
int ret;
|
||||
|
||||
/* Get type of iMC counter */
|
||||
sprintf(imc_counter_type, "%s%s", imc_dir, "type");
|
||||
path_len = snprintf(imc_counter_type, sizeof(imc_counter_type),
|
||||
"%s%s", imc_dir, "type");
|
||||
if (path_len >= sizeof(imc_counter_type)) {
|
||||
ksft_print_msg("Unable to create path to %s%s\n",
|
||||
imc_dir, "type");
|
||||
return -1;
|
||||
}
|
||||
fp = fopen(imc_counter_type, "r");
|
||||
if (!fp) {
|
||||
ksft_perror("Failed to open iMC counter type file");
|
||||
|
||||
return -1;
|
||||
}
|
||||
if (fscanf(fp, "%u", &imc_counters_config[count].type) <= 0) {
|
||||
ret = fscanf(fp, "%u", &type);
|
||||
fclose(fp);
|
||||
if (ret <= 0) {
|
||||
ksft_perror("Could not get iMC type");
|
||||
fclose(fp);
|
||||
|
||||
return -1;
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
/* Get read config */
|
||||
sprintf(imc_counter_cfg, "%s%s", imc_dir, READ_FILE_NAME);
|
||||
fp = fopen(imc_counter_cfg, "r");
|
||||
if (!fp) {
|
||||
ksft_perror("Failed to open iMC config file");
|
||||
|
||||
return -1;
|
||||
ret = parse_imc_read_bw_events(imc_dir, type, count);
|
||||
if (ret) {
|
||||
ksft_print_msg("Unable to parse bandwidth event and umask\n");
|
||||
return ret;
|
||||
}
|
||||
if (fscanf(fp, "%1023s", cas_count_cfg) <= 0) {
|
||||
ksft_perror("Could not get iMC cas count read");
|
||||
fclose(fp);
|
||||
|
||||
return -1;
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
get_read_event_and_umask(cas_count_cfg, count);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -197,13 +265,12 @@ static int num_of_imcs(void)
|
||||
if (temp[0] >= '0' && temp[0] <= '9') {
|
||||
sprintf(imc_dir, "%s/%s/", DYN_PMU_PATH,
|
||||
ep->d_name);
|
||||
ret = read_from_imc_dir(imc_dir, count);
|
||||
ret = read_from_imc_dir(imc_dir, &count);
|
||||
if (ret) {
|
||||
closedir(dp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
}
|
||||
closedir(dp);
|
||||
@@ -312,23 +379,23 @@ static int get_read_mem_bw_imc(float *bw_imc)
|
||||
* Take overflow into consideration before calculating total bandwidth.
|
||||
*/
|
||||
for (imc = 0; imc < imcs; imc++) {
|
||||
struct membw_read_format measurement;
|
||||
struct imc_counter_config *r =
|
||||
&imc_counters_config[imc];
|
||||
|
||||
if (read(r->fd, &r->return_value,
|
||||
sizeof(struct membw_read_format)) == -1) {
|
||||
if (read(r->fd, &measurement, sizeof(measurement)) == -1) {
|
||||
ksft_perror("Couldn't get read bandwidth through iMC");
|
||||
return -1;
|
||||
}
|
||||
|
||||
__u64 r_time_enabled = r->return_value.time_enabled;
|
||||
__u64 r_time_running = r->return_value.time_running;
|
||||
__u64 r_time_enabled = measurement.time_enabled;
|
||||
__u64 r_time_running = measurement.time_running;
|
||||
|
||||
if (r_time_enabled != r_time_running)
|
||||
of_mul_read = (float)r_time_enabled /
|
||||
(float)r_time_running;
|
||||
|
||||
reads += r->return_value.value * of_mul_read * SCALE;
|
||||
reads += measurement.value * of_mul_read * SCALE;
|
||||
}
|
||||
|
||||
*bw_imc = reads;
|
||||
@@ -569,7 +636,7 @@ int resctrl_val(const struct resctrl_test *test,
|
||||
goto reset_affinity;
|
||||
|
||||
if (param->init) {
|
||||
ret = param->init(param, domain_id);
|
||||
ret = param->init(test, uparams, param, domain_id);
|
||||
if (ret)
|
||||
goto reset_affinity;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user