#define ASM_SOURCE 1 #include "segment.h" .file "irq_wrappers.S" .text .extern exception_handler_wrap .globl exception_handler_wrapper_array /** Update the kernel TSS in case we are switching to a thread in user mode in order to come back into the correct kernel stack */ .extern cpu_context_update_kernel_tss /* The address of the function to call to set back the user thread's MMU configuration upon return to user context */ .extern threadPrepareExceptionSwitchBack .altmacro .macro exception_mac id exception_wrapper_\id: .type exception_wrapper_\id,@function /* INTERRUPT FRAME START */ /* ALREADY PUSHED TO US BY THE PROCESSOR UPON ENTRY TO THIS INTERRUPT */ /* uint32_t flags */ /* uint32_t cs; */ /* uint32_t ip */ /* Pushes the other reg to save same and look like a struct cpu_state*/ /* Fake error code */ pushl $0 /* Backup the actual context */ pushl %ebp movl %esp, %ebp pushl %eax pushl %ecx pushl %edx pushl %ebx pushl %esi pushl %edi subl $2,%esp pushw %ss pushw %ds pushw %es pushw %fs pushw %gs /* Set correct kernel segment descriptors' value */ movw $BUILD_SEGMENT_REG_VALUE(0, 0, SEG_KDATA), %di pushw %di ; popw %ds pushw %di ; popw %es pushw %di ; popw %fs pushw %di ; popw %gs push %esp pushl $\id call exception_handler_wrap addl $8, %esp /* Reconfigure the MMU if needed */ pushl %esp /* cpu_ctxt */ call threadPrepareExceptionSwitchBack addl $4, %esp /* Unallocate the stack */ /* Prepare kernel TSS in case we are switching to a user thread: we make sure that we will come back into the kernel at a correct stack location */ pushl %esp /* Pass the location of the context we are restoring to the function */ call cpu_context_update_kernel_tss addl $4, %esp /* Restore the context */ popw %gs popw %fs popw %es popw %ds popw %ss addl $2,%esp popl %edi popl %esi popl %ebx popl %edx popl %ecx popl %eax popl %ebp /* Remove fake error code */ addl $4, %esp iret .endm .macro exception_mac_with_errcode id exception_wrapper_\id: .type exception_wrapper_\id,@function /* INTERRUPT FRAME START */ /* ALREADY PUSHED TO US BY THE PROCESSOR UPON ENTRY TO THIS INTERRUPT */ /* uint32_t flags */ /* uint32_t cs; */ /* uint32_t ip */ /* uint32_t errcode */ /* Pushes the other reg to save same and look like a struct cpu_state*/ /* Backup the actual context */ pushl %ebp movl %esp, %ebp pushl %eax pushl %ecx pushl %edx pushl %ebx pushl %esi pushl %edi subl $2,%esp pushw %ss pushw %ds pushw %es pushw %fs pushw %gs /* Set correct kernel segment descriptors' value */ movw $BUILD_SEGMENT_REG_VALUE(0, 0, SEG_KDATA), %di pushw %di ; popw %ds pushw %di ; popw %es pushw %di ; popw %fs pushw %di ; popw %gs push %esp pushl $\id call exception_handler_wrap addl $8, %esp /* Reconfigure the MMU if needed */ pushl %esp /* cpu_ctxt */ call threadPrepareExceptionSwitchBack addl $4, %esp /* Unallocate the stack */ /* Prepare kernel TSS in case we are switching to a user thread: we make sure that we will come back into the kernel at a correct stack location */ pushl %esp /* Pass the location of the context we are restoring to the function */ call cpu_context_update_kernel_tss addl $4, %esp /* Restore the context */ popw %gs popw %fs popw %es popw %ds popw %ss addl $2,%esp popl %edi popl %esi popl %ebx popl %edx popl %ecx popl %eax popl %ebp /* Error code isn't compatible with iretd */ addl $4, %esp iret .endm /* List of exception w or w/o err code https://wiki.osdev.org/Exceptions */ .irp exception_id, 8, 10, 11, 12, 13, 14, 17, 30 exception_mac_with_errcode exception_id .endr .irp exception_id, 0, 1, 2, 3, 4, 5, 6, 7, 9, 15, 16, 18, 19, 20 21, 22, 23, 24, 25, 26, 27, 28, 29, 31 exception_mac exception_id .endr .macro ref_exception_wrapper id .long exception_wrapper_\id .endm .section ".rodata" .p2align 5, 0x0 exception_handler_wrapper_array: .set i, 0x0 .rept 0x20 ref_exception_wrapper %i .set i, i+1 .endr