sd: remove 'ssd' driver support
[unleashed/tickless.git] / arch / x86 / kernel / platform / i86pc / boot / fb_swtch_src.s
blob351ef89d15b8c9f88ba4803e23a6db257ddc7483
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
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>
35 #include "assym.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) \
45 movb val, %al; \
46 outb $0x80;
49 #define DISABLE_PAGING \
50 movl %cr0, %eax ;\
51 btrl $31, %eax /* clear PG bit */ ;\
52 movl %eax, %cr0
55 * This macro contains common code for 64/32-bit versions of copy_sections().
56 * On entry:
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; \
68 xorl %eax, %eax; \
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; \
73 rep \
74 movsb; \
75 /* Zero BSS */ \
76 movl FB_SEC_BSS_SIZE(fbs), %ecx; \
77 rep \
78 stosb; \
79 add $FB_SECTIONS_INCR, fbs; \
80 dec snum; \
81 jnz 1b
84 .globl _start
85 _start:
87 /* Disable interrupts */
88 cli
90 #if defined(__amd64)
91 /* Switch to a low memory stack */
92 movq $_start, %rsp
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 */
104 smovb
106 #elif defined(__i386)
107 movl 0x4(%esp), %esi /* address of fastboot info struct */
109 /* Switch to a low memory stack */
110 movl $_start, %esp
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 */
117 smovb
119 #endif
121 #if defined(__amd64)
123 xorl %eax, %eax
124 xorl %edx, %edx
126 movl $MSR_AMD_FSBASE, %ecx
127 wrmsr
129 movl $MSR_AMD_GSBASE, %ecx
130 wrmsr
132 movl $MSR_AMD_KGSBASE, %ecx
133 wrmsr
135 #endif
137 * zero out all the registers to make sure they're 16 bit clean
139 #if defined(__amd64)
140 xorq %r8, %r8
141 xorq %r9, %r9
142 xorq %r10, %r10
143 xorq %r11, %r11
144 xorq %r12, %r12
145 xorq %r13, %r13
146 xorq %r14, %r14
147 xorq %r15, %r15
148 #endif
149 xorl %eax, %eax
150 xorl %ebx, %ebx
151 xorl %ecx, %ecx
152 xorl %edx, %edx
153 xorl %ebp, %ebp
155 #if defined(__amd64)
157 * Load our own GDT
159 lgdt gdt_info
160 #endif
162 * Load our own IDT
164 lidt idt_info
166 #if defined(__amd64)
168 * Invalidate all TLB entries.
169 * Load temporary pagetables to copy kernel and boot-archive
171 movq %cr4, %rax
172 andq $_BITNOT(CR4_PGE), %rax
173 movq %rax, %cr4
174 movq FI_PAGETABLE_PA(%rsp), %rax
175 movq %rax, %cr3
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
182 call map_copy
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
187 call map_copy
189 /* Copy sections if there are any */
190 leaq _MUL(FASTBOOT_UNIX, FI_FILES_INCR)(%rbx), %rdi
191 movl FB_SECTCNT(%rdi), %esi
192 cmpl $0, %esi
193 je 1f
194 call copy_sections
197 * Shut down 64 bit mode. First get into compatiblity mode.
199 movq %rsp, %rax
200 pushq $B32DATA_SEL
201 pushq %rax
202 pushf
203 pushq $B32CODE_SEL
204 pushq $1f
205 iretq
207 .code32
209 movl $B32DATA_SEL, %eax
210 movw %ax, %ss
211 movw %ax, %ds
212 movw %ax, %es
213 movw %ax, %fs
214 movw %ax, %gs
217 * Disable long mode by:
218 * - shutting down paging (bit 31 of cr0). This will flush the
219 * TLBs.
220 * - disabling LME (long mode enable) in EFER (extended feature reg)
222 #endif
223 DISABLE_PAGING /* clobbers %eax */
225 #if defined(__amd64)
226 ljmp $B32CODE_SEL, $1f
228 #endif
231 * Clear PGE, PAE and PSE flags as dboot expects them to be
232 * cleared.
234 movl %cr4, %eax
235 andl $_BITNOT(CR4_PGE | CR4_PAE | CR4_PSE), %eax
236 movl %eax, %cr4
238 #if defined(__amd64)
239 movl $MSR_AMD_EFER, %ecx /* Extended Feature Enable */
240 rdmsr
241 btcl $8, %eax /* bit 8 Long Mode Enable bit */
242 wrmsr
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 */
250 cmpl $0, %edi
251 je paging_on /* no need to enable paging */
253 movl FI_LAST_TABLE_PA(%esp), %esi /* page table PA */
256 * Turn on PAE
258 movl %cr4, %eax
259 orl $CR4_PAE, %eax
260 movl %eax, %cr4
263 * Load top pagetable base address into cr3
265 movl FI_PAGETABLE_PA(%esp), %eax
266 movl %eax, %cr3
268 movl %cr0, %eax
269 orl $_CONST(CR0_PG | CR0_WP | CR0_AM), %eax
270 andl $_BITNOT(CR0_NW | CR0_CD), %eax
271 movl %eax, %cr0
272 jmp paging_on
273 paging_on:
275 /* copy unix to final destination */
276 leal _MUL(FASTBOOT_UNIX, FI_FILES_INCR)(%ebx), %edx
277 call map_copy
279 /* copy boot archive to final destination */
280 leal _MUL(FASTBOOT_BOOTARCHIVE, FI_FILES_INCR)(%ebx), %edx
281 call map_copy
283 /* Disable paging one more time */
284 DISABLE_PAGING
286 /* Copy sections if there are any */
287 leal _MUL(FASTBOOT_UNIX, FI_FILES_INCR)(%ebx), %edx
288 movl FB_SECTCNT(%edx), %eax
289 cmpl $0, %eax
290 je 1f
291 call copy_sections
294 /* Whatever flags we turn on we need to turn off */
295 movl %cr4, %eax
296 andl $_BITNOT(CR4_PAE), %eax
297 movl %eax, %cr4
298 #endif /* __i386 */
300 dboot_jump:
301 /* Jump to dboot */
302 movl $DBOOT_ENTRY_ADDRESS, %edi
303 movl FI_NEW_MBI_PA(%esp), %ebx
304 movl $MB_BOOTLOADER_MAGIC, %eax
305 jmp *%edi
307 #if defined(__amd64)
309 .code64
310 ENTRY_NP(copy_sections)
312 * On entry
313 * %rdi points to the fboot_file_t
314 * %rsi contains number of sections
316 movq %rdi, %rdx
317 movq %rsi, %r9
319 COPY_SECT(%rdx, %r8, %r9)
321 SET_SIZE(copy_sections)
323 ENTRY_NP(map_copy)
325 * On entry
326 * %rdi points to the fboot_file_t
327 * %rsi has FI_LAST_TABLE_PA(%rsp)
330 movq %rdi, %rdx
331 movq %rsi, %r8
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
338 je 1f
340 movq %rcx, (%r8)
341 movq %cr3, %rsi /* Reload cr3 */
342 movq %rsi, %cr3
343 movq FB_VA(%rdx), %rsi /* Load from VA */
344 movq $PAGESIZE, %rcx
345 shrq $3, %rcx /* 8-byte at a time */
347 smovq
348 addq $8, %rax /* Go to next PTE */
349 jmp 2b
352 SET_SIZE(map_copy)
354 #elif defined(__i386)
356 ENTRY_NP(copy_sections)
358 * On entry
359 * %edx points to the fboot_file_t
360 * %eax contains the number of sections
362 pushl %ebp
363 pushl %ebx
364 pushl %esi
365 pushl %edi
367 movl %eax, %ebp
369 COPY_SECT(%edx, %ebx, %ebp)
371 popl %edi
372 popl %esi
373 popl %ebx
374 popl %ebp
376 SET_SIZE(copy_sections)
378 ENTRY_NP(map_copy)
380 * On entry
381 * %edx points to the fboot_file_t
382 * %edi has FB_HAS_PAE(%esp)
383 * %esi has FI_LAST_TABLE_PA(%esp)
385 pushl %eax
386 pushl %ebx
387 pushl %ecx
388 pushl %edx
389 pushl %ebp
390 pushl %esi
391 pushl %edi
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 */
397 loop:
398 movl (%eax), %esi /* Are we done? */
399 cmpl $FASTBOOT_TERMINATE, %esi
400 je done
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 */
410 movl %esi, %cr3
411 movl FB_VA(%edx), %esi /* Load from VA */
412 jmp do_copy
413 no_paging:
414 andl $_BITNOT(MMU_PAGEOFFSET), %esi /* clear lower 12-bit */
415 do_copy:
416 movl %ebx, %edi
417 movl $PAGESIZE, %ecx
418 shrl $2, %ecx /* 4-byte at a time */
420 smovl
421 addl $8, %eax /* We built the PTEs as 8-byte entries */
422 addl $PAGESIZE, %ebx
423 jmp loop
424 done:
425 popl %edi
426 popl %esi
427 popl %ebp
428 popl %edx
429 popl %ecx
430 popl %ebx
431 popl %eax
433 SET_SIZE(map_copy)
434 #endif /* __i386 */
437 idt_info:
438 .value 0x3ff
439 .quad 0
442 * We need to trampoline thru a gdt we have in low memory.
444 #include "../boot/boot_gdt.s"