Files
jsix_import/src/kernel/interrupts.s
Justin C. Miller 2597e2002b Get super basic ring3 task switching working
* It looks like UEFI enables SSE, so we need to tell clang -mno-sse for
  now to not use XMM* until we're ready to save them.
* SYSCALL is working from ring3 tasks, calling console printf!
2018-05-21 09:07:53 -07:00

213 lines
2.8 KiB
ArmAsm

extern g_idtr
extern g_gdtr
global idt_write
idt_write:
lidt [rel g_idtr]
ret
global idt_load
idt_load:
sidt [rel g_idtr]
ret
global gdt_write
gdt_write:
lgdt [rel g_gdtr]
mov ax, si ; second arg is data segment
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
push qword rdi ; first arg is code segment
lea rax, [rel .next]
push rax
o64 retf
.next:
ltr dx
ret
global gdt_load
gdt_load:
sgdt [rel g_gdtr]
ret
%macro push_all_and_segments 0
push rax
push rcx
push rdx
push rbx
push rbp
push rsi
push rdi
push r8
push r9
push r10
push r11
push r12
push r13
push r14
push r15
mov ax, ds
push rax
%endmacro
%macro pop_all_and_segments 0
pop rax
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
pop r15
pop r14
pop r13
pop r12
pop r11
pop r10
pop r9
pop r8
pop rdi
pop rsi
pop rbp
pop rbx
pop rdx
pop rcx
pop rax
%endmacro
extern isr_handler
global isr_handler_prelude
isr_handler_prelude:
push_all_and_segments
mov rdi, rsp
call isr_handler
mov rsp, rax
pop_all_and_segments
add rsp, 16 ; because the ISRs added err/num
sti
iretq
extern irq_handler
global irq_handler_prelude
irq_handler_prelude:
push_all_and_segments
call irq_handler
pop_all_and_segments
add rsp, 16 ; because the ISRs added err/num
sti
iretq
%macro EMIT_ISR 2
global %1
%1:
cli
push 0
push %2
jmp isr_handler_prelude
%endmacro
%macro EMIT_EISR 2
global %1
%1:
cli
push %2
jmp isr_handler_prelude
%endmacro
%macro EMIT_IRQ 2
global %1
%1:
cli
push 0
push %2
jmp irq_handler_prelude
%endmacro
%define EISR(i, name) EMIT_EISR name, i
%define ISR(i, name) EMIT_ISR name, i
%define IRQ(i, q, name) EMIT_IRQ name, i
section .isrs
%include "interrupt_isrs.inc"
extern syscall_handler
syscall_handler_prelude:
push 0 ; ss, doesn't matter here
push rsp
pushf
push 0 ; cs, doesn't matter here
push rcx ; user rip
push 0 ; bogus interrupt
push 0 ; bogus errorcode
push_all_and_segments
call syscall_handler
pop_all_and_segments
add rsp, 16 ; ignore bogus interrupt / error
pop rcx ; user rip
add rsp, 32 ; ignore cs, flags, rsp, ss
o64 sysret
global syscall_enable
syscall_enable:
; IA32_EFER - set bit 0, syscall enable
mov rcx, 0xc0000080
rdmsr
or rax, 0x1
wrmsr
; IA32_STAR - cs for syscall
mov rcx, 0xc0000081
mov rax, 0 ; not used
mov rdx, 0x00180008 ; GDT:3 (user code), GDT:1 (kernel code)
wrmsr
; IA32_LSTAR - RIP for syscall
mov rcx, 0xc0000082
lea rax, [rel syscall_handler_prelude]
mov rdx, rax
shr rdx, 32
wrmsr
; IA32_FMASK - FLAGS mask inside syscall
mov rcx, 0xc0000084
mov rax, 0x200
mov rdx, 0
wrmsr
ret
global taskA
taskA:
push rbp
mov rbp, rsp
mov rax, 0xaaaaaaaaaaaaaaaa
.loop:
syscall
jmp .loop
global taskB
taskB:
push rbp
mov rbp, rsp
mov rax, 0xbbbbbbbbbbbbbbbb
.loop:
syscall
jmp .loop