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 166 */ 167 movl %cr0, %eax 168 orl $CR0_PG, %eax 169 movl %eax, %cr0 170 jmp paging_on 171paging_on: 172 173 /* 174 * The xboot_info ptr gets passed to the kernel as its argument 175 */ 176 movl bi, %edi 177 movl entry_addr_low, %esi 178 179#if defined(_BOOT_TARGET_i386) 180 181 pushl %edi 182 call *%esi 183 184#elif defined(_BOOT_TARGET_amd64) 185 186 /* 187 * We're still in compatibility mode with 32 bit execution. 188 * Switch to 64 bit mode now by switching to a 64 bit code segment. 189 * then set up and do a lret to get into 64 bit execution. 190 */ 191 pushl $B64CODE_SEL 192 pushl $longmode 193 lret 194longmode: 195 .code64 196 movq $0xffffffff00000000,%rdx 197 orq %rdx, %rsi /* set upper bits of entry addr */ 198 notq %rdx 199 andq %rdx, %rdi /* clean %rdi for passing arg */ 200 call *%rsi 201 202#else 203#error "undefined target" 204#endif 205 206 .code32 207 208 /* 209 * uint8_t inb(int port) 210 */ 211 ENTRY_NP(inb) 212 movl 4(%esp), %edx 213 inb (%dx) 214 andl $0xff, %eax 215 ret 216 SET_SIZE(inb) 217 218 /* 219 * void outb(int port, uint8_t value) 220 */ 221 ENTRY_NP(outb) 222 movl 4(%esp), %edx 223 movl 8(%esp), %eax 224 outb (%dx) 225 ret 226 SET_SIZE(outb) 227 228 /* 229 * if reset fails halt the system 230 */ 231 ENTRY_NP(dboot_halt) 232 hlt 233 SET_SIZE(dboot_halt) 234 235 /* 236 * flush the TLB 237 */ 238 ENTRY_NP(reload_cr3) 239 movl %cr3, %eax 240 movl %eax, %cr3 241 ret 242 SET_SIZE(reload_cr3) 243 244 /* 245 * do a cpuid instruction, returning the eax/edx values 246 */ 247 ENTRY_NP(get_cpuid_edx) 248 movl 4(%esp), %ecx 249 movl (%ecx), %eax 250 pushl %ebx 251 cpuid 252 popl %ebx 253 movl 4(%esp), %ecx 254 movl %eax, (%ecx) 255 movl %edx, %eax 256 ret 257 SET_SIZE(get_cpuid_edx) 258 259 /* 260 * Detect if we can do cpuid, see if we can change bit 21 of eflags. 261 * Note we don't do the bizarre tests for Cyrix CPUs in ml/locore.s. 262 * If you're on such a CPU, you're stuck with non-PAE 32 bit kernels. 263 */ 264 ENTRY_NP(have_cpuid) 265 pushf 266 pushf 267 xorl %eax, %eax 268 popl %ecx 269 movl %ecx, %edx 270 xorl $0x200000, %ecx 271 pushl %ecx 272 popf 273 pushf 274 popl %ecx 275 cmpl %ecx, %edx 276 setne %al 277 popf 278 ret 279 SET_SIZE(have_cpuid) 280 281#include "../boot/boot_gdt.s" 282 283#endif /* __lint */ 284