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.
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.
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]
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
29 #include <sys/asm_linkage.h>
30 #include <sys/segments.h>
31 #include <sys/controlregs.h>
32 #include <sys/machparam.h>
33 #include <sys/multiboot.h>
34 #include <sys/fastboot.h>
38 * This code is to switch from 64-bit or 32-bit to protected mode.
42 * For debugging with LEDs
44 #define FB_OUTB_ASM(val) \
49 #define DISABLE_PAGING \
51 btrl $
31, %eax
/* clear PG bit */ ;\
55 * This macro contains common code for 64/32-bit versions of copy_sections().
57 * fbf points to the fboot_file_t
58 * snum contains the number of sections
59 * Registers that would be clobbered:
60 * fbs, snum, %eax, %ecx, %edi, %esi.
61 * NOTE: fb_dest_pa is supposed to be in the first 1GB,
62 * therefore it is safe to use 32-bit register to hold it's value
63 * even for 64-bit code.
66 #define COPY_SECT(fbf, fbs, snum) \
67 lea FB_SECTIONS
(fbf
), fbs; \
69 1: movl FB_DEST_PA
(fbf
), %esi; \
70 addl FB_SEC_OFFSET
(fbs
), %esi; \
71 movl FB_SEC_PADDR
(fbs
), %edi; \
72 movl FB_SEC_SIZE
(fbs
), %ecx; \
76 movl FB_SEC_BSS_SIZE
(fbs
), %ecx; \
79 add $FB_SECTIONS_INCR
, fbs; \
87 /* Disable interrupts */
91 /* Switch to a low memory stack */
93 addq $FASTBOOT_STACK_OFFSET
, %rsp
96 * Copy from old stack to new stack
97 * If the content before fi_valid gets bigger than 0x200 bytes,
98 * the reserved stack size above will need to be changed.
100 movq
%rdi
, %rsi
/* source from old stack */
101 movq
%rsp
, %rdi
/* destination on the new stack */
102 movq $FI_VALID
, %rcx
/* size to copy */
106 #elif defined(__i386)
107 movl
0x4(%esp
), %esi
/* address of fastboot info struct */
109 /* Switch to a low memory stack */
111 addl $FASTBOOT_STACK_OFFSET
, %esp
113 /* Copy struct to stack */
114 movl
%esp
, %edi
/* destination on the new stack */
115 movl $FI_VALID
, %ecx
/* size to copy */
126 movl $MSR_AMD_FSBASE
, %ecx
129 movl $MSR_AMD_GSBASE
, %ecx
132 movl $MSR_AMD_KGSBASE
, %ecx
137 * zero out all the registers to make sure they're 16 bit clean
168 * Invalidate all TLB entries.
169 * Load temporary pagetables to copy kernel and boot-archive
172 andq $_BITNOT
(CR4_PGE
), %rax
174 movq FI_PAGETABLE_PA
(%rsp
), %rax
177 leaq FI_FILES
(%rsp
), %rbx
/* offset to the files */
179 /* copy unix to final destination */
180 movq FI_LAST_TABLE_PA
(%rsp
), %rsi
/* page table PA */
181 leaq _MUL
(FASTBOOT_UNIX
, FI_FILES_INCR
)(%rbx
), %rdi
184 /* copy boot archive to final destination */
185 movq FI_LAST_TABLE_PA
(%rsp
), %rsi
/* page table PA */
186 leaq _MUL
(FASTBOOT_BOOTARCHIVE
, FI_FILES_INCR
)(%rbx
), %rdi
189 /* Copy sections if there are any */
190 leaq _MUL
(FASTBOOT_UNIX
, FI_FILES_INCR
)(%rbx
), %rdi
191 movl FB_SECTCNT
(%rdi
), %esi
197 * Shut down 64 bit mode. First get into compatiblity mode.
209 movl $B32DATA_SEL
, %eax
217 * Disable long mode by:
218 * - shutting down paging (bit 31 of cr0). This will flush the
220 * - disabling LME (long mode enable) in EFER (extended feature reg)
223 DISABLE_PAGING
/* clobbers %eax */
226 ljmp $B32CODE_SEL
, $
1f
231 * Clear PGE, PAE and PSE flags as dboot expects them to be
235 andl $_BITNOT
(CR4_PGE | CR4_PAE | CR4_PSE
), %eax
239 movl $MSR_AMD_EFER
, %ecx
/* Extended Feature Enable */
241 btcl $
8, %eax
/* bit 8 Long Mode Enable bit */
244 #elif defined(__i386)
246 * If fi_has_pae is set, re-enable paging with PAE.
248 leal FI_FILES
(%esp
), %ebx
/* offset to the files */
249 movl FI_HAS_PAE
(%esp
), %edi
/* need to enable paging or not */
251 je paging_on
/* no need to enable paging */
253 movl FI_LAST_TABLE_PA
(%esp
), %esi
/* page table PA */
263 * Load top pagetable base address into cr3
265 movl FI_PAGETABLE_PA
(%esp
), %eax
269 orl $_CONST
(CR0_PG | CR0_WP | CR0_AM
), %eax
270 andl $_BITNOT
(CR0_NW | CR0_CD
), %eax
275 /* copy unix to final destination */
276 leal _MUL
(FASTBOOT_UNIX
, FI_FILES_INCR
)(%ebx
), %edx
279 /* copy boot archive to final destination */
280 leal _MUL
(FASTBOOT_BOOTARCHIVE
, FI_FILES_INCR
)(%ebx
), %edx
283 /* Disable paging one more time */
286 /* Copy sections if there are any */
287 leal _MUL
(FASTBOOT_UNIX
, FI_FILES_INCR
)(%ebx
), %edx
288 movl FB_SECTCNT
(%edx
), %eax
294 /* Whatever flags we turn on we need to turn off */
296 andl $_BITNOT
(CR4_PAE
), %eax
302 movl $DBOOT_ENTRY_ADDRESS
, %edi
303 movl FI_NEW_MBI_PA
(%esp
), %ebx
304 movl $MB_BOOTLOADER_MAGIC
, %eax
310 ENTRY_NP
(copy_sections
)
313 * %rdi points to the fboot_file_t
314 * %rsi contains number of sections
319 COPY_SECT
(%rdx
, %r8, %r9)
321 SET_SIZE
(copy_sections
)
326 * %rdi points to the fboot_file_t
327 * %rsi has FI_LAST_TABLE_PA(%rsp)
332 movq FB_PTE_LIST_PA
(%rdx
), %rax
/* PA list of the source */
333 movq FB_DEST_PA
(%rdx
), %rdi
/* PA of the destination */
336 movq
(%rax
), %rcx
/* Are we done? */
337 cmpl $FASTBOOT_TERMINATE
, %ecx
341 movq
%cr3
, %rsi
/* Reload cr3 */
343 movq FB_VA
(%rdx
), %rsi
/* Load from VA */
345 shrq $
3, %rcx
/* 8-byte at a time */
348 addq $
8, %rax
/* Go to next PTE */
354 #elif defined(__i386)
356 ENTRY_NP
(copy_sections
)
359 * %edx points to the fboot_file_t
360 * %eax contains the number of sections
369 COPY_SECT
(%edx
, %ebx
, %ebp
)
376 SET_SIZE
(copy_sections
)
381 * %edx points to the fboot_file_t
382 * %edi has FB_HAS_PAE(%esp)
383 * %esi has FI_LAST_TABLE_PA(%esp)
392 movl
%esi
, %ebp
/* Save page table PA in %ebp */
394 movl FB_PTE_LIST_PA
(%edx
), %eax
/* PA list of the source */
395 movl FB_DEST_PA
(%edx
), %ebx
/* PA of the destination */
398 movl
(%eax
), %esi
/* Are we done? */
399 cmpl $FASTBOOT_TERMINATE
, %esi
402 cmpl $
1, (%esp
) /* Is paging on? */
403 jne no_paging
/* Nope */
405 movl
%ebp
, %edi
/* Page table PA */
406 movl
%esi
, (%edi
) /* Program low 32-bit */
407 movl
4(%eax
), %esi
/* high bits of the table */
408 movl
%esi
, 4(%edi
) /* Program high 32-bit */
409 movl
%cr3
, %esi
/* Reload cr3 */
411 movl FB_VA
(%edx
), %esi
/* Load from VA */
414 andl $_BITNOT
(MMU_PAGEOFFSET
), %esi
/* clear lower 12-bit */
418 shrl $
2, %ecx
/* 4-byte at a time */
421 addl $
8, %eax
/* We built the PTEs as 8-byte entries */
442 * We need to trampoline thru a gdt we have in low memory.
444 #include "../boot/boot_gdt.s"