|
[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 |