224 lines
4.4 KiB
ArmAsm

.altmacro
.global __x86_64_apic_vectors
.set IRQ_REG_RAX, 0 * 8
.set IRQ_REG_RCX, 1 * 8
.set IRQ_REG_RDX, 2 * 8
.set IRQ_REG_RBX, 3 * 8
.set IRQ_REG_RSI, 4 * 8
.set IRQ_REG_RDI, 5 * 8
.set IRQ_REG_RBP, 6 * 8
.set IRQ_REG_R8, 7 * 8
.set IRQ_REG_R9, 8 * 8
.set IRQ_REG_R10, 9 * 8
.set IRQ_REG_R11, 10 * 8
.set IRQ_REG_R12, 11 * 8
.set IRQ_REG_R13, 12 * 8
.set IRQ_REG_R14, 13 * 8
.set IRQ_REG_R15, 14 * 8
// 15 registers + stack align word if needed
.set IRQ_STATE_SIZE, 15 * 8
.macro IRQ_SWAPGS_IF_NEEDED, cs_off
cmpq $0x08, \cs_off(%rsp)
je 1f
swapgs
1:
.endm
.macro IRQ_SAVE_STATE
// Save state
subq $IRQ_STATE_SIZE, %rsp
movq %rax, IRQ_REG_RAX(%rsp)
movq %rcx, IRQ_REG_RCX(%rsp)
movq %rdx, IRQ_REG_RDX(%rsp)
movq %rbx, IRQ_REG_RBX(%rsp)
movq %rsi, IRQ_REG_RSI(%rsp)
movq %rdi, IRQ_REG_RDI(%rsp)
movq %rbp, IRQ_REG_RBP(%rsp)
movq %r8, IRQ_REG_R8(%rsp)
movq %r9, IRQ_REG_R9(%rsp)
movq %r10, IRQ_REG_R10(%rsp)
movq %r11, IRQ_REG_R11(%rsp)
movq %r12, IRQ_REG_R12(%rsp)
movq %r13, IRQ_REG_R13(%rsp)
movq %r14, IRQ_REG_R14(%rsp)
movq %r15, IRQ_REG_R15(%rsp)
// Save current stack into %rbp
movq %rsp, %rbp
// Force correct stack alignment
orq $0xF, %rsp
xorq $0xF, %rsp
.endm
.macro IRQ_RESTORE_STATE
// Restore the stack pointer
movq %rbp, %rsp
// Restore state
movq IRQ_REG_RAX(%rsp), %rax
movq IRQ_REG_RCX(%rsp), %rcx
movq IRQ_REG_RDX(%rsp), %rdx
movq IRQ_REG_RBX(%rsp), %rbx
movq IRQ_REG_RSI(%rsp), %rsi
movq IRQ_REG_RDI(%rsp), %rdi
movq IRQ_REG_RBP(%rsp), %rbp
movq IRQ_REG_R8(%rsp), %r8
movq IRQ_REG_R9(%rsp), %r9
movq IRQ_REG_R10(%rsp), %r10
movq IRQ_REG_R11(%rsp), %r11
movq IRQ_REG_R12(%rsp), %r12
movq IRQ_REG_R13(%rsp), %r13
movq IRQ_REG_R14(%rsp), %r14
movq IRQ_REG_R15(%rsp), %r15
addq $IRQ_STATE_SIZE, %rsp
.endm
.macro IRQ_VECTOR, n
irq_vector_\n:
// %rsp + 0: %rip
// %rsp + 8: %cs
IRQ_SWAPGS_IF_NEEDED 8
IRQ_SAVE_STATE
// Force correct segment registers
mov $0x10, %ax
mov %ax, %ss
mov %ax, %ds
mov %ax, %es
mov $\n, %rdi
mov %rbp, %rsi
call {irq_handler}
IRQ_RESTORE_STATE
IRQ_SWAPGS_IF_NEEDED 8
iretq
.endm
.macro IRQ_VECTOR_ENTRY, n
.quad irq_vector_\n
.endm
.macro IRQ_VECTORS, start, end
.set i, 0
.rept \end - \start
IRQ_VECTOR %i
.set i, i+1
.endr
.endm
.macro IRQ_VECTOR_ENTRIES, start, end
.set i, 0
.rept \end - \start
IRQ_VECTOR_ENTRY %i
.set i, i+1
.endr
.endm
.macro MSI_VECTOR, n
msi_vector_\n:
// %rsp + 0: %rip
// %rsp + 8: %cs
IRQ_SWAPGS_IF_NEEDED 8
IRQ_SAVE_STATE
// Force correct segment registers
mov $0x10, %ax
mov %ax, %ss
mov %ax, %ds
mov %ax, %es
mov $\n, %rdi
mov %rbp, %rsi
call {msi_handler}
IRQ_RESTORE_STATE
IRQ_SWAPGS_IF_NEEDED 8
iretq
.endm
.macro MSI_VECTOR_ENTRY, n
.quad msi_vector_\n
.endm
.macro MSI_VECTORS, start, end
.set i, 0
.rept \end - \start
MSI_VECTOR %i
.set i, i+1
.endr
.endm
.macro MSI_VECTOR_ENTRIES, start, end
.set i, 0
.rept \end - \start
MSI_VECTOR_ENTRY %i
.set i, i+1
.endr
.endm
.macro FILL_EMPTY_SPACE, start, end
.set i, 0
.rept \end - \start
.quad dummy_vector
.endr
.endm
.section .text
local_timer_vector:
IRQ_SWAPGS_IF_NEEDED 8
IRQ_SAVE_STATE
mov %rbp, %rdi
call {local_timer_irq_handler}
IRQ_RESTORE_STATE
IRQ_SWAPGS_IF_NEEDED 8
iretq
ipi_vector:
IRQ_SWAPGS_IF_NEEDED 8
IRQ_SAVE_STATE
call {ipi_handler}
jmp .
dummy_vector:
IRQ_SWAPGS_IF_NEEDED 8
IRQ_SAVE_STATE
call {dummy_irq_handler}
jmp .
IRQ_VECTORS {irq_vector_offset}, {irq_vector_offset} + {irq_vector_count}
MSI_VECTORS {msi_vector_offset}, {msi_vector_offset} + {msi_vector_count}
.section .rodata
// 224 vectors: 256 - 32 (exceptions)
.p2align 4
.type __x86_64_apic_vectors, @object
__x86_64_apic_vectors:
// Local timer IRQ: 0
.quad local_timer_vector
// Dummy entries (currently): 1..=2
.quad dummy_vector
.quad dummy_vector
// IPI vector: 3
.quad ipi_vector
// Regular IRQ vectors: 4..207
IRQ_VECTOR_ENTRIES {irq_vector_offset}, {irq_vector_offset} + {irq_vector_count}
// MSI vectors: 207..223
MSI_VECTOR_ENTRIES {msi_vector_offset}, {msi_vector_offset} + {msi_vector_count}
// Spurious interrupt vector: 223
.quad dummy_vector
.size __x86_64_apic_vectors, . - __x86_64_apic_vectors