-
Notifications
You must be signed in to change notification settings - Fork 19
/
Copy pathk-exception.S
212 lines (179 loc) · 5.33 KB
/
k-exception.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
210
211
212
###############################################################################
# Exception handlers
#
# Assembly code defining kernel exception handlers
# (for interrupts, traps, and faults).
// import constants from kernel.hh and x86-64.h
#include "obj/k-asm.h"
.text
// kernel_entry
// The bootloader jumps here after loading the kernel.
// The code initializes `%rsp` to the top of the kernel stack,
// then jumps to `kernel_start`.
.globl kernel_entry
kernel_entry:
// initialize stack pointer and base pointer
movq $KERNEL_STACK_TOP, %rsp
movq %rsp, %rbp
// clear `%rflags`
pushq $0
popfq
// check for multiboot command line; if found pass it along
cmpl $0x2BADB002, %eax
jne 1f
testl $4, (%rbx)
je 1f
movl 16(%rbx), %edi
jmp 2f
1: movq $0, %rdi
2: // call kernel_start()
jmp _Z12kernel_startPKc
// Exception handlers and interrupt descriptor table
// This code creates an exception handler for all 256 possible
// exceptions, and initializes a table in the
// `.interrupt_descriptors` section containing those handlers.
// The `init_hardware` kernel function installs this table.
// The `exception_handler` macro creates one exception handler
.altmacro
.macro exception_handler num
exception_entry_\num:
// push zero error code, unless exception did so already
.if \num != INT_DF && (\num < INT_TS || \num > INT_PF) && \num != INT_AC
pushq $0
.endif
// push exception number
pushq $\num
// jump to exception entry point
jmp _Z15exception_entryv
// add that handler to the `.interrupt_descriptors` section
.pushsection .interrupt_descriptors, "aw", @progbits
.quad exception_entry_\num
.quad 0
.popsection
.endm
// now create all 256 exception handlers and table
.set exception_number, 0
.rept 256
exception_handler %exception_number
.set exception_number, exception_number + 1
.endr
// Exception entry point
// Most exception handlers jump here.
.globl _Z15exception_entryv
_Z15exception_entryv:
push %gs
push %fs
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %r11
pushq %r10
pushq %r9
pushq %r8
pushq %rdi
pushq %rsi
pushq %rbp
pushq %rbx
pushq %rdx
pushq %rcx
pushq %rax
movq %rsp, %rdi
// load kernel page table
movq $kernel_pagetable, %rax
movq %rax, %cr3
call _Z9exceptionP8regstate
// `exception` should never return.
.globl _Z16exception_returnP4proc
_Z16exception_returnP4proc:
// check process state
movl 12(%rdi), %eax
cmpl $P_RUNNABLE, %eax
jne proc_runnable_fail
// load process page table
movq (%rdi), %rax
movq %rax, %cr3
// restore registers
leaq 16(%rdi), %rsp
popq %rax
popq %rcx
popq %rdx
popq %rbx
popq %rbp
popq %rsi
popq %rdi
popq %r8
popq %r9
popq %r10
popq %r11
popq %r12
popq %r13
popq %r14
popq %r15
pop %fs
pop %gs
addq $16, %rsp
// return to process
iretq
// syscall_entry
// Kernel entry point for the `syscall` instruction
.globl _Z13syscall_entryv
_Z13syscall_entryv:
movq %rsp, KERNEL_STACK_TOP - 16 // save entry %rsp to kernel stack
movq $KERNEL_STACK_TOP, %rsp // change to kernel stack
// structure used by `iret`:
pushq $(SEGSEL_APP_DATA + 3) // %ss
subq $8, %rsp // skip saved %rsp
pushq %r11 // %rflags
pushq $(SEGSEL_APP_CODE + 3) // %cs
pushq %rcx // %rip
// other registers:
subq $8, %rsp // error code unused
pushq $-1 // reg_intno
push %gs
push %fs
pushq %r15 // callee saved
pushq %r14 // callee saved
pushq %r13 // callee saved
pushq %r12 // callee saved
subq $8, %rsp // %r11 clobbered by `syscall`
pushq %r10
pushq %r9
pushq %r8
pushq %rdi
pushq %rsi
pushq %rbp // callee saved
pushq %rbx // callee saved
pushq %rdx
subq $8, %rsp // %rcx clobbered by `syscall`
pushq %rax
// load kernel page table
movq $kernel_pagetable, %rax
movq %rax, %cr3
// call syscall()
movq %rsp, %rdi
call _Z7syscallP8regstate
// check process state
movq current, %rcx
movl 12(%rcx), %ecx
cmpl $P_RUNNABLE, %ecx
jne proc_runnable_fail
// load process page table
movq current, %rcx
movq (%rcx), %rcx
movq %rcx, %cr3
// skip over other registers
addq $(8 * 19), %rsp
// return to process
iretq
proc_runnable_fail:
xorl %ecx, %ecx
movq $proc_runnable_assert, %rdx
xorl %esi, %esi
movq $k_exception_str, %rdi
callq _Z11assert_failPKciS0_S0_
.section .rodata.str1.1
k_exception_str:
.asciz "k-exception.S"
proc_runnable_assert:
.asciz "current->state == P_RUNNABLE"