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