This is the toolstack side of the Linux wallclock fixes. A new libxc call, xc_wallclock_sync() is provided and a new command line utility (xen-wallclock) makes use of this. I also considered making libxl call xc_wallclock_sync() during domain creation but wasn''t sure if this was sensible or whether there needed to be an xl configuration option to enable/disable this behaviour. Any comments? David
From: David Vrabel <david.vrabel@citrix.com> xc_wallclock_sync() synchronizes the Xen wallclock to system time. This requires a Linux kernel with a privcmd device that provides the IOCTL_PRIVCMD_SYNC_WALLCLOCK ioctl. Signed-off-by: David Vrabel <david.vrabel@citrix.com> --- tools/include/xen-sys/Linux/privcmd.h | 8 ++++++++ tools/libxc/Makefile | 1 + tools/libxc/xc_linux_osdep.c | 7 +++++++ tools/libxc/xc_wallclock.c | 23 +++++++++++++++++++++++ tools/libxc/xenctrl.h | 5 +++++ tools/libxc/xenctrlosdep.h | 2 ++ 6 files changed, 46 insertions(+), 0 deletions(-) create mode 100644 tools/libxc/xc_wallclock.c diff --git a/tools/include/xen-sys/Linux/privcmd.h b/tools/include/xen-sys/Linux/privcmd.h index d35aac9..55765d1 100644 --- a/tools/include/xen-sys/Linux/privcmd.h +++ b/tools/include/xen-sys/Linux/privcmd.h @@ -76,6 +76,12 @@ typedef struct privcmd_mmapbatch_v2 { * @cmd: IOCTL_PRIVCMD_HYPERCALL * @arg: &privcmd_hypercall_t * Return: Value returned from execution of the specified hypercall. + * + * @cmd: IOCTL_PRIVCMD_SYNC_WALLCLOCK + * @arg: Unused. + * Synchronizes the Xen wallclock with the current system time. + * Return: 0 on success, or -1 on error with errno set to EPERM or + * EACCES. */ #define IOCTL_PRIVCMD_HYPERCALL \ _IOC(_IOC_NONE, ''P'', 0, sizeof(privcmd_hypercall_t)) @@ -85,5 +91,7 @@ typedef struct privcmd_mmapbatch_v2 { _IOC(_IOC_NONE, ''P'', 3, sizeof(privcmd_mmapbatch_t)) #define IOCTL_PRIVCMD_MMAPBATCH_V2 \ _IOC(_IOC_NONE, ''P'', 4, sizeof(privcmd_mmapbatch_v2_t)) +#define IOCTL_PRIVCMD_SYNC_WALLCLOCK \ + _IOC(_IOC_NONE, ''P'', 5, 0) #endif /* __LINUX_PUBLIC_PRIVCMD_H__ */ diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile index d44abf9..601ea4b 100644 --- a/tools/libxc/Makefile +++ b/tools/libxc/Makefile @@ -31,6 +31,7 @@ CTRL_SRCS-y += xc_mem_access.c CTRL_SRCS-y += xc_memshr.c CTRL_SRCS-y += xc_hcall_buf.c CTRL_SRCS-y += xc_foreign_memory.c +CTRL_SRCS-y += xc_wallclock.c CTRL_SRCS-y += xtl_core.c CTRL_SRCS-y += xtl_logger_stdio.c CTRL_SRCS-$(CONFIG_X86) += xc_pagetab.c diff --git a/tools/libxc/xc_linux_osdep.c b/tools/libxc/xc_linux_osdep.c index 787e742..7c73b66 100644 --- a/tools/libxc/xc_linux_osdep.c +++ b/tools/libxc/xc_linux_osdep.c @@ -412,6 +412,11 @@ static void *linux_privcmd_map_foreign_ranges(xc_interface *xch, xc_osdep_handle return ret; } +static int linux_wallclock_sync(xc_interface *xch, xc_osdep_handle h) +{ + return ioctl(h, IOCTL_PRIVCMD_SYNC_WALLCLOCK, NULL); +} + static struct xc_osdep_ops linux_privcmd_ops = { .open = &linux_privcmd_open, .close = &linux_privcmd_close, @@ -426,6 +431,8 @@ static struct xc_osdep_ops linux_privcmd_ops = { .map_foreign_bulk = &linux_privcmd_map_foreign_bulk, .map_foreign_range = &linux_privcmd_map_foreign_range, .map_foreign_ranges = &linux_privcmd_map_foreign_ranges, + + .wallclock_sync = linux_wallclock_sync, }, }; diff --git a/tools/libxc/xc_wallclock.c b/tools/libxc/xc_wallclock.c new file mode 100644 index 0000000..5119b2a --- /dev/null +++ b/tools/libxc/xc_wallclock.c @@ -0,0 +1,23 @@ +/****************************************************************************** + * xc_wallclock.c + * + * API for the wallclock. + * + * Copyright (C) 2012, Citrix Systems (UK) Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + */ + +#include "xc_private.h" + +int xc_wallclock_sync(xc_interface *xch) +{ + if (xch->ops->u.privcmd.wallclock_sync == NULL) { + errno = ENOSYS; + return -1; + } + return xch->ops->u.privcmd.wallclock_sync(xch, xch->ops_handle); +} diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h index 7eb5743..f9bb21b 100644 --- a/tools/libxc/xenctrl.h +++ b/tools/libxc/xenctrl.h @@ -2224,4 +2224,9 @@ int xc_compression_uncompress_page(xc_interface *xch, char *compbuf, unsigned long compbuf_size, unsigned long *compbuf_pos, char *dest); +/** + * Synchronize Xen''s wallclock with the current system time. + */ +int xc_wallclock_sync(xc_interface *xch); + #endif /* XENCTRL_H */ diff --git a/tools/libxc/xenctrlosdep.h b/tools/libxc/xenctrlosdep.h index a36c4aa..3aa3360 100644 --- a/tools/libxc/xenctrlosdep.h +++ b/tools/libxc/xenctrlosdep.h @@ -89,6 +89,8 @@ struct xc_osdep_ops void *(*map_foreign_ranges)(xc_interface *xch, xc_osdep_handle h, uint32_t dom, size_t size, int prot, size_t chunksize, privcmd_mmap_entry_t entries[], int nentries); + + int (*wallclock_sync)(xc_interface *xch, xc_osdep_handle h); } privcmd; struct { int (*fd)(xc_evtchn *xce, xc_osdep_handle h); -- 1.7.2.5
From: David Vrabel <david.vrabel@citrix.com> Add the xen-wallclock command for synchronizing the Xen wallclock to system time. The command is similar to the hwclock command for synchronizing the hardware RTC and takes a similar --systowc command line option. Signed-off-by: David Vrabel <david.vrabel@citrix.com> --- .gitignore | 1 + .hgignore | 1 + tools/misc/Makefile | 8 +++- tools/misc/xen-wallclock.c | 87 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 tools/misc/xen-wallclock.c diff --git a/.gitignore b/.gitignore index f6edc43..a62abd2 100644 --- a/.gitignore +++ b/.gitignore @@ -196,6 +196,7 @@ tools/misc/xc_shadow tools/misc/xen_cpuperf tools/misc/xen-detect tools/misc/xen-tmem-list-parse +tools/misc/xen-wallclock tools/misc/xenperf tools/misc/xenpm tools/misc/xen-hvmctx diff --git a/.hgignore b/.hgignore index 344792a..3b6f747 100644 --- a/.hgignore +++ b/.hgignore @@ -198,6 +198,7 @@ ^tools/misc/xen-hptool$ ^tools/misc/xen-hvmcrash$ ^tools/misc/xen-tmem-list-parse$ +^tools/misc/xen-wallclock$ ^tools/misc/xenperf$ ^tools/misc/xenpm$ ^tools/misc/xen-hvmctx$ diff --git a/tools/misc/Makefile b/tools/misc/Makefile index 22e60fd..456d1ad 100644 --- a/tools/misc/Makefile +++ b/tools/misc/Makefile @@ -9,7 +9,8 @@ CFLAGS += $(CFLAGS_libxenstore) HDRS = $(wildcard *.h) -TARGETS-y := xenperf xenpm xen-tmem-list-parse gtraceview gtracestat xenlockprof xenwatchdogd +TARGETS-y := xenperf xenpm xen-tmem-list-parse gtraceview gtracestat xenlockprof xenwatchdogd \ + xen-wallclock TARGETS-$(CONFIG_X86) += xen-detect xen-hvmctx xen-hvmcrash xen-lowmemd TARGETS-$(CONFIG_MIGRATE) += xen-hptool TARGETS := $(TARGETS-y) @@ -22,7 +23,7 @@ INSTALL_BIN-y := xencons INSTALL_BIN-$(CONFIG_X86) += xen-detect INSTALL_BIN := $(INSTALL_BIN-y) -INSTALL_SBIN-y := xm xen-bugtool xen-python-path xend xenperf xsview xenpm xen-tmem-list-parse gtraceview gtracestat xenlockprof xenwatchdogd xen-ringwatch +INSTALL_SBIN-y := xm xen-bugtool xen-python-path xend xenperf xsview xenpm xen-tmem-list-parse gtraceview gtracestat xenlockprof xenwatchdogd xen-ringwatch xen-wallclock INSTALL_SBIN-$(CONFIG_X86) += xen-hvmctx xen-hvmcrash xen-lowmemd INSTALL_SBIN-$(CONFIG_MIGRATE) += xen-hptool INSTALL_SBIN := $(INSTALL_SBIN-y) @@ -85,4 +86,7 @@ xen-lowmemd: xen-lowmemd.o gtraceview: gtraceview.o $(CC) $(LDFLAGS) -o $@ $< $(CURSES_LIBS) $(APPEND_LDFLAGS) +xen-wallclock: xen-wallclock.o + $(CC) $(LDFLAGS) -o $@ $< $(LDLIBS_libxenctrl) $(APPEND_LDFLAGS) + -include $(DEPS) diff --git a/tools/misc/xen-wallclock.c b/tools/misc/xen-wallclock.c new file mode 100644 index 0000000..e4af166 --- /dev/null +++ b/tools/misc/xen-wallclock.c @@ -0,0 +1,87 @@ +/* + * xen-wallclock.c: manage the Xen wallclock. + * Copyright (C) 2012, Citrix Systems (UK) Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <getopt.h> + +#include <xenctrl.h> + +static const char *exe_name; + +static void usage(FILE *f) +{ + fprintf(f, "Usage: %s --systowc\n", exe_name); +} + +static void help(void) +{ + usage(stdout); + printf("Synchronize the Xen wallclock with system time.\n" + "\n" + " -w, --systowc synchronize wallclock with system time\n" + " --help display this help and exit\n"); + exit(0); +} + +int main(int argc, char *argv[]) +{ + const static char sopts[] = "w"; + const static struct option lopts[] = { + { "help", 0, NULL, 0 }, + { "systowc", 0, NULL, ''w'' }, + { 0, 0, NULL, 0 }, + }; + int opt, opt_idx; + + int systowc = 0; + xc_interface *xch; + + exe_name = argv[0]; + + while ( (opt = getopt_long(argc, argv, sopts, lopts, &opt_idx)) != -1 ) + { + switch ( opt ) + { + case ''w'': + systowc = 1; + break; + case 0: + switch (opt_idx) + { + case 0: + help(); + } + break; + default: + usage(stderr); + exit(1); + } + } + + /* Valid combination of options? i.e., --systowc */ + if (!systowc) + { + usage(stderr); + exit(1); + } + + xch = xc_interface_open(NULL, NULL, 0); + if (xch == NULL) + { + exit(1); + } + xc_wallclock_sync(xch); + xc_interface_close(xch); + + return 0; +} -- 1.7.2.5
On Fri, 2012-10-12 at 14:02 +0100, David Vrabel wrote:> +int main(int argc, char *argv[]) > +{ > + const static char sopts[] = "w"; > + const static struct option lopts[] = { > + { "help", 0, NULL, 0 }, > + { "systowc", 0, NULL, ''w'' }, > + { 0, 0, NULL, 0 }, > + }; > + int opt, opt_idx; > + > + int systowc = 0; > + xc_interface *xch; > + > + exe_name = argv[0]; > + > + while ( (opt = getopt_long(argc, argv, sopts, lopts, &opt_idx)) != -1 ) > + { > + switch ( opt ) > + { > + case ''w'': > + systowc = 1; > + break; > + case 0: > + switch (opt_idx) > + { > + case 0: > + help(); > + } > + break; > + default: > + usage(stderr); > + exit(1); > + } > + } > + > + /* Valid combination of options? i.e., --systowc */ > + if (!systowc) > + { > + usage(stderr); > + exit(1); > + } > + > + xch = xc_interface_open(NULL, NULL, 0); > + if (xch == NULL) > + {I forget: Does xc_interface_open log on error?> + exit(1); > + } > + xc_wallclock_sync(xch);Worth logging if this fails? I suppose we want to hold off on this and the first patch until the Linux side is agreed and committed?> + xc_interface_close(xch); > + > + return 0; > +}
On 15/10/12 10:35, Ian Campbell wrote:> On Fri, 2012-10-12 at 14:02 +0100, David Vrabel wrote: >> +int main(int argc, char *argv[]) >> +{ >> + const static char sopts[] = "w"; >> + const static struct option lopts[] = { >> + { "help", 0, NULL, 0 }, >> + { "systowc", 0, NULL, ''w'' }, >> + { 0, 0, NULL, 0 }, >> + }; >> + int opt, opt_idx; >> + >> + int systowc = 0; >> + xc_interface *xch; >> + >> + exe_name = argv[0]; >> + >> + while ( (opt = getopt_long(argc, argv, sopts, lopts, &opt_idx)) != -1 ) >> + { >> + switch ( opt ) >> + { >> + case ''w'': >> + systowc = 1; >> + break; >> + case 0: >> + switch (opt_idx) >> + { >> + case 0: >> + help(); >> + } >> + break; >> + default: >> + usage(stderr); >> + exit(1); >> + } >> + } >> + >> + /* Valid combination of options? i.e., --systowc */ >> + if (!systowc) >> + { >> + usage(stderr); >> + exit(1); >> + } >> + >> + xch = xc_interface_open(NULL, NULL, 0); >> + if (xch == NULL) >> + { > > I forget: Does xc_interface_open log on error?Yes.>> + exit(1); >> + } >> + xc_wallclock_sync(xch); > > Worth logging if this fails?Yes.> I suppose we want to hold off on this and the first patch until the > Linux side is agreed and committed?Yes.>> + xc_interface_close(xch); >> + >> + return 0; >> +}David