-
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.
selftests/resctrl: Add Cache QoS Monitoring (CQM) selftest
Cache QoS Monitoring (CQM) selftest starts stressful cache benchmark with specified size of memory to access the cache. Last Level cache occupancy reported by CQM should be close to the size of the memory. 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
01fee6b
commit 7894118
Showing
6 changed files
with
558 additions
and
20 deletions.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
|
||
#include <stdint.h> | ||
#include "resctrl.h" | ||
|
||
struct read_format { | ||
__u64 nr; /* The number of events */ | ||
struct { | ||
__u64 value; /* The value of the event */ | ||
} values[2]; | ||
}; | ||
|
||
char llc_occup_path[1024]; | ||
|
||
/* | ||
* Get LLC Occupancy as reported by RESCTRL FS | ||
* For CQM, | ||
* 1. If con_mon grp and mon grp given, then read from mon grp in | ||
* con_mon grp | ||
* 2. If only con_mon grp given, then read from con_mon grp | ||
* 3. If both not given, then read from root con_mon grp | ||
* For CAT, | ||
* 1. If con_mon grp given, then read from it | ||
* 2. If con_mon grp not given, then read from root con_mon grp | ||
* | ||
* Return: =0 on success. <0 on failure. | ||
*/ | ||
static int get_llc_occu_resctrl(unsigned long *llc_occupancy) | ||
{ | ||
FILE *fp; | ||
|
||
fp = fopen(llc_occup_path, "r"); | ||
if (!fp) { | ||
perror("Failed to open results file"); | ||
|
||
return errno; | ||
} | ||
if (fscanf(fp, "%lu", llc_occupancy) <= 0) { | ||
perror("Could not get llc occupancy"); | ||
fclose(fp); | ||
|
||
return -1; | ||
} | ||
fclose(fp); | ||
|
||
return 0; | ||
} | ||
|
||
/* | ||
* print_results_cache: the cache results are stored in a file | ||
* @filename: file that stores the results | ||
* @bm_pid: child pid that runs benchmark | ||
* @llc_value: perf miss value / | ||
* llc occupancy value reported by resctrl FS | ||
* | ||
* Return: 0 on success. non-zero on failure. | ||
*/ | ||
static int print_results_cache(char *filename, int bm_pid, | ||
unsigned long llc_value) | ||
{ | ||
FILE *fp; | ||
|
||
if (strcmp(filename, "stdio") == 0 || strcmp(filename, "stderr") == 0) { | ||
printf("Pid: %d \t LLC_value: %lu\n", bm_pid, | ||
llc_value); | ||
} else { | ||
fp = fopen(filename, "a"); | ||
if (!fp) { | ||
perror("Cannot open results file"); | ||
|
||
return errno; | ||
} | ||
fprintf(fp, "Pid: %d \t llc_value: %lu\n", bm_pid, llc_value); | ||
fclose(fp); | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
int measure_cache_vals(struct resctrl_val_param *param, int bm_pid) | ||
{ | ||
unsigned long llc_occu_resc = 0, llc_value = 0; | ||
int ret; | ||
|
||
/* | ||
* Measure llc occupancy from resctrl. | ||
*/ | ||
if (!strcmp(param->resctrl_val, "cqm")) { | ||
ret = get_llc_occu_resctrl(&llc_occu_resc); | ||
if (ret < 0) | ||
return ret; | ||
llc_value = llc_occu_resc; | ||
} | ||
ret = print_results_cache(param->filename, bm_pid, llc_value); | ||
if (ret) | ||
return ret; | ||
|
||
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
/* | ||
* Cache Monitoring Technology (CQM) test | ||
* | ||
* Copyright (C) 2018 Intel Corporation | ||
* | ||
* Authors: | ||
* Sai Praneeth Prakhya <sai.praneeth.prakhya@intel.com>, | ||
* Fenghua Yu <fenghua.yu@intel.com> | ||
*/ | ||
#include "resctrl.h" | ||
#include <unistd.h> | ||
|
||
#define RESULT_FILE_NAME "result_cqm" | ||
#define NUM_OF_RUNS 5 | ||
#define MAX_DIFF 2000000 | ||
#define MAX_DIFF_PERCENT 15 | ||
|
||
int count_of_bits; | ||
char cbm_mask[256]; | ||
unsigned long long_mask; | ||
unsigned long cache_size; | ||
|
||
static int cqm_setup(int num, ...) | ||
{ | ||
struct resctrl_val_param *p; | ||
va_list param; | ||
|
||
va_start(param, num); | ||
p = va_arg(param, struct resctrl_val_param *); | ||
va_end(param); | ||
|
||
/* Run NUM_OF_RUNS times */ | ||
if (p->num_of_runs >= NUM_OF_RUNS) | ||
return -1; | ||
|
||
p->num_of_runs++; | ||
|
||
return 0; | ||
} | ||
|
||
static void show_cache_info(unsigned long sum_llc_occu_resc, int no_of_bits, | ||
unsigned long span) | ||
{ | ||
unsigned long avg_llc_occu_resc = 0; | ||
float diff_percent; | ||
long avg_diff = 0; | ||
bool res; | ||
|
||
avg_llc_occu_resc = sum_llc_occu_resc / (NUM_OF_RUNS - 1); | ||
avg_diff = (long)abs(span - avg_llc_occu_resc); | ||
|
||
diff_percent = (((float)span - avg_llc_occu_resc) / span) * 100; | ||
|
||
if ((abs((int)diff_percent) <= MAX_DIFF_PERCENT) || | ||
(abs(avg_diff) <= MAX_DIFF)) | ||
res = true; | ||
else | ||
res = false; | ||
|
||
printf("%sok CQM: diff within %d, %d\%%\n", res ? "" : "not", | ||
MAX_DIFF, (int)MAX_DIFF_PERCENT); | ||
|
||
printf("# diff: %ld\n", avg_diff); | ||
printf("# percent diff=%d\n", abs((int)diff_percent)); | ||
printf("# Results are displayed in (Bytes)\n"); | ||
printf("# Number of bits: %d\n", no_of_bits); | ||
printf("# Avg_llc_occu_resc: %lu\n", avg_llc_occu_resc); | ||
printf("# llc_occu_exp (span): %lu\n", span); | ||
|
||
tests_run++; | ||
} | ||
|
||
static int check_results(struct resctrl_val_param *param, int no_of_bits) | ||
{ | ||
char *token_array[8], temp[512]; | ||
unsigned long sum_llc_occu_resc = 0; | ||
int runs = 0; | ||
FILE *fp; | ||
|
||
printf("# checking for pass/fail\n"); | ||
fp = fopen(param->filename, "r"); | ||
if (!fp) { | ||
perror("# Error in opening file\n"); | ||
|
||
return errno; | ||
} | ||
|
||
while (fgets(temp, 1024, fp)) { | ||
char *token = strtok(temp, ":\t"); | ||
int fields = 0; | ||
|
||
while (token) { | ||
token_array[fields++] = token; | ||
token = strtok(NULL, ":\t"); | ||
} | ||
|
||
/* Field 3 is llc occ resc value */ | ||
if (runs > 0) | ||
sum_llc_occu_resc += strtoul(token_array[3], NULL, 0); | ||
runs++; | ||
} | ||
fclose(fp); | ||
show_cache_info(sum_llc_occu_resc, no_of_bits, param->span); | ||
|
||
return 0; | ||
} | ||
|
||
void cqm_test_cleanup(void) | ||
{ | ||
remove(RESULT_FILE_NAME); | ||
} | ||
|
||
int cqm_resctrl_val(int cpu_no, int n, char **benchmark_cmd) | ||
{ | ||
int ret, mum_resctrlfs; | ||
|
||
cache_size = 0; | ||
mum_resctrlfs = 1; | ||
|
||
ret = remount_resctrlfs(mum_resctrlfs); | ||
if (ret) | ||
return ret; | ||
|
||
if (!validate_resctrl_feature_request("cqm")) | ||
return -1; | ||
|
||
ret = get_cbm_mask("L3"); | ||
if (ret) | ||
return ret; | ||
|
||
long_mask = strtoul(cbm_mask, NULL, 16); | ||
|
||
ret = get_cache_size(cpu_no, "L3", &cache_size); | ||
if (ret) | ||
return ret; | ||
printf("cache size :%lu\n", cache_size); | ||
|
||
count_of_bits = count_bits(long_mask); | ||
|
||
if (n < 1 || n > count_of_bits) { | ||
printf("Invalid input value for numbr_of_bits n!\n"); | ||
printf("Please Enter value in range 1 to %d\n", count_of_bits); | ||
return -1; | ||
} | ||
|
||
struct resctrl_val_param param = { | ||
.resctrl_val = "cqm", | ||
.ctrlgrp = "c1", | ||
.mongrp = "m1", | ||
.cpu_no = cpu_no, | ||
.mum_resctrlfs = 0, | ||
.filename = RESULT_FILE_NAME, | ||
.mask = ~(long_mask << n) & long_mask, | ||
.span = cache_size * n / count_of_bits, | ||
.num_of_runs = 0, | ||
.setup = cqm_setup, | ||
}; | ||
|
||
if (strcmp(benchmark_cmd[0], "fill_buf") == 0) | ||
sprintf(benchmark_cmd[1], "%lu", param.span); | ||
|
||
remove(RESULT_FILE_NAME); | ||
|
||
ret = resctrl_val(benchmark_cmd, ¶m); | ||
if (ret) | ||
return ret; | ||
|
||
ret = check_results(¶m, n); | ||
if (ret) | ||
return ret; | ||
|
||
cqm_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
Oops, something went wrong.