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