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 /*
23  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  *
26  * Copyright 2019 Joyent, Inc.
27  */
28 
29 #ifndef	_SYS_MACHPRIVREGS_H
30 #define	_SYS_MACHPRIVREGS_H
31 
32 /*
33  * Platform dependent instruction sequences for manipulating
34  * privileged state
35  */
36 
37 #ifdef __cplusplus
38 extern "C" {
39 #endif
40 
41 #define	ASSERT_UPCALL_MASK_IS_SET		/* empty */
42 
43 /*
44  * CLI and STI
45  */
46 
47 #define	CLI(r)			\
48 	cli
49 
50 #define	STI			\
51 	sti
52 
53 /*
54  * Used to re-enable interrupts in the body of exception handlers
55  */
56 
57 #if defined(__amd64)
58 
59 #define	ENABLE_INTR_FLAGS		\
60 	pushq	$F_ON;			\
61 	popfq
62 
63 #elif defined(__i386)
64 
65 #define	ENABLE_INTR_FLAGS		\
66 	pushl	$F_ON;			\
67 	popfl
68 
69 #endif	/* __i386 */
70 
71 /*
72  * IRET and SWAPGS
73  */
74 #if defined(__amd64)
75 
76 #define	IRET	iretq
77 #define	SYSRETQ	sysretq
78 #define	SYSRETL	sysretl
79 #define	SWAPGS	swapgs
80 
81 /*
82  * As of GNU binutils 2.37, the assembler has split the 'sysexit' instruction
83  * into 'sysexitl' and 'sysexitq'. Using a plain 'sysexit' is interpreted as
84  * 'sysexitl' but comes with a warning about the assumption being made. Since
85  * all warnings are treated as errors in the kernel build, this results in a
86  * build failure. Unfortunately the desired 'sysexitl' cannot be used since
87  * older versions of the GNU assembler do not understand it.
88  * The following macro emits the correct byte sequence for 'sysexitl' on this
89  * platform.
90  */
91 #define	SYSEXITL .byte 0x0f, 0x35
92 
93 #elif defined(__i386)
94 
95 #define	IRET	iret
96 
97 #endif	/* __i386 */
98 
99 #define	XPV_TRAP_POP	/* empty */
100 #define	XPV_TRAP_PUSH	/* empty */
101 #define	CLEAN_CS	/* empty */
102 
103 
104 /*
105  * Macros for saving the original segment registers and restoring them
106  * for fast traps.
107  */
108 #if defined(__amd64)
109 
110 /*
111  * Smaller versions of INTR_PUSH and INTR_POP for fast traps.
112  * The following registers have been pushed onto the stack by
113  * hardware at this point:
114  *
115  *	greg_t  r_rip;
116  *	greg_t  r_cs;
117  *	greg_t  r_rfl;
118  *	greg_t  r_rsp;
119  *	greg_t  r_ss;
120  *
121  * This handler is executed both by 32-bit and 64-bit applications.
122  * 64-bit applications allow us to treat the set (%rdi, %rsi, %rdx,
123  * %rcx, %r8, %r9, %r10, %r11, %rax) as volatile across function calls.
124  * However, 32-bit applications only expect (%eax, %edx, %ecx) to be volatile
125  * across a function call -- in particular, %esi and %edi MUST be saved!
126  *
127  * We could do this differently by making a FAST_INTR_PUSH32 for 32-bit
128  * programs, and FAST_INTR_PUSH for 64-bit programs, but it doesn't seem
129  * particularly worth it.
130  */
131 #define	FAST_INTR_PUSH			\
132 	INTGATE_INIT_KERNEL_FLAGS;	\
133 	subq	$REGOFF_RIP, %rsp;	\
134 	movq	%rsi, REGOFF_RSI(%rsp);	\
135 	movq	%rdi, REGOFF_RDI(%rsp);	\
136 	swapgs
137 
138 #define	FAST_INTR_POP			\
139 	swapgs;				\
140 	movq	REGOFF_RSI(%rsp), %rsi;	\
141 	movq	REGOFF_RDI(%rsp), %rdi;	\
142 	addq	$REGOFF_RIP, %rsp
143 
144 #define	FAST_INTR_RETURN	call x86_md_clear; jmp tr_iret_user
145 
146 #elif defined(__i386)
147 
148 #define	FAST_INTR_PUSH          \
149 	cld;                    \
150 	__SEGREGS_PUSH          \
151 	__SEGREGS_LOAD_KERNEL
152 
153 #define	FAST_INTR_POP		\
154 	__SEGREGS_POP
155 
156 #define	FAST_INTR_RETURN	iret
157 
158 #endif	/* __i386 */
159 
160 /*
161  * Handling the CR0.TS bit for floating point handling.
162  *
163  * When the TS bit is *set*, attempts to touch the floating
164  * point hardware will result in a #nm trap.
165  */
166 #if defined(__amd64)
167 
168 #define	STTS(rtmp)		\
169 	movq	%cr0, rtmp;	\
170 	orq	$CR0_TS, rtmp;	\
171 	movq	rtmp, %cr0
172 
173 #elif defined(__i386)
174 
175 #define	STTS(rtmp)		\
176 	movl	%cr0, rtmp;	\
177 	orl	$CR0_TS, rtmp;	\
178 	movl	rtmp, %cr0
179 
180 #endif	/* __i386 */
181 
182 #define	CLTS			\
183 	clts
184 
185 #ifdef __cplusplus
186 }
187 #endif
188 
189 #endif	/* _SYS_MACHPRIVREGS_H */
190