[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

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.