.section .shared .global _isr_stubs _isr_stubs: .set i, 0 .rept 256 .set _stub_start, . cli .if i != 8 && i != 10 && i != 11 && i != 12 && i != 13 && i != 14 && i != 17 && i != 21 && i != 29 && i != 30 /* no error code was pushed - push anything, just to line up the stack */ push %rbx .endif call _isr_stage2 .if . - _stub_start > 8 .error "isr stubs over maximum size" .abort .endif .align 8, 0xCC .set i, i + 1 .endr _isr_stage2: /* UserRegs */ /* I'm skipping fields that are in the IRET stack frame * on the assumption it's easier to deal with them from C. */ push $0 /* flags */ push $0 /* ip */ push %rax push %rcx push %rdx push %rbx push $0 /* rsp */ push %rbp push %rsi push %rdi push %r8 push %r9 push %r10 push %r11 push %r12 push %r13 push %r14 push %r15 // TODO FXSAVE might be required on interrupts too? // on interrupts - no // on syscalls - yes // have fun figuring that one out // basically if you're context switching, FXSAVE /* first argument: vector nr. computed from the return address at offset * 18*8 = 144 */ mov 144(%rsp), %rdi sub $_isr_stubs, %rdi shr $3, %rdi /* second argument: stack frame */ mov %rsp, %rsi /* load kernel paging */ mov %cr3, %rbx push %rbx mov $pml4_identity, %rbx mov %rbx, %cr3 mov %rsp, %rbp mov $_isr_big_stack, %rsp call isr_stage3 mov %rbp, %rsp pop %rax /* restore old cr3 */ mov %rax, %cr3 /* restore registers */ pop %r15 pop %r14 pop %r13 pop %r12 pop %r11 pop %r10 pop %r9 pop %r8 pop %rdi pop %rsi pop %rbp pop %rbx /* skip rsp */ pop %rbx pop %rdx pop %rcx pop %rax /* skips: * UserRegs.ip * UserRegs.flags * return address from the CALL in the stub * error code */ add $32, %rsp iretq .align 8 // TODO stack overflow check .skip 256 // seems to be enough .global _isr_mini_stack _isr_mini_stack: