X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Kernel%2Farch%2Fx86_64%2Fdesctab.asm;h=8212773b5b81468a9dbe35614ab9ac5bc9371b1f;hb=98d45a155c3ce437d0eddb67b9eb2b203f87ec3b;hp=aec7656cbc2b789b83ff04455c403aef07fc7605;hpb=89fba51f2433cf185831ee70554b99fe87e44a9d;p=tpg%2Facess2.git diff --git a/Kernel/arch/x86_64/desctab.asm b/Kernel/arch/x86_64/desctab.asm index aec7656c..8212773b 100644 --- a/Kernel/arch/x86_64/desctab.asm +++ b/Kernel/arch/x86_64/desctab.asm @@ -3,49 +3,16 @@ ; [BITS 64] -MM_LOCALAPIC equ 0xFFFFFD0000000000 - -[section .text] -Desctab_Init: - ; Install IRQ Handlers - -[section .data] -gIDT: - times 256 dw 0x00080000, 0x00008E00, 0, 0 ; 64-bit Interrupt Gate, CS = 0x8, IST0 - -%macro DEFERR 1 -Isr%1: - push 0 - push %1 - jmp ErrorCommon -%endmacro -%macro DEFERRNO 1 -Isr%1: - push %1 - jmp ErrorCommon -%endmacro +[extern Log] +[extern gGDTPtr] +[extern gGDT] -%macro DEFIRQ 1 -Irq%1: - push 0 - push %1 - jmp IrqCommon -%endmacro +%define NUM_IRQ_CALLBACKS 4 -%macro PUSH_EX 1-* - %rep %0 - push %1 - %rotate 1 - %endrep -%endmacro -%macro POP_EX 1-* - %rep %0 - %rotate -1 - pop %1 - %endrep -%endmacro +MM_LOCALAPIC equ 0xFFFFFD0000000000 %macro PUSH_GPR 0 + mov [rsp-0x60], rsp mov [rsp-0x08], r15 mov [rsp-0x10], r14 mov [rsp-0x18], r13 @@ -57,7 +24,6 @@ Irq%1: mov [rsp-0x48], rdi mov [rsp-0x50], rsi mov [rsp-0x58], rbp - mov [rsp-0x60], rsp mov [rsp-0x68], rbx mov [rsp-0x70], rdx mov [rsp-0x78], rcx @@ -72,8 +38,8 @@ Irq%1: mov r12, [rsp-0x20] mov r11, [rsp-0x28] mov r10, [rsp-0x30] - mov r9, [rsp-0x38] - mov r8, [rsp-0x40] + mov r9, [rsp-0x38] + mov r8, [rsp-0x40] mov rdi, [rsp-0x48] mov rsi, [rsp-0x50] mov rbp, [rsp-0x58] @@ -84,19 +50,350 @@ Irq%1: mov rax, [rsp-0x80] %endmacro +[section .text] +[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, SchedulerIRQ + 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 + + ret + +; int IRQ_AddHandler(int IRQ, void (*Handler)(int IRQ)) +; Return Values: +; 0 on Success +; -1 on an invalid IRQ Number +; -2 when no slots are avaliable +[global IRQ_AddHandler] +IRQ_AddHandler: + ; RDI - IRQ Number + ; RSI - Callback + + ; Check for RDI >= 16 + cmp rdi, 16 + jb .numOK + xor rax, rax + dec rax + jmp .ret +.numOK: + + ; Get handler base into RAX + lea rax, [rdi*4] + mov rcx, gaIRQ_Handlers + lea rax, [rcx+rax*8] + + ; Find a free callback slot + %rep NUM_IRQ_CALLBACKS + mov rdx, [rax] + test rdx, rdx + jz .assign + add rax, 8 + %endrep + ; None found, return -2 + xor rax, rax + dec rax + dec rax + jmp .ret + + ; Assign the IRQ Callback +.assign: + ; A little bit of debug + push rdi + push rsi + push rax + 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 rax + pop rsi + pop rdi + + ; Assign and return + mov [rax], rsi + xor rax, rax + +.ret: + ret + +[section .rodata] +csIRQ_Assigned: + db "IRQ %p := %p (IRQ %i)",0 +[section .text] + +%macro ISR_NOERRNO 1 +Isr%1: + push QWORD 0 + push QWORD %1 + jmp ErrorCommon +%endmacro +%macro ISR_ERRNO 1 +Isr%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 + push %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 rbx, [rsp+(16+2)*8] ; Get interrupt number (16 GPRS + 2 SRs) +; xchg bx, bx ; Bochs Magic break (NOTE: will clear the high-bits of RBX) + shl rbx, 2 ; *8*4 + mov rax, gaIRQ_Handlers + 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 ; Check if it exists + jz .skip.%[i] + ; Set RDI to IRQ number + mov rdi, [rsp+(16+2+1)*8] ; Get IRQ number + call rax ; Call +.skip.%[i]: + add rbx, 8 ; Next! + %assign i i+1 + %endrep + add rsp, 8 + + ; ACK + mov al, 0x20 + mov rdi, [rsp+16*8] ; Get IRQ number + cmp rdi, 8 + jb .skipAckSecondary + mov dx, 0x00A0 + out dx, al +.skipAckSecondary: + mov dx, 0x0020 + out dx, al + + pop fs + pop gs + POP_GPR + add rsp, 8*2 + ;xchg bx, bx + iretq + [extern Proc_Scheduler] +[global SchedulerIRQ] +; +; NOTE: Proc_Scheduler makes assumptions about the stack state when called +; SchedulerIRQ: - ; TODO: Find Current CPU + push 0 ; Error code + push 0 ; IRQNum PUSH_GPR + push gs + push fs ;PUSH_FPU ;PUSH_XMM - xor rsi, rsi - mov rdi, MM_LOCALAPIC+0x20 - mov esi, [rdi] + ; Save Thread Pointer + mov rax, dr0 + push rax + + ; Get the CPU Number + mov rdi, dr1 + ; Call the Scheduler call Proc_Scheduler + ; Restore Thread Pointer + pop rax + mov dr0, rax + + ; Send EOI (To either the APIC or the PIC) + %if USE_MP + test ebx, ebx + jnz .sendEOI + %endif + ; PIC + mov al, 0x20 + out 0x20, al ; ACK IRQ + %if USE_MP + jmp .ret + ; APIC +.sendEOI: + mov eax, DWORD [gpMP_LocalAPIC] + mov DWORD [eax+0x0B0], 0 + %endif +.ret: + ;POP_XMM ;POP_FPU + pop fs + pop gs POP_GPR - iret + add rsp, 2*8 ; Dummy error code and IRQ num + iretq + +[section .data] +gIDT: + ; 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