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.
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.
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]
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
29 int silence_lint_warnings
= 0;
33 #include <sys/multiboot.h>
34 #include <sys/multiboot2.h>
35 #include <sys/asm_linkage.h>
36 #include <sys/segments.h>
37 #include <sys/controlregs.h>
39 #include "dboot_xboot.h"
47 * The multiboot header has to be at the start of the file
49 * The 32 bit kernel is ELF32, so the MB header is mostly ignored.
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.
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 */
67 #error No architecture defined
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 */
79 #if defined(_BOOT_TARGET_i386)
81 * The MB2 header must be 8 byte aligned relative to the beginning of
82 * the in-memory ELF object. The 32-bit kernel ELF file has sections
83 * which are 4-byte aligned, and as .align family directives only do
84 * control the alignment inside the section, we need to construct the
85 * image manually, by inserting the padding where needed. The alignment
86 * setup here depends on the first PT_LOAD section of the ELF file, if
87 * this section offset will change, this code must be reviewed.
88 * Similarily, if we add extra tag types into the information request
89 * or add tags into the tag list.
93 .balign MULTIBOOT_HEADER_ALIGN
96 .long MULTIBOOT2_HEADER_MAGIC
97 .long MULTIBOOT_ARCHITECTURE_I386
98 .long mb2_header_end - mb2_header
99 .long -(MULTIBOOT2_HEADER_MAGIC + MULTIBOOT_ARCHITECTURE_I386 + (mb2_header_end - mb2_header))
102 * Multiboot 2 tags follow. Note, the first tag immediately follows
103 * the header. Subsequent tags must be aligned by MULTIBOOT_TAG_ALIGN.
105 * MB information request tag.
107 information_request_tag_start
:
108 .word MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST
110 .long information_request_tag_end - information_request_tag_start
111 .long MULTIBOOT_TAG_TYPE_CMDLINE
112 .long MULTIBOOT_TAG_TYPE_MODULE
113 .long MULTIBOOT_TAG_TYPE_BOOTDEV
114 .long MULTIBOOT_TAG_TYPE_MMAP
115 .long MULTIBOOT_TAG_TYPE_BASIC_MEMINFO
116 information_request_tag_end
:
117 .long 0 /* padding */
119 #if defined (_BOOT_TARGET_amd64)
121 * The following values are patched by mbh_patch for the 64-bit kernel,
122 * so we only provide this tag for the 64-bit kernel.
124 .balign MULTIBOOT_TAG_ALIGN
126 .word MULTIBOOT_HEADER_TAG_ADDRESS
128 .long address_tag_end - address_tag_start
132 .long 0 /* load addr */
133 .long 0 /* load_end_addr */
134 .long 0 /* bss_end_addr */
139 .balign MULTIBOOT_TAG_ALIGN
140 entry_address_tag_start
:
141 .word MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS
143 .long entry_address_tag_end - entry_address_tag_start
144 .long 0 /* entry addr */
145 entry_address_tag_end
:
147 .balign MULTIBOOT_TAG_ALIGN /* Alignment for the next tag */
150 * MB console flags tag
153 .word MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS
155 .long console_tag_end - console_tag_start
156 .long MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED
158 .long 0 /* padding */
161 * Tell the bootloader to load the modules page aligned to
162 * the specified alignment.
164 .word MULTIBOOT_HEADER_TAG_MODULE_ALIGN
171 .word MULTIBOOT_HEADER_TAG_END
177 * At entry we are in protected mode, 32 bit execution, paging and
178 * interrupts are disabled.
180 * EAX == MB_BOOTLOADER_MAGIC
181 * EBX points to multiboot information
182 * segment registers all have segments with base 0, limit == 0xffffffff
188 movl $stack_space
, %esp
/* load my stack pointer */
189 addl $STACK_SIZE
, %esp
191 pushl $
0x0 /* push a dead-end frame */
195 pushl $
0x0 /* clear all processor flags */
199 * setup a global descriptor table with known contents
202 movw $B32DATA_SEL
, %ax
208 ljmp $B32CODE_SEL
, $newgdt
213 * go off and determine memory config, build page tables, etc.
219 * On amd64 we'll want the stack pointer to be 16 byte aligned.
221 andl $
0xfffffff0, %esp
224 * Enable PGE, PAE and large pages
227 testl $
1, pge_support
231 testl $
1, pae_support
235 testl $
1, largepage_support
242 * enable NX protection if processor supports it
246 movl $MSR_AMD_EFER
, %ecx
248 orl $AMD_EFER_NXE
, %eax
254 * load the pagetable base address into cr3
256 movl top_page_table
, %eax
259 #if defined(_BOOT_TARGET_amd64)
263 movl $MSR_AMD_EFER
, %ecx
265 orl $AMD_EFER_LME
, %eax
270 * enable paging, write protection, alignment masking, but disable
271 * the cache disable and write through only bits.
274 orl $_CONST
(CR0_PG | CR0_WP | CR0_AM
), %eax
275 andl $_BITNOT
(CR0_NW | CR0_CD
), %eax
281 * The xboot_info ptr gets passed to the kernel as its argument
284 movl entry_addr_low
, %esi
286 #if defined(_BOOT_TARGET_i386)
291 #elif defined(_BOOT_TARGET_amd64)
294 * We're still in compatibility mode with 32 bit execution.
295 * Switch to 64 bit mode now by switching to a 64 bit code segment.
296 * then set up and do a lret to get into 64 bit execution.
303 movq $
0xffffffff00000000,%rdx
304 orq
%rdx
, %rsi
/* set upper bits of entry addr */
306 andq
%rdx
, %rdi
/* clean %rdi for passing arg */
310 #error "undefined target"
316 * if reset fails halt the system
332 * Detect if we can do cpuid, see if we can change bit 21 of eflags.
333 * Note we don't do the bizarre tests for Cyrix CPUs in ml/locore.s.
334 * If you're on such a CPU, you're stuck with non-PAE 32 bit kernels.
354 * We want the GDT to be on its own page for better performance
355 * running under hypervisors.
358 #include "../boot/boot_gdt.s"