xref: /titanic_41/usr/src/uts/i86pc/ml/fb_swtch_src.s (revision 2f0fcb93196badcdd803715656c809058d9f3114)
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 2008 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27
28#if defined(__lint)
29
30int fb_swtch_silence_lint = 0;
31
32#else
33
34#include <sys/asm_linkage.h>
35#include <sys/segments.h>
36#include <sys/controlregs.h>
37#include <sys/machparam.h>
38#include <sys/multiboot.h>
39#include <sys/fastboot.h>
40#include "assym.h"
41
42/*
43 * This code is to switch from 64-bit or 32-bit to protected mode.
44 */
45
46/*
47 * For debugging with LEDs
48 */
49#define	FB_OUTB_ASM(val)	\
50    movb	val, %al;	\
51    outb	$0x80;
52
53
54#define	DISABLE_PAGING							\
55	movl	%cr0, %eax						;\
56	btrl	$31, %eax	/* clear PG bit */			;\
57	movl	%eax, %cr0
58
59
60	.globl	_start
61_start:
62
63	/* Disable interrupts */
64	cli
65
66#if defined(__amd64)
67	/* Switch to a low memory stack */
68	movq	$_start, %rsp
69	addq	$FASTBOOT_STACK_OFFSET, %rsp
70
71	/*
72	 * Copy from old stack to new stack
73	 * If the content before fi_valid gets bigger than 0x200 bytes,
74	 * the reserved stack size above will need to be changed.
75	 */
76	movq	%rdi, %rsi	/* source from old stack */
77	movq	%rsp, %rdi	/* destination on the new stack */
78	movq	$FI_VALID, %rcx	/* size to copy */
79	rep
80	  smovb
81
82#elif defined(__i386)
83	movl	0x4(%esp), %esi	/* address of fastboot info struct */
84
85	/* Switch to a low memory stack */
86	movl	$_start, %esp
87	addl	$FASTBOOT_STACK_OFFSET, %esp
88
89	/* Copy struct to stack */
90	movl	%esp, %edi	/* destination on the new stack */
91	movl	$FI_VALID, %ecx	/* size to copy */
92	rep
93	  smovb
94
95#endif
96
97#if defined(__amd64)
98
99	xorl	%eax, %eax
100	xorl	%edx, %edx
101
102	movl	$MSR_AMD_FSBASE, %ecx
103	wrmsr
104
105	movl	$MSR_AMD_GSBASE, %ecx
106	wrmsr
107
108	movl	$MSR_AMD_KGSBASE, %ecx
109	wrmsr
110
111#endif
112	/*
113	 * zero out all the registers to make sure they're 16 bit clean
114	 */
115#if defined(__amd64)
116	xorq	%r8, %r8
117	xorq	%r9, %r9
118	xorq	%r10, %r10
119	xorq	%r11, %r11
120	xorq	%r12, %r12
121	xorq	%r13, %r13
122	xorq	%r14, %r14
123	xorq	%r15, %r15
124#endif
125	xorl	%eax, %eax
126	xorl	%ebx, %ebx
127	xorl	%ecx, %ecx
128	xorl	%edx, %edx
129	xorl	%ebp, %ebp
130
131#if defined(__amd64)
132	/*
133	 * Load our own GDT
134	 */
135	lgdt	gdt_info
136#endif
137	/*
138	 * Load our own IDT
139	 */
140	lidt	idt_info
141
142#if defined(__amd64)
143	/*
144	 * Shut down 64 bit mode. First get into compatiblity mode.
145	 */
146	movq	%rsp, %rax
147	pushq	$B32DATA_SEL
148	pushq	%rax
149	pushf
150	pushq	$B32CODE_SEL
151	pushq	$1f
152	iretq
153
154	.code32
1551:
156	movl	$B32DATA_SEL, %eax
157	movw	%ax, %ss
158	movw	%ax, %ds
159	movw	%ax, %es
160	movw	%ax, %fs
161	movw	%ax, %gs
162
163	/*
164	 * Disable long mode by:
165	 * - shutting down paging (bit 31 of cr0).  This will flush the
166	 *   TLBs.
167	 * - disabling LME (long made enable) in EFER (extended feature reg)
168	 */
169#endif
170	DISABLE_PAGING		/* clobbers %eax */
171
172#if defined(__amd64)
173	ljmp	$B32CODE_SEL, $1f
1741:
175#endif
176
177	/*
178	 * Clear PGE, PAE and PSE flags as dboot expects them to be
179	 * cleared.
180	 */
181	movl	%cr4, %eax
182	andl	$_BITNOT(CR4_PGE | CR4_PAE | CR4_PSE), %eax
183	movl	%eax, %cr4
184
185#if defined(__amd64)
186	movl	$MSR_AMD_EFER, %ecx	/* Extended Feature Enable */
187	rdmsr
188	btcl	$8, %eax		/* bit 8 Long Mode Enable bit */
189	wrmsr
190#endif
191
192	/*
193	 * If fi_has_pae is set, re-enable paging with PAE.
194	 */
195	leal	FI_FILES(%esp), %ebx	/* offset to the files */
196	movl	FI_HAS_PAE(%esp), %edi	/* need to enable paging or not */
197	cmpl	$0, %edi
198	je	paging_on		/* no need to enable paging */
199
200	movl	FI_LAST_TABLE_PA(%esp), %esi	/* page table PA */
201
202	/*
203	 * Turn on PAE
204	 */
205	movl	%cr4, %eax
206	orl	$CR4_PAE, %eax
207	movl	%eax, %cr4
208
209	/*
210	 * Load top pagetable base address into cr3
211	 */
212	movl	FI_PAGETABLE_PA(%esp), %eax
213	movl	%eax, %cr3
214
215	movl	%cr0, %eax
216	orl	$_CONST(CR0_PG | CR0_WP | CR0_AM), %eax
217	andl	$_BITNOT(CR0_NW | CR0_CD), %eax
218	movl	%eax, %cr0
219	jmp	paging_on
220paging_on:
221
222	/* copy unix to final destination */
223	leal	_MUL(FASTBOOT_UNIX, FI_FILES_INCR)(%ebx), %edx
224	call	map_copy
225
226	/* copy boot archive to final destination */
227	leal	_MUL(FASTBOOT_BOOTARCHIVE, FI_FILES_INCR)(%ebx), %edx
228	call	map_copy
229
230	/* Disable paging one more time */
231	DISABLE_PAGING
232
233	/* Copy sections if there are any */
234	leal	_MUL(FASTBOOT_UNIX, FI_FILES_INCR)(%ebx), %edx
235	movl	FB_SECTCNT(%edx), %eax
236	cmpl	$0, %eax
237	je	1f
238	call	copy_sections
2391:
240
241	/* Whatever flags we turn on we need to turn off */
242	movl	%cr4, %eax
243	andl	$_BITNOT(CR4_PAE), %eax
244	movl	%eax, %cr4
245
246dboot_jump:
247	/* Jump to dboot */
248	movl	$DBOOT_ENTRY_ADDRESS, %edi
249	movl	FI_NEW_MBI_PA(%esp), %ebx
250	movl	$MB_BOOTLOADER_MAGIC, %eax
251	jmp	*%edi
252
253	ENTRY_NP(copy_sections)
254	/*
255	 * On entry
256	 *	%edx points to the fboot_file_t
257	 *	%eax contains the number of sections
258	 */
259	pushl	%ebp
260	pushl	%ebx
261	pushl	%esi
262	pushl	%edi
263
264	leal	FB_SECTIONS(%edx), %ebx
265	movl	%eax, %ebp
266	xorl	%eax, %eax
2671:
268	dec	%ebp
269	movl	FB_DEST_PA(%edx), %esi
270	addl	FB_SEC_OFFSET(%ebx), %esi
271	movl	FB_SEC_PADDR(%ebx), %edi
272	movl	FB_SEC_SIZE(%ebx), %ecx
273	rep
274	  movsb
275	/* Zero BSS */
276	movl	FB_SEC_BSS_SIZE(%ebx), %ecx
277	rep
278	  stosb
279
280	cmpl	$0, %ebp
281	je	2f
282	addl	$FB_SECTIONS_INCR, %ebx
283	jmp	1b
2842:
285	popl	%edi
286	popl	%esi
287	popl	%ebx
288	popl	%ebp
289	ret
290	SET_SIZE(copy_sections)
291
292	ENTRY_NP(map_copy)
293	/*
294	 * On entry
295	 *	%edx points to the fboot_file_t
296	 *	%edi has FB_HAS_PAE(%esp)
297	 *	%esi has FI_LAST_TABLE_PA(%esp)
298	 */
299	pushl	%eax
300	pushl	%ebx
301	pushl	%ecx
302	pushl	%edx
303	pushl	%ebp
304	pushl	%esi
305	pushl	%edi
306	movl	%esi, %ebp	/* Save page table PA in %ebp */
307
308	movl	FB_PTE_LIST_PA(%edx), %eax	/* PA list of the source */
309	movl	FB_DEST_PA(%edx), %ebx		/* PA of the destination */
310
311loop:
312	movl	(%eax), %esi			/* Are we done? */
313	cmpl	$FASTBOOT_TERMINATE, %esi
314	je	done
315
316	cmpl	$1, (%esp)			/* Is paging on? */
317	jne	no_paging			/* Nope */
318
319	movl	%ebp, %edi			/* Page table PA */
320	movl	%esi, (%edi)			/* Program low 32-bit */
321	movl	4(%eax), %esi			/* high bits of the table */
322	movl	%esi, 4(%edi)			/* Program high 32-bit */
323	movl	%cr3, %esi			/* Reload cr3 */
324	movl	%esi, %cr3
325	movl	FB_VA(%edx), %esi		/* Load from VA */
326	jmp	do_copy
327no_paging:
328	andl	$_BITNOT(MMU_PAGEOFFSET), %esi	/* clear lower 12-bit */
329do_copy:
330	movl	%ebx, %edi
331	movl	$PAGESIZE, %ecx
332	shrl	$2, %ecx	/* 4-byte at a time */
333	rep
334	  smovl
335	addl	$8, %eax /* We built the PTEs as 8-byte entries */
336	addl	$PAGESIZE, %ebx
337	jmp	loop
338done:
339	popl	%edi
340	popl	%esi
341	popl	%ebp
342	popl	%edx
343	popl	%ecx
344	popl	%ebx
345	popl	%eax
346	ret
347	SET_SIZE(map_copy)
348
349
350
351idt_info:
352	.value	0x3ff
353	.quad	0
354
355/*
356 * We need to trampoline thru a gdt we have in low memory.
357 */
358#include "../boot/boot_gdt.s"
359#endif /* __lint */
360