1790bf585SFenghua Yu // SPDX-License-Identifier: GPL-2.0 2790bf585SFenghua Yu /* 3790bf585SFenghua Yu * Cache Allocation Technology (CAT) test 4790bf585SFenghua Yu * 5790bf585SFenghua Yu * Copyright (C) 2018 Intel Corporation 6790bf585SFenghua Yu * 7790bf585SFenghua Yu * Authors: 8790bf585SFenghua Yu * Sai Praneeth Prakhya <[email protected]>, 9790bf585SFenghua Yu * Fenghua Yu <[email protected]> 10790bf585SFenghua Yu */ 11790bf585SFenghua Yu #include "resctrl.h" 12790bf585SFenghua Yu #include <unistd.h> 13790bf585SFenghua Yu 14205de6ddSIlpo Järvinen #define RESULT_FILE_NAME "result_cat" 15790bf585SFenghua Yu #define NUM_OF_RUNS 5 16790bf585SFenghua Yu 17790bf585SFenghua Yu /* 18205de6ddSIlpo Järvinen * Minimum difference in LLC misses between a test with n+1 bits CBM to the 19205de6ddSIlpo Järvinen * test with n bits is MIN_DIFF_PERCENT_PER_BIT * (n - 1). With e.g. 5 vs 4 20205de6ddSIlpo Järvinen * bits in the CBM mask, the minimum difference must be at least 21205de6ddSIlpo Järvinen * MIN_DIFF_PERCENT_PER_BIT * (4 - 1) = 3 percent. 22205de6ddSIlpo Järvinen * 23205de6ddSIlpo Järvinen * The relationship between number of used CBM bits and difference in LLC 24205de6ddSIlpo Järvinen * misses is not expected to be linear. With a small number of bits, the 25205de6ddSIlpo Järvinen * margin is smaller than with larger number of bits. For selftest purposes, 26205de6ddSIlpo Järvinen * however, linear approach is enough because ultimately only pass/fail 27205de6ddSIlpo Järvinen * decision has to be made and distinction between strong and stronger 28205de6ddSIlpo Järvinen * signal is irrelevant. 29790bf585SFenghua Yu */ 30205de6ddSIlpo Järvinen #define MIN_DIFF_PERCENT_PER_BIT 1UL 31790bf585SFenghua Yu 3233403bc7SIlpo Järvinen static int show_results_info(__u64 sum_llc_val, int no_of_bits, 33205de6ddSIlpo Järvinen unsigned long cache_span, 34205de6ddSIlpo Järvinen unsigned long min_diff_percent, 35205de6ddSIlpo Järvinen unsigned long num_of_runs, bool platform, 36205de6ddSIlpo Järvinen __s64 *prev_avg_llc_val) 375caf1b64SIlpo Järvinen { 3833403bc7SIlpo Järvinen __u64 avg_llc_val = 0; 39205de6ddSIlpo Järvinen float avg_diff; 40205de6ddSIlpo Järvinen int ret = 0; 415caf1b64SIlpo Järvinen 425caf1b64SIlpo Järvinen avg_llc_val = sum_llc_val / num_of_runs; 43205de6ddSIlpo Järvinen if (*prev_avg_llc_val) { 44205de6ddSIlpo Järvinen float delta = (__s64)(avg_llc_val - *prev_avg_llc_val); 455caf1b64SIlpo Järvinen 46205de6ddSIlpo Järvinen avg_diff = delta / *prev_avg_llc_val; 47205de6ddSIlpo Järvinen ret = platform && (avg_diff * 100) < (float)min_diff_percent; 485caf1b64SIlpo Järvinen 49205de6ddSIlpo Järvinen ksft_print_msg("%s Check cache miss rate changed more than %.1f%%\n", 50205de6ddSIlpo Järvinen ret ? "Fail:" : "Pass:", (float)min_diff_percent); 515caf1b64SIlpo Järvinen 52205de6ddSIlpo Järvinen ksft_print_msg("Percent diff=%.1f\n", avg_diff * 100); 53205de6ddSIlpo Järvinen } 54205de6ddSIlpo Järvinen *prev_avg_llc_val = avg_llc_val; 555caf1b64SIlpo Järvinen 565caf1b64SIlpo Järvinen show_cache_info(no_of_bits, avg_llc_val, cache_span, true); 575caf1b64SIlpo Järvinen 585caf1b64SIlpo Järvinen return ret; 595caf1b64SIlpo Järvinen } 605caf1b64SIlpo Järvinen 61205de6ddSIlpo Järvinen /* Remove the highest bit from CBM */ 62205de6ddSIlpo Järvinen static unsigned long next_mask(unsigned long current_mask) 63205de6ddSIlpo Järvinen { 64205de6ddSIlpo Järvinen return current_mask & (current_mask >> 1); 65205de6ddSIlpo Järvinen } 66205de6ddSIlpo Järvinen 67205de6ddSIlpo Järvinen static int check_results(struct resctrl_val_param *param, const char *cache_type, 68205de6ddSIlpo Järvinen unsigned long cache_total_size, unsigned long full_cache_mask, 69205de6ddSIlpo Järvinen unsigned long current_mask) 70790bf585SFenghua Yu { 71790bf585SFenghua Yu char *token_array[8], temp[512]; 7233403bc7SIlpo Järvinen __u64 sum_llc_perf_miss = 0; 73205de6ddSIlpo Järvinen __s64 prev_avg_llc_val = 0; 74205de6ddSIlpo Järvinen unsigned long alloc_size; 75205de6ddSIlpo Järvinen int runs = 0; 76205de6ddSIlpo Järvinen int fail = 0; 77205de6ddSIlpo Järvinen int ret; 78790bf585SFenghua Yu FILE *fp; 79790bf585SFenghua Yu 80ca2f4214SFenghua Yu ksft_print_msg("Checking for pass/fail\n"); 81790bf585SFenghua Yu fp = fopen(param->filename, "r"); 82790bf585SFenghua Yu if (!fp) { 83cc8ff7f5SIlpo Järvinen ksft_perror("Cannot open file"); 84790bf585SFenghua Yu 85c90fba60SIlpo Järvinen return -1; 86790bf585SFenghua Yu } 87790bf585SFenghua Yu 88790bf585SFenghua Yu while (fgets(temp, sizeof(temp), fp)) { 89790bf585SFenghua Yu char *token = strtok(temp, ":\t"); 90790bf585SFenghua Yu int fields = 0; 91205de6ddSIlpo Järvinen int bits; 92790bf585SFenghua Yu 93790bf585SFenghua Yu while (token) { 94790bf585SFenghua Yu token_array[fields++] = token; 95790bf585SFenghua Yu token = strtok(NULL, ":\t"); 96790bf585SFenghua Yu } 97205de6ddSIlpo Järvinen 9833403bc7SIlpo Järvinen sum_llc_perf_miss += strtoull(token_array[3], NULL, 0); 99790bf585SFenghua Yu runs++; 100205de6ddSIlpo Järvinen 101205de6ddSIlpo Järvinen if (runs < NUM_OF_RUNS) 102205de6ddSIlpo Järvinen continue; 103205de6ddSIlpo Järvinen 104205de6ddSIlpo Järvinen if (!current_mask) { 105205de6ddSIlpo Järvinen ksft_print_msg("Unexpected empty cache mask\n"); 106205de6ddSIlpo Järvinen break; 107205de6ddSIlpo Järvinen } 108205de6ddSIlpo Järvinen 109205de6ddSIlpo Järvinen alloc_size = cache_portion_size(cache_total_size, current_mask, full_cache_mask); 110205de6ddSIlpo Järvinen 111205de6ddSIlpo Järvinen bits = count_bits(current_mask); 112205de6ddSIlpo Järvinen 113205de6ddSIlpo Järvinen ret = show_results_info(sum_llc_perf_miss, bits, 114205de6ddSIlpo Järvinen alloc_size / 64, 115205de6ddSIlpo Järvinen MIN_DIFF_PERCENT_PER_BIT * (bits - 1), 116205de6ddSIlpo Järvinen runs, get_vendor() == ARCH_INTEL, 117205de6ddSIlpo Järvinen &prev_avg_llc_val); 118205de6ddSIlpo Järvinen if (ret) 119205de6ddSIlpo Järvinen fail = 1; 120205de6ddSIlpo Järvinen 121205de6ddSIlpo Järvinen runs = 0; 122205de6ddSIlpo Järvinen sum_llc_perf_miss = 0; 123205de6ddSIlpo Järvinen current_mask = next_mask(current_mask); 124790bf585SFenghua Yu } 125790bf585SFenghua Yu 126790bf585SFenghua Yu fclose(fp); 127790bf585SFenghua Yu 128205de6ddSIlpo Järvinen return fail; 129790bf585SFenghua Yu } 130790bf585SFenghua Yu 131*6cd36898SMaciej Wieczor-Retman static void cat_test_cleanup(void) 132790bf585SFenghua Yu { 133205de6ddSIlpo Järvinen remove(RESULT_FILE_NAME); 134790bf585SFenghua Yu } 135790bf585SFenghua Yu 136433f437bSIlpo Järvinen /* 137433f437bSIlpo Järvinen * cat_test - Execute CAT benchmark and measure cache misses 138ca160887SIlpo Järvinen * @test: Test information structure 13915f29882SIlpo Järvinen * @uparams: User supplied parameters 140433f437bSIlpo Järvinen * @param: Parameters passed to cat_test() 141433f437bSIlpo Järvinen * @span: Buffer size for the benchmark 142205de6ddSIlpo Järvinen * @current_mask Start mask for the first iteration 143205de6ddSIlpo Järvinen * 144205de6ddSIlpo Järvinen * Run CAT selftest by varying the allocated cache portion and comparing the 145205de6ddSIlpo Järvinen * impact on cache misses (the result analysis is done in check_results() 146205de6ddSIlpo Järvinen * and show_results_info(), not in this function). 147205de6ddSIlpo Järvinen * 148205de6ddSIlpo Järvinen * One bit is removed from the CAT allocation bit mask (in current_mask) for 149205de6ddSIlpo Järvinen * each subsequent test which keeps reducing the size of the allocated cache 150205de6ddSIlpo Järvinen * portion. A single test flushes the buffer, reads it to warm up the cache, 151205de6ddSIlpo Järvinen * and reads the buffer again. The cache misses are measured during the last 152205de6ddSIlpo Järvinen * read pass. 153433f437bSIlpo Järvinen * 154433f437bSIlpo Järvinen * Return: 0 when the test was run, < 0 on error. 155433f437bSIlpo Järvinen */ 156ca160887SIlpo Järvinen static int cat_test(const struct resctrl_test *test, 157ca160887SIlpo Järvinen const struct user_params *uparams, 158ca160887SIlpo Järvinen struct resctrl_val_param *param, 15915f29882SIlpo Järvinen size_t span, unsigned long current_mask) 160433f437bSIlpo Järvinen { 161433f437bSIlpo Järvinen char *resctrl_val = param->resctrl_val; 162433f437bSIlpo Järvinen struct perf_event_read pe_read; 163433f437bSIlpo Järvinen struct perf_event_attr pea; 1646c8cb747SIlpo Järvinen cpu_set_t old_affinity; 165205de6ddSIlpo Järvinen unsigned char *buf; 166205de6ddSIlpo Järvinen char schemata[64]; 167205de6ddSIlpo Järvinen int ret, i, pe_fd; 168433f437bSIlpo Järvinen pid_t bm_pid; 169433f437bSIlpo Järvinen 170433f437bSIlpo Järvinen if (strcmp(param->filename, "") == 0) 171433f437bSIlpo Järvinen sprintf(param->filename, "stdio"); 172433f437bSIlpo Järvinen 173433f437bSIlpo Järvinen bm_pid = getpid(); 174433f437bSIlpo Järvinen 175433f437bSIlpo Järvinen /* Taskset benchmark to specified cpu */ 17615f29882SIlpo Järvinen ret = taskset_benchmark(bm_pid, uparams->cpu, &old_affinity); 177433f437bSIlpo Järvinen if (ret) 178433f437bSIlpo Järvinen return ret; 179433f437bSIlpo Järvinen 180433f437bSIlpo Järvinen /* Write benchmark to specified con_mon grp, mon_grp in resctrl FS*/ 181433f437bSIlpo Järvinen ret = write_bm_pid_to_resctrl(bm_pid, param->ctrlgrp, param->mongrp, 182433f437bSIlpo Järvinen resctrl_val); 183433f437bSIlpo Järvinen if (ret) 1846c8cb747SIlpo Järvinen goto reset_affinity; 185433f437bSIlpo Järvinen 186433f437bSIlpo Järvinen perf_event_attr_initialize(&pea, PERF_COUNT_HW_CACHE_MISSES); 187433f437bSIlpo Järvinen perf_event_initialize_read_format(&pe_read); 18815f29882SIlpo Järvinen pe_fd = perf_open(&pea, bm_pid, uparams->cpu); 1896c8cb747SIlpo Järvinen if (pe_fd < 0) { 1906c8cb747SIlpo Järvinen ret = -1; 1916c8cb747SIlpo Järvinen goto reset_affinity; 1926c8cb747SIlpo Järvinen } 193433f437bSIlpo Järvinen 194205de6ddSIlpo Järvinen buf = alloc_buffer(span, 1); 195205de6ddSIlpo Järvinen if (!buf) { 196433f437bSIlpo Järvinen ret = -1; 197433f437bSIlpo Järvinen goto pe_close; 198433f437bSIlpo Järvinen } 199433f437bSIlpo Järvinen 200205de6ddSIlpo Järvinen while (current_mask) { 201205de6ddSIlpo Järvinen snprintf(schemata, sizeof(schemata), "%lx", param->mask & ~current_mask); 202ca160887SIlpo Järvinen ret = write_schemata("", schemata, uparams->cpu, test->resource); 203205de6ddSIlpo Järvinen if (ret) 204205de6ddSIlpo Järvinen goto free_buf; 205205de6ddSIlpo Järvinen snprintf(schemata, sizeof(schemata), "%lx", current_mask); 206ca160887SIlpo Järvinen ret = write_schemata(param->ctrlgrp, schemata, uparams->cpu, test->resource); 207205de6ddSIlpo Järvinen if (ret) 208205de6ddSIlpo Järvinen goto free_buf; 209205de6ddSIlpo Järvinen 210205de6ddSIlpo Järvinen for (i = 0; i < NUM_OF_RUNS; i++) { 211205de6ddSIlpo Järvinen mem_flush(buf, span); 212205de6ddSIlpo Järvinen fill_cache_read(buf, span, true); 213205de6ddSIlpo Järvinen 214205de6ddSIlpo Järvinen ret = perf_event_reset_enable(pe_fd); 215205de6ddSIlpo Järvinen if (ret) 216205de6ddSIlpo Järvinen goto free_buf; 217205de6ddSIlpo Järvinen 218205de6ddSIlpo Järvinen fill_cache_read(buf, span, true); 219205de6ddSIlpo Järvinen 220433f437bSIlpo Järvinen ret = perf_event_measure(pe_fd, &pe_read, param->filename, bm_pid); 221433f437bSIlpo Järvinen if (ret) 222205de6ddSIlpo Järvinen goto free_buf; 223205de6ddSIlpo Järvinen } 224205de6ddSIlpo Järvinen current_mask = next_mask(current_mask); 225433f437bSIlpo Järvinen } 226433f437bSIlpo Järvinen 227205de6ddSIlpo Järvinen free_buf: 228205de6ddSIlpo Järvinen free(buf); 229433f437bSIlpo Järvinen pe_close: 230433f437bSIlpo Järvinen close(pe_fd); 2316c8cb747SIlpo Järvinen reset_affinity: 2326c8cb747SIlpo Järvinen taskset_restore(bm_pid, &old_affinity); 233205de6ddSIlpo Järvinen 234433f437bSIlpo Järvinen return ret; 235433f437bSIlpo Järvinen } 236433f437bSIlpo Järvinen 237c603ff5bSIlpo Järvinen static int cat_run_test(const struct resctrl_test *test, const struct user_params *uparams) 238790bf585SFenghua Yu { 239205de6ddSIlpo Järvinen unsigned long long_mask, start_mask, full_cache_mask; 24019e94a23SIlpo Järvinen unsigned long cache_total_size = 0; 24115f29882SIlpo Järvinen int n = uparams->bits; 242205de6ddSIlpo Järvinen unsigned int start; 24385b73447SIlpo Järvinen int count_of_bits; 244b1a901e0SIlpo Järvinen size_t span; 245205de6ddSIlpo Järvinen int ret; 246790bf585SFenghua Yu 247c603ff5bSIlpo Järvinen ret = get_full_cbm(test->resource, &full_cache_mask); 248b6dfac94SIlpo Järvinen if (ret) 249b6dfac94SIlpo Järvinen return ret; 250b6dfac94SIlpo Järvinen /* Get the largest contiguous exclusive portion of the cache */ 251c603ff5bSIlpo Järvinen ret = get_mask_no_shareable(test->resource, &long_mask); 252790bf585SFenghua Yu if (ret) 253790bf585SFenghua Yu return ret; 254790bf585SFenghua Yu 255790bf585SFenghua Yu /* Get L3/L2 cache size */ 256c603ff5bSIlpo Järvinen ret = get_cache_size(uparams->cpu, test->resource, &cache_total_size); 257790bf585SFenghua Yu if (ret) 258790bf585SFenghua Yu return ret; 25919e94a23SIlpo Järvinen ksft_print_msg("Cache size :%lu\n", cache_total_size); 260790bf585SFenghua Yu 261205de6ddSIlpo Järvinen count_of_bits = count_contiguous_bits(long_mask, &start); 262790bf585SFenghua Yu 26309a67934SFenghua Yu if (!n) 26409a67934SFenghua Yu n = count_of_bits / 2; 26509a67934SFenghua Yu 26609a67934SFenghua Yu if (n > count_of_bits - 1) { 267ca2f4214SFenghua Yu ksft_print_msg("Invalid input value for no_of_bits n!\n"); 268ca2f4214SFenghua Yu ksft_print_msg("Please enter value in range 1 to %d\n", 269790bf585SFenghua Yu count_of_bits - 1); 270790bf585SFenghua Yu return -1; 271790bf585SFenghua Yu } 272205de6ddSIlpo Järvinen start_mask = create_bit_mask(start, n); 273790bf585SFenghua Yu 274790bf585SFenghua Yu struct resctrl_val_param param = { 27524286736SFenghua Yu .resctrl_val = CAT_STR, 276205de6ddSIlpo Järvinen .ctrlgrp = "c1", 277205de6ddSIlpo Järvinen .filename = RESULT_FILE_NAME, 278205de6ddSIlpo Järvinen .num_of_runs = 0, 279790bf585SFenghua Yu }; 280205de6ddSIlpo Järvinen param.mask = long_mask; 281205de6ddSIlpo Järvinen span = cache_portion_size(cache_total_size, start_mask, full_cache_mask); 282790bf585SFenghua Yu 283790bf585SFenghua Yu remove(param.filename); 284790bf585SFenghua Yu 285ca160887SIlpo Järvinen ret = cat_test(test, uparams, ¶m, span, start_mask); 286205de6ddSIlpo Järvinen if (ret) 287*6cd36898SMaciej Wieczor-Retman return ret; 288790bf585SFenghua Yu 289c603ff5bSIlpo Järvinen ret = check_results(¶m, test->resource, 290c603ff5bSIlpo Järvinen cache_total_size, full_cache_mask, start_mask); 29139e34ddcSShaopeng Tan return ret; 292790bf585SFenghua Yu } 293c603ff5bSIlpo Järvinen 294ae638551SMaciej Wieczor-Retman static int noncont_cat_run_test(const struct resctrl_test *test, 295ae638551SMaciej Wieczor-Retman const struct user_params *uparams) 296ae638551SMaciej Wieczor-Retman { 297ae638551SMaciej Wieczor-Retman unsigned long full_cache_mask, cont_mask, noncont_mask; 298ae638551SMaciej Wieczor-Retman unsigned int eax, ebx, ecx, edx, sparse_masks; 299ae638551SMaciej Wieczor-Retman int bit_center, ret; 300ae638551SMaciej Wieczor-Retman char schemata[64]; 301ae638551SMaciej Wieczor-Retman 302ae638551SMaciej Wieczor-Retman /* Check to compare sparse_masks content to CPUID output. */ 303ae638551SMaciej Wieczor-Retman ret = resource_info_unsigned_get(test->resource, "sparse_masks", &sparse_masks); 304ae638551SMaciej Wieczor-Retman if (ret) 305ae638551SMaciej Wieczor-Retman return ret; 306ae638551SMaciej Wieczor-Retman 307ae638551SMaciej Wieczor-Retman if (!strcmp(test->resource, "L3")) 308ae638551SMaciej Wieczor-Retman __cpuid_count(0x10, 1, eax, ebx, ecx, edx); 309ae638551SMaciej Wieczor-Retman else if (!strcmp(test->resource, "L2")) 310ae638551SMaciej Wieczor-Retman __cpuid_count(0x10, 2, eax, ebx, ecx, edx); 311ae638551SMaciej Wieczor-Retman else 312ae638551SMaciej Wieczor-Retman return -EINVAL; 313ae638551SMaciej Wieczor-Retman 314ae638551SMaciej Wieczor-Retman if (sparse_masks != ((ecx >> 3) & 1)) { 315ae638551SMaciej Wieczor-Retman ksft_print_msg("CPUID output doesn't match 'sparse_masks' file content!\n"); 316ae638551SMaciej Wieczor-Retman return 1; 317ae638551SMaciej Wieczor-Retman } 318ae638551SMaciej Wieczor-Retman 319ae638551SMaciej Wieczor-Retman /* Write checks initialization. */ 320ae638551SMaciej Wieczor-Retman ret = get_full_cbm(test->resource, &full_cache_mask); 321ae638551SMaciej Wieczor-Retman if (ret < 0) 322ae638551SMaciej Wieczor-Retman return ret; 323ae638551SMaciej Wieczor-Retman bit_center = count_bits(full_cache_mask) / 2; 324ae638551SMaciej Wieczor-Retman 325ae638551SMaciej Wieczor-Retman /* 326ae638551SMaciej Wieczor-Retman * The bit_center needs to be at least 3 to properly calculate the CBM 327ae638551SMaciej Wieczor-Retman * hole in the noncont_mask. If it's smaller return an error since the 328ae638551SMaciej Wieczor-Retman * cache mask is too short and that shouldn't happen. 329ae638551SMaciej Wieczor-Retman */ 330ae638551SMaciej Wieczor-Retman if (bit_center < 3) 331ae638551SMaciej Wieczor-Retman return -EINVAL; 332ae638551SMaciej Wieczor-Retman cont_mask = full_cache_mask >> bit_center; 333ae638551SMaciej Wieczor-Retman 334ae638551SMaciej Wieczor-Retman /* Contiguous mask write check. */ 335ae638551SMaciej Wieczor-Retman snprintf(schemata, sizeof(schemata), "%lx", cont_mask); 336ae638551SMaciej Wieczor-Retman ret = write_schemata("", schemata, uparams->cpu, test->resource); 337ae638551SMaciej Wieczor-Retman if (ret) { 338ae638551SMaciej Wieczor-Retman ksft_print_msg("Write of contiguous CBM failed\n"); 339ae638551SMaciej Wieczor-Retman return 1; 340ae638551SMaciej Wieczor-Retman } 341ae638551SMaciej Wieczor-Retman 342ae638551SMaciej Wieczor-Retman /* 343ae638551SMaciej Wieczor-Retman * Non-contiguous mask write check. CBM has a 0xf hole approximately in the middle. 344ae638551SMaciej Wieczor-Retman * Output is compared with support information to catch any edge case errors. 345ae638551SMaciej Wieczor-Retman */ 346ae638551SMaciej Wieczor-Retman noncont_mask = ~(0xfUL << (bit_center - 2)) & full_cache_mask; 347ae638551SMaciej Wieczor-Retman snprintf(schemata, sizeof(schemata), "%lx", noncont_mask); 348ae638551SMaciej Wieczor-Retman ret = write_schemata("", schemata, uparams->cpu, test->resource); 349ae638551SMaciej Wieczor-Retman if (ret && sparse_masks) 350ae638551SMaciej Wieczor-Retman ksft_print_msg("Non-contiguous CBMs supported but write of non-contiguous CBM failed\n"); 351ae638551SMaciej Wieczor-Retman else if (ret && !sparse_masks) 352ae638551SMaciej Wieczor-Retman ksft_print_msg("Non-contiguous CBMs not supported and write of non-contiguous CBM failed as expected\n"); 353ae638551SMaciej Wieczor-Retman else if (!ret && !sparse_masks) 354ae638551SMaciej Wieczor-Retman ksft_print_msg("Non-contiguous CBMs not supported but write of non-contiguous CBM succeeded\n"); 355ae638551SMaciej Wieczor-Retman 356ae638551SMaciej Wieczor-Retman return !ret == !sparse_masks; 357ae638551SMaciej Wieczor-Retman } 358ae638551SMaciej Wieczor-Retman 359ae638551SMaciej Wieczor-Retman static bool noncont_cat_feature_check(const struct resctrl_test *test) 360ae638551SMaciej Wieczor-Retman { 361ae638551SMaciej Wieczor-Retman if (!resctrl_resource_exists(test->resource)) 362ae638551SMaciej Wieczor-Retman return false; 363ae638551SMaciej Wieczor-Retman 364ae638551SMaciej Wieczor-Retman return resource_info_file_exists(test->resource, "sparse_masks"); 365ae638551SMaciej Wieczor-Retman } 366ae638551SMaciej Wieczor-Retman 367c603ff5bSIlpo Järvinen struct resctrl_test l3_cat_test = { 3685339792bSIlpo Järvinen .name = "L3_CAT", 3695339792bSIlpo Järvinen .group = "CAT", 370c603ff5bSIlpo Järvinen .resource = "L3", 371c603ff5bSIlpo Järvinen .feature_check = test_resource_feature_check, 372c603ff5bSIlpo Järvinen .run_test = cat_run_test, 3738780bc88SMaciej Wieczor-Retman .cleanup = cat_test_cleanup, 374c603ff5bSIlpo Järvinen }; 375ae638551SMaciej Wieczor-Retman 376ae638551SMaciej Wieczor-Retman struct resctrl_test l3_noncont_cat_test = { 377ae638551SMaciej Wieczor-Retman .name = "L3_NONCONT_CAT", 378ae638551SMaciej Wieczor-Retman .group = "CAT", 379ae638551SMaciej Wieczor-Retman .resource = "L3", 380ae638551SMaciej Wieczor-Retman .feature_check = noncont_cat_feature_check, 381ae638551SMaciej Wieczor-Retman .run_test = noncont_cat_run_test, 382ae638551SMaciej Wieczor-Retman }; 383ae638551SMaciej Wieczor-Retman 384ae638551SMaciej Wieczor-Retman struct resctrl_test l2_noncont_cat_test = { 385ae638551SMaciej Wieczor-Retman .name = "L2_NONCONT_CAT", 386ae638551SMaciej Wieczor-Retman .group = "CAT", 387ae638551SMaciej Wieczor-Retman .resource = "L2", 388ae638551SMaciej Wieczor-Retman .feature_check = noncont_cat_feature_check, 389ae638551SMaciej Wieczor-Retman .run_test = noncont_cat_run_test, 390ae638551SMaciej Wieczor-Retman }; 391