linux/tools/testing/selftests/resctrl/cqm_test.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Cache Monitoring Technology (CQM) 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_cqm"
  15#define NUM_OF_RUNS             5
  16#define MAX_DIFF                2000000
  17#define MAX_DIFF_PERCENT        15
  18
  19int count_of_bits;
  20char cbm_mask[256];
  21unsigned long long_mask;
  22unsigned long cache_size;
  23
  24static int cqm_setup(int num, ...)
  25{
  26        struct resctrl_val_param *p;
  27        va_list param;
  28
  29        va_start(param, num);
  30        p = va_arg(param, struct resctrl_val_param *);
  31        va_end(param);
  32
  33        /* Run NUM_OF_RUNS times */
  34        if (p->num_of_runs >= NUM_OF_RUNS)
  35                return -1;
  36
  37        p->num_of_runs++;
  38
  39        return 0;
  40}
  41
  42static void show_cache_info(unsigned long sum_llc_occu_resc, int no_of_bits,
  43                            unsigned long span)
  44{
  45        unsigned long avg_llc_occu_resc = 0;
  46        float diff_percent;
  47        long avg_diff = 0;
  48        bool res;
  49
  50        avg_llc_occu_resc = sum_llc_occu_resc / (NUM_OF_RUNS - 1);
  51        avg_diff = (long)abs(span - avg_llc_occu_resc);
  52
  53        diff_percent = (((float)span - avg_llc_occu_resc) / span) * 100;
  54
  55        if ((abs((int)diff_percent) <= MAX_DIFF_PERCENT) ||
  56            (abs(avg_diff) <= MAX_DIFF))
  57                res = true;
  58        else
  59                res = false;
  60
  61        printf("%sok CQM: diff within %d, %d\%%\n", res ? "" : "not",
  62               MAX_DIFF, (int)MAX_DIFF_PERCENT);
  63
  64        printf("# diff: %ld\n", avg_diff);
  65        printf("# percent diff=%d\n", abs((int)diff_percent));
  66        printf("# Results are displayed in (Bytes)\n");
  67        printf("# Number of bits: %d\n", no_of_bits);
  68        printf("# Avg_llc_occu_resc: %lu\n", avg_llc_occu_resc);
  69        printf("# llc_occu_exp (span): %lu\n", span);
  70
  71        tests_run++;
  72}
  73
  74static int check_results(struct resctrl_val_param *param, int no_of_bits)
  75{
  76        char *token_array[8], temp[512];
  77        unsigned long sum_llc_occu_resc = 0;
  78        int runs = 0;
  79        FILE *fp;
  80
  81        printf("# checking for pass/fail\n");
  82        fp = fopen(param->filename, "r");
  83        if (!fp) {
  84                perror("# Error in opening file\n");
  85
  86                return errno;
  87        }
  88
  89        while (fgets(temp, 1024, fp)) {
  90                char *token = strtok(temp, ":\t");
  91                int fields = 0;
  92
  93                while (token) {
  94                        token_array[fields++] = token;
  95                        token = strtok(NULL, ":\t");
  96                }
  97
  98                /* Field 3 is llc occ resc value */
  99                if (runs > 0)
 100                        sum_llc_occu_resc += strtoul(token_array[3], NULL, 0);
 101                runs++;
 102        }
 103        fclose(fp);
 104        show_cache_info(sum_llc_occu_resc, no_of_bits, param->span);
 105
 106        return 0;
 107}
 108
 109void cqm_test_cleanup(void)
 110{
 111        remove(RESULT_FILE_NAME);
 112}
 113
 114int cqm_resctrl_val(int cpu_no, int n, char **benchmark_cmd)
 115{
 116        int ret, mum_resctrlfs;
 117
 118        cache_size = 0;
 119        mum_resctrlfs = 1;
 120
 121        ret = remount_resctrlfs(mum_resctrlfs);
 122        if (ret)
 123                return ret;
 124
 125        if (!validate_resctrl_feature_request("cqm"))
 126                return -1;
 127
 128        ret = get_cbm_mask("L3");
 129        if (ret)
 130                return ret;
 131
 132        long_mask = strtoul(cbm_mask, NULL, 16);
 133
 134        ret = get_cache_size(cpu_no, "L3", &cache_size);
 135        if (ret)
 136                return ret;
 137        printf("cache size :%lu\n", cache_size);
 138
 139        count_of_bits = count_bits(long_mask);
 140
 141        if (n < 1 || n > count_of_bits) {
 142                printf("Invalid input value for numbr_of_bits n!\n");
 143                printf("Please Enter value in range 1 to %d\n", count_of_bits);
 144                return -1;
 145        }
 146
 147        struct resctrl_val_param param = {
 148                .resctrl_val    = "cqm",
 149                .ctrlgrp        = "c1",
 150                .mongrp         = "m1",
 151                .cpu_no         = cpu_no,
 152                .mum_resctrlfs  = 0,
 153                .filename       = RESULT_FILE_NAME,
 154                .mask           = ~(long_mask << n) & long_mask,
 155                .span           = cache_size * n / count_of_bits,
 156                .num_of_runs    = 0,
 157                .setup          = cqm_setup,
 158        };
 159
 160        if (strcmp(benchmark_cmd[0], "fill_buf") == 0)
 161                sprintf(benchmark_cmd[1], "%lu", param.span);
 162
 163        remove(RESULT_FILE_NAME);
 164
 165        ret = resctrl_val(benchmark_cmd, &param);
 166        if (ret)
 167                return ret;
 168
 169        ret = check_results(&param, n);
 170        if (ret)
 171                return ret;
 172
 173        cqm_test_cleanup();
 174
 175        return 0;
 176}
 177