X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/935ed37a5c468c8a1c07408573c08b8b7ef80e8b..593a1d5fd87cdf5b46dd5fcb84467b432cea0f91:/osfmk/i386/rtclock.h?ds=sidebyside diff --git a/osfmk/i386/rtclock.h b/osfmk/i386/rtclock.h index 904b38786..e3ea716d4 100644 --- a/osfmk/i386/rtclock.h +++ b/osfmk/i386/rtclock.h @@ -40,8 +40,90 @@ #ifndef _I386_RTCLOCK_H_ #define _I386_RTCLOCK_H_ +#ifndef ASSEMBLER +typedef struct rtc_nanotime { + uint64_t tsc_base; /* timestamp */ + uint64_t ns_base; /* nanoseconds */ + uint32_t scale; /* tsc -> nanosec multiplier */ + uint32_t shift; /* tsc -> nanosec shift/div */ + /* shift is overloaded with + * lower 32bits of tsc_freq + * on slower machines (SLOW_TSC_THRESHOLD) */ + uint32_t generation; /* 0 == being updated */ + uint32_t spare1; +} rtc_nanotime_t; + #include struct cpu_data; +extern void _rtc_nanotime_store( + uint64_t tsc, + uint64_t nsec, + uint32_t scale, + uint32_t shift, + rtc_nanotime_t *dst); + +extern uint64_t _rtc_nanotime_read( + rtc_nanotime_t *rntp, + int slow); + +extern rtc_nanotime_t rtc_nanotime_info; +#endif + +#define SLOW_TSC_THRESHOLD 1000067800 /* TSC is too slow for regular nanotime() algorithm */ + +#if defined(__i386__) +/* + * Assembly snippet included in exception handlers and rtc_nanotime_read() + * %edi points to nanotime info struct + * %edx:%eax returns nanotime + */ +#define RTC_NANOTIME_READ_FAST() \ +0: movl RNT_GENERATION(%edi),%esi /* being updated? */ ; \ + testl %esi,%esi ; \ + jz 0b /* wait until done */ ; \ + rdtsc ; \ + lfence ; \ + subl RNT_TSC_BASE(%edi),%eax ; \ + sbbl RNT_TSC_BASE+4(%edi),%edx /* tsc - tsc_base */ ; \ + movl RNT_SCALE(%edi),%ecx /* * scale factor */ ; \ + movl %edx,%ebx ; \ + mull %ecx ; \ + movl %ebx,%eax ; \ + movl %edx,%ebx ; \ + mull %ecx ; \ + addl %ebx,%eax ; \ + adcl $0,%edx ; \ + addl RNT_NS_BASE(%edi),%eax /* + ns_base */ ; \ + adcl RNT_NS_BASE+4(%edi),%edx ; \ + cmpl RNT_GENERATION(%edi),%esi /* check for update */ ; \ + jne 0b /* do it all again */ + +#elif defined(__x86_64__) + +/* + * Assembly snippet included in exception handlers and rtc_nanotime_read() + * %rdi points to nanotime info struct. + * %rax returns nanotime + */ +#define RTC_NANOTIME_READ_FAST() \ +0: movl RNT_GENERATION(%rdi),%esi ; \ + test %esi,%esi /* info updating? */ ; \ + jz 0b /* - wait if so */ ; \ + rdtsc ; \ + lfence ; \ + shlq $32,%rdx ; \ + orq %rdx,%rax /* %rax := tsc */ ; \ + subq RNT_TSC_BASE(%rdi),%rax /* tsc - tsc_base */ ; \ + xorq %rcx,%rcx ; \ + movl RNT_SCALE(%rdi),%ecx ; \ + mulq %rcx /* delta * scale */ ; \ + shrdq $32,%rdx,%rax /* %rdx:%rax >>= 32 */ ; \ + addq RNT_NS_BASE(%rdi),%rax /* add ns_base */ ; \ + cmpl RNT_GENERATION(%rdi),%esi /* repeat if changed */ ; \ + jne 0b + +#endif + #endif /* _I386_RTCLOCK_H_ */