You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

228 lines
3.5 KiB

.section .text
.global __alltraps
.intel_syntax noprefix
__alltraps:
push rax
push rcx
push rdx
push rdi
push rsi
push r8
push r9
push r10
push r11
push rbx
push rbp
push r12
push r13
push r14
push r15
# push fs.base
xor rax, rax
mov ecx, 0xC0000100
rdmsr # msr[ecx] => edx:eax
shl rdx, 32
or rdx, rax
push rdx
# save fp registers
# align to 16 byte boundary
sub rsp, 512
mov rax, rsp
and rax, 0xFFFFFFFFFFFFFFF0
# fxsave (rax)
.byte 0x0f
.byte 0xae
.byte 0x00
mov rcx, rsp
sub rcx, rax
# push fp state offset
sub rsp, 16
push rcx
mov rdi, rsp
call rust_trap
.global trap_ret
trap_ret:
mov rdi, rsp
call set_return_rsp
# pop fp state offset
pop rcx
cmp rcx, 16 # only 0-15 are valid
jge skip_fxrstor
mov rax, rsp
add rax, 16
sub rax, rcx
# fxrstor (rax)
.byte 0x0f
.byte 0xae
.byte 0x08
skip_fxrstor:
add rsp, 16+512
# pop fs.base
pop rax
mov rdx, rax
shr rdx, 32
mov ecx, 0xC0000100
wrmsr # msr[ecx] <= edx:eax
pop r15
pop r14
pop r13
pop r12
pop rbp
pop rbx
pop r11
pop r10
pop r9
pop r8
pop rsi
pop rdi
pop rdx
pop rcx
pop rax
# pop trap_num, error_code
add rsp, 16
iretq
.global syscall_entry
syscall_entry:
# syscall instruction do:
# - load cs
# - store rflags -> r11
# - mask rflags
# - store rip -> rcx
# - load rip
# swap in kernel gs
swapgs
# store user rsp -> scratch at TSS.sp1
mov gs:[12], rsp
# load kernel rsp <- TSS.sp0
mov rsp, gs:[4]
push 0x23 # ss (WARN: match gdt)
push gs:[12] # rsp
push r11 # rflags
push 0x2b # cs (WARN: match gdt)
push rcx # rip
push 0 # error_code (dummy)
push 0 # trap_num (dummy)
# swap out kernel gs
swapgs
# enable interrupt
# sti
push rax
push rcx
push rdx
push rdi
push rsi
push r8
push r9
push r10
push r11
push rbx
push rbp
push r12
push r13
push r14
push r15
# push fs.base
xor rax, rax
mov ecx, 0xC0000100
rdmsr # msr[ecx] => edx:eax
shl rdx, 32
or rdx, rax
push rdx
# save fp registers
# align to 16 byte boundary
sub rsp, 512
mov rax, rsp
and rax, 0xFFFFFFFFFFFFFFF0
# fxsave (rax)
.byte 0x0f
.byte 0xae
.byte 0x00
mov rcx, rsp
sub rcx, rax
# push fp state offset
sub rsp, 16
push rcx
mov rdi, rsp
call syscall
syscall_return:
# disable interrupt
cli
mov rdi, rsp
call set_return_rsp
# pop fp state offset
pop rcx
cmp rcx, 16 # only 0-15 are valid
jge skip_fxrstor1
mov rax, rsp
add rax, 16
sub rax, rcx
# fxrstor (rax)
.byte 0x0f
.byte 0xae
.byte 0x08
skip_fxrstor1:
add rsp, 16+512
# pop fs.base
pop rax
mov rdx, rax
shr rdx, 32
mov ecx, 0xC0000100
wrmsr # msr[ecx] <= edx:eax
pop r15
pop r14
pop r13
pop r12
pop rbp
pop rbx
pop r11
pop r10
pop r9
pop r8
pop rsi
pop rdi
pop rdx
pop rcx
pop rax
add rsp, 2*8 # trap_num, error_code
pop rcx # rip
add rsp, 1*8 # cs
pop r11 # rflags
pop rsp
sysretq
# sysretq instruction do:
# - load cs, ss
# - load rflags <- r11
# - load rip <- rcx