1/*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source.  A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12/*
13 * Copyright 2016 Toomas Soome <tsoome@me.com>
14 */
15
16#include <x86/specialreg.h>
17
18	.file	"multiboot_tramp.s"
19
20/*
21 * dboot expects a 32-bit multiboot environment and to execute in 32-bit mode.
22 *
23 * EAX: MB magic
24 * EBX: 32-bit physical address of MBI
25 * CS: 32-bit read/execute code segment with offset 0 and limit 0xFFFFFFFF
26 * DS: 32-bit read/write data segment with offset 0 and limit 0xFFFFFFFF
27 * ES: 32-bit read/write data segment with offset 0 and limit 0xFFFFFFFF
28 * FS: 32-bit read/write data segment with offset 0 and limit 0xFFFFFFFF
29 * GS: 32-bit read/write data segment with offset 0 and limit 0xFFFFFFFF
30 * SS: 32-bit read/write data segment with offset 0 and limit 0xFFFFFFFF
31 * A20 enabled
32 * CR0: PG cleared, PE set
33 * EFLAGS: VM cleared, IF cleared
34 * interrupts disabled
35 */
36
37		.set	SEL_SCODE,0x8
38		.set	SEL_SDATA,0x10
39
40		.text
41		.p2align 4
42		.globl	multiboot_tramp
43		.type	multiboot_tramp, STT_FUNC
44
45/*
46 * void multiboot_tramp(uint32_t magic, struct relocator *relocator,
47 *    vm_offset_t entry)
48 */
49multiboot_tramp:
50		cli
51		movq	(%rsi), %rax
52		movq	%rax, %rsp		/* Switch to temporary stack. */
53		movq	0x8(%rsi), %rax		/* relocator->copy */
54		pushq	%rdi			/* save magic */
55		pushq	%rdx			/* save entry */
56		movq	%rsi, %rdi
57		callq	*%rax
58		movq	%rax, %rbx		/* MBI */
59		popq	%rsi			/* entry to rsi */
60		popq	%rdi			/* restore magic */
61		lea	gdt(%rip), %rax
62		lea	gdtaddr(%rip), %rdx
63		movq	%rax, (%rdx)
64		lea	gdtdesc(%rip), %rax
65		lgdt	(%rax)
66
67		/* record the address */
68		lea	multiboot_tramp_2(%rip), %rcx
69		movq	%rsp, %rax
70		pushq	$SEL_SDATA
71		pushq	%rax
72		pushf
73		pushq	$SEL_SCODE
74		lea	multiboot_tramp_1(%rip), %rax
75		pushq	%rax
76		iretq
77
78		.code32
79multiboot_tramp_1:
80		movl	$SEL_SDATA, %eax
81		movw	%ax, %ss
82		movw	%ax, %ds
83		movw	%ax, %es
84		movw	%ax, %fs
85		movw	%ax, %gs
86
87		movl	%cr0, %eax		/* disable paging */
88		btrl	$31, %eax
89		movl	%eax, %cr0
90		jmp	*%ecx
91multiboot_tramp_2:
92		movl	%cr4, %eax		/* disable PAE, PGE, PSE */
93		andl	$~(CR4_PGE | CR4_PAE | CR4_PSE), %eax
94		movl	%eax, %cr4
95		movl	$MSR_EFER, %ecx
96		rdmsr				/* updates %edx:%eax */
97		btcl	$8, %eax		/* clear long mode */
98		wrmsr
99		movl	%edi, %eax		/* magic */
100		jmp	*%esi			/* jump to kernel */
101
102/* GDT record */
103		.p2align 4
104gdt:
105/*
106 * This will create access for 4GB flat memory with
107 * base = 0x00000000, segment limit = 0xffffffff
108 * page granulariy 4k
109 * 32-bit protected mode
110 * ring 0
111 * code segment is executable RW
112 * data segment is not-executable RW
113 */
114		.word	0x0, 0x0		/* NULL entry */
115		.byte	0x0, 0x0, 0x0, 0x0
116		.word	0xffff, 0x0		/* code segment */
117		.byte	0x0, 0x9a, 0xcf, 0x0
118		.word	0xffff, 0x0		/* data segment */
119		.byte	0x0, 0x92, 0xcf, 0x0
120gdt_end:
121
122		.p2align 4
123gdtdesc:	.word	gdt_end - gdt - 1	/* limit */
124gdtaddr:	.long	0			/* base */
125		.long	0
126
127multiboot_tramp_end:
128