/* Copyright (C) 2021,2022 fef . All rights reserved. */ #include #include .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_(%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