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.

89 lines
2.6 KiB
ArmAsm

/* Copyright (C) 2021,2022 fef <owo@fef.moe>. All rights reserved. */
#include <arch/interrupt.h>
#include <asm/common.h>
.section .text.isr
/*
* 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
pushal
mov %esp, %eax
add $32, %eax
push %eax
call x86_isr_\name
add $4, %esp
popal
iretl
END(_x86_isr_\name )
.endm
/*
* So, instead of just adding a dedicated register for exception status, the
* Intel people apparently thought it was better to have the CPU push an error
* code to the stack. This is technically not too bad of an idea because the
* x86 ABI says all parameters are passed through the stack, so you could write
* exception handlers in C! Too bad the CPU (1) doesn't save scratch registers
* eax, ecx and edx automatically, (2) only some of the exceptions push this
* error code?? and (3) you have to pop the error code manually??????
*/
.macro gen_isr_error name
.extern x86_isr_\name
ENTRY(_x86_isr_\name )
cld
pushal
mov %esp, %eax
add $36, %eax
push %eax /* struct x86_trap_frame::hw_frame */
/*
* pushal pushes 8 registers = 32 bytes to the stack, plus 4 bytes
* for the pointer to struct x86_hw_frame, so the error code pushed
* by hardware is 36 bytes into %esp now
*/
mov 36(%esp), %ebx
mov %esp, %eax
push %ebx
push %eax
call x86_isr_\name /* x86_isr_<name>(%esp, error_code); */
add $8, %esp
popal
add $4, %esp /* "pop" the hardware error code from the stack */
iretl
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