/* SPDX-License-Identifier: MPL-2.0 OR MIT
*
* The original source code is from [trapframe-rs](https://github.com/rcore-os/trapframe-rs),
* which is released under the following license:
*
* SPDX-License-Identifier: MIT
*
* Copyright (c) 2020 - 2024 Runji Wang
*
* We make the following new changes:
* * Add the `trap_handler_table`.
* * Adjust some symbol names.
* * Fix an off-by-one bug to correct the RSP value in the trap frame.
* * Disable alternate macro mode after using it.
*
* These changes are released under the following license:
*
* SPDX-License-Identifier: MPL-2.0
*/
.equ NUM_INT, 256
.text
.code64
.altmacro # enable alternate macro mode to use "%i"
.macro DEF_HANDLER, i
_trap_handler_\i:
.if \i == 8 || (\i >= 10 && \i <= 14) || \i == 17
# error code pushed by CPU
push \i # interrupt vector
jmp trap_common
.else
push 0 # fill in error code in TrapFrame
push \i # interrupt vector
jmp trap_common
.endif
.endm
_trap_handlers:
.set i, 0
.rept NUM_INT
DEF_HANDLER %i
.set i, i + 1
.endr
.rodata
.macro DEF_TABLE_ENTRY, i
.quad _trap_handler_\i
.endm
.global trap_handler_table
trap_handler_table:
.set i, 0
.rept NUM_INT
DEF_TABLE_ENTRY %i
.set i, i + 1
.endr
.noaltmacro # disable alternate macro mode; otherwise, it may leak to other files
.text
.code64
trap_common:
cld # clear DF before going to Rust to conform to x86-64 calling convention
push rax
mov ax, [rsp + 4*8] # load cs
and ax, 0x3 # test
jz _trap_from_kernel # continue trap
_trap_from_user:
# kernel stack:
# - ptr to UserContext
# - ss
# - rsp
# - rflags
# - cs
# - rip
# - error code
# - trap num
# - rax
swapgs # swap in kernel gs
mov rax, [rsp + 6*8] # rax = user rsp
mov gs:12, rax # store user rsp -> scratch at TSS.sp1
mov rsp, [rsp + 8*8] # load rsp <- UserContext
add rsp, 22*8 # rsp -> top of UserContext
mov rax, gs:4 # rax = kernel stack
# push trap_num, error_code
push [rax - 6*8] # push error_code
push [rax - 7*8] # push trap_num
sub rsp, 16 # skip fsbase, gsbase
# push general registers
push [rax - 3*8] # push rflags
push [rax - 5*8] # push rip
mov rax, [rax - 8*8] # pop rax
.extern trap_syscall_entry
jmp trap_syscall_entry
_trap_from_kernel:
# kernel stack:
# - rflags
# - cs
# - rip
# - error code
# - trap num
# - rax
pop rax
push 0
push r15
push r14
push r13
push r12
push r11
push r10
push r9
push r8
lea r8, [rsp + 14*8]
push r8 # push rsp
push rbp
push rdi
push rsi
push rdx
push rcx
push rbx
push rax
mov rdi, rsp
call trap_handler
pop rax
pop rbx
pop rcx
pop rdx
pop rsi
pop rdi
pop rbp
pop r8 # skip rsp
pop r8
pop r9
pop r10
pop r11
pop r12
pop r13
pop r14
pop r15
# skip padding, trap_num, error_code
add rsp, 24
iretq