You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
126 lines
3.0 KiB
ArmAsm
126 lines
3.0 KiB
ArmAsm
/* Copyright (C) 2021,2022 fef <owo@fef.moe>. All rights reserved. */
|
|
|
|
#include <arch/interrupt.h>
|
|
|
|
#include <asm/common.h>
|
|
|
|
.section .text.isr
|
|
|
|
/*
|
|
* push all registers except %rsi to the stack, and store a pointer to the
|
|
* struct amd64_trap_frame in %rdi (%rsi is assumed to have already been pushed,
|
|
* right after the hardware frame).
|
|
* The pointer is stored in %rdi because that's where you put the first
|
|
* parameter for function calls as per the amd64 System V ABI.
|
|
*/
|
|
.macro prepare_trap_entry
|
|
pushq %rdi
|
|
pushq %r15
|
|
pushq %r14
|
|
pushq %r13
|
|
pushq %r12
|
|
pushq %r11
|
|
pushq %r10
|
|
pushq %r9
|
|
pushq %r8
|
|
pushq %rbp
|
|
pushq %rdx
|
|
pushq %rcx
|
|
pushq %rbx
|
|
pushq %rax
|
|
movq %rsp, %rdi
|
|
.endm
|
|
|
|
.macro prepare_trap_leave
|
|
popq %rax
|
|
popq %rbx
|
|
popq %rcx
|
|
popq %rdx
|
|
popq %rbp
|
|
popq %r8
|
|
popq %r9
|
|
popq %r10
|
|
popq %r11
|
|
popq %r12
|
|
popq %r13
|
|
popq %r14
|
|
popq %r15
|
|
popq %rdi
|
|
.endm
|
|
|
|
/*
|
|
* Low level trap entry points, this is what gets put into the IDT.
|
|
*
|
|
* Hardware automatically pushes EFLAGS, CS, EIP, and (optionally) an error
|
|
* code to the stack. The rest is pushed by software using the pushal
|
|
* instruction. I wanted to use the same context save struct for both kinds
|
|
* of exceptions (the ones that push an error code and the ones that don't),
|
|
* so the pointer to the hardware context save is also pushed to the stack and
|
|
* included in struct x86_trap_frame.
|
|
*/
|
|
|
|
.macro gen_isr_noerror name
|
|
.extern x86_isr_\name
|
|
ENTRY(_x86_isr_\name )
|
|
cld
|
|
pushq %rsi
|
|
prepare_trap_entry
|
|
|
|
callq x86_isr_\name
|
|
|
|
prepare_trap_leave
|
|
popq %rsi
|
|
iretq
|
|
END(_x86_isr_\name )
|
|
.endm
|
|
|
|
/*
|
|
* This is for traps that additionally push an error code to the stack before
|
|
* entering the handler. The thing with that error code is that it is *not*
|
|
* popped from the stack when leaving again, so we need to account for that
|
|
* difference ourselves.
|
|
*/
|
|
.macro gen_isr_error name
|
|
.extern x86_isr_\name
|
|
ENTRY(_x86_isr_\name )
|
|
cld
|
|
|
|
/*
|
|
* Rather than pushing %rsi, we exchange it with the error code that
|
|
* was pushed by hardware in addition to the regular stack frame.
|
|
* This produces the same stack layout as the ISRs that don't push an
|
|
* error code, and additionally moves said code into the appropriate
|
|
* register for passing it as the second argument to the handler.
|
|
*/
|
|
xchgq %rsi, (%rsp)
|
|
prepare_trap_entry
|
|
|
|
callq x86_isr_\name
|
|
|
|
prepare_trap_leave
|
|
popq %rsi
|
|
iretq
|
|
END(_x86_isr_\name )
|
|
.endm
|
|
|
|
gen_isr_noerror divide_error
|
|
gen_isr_noerror debug_exception
|
|
gen_isr_noerror nmi
|
|
gen_isr_noerror breakpoint
|
|
gen_isr_noerror overflow
|
|
gen_isr_noerror bound_range_exceeded
|
|
gen_isr_noerror invalid_opcode
|
|
gen_isr_noerror device_not_available
|
|
gen_isr_error double_fault
|
|
gen_isr_error invalid_tss
|
|
gen_isr_error segment_not_present
|
|
gen_isr_error stack_segment_fault
|
|
gen_isr_error general_protection
|
|
gen_isr_error page_fault
|
|
gen_isr_noerror x87_fpu_error
|
|
gen_isr_error alignment_check
|
|
gen_isr_noerror machine_check
|
|
gen_isr_noerror simd_floating_point_exception
|
|
gen_isr_noerror virtualization_exception
|
|
gen_isr_error control_protection_exception
|