1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 * Copyright 2019 Joyent, Inc.
25 */
26
27#include <sys/asm_linkage.h>
28#include <sys/asm_misc.h>
29#include <sys/regset.h>
30#include <sys/psw.h>
31
32#if defined(__lint)
33
34#include <sys/types.h>
35#include <sys/thread.h>
36#include <sys/systm.h>
37#include <sys/lgrp.h>
38
39#else   /* __lint */
40
41#include <sys/pcb.h>
42#include <sys/trap.h>
43#include <sys/ftrace.h>
44#include <sys/traptrace.h>
45#include <sys/clock.h>
46#include <sys/panic.h>
47#include <sys/privregs.h>
48
49#include "assym.h"
50
51#endif	/* __lint */
52
53
54#if defined(__lint)
55
56hrtime_t
57get_hrtime(void)
58{ return (0); }
59
60hrtime_t
61get_hrestime(void)
62{
63	hrtime_t ts;
64
65	gethrestime((timespec_t *)&ts);
66	return (ts);
67}
68
69hrtime_t
70gethrvtime(void)
71{
72	klwp_t *lwp = ttolwp(curthread);
73	struct mstate *ms = &lwp->lwp_mstate;
74
75	return (gethrtime() - ms->ms_state_start + ms->ms_acct[LMS_USER]);
76}
77
78uint64_t
79getlgrp(void)
80{
81	return (((uint64_t)(curthread->t_lpl->lpl_lgrpid) << 32) |
82			curthread->t_cpu->cpu_id);
83}
84
85#else	/* __lint */
86
87/*
88 * XX64: We are assuming that libc continues to expect the 64-bit value being
89 * returned in %edx:%eax.  We further assume that it is safe to leave
90 * the top 32-bit intact in %rax as they will be ignored by libc.  In
91 * other words, if the 64-bit value is already in %rax, while we manually
92 * manufacture a 64-bit value in %edx:%eax by setting %edx to be the high
93 * 32 bits of %rax, we don't zero them out in %rax.
94 * The following amd64 versions will need to be changed if the above
95 * assumptions are not true.
96 */
97
98#if defined(__amd64)
99
100	.globl	gethrtimef
101	ENTRY_NP(get_hrtime)
102	FAST_INTR_PUSH
103	movq	gethrtimef(%rip), %rax
104	INDIRECT_CALL_REG(rax)
105	movq	%rax, %rdx
106	shrq	$32, %rdx			/* high 32-bit in %edx */
107	FAST_INTR_POP
108	FAST_INTR_RETURN
109	SET_SIZE(get_hrtime)
110
111#elif defined(__i386)
112
113	.globl	gethrtimef
114	ENTRY_NP(get_hrtime)
115	FAST_INTR_PUSH
116	call	*gethrtimef
117	FAST_INTR_POP
118	FAST_INTR_RETURN
119	SET_SIZE(get_hrtime)
120
121#endif	/* __i386 */
122
123#if defined(__amd64)
124
125	.globl	gethrestimef
126	ENTRY_NP(get_hrestime)
127	FAST_INTR_PUSH
128	subq	$TIMESPEC_SIZE, %rsp
129	movq	%rsp, %rdi
130	movq	gethrestimef(%rip), %rax
131	INDIRECT_CALL_REG(rax)
132	movl	(%rsp), %eax
133	movl	CLONGSIZE(%rsp), %edx
134	addq	$TIMESPEC_SIZE, %rsp
135	FAST_INTR_POP
136	FAST_INTR_RETURN
137	SET_SIZE(get_hrestime)
138
139#elif defined(__i386)
140
141	.globl	gethrestimef
142	ENTRY_NP(get_hrestime)
143	FAST_INTR_PUSH
144	subl	$TIMESPEC_SIZE, %esp
145	pushl	%esp
146	call	*gethrestimef
147	movl	_CONST(4 + 0)(%esp), %eax
148	movl	_CONST(4 + CLONGSIZE)(%esp), %edx
149	addl	$_CONST(4 + TIMESPEC_SIZE), %esp
150	FAST_INTR_POP
151	FAST_INTR_RETURN
152	SET_SIZE(get_hrestime)
153
154#endif	/* __i386 */
155
156#if defined(__amd64)
157
158	ENTRY_NP(gethrvtime)
159	FAST_INTR_PUSH
160	call	gethrtime_unscaled		/* get time since boot */
161	movq	%gs:CPU_LWP, %rcx		/* current lwp */
162	subq	LWP_MS_STATE_START(%rcx), %rax	/* - ms->ms_state_start */
163	addq	LWP_ACCT_USER(%rcx), %rax	/* add ms->ms_acct[LMS_USER] */
164	subq	$16, %rsp
165	movq	%rax, (%rsp)
166	movq	%rsp, %rdi
167	call	scalehrtime
168	movq	(%rsp), %rax
169	addq	$16, %rsp
170	movq	%rax, %rdx
171	shrq	$32, %rdx			/* high 32-bit in %rdx */
172	FAST_INTR_POP
173	FAST_INTR_RETURN
174	SET_SIZE(gethrvtime)
175
176#elif defined(__i386)
177
178	ENTRY_NP(gethrvtime)
179	FAST_INTR_PUSH
180	call	gethrtime_unscaled		/* get time since boot */
181	movl	%gs:CPU_LWP, %ecx		/* current lwp */
182	subl	LWP_MS_STATE_START(%ecx), %eax	/* - ms->ms_state_start */
183	sbbl	LWP_MS_STATE_START+4(%ecx), %edx
184	addl	LWP_ACCT_USER(%ecx), %eax	/* add ms->ms_acct[LMS_USER] */
185	adcl	LWP_ACCT_USER+4(%ecx), %edx
186	subl	$0x8, %esp
187	leal	(%esp), %ecx
188	movl	%eax, (%ecx)
189	movl	%edx, 4(%ecx)
190	pushl	%ecx
191	call	scalehrtime
192	popl	%ecx
193	movl	(%ecx), %eax
194	movl	4(%ecx), %edx
195	addl	$0x8, %esp
196	FAST_INTR_POP
197	FAST_INTR_RETURN
198	SET_SIZE(gethrvtime)
199
200#endif	/* __i386 */
201
202#if defined(__amd64)
203
204	ENTRY_NP(getlgrp)
205	FAST_INTR_PUSH
206	movq	%gs:CPU_THREAD, %rcx
207	movq	T_LPL(%rcx), %rcx
208	movl	LPL_LGRPID(%rcx), %edx
209	movl	%gs:CPU_ID, %eax
210	FAST_INTR_POP
211	FAST_INTR_RETURN
212	SET_SIZE(getlgrp)
213
214#elif defined(__i386)
215
216	ENTRY_NP(getlgrp)
217	FAST_INTR_PUSH
218	movl	%gs:CPU_THREAD, %ecx
219	movl	T_LPL(%ecx), %ecx
220	movl	LPL_LGRPID(%ecx), %edx
221	movl	%gs:CPU_ID, %eax
222	FAST_INTR_POP
223	FAST_INTR_RETURN
224	SET_SIZE(getlgrp)
225
226#endif	/* __i386 */
227
228#endif	/* __lint */
229