xref: /titanic_44/usr/src/lib/commpage/i386/cp_subr.s (revision cc401b3700f84e16c3a03f62783088a993d21466)
1*cc401b37SPatrick Mooney/*
2*cc401b37SPatrick Mooney * This file and its contents are supplied under the terms of the
3*cc401b37SPatrick Mooney * Common Development and Distribution License ("CDDL"), version 1.0.
4*cc401b37SPatrick Mooney * You may only use this file in accordance with the terms of version
5*cc401b37SPatrick Mooney * 1.0 of the CDDL.
6*cc401b37SPatrick Mooney *
7*cc401b37SPatrick Mooney * A full copy of the text of the CDDL should have accompanied this
8*cc401b37SPatrick Mooney * source.  A copy of the CDDL is also available via the Internet at
9*cc401b37SPatrick Mooney * http://www.illumos.org/license/CDDL.
10*cc401b37SPatrick Mooney */
11*cc401b37SPatrick Mooney
12*cc401b37SPatrick Mooney/*
13*cc401b37SPatrick Mooney * Copyright 2016 Joyent, Inc.
14*cc401b37SPatrick Mooney */
15*cc401b37SPatrick Mooney
16*cc401b37SPatrick Mooney#include <sys/asm_linkage.h>
17*cc401b37SPatrick Mooney#include <sys/segments.h>
18*cc401b37SPatrick Mooney#include <sys/time_impl.h>
19*cc401b37SPatrick Mooney#include <sys/tsc.h>
20*cc401b37SPatrick Mooney#include <cp_offsets.h>
21*cc401b37SPatrick Mooney
22*cc401b37SPatrick Mooney#define	GETCPU_GDT_OFFSET	SEL_GDT(GDT_CPUID, SEL_UPL)
23*cc401b37SPatrick Mooney
24*cc401b37SPatrick Mooney	.file	"cp_subr.s"
25*cc401b37SPatrick Mooney
26*cc401b37SPatrick Mooney/*
27*cc401b37SPatrick Mooney * hrtime_t
28*cc401b37SPatrick Mooney * __cp_tsc_read(uint_t cp_tsc_type)
29*cc401b37SPatrick Mooney *
30*cc401b37SPatrick Mooney * Stack usage: 0x18 bytes
31*cc401b37SPatrick Mooney */
32*cc401b37SPatrick Mooney	ENTRY_NP(__cp_tsc_read)
33*cc401b37SPatrick Mooney	pushl	%ebp
34*cc401b37SPatrick Mooney	movl	%esp, %ebp
35*cc401b37SPatrick Mooney	pushl	%edi
36*cc401b37SPatrick Mooney	pushl	%esi
37*cc401b37SPatrick Mooney	subl	$0x4, %esp
38*cc401b37SPatrick Mooney
39*cc401b37SPatrick Mooney	movl	0x8(%ebp), %edi
40*cc401b37SPatrick Mooney	movl	CP_TSC_TYPE(%edi), %eax
41*cc401b37SPatrick Mooney	movl	CP_TSC_NCPU(%edi), %esi
42*cc401b37SPatrick Mooney	cmpl	$TSC_TSCP, %eax
43*cc401b37SPatrick Mooney	jne	3f
44*cc401b37SPatrick Mooney	rdtscp
45*cc401b37SPatrick Mooney	cmpl	$0, %esi
46*cc401b37SPatrick Mooney	jne	2f
47*cc401b37SPatrick Mooney1:
48*cc401b37SPatrick Mooney	addl	$0x4, %esp
49*cc401b37SPatrick Mooney	popl	%esi
50*cc401b37SPatrick Mooney	popl	%edi
51*cc401b37SPatrick Mooney	leave
52*cc401b37SPatrick Mooney	ret
53*cc401b37SPatrick Mooney2:
54*cc401b37SPatrick Mooney	/*
55*cc401b37SPatrick Mooney	 * When cp_tsc_ncpu is non-zero, it indicates the length of the
56*cc401b37SPatrick Mooney	 * cp_tsc_sync_tick_delta array, which contains per-CPU offsets for the
57*cc401b37SPatrick Mooney	 * TSC.  The CPU ID furnished by the IA32_TSC_AUX register via rdtscp
58*cc401b37SPatrick Mooney	 * is used to look up an offset value in that array and apply it to the
59*cc401b37SPatrick Mooney	 * TSC reading.
60*cc401b37SPatrick Mooney	 */
61*cc401b37SPatrick Mooney	leal	CP_TSC_SYNC_TICK_DELTA(%edi), %esi
62*cc401b37SPatrick Mooney	leal	(%esi, %ecx, 8), %ecx
63*cc401b37SPatrick Mooney	addl	(%ecx), %eax
64*cc401b37SPatrick Mooney	adcl	0x4(%ecx), %edx
65*cc401b37SPatrick Mooney	jmp	1b
66*cc401b37SPatrick Mooney
67*cc401b37SPatrick Mooney3:
68*cc401b37SPatrick Mooney	cmpl	$0, %esi
69*cc401b37SPatrick Mooney	je	4f
70*cc401b37SPatrick Mooney	mov	$GETCPU_GDT_OFFSET, %eax
71*cc401b37SPatrick Mooney	lsl	%ax, %eax
72*cc401b37SPatrick Mooney	movl	%eax, (%esp)
73*cc401b37SPatrick Mooney	movl	CP_TSC_TYPE(%edi), %eax
74*cc401b37SPatrick Mooney
75*cc401b37SPatrick Mooney4:
76*cc401b37SPatrick Mooney	cmpl	$TSC_RDTSC_MFENCE, %eax
77*cc401b37SPatrick Mooney	jne	5f
78*cc401b37SPatrick Mooney	mfence
79*cc401b37SPatrick Mooney	rdtsc
80*cc401b37SPatrick Mooney	jmp	8f
81*cc401b37SPatrick Mooney
82*cc401b37SPatrick Mooney5:
83*cc401b37SPatrick Mooney	cmpl	$TSC_RDTSC_LFENCE, %eax
84*cc401b37SPatrick Mooney	jne	6f
85*cc401b37SPatrick Mooney	lfence
86*cc401b37SPatrick Mooney	rdtsc
87*cc401b37SPatrick Mooney	jmp	8f
88*cc401b37SPatrick Mooney
89*cc401b37SPatrick Mooney6:
90*cc401b37SPatrick Mooney	cmpl	$TSC_RDTSC_CPUID, %eax
91*cc401b37SPatrick Mooney	jne	7f
92*cc401b37SPatrick Mooney	pushl	%ebx
93*cc401b37SPatrick Mooney	xorl	%eax, %eax
94*cc401b37SPatrick Mooney	cpuid
95*cc401b37SPatrick Mooney	rdtsc
96*cc401b37SPatrick Mooney	popl	%ebx
97*cc401b37SPatrick Mooney	jmp	8f
98*cc401b37SPatrick Mooney
99*cc401b37SPatrick Mooney7:
100*cc401b37SPatrick Mooney	/*
101*cc401b37SPatrick Mooney	 * Other protections should have prevented this function from being
102*cc401b37SPatrick Mooney	 * called in the first place.  The only sane action is to abort.
103*cc401b37SPatrick Mooney	 * The easiest means in this context is via SIGILL.
104*cc401b37SPatrick Mooney	 */
105*cc401b37SPatrick Mooney	ud2a
106*cc401b37SPatrick Mooney
107*cc401b37SPatrick Mooney8:
108*cc401b37SPatrick Mooney
109*cc401b37SPatrick Mooney	cmpl	$0, %esi
110*cc401b37SPatrick Mooney	je	1b
111*cc401b37SPatrick Mooney	/*
112*cc401b37SPatrick Mooney	 * With a TSC reading in-hand, confirm that the thread has not migrated
113*cc401b37SPatrick Mooney	 * since the cpu_id was first checked.
114*cc401b37SPatrick Mooney	 */
115*cc401b37SPatrick Mooney	movl	$GETCPU_GDT_OFFSET, %ecx
116*cc401b37SPatrick Mooney	lsl	%cx, %ecx
117*cc401b37SPatrick Mooney	movl	(%esp), %esi
118*cc401b37SPatrick Mooney	cmpl	%ecx, %esi
119*cc401b37SPatrick Mooney	je	9f
120*cc401b37SPatrick Mooney	/*
121*cc401b37SPatrick Mooney	 * There was a CPU migration, perform another reading.
122*cc401b37SPatrick Mooney	 */
123*cc401b37SPatrick Mooney	movl	%eax, (%esp)
124*cc401b37SPatrick Mooney	movl	CP_TSC_NCPU(%edi), %esi
125*cc401b37SPatrick Mooney	movl	CP_TSC_TYPE(%edi), %eax
126*cc401b37SPatrick Mooney	jmp	4b
127*cc401b37SPatrick Mooney
128*cc401b37SPatrick Mooney9:
129*cc401b37SPatrick Mooney	/* Grab the per-cpu offset and add it to the TSC result */
130*cc401b37SPatrick Mooney	leal	CP_TSC_SYNC_TICK_DELTA(%edi), %esi
131*cc401b37SPatrick Mooney	leal	(%esi, %ecx, 8), %ecx
132*cc401b37SPatrick Mooney	addl	(%ecx), %eax
133*cc401b37SPatrick Mooney	adcl	0x4(%ecx), %edx
134*cc401b37SPatrick Mooney	jmp	1b
135*cc401b37SPatrick Mooney	SET_SIZE(__cp_tsc_read)
136*cc401b37SPatrick Mooney
137*cc401b37SPatrick Mooney/*
138*cc401b37SPatrick Mooney * uint_t
139*cc401b37SPatrick Mooney * __cp_getcpu(uint_t cp_tsc_type)
140*cc401b37SPatrick Mooney */
141*cc401b37SPatrick Mooney	ENTRY_NP(__cp_getcpu)
142*cc401b37SPatrick Mooney	/*
143*cc401b37SPatrick Mooney	 * If RDTSCP is available, it is a quick way to grab the cpu_id which
144*cc401b37SPatrick Mooney	 * is stored in the TSC_AUX MSR by the kernel.
145*cc401b37SPatrick Mooney	 */
146*cc401b37SPatrick Mooney	movl	4(%esp), %eax
147*cc401b37SPatrick Mooney	movl	CP_TSC_TYPE(%eax), %eax
148*cc401b37SPatrick Mooney	cmpl	$TSC_TSCP, %eax
149*cc401b37SPatrick Mooney	jne	1f
150*cc401b37SPatrick Mooney	rdtscp
151*cc401b37SPatrick Mooney	movl	%ecx, %eax
152*cc401b37SPatrick Mooney	ret
153*cc401b37SPatrick Mooney1:
154*cc401b37SPatrick Mooney	mov	$GETCPU_GDT_OFFSET, %eax
155*cc401b37SPatrick Mooney	lsl	%ax, %eax
156*cc401b37SPatrick Mooney	ret
157*cc401b37SPatrick Mooney	SET_SIZE(__cp_getcpu)
158