[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] Allow guests to register secondary vcpu_time_info
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1255949916 -3600 # Node ID ad2fd7b94bd32e4256640a908ca3c8b40f505021 # Parent 5f28661bb2bbfd903b79d52e2aeabc4e4cb1f4d8 Allow guests to register secondary vcpu_time_info Allow a guest to register a second location for the VCPU time info structure for each vcpu. This is intended to allow the guest kernel to map this information into a usermode accessible page, so that usermode can efficiently calculate system time from the TSC without having to make a syscall. Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@xxxxxxxxxx> Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx> --- xen/arch/x86/domain.c | 19 +++++++ xen/arch/x86/time.c | 107 ++++++++++++++++++++++++++++--------------- xen/include/asm-x86/domain.h | 4 + xen/include/asm-x86/time.h | 2 xen/include/public/vcpu.h | 28 +++++++++++ 5 files changed, 125 insertions(+), 35 deletions(-) diff -r 5f28661bb2bb -r ad2fd7b94bd3 xen/arch/x86/domain.c --- a/xen/arch/x86/domain.c Mon Oct 19 10:57:58 2009 +0100 +++ b/xen/arch/x86/domain.c Mon Oct 19 11:58:36 2009 +0100 @@ -962,6 +962,25 @@ arch_do_vcpu_op( break; } + case VCPUOP_register_vcpu_time_memory_area: + { + struct vcpu_register_time_memory_area area; + + rc = -EFAULT; + if ( copy_from_guest(&area, arg, 1) ) + break; + + if ( !guest_handle_okay(area.addr.h, 1) ) + break; + + rc = 0; + v->arch.time_info_guest = area.addr.h; + + force_update_vcpu_system_time(v); + + break; + } + case VCPUOP_get_physid: { struct vcpu_get_physid cpu_id; diff -r 5f28661bb2bb -r ad2fd7b94bd3 xen/arch/x86/time.c --- a/xen/arch/x86/time.c Mon Oct 19 10:57:58 2009 +0100 +++ b/xen/arch/x86/time.c Mon Oct 19 11:58:36 2009 +0100 @@ -22,6 +22,7 @@ #include <xen/irq.h> #include <xen/softirq.h> #include <xen/keyhandler.h> +#include <xen/guest_access.h> #include <asm/io.h> #include <asm/msr.h> #include <asm/mpspec.h> @@ -807,23 +808,15 @@ s_time_t get_s_time(void) return now; } -static inline void version_update_begin(u32 *version) -{ - /* Explicitly OR with 1 just in case version number gets out of sync. */ - *version = (*version + 1) | 1; - wmb(); -} - -static inline void version_update_end(u32 *version) -{ - wmb(); - (*version)++; -} - -void update_vcpu_system_time(struct vcpu *v) +/* Explicitly OR with 1 just in case version number gets out of sync. */ +#define version_update_begin(v) (((v)+1)|1) +#define version_update_end(v) ((v)+1) + +static void __update_vcpu_system_time(struct vcpu *v, int force) { struct cpu_time *t; - struct vcpu_time_info *u; + struct vcpu_time_info *u, _u; + XEN_GUEST_HANDLE(vcpu_time_info_t) user_u; if ( v->vcpu_info == NULL ) return; @@ -831,35 +824,79 @@ void update_vcpu_system_time(struct vcpu t = &this_cpu(cpu_time); u = &vcpu_info(v, time); + /* Don't bother unless timestamps have changed or we are forced. */ + if ( !force && (u->tsc_timestamp == (v->domain->arch.vtsc + ? t->stime_local_stamp + : t->local_tsc_stamp)) ) + return; + + memset(&_u, 0, sizeof(_u)); + if ( v->domain->arch.vtsc ) { - if ( u->tsc_timestamp == t->stime_local_stamp ) - return; - version_update_begin(&u->version); - u->tsc_timestamp = t->stime_local_stamp; - u->system_time = t->stime_local_stamp; - u->tsc_to_system_mul = 0x80000000u; - u->tsc_shift = 1; - version_update_end(&u->version); - } - else if ( u->tsc_timestamp != t->local_tsc_stamp ) - { - version_update_begin(&u->version); - u->tsc_timestamp = t->local_tsc_stamp; - u->system_time = t->stime_local_stamp; - u->tsc_to_system_mul = t->tsc_scale.mul_frac; - u->tsc_shift = (s8)t->tsc_scale.shift; - version_update_end(&u->version); - } + _u.tsc_timestamp = t->stime_local_stamp; + _u.system_time = t->stime_local_stamp; + _u.tsc_to_system_mul = 0x80000000u; + _u.tsc_shift = 1; + } + else + { + _u.tsc_timestamp = t->local_tsc_stamp; + _u.system_time = t->stime_local_stamp; + _u.tsc_to_system_mul = t->tsc_scale.mul_frac; + _u.tsc_shift = (s8)t->tsc_scale.shift; + } + + /* 1. Update guest kernel version. */ + _u.version = u->version = version_update_begin(u->version); + wmb(); + /* 2. Update all other guest kernel fields. */ + *u = _u; + wmb(); + /* 3. Update guest kernel version. */ + u->version = version_update_end(u->version); + + user_u = v->arch.time_info_guest; + if ( !guest_handle_is_null(user_u) ) + { + /* 1. Update userspace version. */ + __copy_field_to_guest(user_u, &_u, version); + wmb(); + /* 2. Update all other userspavce fields. */ + __copy_to_guest(user_u, &_u, 1); + wmb(); + /* 3. Update userspace version. */ + _u.version = version_update_end(_u.version); + __copy_field_to_guest(user_u, &_u, version); + } +} + +void update_vcpu_system_time(struct vcpu *v) +{ + __update_vcpu_system_time(v, 0); +} + +void force_update_vcpu_system_time(struct vcpu *v) +{ + __update_vcpu_system_time(v, 1); } void update_domain_wallclock_time(struct domain *d) { + uint32_t *wc_version; + spin_lock(&wc_lock); - version_update_begin(&shared_info(d, wc_version)); + + wc_version = &shared_info(d, wc_version); + *wc_version = version_update_begin(*wc_version); + wmb(); + shared_info(d, wc_sec) = wc_sec + d->time_offset_seconds; shared_info(d, wc_nsec) = wc_nsec; - version_update_end(&shared_info(d, wc_version)); + + wmb(); + *wc_version = version_update_end(*wc_version); + spin_unlock(&wc_lock); } diff -r 5f28661bb2bb -r ad2fd7b94bd3 xen/include/asm-x86/domain.h --- a/xen/include/asm-x86/domain.h Mon Oct 19 10:57:58 2009 +0100 +++ b/xen/include/asm-x86/domain.h Mon Oct 19 11:58:36 2009 +0100 @@ -6,6 +6,7 @@ #include <asm/hvm/vcpu.h> #include <asm/hvm/domain.h> #include <asm/e820.h> +#include <public/vcpu.h> #define has_32bit_shinfo(d) ((d)->arch.has_32bit_shinfo) #define is_pv_32bit_domain(d) ((d)->arch.is_32bit_pv) @@ -418,6 +419,9 @@ struct arch_vcpu uint32_t gdbsx_vcpu_event; #endif + /* A secondary copy of the vcpu time info. */ + XEN_GUEST_HANDLE(vcpu_time_info_t) time_info_guest; + } __cacheline_aligned; /* Shorthands to improve code legibility. */ diff -r 5f28661bb2bb -r ad2fd7b94bd3 xen/include/asm-x86/time.h --- a/xen/include/asm-x86/time.h Mon Oct 19 10:57:58 2009 +0100 +++ b/xen/include/asm-x86/time.h Mon Oct 19 11:58:36 2009 +0100 @@ -43,4 +43,6 @@ uint64_t ns_to_acpi_pm_tick(uint64_t ns) void pv_soft_rdtsc(struct vcpu *v, struct cpu_user_regs *regs); +void force_update_vcpu_system_time(struct vcpu *v); + #endif /* __X86_TIME_H__ */ diff -r 5f28661bb2bb -r ad2fd7b94bd3 xen/include/public/vcpu.h --- a/xen/include/public/vcpu.h Mon Oct 19 10:57:58 2009 +0100 +++ b/xen/include/public/vcpu.h Mon Oct 19 11:58:36 2009 +0100 @@ -202,6 +202,34 @@ DEFINE_XEN_GUEST_HANDLE(vcpu_get_physid_ #define xen_vcpu_physid_to_x86_acpiid(physid) \ ((((uint32_t)((physid)>>32)) >= 0xff) ? 0xff : ((uint8_t)((physid)>>32))) +/* + * Register a memory location to get a secondary copy of the vcpu time + * parameters. The master copy still exists as part of the vcpu shared + * memory area, and this secondary copy is updated whenever the master copy + * is updated (and using the same versioning scheme for synchronisation). + * + * The intent is that this copy may be mapped (RO) into userspace so + * that usermode can compute system time using the time info and the + * tsc. Usermode will see an array of vcpu_time_info structures, one + * for each vcpu, and choose the right one by an existing mechanism + * which allows it to get the current vcpu number (such as via a + * segment limit). It can then apply the normal algorithm to compute + * system time from the tsc. + * + * @extra_arg == pointer to vcpu_register_time_info_memory_area structure. + */ +#define VCPUOP_register_vcpu_time_memory_area 13 +DEFINE_XEN_GUEST_HANDLE(vcpu_time_info_t); +struct vcpu_register_time_memory_area { + union { + XEN_GUEST_HANDLE(vcpu_time_info_t) h; + struct vcpu_time_info *v; + uint64_t p; + } addr; +}; +typedef struct vcpu_register_time_memory_area vcpu_register_time_memory_area_t; +DEFINE_XEN_GUEST_HANDLE(vcpu_register_time_memory_area_t); + #endif /* __XEN_PUBLIC_VCPU_H__ */ /* _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |