[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v2 1/2] xtf: add a msleep helper
This requires importing some of the PV timecounter functionality from FreeBSD in order to access the PV time info. Signed-off-by: Roger Pau Monné <roger.pau@xxxxxxxxxx> --- Cc: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> --- Changes since v1: - New in this version. --- arch/x86/include/arch/lib.h | 14 +++++ build/files.mk | 1 + common/pvtimer.c | 136 ++++++++++++++++++++++++++++++++++++++++++++ include/xtf/lib.h | 5 ++ 4 files changed, 156 insertions(+) create mode 100644 common/pvtimer.c diff --git a/arch/x86/include/arch/lib.h b/arch/x86/include/arch/lib.h index 6714bdc..dedab70 100644 --- a/arch/x86/include/arch/lib.h +++ b/arch/x86/include/arch/lib.h @@ -392,6 +392,20 @@ static inline void write_xcr0(uint64_t xcr0) xsetbv(0, xcr0); } +static inline void pause(void) +{ + asm volatile ("pause"); +} + +static inline uint64_t rdtsc_ordered(void) +{ + uint32_t low, high; + + asm volatile ("lfence; mfence; rdtsc" : "=a" (low), "=d" (high)); + + return ((uint64_t)high << 32) | low; +} + #endif /* XTF_X86_LIB_H */ /* diff --git a/build/files.mk b/build/files.mk index 46b42d6..489f28a 100644 --- a/build/files.mk +++ b/build/files.mk @@ -13,6 +13,7 @@ obj-perarch += $(ROOT)/common/lib.o obj-perarch += $(ROOT)/common/libc/stdio.o obj-perarch += $(ROOT)/common/libc/string.o obj-perarch += $(ROOT)/common/libc/vsnprintf.o +obj-perarch += $(ROOT)/common/pvtimer.o obj-perarch += $(ROOT)/common/report.o obj-perarch += $(ROOT)/common/setup.o obj-perarch += $(ROOT)/common/xenbus.o diff --git a/common/pvtimer.c b/common/pvtimer.c new file mode 100644 index 0000000..a39501c --- /dev/null +++ b/common/pvtimer.c @@ -0,0 +1,136 @@ +/** + * @file common/pvtimer.c + * + * A driver for the pv time counter that provides a sleep function. + * + * The routines to access the pv clock are partially imported from FreeBSD. + */ + +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2009 Adrian Chadd + * Copyright (c) 2012 Spectra Logic Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include <xtf/traps.h> +#include <xtf/types.h> + +#include <arch/barrier.h> + +#define MS_TO_NS 1000000ULL + +/* + * Scale a 64-bit delta by scaling and multiplying by a 32-bit fraction, + * yielding a 64-bit result. + */ +static uint64_t scale_delta(uint64_t delta, uint32_t mul_frac, int shift) +{ + uint64_t product; + + if (shift < 0) + delta >>= -shift; + else + delta <<= shift; + +#if defined(__i386__) + { + uint32_t tmp1, tmp2; + + /** + * For i386, the formula looks like: + * + * lower = (mul_frac * (delta & UINT_MAX)) >> 32 + * upper = mul_frac * (delta >> 32) + * product = lower + upper + */ + asm volatile ("mul %5 ;" + "mov %4,%%eax ;" + "mov %%edx,%4 ;" + "mul %5 ;" + "xor %5,%5 ;" + "add %4,%%eax ;" + "adc %5,%%edx ;" + : "=A" (product), "=r" (tmp1), "=r" (tmp2) + : "a" ((uint32_t)delta), "1" ((uint32_t)(delta >> 32)), + "2" (mul_frac)); + } +#elif defined(__amd64__) + { + unsigned long tmp; + + asm volatile ("mulq %[mul_frac] ;" + "shrd $32, %[hi], %[lo] ;" + : [lo] "=a" (product), [hi] "=d" (tmp) + : "0" (delta), [mul_frac] "rm" ((uint64_t)mul_frac)); + } +#else +#error "pvtimer: unsupported architecture" +#endif + + return product; +} + +static uint64_t get_timecounter(void) +{ + struct vcpu_time_info *ti = &shared_info.vcpu_info[0].time; + uint64_t nsec; + uint32_t version; + + do + { + version = ti->version; + rmb(); + nsec = scale_delta(rdtsc_ordered() - ti->tsc_timestamp, + ti->tsc_to_system_mul, ti->tsc_shift) + + ti->system_time; + rmb(); + } while ( (ti->version & 1) != 0 || ti->version != version ); + + return nsec; +} + +void msleep(unsigned int ms) +{ + uint64_t current = get_timecounter(); + uint64_t target = current + ms * MS_TO_NS; + + if ( current > target ) + panic("sleep counter overflow\n"); + + while ( get_timecounter() < target ) + pause(); +} + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/include/xtf/lib.h b/include/xtf/lib.h index abf8f25..17c4e5a 100644 --- a/include/xtf/lib.h +++ b/include/xtf/lib.h @@ -101,6 +101,11 @@ int xtf_probe_sysctl_interface_version(void); */ int xtf_get_domid(void); +/** + * Sleep for ms milliseconds. + */ +void msleep(unsigned int ms); + #endif /* XTF_LIB_H */ /* -- 2.16.3 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |