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