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