xref: /titanic_52/usr/src/uts/intel/ia32/ml/desctbls_asm.s (revision 7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fe)
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, Version 1.0 only
6 * (the "License").  You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22/*
23 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27#pragma ident	"%Z%%M%	%I%	%E% SMI"
28
29#include <sys/asm_linkage.h>
30#include <sys/asm_misc.h>
31#include <sys/regset.h>
32#include <sys/panic.h>
33#include <sys/ontrap.h>
34#include <sys/privregs.h>
35#include <sys/segments.h>
36
37#if defined(__lint)
38#include <sys/types.h>
39#include <sys/systm.h>
40#include <sys/thread.h>
41#include <sys/archsystm.h>
42#include <sys/byteorder.h>
43#include <sys/dtrace.h>
44#include <sys/x86_archext.h>
45#else   /* __lint */
46#include "assym.h"
47#endif  /* __lint */
48
49#if defined(__lint)
50
51/*ARGSUSED*/
52void rd_idtr(desctbr_t *idtr)
53{}
54
55/*ARGSUSED*/
56void wr_idtr(desctbr_t *idtr)
57{}
58
59#else	/* __lint */
60
61#if defined(__amd64)
62
63	ENTRY_NP(rd_idtr)
64	sidt	(%rdi)
65	ret
66	SET_SIZE(rd_idtr)
67
68	ENTRY_NP(wr_idtr)
69	lidt	(%rdi)
70	ret
71	SET_SIZE(wr_idtr)
72
73#elif defined(__i386)
74
75	ENTRY_NP(rd_idtr)
76	pushl	%ebp
77	movl	%esp, %ebp
78	movl	8(%ebp), %edx
79	sidt	(%edx)
80	leave
81	ret
82	SET_SIZE(rd_idtr)
83
84	ENTRY_NP(wr_idtr)
85	pushl	%ebp
86	movl	%esp, %ebp
87	movl	8(%ebp), %edx
88	lidt	(%edx)
89	leave
90	ret
91	SET_SIZE(wr_idtr)
92
93#endif	/* __i386 */
94#endif	/* __lint */
95
96#if defined(__lint)
97
98/*ARGSUSED*/
99void rd_gdtr(desctbr_t *gdtr)
100{}
101
102/*ARGSUSED*/
103void wr_gdtr(desctbr_t *gdtr)
104{}
105
106#else	/* __lint */
107
108#if defined(__amd64)
109
110	ENTRY_NP(rd_gdtr)
111	sgdt	(%rdi)
112	ret
113	SET_SIZE(rd_gdtr)
114
115	ENTRY_NP(wr_gdtr)
116	lgdt	(%rdi)
117	jmp	1f
118	nop
1191:
120	movl	$KDS_SEL, %eax
121	movw	%ax, %ss
122	/*
123	 * zero %ds and %es - they're ignored anyway
124	 */
125	xorl	%eax, %eax
126	movw	%ax, %ds
127	movw	%ax, %es
128	/*
129	 * set %fs and %gs (probably to zero also)
130	 */
131	movl	$KFS_SEL, %eax
132	movw	%ax, %fs
133	movl	$KGS_SEL, %eax
134	movw	%ax, %gs
135	popq	%rax
136	pushq	$KCS_SEL
137	pushq	%rax
138	lretq
139	SET_SIZE(wr_gdtr)
140
141#elif defined(__i386)
142
143	ENTRY_NP(rd_gdtr)
144	pushl	%ebp
145	movl	%esp, %ebp
146	movl	8(%ebp), %edx
147	sgdt	(%edx)
148	leave
149	ret
150	SET_SIZE(rd_gdtr)
151
152	ENTRY_NP(wr_gdtr)
153	pushl	%ebp
154	movl	%esp, %ebp
155	movl	8(%ebp), %edx
156	lgdt	(%edx)
157	nop
158	ljmp	$KCS_SEL, $.next
159.next:
160	movl	$KDS_SEL, %eax
161	movw	%ax, %ds
162	movw	%ax, %es
163	movw	%ax, %ss
164	movl	$KFS_SEL, %eax
165	movw	%ax, %fs
166	movl	$KGS_SEL, %eax
167	movw	%ax, %gs
168	leave
169	ret
170	SET_SIZE(wr_gdtr)
171
172#endif	/* __i386 */
173#endif	/* __lint */
174
175#if defined(__lint)
176
177/*ARGSUSED*/
178void wr_ldtr(selector_t ldtsel)
179{}
180
181selector_t rd_ldtr(void)
182{ return (0); }
183
184#if defined(__amd64)
185void clr_ldt_sregs(void)
186{}
187#endif
188
189#else	/* __lint */
190
191#if defined(__amd64)
192
193	ENTRY_NP(wr_ldtr)
194	movq	%rdi, %rax
195	lldt	%ax
196	ret
197	SET_SIZE(wr_ldtr)
198
199	ENTRY_NP(rd_ldtr)
200	xorl	%eax, %eax
201	sldt	%ax
202	ret
203	SET_SIZE(rd_ldtr)
204
205	/*
206	 * Make sure any stale ldt selectors are cleared by loading
207	 * KDS_SEL (kernel %ds gdt selector). This is necessary
208	 * since the kernel does not use %es, %fs and %ds. %cs and
209	 * %ss are necessary and setup by the kernel along with %gs
210	 * to point to current cpu struct. If we take a kmdb breakpoint
211	 * in the kernel and resume with a stale ldt selector kmdb
212	 * would #gp fault if it points to a ldt in the context of
213	 * another process.
214	 *
215	 * WARNING: Nocona and AMD have different behaviour about storing
216	 * the null selector into %fs and %gs while in long mode. On AMD
217	 * chips fsbase and gsbase is not cleared. But on nocona storing
218	 * null selector into %fs or %gs has the side effect of clearing
219	 * fsbase or gsbase. For that reason we use KDS_SEL which has
220	 * consistent behavoir between AMD and Nocona.
221	 */
222	ENTRY_NP(clr_ldt_sregs)
223
224	/*
225	 * Save GSBASE before resetting %gs to KDS_SEL
226	 * then restore GSBASE.
227	 */
228	cli
229	movq	%rbx, %rdi
230	movw	$KDS_SEL, %bx
231        movl    $MSR_AMD_GSBASE, %ecx
232        rdmsr
233        movw    %bx, %gs
234	wrmsr
235	sti
236	movw	%bx, %ds
237	movw	%bx, %es
238	movw	%bx, %fs
239	movq	%rdi, %rbx
240	ret
241	SET_SIZE(clr_ldt_sregs)
242
243#elif defined(__i386)
244
245	ENTRY_NP(wr_ldtr)
246	movw	4(%esp), %ax
247	lldt	%ax
248	ret
249	SET_SIZE(wr_ldtr)
250
251	ENTRY_NP(rd_ldtr)
252	xorl	%eax, %eax
253	sldt	%ax
254	ret
255	SET_SIZE(rd_ldtr)
256
257#endif	/* __i386 */
258#endif	/* __lint */
259
260#if defined(__lint)
261
262/*ARGSUSED*/
263void wr_tsr(selector_t tsssel)
264{}
265
266#else	/* __lint */
267
268#if defined(__amd64)
269
270	ENTRY_NP(wr_tsr)
271	movq	%rdi, %rax
272	ltr	%ax
273	ret
274	SET_SIZE(wr_tsr)
275
276#elif defined(__i386)
277
278	ENTRY_NP(wr_tsr)
279	movw	4(%esp), %ax
280	ltr	%ax
281	ret
282	SET_SIZE(wr_tsr)
283
284#endif	/* __i386 */
285#endif	/* __lint */
286