The current code results in `error: invalid reassignment of non-absolute variable 'isr_stub_start'`. Use a numbered label instead (as that can be reassigned) and reference the last occurrence using the b suffix.
157 lines
3.2 KiB
ArmAsm
157 lines
3.2 KiB
ArmAsm
/*
|
|
* Copyright (c) 2009 Corey Tabaka
|
|
* Copyright (c) 2015 Intel Corporation
|
|
* Copyright (c) 2016 Travis Geiselbrecht
|
|
*
|
|
* Use of this source code is governed by a MIT-style
|
|
* license that can be found in the LICENSE file or at
|
|
* https://opensource.org/licenses/MIT
|
|
*/
|
|
#include <lk/asm.h>
|
|
#include <arch/x86/descriptor.h>
|
|
|
|
#define NUM_INT 0x100
|
|
#define NUM_EXC 0x14
|
|
|
|
.text
|
|
|
|
/* interrupt service routine stubs */
|
|
|
|
/*
|
|
* pushq $i occupies 5 bytes when i >= 0x80 compare to
|
|
* 2 bytes when i < 0x80, use align to fill the gap
|
|
* to make sure isr_stub_len correct for each interrupts
|
|
*/
|
|
_isr:
|
|
.set i, 0
|
|
.rept NUM_INT
|
|
|
|
100: /* unnamed label for start of isr stub */
|
|
|
|
.if i == 8 || (i >= 10 && i <= 14) || i == 17
|
|
.align 16
|
|
nop /* error code pushed by exception */
|
|
nop /* 2 nops are the same length as push byte */
|
|
pushq $i /* interrupt number */
|
|
jmp interrupt_common
|
|
.align 16
|
|
.else
|
|
.align 16
|
|
pushq $0 /* fill in error code in iframe */
|
|
pushq $i /* interrupt number */
|
|
jmp interrupt_common
|
|
.align 16
|
|
.endif
|
|
|
|
.set i, i + 1
|
|
.endr
|
|
|
|
/* figure out the length of a single isr stub (usually 6 or 9 bytes) */
|
|
.set isr_stub_len, . - 100b
|
|
|
|
/* annoying, but force AS to use the same (longer) encoding of jmp for all of the stubs */
|
|
.fill 256
|
|
|
|
interrupt_common:
|
|
|
|
/* clear the direction bit */
|
|
cld
|
|
|
|
/* save general purpose registers */
|
|
pushq %r15
|
|
pushq %r14
|
|
pushq %r13
|
|
pushq %r12
|
|
pushq %r11
|
|
pushq %r10
|
|
pushq %r9
|
|
pushq %r8
|
|
pushq %rax
|
|
pushq %rcx
|
|
pushq %rdx
|
|
pushq %rbx
|
|
pushq %rbp
|
|
pushq %rsi
|
|
pushq %rdi
|
|
|
|
/* pass the iframe using rdi */
|
|
movq %rsp, %rdi
|
|
|
|
call x86_exception_handler
|
|
|
|
/* restore general purpose registers */
|
|
popq %rdi
|
|
popq %rsi
|
|
popq %rbp
|
|
popq %rbx
|
|
popq %rdx
|
|
popq %rcx
|
|
popq %rax
|
|
popq %r8
|
|
popq %r9
|
|
popq %r10
|
|
popq %r11
|
|
popq %r12
|
|
popq %r13
|
|
popq %r14
|
|
popq %r15
|
|
|
|
/* drop vector number and error code*/
|
|
addq $16, %rsp
|
|
iretq
|
|
|
|
FUNCTION(setup_idt)
|
|
/* setup isr stub descriptors in the idt */
|
|
mov $_isr, %rsi
|
|
mov $_idt, %rdi
|
|
movl $NUM_INT, %ecx
|
|
|
|
.Lloop:
|
|
mov %rsi, %rbx
|
|
movw %bx, (%rdi) /* offset [0:15] in IDT(n).low */
|
|
shr $16, %rbx
|
|
movw %bx, 6(%rdi) /* offset [16:31] in IDT(n).high */
|
|
shr $16, %rbx
|
|
movl %ebx, 8(%rdi) /* offset [32:63] */
|
|
|
|
add $isr_stub_len, %rsi /* index the next ISR stub */
|
|
add $16, %rdi /* index the next IDT entry */
|
|
|
|
loop .Lloop
|
|
|
|
lidt _idtr
|
|
|
|
ret
|
|
|
|
.data
|
|
|
|
.align 8
|
|
DATA(_idtr)
|
|
.short _idt_end - _idt - 1 /* IDT limit */
|
|
.quad _idt
|
|
.fill 8
|
|
|
|
.align 8
|
|
/* interrupt descriptor table (IDT) */
|
|
DATA(_idt)
|
|
|
|
.set i, 0
|
|
.rept NUM_INT
|
|
.short 0 /* low 16 bits of ISR offset (_isr#i & 0FFFFh) */
|
|
.short CODE_64_SELECTOR /* selector */
|
|
.byte 0
|
|
.byte 0x8e /* present, ring 0, 64-bit interrupt gate */
|
|
.short 0 /* high 16 bits of ISR offset (_isr#i / 65536) */
|
|
.short 0 /* ISR offset */
|
|
.short 0 /* ISR offset */
|
|
.short 0 /* 32bits Reserved */
|
|
.short 0 /* 32bits Reserved */
|
|
|
|
|
|
.set i, i + 1
|
|
.endr
|
|
|
|
.global _idt_end
|
|
_idt_end:
|
|
|