2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
13 * Copyright 2016 Joyent, Inc.
16 #include <sys/asm_linkage.h>
17 #include <sys/segments.h>
18 #include <sys/time_impl.h>
20 #include <cp_offsets.h>
22 #define GETCPU_GDT_OFFSET SEL_GDT(GDT_CPUID, SEL_UPL)
28 * __cp_tsc_read(uint_t cp_tsc_type)
30 * Stack usage: 0x18 bytes
32 ENTRY_NP
(__cp_tsc_read
)
40 movl CP_TSC_TYPE
(%edi
), %eax
41 movl CP_TSC_NCPU
(%edi
), %esi
55 * When cp_tsc_ncpu is non-zero, it indicates the length of the
56 * cp_tsc_sync_tick_delta array, which contains per-CPU offsets for the
57 * TSC. The CPU ID furnished by the IA32_TSC_AUX register via rdtscp
58 * is used to look up an offset value in that array and apply it to the
61 leal CP_TSC_SYNC_TICK_DELTA
(%edi
), %esi
62 leal
(%esi
, %ecx
, 8), %ecx
70 mov $GETCPU_GDT_OFFSET
, %eax
73 movl CP_TSC_TYPE
(%edi
), %eax
76 cmpl $TSC_RDTSC_MFENCE
, %eax
83 cmpl $TSC_RDTSC_LFENCE
, %eax
90 cmpl $TSC_RDTSC_CPUID
, %eax
101 * Other protections should have prevented this function from being
102 * called in the first place. The only sane action is to abort.
103 * The easiest means in this context is via SIGILL.
112 * With a TSC reading in-hand, confirm that the thread has not migrated
113 * since the cpu_id was first checked.
115 movl $GETCPU_GDT_OFFSET
, %ecx
121 * There was a CPU migration, perform another reading.
124 movl CP_TSC_NCPU
(%edi
), %esi
125 movl CP_TSC_TYPE
(%edi
), %eax
129 /* Grab the per-cpu offset and add it to the TSC result */
130 leal CP_TSC_SYNC_TICK_DELTA
(%edi
), %esi
131 leal
(%esi
, %ecx
, 8), %ecx
135 SET_SIZE
(__cp_tsc_read
)
139 * __cp_getcpu(uint_t cp_tsc_type)
141 ENTRY_NP
(__cp_getcpu
)
143 * If RDTSCP is available, it is a quick way to grab the cpu_id which
144 * is stored in the TSC_AUX MSR by the kernel.
147 movl CP_TSC_TYPE
(%eax
), %eax
154 mov $GETCPU_GDT_OFFSET
, %eax
157 SET_SIZE
(__cp_getcpu
)