X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Kernel%2Farch%2Fx86_64%2Fdesctab.asm;h=6e8aa6398ca7f64fa4491d7181793555b28035a0;hb=6d5880d56afb2c6a900e480c891fb40e05457ea3;hp=de606ea63f6a1bc00586aebfa2185bd80659b071;hpb=9f407c493c33928e0f19b834699d9694036ca42e;p=tpg%2Facess2.git diff --git a/Kernel/arch/x86_64/desctab.asm b/Kernel/arch/x86_64/desctab.asm index de606ea6..6e8aa639 100644 --- a/Kernel/arch/x86_64/desctab.asm +++ b/Kernel/arch/x86_64/desctab.asm @@ -1,57 +1,128 @@ ; ; ; +%include "arch/x86_64/include/common.inc.asm" [BITS 64] +[extern Log] +[extern gGDTPtr] +[extern gGDT] + %define NUM_IRQ_CALLBACKS 4 MM_LOCALAPIC equ 0xFFFFFD0000000000 -%macro PUSH_GPR 0 - mov [rsp-0x60], rsp - mov [rsp-0x08], r15 - mov [rsp-0x10], r14 - mov [rsp-0x18], r13 - mov [rsp-0x20], r12 - mov [rsp-0x28], r11 - mov [rsp-0x30], r10 - mov [rsp-0x38], r9 - mov [rsp-0x40], r8 - mov [rsp-0x48], rdi - mov [rsp-0x50], rsi - mov [rsp-0x58], rbp - mov [rsp-0x68], rbx - mov [rsp-0x70], rdx - mov [rsp-0x78], rcx - mov [rsp-0x80], rax - sub rsp, 0x80 -%endmacro -%macro POP_GPR 0 - add rsp, 0x80 - mov r15, [rsp-0x08] - mov r14, [rsp-0x10] - mov r13, [rsp-0x18] - mov r12, [rsp-0x20] - mov r11, [rsp-0x28] - mov r10, [rsp-0x30] - mov r9, [rsp-0x38] - mov r8, [rsp-0x40] - mov rdi, [rsp-0x48] - mov rsi, [rsp-0x50] - mov rbp, [rsp-0x58] - ;mov rsp, [rsp-0x60] - mov rbx, [rsp-0x68] - mov rdx, [rsp-0x70] - mov rcx, [rsp-0x78] - mov rax, [rsp-0x80] -%endmacro - [section .text] -Desctab_Init: - ; Install IRQ Handlers +[global Desctab_Init] +Desctab_Init: + ; Save to make following instructions smaller + mov rdi, gIDT + + ; Set an IDT entry to a callback + %macro SETIDT 2 + mov rax, %2 + mov WORD [rdi + %1*16], ax + shr rax, 16 + mov WORD [rdi + %1*16 + 6], ax + shr rax, 16 + mov DWORD [rdi + %1*16 + 8], eax + ; Enable + mov ax, WORD [rdi + %1*16 + 4] + or ax, 0x8000 + mov WORD [rdi + %1*16 + 4], ax + %endmacro + + ; Install error handlers + %macro SETISR 1 + SETIDT %1, Isr%1 + %endmacro + + %assign i 0 + %rep 32 + SETISR i + %assign i i+1 + %endrep + + ; Install IRQs + SETIDT 0xF0, PIT_IRQ + SETIDT 0xF1, Irq1 + SETIDT 0xF2, Irq2 + SETIDT 0xF3, Irq3 + SETIDT 0xF4, Irq4 + SETIDT 0xF5, Irq5 + SETIDT 0xF6, Irq6 + SETIDT 0xF7, Irq7 + SETIDT 0xF8, Irq8 + SETIDT 0xF9, Irq9 + SETIDT 0xFA, Irq10 + SETIDT 0xFB, Irq11 + SETIDT 0xFC, Irq12 + SETIDT 0xFD, Irq13 + SETIDT 0xFE, Irq14 + SETIDT 0xFF, Irq15 + + ; Remap PIC + push rdx ; Save RDX + mov dx, 0x20 + mov al, 0x11 + out dx, al ; Init Command + mov dx, 0x21 + mov al, 0xF0 + out dx, al ; Offset (Start of IDT Range) + mov al, 0x04 + out dx, al ; IRQ connected to Slave (00000100b) = IRQ2 + mov al, 0x01 + out dx, al ; Set Mode + mov al, 0x00 + out dx, al ; Set Mode + + mov dx, 0xA0 + mov al, 0x11 + out dx, al ; Init Command + mov dx, 0xA1 + mov al, 0xF8 + out dx, al ; Offset (Start of IDT Range) + mov al, 0x02 + out dx, al ; IRQ Line connected to master + mov al, 0x01 + out dx, al ; Set Mode + mov dl, 0x00 + out dx, al ; Set Mode + pop rdx + + + ; Install IDT + mov rax, gIDTPtr + lidt [rax] + + ; Re-install GDT (in higher address space) + mov rax, gGDTPtr + mov rcx, gGDT + mov QWORD [rax+2], rcx + lgdt [rax] + + ; Start interrupts + sti + + ; Set IA32_LSTAR (RIP of handler) + mov ecx, 0xC0000082 ; IA32_LSTAR + mov eax, SyscallStub - 0xFFFFFFFF00000000 + mov edx, 0xFFFFFFFF + wrmsr + ; Set IA32_FMASK (flags mask) + mov ecx, 0xC0000084 + rdmsr + mov eax, ~0x202 + wrmsr + ; Set IA32_STAR (Kernel/User CS) + mov ecx, 0xC0000081 + rdmsr + mov edx, 0x8 | (0x1B << 16) ; Kernel CS (and Kernel DS/SS - 8), User CS + wrmsr + ret -; int IRQ_AddHandler(int IRQ, void (*Handler)(int IRQ)) +; int IRQ_AddHandler(int IRQ, void (*Handler)(int IRQ), void *Ptr) ; Return Values: ; 0 on Success ; -1 on an invalid IRQ Number @@ -60,7 +131,9 @@ Desctab_Init: IRQ_AddHandler: ; RDI - IRQ Number ; RSI - Callback + ; RDX - Ptr + ; Check for RDI >= 16 cmp rdi, 16 jb .numOK xor rax, rax @@ -68,15 +141,15 @@ IRQ_AddHandler: jmp .ret .numOK: - mov rax, rdi - shr rax, 3+2 + ; Get handler base into RAX + lea rax, [rdi*4] mov rcx, gaIRQ_Handlers - add rax, rcx + lea rax, [rcx+rax*8] ; Find a free callback slot %rep NUM_IRQ_CALLBACKS - mov rdx, [rax] - test rdx, rdx + mov rcx, [rax] + test rcx, rcx jz .assign add rax, 8 %endrep @@ -88,24 +161,105 @@ IRQ_AddHandler: ; Assign the IRQ Callback .assign: + ; A little bit of debug + push rdi + push rsi + push rax + push rdx + sub rsp, 8 + mov rcx, rdi ; IRQ Number + mov rdx, rsi ; Callback + mov rsi, rax ; Pointer + mov rdi, csIRQ_Assigned + call Log + add rsp, 8 + pop rdx + pop rax + pop rsi + pop rdi + + ; Assign and return mov [rax], rsi + add rax, gaIRQ_DataPtrs - gaIRQ_Handlers + mov [rax], rdx xor rax, rax .ret: ret + +[section .rodata] +csIRQ_Assigned: + db "IRQ %p := %p (IRQ %i)",0 +csIRQ_Fired: + db "IRQ %i fired",0 +[section .text] -%macro DEFERR 1 +%macro ISR_NOERRNO 1 Isr%1: - push 0 - push %1 + push QWORD 0 + push QWORD %1 jmp ErrorCommon %endmacro -%macro DEFERRNO 1 +%macro ISR_ERRNO 1 Isr%1: - push %1 + push QWORD %1 jmp ErrorCommon %endmacro +ISR_NOERRNO 0; 0: Divide By Zero Exception +ISR_NOERRNO 1; 1: Debug Exception +ISR_NOERRNO 2; 2: Non Maskable Interrupt Exception +ISR_NOERRNO 3; 3: Int 3 Exception +ISR_NOERRNO 4; 4: INTO Exception +ISR_NOERRNO 5; 5: Out of Bounds Exception +ISR_NOERRNO 6; 6: Invalid Opcode Exception +ISR_NOERRNO 7; 7: Coprocessor Not Available Exception +ISR_ERRNO 8; 8: Double Fault Exception (With Error Code!) +ISR_NOERRNO 9; 9: Coprocessor Segment Overrun Exception +ISR_ERRNO 10; 10: Bad TSS Exception (With Error Code!) +ISR_ERRNO 11; 11: Segment Not Present Exception (With Error Code!) +ISR_ERRNO 12; 12: Stack Fault Exception (With Error Code!) +ISR_ERRNO 13; 13: General Protection Fault Exception (With Error Code!) +ISR_ERRNO 14; 14: Page Fault Exception (With Error Code!) +ISR_NOERRNO 15; 15: Reserved Exception +ISR_NOERRNO 16; 16: Floating Point Exception +ISR_NOERRNO 17; 17: Alignment Check Exception +ISR_NOERRNO 18; 18: Machine Check Exception +ISR_NOERRNO 19; 19: Reserved +ISR_NOERRNO 20; 20: Reserved +ISR_NOERRNO 21; 21: Reserved +ISR_NOERRNO 22; 22: Reserved +ISR_NOERRNO 23; 23: Reserved +ISR_NOERRNO 24; 24: Reserved +ISR_NOERRNO 25; 25: Reserved +ISR_NOERRNO 26; 26: Reserved +ISR_NOERRNO 27; 27: Reserved +ISR_NOERRNO 28; 28: Reserved +ISR_NOERRNO 29; 29: Reserved +ISR_NOERRNO 30; 30: Reserved +ISR_NOERRNO 31; 31: Reserved + +[extern Error_Handler] +[global ErrorCommon] +ErrorCommon: + PUSH_GPR + push gs + push fs + ;PUSH_FPU + ;PUSH_XMM + + mov rdi, rsp +; xchg bx, bx + call Error_Handler + + ;POP_XMM + ;POP_FPU + pop fs + pop gs + POP_GPR + add rsp, 2*8 + iretq + %macro DEFIRQ 1 Irq%1: push 0 @@ -113,60 +267,172 @@ Irq%1: jmp IrqCommon %endmacro +%assign i 0 +%rep 16 +DEFIRQ i +%assign i i+1 +%endrep + +[global IrqCommon] IrqCommon: PUSH_GPR + push gs + push fs + +; mov rdi, csIRQ_Fired +; mov rsi, [rsp+(16+2)*8] +; call Log - mov rbx, [rsp+16*8] ; Calculate address - shr rbx, 3+2 ; *8*4 + mov ebx, [rsp+(16+2)*8] ; Get interrupt number (16 GPRS + 2 SRs) + shl ebx, 2 ; *4 mov rax, gaIRQ_Handlers - add rbx, rax + lea rbx, [rax+rbx*8] + ; Check all callbacks + sub rsp, 8 ; Shadow of argument %assign i 0 %rep NUM_IRQ_CALLBACKS + ; Get callback address mov rax, [rbx] - test rax, rax - mov rdi, [rsp+16*8] ; Get IRQ number + test rax, rax ; Check if it exists jz .skip.%[i] - call rax ; 2 Bytes (Op and Mod/RM) + ; Set RDI to IRQ number + mov rdi, [rsp+(16+2+1)*8] ; Get IRQ number + mov rsi, [rbx-gaIRQ_Handlers+gaIRQ_DataPtrs] + call rax ; Call .skip.%[i]: - add rbx, 8 + add rbx, 8 ; Next! %assign i i+1 %endrep + add rsp, 8 - mov rdi, [rsp+16*8] ; Get IRQ number - cmp rdi, 8 + ; ACK mov al, 0x20 + mov rdi, [rsp+(16+2)*8] ; Get IRQ number + cmp rdi, 8 jb .skipAckSecondary - mov dx, 0x00A0 - out dx, al + out 0xA0, al .skipAckSecondary: - mov dx, 0x0020 - out dx, al + out 0x20, al + pop fs + pop gs + POP_GPR + add rsp, 8*2 + iretq + +[extern Time_UpdateTimestamp] + +%if USE_MP +[global APIC_Timer_IRQ] +APIC_Timer_IRQ: + PUSH_GPR + push gs + push fs + + ; TODO: What to do? + + mov eax, DWORD [gpMP_LocalAPIC] + mov DWORD [eax+0x0B0], 0 + + pop fs + pop gs POP_GPR - add rsp, 16 - iret + iretq +%endif -[extern Proc_Scheduler] -SchedulerIRQ: - ; TODO: Find Current CPU +[global PIT_IRQ] +PIT_IRQ: PUSH_GPR ;PUSH_FPU ;PUSH_XMM - xor rsi, rsi - mov rdi, MM_LOCALAPIC+0x20 - mov esi, [rdi] - call Proc_Scheduler + call Time_UpdateTimestamp + + %if 0 +[section .rodata] +csUserSS: db "User SS: 0x%x",0 +[section .text] + mov rdi, csUserSS + mov rsi, [rsp+0x80+0x20] + call Log + %endif + + ; Send EOI + mov al, 0x20 + out 0x20, al ; ACK IRQ ;POP_XMM ;POP_FPU POP_GPR - iret + iretq + +[extern ci_offsetof_tThread_KernelStack] +[extern SyscallHandler] +[global SyscallStub] +SyscallStub: + mov rbp, dr0 + mov ebx, [rel ci_offsetof_tThread_KernelStack] + mov rbp, [rbp+rbx] ; Get kernel stack + xchg rbp, rsp ; Swap stacks + + push rbp ; Save User RSP + push rcx ; RIP + push r11 ; RFLAGS + + ; RDI + ; RSI + ; RDX + ; R10 (RCX for non syscall) + ; R8 + ; R9 + sub rsp, (6+2)*8 + mov [rsp+0x00], rax ; Number +; mov [rsp+0x08], rax ; Errno (output only) + mov [rsp+0x10], rdi ; Arg1 + mov [rsp+0x18], rsi ; Arg2 + mov [rsp+0x20], rdx ; Arg3 + mov [rsp+0x28], r10 ; Arg4 + mov [rsp+0x30], r8 ; Arg5 + mov [rsp+0x38], r9 ; Arg6 + + mov rdi, rsp + sub rsp, 8 + call SyscallHandler + + %if 0 +[section .rodata] +csSyscallReturn: db "Syscall Return: 0x%x",0 +[section .text] + mov rdi, csSyscallReturn + mov rsi, [rsp+0+8] + call Log + %endif + + add rsp, 8 + mov ebx, [rsp+8] ; Get errno + mov rax, [rsp+0] ; Get return + add rsp, (6+2)*8 + + pop r11 + pop rcx + pop rsp ; Change back to user stack + ; TODO: Determine if user is 64 or 32 bit + + db 0x48 ; REX, nasm doesn't have a sysretq opcode + sysret [section .data] gIDT: - times 256 dw 0x00080000, 0x00008E00, 0, 0 ; 64-bit Interrupt Gate, CS = 0x8, IST0 + ; 64-bit Interrupt Gate, CS = 0x8, IST0 (Disabled) + times 256 dd 0x00080000, 0x00000E00, 0, 0 +gIDTPtr: + dw 256*16-1 + dq gIDT gaIRQ_Handlers: times 16*NUM_IRQ_CALLBACKS dq 0 +gaIRQ_DataPtrs: + times 16*NUM_IRQ_CALLBACKS dq 0 + +; vim: ft=nasm