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