1 2/* 3 * CDDL HEADER START 4 * 5 * The contents of this file are subject to the terms of the 6 * Common Development and Distribution License (the "License"). 7 * You may not use this file except in compliance with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 23/* 24 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 */ 27 28#if defined(__lint) 29 30int silence_lint_warnings = 0; 31 32#else /* __lint */ 33 34#include <sys/multiboot.h> 35#include <sys/asm_linkage.h> 36#include <sys/segments.h> 37#include <sys/controlregs.h> 38 39#include "dboot_xboot.h" 40 41 .text 42 .globl _start 43_start: 44 jmp code_start 45 46 /* 47 * The multiboot header has to be at the start of the file 48 * 49 * The 32 bit kernel is ELF32, so the MB header is mostly ignored. 50 * 51 * The 64 bit kernel is ELF64, so we get grub to load the entire 52 * ELF file into memory and trick it into jumping into this code. 53 * The trick is done by a binary utility run after unix is linked, 54 * that rewrites the mb_header. 55 */ 56 .align 4 57 .globl mb_header 58mb_header: 59 .long MB_HEADER_MAGIC /* magic number */ 60#if defined(_BOOT_TARGET_i386) 61 .long MB_HEADER_FLAGS_32 /* flags */ 62 .long MB_HEADER_CHECKSUM_32 /* checksum */ 63#elif defined (_BOOT_TARGET_amd64) 64 .long MB_HEADER_FLAGS_64 /* flags */ 65 .long MB_HEADER_CHECKSUM_64 /* checksum */ 66#else 67#error No architecture defined 68#endif 69 .long 0x11111111 /* header_addr: patched by mbh_patch */ 70 .long 0x100000 /* load_addr: patched by mbh_patch */ 71 .long 0 /* load_end_addr - 0 means entire file */ 72 .long 0 /* bss_end_addr */ 73 .long 0x2222222 /* entry_addr: patched by mbh_patch */ 74 .long 0 /* video mode.. */ 75 .long 0 /* width 0 == don't care */ 76 .long 0 /* height 0 == don't care */ 77 .long 0 /* depth 0 == don't care */ 78 79 /* 80 * At entry we are in protected mode, 32 bit execution, paging and 81 * interrupts are disabled. 82 * 83 * EAX == MB_BOOTLOADER_MAGIC 84 * EBX points to multiboot information 85 * segment registers all have segments with base 0, limit == 0xffffffff 86 */ 87code_start: 88 movl %ebx, mb_info 89 90 movl $stack_space, %esp /* load my stack pointer */ 91 addl $STACK_SIZE, %esp 92 93 pushl $0x0 /* push a dead-end frame */ 94 pushl $0x0 95 movl %esp, %ebp 96 97 pushl $0x0 /* clear all processor flags */ 98 popf 99 100 /* 101 * setup a global descriptor table with known contents 102 */ 103 lgdt gdt_info 104 movw $B32DATA_SEL, %ax 105 movw %ax, %ds 106 movw %ax, %es 107 movw %ax, %fs 108 movw %ax, %gs 109 movw %ax, %ss 110 ljmp $B32CODE_SEL, $newgdt 111newgdt: 112 nop 113 114 /* 115 * go off and determine memory config, build page tables, etc. 116 */ 117 call startup_kernel 118 119 120 /* 121 * On amd64 we'll want the stack pointer to be 16 byte aligned. 122 */ 123 andl $0xfffffff0, %esp 124 125 /* 126 * Enable PGE, PAE and large pages 127 */ 128 movl %cr4, %eax 129 testl $1, pge_support 130 jz 1f 131 orl $CR4_PGE, %eax 1321: 133 testl $1, pae_support 134 jz 1f 135 orl $CR4_PAE, %eax 1361: 137 testl $1, largepage_support 138 jz 1f 139 orl $CR4_PSE, %eax 1401: 141 movl %eax, %cr4 142 143 /* 144 * enable NX protection if processor supports it 145 */ 146 testl $1, NX_support 147 jz 1f 148 movl $MSR_AMD_EFER, %ecx 149 rdmsr 150 orl $AMD_EFER_NXE, %eax 151 wrmsr 1521: 153 154 155 /* 156 * load the pagetable base address into cr3 157 */ 158 movl top_page_table, %eax 159 movl %eax, %cr3 160 161#if defined(_BOOT_TARGET_amd64) 162 /* 163 * enable long mode 164 */ 165 movl $MSR_AMD_EFER, %ecx 166 rdmsr 167 orl $AMD_EFER_LME, %eax 168 wrmsr 169#endif 170 171 /* 172 * enable paging, write protection, alignment masking, but disable 173 * the cache disable and write through only bits. 174 */ 175 movl %cr0, %eax 176 orl $_CONST(CR0_PG | CR0_WP | CR0_AM), %eax 177 andl $_BITNOT(CR0_NW | CR0_CD), %eax 178 movl %eax, %cr0 179 jmp paging_on 180paging_on: 181 182 /* 183 * The xboot_info ptr gets passed to the kernel as its argument 184 */ 185 movl bi, %edi 186 movl entry_addr_low, %esi 187 188#if defined(_BOOT_TARGET_i386) 189 190 pushl %edi 191 call *%esi 192 193#elif defined(_BOOT_TARGET_amd64) 194 195 /* 196 * We're still in compatibility mode with 32 bit execution. 197 * Switch to 64 bit mode now by switching to a 64 bit code segment. 198 * then set up and do a lret to get into 64 bit execution. 199 */ 200 pushl $B64CODE_SEL 201 pushl $longmode 202 lret 203longmode: 204 .code64 205 movq $0xffffffff00000000,%rdx 206 orq %rdx, %rsi /* set upper bits of entry addr */ 207 notq %rdx 208 andq %rdx, %rdi /* clean %rdi for passing arg */ 209 call *%rsi 210 211#else 212#error "undefined target" 213#endif 214 215 .code32 216 217 /* 218 * if reset fails halt the system 219 */ 220 ENTRY_NP(dboot_halt) 221 hlt 222 SET_SIZE(dboot_halt) 223 224 /* 225 * flush the TLB 226 */ 227 ENTRY_NP(reload_cr3) 228 movl %cr3, %eax 229 movl %eax, %cr3 230 ret 231 SET_SIZE(reload_cr3) 232 233 /* 234 * Detect if we can do cpuid, see if we can change bit 21 of eflags. 235 * Note we don't do the bizarre tests for Cyrix CPUs in ml/locore.s. 236 * If you're on such a CPU, you're stuck with non-PAE 32 bit kernels. 237 */ 238 ENTRY_NP(have_cpuid) 239 pushf 240 pushf 241 xorl %eax, %eax 242 popl %ecx 243 movl %ecx, %edx 244 xorl $0x200000, %ecx 245 pushl %ecx 246 popf 247 pushf 248 popl %ecx 249 cmpl %ecx, %edx 250 setne %al 251 popf 252 ret 253 SET_SIZE(have_cpuid) 254 255 /* 256 * We want the GDT to be on its own page for better performance 257 * running under hypervisors. 258 */ 259 .skip 4096 260#include "../boot/boot_gdt.s" 261 .skip 4096 262 .long 0 263 264#endif /* __lint */ 265