1/* 2 * Copyright (c) 2003-2007 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 29#include <sys/appleapiopts.h> 30#include <machine/cpu_capabilities.h> 31#include <machine/commpage.h> 32#include <i386/asm.h> 33 34#include <assym.s> 35 36 .text 37 .align 2, 0x90 38 39Lmach_absolute_time: 40 int $0x3 41 ret 42 43 COMMPAGE_DESCRIPTOR(mach_absolute_time,_COMM_PAGE_ABSOLUTE_TIME,0,0) 44 45 46/* return nanotime in %edx:%eax */ 47 48Lnanotime: 49 pushl %ebp 50 movl %esp,%ebp 51 pushl %esi 52 pushl %ebx 53 540: 55 movl _COMM_PAGE_NT_GENERATION,%esi /* get generation (0 if being changed) */ 56 testl %esi,%esi /* if being updated, loop until stable */ 57 jz 0b 58 59 lfence 60 rdtsc /* get TSC in %edx:%eax */ 61 lfence 62 63 subl _COMM_PAGE_NT_TSC_BASE,%eax 64 sbbl _COMM_PAGE_NT_TSC_BASE+4,%edx 65 66 movl _COMM_PAGE_NT_SCALE,%ecx 67 68 movl %edx,%ebx 69 mull %ecx 70 movl %ebx,%eax 71 movl %edx,%ebx 72 mull %ecx 73 addl %ebx,%eax 74 adcl $0,%edx 75 76 addl _COMM_PAGE_NT_NS_BASE,%eax 77 adcl _COMM_PAGE_NT_NS_BASE+4,%edx 78 79 cmpl _COMM_PAGE_NT_GENERATION,%esi /* have the parameters changed? */ 80 jne 0b /* yes, loop until stable */ 81 82 popl %ebx 83 popl %esi 84 popl %ebp 85 ret 86 87 COMMPAGE_DESCRIPTOR(nanotime,_COMM_PAGE_NANOTIME,0,kSlow) 88 89 90/* nanotime routine for machines slower than ~1Gz (SLOW_TSC_THRESHOLD) */ 91Lnanotime_slow: 92 push %ebp 93 mov %esp,%ebp 94 push %esi 95 push %edi 96 push %ebx 97 980: 99 movl _COMM_PAGE_NT_GENERATION,%esi 100 testl %esi,%esi /* if generation is 0, data being changed */ 101 jz 0b /* so loop until stable */ 102 103 lfence 104 rdtsc /* get TSC in %edx:%eax */ 105 lfence 106 subl _COMM_PAGE_NT_TSC_BASE,%eax 107 sbbl _COMM_PAGE_NT_TSC_BASE+4,%edx 108 109 pushl %esi /* save generation */ 110 /* 111 * Do the math to convert tsc ticks to nanoseconds. We first 112 * do long multiply of 1 billion times the tsc. Then we do 113 * long division by the tsc frequency 114 */ 115 mov $1000000000, %ecx /* number of nanoseconds in a second */ 116 mov %edx, %ebx 117 mul %ecx 118 mov %edx, %edi 119 mov %eax, %esi 120 mov %ebx, %eax 121 mul %ecx 122 add %edi, %eax 123 adc $0, %edx /* result in edx:eax:esi */ 124 mov %eax, %edi 125 mov _COMM_PAGE_NT_SHIFT,%ecx /* overloaded as the low 32 tscFreq */ 126 xor %eax, %eax 127 xchg %edx, %eax 128 div %ecx 129 xor %eax, %eax 130 mov %edi, %eax 131 div %ecx 132 mov %eax, %ebx 133 mov %esi, %eax 134 div %ecx 135 mov %ebx, %edx /* result in edx:eax */ 136 popl %esi /* recover generation */ 137 138 add _COMM_PAGE_NT_NS_BASE,%eax 139 adc _COMM_PAGE_NT_NS_BASE+4,%edx 140 141 cmpl _COMM_PAGE_NT_GENERATION,%esi /* have the parameters changed? */ 142 jne 0b /* yes, loop until stable */ 143 144 pop %ebx 145 pop %edi 146 pop %esi 147 pop %ebp 148 ret /* result in edx:eax */ 149 150 COMMPAGE_DESCRIPTOR(nanotime_slow,_COMM_PAGE_NANOTIME,kSlow,0) 151 152 153/* The 64-bit version. We return the 64-bit nanotime in %rax, 154 * and by convention we must preserve %r9, %r10, and %r11. 155 */ 156 .text 157 .align 2 158 .code64 159Lnanotime_64: // NB: must preserve r9, r10, and r11 160 pushq %rbp // set up a frame for backtraces 161 movq %rsp,%rbp 162 movq $_COMM_PAGE_32_TO_64(_COMM_PAGE_TIME_DATA_START),%rsi 1631: 164 movl _NT_GENERATION(%rsi),%r8d // get generation 165 testl %r8d,%r8d // if 0, data is being changed... 166 jz 1b // ...so loop until stable 167 lfence 168 rdtsc // edx:eax := tsc 169 lfence 170 shlq $32,%rdx // rax := ((edx << 32) | eax), ie 64-bit tsc 171 orq %rdx,%rax 172 subq _NT_TSC_BASE(%rsi), %rax // rax := (tsc - base_tsc) 173 movl _NT_SCALE(%rsi),%ecx 174 mulq %rcx // rdx:rax := (tsc - base_tsc) * scale 175 shrdq $32,%rdx,%rax // _COMM_PAGE_NT_SHIFT is always 32 176 addq _NT_NS_BASE(%rsi),%rax // (((tsc - base_tsc) * scale) >> 32) + ns_base 177 178 cmpl _NT_GENERATION(%rsi),%r8d // did the data change during computation? 179 jne 1b 180 popq %rbp 181 ret 182 183 COMMPAGE_DESCRIPTOR(nanotime_64,_COMM_PAGE_NANOTIME,0,kSlow) 184