xref: /illumos-gate/usr/src/lib/commpage/i386/cp_subr.S (revision 5d9d9091)
12428aad8SPatrick Mooney/*
22428aad8SPatrick Mooney * This file and its contents are supplied under the terms of the
32428aad8SPatrick Mooney * Common Development and Distribution License ("CDDL"), version 1.0.
42428aad8SPatrick Mooney * You may only use this file in accordance with the terms of version
52428aad8SPatrick Mooney * 1.0 of the CDDL.
62428aad8SPatrick Mooney *
72428aad8SPatrick Mooney * A full copy of the text of the CDDL should have accompanied this
82428aad8SPatrick Mooney * source.  A copy of the CDDL is also available via the Internet at
92428aad8SPatrick Mooney * http://www.illumos.org/license/CDDL.
102428aad8SPatrick Mooney */
112428aad8SPatrick Mooney
122428aad8SPatrick Mooney/*
13e121b61fSPatrick Mooney * Copyright 2019 Joyent, Inc.
14beed421eSPatrick Mooney * Copyright 2020 Oxide Computer Company
152428aad8SPatrick Mooney */
162428aad8SPatrick Mooney
172428aad8SPatrick Mooney#include <sys/asm_linkage.h>
182428aad8SPatrick Mooney#include <sys/segments.h>
192428aad8SPatrick Mooney#include <sys/time_impl.h>
202428aad8SPatrick Mooney#include <sys/tsc.h>
212428aad8SPatrick Mooney#include <cp_offsets.h>
222428aad8SPatrick Mooney
232428aad8SPatrick Mooney#define	GETCPU_GDT_OFFSET	SEL_GDT(GDT_CPUID, SEL_UPL)
242428aad8SPatrick Mooney
25e121b61fSPatrick Mooney/*
26e121b61fSPatrick Mooney * For __cp_tsc_read calls which incur looping retries due to CPU migration,
27e121b61fSPatrick Mooney * this represents the maximum number of tries before bailing out.
28e121b61fSPatrick Mooney */
29e121b61fSPatrick Mooney#define	TSC_READ_MAXLOOP	0x4
30e121b61fSPatrick Mooney
312428aad8SPatrick Mooney	.file	"cp_subr.s"
322428aad8SPatrick Mooney
332428aad8SPatrick Mooney/*
342428aad8SPatrick Mooney * hrtime_t
35e121b61fSPatrick Mooney * __cp_tsc_read(comm_page_t *cp)
362428aad8SPatrick Mooney *
372428aad8SPatrick Mooney * Stack usage: 0x18 bytes
38e121b61fSPatrick Mooney *
39e121b61fSPatrick Mooney * %ebp-0x00 - frame pointer
40e121b61fSPatrick Mooney * %ebp-0x04 - saved %edi
41e121b61fSPatrick Mooney * %ebp-0x08 - saved %esi
42e121b61fSPatrick Mooney * %ebp-0x0c - CPU ID
43e121b61fSPatrick Mooney * %ebp-0x10 - loop count
44e121b61fSPatrick Mooney * %ebp-0x14 - saved %ebx (during cpuid)
452428aad8SPatrick Mooney */
462428aad8SPatrick Mooney	ENTRY_NP(__cp_tsc_read)
472428aad8SPatrick Mooney	pushl	%ebp
482428aad8SPatrick Mooney	movl	%esp, %ebp
492428aad8SPatrick Mooney	pushl	%edi
502428aad8SPatrick Mooney	pushl	%esi
51e121b61fSPatrick Mooney	subl	$0x8, %esp
522428aad8SPatrick Mooney
532428aad8SPatrick Mooney	movl	0x8(%ebp), %edi
542428aad8SPatrick Mooney	movl	CP_TSC_TYPE(%edi), %eax
552428aad8SPatrick Mooney	movl	CP_TSC_NCPU(%edi), %esi
562428aad8SPatrick Mooney	cmpl	$TSC_TSCP, %eax
572428aad8SPatrick Mooney	jne	3f
582428aad8SPatrick Mooney	rdtscp
592428aad8SPatrick Mooney	cmpl	$0, %esi
602428aad8SPatrick Mooney	jne	2f
612428aad8SPatrick Mooney1:
62e121b61fSPatrick Mooney	addl	$0x8, %esp
632428aad8SPatrick Mooney	popl	%esi
642428aad8SPatrick Mooney	popl	%edi
652428aad8SPatrick Mooney	leave
662428aad8SPatrick Mooney	ret
672428aad8SPatrick Mooney2:
682428aad8SPatrick Mooney	/*
692428aad8SPatrick Mooney	 * When cp_tsc_ncpu is non-zero, it indicates the length of the
702428aad8SPatrick Mooney	 * cp_tsc_sync_tick_delta array, which contains per-CPU offsets for the
712428aad8SPatrick Mooney	 * TSC.  The CPU ID furnished by the IA32_TSC_AUX register via rdtscp
722428aad8SPatrick Mooney	 * is used to look up an offset value in that array and apply it to the
732428aad8SPatrick Mooney	 * TSC reading.
742428aad8SPatrick Mooney	 */
752428aad8SPatrick Mooney	leal	CP_TSC_SYNC_TICK_DELTA(%edi), %esi
762428aad8SPatrick Mooney	leal	(%esi, %ecx, 8), %ecx
772428aad8SPatrick Mooney	addl	(%ecx), %eax
782428aad8SPatrick Mooney	adcl	0x4(%ecx), %edx
792428aad8SPatrick Mooney	jmp	1b
802428aad8SPatrick Mooney
812428aad8SPatrick Mooney3:
82e121b61fSPatrick Mooney	testl	%esi, %esi
83e121b61fSPatrick Mooney	jz	4f
84e121b61fSPatrick Mooney
85e121b61fSPatrick Mooney	movl	$0, (%esp)
862428aad8SPatrick Mooney	mov	$GETCPU_GDT_OFFSET, %eax
873cc24548SToomas Soome	lsl	%eax, %eax
88e121b61fSPatrick Mooney	movl	%eax, 0x4(%esp)
892428aad8SPatrick Mooney	movl	CP_TSC_TYPE(%edi), %eax
902428aad8SPatrick Mooney
912428aad8SPatrick Mooney4:
92beed421eSPatrick Mooney	/*
93beed421eSPatrick Mooney	 * TSC_RDTSC_MFENCE was used in the past for AMD chips, but has been
94beed421eSPatrick Mooney	 * supplanted by TSC_RDTSC_LFENCE, which works on Intel and AMD (when
95beed421eSPatrick Mooney	 * lfence can be confirmed as serializing).
96beed421eSPatrick Mooney	 */
972428aad8SPatrick Mooney
982428aad8SPatrick Mooney5:
992428aad8SPatrick Mooney	cmpl	$TSC_RDTSC_LFENCE, %eax
1002428aad8SPatrick Mooney	jne	6f
1012428aad8SPatrick Mooney	lfence
1022428aad8SPatrick Mooney	rdtsc
1032428aad8SPatrick Mooney	jmp	8f
1042428aad8SPatrick Mooney
1052428aad8SPatrick Mooney6:
1062428aad8SPatrick Mooney	cmpl	$TSC_RDTSC_CPUID, %eax
1072428aad8SPatrick Mooney	jne	7f
1082428aad8SPatrick Mooney	pushl	%ebx
1092428aad8SPatrick Mooney	xorl	%eax, %eax
1102428aad8SPatrick Mooney	cpuid
1112428aad8SPatrick Mooney	rdtsc
1122428aad8SPatrick Mooney	popl	%ebx
1132428aad8SPatrick Mooney	jmp	8f
1142428aad8SPatrick Mooney
1152428aad8SPatrick Mooney7:
1162428aad8SPatrick Mooney	/*
1172428aad8SPatrick Mooney	 * Other protections should have prevented this function from being
118e121b61fSPatrick Mooney	 * called in the first place.  Since callers must handle a failure from
119e121b61fSPatrick Mooney	 * CPU migration looping, yield the same result as a bail-out: 0
1202428aad8SPatrick Mooney	 */
121e121b61fSPatrick Mooney	xorl	%eax, %eax
122e121b61fSPatrick Mooney	xorl	%edx, %edx
123e121b61fSPatrick Mooney	jmp	1b
1242428aad8SPatrick Mooney
1252428aad8SPatrick Mooney8:
1262428aad8SPatrick Mooney
1272428aad8SPatrick Mooney	cmpl	$0, %esi
1282428aad8SPatrick Mooney	je	1b
1292428aad8SPatrick Mooney	/*
1302428aad8SPatrick Mooney	 * With a TSC reading in-hand, confirm that the thread has not migrated
1312428aad8SPatrick Mooney	 * since the cpu_id was first checked.
1322428aad8SPatrick Mooney	 */
1332428aad8SPatrick Mooney	movl	$GETCPU_GDT_OFFSET, %ecx
1343cc24548SToomas Soome	lsl	%ecx, %ecx
135e121b61fSPatrick Mooney	movl	0x4(%esp), %esi
1362428aad8SPatrick Mooney	cmpl	%ecx, %esi
137e121b61fSPatrick Mooney	jne	9f
138e121b61fSPatrick Mooney
139e121b61fSPatrick Mooney	/* Grab the per-cpu offset and add it to the TSC result */
140e121b61fSPatrick Mooney	leal	CP_TSC_SYNC_TICK_DELTA(%edi), %esi
141e121b61fSPatrick Mooney	leal	(%esi, %ecx, 8), %ecx
142e121b61fSPatrick Mooney	addl	(%ecx), %eax
143e121b61fSPatrick Mooney	adcl	0x4(%ecx), %edx
144e121b61fSPatrick Mooney	jmp	1b
145e121b61fSPatrick Mooney
146e121b61fSPatrick Mooney9:
1472428aad8SPatrick Mooney	/*
148e121b61fSPatrick Mooney	 * It appears that a migration has occurred between the first CPU ID
149e121b61fSPatrick Mooney	 * query and now.  Check if the loop limit has been broken and retry if
150e121b61fSPatrick Mooney	 * that's not the case.
1512428aad8SPatrick Mooney	 */
152e121b61fSPatrick Mooney	movl	(%esp), %eax
153e121b61fSPatrick Mooney	cmpl	$TSC_READ_MAXLOOP, %eax
154e121b61fSPatrick Mooney	jge	10f
155e121b61fSPatrick Mooney
156e121b61fSPatrick Mooney	incl	%eax
1572428aad8SPatrick Mooney	movl	%eax, (%esp)
158e121b61fSPatrick Mooney	movl	%ecx, 0x4(%esp)
1592428aad8SPatrick Mooney	movl	CP_TSC_NCPU(%edi), %esi
1602428aad8SPatrick Mooney	movl	CP_TSC_TYPE(%edi), %eax
1612428aad8SPatrick Mooney	jmp	4b
1622428aad8SPatrick Mooney
163e121b61fSPatrick Mooney10:
164e121b61fSPatrick Mooney	/* Loop limit was reached. Return bail-out value of 0. */
165e121b61fSPatrick Mooney	xorl	%eax, %eax
166e121b61fSPatrick Mooney	xorl	%edx, %edx
1672428aad8SPatrick Mooney	jmp	1b
168e121b61fSPatrick Mooney
1692428aad8SPatrick Mooney	SET_SIZE(__cp_tsc_read)
1702428aad8SPatrick Mooney
171e121b61fSPatrick Mooney/*
172e121b61fSPatrick Mooney * hrtime_t
173e121b61fSPatrick Mooney * __cp_gethrtime_fasttrap()
174e121b61fSPatrick Mooney */
175e121b61fSPatrick Mooney	ENTRY_NP(__cp_gethrtime_fasttrap)
176e121b61fSPatrick Mooney	movl	$T_GETHRTIME, %eax
177e121b61fSPatrick Mooney	int	$T_FASTTRAP
178e121b61fSPatrick Mooney	ret
179e121b61fSPatrick Mooney	SET_SIZE(__cp_gethrtime_fasttrap)
180e121b61fSPatrick Mooney
1812428aad8SPatrick Mooney/*
1822428aad8SPatrick Mooney * uint_t
1832428aad8SPatrick Mooney * __cp_getcpu(uint_t cp_tsc_type)
1842428aad8SPatrick Mooney */
1852428aad8SPatrick Mooney	ENTRY_NP(__cp_getcpu)
1862428aad8SPatrick Mooney	/*
1872428aad8SPatrick Mooney	 * If RDTSCP is available, it is a quick way to grab the cpu_id which
1882428aad8SPatrick Mooney	 * is stored in the TSC_AUX MSR by the kernel.
1892428aad8SPatrick Mooney	 */
1902428aad8SPatrick Mooney	movl	4(%esp), %eax
1912428aad8SPatrick Mooney	movl	CP_TSC_TYPE(%eax), %eax
1922428aad8SPatrick Mooney	cmpl	$TSC_TSCP, %eax
1932428aad8SPatrick Mooney	jne	1f
1942428aad8SPatrick Mooney	rdtscp
1952428aad8SPatrick Mooney	movl	%ecx, %eax
1962428aad8SPatrick Mooney	ret
1972428aad8SPatrick Mooney1:
1982428aad8SPatrick Mooney	mov	$GETCPU_GDT_OFFSET, %eax
1993cc24548SToomas Soome	lsl	%eax, %eax
2002428aad8SPatrick Mooney	ret
2012428aad8SPatrick Mooney	SET_SIZE(__cp_getcpu)
202