-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathexception.S
162 lines (136 loc) · 4.27 KB
/
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
###############################################################################
# Exception handlers
#
# Assembly code defining kernel exception handlers
# (for interrupts, traps, and faults).
// import constants from kernel.hh and x86-64.h
#include "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: jmp kernel_main
// 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 exception_entry
// 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 exception_entry
exception_entry:
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 kernel_exception
// `exception` should never return.
// syscall_entry
// Kernel entry point for the `syscall` instruction
.globl syscall_entry
syscall_entry:
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 syscall
// 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