cc93cb5ae7ee9ae8c09d2c325c6106cea887707c
[platform/kernel/linux-rpi.git] / tools / testing / selftests / resctrl / cmt_test.c
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
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
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
66 void cmt_test_cleanup(void)
67 {
68         remove(RESULT_FILE_NAME);
69 }
70
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         ret = get_cbm_mask("L3", cbm_mask);
80         if (ret)
81                 return ret;
82
83         long_mask = strtoul(cbm_mask, NULL, 16);
84
85         ret = get_cache_size(cpu_no, "L3", &cache_size);
86         if (ret)
87                 return ret;
88         ksft_print_msg("Cache size :%lu\n", cache_size);
89
90         count_of_bits = count_bits(long_mask);
91
92         if (n < 1 || n > count_of_bits) {
93                 ksft_print_msg("Invalid input value for numbr_of_bits n!\n");
94                 ksft_print_msg("Please enter value in range 1 to %d\n", count_of_bits);
95                 return -1;
96         }
97
98         struct resctrl_val_param param = {
99                 .resctrl_val    = CMT_STR,
100                 .ctrlgrp        = "c1",
101                 .mongrp         = "m1",
102                 .cpu_no         = cpu_no,
103                 .filename       = RESULT_FILE_NAME,
104                 .mask           = ~(long_mask << n) & long_mask,
105                 .span           = cache_size * n / count_of_bits,
106                 .num_of_runs    = 0,
107                 .setup          = cmt_setup,
108         };
109
110         if (strcmp(benchmark_cmd[0], "fill_buf") == 0)
111                 sprintf(benchmark_cmd[1], "%zu", param.span);
112
113         remove(RESULT_FILE_NAME);
114
115         ret = resctrl_val(benchmark_cmd, &param);
116         if (ret)
117                 goto out;
118
119         ret = check_results(&param, n);
120
121 out:
122         cmt_test_cleanup();
123
124         return ret;
125 }