1 /*
2  * Copyright 2009-2017 Citrix Ltd and other contributors
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as published
6  * by the Free Software Foundation; version 2.1 only. with the special
7  * exception on linking described in file LICENSE.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU Lesser General Public License for more details.
13  */
14 
15 #include <ctype.h>
16 #include <inttypes.h>
17 #include <stdlib.h>
18 #include <unistd.h>
19 
20 #include <libxl.h>
21 #include <libxl_utils.h>
22 #include <libxlutil.h>
23 
24 #include "xl.h"
25 #include "xl_utils.h"
26 #include "xl_parse.h"
27 
psr_cmt_hwinfo(void)28 static int psr_cmt_hwinfo(void)
29 {
30     int rc;
31     int enabled;
32     uint32_t total_rmid;
33 
34     printf("Cache Monitoring Technology (CMT):\n");
35 
36     enabled = libxl_psr_cmt_enabled(ctx);
37     printf("%-16s: %s\n", "Enabled", enabled ? "1" : "0");
38     if (!enabled)
39         return 0;
40 
41     rc = libxl_psr_cmt_get_total_rmid(ctx, &total_rmid);
42     if (rc) {
43         fprintf(stderr, "Failed to get max RMID value\n");
44         return rc;
45     }
46     printf("%-16s: %u\n", "Total RMID", total_rmid);
47 
48     printf("Supported monitor types:\n");
49     if (libxl_psr_cmt_type_supported(ctx, LIBXL_PSR_CMT_TYPE_CACHE_OCCUPANCY))
50         printf("cache-occupancy\n");
51     if (libxl_psr_cmt_type_supported(ctx, LIBXL_PSR_CMT_TYPE_TOTAL_MEM_COUNT))
52         printf("total-mem-bandwidth\n");
53     if (libxl_psr_cmt_type_supported(ctx, LIBXL_PSR_CMT_TYPE_LOCAL_MEM_COUNT))
54         printf("local-mem-bandwidth\n");
55 
56     return rc;
57 }
58 
59 #define MBM_SAMPLE_RETRY_MAX 4
psr_cmt_get_mem_bandwidth(uint32_t domid,libxl_psr_cmt_type type,uint32_t socketid,uint64_t * bandwidth_r)60 static int psr_cmt_get_mem_bandwidth(uint32_t domid,
61                                      libxl_psr_cmt_type type,
62                                      uint32_t socketid,
63                                      uint64_t *bandwidth_r)
64 {
65     uint64_t sample1, sample2;
66     uint64_t tsc1, tsc2;
67     int retry_attempts = 0;
68     int rc;
69 
70     while (1) {
71         rc = libxl_psr_cmt_get_sample(ctx, domid, type, socketid,
72                                       &sample1, &tsc1);
73         if (rc < 0)
74             return rc;
75 
76         usleep(10000);
77 
78         rc = libxl_psr_cmt_get_sample(ctx, domid, type, socketid,
79                                       &sample2, &tsc2);
80         if (rc < 0)
81             return rc;
82 
83         if (tsc2 <= tsc1)
84             return -1;
85 
86         /*
87          * Hardware guarantees at most 1 overflow can happen if the duration
88          * between two samples is less than 1 second. Note that tsc returned
89          * from hypervisor is already-scaled time(ns).
90          */
91         if (tsc2 - tsc1 < 1000000000 && sample2 >= sample1)
92             break;
93 
94         if (retry_attempts < MBM_SAMPLE_RETRY_MAX) {
95             retry_attempts++;
96         } else {
97             fprintf(stderr, "event counter overflowed\n");
98             return -1;
99         }
100     }
101 
102     *bandwidth_r = (sample2 - sample1) * 1000000000 / (tsc2 - tsc1) / 1024;
103     return 0;
104 }
105 
psr_cmt_print_domain_info(libxl_dominfo * dominfo,libxl_psr_cmt_type type,libxl_bitmap * socketmap)106 static void psr_cmt_print_domain_info(libxl_dominfo *dominfo,
107                                       libxl_psr_cmt_type type,
108                                       libxl_bitmap *socketmap)
109 {
110     char *domain_name;
111     uint32_t socketid;
112     uint64_t monitor_data;
113 
114     if (!libxl_psr_cmt_domain_attached(ctx, dominfo->domid))
115         return;
116 
117     domain_name = libxl_domid_to_name(ctx, dominfo->domid);
118     printf("%-40s %5d", domain_name, dominfo->domid);
119     free(domain_name);
120 
121     libxl_for_each_set_bit(socketid, *socketmap) {
122         switch (type) {
123         case LIBXL_PSR_CMT_TYPE_CACHE_OCCUPANCY:
124             if (!libxl_psr_cmt_get_sample(ctx, dominfo->domid, type, socketid,
125                                           &monitor_data, NULL))
126                 printf("%13"PRIu64" KB", monitor_data / 1024);
127             break;
128         case LIBXL_PSR_CMT_TYPE_TOTAL_MEM_COUNT:
129         case LIBXL_PSR_CMT_TYPE_LOCAL_MEM_COUNT:
130             if (!psr_cmt_get_mem_bandwidth(dominfo->domid, type, socketid,
131                                            &monitor_data))
132                 printf("%11"PRIu64" KB/s", monitor_data);
133             break;
134         default:
135             return;
136         }
137     }
138 
139     printf("\n");
140 }
141 
psr_cmt_show(libxl_psr_cmt_type type,uint32_t domid)142 static int psr_cmt_show(libxl_psr_cmt_type type, uint32_t domid)
143 {
144     uint32_t i, socketid, total_rmid;
145     uint32_t l3_cache_size;
146     libxl_bitmap socketmap;
147     int rc, nr_domains;
148 
149     if (!libxl_psr_cmt_enabled(ctx)) {
150         fprintf(stderr, "CMT is disabled in the system\n");
151         return -1;
152     }
153 
154     if (!libxl_psr_cmt_type_supported(ctx, type)) {
155         fprintf(stderr, "Monitor type '%s' is not supported in the system\n",
156                 libxl_psr_cmt_type_to_string(type));
157         return -1;
158     }
159 
160     libxl_bitmap_init(&socketmap);
161     libxl_socket_bitmap_alloc(ctx, &socketmap, 0);
162     rc = libxl_get_online_socketmap(ctx, &socketmap);
163     if (rc < 0) {
164         fprintf(stderr, "Failed getting available sockets, rc: %d\n", rc);
165         goto out;
166     }
167 
168     rc = libxl_psr_cmt_get_total_rmid(ctx, &total_rmid);
169     if (rc < 0) {
170         fprintf(stderr, "Failed to get max RMID value\n");
171         goto out;
172     }
173 
174     printf("Total RMID: %d\n", total_rmid);
175 
176     /* Header */
177     printf("%-40s %5s", "Name", "ID");
178     libxl_for_each_set_bit(socketid, socketmap)
179         printf("%14s %d", "Socket", socketid);
180     printf("\n");
181 
182     if (type == LIBXL_PSR_CMT_TYPE_CACHE_OCCUPANCY) {
183             /* Total L3 cache size */
184             printf("%-46s", "Total L3 Cache Size");
185             libxl_for_each_set_bit(socketid, socketmap) {
186                 rc = libxl_psr_cmt_get_l3_cache_size(ctx, socketid,
187                                                      &l3_cache_size);
188                 if (rc < 0) {
189                     fprintf(stderr,
190                             "Failed to get system l3 cache size for socket:%d\n",
191                             socketid);
192                     goto out;
193                 }
194                 printf("%13u KB", l3_cache_size);
195             }
196             printf("\n");
197     }
198 
199     /* Each domain */
200     if (domid != INVALID_DOMID) {
201         libxl_dominfo dominfo;
202 
203         libxl_dominfo_init(&dominfo);
204         if (libxl_domain_info(ctx, &dominfo, domid)) {
205             fprintf(stderr, "Failed to get domain info for %d\n", domid);
206             rc = -1;
207             goto out;
208         }
209         psr_cmt_print_domain_info(&dominfo, type, &socketmap);
210         libxl_dominfo_dispose(&dominfo);
211     }
212     else
213     {
214         libxl_dominfo *list;
215         if (!(list = libxl_list_domain(ctx, &nr_domains))) {
216             fprintf(stderr, "Failed to get domain info for domain list.\n");
217             rc = -1;
218             goto out;
219         }
220         for (i = 0; i < nr_domains; i++)
221             psr_cmt_print_domain_info(list + i, type, &socketmap);
222         libxl_dominfo_list_free(list, nr_domains);
223     }
224 
225 out:
226     libxl_bitmap_dispose(&socketmap);
227     return rc;
228 }
229 
main_psr_cmt_attach(int argc,char ** argv)230 int main_psr_cmt_attach(int argc, char **argv)
231 {
232     uint32_t domid;
233     int opt, ret = 0;
234 
235     SWITCH_FOREACH_OPT(opt, "", NULL, "psr-cmt-attach", 1) {
236         /* No options */
237     }
238 
239     domid = find_domain(argv[optind]);
240     ret = libxl_psr_cmt_attach(ctx, domid);
241 
242     return ret;
243 }
244 
main_psr_cmt_detach(int argc,char ** argv)245 int main_psr_cmt_detach(int argc, char **argv)
246 {
247     uint32_t domid;
248     int opt, ret = 0;
249 
250     SWITCH_FOREACH_OPT(opt, "", NULL, "psr-cmt-detach", 1) {
251         /* No options */
252     }
253 
254     domid = find_domain(argv[optind]);
255     ret = libxl_psr_cmt_detach(ctx, domid);
256 
257     return ret;
258 }
259 
main_psr_cmt_show(int argc,char ** argv)260 int main_psr_cmt_show(int argc, char **argv)
261 {
262     int opt, ret = 0;
263     uint32_t domid;
264     libxl_psr_cmt_type type;
265 
266     SWITCH_FOREACH_OPT(opt, "", NULL, "psr-cmt-show", 1) {
267         /* No options */
268     }
269 
270     if (!strcmp(argv[optind], "cache-occupancy"))
271         type = LIBXL_PSR_CMT_TYPE_CACHE_OCCUPANCY;
272     else if (!strcmp(argv[optind], "total-mem-bandwidth"))
273         type = LIBXL_PSR_CMT_TYPE_TOTAL_MEM_COUNT;
274     else if (!strcmp(argv[optind], "local-mem-bandwidth"))
275         type = LIBXL_PSR_CMT_TYPE_LOCAL_MEM_COUNT;
276     else {
277         help("psr-cmt-show");
278         return 2;
279     }
280 
281     if (optind + 1 >= argc)
282         domid = INVALID_DOMID;
283     else if (optind + 1 == argc - 1)
284         domid = find_domain(argv[optind + 1]);
285     else {
286         help("psr-cmt-show");
287         return 2;
288     }
289 
290     ret = psr_cmt_show(type, domid);
291 
292     return ret;
293 }
294 
psr_l3_cat_hwinfo(void)295 static int psr_l3_cat_hwinfo(void)
296 {
297     int rc;
298     unsigned int i, nr;
299     uint32_t l3_cache_size;
300     libxl_psr_cat_info *info;
301 
302     rc = libxl_psr_cat_get_info(ctx, &info, &nr, 3);
303     if (rc)
304         return rc;
305 
306     printf("Cache Allocation Technology (CAT):\n");
307 
308     for (i = 0; i < nr; i++) {
309         rc = libxl_psr_cmt_get_l3_cache_size(ctx, info[i].id, &l3_cache_size);
310         if (rc) {
311             fprintf(stderr, "Failed to get l3 cache size for socket:%d\n",
312                     info[i].id);
313             goto out;
314         }
315         printf("%-16s: %u\n", "Socket ID", info[i].id);
316         printf("%-16s: %uKB\n", "L3 Cache", l3_cache_size);
317         printf("%-16s: %s\n", "CDP Status",
318                info[i].cdp_enabled ? "Enabled" : "Disabled");
319         printf("%-16s: %u\n", "Maximum COS", info[i].cos_max);
320         printf("%-16s: %u\n", "CBM length", info[i].cbm_len);
321         printf("%-16s: %#llx\n", "Default CBM",
322                (1ull << info[i].cbm_len) - 1);
323     }
324 
325 out:
326     libxl_psr_cat_info_list_free(info, nr);
327     return rc;
328 }
329 
psr_print_one_domain_val_type(uint32_t domid,libxl_psr_hw_info * info,libxl_psr_type type)330 static void psr_print_one_domain_val_type(uint32_t domid,
331                                           libxl_psr_hw_info *info,
332                                           libxl_psr_type type)
333 {
334     uint64_t val;
335 
336     if (!libxl_psr_get_val(ctx, domid, type, info->id, &val)) {
337         if (type == LIBXL_PSR_CBM_TYPE_MBA_THRTL && info->u.mba.linear)
338             printf("%16"PRIu64, val);
339         else
340             printf("%#16"PRIx64, val);
341     }
342     else
343         printf("%16s", "error");
344 }
345 
psr_print_one_domain_val(uint32_t domid,libxl_psr_hw_info * info,libxl_psr_feat_type type,unsigned int lvl)346 static void psr_print_one_domain_val(uint32_t domid,
347                                      libxl_psr_hw_info *info,
348                                      libxl_psr_feat_type type,
349                                      unsigned int lvl)
350 {
351     char *domain_name;
352 
353     domain_name = libxl_domid_to_name(ctx, domid);
354     printf("%5d%25s", domid, domain_name);
355     free(domain_name);
356 
357     switch (type) {
358     case LIBXL_PSR_FEAT_TYPE_CAT:
359         switch (lvl) {
360         case 3:
361             if (!info->u.cat.cdp_enabled) {
362                 psr_print_one_domain_val_type(domid, info,
363                                               LIBXL_PSR_CBM_TYPE_L3_CBM);
364             } else {
365                 psr_print_one_domain_val_type(domid, info,
366                                               LIBXL_PSR_CBM_TYPE_L3_CBM_CODE);
367                 psr_print_one_domain_val_type(domid, info,
368                                               LIBXL_PSR_CBM_TYPE_L3_CBM_DATA);
369             }
370             break;
371 
372         case 2:
373             psr_print_one_domain_val_type(domid, info,
374                                           LIBXL_PSR_CBM_TYPE_L2_CBM);
375             break;
376 
377         default:
378             printf("Input lvl %d is wrong!", lvl);
379         }
380         break;
381 
382     case LIBXL_PSR_FEAT_TYPE_MBA:
383         psr_print_one_domain_val_type(domid, info,
384                                       LIBXL_PSR_CBM_TYPE_MBA_THRTL);
385         break;
386     }
387 
388     printf("\n");
389 }
390 
psr_print_domain_val(uint32_t domid,libxl_psr_hw_info * info,libxl_psr_feat_type type,unsigned int lvl)391 static int psr_print_domain_val(uint32_t domid,
392                                 libxl_psr_hw_info *info,
393                                 libxl_psr_feat_type type,
394                                 unsigned int lvl)
395 {
396     int i, nr_domains;
397     libxl_dominfo *list;
398 
399     if (domid != INVALID_DOMID) {
400         psr_print_one_domain_val(domid, info, type, lvl);
401         return 0;
402     }
403 
404     if (!(list = libxl_list_domain(ctx, &nr_domains))) {
405         fprintf(stderr, "Failed to get domain list for value display\n");
406         return EXIT_FAILURE;
407     }
408 
409     for (i = 0; i < nr_domains; i++)
410         psr_print_one_domain_val(list[i].domid, info, type, lvl);
411     libxl_dominfo_list_free(list, nr_domains);
412 
413     return 0;
414 }
415 
psr_print_socket(uint32_t domid,libxl_psr_hw_info * info,libxl_psr_feat_type type,unsigned int lvl)416 static int psr_print_socket(uint32_t domid,
417                             libxl_psr_hw_info *info,
418                             libxl_psr_feat_type type,
419                             unsigned int lvl)
420 {
421     printf("%-16s: %u\n", "Socket ID", info->id);
422 
423     switch (type) {
424     case LIBXL_PSR_FEAT_TYPE_CAT:
425     {
426         int rc;
427         uint32_t l3_cache_size;
428 
429         /* So far, CMT only supports L3 cache. */
430         if (lvl == 3) {
431             rc = libxl_psr_cmt_get_l3_cache_size(ctx, info->id, &l3_cache_size);
432             if (rc) {
433                 fprintf(stderr, "Failed to get l3 cache size for socket:%d\n",
434                         info->id);
435                 return -1;
436             }
437             printf("%-16s: %uKB\n", "L3 Cache", l3_cache_size);
438         }
439 
440         printf("%-16s: %#llx\n", "Default CBM",
441                (1ull << info->u.cat.cbm_len) - 1);
442         if (info->u.cat.cdp_enabled)
443             printf("%5s%25s%16s%16s\n", "ID", "NAME", "CBM (code)", "CBM (data)");
444         else
445             printf("%5s%25s%16s\n", "ID", "NAME", "CBM");
446 
447         break;
448     }
449 
450     case LIBXL_PSR_FEAT_TYPE_MBA:
451         printf("%-16s: %u\n", "Default THRTL", 0);
452         printf("%5s%25s%16s\n", "ID", "NAME", "THRTL");
453         break;
454 
455     default:
456         fprintf(stderr, "Input feature type %d is wrong\n", type);
457         return EXIT_FAILURE;
458     }
459 
460     return psr_print_domain_val(domid, info, type, lvl);
461 }
462 
psr_val_show(uint32_t domid,libxl_psr_feat_type type,unsigned int lvl)463 static int psr_val_show(uint32_t domid,
464                         libxl_psr_feat_type type,
465                         unsigned int lvl)
466 {
467     unsigned int i, nr;
468     int rc;
469     libxl_psr_hw_info *info;
470 
471     switch (type) {
472     case LIBXL_PSR_FEAT_TYPE_CAT:
473         if (lvl != 2 && lvl != 3) {
474             fprintf(stderr, "Input lvl %d is wrong\n", lvl);
475             return EXIT_FAILURE;
476         }
477         break;
478 
479     case LIBXL_PSR_FEAT_TYPE_MBA:
480         if (lvl) {
481             fprintf(stderr,
482                     "Unexpected lvl parameter %d for MBA feature\n", lvl);
483             return EXIT_FAILURE;
484         }
485         break;
486 
487     default:
488         fprintf(stderr, "Input feature type %d is wrong\n", type);
489         return EXIT_FAILURE;
490     }
491 
492     rc = libxl_psr_get_hw_info(ctx, type, lvl, &nr, &info);
493     if (rc) {
494         fprintf(stderr, "Failed to get info\n");
495         return rc;
496     }
497 
498     for (i = 0; i < nr; i++) {
499         rc = psr_print_socket(domid, info + i, type, lvl);
500         if (rc)
501             goto out;
502     }
503 
504 out:
505     libxl_psr_hw_info_list_free(info, nr);
506     return rc;
507 }
508 
psr_l2_cat_hwinfo(void)509 static int psr_l2_cat_hwinfo(void)
510 {
511     int rc;
512     unsigned int i, nr;
513     libxl_psr_cat_info *info;
514 
515     rc = libxl_psr_cat_get_info(ctx, &info, &nr, 2);
516     if (rc)
517         return rc;
518 
519     printf("Cache Allocation Technology (CAT): L2\n");
520 
521     for (i = 0; i < nr; i++) {
522         /* There is no CMT on L2 cache so far. */
523         printf("%-16s: %u\n", "Socket ID", info[i].id);
524         printf("%-16s: %u\n", "Maximum COS", info[i].cos_max);
525         printf("%-16s: %u\n", "CBM length", info[i].cbm_len);
526         printf("%-16s: %#llx\n", "Default CBM",
527                (1ull << info[i].cbm_len) - 1);
528     }
529 
530     libxl_psr_cat_info_list_free(info, nr);
531     return rc;
532 }
533 
main_psr_mba_show(int argc,char ** argv)534 int main_psr_mba_show(int argc, char **argv)
535 {
536     int opt;
537     uint32_t domid;
538 
539     SWITCH_FOREACH_OPT(opt, "", NULL, "psr-mba-show", 0) {
540         /* No options */
541     }
542 
543     if (optind >= argc)
544         domid = INVALID_DOMID;
545     else if (optind == argc - 1)
546         domid = find_domain(argv[optind]);
547     else {
548         help("psr-mba-show");
549         return 2;
550     }
551 
552     return psr_val_show(domid, LIBXL_PSR_FEAT_TYPE_MBA, 0);
553 }
554 
main_psr_mba_set(int argc,char ** argv)555 int main_psr_mba_set(int argc, char **argv)
556 {
557     uint32_t domid;
558     libxl_psr_type type;
559     uint64_t thrtl;
560     int ret, opt = 0;
561     libxl_bitmap target_map;
562     char *value;
563     libxl_string_list socket_list;
564     unsigned long start, end;
565     unsigned int i, j, len;
566 
567     static const struct option opts[] = {
568         {"socket", 1, 0, 's'},
569         COMMON_LONG_OPTS
570     };
571 
572     libxl_socket_bitmap_alloc(ctx, &target_map, 0);
573     libxl_bitmap_set_none(&target_map);
574 
575     SWITCH_FOREACH_OPT(opt, "s:", opts, "psr-mba-set", 0) {
576     case 's':
577         trim(isspace, optarg, &value);
578         split_string_into_string_list(value, ",", &socket_list);
579         len = libxl_string_list_length(&socket_list);
580         for (i = 0; i < len; i++) {
581             parse_range(socket_list[i], &start, &end);
582             for (j = start; j <= end; j++)
583                 libxl_bitmap_set(&target_map, j);
584         }
585 
586         libxl_string_list_dispose(&socket_list);
587         free(value);
588         break;
589     }
590 
591     type = LIBXL_PSR_CBM_TYPE_MBA_THRTL;
592 
593     if (libxl_bitmap_is_empty(&target_map))
594         libxl_bitmap_set_any(&target_map);
595 
596     if (argc != optind + 2) {
597         help("psr-mba-set");
598         return EXIT_FAILURE;
599     }
600 
601     domid = find_domain(argv[optind]);
602     thrtl = strtoll(argv[optind + 1], NULL , 0);
603 
604     ret = libxl_psr_set_val(ctx, domid, type, &target_map, thrtl);
605 
606     libxl_bitmap_dispose(&target_map);
607     return ret;
608 }
609 
psr_mba_hwinfo(void)610 static int psr_mba_hwinfo(void)
611 {
612     int rc;
613     unsigned int i, nr;
614     libxl_psr_hw_info *info;
615 
616     rc = libxl_psr_get_hw_info(ctx, LIBXL_PSR_FEAT_TYPE_MBA, 0, &nr, &info);
617     if (rc)
618         return rc;
619 
620     printf("Memory Bandwidth Allocation (MBA):\n");
621 
622     for (i = 0; i < nr; i++) {
623         printf("Socket ID               : %u\n", info[i].id);
624         printf("Linear Mode             : %s\n",
625                info[i].u.mba.linear ? "Enabled" : "Disabled");
626         printf("Maximum COS             : %u\n", info[i].u.mba.cos_max);
627         printf("Maximum Throttling Value: %u\n", info[i].u.mba.thrtl_max);
628         printf("Default Throttling Value: %u\n", 0);
629     }
630 
631     libxl_psr_hw_info_list_free(info, nr);
632     return rc;
633 }
634 
main_psr_cat_cbm_set(int argc,char ** argv)635 int main_psr_cat_cbm_set(int argc, char **argv)
636 {
637     uint32_t domid;
638     libxl_psr_cbm_type type;
639     uint64_t cbm;
640     int ret, opt = 0;
641     int opt_data = 0, opt_code = 0;
642     libxl_bitmap target_map;
643     char *value;
644     libxl_string_list socket_list;
645     unsigned long start, end;
646     unsigned int i, j, len;
647     unsigned int lvl = 3;
648 
649     static struct option opts[] = {
650         {"socket", 1, 0, 's'},
651         {"data", 0, 0, 'd'},
652         {"code", 0, 0, 'c'},
653         {"level", 1, 0, 'l'},
654         COMMON_LONG_OPTS
655     };
656 
657     libxl_socket_bitmap_alloc(ctx, &target_map, 0);
658     libxl_bitmap_set_none(&target_map);
659 
660     SWITCH_FOREACH_OPT(opt, "s:l:cd", opts, "psr-cat-set", 2) {
661     case 's':
662         trim(isspace, optarg, &value);
663         split_string_into_string_list(value, ",", &socket_list);
664         len = libxl_string_list_length(&socket_list);
665         for (i = 0; i < len; i++) {
666             parse_range(socket_list[i], &start, &end);
667             for (j = start; j <= end; j++)
668                 libxl_bitmap_set(&target_map, j);
669         }
670 
671         libxl_string_list_dispose(&socket_list);
672         free(value);
673         break;
674     case 'd':
675         opt_data = 1;
676         break;
677     case 'c':
678         opt_code = 1;
679         break;
680     case 'l':
681         lvl = atoi(optarg);
682         break;
683     }
684 
685     if (lvl == 2)
686         type = LIBXL_PSR_CBM_TYPE_L2_CBM;
687     else if (lvl == 3) {
688         if (opt_data && opt_code) {
689             fprintf(stderr, "Cannot handle -c and -d at the same time\n");
690             return EXIT_FAILURE;
691         } else if (opt_data) {
692             type = LIBXL_PSR_CBM_TYPE_L3_CBM_DATA;
693         } else if (opt_code) {
694             type = LIBXL_PSR_CBM_TYPE_L3_CBM_CODE;
695         } else {
696             type = LIBXL_PSR_CBM_TYPE_L3_CBM;
697         }
698     } else {
699         type = LIBXL_PSR_CBM_TYPE_L3_CBM;
700         fprintf(stderr, "Input lvl %d is wrong\n", lvl);
701         return EXIT_FAILURE;
702     }
703 
704     if (libxl_bitmap_is_empty(&target_map))
705         libxl_bitmap_set_any(&target_map);
706 
707     if (argc != optind + 2) {
708         help("psr-cat-set");
709         return 2;
710     }
711 
712     domid = find_domain(argv[optind]);
713     cbm = strtoll(argv[optind + 1], NULL , 0);
714 
715     ret = libxl_psr_cat_set_cbm(ctx, domid, type, &target_map, cbm);
716 
717     libxl_bitmap_dispose(&target_map);
718     return ret;
719 }
720 
main_psr_cat_show(int argc,char ** argv)721 int main_psr_cat_show(int argc, char **argv)
722 {
723     int opt = 0;
724     uint32_t domid;
725     unsigned int lvl = 3;
726 
727     static struct option opts[] = {
728         {"level", 1, 0, 'l'},
729         COMMON_LONG_OPTS
730     };
731 
732     SWITCH_FOREACH_OPT(opt, "l:", opts, "psr-cat-show", 0) {
733     case 'l':
734         lvl = atoi(optarg);
735         break;
736     }
737 
738     if (optind >= argc)
739         domid = INVALID_DOMID;
740     else if (optind == argc - 1)
741         domid = find_domain(argv[optind]);
742     else {
743         help("psr-cat-show");
744         return 2;
745     }
746 
747     return psr_val_show(domid, LIBXL_PSR_FEAT_TYPE_CAT, lvl);
748 }
749 
main_psr_hwinfo(int argc,char ** argv)750 int main_psr_hwinfo(int argc, char **argv)
751 {
752     int opt, ret = 0;
753     bool all = true, cmt = false, cat = false, mba = false;
754     static const struct option opts[] = {
755         {"cmt", 0, 0, 'm'},
756         {"cat", 0, 0, 'a'},
757         {"mba", 0, 0, 'b'},
758         COMMON_LONG_OPTS
759     };
760 
761     SWITCH_FOREACH_OPT(opt, "mab", opts, "psr-hwinfo", 0) {
762     case 'm':
763         all = false; cmt = true;
764         break;
765     case 'a':
766         all = false; cat = true;
767         break;
768     case 'b':
769         all = false; mba = true;
770         break;
771     }
772 
773     if (!ret && (all || cmt))
774         ret = psr_cmt_hwinfo();
775 
776     if (!ret && (all || cat))
777         ret = psr_l3_cat_hwinfo();
778 
779     /* L2 CAT is independent of CMT and L3 CAT */
780     if (all || cat)
781         ret = psr_l2_cat_hwinfo();
782 
783     /* MBA is independent of CMT and CAT */
784     if (all || mba)
785         ret = psr_mba_hwinfo();
786 
787     return ret;
788 }
789 
790 /*
791  * Local variables:
792  * mode: C
793  * c-basic-offset: 4
794  * indent-tabs-mode: nil
795  * End:
796  */
797