[arch][x86][exceptions] clean up the exception handlers

For both 32 and 64bit x86, have each of the exception stubs which push a
few words and branch to the common isr routine be simply 16 byte aligned
to make it easy to calculate the offset from the main isr table. This
cleans up some complexity that was actually broken for interrupts >= 0x80.

Also:
-Switch alignment directives to .balign
-Expand the x86-32 exception table to a full 256
-Remove an extraneous define
-Make sure the IDT is 8 or 16 byte aligned
-Use END_DATA and END_FUNCTION in the exception and gdt asm files
This commit is contained in:
Travis Geiselbrecht
2024-03-10 21:29:47 -07:00
parent 6d7d31d9b4
commit ab0e1fd3a1
3 changed files with 54 additions and 67 deletions

View File

@@ -10,39 +10,34 @@
#include <lk/asm.h>
#include <arch/x86/descriptor.h>
#define NUM_INT 0x31
#define NUM_EXC 0x14
#define NUM_INT 0x100
#define ISR_STUB_LEN 16
.text
/* interrupt service routine stubs */
_isr:
.balign ISR_STUB_LEN
LOCAL_FUNCTION(_isr_vectors)
.set i, 0
.rept NUM_INT
100: /* unnamed label for start of isr stub */
.balign ISR_STUB_LEN
.if i == 8 || (i >= 10 && i <= 14) || i == 17
nop /* error code pushed by exception */
nop /* 2 nops are the same length as push byte */
pushl $i /* interrupt number */
/* error code pushed by exception */
push $i /* interrupt number */
jmp interrupt_common
.else
pushl $0 /* fill in error code in iframe */
pushl $i /* interrupt number */
push $0 /* fill in error code in iframe */
push $i /* interrupt number */
jmp interrupt_common
.endif
.set i, i + 1
.endr
END_FUNCTION(_isr_vectors)
/* 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
FUNCTION(interrupt_common)
.balign 16
LOCAL_FUNCTION(interrupt_common)
cld
pushl %gs /* save segment registers */
pushl %fs
@@ -69,10 +64,11 @@ FUNCTION(interrupt_common)
popl %gs
addl $8, %esp /* drop exception number and error code */
iret
END_FUNCTION(interrupt_common)
FUNCTION(setup_idt)
/* setup isr stub descriptors in the idt */
movl $_isr, %esi
movl $_isr_vectors, %esi
movl $_idt, %edi
movl $NUM_INT, %ecx
@@ -82,7 +78,7 @@ FUNCTION(setup_idt)
shrl $16, %ebx
movw %bx, 6(%edi) /* high word in IDT(n).high */
addl $isr_stub_len, %esi/* index the next ISR stub */
addl $ISR_STUB_LEN, %esi/* index the next ISR stub */
addl $8, %edi /* index the next IDT entry */
loop .Lloop
@@ -90,19 +86,19 @@ FUNCTION(setup_idt)
lidt _idtr
ret
END_FUNCTION(setup_idt)
.data
.align 8
.global _idtr
_idtr:
.balign 8
DATA(_idtr)
.short _idt_end - _idt - 1 /* IDT limit */
.int _idt
END_DATA(_idtr)
/* interrupt descriptor table (IDT) */
.global _idt
_idt:
.balign 8
DATA(_idt)
.set i, 0
.rept NUM_INT-1
.short 0 /* low 16 bits of ISR offset (_isr#i & 0FFFFh) */
@@ -114,15 +110,6 @@ _idt:
.set i, i + 1
.endr
/* syscall int (ring 3) */
_idt30:
.short 0 /* low 16 bits of ISR offset (_isr#i & 0FFFFh) */
.short CODE_SELECTOR /* selector */
.byte 0
.byte 0xee /* present, ring 3, 32-bit interrupt gate */
.short 0 /* high 16 bits of ISR offset (_isr#i / 65536) */
.global _idt_end
_idt_end:
END_DATA(_idt)
DATA(_idt_end)

View File

@@ -11,7 +11,7 @@
#include <arch/x86/descriptor.h>
#define NUM_INT 0x100
#define NUM_EXC 0x14
#define ISR_STUB_LEN 16
.text
@@ -22,36 +22,29 @@
* 2 bytes when i < 0x80, use align to fill the gap
* to make sure isr_stub_len correct for each interrupts
*/
.balign ISR_STUB_LEN
LOCAL_FUNCTION(_isr_vectors)
_isr:
.set i, 0
.rept NUM_INT
100: /* unnamed label for start of isr stub */
.balign ISR_STUB_LEN
.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
/* error code pushed by exception */
push $i /* interrupt number */
jmp interrupt_common
.else
.align 16
pushq $0 /* fill in error code in iframe */
pushq $i /* interrupt number */
jmp interrupt_common
.align 16
push $0 /* fill in error code in iframe */
push $i /* interrupt number */
jmp interrupt_common
.endif
.set i, i + 1
.endr
END_FUNCTION(_isr_vectors)
/* 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
.balign 16
LOCAL_FUNCTION(interrupt_common)
interrupt_common:
/* clear the direction bit */
@@ -99,10 +92,11 @@ interrupt_common:
/* drop vector number and error code*/
addq $16, %rsp
iretq
END_FUNCTION(interrupt_common)
FUNCTION(setup_idt)
/* setup isr stub descriptors in the idt */
mov $_isr, %rsi
mov $_isr_vectors, %rsi
mov $_idt, %rdi
movl $NUM_INT, %ecx
@@ -114,7 +108,7 @@ FUNCTION(setup_idt)
shr $16, %rbx
movl %ebx, 8(%rdi) /* offset [32:63] */
add $isr_stub_len, %rsi /* index the next ISR stub */
add $ISR_STUB_LEN, %rsi /* index the next ISR stub */
add $16, %rdi /* index the next IDT entry */
loop .Lloop
@@ -122,16 +116,17 @@ FUNCTION(setup_idt)
lidt _idtr
ret
END_FUNCTION(setup_idt)
.data
.align 8
.balign 8
DATA(_idtr)
.short _idt_end - _idt - 1 /* IDT limit */
.quad _idt
.fill 8
END_DATA(_idtr)
.align 8
.balign 16
/* interrupt descriptor table (IDT) */
DATA(_idt)
@@ -147,10 +142,11 @@ DATA(_idt)
.short 0 /* 32bits Reserved */
.short 0 /* 32bits Reserved */
.set i, i + 1
.endr
.global _idt_end
_idt_end:
END_DATA(_idt)
DATA(_idt_end)

View File

@@ -16,12 +16,13 @@
.section .rodata
.align 8
.balign 8
DATA(_gdtr_phys)
.short _gdt_end - _gdt - 1
.int PHYS(_gdt)
END_DATA(_gdtr_phys)
.align 8
.balign 8
DATA(_gdtr)
.short _gdt_end - _gdt - 1
#if ARCH_X86_32
@@ -29,9 +30,10 @@ DATA(_gdtr)
#elif ARCH_X86_64
.quad _gdt
#endif
END_DATA(_gdtr)
.data
.align 8
.balign 8
DATA(_gdt)
.int 0
.int 0
@@ -125,5 +127,7 @@ _tss_gde:
.set i, i+1
.endr
END_DATA(_gdt)
DATA(_gdt_end)