17656SSherry.Moore@Sun.COM 23446Smrj/* 33446Smrj * CDDL HEADER START 43446Smrj * 53446Smrj * The contents of this file are subject to the terms of the 63446Smrj * Common Development and Distribution License (the "License"). 73446Smrj * You may not use this file except in compliance with the License. 83446Smrj * 93446Smrj * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 103446Smrj * or http://www.opensolaris.org/os/licensing. 113446Smrj * See the License for the specific language governing permissions 123446Smrj * and limitations under the License. 133446Smrj * 143446Smrj * When distributing Covered Code, include this CDDL HEADER in each 153446Smrj * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 163446Smrj * If applicable, add the following below this CDDL HEADER, with the 173446Smrj * fields enclosed by brackets "[]" replaced with your own identifying 183446Smrj * information: Portions Copyright [yyyy] [name of copyright owner] 193446Smrj * 203446Smrj * CDDL HEADER END 213446Smrj */ 223446Smrj 233446Smrj/* 24*10304SSeth.Goldberg@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 253446Smrj * Use is subject to license terms. 263446Smrj */ 273446Smrj 283446Smrj#if defined(__lint) 293446Smrj 303446Smrjint silence_lint_warnings = 0; 313446Smrj 323446Smrj#else /* __lint */ 333446Smrj 343446Smrj#include <sys/multiboot.h> 353446Smrj#include <sys/asm_linkage.h> 363446Smrj#include <sys/segments.h> 373446Smrj#include <sys/controlregs.h> 383446Smrj 393446Smrj#include "dboot_xboot.h" 403446Smrj 413446Smrj .text 423446Smrj .globl _start 433446Smrj_start: 443446Smrj jmp code_start 453446Smrj 463446Smrj /* 473446Smrj * The multiboot header has to be at the start of the file 483446Smrj * 493446Smrj * The 32 bit kernel is ELF32, so the MB header is mostly ignored. 503446Smrj * 513446Smrj * The 64 bit kernel is ELF64, so we get grub to load the entire 523446Smrj * ELF file into memory and trick it into jumping into this code. 533446Smrj * The trick is done by a binary utility run after unix is linked, 543446Smrj * that rewrites the mb_header. 553446Smrj */ 563446Smrj .align 4 573446Smrj .globl mb_header 583446Smrjmb_header: 593446Smrj .long MB_HEADER_MAGIC /* magic number */ 60*10304SSeth.Goldberg@Sun.COM#if defined(_BOOT_TARGET_i386) 61*10304SSeth.Goldberg@Sun.COM .long MB_HEADER_FLAGS_32 /* flags */ 62*10304SSeth.Goldberg@Sun.COM .long MB_HEADER_CHECKSUM_32 /* checksum */ 63*10304SSeth.Goldberg@Sun.COM#elif defined (_BOOT_TARGET_amd64) 64*10304SSeth.Goldberg@Sun.COM .long MB_HEADER_FLAGS_64 /* flags */ 65*10304SSeth.Goldberg@Sun.COM .long MB_HEADER_CHECKSUM_64 /* checksum */ 66*10304SSeth.Goldberg@Sun.COM#else 67*10304SSeth.Goldberg@Sun.COM#error No architecture defined 68*10304SSeth.Goldberg@Sun.COM#endif 69*10304SSeth.Goldberg@Sun.COM .long 0x11111111 /* header_addr: patched by mbh_patch */ 70*10304SSeth.Goldberg@Sun.COM .long 0x100000 /* load_addr: patched by mbh_patch */ 713446Smrj .long 0 /* load_end_addr - 0 means entire file */ 723446Smrj .long 0 /* bss_end_addr */ 73*10304SSeth.Goldberg@Sun.COM .long 0x2222222 /* entry_addr: patched by mbh_patch */ 743446Smrj .long 0 /* video mode.. */ 753446Smrj .long 0 /* width 0 == don't care */ 763446Smrj .long 0 /* height 0 == don't care */ 773446Smrj .long 0 /* depth 0 == don't care */ 783446Smrj 793446Smrj /* 803446Smrj * At entry we are in protected mode, 32 bit execution, paging and 813446Smrj * interrupts are disabled. 823446Smrj * 837656SSherry.Moore@Sun.COM * EAX == MB_BOOTLOADER_MAGIC 843446Smrj * EBX points to multiboot information 853446Smrj * segment registers all have segments with base 0, limit == 0xffffffff 863446Smrj */ 873446Smrjcode_start: 883446Smrj movl %ebx, mb_info 893446Smrj 903446Smrj movl $stack_space, %esp /* load my stack pointer */ 913446Smrj addl $STACK_SIZE, %esp 923446Smrj 933446Smrj pushl $0x0 /* push a dead-end frame */ 943446Smrj pushl $0x0 953446Smrj movl %esp, %ebp 963446Smrj 973446Smrj pushl $0x0 /* clear all processor flags */ 983446Smrj popf 993446Smrj 1003446Smrj /* 1013446Smrj * setup a global descriptor table with known contents 1023446Smrj */ 1033446Smrj lgdt gdt_info 1043446Smrj movw $B32DATA_SEL, %ax 1053446Smrj movw %ax, %ds 1063446Smrj movw %ax, %es 1073446Smrj movw %ax, %fs 1083446Smrj movw %ax, %gs 1093446Smrj movw %ax, %ss 1103446Smrj ljmp $B32CODE_SEL, $newgdt 1113446Smrjnewgdt: 1123446Smrj nop 1133446Smrj 1143446Smrj /* 1153446Smrj * go off and determine memory config, build page tables, etc. 1163446Smrj */ 1173446Smrj call startup_kernel 1183446Smrj 1197656SSherry.Moore@Sun.COM 1203446Smrj /* 1213446Smrj * On amd64 we'll want the stack pointer to be 16 byte aligned. 1223446Smrj */ 1233446Smrj andl $0xfffffff0, %esp 1243446Smrj 1253446Smrj /* 1263446Smrj * Enable PGE, PAE and large pages 1273446Smrj */ 1283446Smrj movl %cr4, %eax 1293446Smrj testl $1, pge_support 1303446Smrj jz 1f 1313446Smrj orl $CR4_PGE, %eax 1323446Smrj1: 1333446Smrj testl $1, pae_support 1343446Smrj jz 1f 1353446Smrj orl $CR4_PAE, %eax 1363446Smrj1: 1373446Smrj testl $1, largepage_support 1383446Smrj jz 1f 1393446Smrj orl $CR4_PSE, %eax 1403446Smrj1: 1413446Smrj movl %eax, %cr4 1423446Smrj 1433446Smrj /* 1443446Smrj * enable NX protection if processor supports it 1453446Smrj */ 1463446Smrj testl $1, NX_support 1473446Smrj jz 1f 1483446Smrj movl $MSR_AMD_EFER, %ecx 1493446Smrj rdmsr 1503446Smrj orl $AMD_EFER_NXE, %eax 1513446Smrj wrmsr 1523446Smrj1: 1533446Smrj 1543446Smrj 1553446Smrj /* 1563446Smrj * load the pagetable base address into cr3 1573446Smrj */ 1583446Smrj movl top_page_table, %eax 1593446Smrj movl %eax, %cr3 1603446Smrj 1613446Smrj#if defined(_BOOT_TARGET_amd64) 1623446Smrj /* 1633446Smrj * enable long mode 1643446Smrj */ 1653446Smrj movl $MSR_AMD_EFER, %ecx 1663446Smrj rdmsr 1673446Smrj orl $AMD_EFER_LME, %eax 1683446Smrj wrmsr 1693446Smrj#endif 1703446Smrj 1713446Smrj /* 1725084Sjohnlev * enable paging, write protection, alignment masking, but disable 1735084Sjohnlev * the cache disable and write through only bits. 1743446Smrj */ 1753446Smrj movl %cr0, %eax 1765084Sjohnlev orl $_CONST(CR0_PG | CR0_WP | CR0_AM), %eax 1775084Sjohnlev andl $_BITNOT(CR0_NW | CR0_CD), %eax 1783446Smrj movl %eax, %cr0 1793446Smrj jmp paging_on 1803446Smrjpaging_on: 1813446Smrj 1823446Smrj /* 1833446Smrj * The xboot_info ptr gets passed to the kernel as its argument 1843446Smrj */ 1853446Smrj movl bi, %edi 1863446Smrj movl entry_addr_low, %esi 1873446Smrj 1883446Smrj#if defined(_BOOT_TARGET_i386) 1893446Smrj 1903446Smrj pushl %edi 1913446Smrj call *%esi 1923446Smrj 1933446Smrj#elif defined(_BOOT_TARGET_amd64) 1943446Smrj 1953446Smrj /* 1963446Smrj * We're still in compatibility mode with 32 bit execution. 1973446Smrj * Switch to 64 bit mode now by switching to a 64 bit code segment. 1983446Smrj * then set up and do a lret to get into 64 bit execution. 1993446Smrj */ 2003446Smrj pushl $B64CODE_SEL 2013446Smrj pushl $longmode 2023446Smrj lret 2033446Smrjlongmode: 2043446Smrj .code64 2053446Smrj movq $0xffffffff00000000,%rdx 2063446Smrj orq %rdx, %rsi /* set upper bits of entry addr */ 2073446Smrj notq %rdx 2083446Smrj andq %rdx, %rdi /* clean %rdi for passing arg */ 2093446Smrj call *%rsi 2103446Smrj 2113446Smrj#else 2123446Smrj#error "undefined target" 2133446Smrj#endif 2143446Smrj 2153446Smrj .code32 2163446Smrj 2173446Smrj /* 2183446Smrj * if reset fails halt the system 2193446Smrj */ 2203446Smrj ENTRY_NP(dboot_halt) 2213446Smrj hlt 2223446Smrj SET_SIZE(dboot_halt) 2233446Smrj 2243446Smrj /* 2253446Smrj * flush the TLB 2263446Smrj */ 2273446Smrj ENTRY_NP(reload_cr3) 2283446Smrj movl %cr3, %eax 2293446Smrj movl %eax, %cr3 2303446Smrj ret 2313446Smrj SET_SIZE(reload_cr3) 2323446Smrj 2333446Smrj /* 2343446Smrj * Detect if we can do cpuid, see if we can change bit 21 of eflags. 2353446Smrj * Note we don't do the bizarre tests for Cyrix CPUs in ml/locore.s. 2363446Smrj * If you're on such a CPU, you're stuck with non-PAE 32 bit kernels. 2373446Smrj */ 2383446Smrj ENTRY_NP(have_cpuid) 2393446Smrj pushf 2403446Smrj pushf 2413446Smrj xorl %eax, %eax 2423446Smrj popl %ecx 2433446Smrj movl %ecx, %edx 2443446Smrj xorl $0x200000, %ecx 2453446Smrj pushl %ecx 2463446Smrj popf 2473446Smrj pushf 2483446Smrj popl %ecx 2493446Smrj cmpl %ecx, %edx 2503446Smrj setne %al 2513446Smrj popf 2523446Smrj ret 2533446Smrj SET_SIZE(have_cpuid) 2543446Smrj 2555460Sjosephb /* 2565460Sjosephb * We want the GDT to be on its own page for better performance 2575460Sjosephb * running under hypervisors. 2585460Sjosephb */ 2595460Sjosephb .skip 4096 2603446Smrj#include "../boot/boot_gdt.s" 2615460Sjosephb .skip 4096 2625460Sjosephb .long 0 2633446Smrj 2643446Smrj#endif /* __lint */ 265