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 * 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 49 #define DISABLE_PAGING \ 50 movl %cr4, %eax ;\ 51 btrl $17, %eax /* clear PCIDE bit */ ;\ 52 movl %eax, %cr4 ;\ 53 movl %cr0, %eax ;\ 54 btrl $31, %eax /* clear PG bit */ ;\ 55 movl %eax, %cr0 56 57 /* 58 * This macro contains common code for 64/32-bit versions of copy_sections(). 59 * On entry: 60 * fbf points to the fboot_file_t 61 * snum contains the number of sections 62 * Registers that would be clobbered: 63 * fbs, snum, %eax, %ecx, %edi, %esi. 64 * NOTE: fb_dest_pa is supposed to be in the first 1GB, 65 * therefore it is safe to use 32-bit register to hold it's value 66 * even for 64-bit code. 67 */ 68 69 #define COPY_SECT(fbf, fbs, snum) \ 70 lea FB_SECTIONS(fbf), fbs; \ 71 xorl %eax, %eax; \ 72 1: movl FB_DEST_PA(fbf), %esi; \ 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 166 call map_copy 167 168 /* Copy sections if there are any */ 169 leaq _MUL(FASTBOOT_UNIX, FI_FILES_INCR)(%rbx), %rdi 170 movl FB_SECTCNT(%rdi), %esi 171 cmpl $0, %esi 172 je 1f 173 call copy_sections 174 1: 175 /* 176 * Shut down 64 bit mode. First get into compatiblity mode. 177 */ 178 movq %rsp, %rax 179 pushq $B32DATA_SEL 180 pushq %rax 181 pushf 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 */ 247 248 movq %rdi, %rdx 249 movq %rsi, %r8 250 movq FB_PTE_LIST_PA(%rdx), %rax /* PA list of the source */ 251 movq FB_DEST_PA(%rdx), %rdi /* PA of the destination */ 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"