[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH] libxc/xentrace: Replace xc_tbuf_set_cpu_mask with CPU mask with xc_cpumap_t instead of uint32_t
We replace the implementation of xc_tbuf_set_cpu_mask with an xc_cpumap_t instead of a uint32_t. This means we can use an arbitrary bitmap without being limited to the 32-bits as previously we were. Furthermore since there is only one user of xc_tbuf_set_cpu_mask we just replace it and its user in one go. We also add an macro which can be used by both libxc and xentrace. And update the man page to describe this behavior. Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@xxxxxxxxxx> Acked-by: Ian Campbell <Ian.Campbell@xxxxxxxxxx> [libxc pieces] --- tools/libxc/include/xenctrl.h | 7 ++- tools/libxc/xc_tbuf.c | 26 +++++++---- tools/xentrace/xentrace.8 | 3 ++ tools/xentrace/xentrace.c | 106 ++++++++++++++++++++++++++++++++++++------ 4 files changed, 116 insertions(+), 26 deletions(-) diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h index df18292..713e52b 100644 --- a/tools/libxc/include/xenctrl.h +++ b/tools/libxc/include/xenctrl.h @@ -1534,6 +1534,11 @@ int xc_availheap(xc_interface *xch, int min_width, int max_width, int node, */ /** + * Useful macro for converting byte arrays to bitmaps. + */ +#define XC_DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) + +/** * xc_tbuf_enable - enable tracing buffers * * @parm xch a handle to an open hypervisor interface @@ -1574,7 +1579,7 @@ int xc_tbuf_set_size(xc_interface *xch, unsigned long size); */ int xc_tbuf_get_size(xc_interface *xch, unsigned long *size); -int xc_tbuf_set_cpu_mask(xc_interface *xch, uint32_t mask); +int xc_tbuf_set_cpu_mask(xc_interface *xch, xc_cpumap_t mask, int bits); int xc_tbuf_set_evt_mask(xc_interface *xch, uint32_t mask); diff --git a/tools/libxc/xc_tbuf.c b/tools/libxc/xc_tbuf.c index 8777492..d54da8a 100644 --- a/tools/libxc/xc_tbuf.c +++ b/tools/libxc/xc_tbuf.c @@ -113,15 +113,23 @@ int xc_tbuf_disable(xc_interface *xch) return tbuf_enable(xch, 0); } -int xc_tbuf_set_cpu_mask(xc_interface *xch, uint32_t mask) +int xc_tbuf_set_cpu_mask(xc_interface *xch, xc_cpumap_t mask, int bits) { DECLARE_SYSCTL; - DECLARE_HYPERCALL_BUFFER(uint8_t, bytemap); + DECLARE_HYPERCALL_BOUNCE(mask, XC_DIV_ROUND_UP(bits, 8), XC_HYPERCALL_BUFFER_BOUNCE_IN); int ret = -1; - uint64_t mask64 = mask; + int local_bits; - bytemap = xc_hypercall_buffer_alloc(xch, bytemap, sizeof(mask64)); - if ( bytemap == NULL ) + if ( bits <= 0 ) + goto out; + + local_bits = xc_get_max_cpus(xch); + if ( bits > local_bits ) + { + PERROR("Wrong amount of bits supplied: %d > %d!\n", bits, local_bits); + goto out; + } + if ( xc_hypercall_bounce_pre(xch, mask) ) { PERROR("Could not allocate memory for xc_tbuf_set_cpu_mask hypercall"); goto out; @@ -131,14 +139,12 @@ int xc_tbuf_set_cpu_mask(xc_interface *xch, uint32_t mask) sysctl.interface_version = XEN_SYSCTL_INTERFACE_VERSION; sysctl.u.tbuf_op.cmd = XEN_SYSCTL_TBUFOP_set_cpu_mask; - bitmap_64_to_byte(bytemap, &mask64, sizeof (mask64) * 8); - - set_xen_guest_handle(sysctl.u.tbuf_op.cpu_mask.bitmap, bytemap); - sysctl.u.tbuf_op.cpu_mask.nr_bits = sizeof(bytemap) * 8; + set_xen_guest_handle(sysctl.u.tbuf_op.cpu_mask.bitmap, mask); + sysctl.u.tbuf_op.cpu_mask.nr_bits = bits; ret = do_sysctl(xch, &sysctl); - xc_hypercall_buffer_free(xch, bytemap); + xc_hypercall_bounce_post(xch, mask); out: return ret; diff --git a/tools/xentrace/xentrace.8 b/tools/xentrace/xentrace.8 index ac18e9f..c176a96 100644 --- a/tools/xentrace/xentrace.8 +++ b/tools/xentrace/xentrace.8 @@ -38,6 +38,9 @@ for new data. .TP .B -c, --cpu-mask=c set bitmask of CPUs to trace. It is limited to 32-bits. +If not specified, the cpu-mask of all of the available CPUs will be +constructed. + .TP .B -e, --evt-mask=e set event capture mask. If not specified the TRC_ALL will be used. diff --git a/tools/xentrace/xentrace.c b/tools/xentrace/xentrace.c index 8a38e32..f515bd2 100644 --- a/tools/xentrace/xentrace.c +++ b/tools/xentrace/xentrace.c @@ -52,7 +52,8 @@ typedef struct settings_st { char *outfile; unsigned long poll_sleep; /* milliseconds to sleep between polls */ uint32_t evt_mask; - uint32_t cpu_mask; + xc_cpumap_t cpu_mask; + int cpu_bits; unsigned long tbuf_size; unsigned long disk_rsvd; unsigned long timeout; @@ -521,23 +522,68 @@ static struct t_struct *map_tbufs(unsigned long tbufs_mfn, unsigned int num, return &tbufs; } +void print_cpu_mask(xc_cpumap_t mask, int bits) +{ + unsigned int v, had_printed = 0; + int i; + + fprintf(stderr, "change cpumask to 0x"); + + for ( i = XC_DIV_ROUND_UP(bits, 8); i >= 0; i-- ) + { + v = mask[i]; + if ( v || had_printed || !i ) { + fprintf(stderr,"%x", v); + had_printed = 1; + } + } + fprintf(stderr, "\n"); +} + +static void set_cpu_mask(xc_cpumap_t mask, int bits) +{ + int i, ret = 0; + + if ( bits <= 0 ) + { + bits = xc_get_max_cpus(xc_handle); + if ( bits <= 0 ) + goto out; + } + if ( !mask ) + { + mask = xc_cpumap_alloc(xc_handle); + if ( !mask ) + goto out; + + /* Set it to include _all_ CPUs. */ + for ( i = 0; i < XC_DIV_ROUND_UP(bits, 8); i++ ) + mask[i] = 0xff; + } + /* And this will limit it to the exact amount of bits. */ + ret = xc_tbuf_set_cpu_mask(xc_handle, mask, bits); + if ( ret != 0 ) + goto out; + + print_cpu_mask(mask, bits); + return; +out: + PERROR("Failure to get trace buffer pointer from Xen and set the new mask"); + exit(EXIT_FAILURE); +} + /** - * set_mask - set the cpu/event mask in HV + * set_mask - set the event mask in HV * @mask: the new mask * @type: the new mask type,0-event mask, 1-cpu mask * */ -static void set_mask(uint32_t mask, int type) +static void set_evt_mask(uint32_t mask) { int ret = 0; - if (type == 1) { - ret = xc_tbuf_set_cpu_mask(xc_handle, mask); - fprintf(stderr, "change cpumask to 0x%x\n", mask); - } else if (type == 0) { - ret = xc_tbuf_set_evt_mask(xc_handle, mask); - fprintf(stderr, "change evtmask to 0x%x\n", mask); - } + ret = xc_tbuf_set_evt_mask(xc_handle, mask); + fprintf(stderr, "change evtmask to 0x%x\n", mask); if ( ret != 0 ) { @@ -906,6 +952,28 @@ static int parse_evtmask(char *arg) return 0; } +static int parse_cpumask(const char *arg) +{ + xc_cpumap_t map; + uint32_t v, i; + int bits = 0; + + map = malloc(sizeof(uint32_t)); + if ( !map ) + return -ENOMEM; + + v = argtol(arg, 0); + for ( i = 0; i < sizeof(uint32_t) ; i++ ) + map[i] = (v >> (i * 8)) & 0xff; + + for ( i = 0; v; v >>= 1) + bits += v & 1; + + opts.cpu_mask = map; + opts.cpu_bits = bits; + return 0; +} + /* parse command line arguments */ static void parse_args(int argc, char **argv) { @@ -937,7 +1005,12 @@ static void parse_args(int argc, char **argv) break; case 'c': /* set new cpu mask for filtering*/ - opts.cpu_mask = argtol(optarg, 0); + /* Set opts.cpu_mask later as we don't have 'xch' set yet. */ + if ( parse_cpumask(optarg) ) + { + perror("Not enough memory!"); + exit(EXIT_FAILURE); + } break; case 'e': /* set new event mask for filtering*/ @@ -1002,7 +1075,8 @@ int main(int argc, char **argv) opts.outfile = 0; opts.poll_sleep = POLL_SLEEP_MILLIS; opts.evt_mask = 0; - opts.cpu_mask = 0; + opts.cpu_mask = NULL; + opts.cpu_bits = 0; opts.disk_rsvd = 0; opts.disable_tracing = 1; opts.start_disabled = 0; @@ -1018,10 +1092,12 @@ int main(int argc, char **argv) } if ( opts.evt_mask != 0 ) - set_mask(opts.evt_mask, 0); + set_evt_mask(opts.evt_mask); + - if ( opts.cpu_mask != 0 ) - set_mask(opts.cpu_mask, 1); + set_cpu_mask(opts.cpu_mask, opts.cpu_bits); + /* We don't use it pass this point. */ + free(opts.cpu_mask); if ( opts.timeout != 0 ) alarm(opts.timeout); -- 2.1.0 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |