[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v4 5/5] tools: add total/local memory bandwith monitoring
Add Memory Bandwidth Monitoring(MBM) for VMs. Two types of monitoring are supported: total and local memory bandwidth monitoring. To use it, CMT should be enabled in hypervisor. Signed-off-by: Chao Peng <chao.p.peng@xxxxxxxxxxxxxxx> --- Changes in v4: 1. Get timestamp from hypervisor and use that for bandwidth calculation. 2. Minor document and coding style fix. --- docs/man/xl.pod.1 | 9 ++++ tools/libxc/include/xenctrl.h | 5 ++- tools/libxc/xc_msr_x86.h | 1 + tools/libxc/xc_psr.c | 34 ++++++++++++--- tools/libxl/libxl.h | 10 +++++ tools/libxl/libxl_psr.c | 99 +++++++++++++++++++++++++++++++++++++++++-- tools/libxl/libxl_types.idl | 2 + tools/libxl/xl_cmdimpl.c | 33 ++++++++++++--- tools/libxl/xl_cmdtable.c | 4 +- 9 files changed, 182 insertions(+), 15 deletions(-) diff --git a/docs/man/xl.pod.1 b/docs/man/xl.pod.1 index 6b89ba8..50759c0 100644 --- a/docs/man/xl.pod.1 +++ b/docs/man/xl.pod.1 @@ -1461,6 +1461,13 @@ is domain level. To monitor a specific domain, just attach the domain id with the monitoring service. When the domain doesn't need to be monitored any more, detach the domain id from the monitoring service. +Intel Broadwell and later server platforms also offer total/local memory +bandwidth monitoring. Xen supports per-domain monitoring for these two +additional monitoring types. Both memory bandwidth monitoring and L3 cache +occupancy monitoring share the same set of underlying monitoring service. Once +a domain is attached to the monitoring service, monitoring data can be showed +for any of these monitoring types. + =over 4 =item B<psr-cmt-attach> [I<domain-id>] @@ -1476,6 +1483,8 @@ detach: Detach the platform shared resource monitoring service from a domain. Show monitoring data for a certain domain or all domains. Current supported monitor types are: - "cache-occupancy": showing the L3 cache occupancy. + - "total-mem-bandwidth": showing the total memory bandwidth. + - "local-mem-bandwidth": showing the local memory bandwidth. =back diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h index 8a0eab6..8f964ad 100644 --- a/tools/libxc/include/xenctrl.h +++ b/tools/libxc/include/xenctrl.h @@ -2688,6 +2688,8 @@ int xc_resource_op(xc_interface *xch, uint32_t nr_ops, xc_resource_op_t *ops); #if defined(__i386__) || defined(__x86_64__) enum xc_psr_cmt_type { XC_PSR_CMT_L3_OCCUPANCY, + XC_PSR_CMT_TOTAL_MEM_BANDWIDTH, + XC_PSR_CMT_LOCAL_MEM_BANDWIDTH, }; typedef enum xc_psr_cmt_type xc_psr_cmt_type; int xc_psr_cmt_attach(xc_interface *xch, uint32_t domid); @@ -2701,7 +2703,8 @@ int xc_psr_cmt_get_l3_event_mask(xc_interface *xch, uint32_t *event_mask); int xc_psr_cmt_get_l3_cache_size(xc_interface *xch, uint32_t cpu, uint32_t *l3_cache_size); int xc_psr_cmt_get_data(xc_interface *xch, uint32_t rmid, uint32_t cpu, - uint32_t psr_cmt_type, uint64_t *monitor_data); + uint32_t psr_cmt_type, uint64_t *monitor_data, + uint64_t *tsc); int xc_psr_cmt_enabled(xc_interface *xch); #endif diff --git a/tools/libxc/xc_msr_x86.h b/tools/libxc/xc_msr_x86.h index 7c3e1a3..7f100e7 100644 --- a/tools/libxc/xc_msr_x86.h +++ b/tools/libxc/xc_msr_x86.h @@ -20,6 +20,7 @@ #ifndef XC_MSR_X86_H #define XC_MSR_X86_H +#define MSR_IA32_TSC 0x00000010 #define MSR_IA32_CMT_EVTSEL 0x00000c8d #define MSR_IA32_CMT_CTR 0x00000c8e diff --git a/tools/libxc/xc_psr.c b/tools/libxc/xc_psr.c index a9881a4..9f8a4f9 100644 --- a/tools/libxc/xc_psr.c +++ b/tools/libxc/xc_psr.c @@ -23,6 +23,8 @@ #define IA32_CMT_CTR_ERROR_MASK (0x3ull << 62) #define EVTID_L3_OCCUPANCY 0x1 +#define EVTID_TOTAL_MEM_BANDWIDTH 0x2 +#define EVTID_LOCAL_MEM_BANDWIDTH 0x3 int xc_psr_cmt_attach(xc_interface *xch, uint32_t domid) { @@ -156,11 +158,12 @@ int xc_psr_cmt_get_l3_cache_size(xc_interface *xch, uint32_t cpu, } int xc_psr_cmt_get_data(xc_interface *xch, uint32_t rmid, uint32_t cpu, - xc_psr_cmt_type type, uint64_t *monitor_data) + xc_psr_cmt_type type, uint64_t *monitor_data, + uint64_t *tsc) { xc_resource_op_t op; - xc_resource_entry_t entries[2]; - uint32_t evtid; + xc_resource_entry_t entries[3]; + uint32_t evtid, nr_entries; int rc; switch ( type ) @@ -168,6 +171,12 @@ int xc_psr_cmt_get_data(xc_interface *xch, uint32_t rmid, uint32_t cpu, case XC_PSR_CMT_L3_OCCUPANCY: evtid = EVTID_L3_OCCUPANCY; break; + case XC_PSR_CMT_TOTAL_MEM_BANDWIDTH: + evtid = EVTID_TOTAL_MEM_BANDWIDTH; + break; + case XC_PSR_CMT_LOCAL_MEM_BANDWIDTH: + evtid = EVTID_LOCAL_MEM_BANDWIDTH; + break; default: return -1; } @@ -182,19 +191,34 @@ int xc_psr_cmt_get_data(xc_interface *xch, uint32_t rmid, uint32_t cpu, entries[1].val = 0; entries[1].rsvd = 0; + if ( type == XC_PSR_CMT_L3_OCCUPANCY ) + nr_entries = 2; + else + { + entries[2].u.cmd = XEN_RESOURCE_OP_MSR_READ; + entries[2].idx = MSR_IA32_TSC; + entries[2].val = 0; + entries[2].rsvd = 0; + nr_entries = 3; + } + op.cpu = cpu; - op.nr_entries = 2; + op.nr_entries = nr_entries; op.entries = entries; rc = xc_resource_op(xch, 1, &op); if ( rc < 0 ) return rc; - if ( op.result !=2 || entries[1].val & IA32_CMT_CTR_ERROR_MASK ) + if ( op.result != nr_entries || entries[1].val & IA32_CMT_CTR_ERROR_MASK ) return -1; *monitor_data = entries[1].val; + if ( type == XC_PSR_CMT_TOTAL_MEM_BANDWIDTH || + type == XC_PSR_CMT_LOCAL_MEM_BANDWIDTH ) + *tsc = entries[2].val; + return 0; } diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h index 596d2a0..789560f 100644 --- a/tools/libxl/libxl.h +++ b/tools/libxl/libxl.h @@ -1462,6 +1462,16 @@ int libxl_psr_cmt_get_cache_occupancy(libxl_ctx *ctx, uint32_t domid, uint32_t socketid, uint32_t *l3_cache_occupancy); +int libxl_psr_cmt_get_total_mem_bandwidth(libxl_ctx *ctx, + uint32_t domid, + uint32_t socketid, + uint32_t cpu_khz, + uint32_t *bandwidth); +int libxl_psr_cmt_get_local_mem_bandwidth(libxl_ctx *ctx, + uint32_t domid, + uint32_t socketid, + uint32_t cpu_khz, + uint32_t *bandwidth); #endif /* misc */ diff --git a/tools/libxl/libxl_psr.c b/tools/libxl/libxl_psr.c index c88c421..b1a0412 100644 --- a/tools/libxl/libxl_psr.c +++ b/tools/libxl/libxl_psr.c @@ -18,6 +18,7 @@ #define IA32_QM_CTR_ERROR_MASK (0x3ul << 62) +#define MBM_SAMPLE_RETRY_MAX 4 static void libxl__psr_cmt_log_err_msg(libxl__gc *gc, int err) { @@ -180,7 +181,8 @@ static int libxl__psr_cmt_get_l3_monitoring_data(libxl__gc *gc, uint32_t domid, xc_psr_cmt_type type, uint32_t socketid, - uint64_t *data) + uint64_t *data, + uint64_t *tsc) { unsigned int rmid; int cpu, rc; @@ -200,7 +202,7 @@ static int libxl__psr_cmt_get_l3_monitoring_data(libxl__gc *gc, goto out; } - rc = xc_psr_cmt_get_data(CTX->xch, rmid, cpu, type, data); + rc = xc_psr_cmt_get_data(CTX->xch, rmid, cpu, type, data, tsc); if (rc < 0) { LOGE(ERROR, "failed to get monitoring data"); rc = ERROR_FAIL; @@ -222,7 +224,7 @@ int libxl_psr_cmt_get_cache_occupancy(libxl_ctx *ctx, rc = libxl__psr_cmt_get_l3_monitoring_data(gc, domid, XC_PSR_CMT_L3_OCCUPANCY, - socketid, &data); + socketid, &data, NULL); if (rc < 0) goto out; @@ -240,6 +242,101 @@ out: return rc; } +static int libxl__psr_cmt_get_mem_bandwidth(libxl__gc *gc, + uint32_t domid, + xc_psr_cmt_type type, + uint32_t socketid, + uint32_t cpu_khz, + uint32_t *bandwidth) +{ + uint64_t sample1, sample2; + uint64_t tsc1, tsc2; + uint32_t upscaling_factor; + int retry_attempts = 0; + int rc; + + while (1) { + rc = libxl__psr_cmt_get_l3_monitoring_data(gc, domid, type, socketid, + &sample1, &tsc1); + if (rc < 0) { + rc = ERROR_FAIL; + goto out; + } + + usleep(10000); + + rc = libxl__psr_cmt_get_l3_monitoring_data(gc, domid, type, socketid, + &sample2, &tsc2); + if (rc < 0) { + rc = ERROR_FAIL; + goto out; + } + if (tsc2 <= tsc1) { + rc = ERROR_FAIL; + goto out; + } + /* + * Hardware guarantees at most 1 overflow can happen if the duration + * between two samples is less than 1 second. + */ + if (tsc2 - tsc1 < cpu_khz * 1000 && sample2 >= sample1) + break; + + if (retry_attempts < MBM_SAMPLE_RETRY_MAX) { + retry_attempts++; + } else { + LOGE(ERROR, "event counter overflowed"); + rc = ERROR_FAIL; + goto out; + } + + } + + rc = xc_psr_cmt_get_l3_upscaling_factor(CTX->xch, &upscaling_factor); + if (rc < 0) { + LOGE(ERROR, "failed to get L3 upscaling factor"); + rc = ERROR_FAIL; + goto out; + } + + *bandwidth = (sample2 - sample1) * 1000 * cpu_khz / (tsc2 - tsc1) + * upscaling_factor / 1024; +out: + return rc; +} + +int libxl_psr_cmt_get_total_mem_bandwidth(libxl_ctx *ctx, + uint32_t domid, + uint32_t socketid, + uint32_t cpu_khz, + uint32_t *bandwidth) +{ + GC_INIT(ctx); + int rc; + + rc = libxl__psr_cmt_get_mem_bandwidth(gc, domid, + XC_PSR_CMT_TOTAL_MEM_BANDWIDTH, + socketid, cpu_khz, bandwidth); + GC_FREE; + return rc; +} + +int libxl_psr_cmt_get_local_mem_bandwidth(libxl_ctx *ctx, + uint32_t domid, + uint32_t socketid, + uint32_t cpu_khz, + uint32_t *bandwidth) +{ + GC_INIT(ctx); + int rc; + + rc = libxl__psr_cmt_get_mem_bandwidth(gc, domid, + XC_PSR_CMT_LOCAL_MEM_BANDWIDTH, + socketid, cpu_khz, bandwidth); + GC_FREE; + return rc; +} + /* * Local variables: * mode: C diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl index 1214d2e..46d160e 100644 --- a/tools/libxl/libxl_types.idl +++ b/tools/libxl/libxl_types.idl @@ -694,4 +694,6 @@ libxl_event = Struct("event",[ libxl_psr_cmt_type = Enumeration("psr_cmt_type", [ (1, "CACHE_OCCUPANCY"), + (2, "TOTAL_MEM_BANDWIDTH"), + (3, "LOCAL_MEM_BANDWIDTH"), ]) diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c index 1827c63..da7443e 100644 --- a/tools/libxl/xl_cmdimpl.c +++ b/tools/libxl/xl_cmdimpl.c @@ -7809,7 +7809,8 @@ out: #ifdef LIBXL_HAVE_PSR_CMT static void psr_cmt_print_domain_l3_info(libxl_dominfo *dominfo, libxl_psr_cmt_type type, - uint32_t nr_sockets) + uint32_t nr_sockets, + uint32_t cpu_khz) { char *domain_name; uint32_t socketid; @@ -7829,6 +7830,18 @@ static void psr_cmt_print_domain_l3_info(libxl_dominfo *dominfo, socketid, &data)) printf("%13u KB", data); break; + case LIBXL_PSR_CMT_TYPE_TOTAL_MEM_BANDWIDTH: + if (!libxl_psr_cmt_get_total_mem_bandwidth(ctx, dominfo->domid, + socketid, cpu_khz, + &data)) + printf("%11u KB/s", data); + break; + case LIBXL_PSR_CMT_TYPE_LOCAL_MEM_BANDWIDTH: + if (!libxl_psr_cmt_get_local_mem_bandwidth(ctx, dominfo->domid, + socketid, cpu_khz, + &data)) + printf("%11u KB/s", data); + break; default: return; } @@ -7839,8 +7852,8 @@ static void psr_cmt_print_domain_l3_info(libxl_dominfo *dominfo, static int psr_cmt_show_l3_info(libxl_psr_cmt_type type, uint32_t domid) { - uint32_t i, socketid, nr_sockets, total_rmid; - uint32_t l3_cache_size; + uint32_t i, socketid, nr_sockets, total_rmid, cpu_khz; + uint32_t l3_cache_size, l3_event_mask; libxl_physinfo info; int rc, nr_domains; @@ -7849,6 +7862,13 @@ static int psr_cmt_show_l3_info(libxl_psr_cmt_type type, uint32_t domid) return -1; } + rc = libxl_psr_cmt_get_l3_event_mask(ctx, &l3_event_mask); + if (rc < 0 || !(l3_event_mask & (1 << (type - 1)))) { + fprintf(stderr, "Monitor type '%s' is not supported in the system\n", + libxl_psr_cmt_type_to_string(type)); + return -1; + } + libxl_physinfo_init(&info); rc = libxl_get_physinfo(ctx, &info); if (rc < 0) { @@ -7857,6 +7877,7 @@ static int psr_cmt_show_l3_info(libxl_psr_cmt_type type, uint32_t domid) return -1; } nr_sockets = info.nr_cpus / info.threads_per_core / info.cores_per_socket; + cpu_khz = info.cpu_khz; libxl_physinfo_dispose(&info); rc = libxl_psr_cmt_get_total_rmid(ctx, &total_rmid); @@ -7897,7 +7918,7 @@ static int psr_cmt_show_l3_info(libxl_psr_cmt_type type, uint32_t domid) fprintf(stderr, "Failed to get domain info for %d\n", domid); return -1; } - psr_cmt_print_domain_l3_info(&dominfo, type, nr_sockets); + psr_cmt_print_domain_l3_info(&dominfo, type, nr_sockets, cpu_khz); } else { @@ -7907,7 +7928,7 @@ static int psr_cmt_show_l3_info(libxl_psr_cmt_type type, uint32_t domid) return -1; } for (i = 0; i < nr_domains; i++) - psr_cmt_print_domain_l3_info(list + i, type, nr_sockets); + psr_cmt_print_domain_l3_info(list + i, type, nr_sockets, cpu_khz); libxl_dominfo_list_free(list, nr_domains); } return 0; @@ -7966,6 +7987,8 @@ int main_psr_cmt_show(int argc, char **argv) switch (type) { case LIBXL_PSR_CMT_TYPE_CACHE_OCCUPANCY: + case LIBXL_PSR_CMT_TYPE_TOTAL_MEM_BANDWIDTH: + case LIBXL_PSR_CMT_TYPE_LOCAL_MEM_BANDWIDTH: ret = psr_cmt_show_l3_info(type, domid); break; default: diff --git a/tools/libxl/xl_cmdtable.c b/tools/libxl/xl_cmdtable.c index 4b30d3d..2d8f272 100644 --- a/tools/libxl/xl_cmdtable.c +++ b/tools/libxl/xl_cmdtable.c @@ -538,7 +538,9 @@ struct cmd_spec cmd_table[] = { "Show Cache Monitoring Technology information", "<PSR-CMT-Type> <Domain>", "Available monitor types:\n" - "\"cache_occupancy\": Show L3 cache occupancy\n", + "\"cache_occupancy\": Show L3 cache occupancy\n" + "\"total_mem_bandwidth\": Show total memory bandwidth\n" + "\"local_mem_bandwidth\": Show local memory bandwidth\n", }, #endif }; -- 1.9.1 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |