;
;
;
+%include "arch/x86_64/include/common.inc.asm"
[BITS 64]
[extern Log]
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]
[global Desctab_Init]
Desctab_Init:
; Set an IDT entry to a callback
%macro SETIDT 2
mov rax, %2
- mov WORD [rdi + %1*16], ax
+ mov WORD [rdi + %1*16], ax
shr rax, 16
- mov WORD [rdi + %1*16 + 6], ax
+ 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
+ mov ax, WORD [rdi + %1*16 + 4]
+ or ax, 0x8000
+ mov WORD [rdi + %1*16 + 4], ax
%endmacro
; Install error handlers
%endrep
; Install IRQs
- SETIDT 0xF0, SchedulerIRQ
+ SETIDT 0xF0, PIT_IRQ
SETIDT 0xF1, Irq1
SETIDT 0xF2, Irq2
SETIDT 0xF3, Irq3
mov dx, 0x20
mov al, 0x11
out dx, al ; Init Command
- mov dx, 0x21
+ mov dx, 0x21
mov al, 0xF0
out dx, al ; Offset (Start of IDT Range)
- mov al, 0x04
+ mov al, 0x04
out dx, al ; IRQ connected to Slave (00000100b) = IRQ2
- mov al, 0x01
+ mov al, 0x01
out dx, al ; Set Mode
- mov al, 0x00
+ mov al, 0x00
out dx, al ; Set Mode
mov dx, 0xA0
mov al, 0x11
out dx, al ; Init Command
- mov dx, 0xA1
+ mov dx, 0xA1
mov al, 0xF8
out dx, al ; Offset (Start of IDT Range)
- mov al, 0x02
+ mov al, 0x02
out dx, al ; IRQ Line connected to master
- mov al, 0x01
+ mov al, 0x01
out dx, al ; Set Mode
- mov dl, 0x00
+ mov dl, 0x00
out dx, al ; Set Mode
pop rdx
mov rax, gGDTPtr
mov rcx, gGDT
mov QWORD [rax+2], rcx
- lidt [rax]
+ 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
IRQ_AddHandler:
; RDI - IRQ Number
; RSI - Callback
+ ; RDX - Ptr
+ ; Check for RDI >= 16
cmp rdi, 16
jb .numOK
xor rax, rax
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
push rdi
push rsi
push rax
+ push rdx
sub rsp, 8
mov rcx, rdi ; IRQ Number
mov rdx, rsi ; Callback
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:
[section .rodata]
csIRQ_Assigned:
db "IRQ %p := %p (IRQ %i)",0
+csIRQ_Fired:
+ db "IRQ %i fired",0
[section .text]
%macro ISR_NOERRNO 1
;PUSH_XMM
mov rdi, rsp
- xchg bx, bx
+; xchg bx, bx
call Error_Handler
;POP_XMM
[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
test rax, rax ; Check if it exists
jz .skip.%[i]
; Set RDI to IRQ number
- mov rdi, [rsp+16*8] ; Get 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 ; Next!
%assign i i+1
%endrep
+ add rsp, 8
; ACK
- mov rdi, [rsp+16*8] ; Get IRQ number
- cmp rdi, 8
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
- ;xchg bx, bx
iretq
-[extern Proc_Scheduler]
-[global SchedulerIRQ]
-SchedulerIRQ:
+[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
+ iretq
+%endif
+
+[global PIT_IRQ]
+PIT_IRQ:
PUSH_GPR
;PUSH_FPU
;PUSH_XMM
- ; 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
+ 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
- ; PIC
+
+ ; Send EOI
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_GPR
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:
; 64-bit Interrupt Gate, CS = 0x8, IST0 (Disabled)
gaIRQ_Handlers:
times 16*NUM_IRQ_CALLBACKS dq 0
+gaIRQ_DataPtrs:
+ times 16*NUM_IRQ_CALLBACKS dq 0
+
+; vim: ft=nasm