|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v5 6/6] tools, docs: 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 v5:
1. Add MBM description in xen command line.
2. Use the tsc from hypervisor directly which is already ns.
3. Call resource_op with DISABLE_IRQ flag.
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 ++++
docs/misc/xen-command-line.markdown | 3 ++
tools/libxc/include/xenctrl.h | 5 +-
tools/libxc/xc_msr_x86.h | 1 +
tools/libxc/xc_psr.c | 37 +++++++++++--
tools/libxl/libxl.h | 8 +++
tools/libxl/libxl_psr.c | 101 ++++++++++++++++++++++++++++++++++--
tools/libxl/libxl_types.idl | 2 +
tools/libxl/xl_cmdimpl.c | 21 +++++++-
tools/libxl/xl_cmdtable.c | 4 +-
10 files changed, 180 insertions(+), 11 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/docs/misc/xen-command-line.markdown
b/docs/misc/xen-command-line.markdown
index a061aa4..0491dbb 100644
--- a/docs/misc/xen-command-line.markdown
+++ b/docs/misc/xen-command-line.markdown
@@ -1097,6 +1097,9 @@ The following resources are available:
L3 cache occupancy.
* `cmt` instructs Xen to enable/disable Cache Monitoring Technology.
* `rmid_max` indicates the max value for rmid.
+* Memory Bandwidth Monitoring (Broadwell and later). Information regarding the
+ total/local memory bandwidth. Follow the same options with Cache Monitoring
+ Technology.
### reboot
> `= t[riple] | k[bd] | a[cpi] | p[ci] | n[o] [, [w]arm | [c]old]`
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 368aeb0..fda6128 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,37 @@ int xc_psr_cmt_get_data(xc_interface *xch, uint32_t rmid,
uint32_t cpu,
entries[1].val = 0;
entries[1].flags = 0;
+ if ( type == XC_PSR_CMT_L3_OCCUPANCY )
+ nr_entries = 2;
+ else
+ {
+ entries[1].flags = XEN_RESOURCE_ENTRY_FLAGS_DISABLE_IRQ;
+
+ entries[2].u.cmd = XEN_RESOURCE_OP_MSR_READ;
+ entries[2].idx = MSR_IA32_TSC;
+ entries[2].val = 0;
+ entries[2].flags = 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..347ef52 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -1462,6 +1462,14 @@ 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 *bandwidth);
+int libxl_psr_cmt_get_local_mem_bandwidth(libxl_ctx *ctx,
+ uint32_t domid,
+ uint32_t socketid,
+ uint32_t *bandwidth);
#endif
/* misc */
diff --git a/tools/libxl/libxl_psr.c b/tools/libxl/libxl_psr.c
index c88c421..4c8bcc8 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,99 @@ 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 *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. Note that tsc returned
+ * from hypervisor is already-scaled time(ns).
+ */
+ if (tsc2 - tsc1 < 1000000000 && 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) * 1000000000 / (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 *bandwidth)
+{
+ GC_INIT(ctx);
+ int rc;
+
+ rc = libxl__psr_cmt_get_mem_bandwidth(gc, domid,
+ XC_PSR_CMT_TOTAL_MEM_BANDWIDTH,
+ socketid, bandwidth);
+ GC_FREE;
+ return rc;
+}
+
+int libxl_psr_cmt_get_local_mem_bandwidth(libxl_ctx *ctx,
+ uint32_t domid,
+ uint32_t socketid,
+ uint32_t *bandwidth)
+{
+ GC_INIT(ctx);
+ int rc;
+
+ rc = libxl__psr_cmt_get_mem_bandwidth(gc, domid,
+ XC_PSR_CMT_LOCAL_MEM_BANDWIDTH,
+ socketid, 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..6d5c7af 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -7829,6 +7829,16 @@ 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, &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, &data))
+ printf("%11u KB/s", data);
+ break;
default:
return;
}
@@ -7840,7 +7850,7 @@ 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 l3_cache_size, l3_event_mask;
libxl_physinfo info;
int rc, nr_domains;
@@ -7849,6 +7859,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) {
@@ -7966,6 +7983,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 |