-
Notifications
You must be signed in to change notification settings - Fork 31
Expand file tree
/
Copy pathentry.s
More file actions
141 lines (119 loc) · 3.26 KB
/
Copy pathentry.s
File metadata and controls
141 lines (119 loc) · 3.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# This is the kernel's entry point. We could either call main here,
# or we can use this to setup the stack or other nice stuff, like
# perhaps setting up the GDT and segments. Please note that interrupts
# are disabled at this point: More on interrupts later!
.code32
.macro gotpcrel reg, sym
call 2f
2:
pop eax
3:
.att_syntax prefix
addl $_GLOBAL_OFFSET_TABLE_ + (3b - 2b), %eax
.intel_syntax noprefix
mov \reg, dword ptr [eax + \sym@GOT]
.endm
.section .text
.align 4
.global _start
_start:
mov edi, ebx
cli # avoid any interrupt
call 2f
2:
pop eax
3:
.att_syntax prefix
addl $_GLOBAL_OFFSET_TABLE_ + (3b - 2b), %eax
.intel_syntax noprefix
mov esp, dword ptr [eax + {stack}@GOT]
# Initialize stack pointer
add esp, {stack_top_offset}
# Move the 32-bit physical address of the Multiboot information structure into `RDI` as first argument to `rust_start`.
mov edi, ebx
# This will set up the x86 control registers:
# Caching and the floating point unit are enabled
# Bootstrap page tables are loaded and page size
# extensions (huge pages) enabled.
cpu_init:
# check for long mode
# do we have the instruction cpuid?
pushfd
pop eax
mov ecx, eax
xor eax, 1 << 21
push eax
popfd
pushfd
pop eax
push ecx
popfd
xor eax, ecx
jz Linvalid
# cpuid > 0x80000000?
mov eax, 0x80000000
cpuid
cmp eax, 0x80000001
jb Linvalid # It is less, there is no long mode.
# do we have a long mode?
mov eax, 0x80000001
cpuid
test edx, 1 << 29 # Test if the LM-bit, which is bit 29, is set in the D-register.
jz Linvalid # They aren't, there is no long mode.
# Set CR3
gotpcrel eax, {level_4_table}
mov cr3, eax
# we need to enable PAE modus
mov eax, cr4
or eax, 1 << 5
mov cr4, eax
# switch to the compatibility mode (which is part of long mode)
mov ecx, 0xC0000080
rdmsr
or eax, 1 << 8
wrmsr
# Set CR4
mov eax, cr4
and eax, 0xfffbf9ff # disable SSE
# or eax, (1 << 7) # enable PGE
mov cr4, eax
# Set CR0 (PM-bit is already set)
mov eax, cr0
and eax, ~(1 << 2) # disable FPU emulation
or eax, (1 << 1) # enable FPU montitoring
and eax, ~(1 << 30) # enable caching
and eax, ~(1 << 29) # disable write through caching
and eax, ~(1 << 16) # allow kernel write access to read-only pages
or eax, (1 << 31) # enable paging
mov cr0, eax
gotpcrel eax, {gdt_ptr}
lgdt [eax] # Load the 64-bit global descriptor table.
push {kernel_code_selector}
gotpcrel eax, start64
push eax
retf
# https://github.com/llvm/llvm-project/issues/46048
.att_syntax prefix
# Set the code segment and enter 64-bit long mode.
# ljmp ${kernel_code_selector}, $start64
.intel_syntax noprefix
# there is no long mode
Linvalid:
jmp Linvalid
.code64
start64:
# initialize segment registers
mov ax, {kernel_data_selector}
mov ds, eax
mov es, eax
mov ss, eax
xor ax, ax
mov fs, eax
mov gs, eax
cld
# set default stack pointer
mov rsp, [rip + {stack}@GOTPCREL]
add rsp, {stack_top_offset}
# jump to the boot processors's C code
jmp {rust_start}
jmp start64+0x28