xref: /xnu-10002.1.13/osfmk/i386/rtclock_asm_native.h (revision 1031c584a5e37aff177559b9f69dbd3c8c3fd30a) !
1 /*
2  * Copyright (c) 2010-2012 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  * @OSF_COPYRIGHT@
30  */
31 /*
32  * @APPLE_FREE_COPYRIGHT@
33  */
34 /*
35  *	File:		rtclock_asm_native.h
36  *	Purpose:	Native routines for reading nanotime
37  */
38 
39 #ifndef _PAL_RTCLOCK_ASM_NATIVE_H_
40 #define _PAL_RTCLOCK_ASM_NATIVE_H_
41 
42 /*
43  * Assembly snippet included in exception handlers and rtc_nanotime_read()
44  *
45  *
46  * Warning!  There are several copies of this code in the trampolines found in
47  * osfmk/x86_64/idt64.s, coming from the various TIMER macros in rtclock_asm.h.
48  * They're all kept in sync by using the RTC_NANOTIME_READ() macro.
49  *
50  * The algorithm we use is:
51  *
52  *	ns = ((((rdtsc - rnt_tsc_base)<<rnt_shift)*rnt_tsc_scale) / 2**32) + rnt_ns_base;
53  *
54  * rnt_shift, a constant computed during initialization, is the smallest value for which:
55  *
56  *	(tscFreq << rnt_shift) > SLOW_TSC_THRESHOLD
57  *
58  * Where SLOW_TSC_THRESHOLD is about 10e9.  Since most processor's tscFreqs are greater
59  * than 1GHz, rnt_shift is usually 0.  rnt_tsc_scale is also a 32-bit constant:
60  *
61  *	rnt_tsc_scale = (10e9 * 2**32) / (tscFreq << rnt_shift);
62  *
63  * %rdi points to nanotime info struct.
64  * %rax returns nanotime
65  */
66 #define PAL_RTC_NANOTIME_READ_FAST()					  \
67 0:	movl	RNT_GENERATION(%rdi),%esi				; \
68 	test        %esi,%esi		/* info updating? */		; \
69         jz        0b			/* - wait if so */		; \
70 	lfence								; \
71 	rdtsc								; \
72 	shlq	$32,%rdx						; \
73 	movl    RNT_SHIFT(%rdi),%ecx					; \
74 	orq	%rdx,%rax			/* %rax := tsc */	; \
75 	subq	RNT_TSC_BASE(%rdi),%rax		/* tsc - tsc_base */	; \
76 	shlq    %cl,%rax						; \
77 	movl	RNT_SCALE(%rdi),%ecx					; \
78 	mulq	%rcx				/* delta * scale */	; \
79 	shrdq	$32,%rdx,%rax			/* %rdx:%rax >>= 32 */	; \
80 	addq	RNT_NS_BASE(%rdi),%rax		/* add ns_base */	; \
81 	cmpl	RNT_GENERATION(%rdi),%esi	/* repeat if changed */ ; \
82 	jne	0b
83 
84 #define PAL_RTC_NANOTIME_READ_NOBARRIER()					  \
85 0:	movl	RNT_GENERATION(%rdi),%esi				; \
86 	test        %esi,%esi		/* info updating? */		; \
87         jz        0b			/* - wait if so */		; \
88 	rdtsc								; \
89 	shlq	$32,%rdx						; \
90 	movl    RNT_SHIFT(%rdi),%ecx					; \
91 	orq	%rdx,%rax			/* %rax := tsc */	; \
92 	subq	RNT_TSC_BASE(%rdi),%rax		/* tsc - tsc_base */	; \
93 	shlq    %cl,%rax						; \
94 	movl	RNT_SCALE(%rdi),%ecx					; \
95 	mulq	%rcx				/* delta * scale */	; \
96 	shrdq	$32,%rdx,%rax			/* %rdx:%rax >>= 32 */	; \
97 	addq	RNT_NS_BASE(%rdi),%rax		/* add ns_base */	; \
98 	cmpl	RNT_GENERATION(%rdi),%esi	/* repeat if changed */ ; \
99 	jne	0b
100 
101 #endif /* _PAL_RTCLOCK_ASM_NATIVE_H_ */
102