-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathboot.S
executable file
·209 lines (188 loc) · 3.81 KB
/
boot.S
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
#include <memlayout.h>
#include <mmu.h>
.set ALIGN, 1<<0
.set MEMINFO, 1<<1
.set FLAGS, ALIGN | MEMINFO
.set MAGIC, 0x1BADB002
.set CHECKSUM, -(MAGIC + FLAGS)
# The Multiboot header should be defined in a section and also reserve a section
# in kernel linker script otherwise and error related to Multiboot header not found
# will be shown.
.section .multiboot
.align 4
.long MAGIC
.long FLAGS
.long CHECKSUM
.section .text
# Entry Point
.globl _start
_start:
# The multiboot standard does not define the value of the stack pointer register
# (esp) and it is up to the kernel to provide a stack. The stack gets allocated
# in data section and according to the kernel linking, it is located at a high
# address. The stack grows downwards on x86. The stack on x86 must be 16-byte aligned
# according to the System V ABI standard and de-facto extensions. The compiler will
# assume the stack is properly aligned and failure to align the stack will result in
# undefined behavior.
# Use 4MB pages
movl %cr4, %eax
orl $(CR4_PSE), %eax
movl %eax, %cr4
# Physical address of Page Directory
movl $(V2P_WO(entrypgdir)), %eax
movl %eax, %cr3
# Turn on paging
movl %cr0, %eax
orl $(CR0_PG|CR0_WP), %eax
movl %eax, %cr0
movl $(stack + 4096), %esp
pushl %eax
pushl %ebx
movl $kernel_main, %eax
jmp *%eax
.macro ISR_NOERRORCODE code
.global isr\code
isr\code:
cli
pushl $0
pushl $\code
jmp isr_common_stub
.endm
.macro ISR_ERRORCODE code
.global isr\code
isr\code:
cli
pushl $\code
jmp isr_common_stub
.endm
.macro IRQ_ERRORCODE one, two
.global irq\one
irq\one:
cli
push $0
pushl $\two
jmp irq_common_stub
.endm
ISR_NOERRORCODE 0
ISR_NOERRORCODE 1
ISR_NOERRORCODE 2
ISR_NOERRORCODE 3
ISR_NOERRORCODE 4
ISR_NOERRORCODE 5
ISR_NOERRORCODE 6
ISR_NOERRORCODE 7
ISR_ERRORCODE 8
ISR_NOERRORCODE 9
ISR_ERRORCODE 10
ISR_ERRORCODE 11
ISR_ERRORCODE 12
ISR_ERRORCODE 13
ISR_ERRORCODE 14
ISR_NOERRORCODE 15
ISR_NOERRORCODE 16
ISR_ERRORCODE 17
ISR_ERRORCODE 18
ISR_ERRORCODE 19
ISR_ERRORCODE 20
ISR_ERRORCODE 21
ISR_ERRORCODE 22
ISR_ERRORCODE 23
ISR_ERRORCODE 24
ISR_ERRORCODE 25
ISR_ERRORCODE 26
ISR_ERRORCODE 27
ISR_ERRORCODE 28
ISR_ERRORCODE 29
ISR_ERRORCODE 30
ISR_ERRORCODE 31
IRQ_ERRORCODE 0, 32
IRQ_ERRORCODE 1, 33
IRQ_ERRORCODE 2, 34
IRQ_ERRORCODE 3, 35
IRQ_ERRORCODE 4, 36
IRQ_ERRORCODE 5, 37
IRQ_ERRORCODE 6, 38
IRQ_ERRORCODE 7, 39
IRQ_ERRORCODE 8, 40
IRQ_ERRORCODE 9, 41
IRQ_ERRORCODE 10, 42
IRQ_ERRORCODE 11, 43
IRQ_ERRORCODE 12, 44
IRQ_ERRORCODE 13, 45
IRQ_ERRORCODE 14, 46
IRQ_ERRORCODE 15, 47
.extern isr_handler
isr_common_stub:
pushal
movw %ds, %ax
pushl %eax
movw $0x10, %ax # Load kernel data segment descriptor
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
call isr_handler
popl %ebx # Reload the original data segment descriptor
movw %bx, %ds
movw %bx, %es
movw %bx, %fs
movw %bx, %gs
popal
addl $8, %esp
sti
iretl
.extern irq_handler
irq_common_stub:
pushal
movw %ds, %ax
pushl %eax
movw $0x10, %ax # Load kernel data segment descriptor
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
call irq_handler
popl %ebx # Reload the original data segment descriptor
movw %bx, %ds
movw %bx, %es
movw %bx, %fs
movw %bx, %gs
popal
addl $8, %esp
sti
iretl
.global gdt_flush
.extern gdpt
.type gdt_flush, @function
gdt_flush:
movl 4(%esp), %eax
lgdt (%eax)
# Our code descriptor is 8 bytes offset from start of gdt
movw $0x10, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
movw %ax, %ss
ljmp $0x08,$flush2
flush2:
ret
.global tss_flush
.type tss_flush, @function
tss_flush:
movw $0x10, %ax
ltr %ax
ret
.global idt_flush
.extern idtp
.type idt_flush, @function
idt_flush:
movl 4(%esp), %eax
lidt (%eax)
ret
.global die
.type die, @function
die:
hlt
jmp die
.comm stack, 4096, 16