From mboxrd@z Thu Jan 1 00:00:00 1970 From: Chao Peng Subject: [PATCH 6/6] tools: add tools support for Intel CAT Date: Fri, 13 Mar 2015 18:13:25 +0800 Message-ID: <1426241605-4114-7-git-send-email-chao.p.peng@linux.intel.com> References: <1426241605-4114-1-git-send-email-chao.p.peng@linux.intel.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: <1426241605-4114-1-git-send-email-chao.p.peng@linux.intel.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: xen-devel@lists.xen.org Cc: keir@xen.org, Ian.Campbell@citrix.com, stefano.stabellini@eu.citrix.com, andrew.cooper3@citrix.com, Ian.Jackson@eu.citrix.com, will.auld@intel.com, JBeulich@suse.com, wei.liu2@citrix.com, dgdegra@tycho.nsa.gov List-Id: xen-devel@lists.xenproject.org This is the xc/xl changes to support Intel Cache Allocation Technology(CAT). Two commands are introduced: - xl psr-cat-cbm-set [-s socket] Set cache capacity bitmasks(CBM) for a domain. - xl psr-cat-show Show Cache Allocation Technology information. Signed-off-by: Chao Peng --- tools/libxc/include/xenctrl.h | 15 +++ tools/libxc/xc_psr.c | 74 ++++++++++++++ tools/libxl/libxl.h | 18 ++++ tools/libxl/libxl_psr.c | 106 ++++++++++++++++++-- tools/libxl/libxl_types.idl | 4 + tools/libxl/xl.h | 4 + tools/libxl/xl_cmdimpl.c | 225 ++++++++++++++++++++++++++++++++++++++++-- tools/libxl/xl_cmdtable.c | 13 +++ 8 files changed, 444 insertions(+), 15 deletions(-) diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h index df18292..1373a46 100644 --- a/tools/libxc/include/xenctrl.h +++ b/tools/libxc/include/xenctrl.h @@ -2692,6 +2692,12 @@ enum xc_psr_cmt_type { XC_PSR_CMT_LOCAL_MEM_COUNT, }; typedef enum xc_psr_cmt_type xc_psr_cmt_type; + +enum xc_psr_cat_type { + XC_PSR_CAT_L3_CBM = 1, +}; +typedef enum xc_psr_cat_type xc_psr_cat_type; + int xc_psr_cmt_attach(xc_interface *xch, uint32_t domid); int xc_psr_cmt_detach(xc_interface *xch, uint32_t domid); int xc_psr_cmt_get_domain_rmid(xc_interface *xch, uint32_t domid, @@ -2706,6 +2712,15 @@ int xc_psr_cmt_get_data(xc_interface *xch, uint32_t rmid, uint32_t cpu, uint32_t psr_cmt_type, uint64_t *monitor_data, uint64_t *tsc); int xc_psr_cmt_enabled(xc_interface *xch); + +int xc_psr_cat_set_domain_data(xc_interface *xch, uint32_t domid, + xc_psr_cat_type type, uint32_t target, + uint64_t data); +int xc_psr_cat_get_domain_data(xc_interface *xch, uint32_t domid, + xc_psr_cat_type type, uint32_t target, + uint64_t *data); +int xc_psr_cat_get_l3_info(xc_interface *xch, uint32_t socket, + uint32_t *cos_max, uint32_t *cbm_len); #endif #endif /* XENCTRL_H */ diff --git a/tools/libxc/xc_psr.c b/tools/libxc/xc_psr.c index e367a80..6c670d5 100644 --- a/tools/libxc/xc_psr.c +++ b/tools/libxc/xc_psr.c @@ -248,6 +248,80 @@ int xc_psr_cmt_enabled(xc_interface *xch) return 0; } +int xc_psr_cat_set_domain_data(xc_interface *xch, uint32_t domid, + xc_psr_cat_type type, uint32_t target, + uint64_t data) +{ + DECLARE_DOMCTL; + uint32_t cmd; + + switch ( type ) + { + case XC_PSR_CAT_L3_CBM: + cmd = XEN_DOMCTL_PSR_CAT_OP_SET_L3_CBM; + break; + default: + return -1; + } + + domctl.cmd = XEN_DOMCTL_psr_cat_op; + domctl.domain = (domid_t)domid; + domctl.u.psr_cat_op.cmd = cmd; + domctl.u.psr_cat_op.target = target; + domctl.u.psr_cat_op.data = data; + + return do_domctl(xch, &domctl); +} + +int xc_psr_cat_get_domain_data(xc_interface *xch, uint32_t domid, + xc_psr_cat_type type, uint32_t target, + uint64_t *data) +{ + int rc; + DECLARE_DOMCTL; + uint32_t cmd; + + switch ( type ) + { + case XC_PSR_CAT_L3_CBM: + cmd = XEN_DOMCTL_PSR_CAT_OP_GET_L3_CBM; + break; + default: + return -1; + } + + domctl.cmd = XEN_DOMCTL_psr_cat_op; + domctl.domain = (domid_t)domid; + domctl.u.psr_cat_op.cmd = cmd; + domctl.u.psr_cat_op.target = target; + + rc = do_domctl(xch, &domctl); + + if ( !rc ) + *data = domctl.u.psr_cat_op.data; + + return rc; +} + +int xc_psr_cat_get_l3_info(xc_interface *xch, uint32_t socket, + uint32_t *cos_max, uint32_t *cbm_len) +{ + int rc; + DECLARE_SYSCTL; + + sysctl.cmd = XEN_SYSCTL_psr_cat_op; + sysctl.u.psr_cat_op.cmd = XEN_SYSCTL_PSR_CAT_get_l3_info; + sysctl.u.psr_cat_op.target = socket; + + rc = xc_sysctl(xch, &sysctl); + if ( !rc ) + { + *cos_max = sysctl.u.psr_cat_op.u.l3_info.cos_max; + *cbm_len = sysctl.u.psr_cat_op.u.l3_info.cbm_len; + } + + return rc; +} /* * Local variables: diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h index 6bbc52d..dd2c28f 100644 --- a/tools/libxl/libxl.h +++ b/tools/libxl/libxl.h @@ -718,6 +718,13 @@ void libxl_mac_copy(libxl_ctx *ctx, libxl_mac *dst, libxl_mac *src); * If this is defined, the Memory Bandwidth Monitoring feature is supported. */ #define LIBXL_HAVE_PSR_MBM 1 + +/* + * LIBXL_HAVE_PSR_CAT + * + * If this is defined, the Cache Allocation Technology feature is supported. + */ +#define LIBXL_HAVE_PSR_CAT 1 #endif typedef char **libxl_string_list; @@ -1501,6 +1508,17 @@ int libxl_psr_cmt_get_sample(libxl_ctx *ctx, uint64_t *tsc_r); #endif +#ifdef LIBXL_HAVE_PSR_CAT +int libxl_psr_cat_set_domain_data(libxl_ctx *ctx, uint32_t domid, + libxl_psr_cat_type type, uint32_t target, + uint64_t data); +int libxl_psr_cat_get_domain_data(libxl_ctx *ctx, uint32_t domid, + libxl_psr_cat_type type, uint32_t target, + uint64_t *data_r); +int libxl_psr_cat_get_l3_info(libxl_ctx *ctx, uint32_t socket, + uint32_t *cos_max_r, uint32_t *cbm_len_r); +#endif + /* misc */ /* Each of these sets or clears the flag according to whether the diff --git a/tools/libxl/libxl_psr.c b/tools/libxl/libxl_psr.c index 3e1c792..645f9f1 100644 --- a/tools/libxl/libxl_psr.c +++ b/tools/libxl/libxl_psr.c @@ -19,7 +19,7 @@ #define IA32_QM_CTR_ERROR_MASK (0x3ul << 62) -static void libxl__psr_cmt_log_err_msg(libxl__gc *gc, int err) +static void libxl__psr_log_err_msg(libxl__gc *gc, int err) { char *msg; @@ -27,6 +27,28 @@ static void libxl__psr_cmt_log_err_msg(libxl__gc *gc, int err) case ENOSYS: msg = "unsupported operation"; break; + case ESRCH: + msg = "invalid domain ID"; + break; + case EBADSLT: + msg = "socket is not supported"; + break; + case EFAULT: + msg = "failed to exchange data with Xen"; + break; + default: + msg = "unknown error"; + break; + } + + LOGE(ERROR, "%s", msg); +} + +static void libxl__psr_cmt_log_err_msg(libxl__gc *gc, int err) +{ + char *msg; + + switch (err) { case ENODEV: msg = "CMT is not supported in this system"; break; @@ -39,15 +61,35 @@ static void libxl__psr_cmt_log_err_msg(libxl__gc *gc, int err) case EUSERS: msg = "no free RMID available"; break; - case ESRCH: - msg = "invalid domain ID"; + default: + libxl__psr_log_err_msg(gc, err); + return; + } + + LOGE(ERROR, "%s", msg); +} + +static void libxl__psr_cat_log_err_msg(libxl__gc *gc, int err) +{ + char *msg; + + switch (err) { + case ENODEV: + msg = "CAT is not supported in this system"; break; - case EFAULT: - msg = "failed to exchange data with Xen"; + case ENOENT: + msg = "CAT is not enabled on the socket"; break; - default: - msg = "unknown error"; + case EUSERS: + msg = "no free COS available"; break; + case EEXIST: + msg = "The same CBM is already set to this domain"; + break; + + default: + libxl__psr_log_err_msg(gc, err); + return; } LOGE(ERROR, "%s", msg); @@ -247,6 +289,56 @@ out: return rc; } +int libxl_psr_cat_set_domain_data(libxl_ctx *ctx, uint32_t domid, + libxl_psr_cat_type type, uint32_t target, + uint64_t data) +{ + GC_INIT(ctx); + int rc; + + rc = xc_psr_cat_set_domain_data(ctx->xch, domid, type, target, data); + if (rc < 0) { + libxl__psr_cat_log_err_msg(gc, errno); + rc = ERROR_FAIL; + } + + GC_FREE; + return rc; +} + +int libxl_psr_cat_get_domain_data(libxl_ctx *ctx, uint32_t domid, + libxl_psr_cat_type type, uint32_t target, + uint64_t *data_r) +{ + GC_INIT(ctx); + int rc; + + rc = xc_psr_cat_get_domain_data(ctx->xch, domid, type, target, data_r); + if (rc < 0) { + libxl__psr_cat_log_err_msg(gc, errno); + rc = ERROR_FAIL; + } + + GC_FREE; + return rc; +} + +int libxl_psr_cat_get_l3_info(libxl_ctx *ctx, uint32_t socket, + uint32_t *cos_max_r, uint32_t *cbm_len_r) +{ + GC_INIT(ctx); + int rc; + + rc = xc_psr_cat_get_l3_info(ctx->xch, socket, cos_max_r, cbm_len_r); + if (rc < 0) { + libxl__psr_cat_log_err_msg(gc, errno); + rc = ERROR_FAIL; + } + + GC_FREE; + return rc; +} + /* * Local variables: * mode: C diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl index 47af340..228f37c 100644 --- a/tools/libxl/libxl_types.idl +++ b/tools/libxl/libxl_types.idl @@ -699,3 +699,7 @@ libxl_psr_cmt_type = Enumeration("psr_cmt_type", [ (2, "TOTAL_MEM_COUNT"), (3, "LOCAL_MEM_COUNT"), ]) + +libxl_psr_cat_type = Enumeration("psr_cat_type", [ + (1, "L3_CBM"), + ]) diff --git a/tools/libxl/xl.h b/tools/libxl/xl.h index 5bc138c..85fa997 100644 --- a/tools/libxl/xl.h +++ b/tools/libxl/xl.h @@ -117,6 +117,10 @@ int main_psr_cmt_attach(int argc, char **argv); int main_psr_cmt_detach(int argc, char **argv); int main_psr_cmt_show(int argc, char **argv); #endif +#ifdef LIBXL_HAVE_PSR_CAT +int main_psr_cat_cbm_set(int argc, char **argv); +int main_psr_cat_show(int argc, char **argv); +#endif void help(const char *command); diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c index 5c40e84..fb0a9a4 100644 --- a/tools/libxl/xl_cmdimpl.c +++ b/tools/libxl/xl_cmdimpl.c @@ -85,6 +85,7 @@ libxl_ctx *ctx; xlchild children[child_max]; +#define ALL_SOCKETS ~0 #define INVALID_DOMID ~0 static const char *common_domname; static int fd_lock = -1; @@ -7824,6 +7825,23 @@ out: return ret; } +static uint32_t get_phy_socket_num(void) +{ + int rc; + uint32_t nr_sockets; + libxl_physinfo info; + libxl_physinfo_init(&info); + rc = libxl_get_physinfo(ctx, &info); + if (rc < 0) { + libxl_physinfo_dispose(&info); + return 0; + } + nr_sockets = info.nr_cpus / info.threads_per_core / info.cores_per_socket; + libxl_physinfo_dispose(&info); + return nr_sockets; + +} + #ifdef LIBXL_HAVE_PSR_CMT #define MBM_SAMPLE_RETRY_MAX 4 @@ -7913,7 +7931,6 @@ static int psr_cmt_show(libxl_psr_cmt_type type, uint32_t domid) { uint32_t i, socketid, nr_sockets, total_rmid; uint32_t l3_cache_size; - libxl_physinfo info; int rc, nr_domains; if (!libxl_psr_cmt_enabled(ctx)) { @@ -7927,15 +7944,11 @@ static int psr_cmt_show(libxl_psr_cmt_type type, uint32_t domid) return -1; } - libxl_physinfo_init(&info); - rc = libxl_get_physinfo(ctx, &info); - if (rc < 0) { - fprintf(stderr, "Failed getting physinfo, rc: %d\n", rc); - libxl_physinfo_dispose(&info); + nr_sockets = get_phy_socket_num(); + if (nr_sockets == 0) { + fprintf(stderr, "Failed getting physinfo\n"); return -1; } - nr_sockets = info.nr_cpus / info.threads_per_core / info.cores_per_socket; - libxl_physinfo_dispose(&info); rc = libxl_psr_cmt_get_total_rmid(ctx, &total_rmid); if (rc < 0) { @@ -8057,6 +8070,202 @@ int main_psr_cmt_show(int argc, char **argv) } #endif +#ifdef LIBXL_HAVE_PSR_CAT +static int psr_cat_l3_cbm_set(uint32_t domid, uint32_t socket, uint64_t cbm) +{ + int rc; + uint32_t i, nr_sockets; + + if (socket != ALL_SOCKETS) { + return libxl_psr_cat_set_domain_data(ctx, domid, + LIBXL_PSR_CAT_TYPE_L3_CBM, + socket, cbm); + } else { + nr_sockets = get_phy_socket_num(); + if (nr_sockets == 0) { + fprintf(stderr, "Failed getting physinfo\n"); + return -1; + } + for (i = 0; i < nr_sockets; i++) { + rc = libxl_psr_cat_set_domain_data(ctx, domid, + LIBXL_PSR_CAT_TYPE_L3_CBM, + i, cbm); + if (rc < 0) { + fprintf(stderr, "Failed to set l3 cbm for socket:%d\n", i); + return -1; + } + } + } + return 0; +} + +struct psr_cat_l3_info +{ + uint32_t cos_max; + uint32_t cbm_len; +}; + +static void psr_cat_print_domain_info(libxl_dominfo *dominfo, + struct psr_cat_l3_info *l3_info, + uint32_t nr_sockets) +{ + char *domain_name; + uint32_t socketid; + uint64_t cbm; + + domain_name = libxl_domid_to_name(ctx, dominfo->domid); + printf("%-40s %5d", domain_name, dominfo->domid); + free(domain_name); + + for (socketid = 0; socketid < nr_sockets; socketid++) { + if (l3_info[socketid].cbm_len > 0 && + !libxl_psr_cat_get_domain_data(ctx, dominfo->domid, + LIBXL_PSR_CAT_TYPE_L3_CBM, + socketid, &cbm) ) + printf("%#16"PRIx64, cbm); + } + + printf("\n"); +} + +static int psr_cat_show(uint32_t domid) +{ + uint32_t i, socketid, nr_sockets; + int rc, nr_domains; + uint32_t l3_cache_size; + struct psr_cat_l3_info *l3_info; + + nr_sockets = get_phy_socket_num(); + if (nr_sockets == 0) { + fprintf(stderr, "Failed getting physinfo\n"); + return -1; + } + + /* Header */ + printf("%-40s %5s", "Name", "ID"); + for (socketid = 0; socketid < nr_sockets; socketid++) + printf("%14s %d", "Socket", socketid); + printf("\n"); + + /* Total L3 cache size */ + printf("%-46s", "Total L3 Cache Size"); + for (socketid = 0; socketid < nr_sockets; socketid++) { + rc = libxl_psr_cmt_get_l3_cache_size(ctx, socketid, &l3_cache_size); + if (rc < 0) { + fprintf(stderr, "Failed to get system l3 cache size for socket:%d\n", + socketid); + return -1; + } + printf("%13u KB", l3_cache_size); + } + printf("\n"); + + /* Max COS and CBM length */ + l3_info = malloc(sizeof(l3_info) * nr_sockets); + //if (!l3_info) + for (socketid = 0; socketid < nr_sockets; socketid++) { + rc = libxl_psr_cat_get_l3_info(ctx, socketid, + &l3_info[socketid].cos_max, + &l3_info[socketid].cbm_len); + if (rc < 0) { + fprintf(stderr, "Failed to get system l3 info for socket:%d\n", + socketid); + rc = -1; + goto out; + } + } + printf("%-46s", "Max COS"); + for (socketid = 0; socketid < nr_sockets; socketid++) { + printf("%16u", l3_info[socketid].cos_max); + } + printf("\n"); + printf("%-46s", "Default CBM"); + for (socketid = 0; socketid < nr_sockets; socketid++) { + printf("%#16"PRIx64, (1ul << l3_info[socketid].cbm_len) - 1); + } + printf("\n"); + + /* Each domain */ + if (domid != INVALID_DOMID) { + libxl_dominfo dominfo; + if (libxl_domain_info(ctx, &dominfo, domid)) { + fprintf(stderr, "Failed to get domain info for %d\n", domid); + rc = -1; + goto out; + } + psr_cat_print_domain_info(&dominfo, l3_info, nr_sockets); + } + else + { + libxl_dominfo *list; + if (!(list = libxl_list_domain(ctx, &nr_domains))) { + fprintf(stderr, "Failed to get domain info for domain list.\n"); + rc = -1; + goto out; + } + for (i = 0; i < nr_domains; i++) + psr_cat_print_domain_info(list + i, l3_info, nr_sockets); + libxl_dominfo_list_free(list, nr_domains); + } + rc = 0; +out: + if (l3_info) + free(l3_info); + return rc; +} + +int main_psr_cat_cbm_set(int argc, char **argv) +{ + uint32_t domid; + uint32_t socket = ALL_SOCKETS; + uint64_t cbm; + char *ptr; + int opt = 0; + + static struct option opts[] = { + {"socket", 0, 0, 's'}, + {0, 0, 0, 0} + }; + + SWITCH_FOREACH_OPT(opt, "s", opts, "psr-cat-cbm-set", 1) { + case 's': + socket = strtol(optarg, NULL, 10); + break; + } + + domid = find_domain(argv[optind]); + ptr = argv[optind + 1]; + if (strlen(ptr) > 2 && ptr[0] == '0' && ptr[1] == 'x') + cbm = strtoll(ptr, NULL , 16); + else + cbm = strtoll(ptr, NULL , 10); + + return psr_cat_l3_cbm_set(domid, socket, cbm); +} + +int main_psr_cat_show(int argc, char **argv) +{ + int opt; + uint32_t domid; + + SWITCH_FOREACH_OPT(opt, "", NULL, "psr-cat-show", 0) { + /* No options */ + } + + if (optind >= argc) + domid = INVALID_DOMID; + else if (optind == argc - 1) + domid = find_domain(argv[optind]); + else { + help("psr-cat-show"); + return 2; + } + + return psr_cat_show(domid); +} + +#endif + /* * Local variables: * mode: C diff --git a/tools/libxl/xl_cmdtable.c b/tools/libxl/xl_cmdtable.c index 22ab63b..ffaf4ed 100644 --- a/tools/libxl/xl_cmdtable.c +++ b/tools/libxl/xl_cmdtable.c @@ -542,6 +542,19 @@ struct cmd_spec cmd_table[] = { "\"total_mem_bandwidth\": Show total memory bandwidth(KB/s)\n" "\"local_mem_bandwidth\": Show local memory bandwidth(KB/s)\n", }, + { "psr-cat-cbm-set", + &main_psr_cat_cbm_set, 0, 1, + "Set cache capacity bitmasks(CBM) for a domain", + "-s Specify the socket to process, all sockets when not" + "specified\n" + " ", + }, + { "psr-cat-show", + &main_psr_cat_show, 0, 1, + "Show Cache Allocation Technology information", + "", + }, + #endif }; -- 1.9.1