1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Cache Monitoring Technology (CMT) test
4 *
5 * Copyright (C) 2018 Intel Corporation
6 *
7 * Authors:
8 * Sai Praneeth Prakhya <sai.praneeth.prakhya@intel.com>,
9 * Fenghua Yu <fenghua.yu@intel.com>
10 */
11 #include "resctrl.h"
12 #include <unistd.h>
13
14 #define RESULT_FILE_NAME "result_cmt"
15 #define NUM_OF_RUNS 5
16 #define MAX_DIFF 2000000
17 #define MAX_DIFF_PERCENT 15
18
cmt_setup(struct resctrl_val_param * p)19 static int cmt_setup(struct resctrl_val_param *p)
20 {
21 /* Run NUM_OF_RUNS times */
22 if (p->num_of_runs >= NUM_OF_RUNS)
23 return END_OF_TESTS;
24
25 p->num_of_runs++;
26
27 return 0;
28 }
29
check_results(struct resctrl_val_param * param,int no_of_bits)30 static int check_results(struct resctrl_val_param *param, int no_of_bits)
31 {
32 char *token_array[8], temp[512];
33 unsigned long sum_llc_occu_resc = 0;
34 int runs = 0;
35 FILE *fp;
36
37 ksft_print_msg("Checking for pass/fail\n");
38 fp = fopen(param->filename, "r");
39 if (!fp) {
40 perror("# Error in opening file\n");
41
42 return errno;
43 }
44
45 while (fgets(temp, sizeof(temp), fp)) {
46 char *token = strtok(temp, ":\t");
47 int fields = 0;
48
49 while (token) {
50 token_array[fields++] = token;
51 token = strtok(NULL, ":\t");
52 }
53
54 /* Field 3 is llc occ resc value */
55 if (runs > 0)
56 sum_llc_occu_resc += strtoul(token_array[3], NULL, 0);
57 runs++;
58 }
59 fclose(fp);
60
61 return show_cache_info(sum_llc_occu_resc, no_of_bits, param->span,
62 MAX_DIFF, MAX_DIFF_PERCENT, runs - 1,
63 true, true);
64 }
65
cmt_test_cleanup(void)66 void cmt_test_cleanup(void)
67 {
68 remove(RESULT_FILE_NAME);
69 }
70
cmt_resctrl_val(int cpu_no,int n,char ** benchmark_cmd)71 int cmt_resctrl_val(int cpu_no, int n, char **benchmark_cmd)
72 {
73 unsigned long cache_size = 0;
74 unsigned long long_mask;
75 char cbm_mask[256];
76 int count_of_bits;
77 int ret;
78
79 if (!validate_resctrl_feature_request(CMT_STR))
80 return -1;
81
82 ret = get_cbm_mask("L3", cbm_mask);
83 if (ret)
84 return ret;
85
86 long_mask = strtoul(cbm_mask, NULL, 16);
87
88 ret = get_cache_size(cpu_no, "L3", &cache_size);
89 if (ret)
90 return ret;
91 ksft_print_msg("Cache size :%lu\n", cache_size);
92
93 count_of_bits = count_bits(long_mask);
94
95 if (n < 1 || n > count_of_bits) {
96 ksft_print_msg("Invalid input value for numbr_of_bits n!\n");
97 ksft_print_msg("Please enter value in range 1 to %d\n", count_of_bits);
98 return -1;
99 }
100
101 struct resctrl_val_param param = {
102 .resctrl_val = CMT_STR,
103 .ctrlgrp = "c1",
104 .mongrp = "m1",
105 .cpu_no = cpu_no,
106 .filename = RESULT_FILE_NAME,
107 .mask = ~(long_mask << n) & long_mask,
108 .span = cache_size * n / count_of_bits,
109 .num_of_runs = 0,
110 .setup = cmt_setup,
111 };
112
113 if (strcmp(benchmark_cmd[0], "fill_buf") == 0)
114 sprintf(benchmark_cmd[1], "%zu", param.span);
115
116 remove(RESULT_FILE_NAME);
117
118 ret = resctrl_val(benchmark_cmd, ¶m);
119 if (ret)
120 goto out;
121
122 ret = check_results(¶m, n);
123
124 out:
125 cmt_test_cleanup();
126
127 return ret;
128 }
129