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
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 |