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 * Copyright 2018 Joyent, Inc.
26 */
27
28
29 #if defined(__lint)
30
31 int fb_swtch_silence_lint = 0;
32
33 #else
34
35 #include <sys/asm_linkage.h>
36 #include <sys/segments.h>
37 #include <sys/controlregs.h>
38 #include <sys/machparam.h>
39 #include <sys/multiboot.h>
40 #include <sys/fastboot.h>
41 #include "assym.h"
42
43 /*
44 * This code is to switch from 64-bit or 32-bit to protected mode.
45 */
46
47 /*
48 * For debugging with LEDs
49 */
50 #define FB_OUTB_ASM(val) \
51 movb val, %al; \
52 outb $0x80;
53
54
79 addl FB_SEC_OFFSET(fbs), %esi; \
80 movl FB_SEC_PADDR(fbs), %edi; \
81 movl FB_SEC_SIZE(fbs), %ecx; \
82 rep \
83 movsb; \
84 /* Zero BSS */ \
85 movl FB_SEC_BSS_SIZE(fbs), %ecx; \
86 rep \
87 stosb; \
88 add $FB_SECTIONS_INCR, fbs; \
89 dec snum; \
90 jnz 1b
91
92
93 .globl _start
94 _start:
95
96 /* Disable interrupts */
97 cli
98
99 #if defined(__amd64)
100 /* Switch to a low memory stack */
101 movq $_start, %rsp
102 addq $FASTBOOT_STACK_OFFSET, %rsp
103
104 /*
105 * Copy from old stack to new stack
106 * If the content before fi_valid gets bigger than 0x200 bytes,
107 * the reserved stack size above will need to be changed.
108 */
109 movq %rdi, %rsi /* source from old stack */
110 movq %rsp, %rdi /* destination on the new stack */
111 movq $FI_VALID, %rcx /* size to copy */
112 rep
113 smovb
114
115 #elif defined(__i386)
116 movl 0x4(%esp), %esi /* address of fastboot info struct */
117
118 /* Switch to a low memory stack */
119 movl $_start, %esp
120 addl $FASTBOOT_STACK_OFFSET, %esp
121
122 /* Copy struct to stack */
123 movl %esp, %edi /* destination on the new stack */
124 movl $FI_VALID, %ecx /* size to copy */
125 rep
126 smovb
127
128 #endif
129
130 #if defined(__amd64)
131
132 xorl %eax, %eax
133 xorl %edx, %edx
134
135 movl $MSR_AMD_FSBASE, %ecx
136 wrmsr
137
138 movl $MSR_AMD_GSBASE, %ecx
139 wrmsr
140
141 movl $MSR_AMD_KGSBASE, %ecx
142 wrmsr
143
144 #endif
145 /*
146 * zero out all the registers to make sure they're 16 bit clean
147 */
148 #if defined(__amd64)
149 xorq %r8, %r8
150 xorq %r9, %r9
151 xorq %r10, %r10
152 xorq %r11, %r11
153 xorq %r12, %r12
154 xorq %r13, %r13
155 xorq %r14, %r14
156 xorq %r15, %r15
157 #endif
158 xorl %eax, %eax
159 xorl %ebx, %ebx
160 xorl %ecx, %ecx
161 xorl %edx, %edx
162 xorl %ebp, %ebp
163
164 #if defined(__amd64)
165 /*
166 * Load our own GDT
167 */
168 lgdt gdt_info
169 #endif
170 /*
171 * Load our own IDT
172 */
173 lidt idt_info
174
175 #if defined(__amd64)
176 /*
177 * Invalidate all TLB entries.
178 * Load temporary pagetables to copy kernel and boot-archive
179 */
180 movq %cr4, %rax
181 andq $_BITNOT(CR4_PGE), %rax
182 movq %rax, %cr4
183 movq FI_PAGETABLE_PA(%rsp), %rax
184 movq %rax, %cr3
185
186 leaq FI_FILES(%rsp), %rbx /* offset to the files */
187
188 /* copy unix to final destination */
189 movq FI_LAST_TABLE_PA(%rsp), %rsi /* page table PA */
190 leaq _MUL(FASTBOOT_UNIX, FI_FILES_INCR)(%rbx), %rdi
191 call map_copy
192
193 /* copy boot archive to final destination */
194 movq FI_LAST_TABLE_PA(%rsp), %rsi /* page table PA */
195 leaq _MUL(FASTBOOT_BOOTARCHIVE, FI_FILES_INCR)(%rbx), %rdi
212 pushq $B32CODE_SEL
213 pushq $1f
214 iretq
215
216 .code32
217 1:
218 movl $B32DATA_SEL, %eax
219 movw %ax, %ss
220 movw %ax, %ds
221 movw %ax, %es
222 movw %ax, %fs
223 movw %ax, %gs
224
225 /*
226 * Disable long mode by:
227 * - shutting down paging (bit 31 of cr0). This will flush the
228 * TLBs.
229 * - turning off PCID in cr4
230 * - disabling LME (long mode enable) in EFER (extended feature reg)
231 */
232 #endif
233 DISABLE_PAGING /* clobbers %eax */
234
235 #if defined(__amd64)
236 ljmp $B32CODE_SEL, $1f
237 1:
238 #endif
239
240 /*
241 * Clear PGE, PAE and PSE flags as dboot expects them to be
242 * cleared.
243 */
244 movl %cr4, %eax
245 andl $_BITNOT(CR4_PGE | CR4_PAE | CR4_PSE), %eax
246 movl %eax, %cr4
247
248 #if defined(__amd64)
249 movl $MSR_AMD_EFER, %ecx /* Extended Feature Enable */
250 rdmsr
251 btcl $8, %eax /* bit 8 Long Mode Enable bit */
252 wrmsr
253
254 #elif defined(__i386)
255 /*
256 * If fi_has_pae is set, re-enable paging with PAE.
257 */
258 leal FI_FILES(%esp), %ebx /* offset to the files */
259 movl FI_HAS_PAE(%esp), %edi /* need to enable paging or not */
260 cmpl $0, %edi
261 je paging_on /* no need to enable paging */
262
263 movl FI_LAST_TABLE_PA(%esp), %esi /* page table PA */
264
265 /*
266 * Turn on PAE
267 */
268 movl %cr4, %eax
269 orl $CR4_PAE, %eax
270 movl %eax, %cr4
271
272 /*
273 * Load top pagetable base address into cr3
274 */
275 movl FI_PAGETABLE_PA(%esp), %eax
276 movl %eax, %cr3
277
278 movl %cr0, %eax
279 orl $_CONST(CR0_PG | CR0_WP | CR0_AM), %eax
280 andl $_BITNOT(CR0_NW | CR0_CD), %eax
281 movl %eax, %cr0
282 jmp paging_on
283 paging_on:
284
285 /* copy unix to final destination */
286 leal _MUL(FASTBOOT_UNIX, FI_FILES_INCR)(%ebx), %edx
287 call map_copy
288
289 /* copy boot archive to final destination */
290 leal _MUL(FASTBOOT_BOOTARCHIVE, FI_FILES_INCR)(%ebx), %edx
291 call map_copy
292
293 /* Disable paging one more time */
294 DISABLE_PAGING
295
296 /* Copy sections if there are any */
297 leal _MUL(FASTBOOT_UNIX, FI_FILES_INCR)(%ebx), %edx
298 movl FB_SECTCNT(%edx), %eax
299 cmpl $0, %eax
300 je 1f
301 call copy_sections
302 1:
303
304 /* Whatever flags we turn on we need to turn off */
305 movl %cr4, %eax
306 andl $_BITNOT(CR4_PAE), %eax
307 movl %eax, %cr4
308 #endif /* __i386 */
309
310 dboot_jump:
311 /* Jump to dboot */
312 movl $DBOOT_ENTRY_ADDRESS, %edi
313 movl FI_NEW_MBI_PA(%esp), %ebx
314 movl $MB_BOOTLOADER_MAGIC, %eax
315 jmp *%edi
316
317 #if defined(__amd64)
318
319 .code64
320 ENTRY_NP(copy_sections)
321 /*
322 * On entry
323 * %rdi points to the fboot_file_t
324 * %rsi contains number of sections
325 */
326 movq %rdi, %rdx
327 movq %rsi, %r9
328
329 COPY_SECT(%rdx, %r8, %r9)
330 ret
331 SET_SIZE(copy_sections)
332
333 ENTRY_NP(map_copy)
334 /*
335 * On entry
336 * %rdi points to the fboot_file_t
337 * %rsi has FI_LAST_TABLE_PA(%rsp)
338 */
344
345 2:
346 movq (%rax), %rcx /* Are we done? */
347 cmpl $FASTBOOT_TERMINATE, %ecx
348 je 1f
349
350 movq %rcx, (%r8)
351 movq %cr3, %rsi /* Reload cr3 */
352 movq %rsi, %cr3
353 movq FB_VA(%rdx), %rsi /* Load from VA */
354 movq $PAGESIZE, %rcx
355 shrq $3, %rcx /* 8-byte at a time */
356 rep
357 smovq
358 addq $8, %rax /* Go to next PTE */
359 jmp 2b
360 1:
361 ret
362 SET_SIZE(map_copy)
363
364 #elif defined(__i386)
365
366 ENTRY_NP(copy_sections)
367 /*
368 * On entry
369 * %edx points to the fboot_file_t
370 * %eax contains the number of sections
371 */
372 pushl %ebp
373 pushl %ebx
374 pushl %esi
375 pushl %edi
376
377 movl %eax, %ebp
378
379 COPY_SECT(%edx, %ebx, %ebp)
380
381 popl %edi
382 popl %esi
383 popl %ebx
384 popl %ebp
385 ret
386 SET_SIZE(copy_sections)
387
388 ENTRY_NP(map_copy)
389 /*
390 * On entry
391 * %edx points to the fboot_file_t
392 * %edi has FB_HAS_PAE(%esp)
393 * %esi has FI_LAST_TABLE_PA(%esp)
394 */
395 pushl %eax
396 pushl %ebx
397 pushl %ecx
398 pushl %edx
399 pushl %ebp
400 pushl %esi
401 pushl %edi
402 movl %esi, %ebp /* Save page table PA in %ebp */
403
404 movl FB_PTE_LIST_PA(%edx), %eax /* PA list of the source */
405 movl FB_DEST_PA(%edx), %ebx /* PA of the destination */
406
407 loop:
408 movl (%eax), %esi /* Are we done? */
409 cmpl $FASTBOOT_TERMINATE, %esi
410 je done
411
412 cmpl $1, (%esp) /* Is paging on? */
413 jne no_paging /* Nope */
414
415 movl %ebp, %edi /* Page table PA */
416 movl %esi, (%edi) /* Program low 32-bit */
417 movl 4(%eax), %esi /* high bits of the table */
418 movl %esi, 4(%edi) /* Program high 32-bit */
419 movl %cr3, %esi /* Reload cr3 */
420 movl %esi, %cr3
421 movl FB_VA(%edx), %esi /* Load from VA */
422 jmp do_copy
423 no_paging:
424 andl $_BITNOT(MMU_PAGEOFFSET), %esi /* clear lower 12-bit */
425 do_copy:
426 movl %ebx, %edi
427 movl $PAGESIZE, %ecx
428 shrl $2, %ecx /* 4-byte at a time */
429 rep
430 smovl
431 addl $8, %eax /* We built the PTEs as 8-byte entries */
432 addl $PAGESIZE, %ebx
433 jmp loop
434 done:
435 popl %edi
436 popl %esi
437 popl %ebp
438 popl %edx
439 popl %ecx
440 popl %ebx
441 popl %eax
442 ret
443 SET_SIZE(map_copy)
444 #endif /* __i386 */
445
446
447 idt_info:
448 .value 0x3ff
449 .quad 0
450
451 /*
452 * We need to trampoline thru a gdt we have in low memory.
453 */
454 #include "../boot/boot_gdt.s"
455 #endif /* __lint */
|
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 * Copyright 2018 Joyent, Inc.
26 */
27
28
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"
36
37 /*
38 * This code is to switch from 64-bit or 32-bit to protected mode.
39 */
40
41 /*
42 * For debugging with LEDs
43 */
44 #define FB_OUTB_ASM(val) \
45 movb val, %al; \
46 outb $0x80;
47
48
73 addl FB_SEC_OFFSET(fbs), %esi; \
74 movl FB_SEC_PADDR(fbs), %edi; \
75 movl FB_SEC_SIZE(fbs), %ecx; \
76 rep \
77 movsb; \
78 /* Zero BSS */ \
79 movl FB_SEC_BSS_SIZE(fbs), %ecx; \
80 rep \
81 stosb; \
82 add $FB_SECTIONS_INCR, fbs; \
83 dec snum; \
84 jnz 1b
85
86
87 .globl _start
88 _start:
89
90 /* Disable interrupts */
91 cli
92
93 /* Switch to a low memory stack */
94 movq $_start, %rsp
95 addq $FASTBOOT_STACK_OFFSET, %rsp
96
97 /*
98 * Copy from old stack to new stack
99 * If the content before fi_valid gets bigger than 0x200 bytes,
100 * the reserved stack size above will need to be changed.
101 */
102 movq %rdi, %rsi /* source from old stack */
103 movq %rsp, %rdi /* destination on the new stack */
104 movq $FI_VALID, %rcx /* size to copy */
105 rep
106 smovb
107
108 xorl %eax, %eax
109 xorl %edx, %edx
110
111 movl $MSR_AMD_FSBASE, %ecx
112 wrmsr
113
114 movl $MSR_AMD_GSBASE, %ecx
115 wrmsr
116
117 movl $MSR_AMD_KGSBASE, %ecx
118 wrmsr
119
120 /*
121 * zero out all the registers to make sure they're 16 bit clean
122 */
123 xorq %r8, %r8
124 xorq %r9, %r9
125 xorq %r10, %r10
126 xorq %r11, %r11
127 xorq %r12, %r12
128 xorq %r13, %r13
129 xorq %r14, %r14
130 xorq %r15, %r15
131 xorl %eax, %eax
132 xorl %ebx, %ebx
133 xorl %ecx, %ecx
134 xorl %edx, %edx
135 xorl %ebp, %ebp
136
137 /*
138 * Load our own GDT
139 */
140 lgdt gdt_info
141 /*
142 * Load our own IDT
143 */
144 lidt idt_info
145
146 /*
147 * Invalidate all TLB entries.
148 * Load temporary pagetables to copy kernel and boot-archive
149 */
150 movq %cr4, %rax
151 andq $_BITNOT(CR4_PGE), %rax
152 movq %rax, %cr4
153 movq FI_PAGETABLE_PA(%rsp), %rax
154 movq %rax, %cr3
155
156 leaq FI_FILES(%rsp), %rbx /* offset to the files */
157
158 /* copy unix to final destination */
159 movq FI_LAST_TABLE_PA(%rsp), %rsi /* page table PA */
160 leaq _MUL(FASTBOOT_UNIX, FI_FILES_INCR)(%rbx), %rdi
161 call map_copy
162
163 /* copy boot archive to final destination */
164 movq FI_LAST_TABLE_PA(%rsp), %rsi /* page table PA */
165 leaq _MUL(FASTBOOT_BOOTARCHIVE, FI_FILES_INCR)(%rbx), %rdi
182 pushq $B32CODE_SEL
183 pushq $1f
184 iretq
185
186 .code32
187 1:
188 movl $B32DATA_SEL, %eax
189 movw %ax, %ss
190 movw %ax, %ds
191 movw %ax, %es
192 movw %ax, %fs
193 movw %ax, %gs
194
195 /*
196 * Disable long mode by:
197 * - shutting down paging (bit 31 of cr0). This will flush the
198 * TLBs.
199 * - turning off PCID in cr4
200 * - disabling LME (long mode enable) in EFER (extended feature reg)
201 */
202 DISABLE_PAGING /* clobbers %eax */
203
204 ljmp $B32CODE_SEL, $1f
205 1:
206
207 /*
208 * Clear PGE, PAE and PSE flags as dboot expects them to be
209 * cleared.
210 */
211 movl %cr4, %eax
212 andl $_BITNOT(CR4_PGE | CR4_PAE | CR4_PSE), %eax
213 movl %eax, %cr4
214
215 movl $MSR_AMD_EFER, %ecx /* Extended Feature Enable */
216 rdmsr
217 btcl $8, %eax /* bit 8 Long Mode Enable bit */
218 wrmsr
219
220 dboot_jump:
221 /* Jump to dboot */
222 movl $DBOOT_ENTRY_ADDRESS, %edi
223 movl FI_NEW_MBI_PA(%esp), %ebx
224 movl $MB_BOOTLOADER_MAGIC, %eax
225 jmp *%edi
226
227 .code64
228 ENTRY_NP(copy_sections)
229 /*
230 * On entry
231 * %rdi points to the fboot_file_t
232 * %rsi contains number of sections
233 */
234 movq %rdi, %rdx
235 movq %rsi, %r9
236
237 COPY_SECT(%rdx, %r8, %r9)
238 ret
239 SET_SIZE(copy_sections)
240
241 ENTRY_NP(map_copy)
242 /*
243 * On entry
244 * %rdi points to the fboot_file_t
245 * %rsi has FI_LAST_TABLE_PA(%rsp)
246 */
252
253 2:
254 movq (%rax), %rcx /* Are we done? */
255 cmpl $FASTBOOT_TERMINATE, %ecx
256 je 1f
257
258 movq %rcx, (%r8)
259 movq %cr3, %rsi /* Reload cr3 */
260 movq %rsi, %cr3
261 movq FB_VA(%rdx), %rsi /* Load from VA */
262 movq $PAGESIZE, %rcx
263 shrq $3, %rcx /* 8-byte at a time */
264 rep
265 smovq
266 addq $8, %rax /* Go to next PTE */
267 jmp 2b
268 1:
269 ret
270 SET_SIZE(map_copy)
271
272 idt_info:
273 .value 0x3ff
274 .quad 0
275
276 /*
277 * We need to trampoline thru a gdt we have in low memory.
278 */
279 #include "../boot/boot_gdt.s"
|