2 // Copyright (c) 2010-2017 Intel Corporation
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
8 // http://www.apache.org/licenses/LICENSE-2.0
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
17 #include <rte_lcore.h>
19 #include "prox_malloc.h"
20 #include "stats_core.h"
24 #include "parse_utils.h"
28 struct stats_core_manager {
29 struct rdt_features rdt_features;
32 uint16_t n_lcore_stats;
33 int cache_size[RTE_MAX_LCORE];
34 struct lcore_stats lcore_stats_set[0];
37 static struct stats_core_manager *scm;
40 static int get_L3_size(void)
42 char buf[1024]= "/proc/cpuinfo";
43 FILE* fd = fopen(buf, "r");
45 plogx_err("Could not open %s", buf);
48 int lcore = -1, val = 0, size = 0;
49 while (fgets(buf, sizeof(buf), fd) != NULL) {
50 if (sscanf(buf, "processor : %u", &val) == 1) {
52 scm->max_core_id = lcore;
54 if (sscanf(buf, "cache size : %u", &val) == 1) {
56 if ((lcore != -1) && (lcore < RTE_MAX_LCORE)) {
57 scm->cache_size[lcore] = size * 1024;
62 plog_info("\tMaximum core_id = %d\n", scm->max_core_id);
66 int stats_get_n_lcore_stats(void)
68 return scm->n_lcore_stats;
71 int stats_cpu_freq_enabled(void)
73 return scm->msr_support;
76 int stats_cmt_enabled(void)
78 return cmt_is_supported();
81 int stats_cat_enabled(void)
83 return cat_is_supported();
86 int stats_mbm_enabled(void)
88 return mbm_is_supported();
91 uint32_t stats_lcore_find_stat_id(uint32_t lcore_id)
93 for (int i = 0; i < scm->n_lcore_stats; ++i)
94 if (scm->lcore_stats_set[i].lcore_id == lcore_id)
99 struct lcore_stats_sample *stats_get_lcore_stats_sample(uint32_t stat_id, int l)
101 return &scm->lcore_stats_set[stat_id].sample[l == last_stat];
104 struct lcore_stats *stats_get_lcore_stats(uint32_t stat_id)
106 return &scm->lcore_stats_set[stat_id];
109 static struct stats_core_manager *alloc_stats_core_manager(void)
111 const int socket_id = rte_lcore_to_socket_id(rte_lcore_id());
112 uint32_t n_lcore_stats = 0;
117 while (prox_core_next(&lcore_id, 0) == 0)
119 mem_size = sizeof(struct stats_core_manager) + sizeof(struct lcore_stats) * n_lcore_stats;
120 return prox_zmalloc(mem_size, socket_id);
123 void stats_lcore_init(void)
125 struct lcore_cfg *lconf;
129 scm = alloc_stats_core_manager();
131 if (is_virtualized()) {
132 plog_info("Not initializing msr as running in a VM\n");
133 scm->msr_support = 0;
134 } else if ((scm->msr_support = !msr_init()) == 0) {
135 plog_warn("Failed to open msr pseudo-file (missing msr kernel module?)\n");
138 scm->n_lcore_stats = 0;
141 while (prox_core_next(&lcore_id, 0) == 0) {
142 scm->lcore_stats_set[scm->n_lcore_stats++].lcore_id = lcore_id;
144 if (!rdt_is_supported())
147 if (!scm->msr_support) {
148 plog_warn("CPU supports RDT but msr module not loaded. Disabling RDT stats.\n");
152 if (0 != rdt_get_features(&scm->rdt_features)) {
153 plog_warn("Failed to get RDT features\n");
157 rdt_init_stat_core(rte_lcore_id());
160 /* Start using last rmid, to keep first rmid for technologies (like cat) where there are less rmid */
161 uint32_t last_rmid = scm->rdt_features.cmt_max_rmid;
162 for (uint32_t i = 0; i < scm->n_lcore_stats; ++i) {
163 scm->lcore_stats_set[i].rmid = last_rmid; // cmt_max_rmid is used by non-monitored cores
168 for (uint32_t i = 0; i < scm->n_lcore_stats; ++i) {
169 plog_info("\tAssociating core %u to rmid %lu (associating each core used by prox to a different rmid)\n", scm->lcore_stats_set[i].lcore_id, scm->lcore_stats_set[i].rmid);
170 cqm_assoc(scm->lcore_stats_set[i].lcore_id, scm->lcore_stats_set[i].rmid);
171 uint32_t lcore_id = scm->lcore_stats_set[i].lcore_id;
172 lconf = &lcore_cfg[lcore_id];
173 cache_set = lconf->cache_set;
174 if ((cache_set) && (cache_set < PROX_MAX_CACHE_SET)) {
175 scm->lcore_stats_set[i].class = cache_set;
176 scm->lcore_stats_set[i].cat_mask = prox_cache_set_cfg[cache_set].mask;
177 if (prox_cache_set_cfg[cache_set].socket_id == -1) {
178 prox_cache_set_cfg[cache_set].socket_id = scm->lcore_stats_set[i].socket_id;
179 prox_cache_set_cfg[cache_set].lcore_id = lcore_id;
180 } else if (prox_cache_set_cfg[cache_set].socket_id != (int32_t)scm->lcore_stats_set[i].socket_id) {
181 plog_err("Unsupported config: Using same cache set on two different socket\n");
184 scm->lcore_stats_set[i].class = 0;
185 scm->lcore_stats_set[i].cat_mask = (1 << cat_get_num_ways()) -1;
189 last_rmid = scm->rdt_features.cat_max_rmid;
190 for (int i = 0; i < PROX_MAX_CACHE_SET; i++) {
191 if (prox_cache_set_cfg[i].mask) {
192 plog_info("\tSetting cache set %d to %x\n", i, prox_cache_set_cfg[i].mask);
193 cat_set_class_mask(prox_cache_set_cfg[i].lcore_id, i, prox_cache_set_cfg[i].mask);
196 for (uint32_t i = 0; i < scm->n_lcore_stats; ++i) {
197 uint32_t lcore_id = scm->lcore_stats_set[i].lcore_id;
198 lconf = &lcore_cfg[lcore_id];
199 cache_set = lconf->cache_set;
201 if (prox_cache_set_cfg[cache_set].mask) {
202 scm->lcore_stats_set[i].rmid = (scm->lcore_stats_set[i].rmid) | (cache_set << 32);
203 plog_info("\tCache set = %ld for core %d\n", cache_set, lcore_id);
204 cqm_assoc(lcore_id, scm->lcore_stats_set[i].rmid);
206 plog_err("\tUndefined Cache set = %ld for core %d\n", cache_set, lcore_id);
209 if (prox_cache_set_cfg[cache_set].mask) {
210 scm->lcore_stats_set[i].rmid = (scm->lcore_stats_set[i].rmid);
211 plog_info("\tUsing default cache set for core %d\n", lcore_id);
212 cqm_assoc(lcore_id, scm->lcore_stats_set[i].rmid);
214 plog_info("\tNo default cache set for core %d\n", lcore_id);
220 static void stats_lcore_update_freq(void)
222 for (uint8_t i = 0; i < scm->n_lcore_stats; ++i) {
223 struct lcore_stats *ls = &scm->lcore_stats_set[i];
224 struct lcore_stats_sample *lss = &ls->sample[last_stat];
226 msr_read(&lss->afreq, ls->lcore_id, 0xe8);
227 msr_read(&lss->mfreq, ls->lcore_id, 0xe7);
230 void stats_update_cache_mask(uint32_t lcore_id, uint32_t mask)
232 for (uint8_t i = 0; i < scm->n_lcore_stats; ++i) {
233 struct lcore_stats *ls = &scm->lcore_stats_set[i];
234 if (ls->lcore_id == lcore_id) {
235 plog_info("Updating core %d stats %d to mask %x\n", lcore_id, i, mask);
236 scm->lcore_stats_set[i].cat_mask = mask;
241 static void stats_lcore_update_rdt(void)
243 for (uint8_t i = 0; i < scm->n_lcore_stats; ++i) {
244 struct lcore_stats *ls = &scm->lcore_stats_set[i];
247 cmt_read_ctr(&ls->cmt_data, ls->rmid, ls->lcore_id);
248 mbm_read_tot_bdw(&ls->mbm_tot, ls->rmid, ls->lcore_id);
249 mbm_read_loc_bdw(&ls->mbm_loc, ls->rmid, ls->lcore_id);
254 void stats_lcore_post_proc(void)
256 /* update CQM stats (calculate fraction and bytes reported) */
257 for (uint8_t i = 0; i < scm->n_lcore_stats; ++i) {
258 struct lcore_stats *ls = &scm->lcore_stats_set[i];
259 struct lcore_stats_sample *lss = &ls->sample[last_stat];
262 ls->cmt_bytes = ls->cmt_data * scm->rdt_features.upscaling_factor;
263 lss->mbm_tot_bytes = ls->mbm_tot * scm->rdt_features.upscaling_factor;
264 lss->mbm_loc_bytes = ls->mbm_loc * scm->rdt_features.upscaling_factor;
265 plogx_dbg("cache[core %d] = %ld\n", ls->lcore_id, ls->cmt_bytes);
268 for (uint8_t i = 0; i < scm->n_lcore_stats; ++i) {
269 struct lcore_stats *ls = &scm->lcore_stats_set[i];
271 if (ls->rmid && scm->cache_size[ls->lcore_id])
272 ls->cmt_fraction = ls->cmt_bytes * 10000 / scm->cache_size[ls->lcore_id];
274 ls->cmt_fraction = 0;
278 void stats_lcore_update(void)
280 if (scm->msr_support)
281 stats_lcore_update_freq();
282 if (rdt_is_supported())
283 stats_lcore_update_rdt();
286 void stats_lcore_assoc_rmid(void)
288 for (uint32_t i = 0; i < scm->n_lcore_stats; ++i) {
289 uint32_t lcore_id = scm->lcore_stats_set[i].lcore_id;
290 scm->lcore_stats_set[i].rmid = scm->lcore_stats_set[i].rmid & 0xffffffff;
291 cqm_assoc(lcore_id, scm->lcore_stats_set[i].rmid);