Kernel/x86_64 - Fucking about removing inline asm
[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 [section .text]
195
196 %macro ISR_NOERRNO      1
197 Isr%1:
198         push    QWORD 0
199         push    QWORD %1
200         jmp     ErrorCommon
201 %endmacro
202 %macro ISR_ERRNO        1
203 Isr%1:
204         push    QWORD %1
205         jmp     ErrorCommon
206 %endmacro
207
208 ISR_NOERRNO     0;  0: Divide By Zero Exception
209 ISR_NOERRNO     1;  1: Debug Exception
210 ISR_NOERRNO     2;  2: Non Maskable Interrupt Exception
211 ISR_NOERRNO     3;  3: Int 3 Exception
212 ISR_NOERRNO     4;  4: INTO Exception
213 ISR_NOERRNO     5;  5: Out of Bounds Exception
214 ISR_NOERRNO     6;  6: Invalid Opcode Exception
215 ISR_NOERRNO     7;  7: Coprocessor Not Available Exception
216 ISR_ERRNO       8;  8: Double Fault Exception (With Error Code!)
217 ISR_NOERRNO     9;  9: Coprocessor Segment Overrun Exception
218 ISR_ERRNO       10; 10: Bad TSS Exception (With Error Code!)
219 ISR_ERRNO       11; 11: Segment Not Present Exception (With Error Code!)
220 ISR_ERRNO       12; 12: Stack Fault Exception (With Error Code!)
221 ISR_ERRNO       13; 13: General Protection Fault Exception (With Error Code!)
222 ISR_ERRNO       14; 14: Page Fault Exception (With Error Code!)
223 ISR_NOERRNO     15; 15: Reserved Exception
224 ISR_NOERRNO     16; 16: Floating Point Exception
225 ISR_NOERRNO     17; 17: Alignment Check Exception
226 ISR_NOERRNO     18; 18: Machine Check Exception
227 ISR_NOERRNO     19; 19: Reserved
228 ISR_NOERRNO     20; 20: Reserved
229 ISR_NOERRNO     21; 21: Reserved
230 ISR_NOERRNO     22; 22: Reserved
231 ISR_NOERRNO     23; 23: Reserved
232 ISR_NOERRNO     24; 24: Reserved
233 ISR_NOERRNO     25; 25: Reserved
234 ISR_NOERRNO     26; 26: Reserved
235 ISR_NOERRNO     27; 27: Reserved
236 ISR_NOERRNO     28; 28: Reserved
237 ISR_NOERRNO     29; 29: Reserved
238 ISR_NOERRNO     30; 30: Reserved
239 ISR_NOERRNO     31; 31: Reserved
240
241 [extern Error_Handler]
242 [global ErrorCommon]
243 ErrorCommon:
244         PUSH_GPR
245         push gs
246         push fs
247         ;PUSH_FPU
248         ;PUSH_XMM
249         
250         mov rdi, rsp
251         xchg bx, bx
252         call Error_Handler
253         
254         ;POP_XMM
255         ;POP_FPU
256         pop fs
257         pop gs
258         POP_GPR
259         add rsp, 2*8
260         iretq
261
262 %macro DEFIRQ   1
263 Irq%1:
264         push    0
265         push    %1
266         jmp     IrqCommon
267 %endmacro
268
269 %assign i 0
270 %rep 16
271 DEFIRQ  i
272 %assign i i+1
273 %endrep
274
275 [global IrqCommon]
276 IrqCommon:
277         PUSH_GPR
278         push gs
279         push fs
280         
281         mov rbx, [rsp+(16+2)*8] ; Get interrupt number (16 GPRS + 2 SRs)
282 ;       xchg bx, bx     ; Bochs Magic break (NOTE: will clear the high-bits of RBX)
283         shl rbx, 2      ; *8*4
284         mov rax, gaIRQ_Handlers
285         lea rbx, [rax+rbx*8]
286         
287         ; Check all callbacks
288         sub rsp, 8      ; Shadow of argument
289         %assign i 0
290         %rep NUM_IRQ_CALLBACKS
291         ; Get callback address
292         mov rax, [rbx]
293         test rax, rax   ; Check if it exists
294         jz .skip.%[i]
295         ; Set RDI to IRQ number
296         mov rdi, [rsp+(16+2+1)*8]       ; Get IRQ number
297         call rax        ; Call
298 .skip.%[i]:
299         add rbx, 8      ; Next!
300         %assign i i+1
301         %endrep
302         add rsp, 8
303         
304         ; ACK
305         mov al, 0x20
306         mov rdi, [rsp+16*8]     ; Get IRQ number
307         cmp rdi, 8
308         jb .skipAckSecondary
309         mov dx, 0x00A0
310         out dx, al
311 .skipAckSecondary:
312         mov dx, 0x0020
313         out dx, al
314         
315         pop fs
316         pop gs
317         POP_GPR
318         add rsp, 8*2
319         ;xchg bx, bx
320         iretq
321
322 [extern Proc_Scheduler]
323 [global SchedulerIRQ]
324 ;
325 ; NOTE: Proc_Scheduler makes assumptions about the stack state when called 
326 ;
327 SchedulerIRQ:
328         push 0  ; Error code
329         push 0  ; IRQNum
330         PUSH_GPR
331         push gs
332         push fs
333         ;PUSH_FPU
334         ;PUSH_XMM
335         
336         ; Save Thread Pointer
337         mov rax, dr0
338         push rax
339         
340         mov rdi, dr1    ; Get the CPU Number
341         mov rsi, rsp    ; Save stack pointer
342         mov rdx, SchedulerIRQ.restoreState
343         ; Call the Scheduler
344         call Proc_Scheduler
345 .restoreState:
346         
347         ; Restore Thread Pointer
348         pop rax
349         mov dr0, rax
350         
351         ; Send EOI (To either the APIC or the PIC)
352         %if USE_MP
353         test ebx, ebx
354         jnz .sendEOI
355         %endif
356         ; PIC
357         mov al, 0x20
358         out 0x20, al            ; ACK IRQ
359         %if USE_MP
360         jmp .ret
361         ; APIC
362 .sendEOI:
363         mov eax, DWORD [gpMP_LocalAPIC]
364         mov DWORD [eax+0x0B0], 0
365         %endif
366 .ret:
367         
368         ;POP_XMM
369         ;POP_FPU
370         pop fs
371         pop gs
372         POP_GPR
373         add rsp, 2*8    ; Dummy error code and IRQ num
374         iretq
375
376 [extern ci_offsetof_tThread_KernelStack]
377 [extern SyscallHandler]
378 [global SyscallStub]
379 SyscallStub:
380         mov rbp, dr0
381         mov ebx, [rel ci_offsetof_tThread_KernelStack]
382         mov rbp, [rbp+rbx]      ; Get kernel stack
383         xchg rbp, rsp   ; Swap stacks
384
385         push rbp        ; Save User RSP
386         push rcx        ; RIP
387         push r11        ; RFLAGS
388
389         ; RDI
390         ; RSI
391         ; RDX
392         ; R10 (RCX for non syscall)
393         ; R8
394         ; R9
395         sub rsp, (6+2)*8
396         mov [rsp+0x00], rax     ; Number
397 ;       mov [rsp+0x08], rax     ; Errno (don't care really)
398         mov [rsp+0x10], rdi     ; Arg1
399         mov [rsp+0x18], rsi     ; Arg2
400         mov [rsp+0x20], rdx     ; Arg3
401         mov [rsp+0x28], r10     ; Arg4
402         mov [rsp+0x30], r8      ; Arg5
403         mov [rsp+0x38], r9      ; Arg6
404         
405         mov rdi, rsp
406         sub rsp, 8
407         call SyscallHandler
408         add rsp, 8
409         mov ebx, [rsp+8]        ; Get errno
410         mov rax, [rsp+0]        ; Get return
411         add rsp, (6+2)*8
412
413         pop r11
414         pop rcx
415         pop rsp         ; Change back to user stack
416         sysret
417
418 [section .data]
419 gIDT:
420         ; 64-bit Interrupt Gate, CS = 0x8, IST0 (Disabled)
421         times 256       dd      0x00080000, 0x00000E00, 0, 0
422 gIDTPtr:
423         dw      256*16-1
424         dq      gIDT
425
426 gaIRQ_Handlers:
427         times   16*NUM_IRQ_CALLBACKS    dq      0

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