selftests/resctrl: Exclude shareable bits from schemata in CAT test

CAT test doesn't take shareable bits into account, i.e., the test might
be sharing cache with some devices (e.g., graphics).

Introduce get_mask_no_shareable() and use it to provision an
environment for CAT test where the allocated LLC is isolated better.
Excluding shareable_bits may create hole(s) into the cbm_mask, thus add
a new helper count_contiguous_bits() to find the longest contiguous set
of CBM bits.

create_bit_mask() is needed by an upcoming CAT test rewrite so make it
available in resctrl.h right away.

Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Reviewed-by: Reinette Chatre <reinette.chatre@intel.com>
Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
This commit is contained in:
Ilpo Järvinen 2023-12-15 17:04:56 +02:00 committed by Shuah Khan
parent 19e94a2333
commit b6dfac9486
3 changed files with 99 additions and 4 deletions

View File

@ -89,15 +89,19 @@ void cat_test_cleanup(void)
int cat_perf_miss_val(int cpu_no, int n, char *cache_type)
{
unsigned long full_cache_mask, long_mask;
unsigned long l_mask, l_mask_1;
int ret, pipefd[2], sibling_cpu_no;
unsigned long cache_total_size = 0;
unsigned long long_mask;
int count_of_bits;
char pipe_message;
size_t span;
ret = get_full_cbm(cache_type, &long_mask);
ret = get_full_cbm(cache_type, &full_cache_mask);
if (ret)
return ret;
/* Get the largest contiguous exclusive portion of the cache */
ret = get_mask_no_shareable(cache_type, &long_mask);
if (ret)
return ret;
@ -136,7 +140,7 @@ int cat_perf_miss_val(int cpu_no, int n, char *cache_type)
/* Set param values for parent thread which will be allocated bitmask
* with (max_bits - n) bits
*/
span = cache_portion_size(cache_total_size, l_mask, long_mask);
span = cache_portion_size(cache_total_size, l_mask, full_cache_mask);
strcpy(param.ctrlgrp, "c2");
strcpy(param.mongrp, "m2");
strcpy(param.filename, RESULT_FILE_NAME2);
@ -158,7 +162,7 @@ int cat_perf_miss_val(int cpu_no, int n, char *cache_type)
param.mask = l_mask_1;
strcpy(param.ctrlgrp, "c1");
strcpy(param.mongrp, "m1");
span = cache_portion_size(cache_total_size, l_mask_1, long_mask);
span = cache_portion_size(cache_total_size, l_mask_1, full_cache_mask);
strcpy(param.filename, RESULT_FILE_NAME1);
param.num_of_runs = 0;
param.cpu_no = sibling_cpu_no;

View File

@ -98,7 +98,9 @@ void tests_cleanup(void);
void mbm_test_cleanup(void);
int mba_schemata_change(int cpu_no, const char * const *benchmark_cmd);
void mba_test_cleanup(void);
unsigned long create_bit_mask(unsigned int start, unsigned int len);
int get_full_cbm(const char *cache_type, unsigned long *mask);
int get_mask_no_shareable(const char *cache_type, unsigned long *mask);
int get_cache_size(int cpu_no, const char *cache_type, unsigned long *cache_size);
void ctrlc_handler(int signum, siginfo_t *info, void *ptr);
int signal_handler_register(void);

View File

@ -228,6 +228,44 @@ static int get_bit_mask(const char *filename, unsigned long *mask)
return 0;
}
/*
* create_bit_mask- Create bit mask from start, len pair
* @start: LSB of the mask
* @len Number of bits in the mask
*/
unsigned long create_bit_mask(unsigned int start, unsigned int len)
{
return ((1UL << len) - 1UL) << start;
}
/*
* count_contiguous_bits - Returns the longest train of bits in a bit mask
* @val A bit mask
* @start The location of the least-significant bit of the longest train
*
* Return: The length of the contiguous bits in the longest train of bits
*/
static unsigned int count_contiguous_bits(unsigned long val, unsigned int *start)
{
unsigned long last_val;
unsigned int count = 0;
while (val) {
last_val = val;
val &= (val >> 1);
count++;
}
if (start) {
if (count)
*start = ffsl(last_val) - 1;
else
*start = 0;
}
return count;
}
/*
* get_full_cbm - Get full Cache Bit Mask (CBM)
* @cache_type: Cache type as "L2" or "L3"
@ -254,6 +292,57 @@ int get_full_cbm(const char *cache_type, unsigned long *mask)
return 0;
}
/*
* get_shareable_mask - Get shareable mask from shareable_bits
* @cache_type: Cache type as "L2" or "L3"
* @shareable_mask: Shareable mask returned as unsigned long
*
* Return: = 0 on success, < 0 on failure.
*/
static int get_shareable_mask(const char *cache_type, unsigned long *shareable_mask)
{
char mask_path[PATH_MAX];
if (!cache_type)
return -1;
snprintf(mask_path, sizeof(mask_path), "%s/%s/shareable_bits",
INFO_PATH, cache_type);
return get_bit_mask(mask_path, shareable_mask);
}
/*
* get_mask_no_shareable - Get Cache Bit Mask (CBM) without shareable bits
* @cache_type: Cache type as "L2" or "L3"
* @mask: The largest exclusive portion of the cache out of the
* full CBM, returned as unsigned long
*
* Parts of a cache may be shared with other devices such as GPU. This function
* calculates the largest exclusive portion of the cache where no other devices
* besides CPU have access to the cache portion.
*
* Return: = 0 on success, < 0 on failure.
*/
int get_mask_no_shareable(const char *cache_type, unsigned long *mask)
{
unsigned long full_mask, shareable_mask;
unsigned int start, len;
if (get_full_cbm(cache_type, &full_mask) < 0)
return -1;
if (get_shareable_mask(cache_type, &shareable_mask) < 0)
return -1;
len = count_contiguous_bits(full_mask & ~shareable_mask, &start);
if (!len)
return -1;
*mask = create_bit_mask(start, len);
return 0;
}
/*
* get_core_sibling - Get sibling core id from the same socket for given CPU
* @cpu_no: CPU number