[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [RFC PATCH v3 3/3] tools/misc: Add xen-vcpus-stats tool
Add a demonstration tool that uses the stats_table resource to query vcpus' RUNSTATE_running counter for a DomU. Signed-off-by: Matias Ezequiel Vara Larsen <matias.vara@xxxxxxxx> --- Changes in v3: - use memory layout as discussed at https://lists.xenproject.org/archives/html/xen-devel/2023-03/msg00383.html - use virt_*() - issue xenforeignmemory_close() Changes in v2: - use period instead of frec - rely on version to ensure reading is coherent Changes in v1: - change the name of the tool to xen-vcpus-stats - set command line parameters in the same order that are passed - remove header libs.h - build by default - remove errno, strerrno, "\n", and identation - use errx when errno is not needed - address better the number of pages requested and error msgs - use the shared_vcpustatspage_t structure - use the correct frame id when requesting the resource --- tools/misc/Makefile | 6 ++ tools/misc/xen-vcpus-stats.c | 132 +++++++++++++++++++++++++++++++++++ 2 files changed, 138 insertions(+) create mode 100644 tools/misc/xen-vcpus-stats.c diff --git a/tools/misc/Makefile b/tools/misc/Makefile index 8b9558b93f..9c7cb50483 100644 --- a/tools/misc/Makefile +++ b/tools/misc/Makefile @@ -51,6 +51,7 @@ TARGETS_COPY += xenpvnetboot # Everything which needs to be built TARGETS_BUILD := $(filter-out $(TARGETS_COPY),$(TARGETS_ALL)) +TARGETS_BUILD += xen-vcpus-stats # ... including build-only targets TARGETS_BUILD += $(TARGETS_BUILD-y) @@ -139,4 +140,9 @@ xencov: xencov.o xen-ucode: xen-ucode.o $(CC) $(LDFLAGS) -o $@ $< $(LDLIBS_libxenctrl) $(APPEND_LDFLAGS) +xen-vcpus-stats.o: CFLAGS += $(CFLAGS_libxenforeginmemory) + +xen-vcpus-stats: xen-vcpus-stats.o + $(CC) $(LDFLAGS) -o $@ $< $(LDLIBS_libxenctrl) $(LDLIBS_libxenforeignmemory) $(APPEND_LDFLAGS) + -include $(DEPS_INCLUDE) diff --git a/tools/misc/xen-vcpus-stats.c b/tools/misc/xen-vcpus-stats.c new file mode 100644 index 0000000000..f277b6ce8f --- /dev/null +++ b/tools/misc/xen-vcpus-stats.c @@ -0,0 +1,132 @@ +#include <err.h> +#include <errno.h> +#include <error.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/mman.h> +#include <signal.h> + +#include <xenctrl.h> +#include <xenforeignmemory.h> +#include <xen/vcpu.h> + +/* + * Note that virt_*() is used when ordering is required between the hypevisor + * and the tool domain. This tool is meant to be arch-agnostic so add the + * corresponding barrier for each architecture. + * + */ +#if defined(__x86_64__) +#define barrier() asm volatile("" ::: "memory") +#define virt_rmb() barrier() +#elif defined(__aarch64__) +#define dmb(opt) asm volatile("dmb " #opt : : : "memory") +#define virt_rmb() dmb(ishld) +#else +#error Please fill in barrier macros +#endif + +static sig_atomic_t interrupted; +static void close_handler(int signum) +{ + interrupted = 1; +} + +int main(int argc, char **argv) +{ + xenforeignmemory_handle *fh; + xenforeignmemory_resource_handle *res; + size_t size; + int rc, domid, period, vcpu; + xen_vcpu_shmemstats_t *info_shmem; + xen_shared_vcpustats_t *info; + struct sigaction act; + uint32_t seq; + uint64_t value; + + if ( argc != 4 ) + { + fprintf(stderr, "Usage: %s <domid> <vcpu> <period>\n", argv[0]); + return 1; + } + + domid = atoi(argv[1]); + vcpu = atoi(argv[2]); + period = atoi(argv[3]); + + act.sa_handler = close_handler; + act.sa_flags = 0; + sigemptyset(&act.sa_mask); + sigaction(SIGHUP, &act, NULL); + sigaction(SIGTERM, &act, NULL); + sigaction(SIGINT, &act, NULL); + sigaction(SIGALRM, &act, NULL); + + fh = xenforeignmemory_open(NULL, 0); + + if ( !fh ) + err(1, "xenforeignmemory_open"); + + rc = xenforeignmemory_resource_size( + fh, domid, XENMEM_resource_stats_table, + XENMEM_resource_stats_table_id_vcpustats, &size); + + if ( rc ) + err(1, "Fail: Get size"); + + res = xenforeignmemory_map_resource( + fh, domid, XENMEM_resource_stats_table, + XENMEM_resource_stats_table_id_vcpustats, 0, size >> XC_PAGE_SHIFT, + (void **)&info_shmem, PROT_READ, 0); + + if ( !res ) + err(1, "Fail: Map"); + + if ( info_shmem->magic != VCPU_STATS_MAGIC ) + { + fprintf(stderr, "Wrong magic number\n"); + return 1; + } + + if ( offsetof(struct vcpu_stats, runstate_running_time) > info_shmem->size ) + { + fprintf(stderr, "The counter is not produced\n"); + return 1; + } + + info = (xen_shared_vcpustats_t*)((void*)info_shmem + + info_shmem->offset + + info_shmem->size * vcpu); + + if ( info->runstate_running_time & ((uint64_t)1 << 63) ) + { + fprintf(stderr, "The counter is inactived or has overflowed\n"); + return 1; + } + + while ( !interrupted ) + { + sleep(period); + do { + seq = info[vcpu].seq; + virt_rmb(); + value = info[vcpu].runstate_running_time; + virt_rmb(); + } while ( (info[vcpu].seq & 1) || + (seq != info[vcpu].seq) ); + if ( value & ((uint64_t)1 << 63) ) + break; + printf("running_vcpu_time[%d]: %ld\n", vcpu, value); + } + + rc = xenforeignmemory_unmap_resource(fh, res); + if ( rc ) + err(1, "Fail: Unmap"); + + rc = xenforeignmemory_close(fh); + if ( rc ) + err(1, "Fail: Close"); + + return 0; +} -- 2.34.1
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |