summaryrefslogtreecommitdiff
path: root/kernel/interrupts.asm
blob: c096ddbd9e1f07902803980142726c256eca7d7f (plain) (blame)
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
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
bits 64

global load_gdt_and_idt

section .rodata

;0x28 picked to align with limine choice

;0x18 - tss
;0x28 - kernel code
;0x30 - kernel data
;0x38 - user data
;0x40 - user code

tss:
  times 9 dd 0
  dq 0xffffffffffeff000
  times 15 dd 0

gdtr:
  dw 0x47
  dq gdt

idtr:
  dw 4095
  dq idt

section .bss

idt:
  resq 512

global exception_info
exception_info:
.rax:
  resq 1
.rbx:
  resq 1
.rcx:
  resq 1
.rdx:
  resq 1
.rdi:
  resq 1
.rsi:
  resq 1
.rbp:
  resq 1
.rsp:
  resq 1
.r8:
  resq 1
.r9:
  resq 1
.r10:
  resq 1
.r11:
  resq 1
.r12:
  resq 1
.r13:
  resq 1
.r14:
  resq 1
.r15:
  resq 1
.cr2:
  resq 1
.cr3:
  resq 1
.rip:
  resq 1
.rflags:
  resq 1
.error:
  resq 1
.has_error:
  resb 1
.exception_number:
  resb 1

section .rodata

has_error_code:
  db 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0

exception_isrs:
  dq exception_00, exception_01, exception_02, exception_03
  dq exception_04, exception_05, exception_06, exception_07
  dq exception_08, exception_09, exception_0a, exception_0b
  dq exception_0c, exception_0d, exception_0e, exception_0f

section .text

extern print_exception

exception_00:
  mov byte [exception_info.exception_number], 0x00
  jmp exception_common
exception_01:
  mov byte [exception_info.exception_number], 0x01
  jmp exception_common
exception_02:
  mov byte [exception_info.exception_number], 0x02
  jmp exception_common
exception_03:
  mov byte [exception_info.exception_number], 0x03
  jmp exception_common
exception_04:
  mov byte [exception_info.exception_number], 0x04
  jmp exception_common
exception_05:
  mov byte [exception_info.exception_number], 0x05
  jmp exception_common
exception_06:
  mov byte [exception_info.exception_number], 0x06
  jmp exception_common
exception_07:
  mov byte [exception_info.exception_number], 0x07
  jmp exception_common
exception_08:
  mov byte [exception_info.exception_number], 0x08
  jmp exception_common
exception_09:
  mov byte [exception_info.exception_number], 0x09
  jmp exception_common
exception_0a:
  mov byte [exception_info.exception_number], 0x0a
  jmp exception_common
exception_0b:
  mov byte [exception_info.exception_number], 0x0b
  jmp exception_common
exception_0c:
  mov byte [exception_info.exception_number], 0x0c
  jmp exception_common
exception_0d:
  mov byte [exception_info.exception_number], 0x0d
  jmp exception_common
exception_0e:
  mov byte [exception_info.exception_number], 0x0e
  jmp exception_common
exception_0f:
  mov byte [exception_info.exception_number], 0x0f
  jmp exception_common

exception_common:
  mov qword [exception_info.rax], rax

  movzx rax, byte [exception_info.exception_number]
  mov al, byte [has_error_code + rax]
  test al, al
  jz .no_error_code

  mov byte [exception_info.has_error], 1
  pop rax
  mov qword [exception_info.error], rax
  jmp .post_error_code

.no_error_code:
  mov byte [exception_info.has_error], 0

.post_error_code:
  mov qword [exception_info.rbx], rbx
  mov qword [exception_info.rcx], rcx
  mov qword [exception_info.rdx], rdx
  mov qword [exception_info.rdi], rdi
  mov qword [exception_info.rsi], rsi
  mov qword [exception_info.rbp], rbp
  mov qword [exception_info.r8], r8
  mov qword [exception_info.r9], r9
  mov qword [exception_info.r10], r10
  mov qword [exception_info.r11], r11
  mov qword [exception_info.r12], r12
  mov qword [exception_info.r13], r13
  mov qword [exception_info.r14], r14
  mov qword [exception_info.r15], r15

  pop rax
  mov qword [exception_info.rip], rax
  pop rax
  pop rax
  mov qword [exception_info.rflags], rax
  pop rax
  mov qword [exception_info.rsp], rax

  mov rax, cr2
  mov qword [exception_info.cr2], rax
  mov rax, cr3
  mov qword [exception_info.cr3], rax

  jmp print_exception

set_isr:
;rdi - index
;sil - 1 if this is a trap, 0 if it is an interrupt
;rdx - isr pointer

  shl rdi, 4
  add rdi, idt

  mov word [rdi], dx
  shr rdx, 16
  mov word [rdi + 6], dx
  shr rdx, 16
  mov dword [rdi + 8], edx

  or sil, 0x8e
  mov byte [rdi + 5], sil
  mov word [rdi + 2], 0x28
  mov byte [rdi + 4], 1

  ret

section .data

gdt:
  dq 0
  dq 0
  dq 0
.tss:
  dq 0x0000e90000000067
  dq 0;tss is 2 qwords wide
  dq 0x002f98000000ffff
  dq 0x002f92000000ffff
  dq 0x002ff2000000ffff
  dq 0x002ff8000000ffff

section .bss

section .text

write_keyboard_byte:
  in al, 0x64
  test al, 0x02
  jnz write_keyboard_byte
  mov al, dil
  out 0x60, al
  ret

extern on_keyboard_interrupt

keyboard_isr:

  push r11
  push r10
  push r9
  push r8
  push rsi
  push rdi
  push rdx
  push rcx
  push rax

  in al, 0x60
  mov dil, al

  call on_keyboard_interrupt

  mov al, 0x20
  out 0x20, al

  pop rax
  pop rcx
  pop rdx
  pop rdi
  pop rsi
  pop r8
  pop r9
  pop r10
  pop r11

  iretq

load_gdt_and_idt:

  ;fill exception entries in idt

  mov rcx, 16

.loop:

  mov rdi, rcx
  dec rdi
  mov sil, 1
  mov rdx, qword [exception_isrs + rdi * 8]
  call set_isr

  loop .loop

  ;reset pic and map irqs to 0x20 - 0x2f

  mov al, 0x11
  out 0x20, al
  mov al, 0x20
  out 0x21, al
  mov al, 0x04
  out 0x21, al
  mov al, 0x01
  out 0x21, al
  mov al, 0xfd ;mask all but irq 1
  out 0x21, al

  mov al, 0x11
  out 0xa0, al
  mov al, 0x28
  out 0xa1, al
  mov al, 0x02
  out 0xa1, al
  mov al, 0x01
  out 0xa1, al
  mov al, 0xff ;mask all
  out 0xa1, al

  mov rdi, 0x21
  xor sil, sil
  mov rdx, keyboard_isr
  call set_isr

  ;set keyboard config

  mov al, 0x60
  out 0x64, al
  mov dil, 0x01
  call write_keyboard_byte

  ;make tss entry in gdt

  mov rax, tss

  mov word [gdt.tss + 2], ax
  shr rax, 16
  mov byte [gdt.tss + 4], al
  mov byte [gdt.tss + 7], ah
  shr rax, 16
  mov dword [gdt.tss + 8], eax

  ;load gdt, idt, tss

  lgdt [gdtr]
  lidt [idtr]
  mov ax, 0x18
  ltr ax

  ret