xref: /titanic_52/usr/src/uts/i86pc/dboot/dboot_grub.s (revision dd51520e127b452179a2ce4ea3bd8dee949f9afe)
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