]> git.saurik.com Git - apple/xnu.git/blobdiff - libsyscall/wrappers/mach_continuous_time.c
xnu-7195.50.7.100.1.tar.gz
[apple/xnu.git] / libsyscall / wrappers / mach_continuous_time.c
index 61b996de70fac6ff24abfa669eddf8a6460f125f..e07aba3bf8cb174445f54cc4868bc858e2b36ce0 100644 (file)
@@ -2,14 +2,14 @@
  * Copyright (c) 2015 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * Copyright (c) 2015 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
- * 
+ *
  * This file contains Original Code and/or Modifications of Original Code
  * as defined in and that are subject to the Apple Public Source License
  * Version 2.0 (the 'License'). You may not use this file except in
  * compliance with the License. Please obtain a copy of the License at
  * http://www.opensource.apple.com/apsl/ and read it before using this
  * file.
  * This file contains Original Code and/or Modifications of Original Code
  * as defined in and that are subject to the Apple Public Source License
  * Version 2.0 (the 'License'). You may not use this file except in
  * compliance with the License. Please obtain a copy of the License at
  * http://www.opensource.apple.com/apsl/ and read it before using this
  * file.
- * 
+ *
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
@@ -17,7 +17,7 @@
  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
  * Please see the License for the specific language governing rights and
  * limitations under the License.
  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
  * Please see the License for the specific language governing rights and
  * limitations under the License.
- * 
+ *
  * @APPLE_LICENSE_HEADER_END@
  */
 #include <stddef.h>
  * @APPLE_LICENSE_HEADER_END@
  */
 #include <stddef.h>
@@ -32,21 +32,22 @@ _mach_continuous_time_base(void)
 {
 #if !defined(__x86_64__) && !defined(__arm64__)
        // Deal with the lack of 64-bit loads on arm32 (see mach_approximate_time.s)
 {
 #if !defined(__x86_64__) && !defined(__arm64__)
        // Deal with the lack of 64-bit loads on arm32 (see mach_approximate_time.s)
-       while(1) {
+       while (1) {
                volatile uint64_t *base_ptr = (volatile uint64_t*)_COMM_PAGE_CONT_TIMEBASE;
                uint64_t read1, read2;
                read1 = *base_ptr;
 #if defined(__arm__)
                volatile uint64_t *base_ptr = (volatile uint64_t*)_COMM_PAGE_CONT_TIMEBASE;
                uint64_t read1, read2;
                read1 = *base_ptr;
 #if defined(__arm__)
-               __asm__ volatile("dsb sy" ::: "memory");
+               __asm__ volatile ("dsb sy" ::: "memory");
 #elif defined(__i386__)
 #elif defined(__i386__)
-               __asm__ volatile("lfence" ::: "memory");
+               __asm__ volatile ("lfence" ::: "memory");
 #else
 #error "unsupported arch"
 #endif
                read2 = *base_ptr;
 
 #else
 #error "unsupported arch"
 #endif
                read2 = *base_ptr;
 
-               if(__builtin_expect((read1 == read2), 1))
+               if (__builtin_expect((read1 == read2), 1)) {
                        return read1;
                        return read1;
+               }
        }
 #else // 64-bit
        return *(volatile uint64_t*)_COMM_PAGE_CONT_TIMEBASE;
        }
 #else // 64-bit
        return *(volatile uint64_t*)_COMM_PAGE_CONT_TIMEBASE;
@@ -58,11 +59,12 @@ kern_return_t
 _mach_continuous_hwclock(uint64_t *cont_time __unused)
 {
 #if defined(__arm64__)
 _mach_continuous_hwclock(uint64_t *cont_time __unused)
 {
 #if defined(__arm64__)
+#define ISB_SY          0xf
        uint8_t cont_hwclock = *((uint8_t*)_COMM_PAGE_CONT_HWCLOCK);
        uint8_t cont_hwclock = *((uint8_t*)_COMM_PAGE_CONT_HWCLOCK);
-       uint64_t timebase;
        if (cont_hwclock) {
        if (cont_hwclock) {
-               __asm__ volatile("isb\n" "mrs %0, CNTPCT_EL0" : "=r"(timebase));
-               *cont_time = timebase;
+               volatile uint64_t *base_ptr = (volatile uint64_t*)_COMM_PAGE_CONT_HW_TIMEBASE;
+               __builtin_arm_isb(ISB_SY);
+               *cont_time = __builtin_arm_rsr64("CNTVCT_EL0") + *base_ptr;
                return KERN_SUCCESS;
        }
 #endif
                return KERN_SUCCESS;
        }
 #endif
@@ -78,20 +80,24 @@ _mach_continuous_time(uint64_t* absolute_time, uint64_t* cont_time)
        volatile uint64_t absolute;
 
        do {
        volatile uint64_t absolute;
 
        do {
-        read1 = *base_ptr;
-        absolute = mach_absolute_time();
-#if    defined(__arm__) || defined(__arm64__)
-            /*
-             * mach_absolute_time() contains an instruction barrier which will
-             * prevent the speculation of read2 above this point, so we don't
-             * need another barrier here.
-             */
+               read1 = *base_ptr;
+               absolute = mach_absolute_time();
+#if     defined(__arm__) || defined(__arm64__)
+               /*
+                * mach_absolute_time() contains an instruction barrier which will
+                * prevent the speculation of read2 above this point, so we don't
+                * need another barrier here.
+                */
 #endif
                read2 = *base_ptr;
        } while (__builtin_expect((read1 != read2), 0));
 
 #endif
                read2 = *base_ptr;
        } while (__builtin_expect((read1 != read2), 0));
 
-       if (absolute_time) *absolute_time = absolute;
-       if (cont_time) *cont_time = absolute + read1;
+       if (absolute_time) {
+               *absolute_time = absolute;
+       }
+       if (cont_time) {
+               *cont_time = absolute + read1;
+       }
 
        return KERN_SUCCESS;
 }
 
        return KERN_SUCCESS;
 }
@@ -100,8 +106,9 @@ uint64_t
 mach_continuous_time(void)
 {
        uint64_t cont_time;
 mach_continuous_time(void)
 {
        uint64_t cont_time;
-       if (_mach_continuous_hwclock(&cont_time) != KERN_SUCCESS)
+       if (_mach_continuous_hwclock(&cont_time) != KERN_SUCCESS) {
                _mach_continuous_time(NULL, &cont_time);
                _mach_continuous_time(NULL, &cont_time);
+       }
        return cont_time;
 }
 
        return cont_time;
 }
 
@@ -111,7 +118,7 @@ mach_continuous_approximate_time(void)
        /*
         * No retry loop here because if we use a slightly too old timebase that's
         * okay, we are approximate time anyway.
        /*
         * No retry loop here because if we use a slightly too old timebase that's
         * okay, we are approximate time anyway.
-       */
+        */
        volatile register uint64_t time_base = _mach_continuous_time_base();
        return time_base + mach_approximate_time();
 }
        volatile register uint64_t time_base = _mach_continuous_time_base();
        return time_base + mach_approximate_time();
 }