xref: /haiku/src/system/boot/platform/bios_ia32/long_asm.S (revision 1f8a8d2b48943fd22b3bcb5156130348dd312ca0)
1e5fc2bfcSAlex Smith/*
2e5fc2bfcSAlex Smith * Copyright 2012, Alex Smith, alex@alex-smith.me.uk.
3e5fc2bfcSAlex Smith * Distributed under the terms of the MIT License.
4e5fc2bfcSAlex Smith */
5e5fc2bfcSAlex Smith
6e5fc2bfcSAlex Smith
7e5fc2bfcSAlex Smith#include <asm_defs.h>
8e5fc2bfcSAlex Smith
9c005e747SAlex Smith#define __x86_64__
10c005e747SAlex Smith#include <arch/x86/descriptors.h>
11527da4caSPawel Dziepak
12527da4caSPawel Dziepak#include "mmu.h"
13c005e747SAlex Smith#undef __x86_64__
14e5fc2bfcSAlex Smith
15e5fc2bfcSAlex Smith
160da10c8bSAlex Smith#define GDT_LIMIT 0x800
170da10c8bSAlex Smith
180da10c8bSAlex Smith
19e5fc2bfcSAlex Smith.code32
20e5fc2bfcSAlex Smith
21e5fc2bfcSAlex Smith
2276a1175dSAlex Smith/*!	void long_enter_kernel(int currentCPU, uint64 stackTop); */
23e5fc2bfcSAlex SmithFUNCTION(long_enter_kernel):
2476a1175dSAlex Smith	// Preserve the arguments. We may no longer be able to use the stack once
2576a1175dSAlex Smith	// paging is disabled.
2676a1175dSAlex Smith	movl	4(%esp), %ebx
2776a1175dSAlex Smith	movl	8(%esp), %edi
2876a1175dSAlex Smith	movl	12(%esp), %esi
2976a1175dSAlex Smith
30*1f8a8d2bSJérôme Duval	movl	gLongLA57, %ecx
31*1f8a8d2bSJérôme Duval	shl		$12, %ecx
32*1f8a8d2bSJérôme Duval
33e5fc2bfcSAlex Smith	// Currently running with 32-bit paging tables at an identity mapped
34e5fc2bfcSAlex Smith	// address. To switch to 64-bit paging we must first disable 32-bit paging,
35e5fc2bfcSAlex Smith	// otherwise loading the new CR3 will fault.
36e5fc2bfcSAlex Smith	movl	%cr0, %eax
37e5fc2bfcSAlex Smith	andl	$~(1 << 31), %eax
38e5fc2bfcSAlex Smith	movl	%eax, %cr0
39e5fc2bfcSAlex Smith
40*1f8a8d2bSJérôme Duval	// Enable PAE and PGE, and optionally LA57
41e5fc2bfcSAlex Smith	movl	%cr4, %eax
4240aeaeb9SAlex Smith	orl		$(1 << 5) | (1 << 7), %eax
43*1f8a8d2bSJérôme Duval	orl		%ecx, %eax
44e5fc2bfcSAlex Smith	movl	%eax, %cr4
45e5fc2bfcSAlex Smith
46*1f8a8d2bSJérôme Duval	// Point CR3 to the kernel's PMLTop.
47*1f8a8d2bSJérôme Duval	movl	gLongPhysicalPMLTop, %eax
48e5fc2bfcSAlex Smith	movl	%eax, %cr3
49e5fc2bfcSAlex Smith
50e5fc2bfcSAlex Smith	// Enable long mode by setting EFER.LME.
5176a1175dSAlex Smith	movl	$0xc0000080, %ecx
52e5fc2bfcSAlex Smith	rdmsr
53e5fc2bfcSAlex Smith	orl		$(1 << 8), %eax
54e5fc2bfcSAlex Smith	wrmsr
55e5fc2bfcSAlex Smith
56e5fc2bfcSAlex Smith	// Re-enable paging, which will put us in compatibility mode as we are
57e5fc2bfcSAlex Smith	// currently in a 32-bit code segment.
58e5fc2bfcSAlex Smith	movl	%cr0, %ecx
59e5fc2bfcSAlex Smith	orl		$(1 << 31), %ecx
60e5fc2bfcSAlex Smith	movl	%ecx, %cr0
61e5fc2bfcSAlex Smith
62527da4caSPawel Dziepak	// Load 64-bit enabled GDT
63527da4caSPawel Dziepak	lgdtl	long_gdtr
64527da4caSPawel Dziepak
65e5fc2bfcSAlex Smith	// Jump into the 64-bit code segment.
66611376feSPawel Dziepak	ljmp	$KERNEL_CODE_SELECTOR, $.Llmode
67e5fc2bfcSAlex Smith.align 8
68e5fc2bfcSAlex Smith.code64
69e5fc2bfcSAlex Smith.Llmode:
70e5fc2bfcSAlex Smith	// Set data segments.
71611376feSPawel Dziepak	mov		$KERNEL_DATA_SELECTOR, %ax
72e5fc2bfcSAlex Smith	mov		%ax, %ss
7303add8e7SAlex Smith	xor		%ax, %ax
74e5fc2bfcSAlex Smith	mov		%ax, %ds
75e5fc2bfcSAlex Smith	mov		%ax, %es
76e5fc2bfcSAlex Smith	mov		%ax, %fs
77e5fc2bfcSAlex Smith	mov		%ax, %gs
78e5fc2bfcSAlex Smith
7976a1175dSAlex Smith	// Set the stack pointer.
8076a1175dSAlex Smith	movl	%edi, %esp
8176a1175dSAlex Smith	shl		$32, %rsi
8276a1175dSAlex Smith	orq		%rsi, %rsp
83e5fc2bfcSAlex Smith
84e5fc2bfcSAlex Smith	// Clear the stack frame/RFLAGS.
85e5fc2bfcSAlex Smith	xorq	%rbp, %rbp
86e5fc2bfcSAlex Smith	push	$0
87e5fc2bfcSAlex Smith	popf
88e5fc2bfcSAlex Smith
8976a1175dSAlex Smith	// Get arguments and call the kernel entry point.
9076a1175dSAlex Smith	leaq	gKernelArgs(%rip), %rdi
9176a1175dSAlex Smith	movl	%ebx, %esi
9276a1175dSAlex Smith	movq	gLongKernelEntry(%rip), %rax
93e5fc2bfcSAlex Smith	call	*%rax
940da10c8bSAlex Smith
950da10c8bSAlex Smith
960da10c8bSAlex Smith.data
970da10c8bSAlex Smith
980da10c8bSAlex Smith
99527da4caSPawel Dziepaklong_gdtr:
100527da4caSPawel Dziepak	.word	BOOT_GDT_SEGMENT_COUNT * 8 - 1
101527da4caSPawel DziepakSYMBOL(gLongGDT):
10276a1175dSAlex Smith	.long	0
10376a1175dSAlex Smith
104*1f8a8d2bSJérôme DuvalSYMBOL(gLongPhysicalPMLTop):
105*1f8a8d2bSJérôme Duval	.long	0
106*1f8a8d2bSJérôme Duval
107*1f8a8d2bSJérôme DuvalSYMBOL(gLongLA57):
10876a1175dSAlex Smith	.long	0
10976a1175dSAlex Smith
11076a1175dSAlex SmithSYMBOL(gLongKernelEntry):
1110da10c8bSAlex Smith	.quad	0
112