xref: /illumos-gate/usr/src/uts/i86pc/ml/fb_swtch_src.S (revision 55fea89d)
119397407SSherry Moore/*
219397407SSherry Moore * CDDL HEADER START
319397407SSherry Moore *
419397407SSherry Moore * The contents of this file are subject to the terms of the
519397407SSherry Moore * Common Development and Distribution License (the "License").
619397407SSherry Moore * You may not use this file except in compliance with the License.
719397407SSherry Moore *
819397407SSherry Moore * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
919397407SSherry Moore * or http://www.opensolaris.org/os/licensing.
1019397407SSherry Moore * See the License for the specific language governing permissions
1119397407SSherry Moore * and limitations under the License.
1219397407SSherry Moore *
1319397407SSherry Moore * When distributing Covered Code, include this CDDL HEADER in each
1419397407SSherry Moore * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1519397407SSherry Moore * If applicable, add the following below this CDDL HEADER, with the
1619397407SSherry Moore * fields enclosed by brackets "[]" replaced with your own identifying
1719397407SSherry Moore * information: Portions Copyright [yyyy] [name of copyright owner]
1819397407SSherry Moore *
1919397407SSherry Moore * CDDL HEADER END
2019397407SSherry Moore */
2119397407SSherry Moore
2219397407SSherry Moore/*
2319397407SSherry Moore * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
2419397407SSherry Moore * Use is subject to license terms.
2574ecdb51SJohn Levon * Copyright 2018 Joyent, Inc.
2619397407SSherry Moore */
2719397407SSherry Moore
2819397407SSherry Moore
2919397407SSherry Moore#include <sys/asm_linkage.h>
3019397407SSherry Moore#include <sys/segments.h>
3119397407SSherry Moore#include <sys/controlregs.h>
3219397407SSherry Moore#include <sys/machparam.h>
3319397407SSherry Moore#include <sys/multiboot.h>
3419397407SSherry Moore#include <sys/fastboot.h>
3519397407SSherry Moore#include "assym.h"
3619397407SSherry Moore
3719397407SSherry Moore/*
3819397407SSherry Moore * This code is to switch from 64-bit or 32-bit to protected mode.
3919397407SSherry Moore */
4019397407SSherry Moore
4119397407SSherry Moore/*
4219397407SSherry Moore * For debugging with LEDs
4319397407SSherry Moore */
4419397407SSherry Moore#define	FB_OUTB_ASM(val)	\
4519397407SSherry Moore    movb	val, %al;	\
4619397407SSherry Moore    outb	$0x80;
4719397407SSherry Moore
4819397407SSherry Moore
4919397407SSherry Moore#define	DISABLE_PAGING							\
5074ecdb51SJohn Levon	movl	%cr4, %eax						;\
5174ecdb51SJohn Levon	btrl	$17, %eax	/* clear PCIDE bit */			;\
5274ecdb51SJohn Levon	movl	%eax, %cr4						;\
5319397407SSherry Moore	movl	%cr0, %eax						;\
5419397407SSherry Moore	btrl	$31, %eax	/* clear PG bit */			;\
5519397407SSherry Moore	movl	%eax, %cr0
5619397407SSherry Moore
57877400d3SKonstantin Ananyev/*
58877400d3SKonstantin Ananyev * This macro contains common code for 64/32-bit versions of copy_sections().
59877400d3SKonstantin Ananyev * On entry:
60877400d3SKonstantin Ananyev *	fbf points to the fboot_file_t
61877400d3SKonstantin Ananyev *	snum contains the number of sections
62877400d3SKonstantin Ananyev * Registers that would be clobbered:
63877400d3SKonstantin Ananyev *	fbs, snum, %eax, %ecx, %edi, %esi.
64877400d3SKonstantin Ananyev * NOTE: fb_dest_pa is supposed to be in the first 1GB,
65877400d3SKonstantin Ananyev * therefore it is safe to use 32-bit register to hold it's value
66877400d3SKonstantin Ananyev * even for 64-bit code.
67877400d3SKonstantin Ananyev */
68877400d3SKonstantin Ananyev
69877400d3SKonstantin Ananyev#define	COPY_SECT(fbf, fbs, snum)		\
70877400d3SKonstantin Ananyev	lea	FB_SECTIONS(fbf), fbs;		\
71877400d3SKonstantin Ananyev	xorl	%eax, %eax;			\
72877400d3SKonstantin Ananyev1:	movl	FB_DEST_PA(fbf), %esi;		\
73877400d3SKonstantin Ananyev	addl	FB_SEC_OFFSET(fbs), %esi;	\
74877400d3SKonstantin Ananyev	movl	FB_SEC_PADDR(fbs), %edi;	\
75877400d3SKonstantin Ananyev	movl	FB_SEC_SIZE(fbs), %ecx;		\
76877400d3SKonstantin Ananyev	rep					\
77877400d3SKonstantin Ananyev	  movsb;				\
78877400d3SKonstantin Ananyev	/* Zero BSS */				\
79877400d3SKonstantin Ananyev	movl	FB_SEC_BSS_SIZE(fbs), %ecx;	\
80877400d3SKonstantin Ananyev	rep					\
81877400d3SKonstantin Ananyev	  stosb;				\
82877400d3SKonstantin Ananyev	add	$FB_SECTIONS_INCR, fbs;		\
83877400d3SKonstantin Ananyev	dec	snum;				\
84877400d3SKonstantin Ananyev	jnz	1b
85877400d3SKonstantin Ananyev
8619397407SSherry Moore
8719397407SSherry Moore	.globl	_start
8819397407SSherry Moore_start:
8919397407SSherry Moore
9019397407SSherry Moore	/* Disable interrupts */
9119397407SSherry Moore	cli
9219397407SSherry Moore
9319397407SSherry Moore	/* Switch to a low memory stack */
9419397407SSherry Moore	movq	$_start, %rsp
9519397407SSherry Moore	addq	$FASTBOOT_STACK_OFFSET, %rsp
9619397407SSherry Moore
9719397407SSherry Moore	/*
9819397407SSherry Moore	 * Copy from old stack to new stack
9919397407SSherry Moore	 * If the content before fi_valid gets bigger than 0x200 bytes,
10019397407SSherry Moore	 * the reserved stack size above will need to be changed.
10119397407SSherry Moore	 */
10219397407SSherry Moore	movq	%rdi, %rsi	/* source from old stack */
10319397407SSherry Moore	movq	%rsp, %rdi	/* destination on the new stack */
10419397407SSherry Moore	movq	$FI_VALID, %rcx	/* size to copy */
10519397407SSherry Moore	rep
10619397407SSherry Moore	  smovb
10719397407SSherry Moore
10819397407SSherry Moore	xorl	%eax, %eax
10919397407SSherry Moore	xorl	%edx, %edx
11019397407SSherry Moore
11119397407SSherry Moore	movl	$MSR_AMD_FSBASE, %ecx
11219397407SSherry Moore	wrmsr
11319397407SSherry Moore
11419397407SSherry Moore	movl	$MSR_AMD_GSBASE, %ecx
11519397407SSherry Moore	wrmsr
11619397407SSherry Moore
11719397407SSherry Moore	movl	$MSR_AMD_KGSBASE, %ecx
11819397407SSherry Moore	wrmsr
11919397407SSherry Moore
12019397407SSherry Moore	/*
12119397407SSherry Moore	 * zero out all the registers to make sure they're 16 bit clean
12219397407SSherry Moore	 */
12319397407SSherry Moore	xorq	%r8, %r8
12419397407SSherry Moore	xorq	%r9, %r9
12519397407SSherry Moore	xorq	%r10, %r10
12619397407SSherry Moore	xorq	%r11, %r11
12719397407SSherry Moore	xorq	%r12, %r12
12819397407SSherry Moore	xorq	%r13, %r13
12919397407SSherry Moore	xorq	%r14, %r14
13019397407SSherry Moore	xorq	%r15, %r15
13119397407SSherry Moore	xorl	%eax, %eax
13219397407SSherry Moore	xorl	%ebx, %ebx
13319397407SSherry Moore	xorl	%ecx, %ecx
13419397407SSherry Moore	xorl	%edx, %edx
13519397407SSherry Moore	xorl	%ebp, %ebp
13619397407SSherry Moore
13719397407SSherry Moore	/*
13819397407SSherry Moore	 * Load our own GDT
13919397407SSherry Moore	 */
14019397407SSherry Moore	lgdt	gdt_info
14119397407SSherry Moore	/*
14219397407SSherry Moore	 * Load our own IDT
14319397407SSherry Moore	 */
14419397407SSherry Moore	lidt	idt_info
14519397407SSherry Moore
146877400d3SKonstantin Ananyev	/*
147877400d3SKonstantin Ananyev	 * Invalidate all TLB entries.
148877400d3SKonstantin Ananyev	 * Load temporary pagetables to copy kernel and boot-archive
149877400d3SKonstantin Ananyev	 */
150877400d3SKonstantin Ananyev	movq	%cr4, %rax
151877400d3SKonstantin Ananyev	andq	$_BITNOT(CR4_PGE), %rax
152877400d3SKonstantin Ananyev	movq	%rax, %cr4
153877400d3SKonstantin Ananyev	movq	FI_PAGETABLE_PA(%rsp), %rax
154877400d3SKonstantin Ananyev	movq	%rax, %cr3
155877400d3SKonstantin Ananyev
156877400d3SKonstantin Ananyev	leaq	FI_FILES(%rsp), %rbx	/* offset to the files */
157877400d3SKonstantin Ananyev
158877400d3SKonstantin Ananyev	/* copy unix to final destination */
159877400d3SKonstantin Ananyev	movq	FI_LAST_TABLE_PA(%rsp), %rsi	/* page table PA */
160877400d3SKonstantin Ananyev	leaq	_MUL(FASTBOOT_UNIX, FI_FILES_INCR)(%rbx), %rdi
161877400d3SKonstantin Ananyev	call	map_copy
162877400d3SKonstantin Ananyev
163877400d3SKonstantin Ananyev	/* copy boot archive to final destination */
164877400d3SKonstantin Ananyev	movq	FI_LAST_TABLE_PA(%rsp), %rsi	/* page table PA */
165877400d3SKonstantin Ananyev	leaq	_MUL(FASTBOOT_BOOTARCHIVE, FI_FILES_INCR)(%rbx), %rdi
166877400d3SKonstantin Ananyev	call	map_copy
167877400d3SKonstantin Ananyev
168*55fea89dSDan Cross	/* Copy sections if there are any */
169877400d3SKonstantin Ananyev	leaq	_MUL(FASTBOOT_UNIX, FI_FILES_INCR)(%rbx), %rdi
170877400d3SKonstantin Ananyev	movl	FB_SECTCNT(%rdi), %esi
171877400d3SKonstantin Ananyev	cmpl	$0, %esi
172877400d3SKonstantin Ananyev	je	1f
173877400d3SKonstantin Ananyev	call	copy_sections
174877400d3SKonstantin Ananyev1:
17519397407SSherry Moore	/*
17619397407SSherry Moore	 * Shut down 64 bit mode. First get into compatiblity mode.
17719397407SSherry Moore	 */
17819397407SSherry Moore	movq	%rsp, %rax
17919397407SSherry Moore	pushq	$B32DATA_SEL
18019397407SSherry Moore	pushq	%rax
18119397407SSherry Moore	pushf
18219397407SSherry Moore	pushq	$B32CODE_SEL
18319397407SSherry Moore	pushq	$1f
18419397407SSherry Moore	iretq
18519397407SSherry Moore
18619397407SSherry Moore	.code32
18719397407SSherry Moore1:
18819397407SSherry Moore	movl	$B32DATA_SEL, %eax
18919397407SSherry Moore	movw	%ax, %ss
19019397407SSherry Moore	movw	%ax, %ds
19119397407SSherry Moore	movw	%ax, %es
19219397407SSherry Moore	movw	%ax, %fs
19319397407SSherry Moore	movw	%ax, %gs
19419397407SSherry Moore
19519397407SSherry Moore	/*
19619397407SSherry Moore	 * Disable long mode by:
19719397407SSherry Moore	 * - shutting down paging (bit 31 of cr0).  This will flush the
19819397407SSherry Moore	 *   TLBs.
19974ecdb51SJohn Levon	 * - turning off PCID in cr4
200877400d3SKonstantin Ananyev	 * - disabling LME (long mode enable) in EFER (extended feature reg)
20119397407SSherry Moore	 */
20219397407SSherry Moore	DISABLE_PAGING		/* clobbers %eax */
20319397407SSherry Moore
20419397407SSherry Moore	ljmp	$B32CODE_SEL, $1f
20519397407SSherry Moore1:
20619397407SSherry Moore
20719397407SSherry Moore	/*
20819397407SSherry Moore	 * Clear PGE, PAE and PSE flags as dboot expects them to be
20919397407SSherry Moore	 * cleared.
21019397407SSherry Moore	 */
21119397407SSherry Moore	movl	%cr4, %eax
21219397407SSherry Moore	andl	$_BITNOT(CR4_PGE | CR4_PAE | CR4_PSE), %eax
21319397407SSherry Moore	movl	%eax, %cr4
21419397407SSherry Moore
21519397407SSherry Moore	movl	$MSR_AMD_EFER, %ecx	/* Extended Feature Enable */
21619397407SSherry Moore	rdmsr
21719397407SSherry Moore	btcl	$8, %eax		/* bit 8 Long Mode Enable bit */
21819397407SSherry Moore	wrmsr
21919397407SSherry Moore
22019397407SSherry Mooredboot_jump:
22119397407SSherry Moore	/* Jump to dboot */
22219397407SSherry Moore	movl	$DBOOT_ENTRY_ADDRESS, %edi
22319397407SSherry Moore	movl	FI_NEW_MBI_PA(%esp), %ebx
22419397407SSherry Moore	movl	$MB_BOOTLOADER_MAGIC, %eax
22519397407SSherry Moore	jmp	*%edi
22619397407SSherry Moore
227877400d3SKonstantin Ananyev	.code64
228877400d3SKonstantin Ananyev	ENTRY_NP(copy_sections)
229877400d3SKonstantin Ananyev	/*
230877400d3SKonstantin Ananyev	 * On entry
231877400d3SKonstantin Ananyev	 *	%rdi points to the fboot_file_t
232877400d3SKonstantin Ananyev	 *	%rsi contains number of sections
233877400d3SKonstantin Ananyev	 */
234877400d3SKonstantin Ananyev	movq	%rdi, %rdx
235877400d3SKonstantin Ananyev	movq	%rsi, %r9
236877400d3SKonstantin Ananyev
237877400d3SKonstantin Ananyev	COPY_SECT(%rdx, %r8, %r9)
238877400d3SKonstantin Ananyev	ret
239877400d3SKonstantin Ananyev	SET_SIZE(copy_sections)
240877400d3SKonstantin Ananyev
241877400d3SKonstantin Ananyev	ENTRY_NP(map_copy)
242877400d3SKonstantin Ananyev	/*
243877400d3SKonstantin Ananyev	 * On entry
244877400d3SKonstantin Ananyev	 *	%rdi points to the fboot_file_t
245877400d3SKonstantin Ananyev	 *	%rsi has FI_LAST_TABLE_PA(%rsp)
246877400d3SKonstantin Ananyev	 */
247877400d3SKonstantin Ananyev
248877400d3SKonstantin Ananyev	movq	%rdi, %rdx
249877400d3SKonstantin Ananyev	movq	%rsi, %r8
250877400d3SKonstantin Ananyev	movq	FB_PTE_LIST_PA(%rdx), %rax	/* PA list of the source */
251877400d3SKonstantin Ananyev	movq	FB_DEST_PA(%rdx), %rdi		/* PA of the destination */
252877400d3SKonstantin Ananyev
253877400d3SKonstantin Ananyev2:
254877400d3SKonstantin Ananyev	movq	(%rax), %rcx			/* Are we done? */
255877400d3SKonstantin Ananyev	cmpl	$FASTBOOT_TERMINATE, %ecx
256877400d3SKonstantin Ananyev	je	1f
257877400d3SKonstantin Ananyev
258877400d3SKonstantin Ananyev	movq	%rcx, (%r8)
259877400d3SKonstantin Ananyev	movq	%cr3, %rsi		/* Reload cr3 */
260877400d3SKonstantin Ananyev	movq	%rsi, %cr3
261877400d3SKonstantin Ananyev	movq	FB_VA(%rdx), %rsi	/* Load from VA */
262877400d3SKonstantin Ananyev	movq	$PAGESIZE, %rcx
263877400d3SKonstantin Ananyev	shrq	$3, %rcx		/* 8-byte at a time */
264877400d3SKonstantin Ananyev	rep
265877400d3SKonstantin Ananyev	  smovq
266877400d3SKonstantin Ananyev	addq	$8, %rax 		/* Go to next PTE */
267877400d3SKonstantin Ananyev	jmp	2b
268877400d3SKonstantin Ananyev1:
269877400d3SKonstantin Ananyev	ret
270*55fea89dSDan Cross	SET_SIZE(map_copy)
271877400d3SKonstantin Ananyev
27219397407SSherry Mooreidt_info:
27319397407SSherry Moore	.value	0x3ff
27419397407SSherry Moore	.quad	0
27519397407SSherry Moore
27619397407SSherry Moore/*
27719397407SSherry Moore * We need to trampoline thru a gdt we have in low memory.
27819397407SSherry Moore */
27919397407SSherry Moore#include "../boot/boot_gdt.s"
280