739b219f6a51fc27c2a42de1cb7a74ce9df5f8e4
[tpg/acess2.git] / Kernel / arch / x86_64 / desctab.asm
1 ;
2 ;
3 ;
4 %include "arch/x86_64/include/common.inc.asm"
5 [BITS 64]
6
7 [extern Log]
8 [extern gGDTPtr]
9 [extern gGDT]
10
11 %define NUM_IRQ_CALLBACKS       4
12
13 MM_LOCALAPIC    equ     0xFFFFFD0000000000
14
15 [section .text]
16 [global Desctab_Init]
17 Desctab_Init:   
18         ; Save to make following instructions smaller
19         mov rdi, gIDT
20         
21         ; Set an IDT entry to a callback
22         %macro SETIDT 2
23         mov rax, %2
24         mov WORD [rdi + %1*16], ax
25         shr rax, 16
26         mov WORD [rdi + %1*16 + 6], ax
27         shr rax, 16
28         mov DWORD [rdi + %1*16 + 8], eax
29         ; Enable
30         mov ax, WORD [rdi + %1*16 + 4]
31         or  ax, 0x8000
32         mov WORD [rdi + %1*16 + 4], ax
33         %endmacro
34         
35         ; Install error handlers
36         %macro SETISR 1
37         SETIDT %1, Isr%1
38         %endmacro
39         
40         %assign i 0
41         %rep 32
42         SETISR i
43         %assign i i+1
44         %endrep
45         
46         ; Install IRQs
47         SETIDT  0xF0, SchedulerIRQ
48         SETIDT  0xF1, Irq1
49         SETIDT  0xF2, Irq2
50         SETIDT  0xF3, Irq3
51         SETIDT  0xF4, Irq4
52         SETIDT  0xF5, Irq5
53         SETIDT  0xF6, Irq6
54         SETIDT  0xF7, Irq7
55         SETIDT  0xF8, Irq8
56         SETIDT  0xF9, Irq9
57         SETIDT  0xFA, Irq10
58         SETIDT  0xFB, Irq11
59         SETIDT  0xFC, Irq12
60         SETIDT  0xFD, Irq13
61         SETIDT  0xFE, Irq14
62         SETIDT  0xFF, Irq15
63
64         ; Remap PIC
65         push rdx        ; Save RDX
66         mov dx, 0x20
67         mov al, 0x11
68         out dx, al      ;       Init Command
69         mov dx, 0x21
70         mov al, 0xF0
71         out dx, al      ;       Offset (Start of IDT Range)
72         mov al, 0x04
73         out dx, al      ;       IRQ connected to Slave (00000100b) = IRQ2
74         mov al, 0x01
75         out dx, al      ;       Set Mode
76         mov al, 0x00
77         out dx, al      ;       Set Mode
78         
79         mov dx, 0xA0
80         mov al, 0x11
81         out dx, al      ;       Init Command
82         mov dx, 0xA1
83         mov al, 0xF8
84         out dx, al      ;       Offset (Start of IDT Range)
85         mov al, 0x02
86         out dx, al      ;       IRQ Line connected to master
87         mov al, 0x01
88         out dx, al      ;       Set Mode
89         mov dl, 0x00
90         out dx, al      ;       Set Mode
91         pop rdx
92         
93         
94         ; Install IDT
95         mov rax, gIDTPtr
96         lidt [rax]
97         
98         ; Re-install GDT (in higher address space)
99         mov rax, gGDTPtr
100         mov rcx, gGDT
101         mov QWORD [rax+2], rcx
102         lgdt [rax]
103         
104         ; Start interrupts
105         sti
106
107         ; Initialise System Calls (SYSCALL/SYSRET)
108         ; Set IA32_EFER.SCE
109         mov ecx, 0xC0000080
110         rdmsr
111         or eax, 1
112         wrmsr
113         ; Set IA32_LSTAR (RIP of handler)
114         mov ecx, 0xC0000082     ; IA32_LSTAR
115         mov eax, SyscallStub - 0xFFFFFFFF00000000
116         mov edx, 0xFFFFFFFF
117         wrmsr
118         ; Set IA32_FMASK (flags mask)
119         mov ecx, 0xC0000084
120         rdmsr
121         mov eax, 0x202
122         wrmsr
123         ; Set IA32_STAR (Kernel/User CS)
124         mov ecx, 0xC0000081
125         rdmsr
126         mov edx, 0x8 | (0x18 << 16)     ; Kernel CS (and Kernel DS/SS - 8), User CS
127         wrmsr
128         
129         ret
130
131 ; int IRQ_AddHandler(int IRQ, void (*Handler)(int IRQ))
132 ; Return Values:
133 ;  0 on Success
134 ; -1 on an invalid IRQ Number
135 ; -2 when no slots are avaliable
136 [global IRQ_AddHandler]
137 IRQ_AddHandler:
138         ; RDI - IRQ Number
139         ; RSI - Callback
140         
141         ; Check for RDI >= 16
142         cmp rdi, 16
143         jb .numOK
144         xor rax, rax
145         dec rax
146         jmp .ret
147 .numOK:
148
149         ; Get handler base into RAX
150         lea rax, [rdi*4]
151         mov rcx, gaIRQ_Handlers
152         lea rax, [rcx+rax*8]
153         
154         ; Find a free callback slot
155         %rep NUM_IRQ_CALLBACKS
156         mov rdx, [rax]
157         test rdx, rdx
158         jz .assign
159         add rax, 8
160         %endrep
161         ; None found, return -2
162         xor rax, rax
163         dec rax
164         dec rax
165         jmp .ret
166         
167         ; Assign the IRQ Callback
168 .assign:
169         ; A little bit of debug
170         push rdi
171         push rsi
172         push rax
173         sub rsp, 8
174         mov rcx, rdi    ; IRQ Number
175         mov rdx, rsi    ; Callback
176         mov rsi, rax    ; Pointer
177         mov rdi, csIRQ_Assigned
178         call Log
179         add rsp, 8
180         pop rax
181         pop rsi
182         pop rdi
183
184         ; Assign and return
185         mov [rax], rsi
186         xor rax, rax
187
188 .ret:
189         ret
190         
191 [section .rodata]
192 csIRQ_Assigned:
193         db      "IRQ %p := %p (IRQ %i)",0
194 csIRQ_Fired:
195         db      "IRQ %i fired",0
196 [section .text]
197
198 %macro ISR_NOERRNO      1
199 Isr%1:
200         push    QWORD 0
201         push    QWORD %1
202         jmp     ErrorCommon
203 %endmacro
204 %macro ISR_ERRNO        1
205 Isr%1:
206         push    QWORD %1
207         jmp     ErrorCommon
208 %endmacro
209
210 ISR_NOERRNO     0;  0: Divide By Zero Exception
211 ISR_NOERRNO     1;  1: Debug Exception
212 ISR_NOERRNO     2;  2: Non Maskable Interrupt Exception
213 ISR_NOERRNO     3;  3: Int 3 Exception
214 ISR_NOERRNO     4;  4: INTO Exception
215 ISR_NOERRNO     5;  5: Out of Bounds Exception
216 ISR_NOERRNO     6;  6: Invalid Opcode Exception
217 ISR_NOERRNO     7;  7: Coprocessor Not Available Exception
218 ISR_ERRNO       8;  8: Double Fault Exception (With Error Code!)
219 ISR_NOERRNO     9;  9: Coprocessor Segment Overrun Exception
220 ISR_ERRNO       10; 10: Bad TSS Exception (With Error Code!)
221 ISR_ERRNO       11; 11: Segment Not Present Exception (With Error Code!)
222 ISR_ERRNO       12; 12: Stack Fault Exception (With Error Code!)
223 ISR_ERRNO       13; 13: General Protection Fault Exception (With Error Code!)
224 ISR_ERRNO       14; 14: Page Fault Exception (With Error Code!)
225 ISR_NOERRNO     15; 15: Reserved Exception
226 ISR_NOERRNO     16; 16: Floating Point Exception
227 ISR_NOERRNO     17; 17: Alignment Check Exception
228 ISR_NOERRNO     18; 18: Machine Check Exception
229 ISR_NOERRNO     19; 19: Reserved
230 ISR_NOERRNO     20; 20: Reserved
231 ISR_NOERRNO     21; 21: Reserved
232 ISR_NOERRNO     22; 22: Reserved
233 ISR_NOERRNO     23; 23: Reserved
234 ISR_NOERRNO     24; 24: Reserved
235 ISR_NOERRNO     25; 25: Reserved
236 ISR_NOERRNO     26; 26: Reserved
237 ISR_NOERRNO     27; 27: Reserved
238 ISR_NOERRNO     28; 28: Reserved
239 ISR_NOERRNO     29; 29: Reserved
240 ISR_NOERRNO     30; 30: Reserved
241 ISR_NOERRNO     31; 31: Reserved
242
243 [extern Error_Handler]
244 [global ErrorCommon]
245 ErrorCommon:
246         PUSH_GPR
247         push gs
248         push fs
249         ;PUSH_FPU
250         ;PUSH_XMM
251         
252         mov rdi, rsp
253         xchg bx, bx
254         call Error_Handler
255         
256         ;POP_XMM
257         ;POP_FPU
258         pop fs
259         pop gs
260         POP_GPR
261         add rsp, 2*8
262         iretq
263
264 %macro DEFIRQ   1
265 Irq%1:
266         push    0
267         push    %1
268         jmp     IrqCommon
269 %endmacro
270
271 %assign i 0
272 %rep 16
273 DEFIRQ  i
274 %assign i i+1
275 %endrep
276
277 [global IrqCommon]
278 IrqCommon:
279         PUSH_GPR
280         push gs
281         push fs
282
283 ;       mov rdi, csIRQ_Fired
284 ;       mov rsi, [rsp+(16+2)*8]
285 ;       call Log
286         
287         mov ebx, [rsp+(16+2)*8] ; Get interrupt number (16 GPRS + 2 SRs)
288 ;       xchg bx, bx     ; Bochs Magic break (NOTE: will clear the high-bits of RBX)
289         shl ebx, 2      ; *4
290         mov rax, gaIRQ_Handlers
291         lea rbx, [rax+rbx*8]
292         
293         ; Check all callbacks
294         sub rsp, 8      ; Shadow of argument
295         %assign i 0
296         %rep NUM_IRQ_CALLBACKS
297         ; Get callback address
298         mov rax, [rbx]
299         test rax, rax   ; Check if it exists
300         jz .skip.%[i]
301         ; Set RDI to IRQ number
302         mov rdi, [rsp+(16+2+1)*8]       ; Get IRQ number
303         call rax        ; Call
304 .skip.%[i]:
305         add rbx, 8      ; Next!
306         %assign i i+1
307         %endrep
308         add rsp, 8
309         
310         ; ACK
311         mov al, 0x20
312         mov rdi, [rsp+(16+2)*8] ; Get IRQ number
313         cmp rdi, 8
314         jb .skipAckSecondary
315         out 0xA0, al
316 .skipAckSecondary:
317         out 0x20, al
318         
319         pop fs
320         pop gs
321         POP_GPR
322         add rsp, 8*2
323         iretq
324
325 [extern Proc_Scheduler]
326 [global SchedulerIRQ]
327 ;
328 ; NOTE: Proc_Scheduler makes assumptions about the stack state when called 
329 ;
330 SchedulerIRQ:
331         push 0  ; Error code
332         push 0  ; IRQNum
333         PUSH_GPR
334         push gs
335         push fs
336         ;PUSH_FPU
337         ;PUSH_XMM
338         
339         ; Save Thread Pointer
340         mov rax, dr0
341         push rax
342         
343         mov rdi, dr1    ; Get the CPU Number
344         mov rsi, rsp    ; Save stack pointer
345         mov rdx, SchedulerIRQ.restoreState
346         ; Call the Scheduler
347         call Proc_Scheduler
348 .restoreState:
349         
350         ; Restore Thread Pointer
351         pop rax
352         mov dr0, rax
353         
354         ; Send EOI (To either the APIC or the PIC)
355         %if USE_MP
356         test ebx, ebx
357         jnz .sendEOI
358         %endif
359         ; PIC
360         mov al, 0x20
361         out 0x20, al            ; ACK IRQ
362         %if USE_MP
363         jmp .ret
364         ; APIC
365 .sendEOI:
366         mov eax, DWORD [gpMP_LocalAPIC]
367         mov DWORD [eax+0x0B0], 0
368         %endif
369 .ret:
370         
371         ;POP_XMM
372         ;POP_FPU
373         pop fs
374         pop gs
375         POP_GPR
376         add rsp, 2*8    ; Dummy error code and IRQ num
377 ;       xchg bx, bx
378         iretq
379
380 [extern ci_offsetof_tThread_KernelStack]
381 [extern SyscallHandler]
382 [global SyscallStub]
383 SyscallStub:
384         mov rbp, dr0
385         mov ebx, [rel ci_offsetof_tThread_KernelStack]
386         mov rbp, [rbp+rbx]      ; Get kernel stack
387         xchg rbp, rsp   ; Swap stacks
388
389         push rbp        ; Save User RSP
390         push rcx        ; RIP
391         push r11        ; RFLAGS
392
393         ; RDI
394         ; RSI
395         ; RDX
396         ; R10 (RCX for non syscall)
397         ; R8
398         ; R9
399         sub rsp, (6+2)*8
400         mov [rsp+0x00], rax     ; Number
401 ;       mov [rsp+0x08], rax     ; Errno (don't care really)
402         mov [rsp+0x10], rdi     ; Arg1
403         mov [rsp+0x18], rsi     ; Arg2
404         mov [rsp+0x20], rdx     ; Arg3
405         mov [rsp+0x28], r10     ; Arg4
406         mov [rsp+0x30], r8      ; Arg5
407         mov [rsp+0x38], r9      ; Arg6
408         
409         mov rdi, rsp
410         sub rsp, 8
411         call SyscallHandler
412         add rsp, 8
413         mov ebx, [rsp+8]        ; Get errno
414         mov rax, [rsp+0]        ; Get return
415         add rsp, (6+2)*8
416
417         pop r11
418         pop rcx
419         pop rsp         ; Change back to user stack
420         ; TODO: Determine if user is 64 or 32 bit
421
422 ;       xchg bx, bx     
423         db 0x48 ; REX, nasm doesn't have a sysretq opcode
424         sysret
425
426 [section .data]
427 gIDT:
428         ; 64-bit Interrupt Gate, CS = 0x8, IST0 (Disabled)
429         times 256       dd      0x00080000, 0x00000E00, 0, 0
430 gIDTPtr:
431         dw      256*16-1
432         dq      gIDT
433
434 gaIRQ_Handlers:
435         times   16*NUM_IRQ_CALLBACKS    dq      0

UCC git Repository :: git.ucc.asn.au