/* * 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
staticint show_results_info(__u64 sum_llc_val, int no_of_bits, unsignedlong cache_span, unsignedlong min_diff_percent, unsignedlong num_of_runs, bool platform,
__s64 *prev_avg_llc_val)
{
__u64 avg_llc_val = 0; float avg_diff; int ret = 0;
/* * cat_test - Execute CAT benchmark and measure cache misses * @test: Test information structure * @uparams: User supplied parameters * @param: Parameters passed to cat_test() * @span: Buffer size for the benchmark * @current_mask Start mask for the first iteration * * Run CAT selftest by varying the allocated cache portion and comparing the * impact on cache misses (the result analysis is done in check_results() * and show_results_info(), not in this function). * * One bit is removed from the CAT allocation bit mask (in current_mask) for * each subsequent test which keeps reducing the size of the allocated cache * portion. A single test flushes the buffer, reads it to warm up the cache, * and reads the buffer again. The cache misses are measured during the last * read pass. * * Return: 0 when the test was run, < 0 on error.
*/ staticint cat_test(conststruct resctrl_test *test, conststruct user_params *uparams, struct resctrl_val_param *param,
size_t span, unsignedlong current_mask)
{ struct perf_event_read pe_read; struct perf_event_attr pea;
cpu_set_t old_affinity; unsignedchar *buf; char schemata[64]; int ret, i, pe_fd;
pid_t bm_pid;
if (strcmp(param->filename, "") == 0)
sprintf(param->filename, "stdio");
bm_pid = getpid();
/* Taskset benchmark to specified cpu */
ret = taskset_benchmark(bm_pid, uparams->cpu, &old_affinity); if (ret) return ret;
/* Write benchmark to specified con_mon grp, mon_grp in resctrl FS*/
ret = write_bm_pid_to_resctrl(bm_pid, param->ctrlgrp, param->mongrp); 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; goto reset_affinity;
}
buf = alloc_buffer(span, 1); if (!buf) {
ret = -1; goto pe_close;
}
while (current_mask) {
snprintf(schemata, sizeof(schemata), "%lx", param->mask & ~current_mask);
ret = write_schemata("", schemata, uparams->cpu, test->resource); if (ret) goto free_buf;
snprintf(schemata, sizeof(schemata), "%lx", current_mask);
ret = write_schemata(param->ctrlgrp, schemata, uparams->cpu, test->resource); if (ret) goto free_buf;
for (i = 0; i < NUM_OF_RUNS; i++) {
mem_flush(buf, span);
fill_cache_read(buf, span, true);
ret = perf_event_reset_enable(pe_fd); if (ret) goto free_buf;
fill_cache_read(buf, span, true);
ret = perf_event_measure(pe_fd, &pe_read, param->filename, bm_pid); if (ret) goto free_buf;
}
current_mask = next_mask(current_mask);
}
staticint cat_run_test(conststruct resctrl_test *test, conststruct user_params *uparams)
{ unsignedlong long_mask, start_mask, full_cache_mask; unsignedlong cache_total_size = 0; int n = uparams->bits; unsignedint start; int count_of_bits;
size_t span; int ret;
ret = get_full_cbm(test->resource, &full_cache_mask); if (ret) return ret; /* Get the largest contiguous exclusive portion of the cache */
ret = get_mask_no_shareable(test->resource, &long_mask); if (ret) return ret;
/* Get L3/L2 cache size */
ret = get_cache_size(uparams->cpu, test->resource, &cache_total_size); if (ret) return ret;
ksft_print_msg("Cache size :%lu\n", cache_total_size);
if (n > count_of_bits - 1) {
ksft_print_msg("Invalid input value for no_of_bits n!\n");
ksft_print_msg("Please enter value in range 1 to %d\n",
count_of_bits - 1); return -1;
}
start_mask = create_bit_mask(start, n);
/* Check to compare sparse_masks content to CPUID output. */
ret = resource_info_unsigned_get(test->resource, "sparse_masks", &sparse_masks); if (ret) return ret;
if (arch_supports_noncont_cat(test) != sparse_masks) {
ksft_print_msg("Hardware and kernel differ on non-contiguous CBM support!\n"); return 1;
}
/* Write checks initialization. */
ret = get_full_cbm(test->resource, &full_cache_mask); if (ret < 0) return ret;
bit_center = count_bits(full_cache_mask) / 2;
/* * The bit_center needs to be at least 3 to properly calculate the CBM * hole in the noncont_mask. If it's smaller return an error since the * cache mask is too short and that shouldn't happen.
*/ if (bit_center < 3) return -EINVAL;
cont_mask = full_cache_mask >> bit_center;
/* Contiguous mask write check. */
snprintf(schemata, sizeof(schemata), "%lx", cont_mask);
ret = write_schemata("", schemata, uparams->cpu, test->resource); if (ret) {
ksft_print_msg("Write of contiguous CBM failed\n"); return 1;
}
/* * Non-contiguous mask write check. CBM has a 0xf hole approximately in the middle. * Output is compared with support information to catch any edge case errors.
*/
noncont_mask = ~(0xfUL << (bit_center - 2)) & full_cache_mask;
snprintf(schemata, sizeof(schemata), "%lx", noncont_mask);
ret = write_schemata("", schemata, uparams->cpu, test->resource); if (ret && sparse_masks)
ksft_print_msg("Non-contiguous CBMs supported but write of non-contiguous CBM failed\n"); elseif (ret && !sparse_masks)
ksft_print_msg("Non-contiguous CBMs not supported and write of non-contiguous CBM failed as expected\n"); elseif (!ret && !sparse_masks)
ksft_print_msg("Non-contiguous CBMs not supported but write of non-contiguous CBM succeeded\n");
return !ret == !sparse_masks;
}
staticbool noncont_cat_feature_check(conststruct resctrl_test *test)
{ if (!resctrl_resource_exists(test->resource)) returnfalse;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.