Skip to content

Commit

Permalink
[arch][x86][exceptions] clean up the exception handlers
Browse files Browse the repository at this point in the history
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
  • Loading branch information
travisg committed Mar 11, 2024
1 parent 6d7d31d commit ab0e1fd
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 67 deletions.
59 changes: 23 additions & 36 deletions arch/x86/32/exceptions.S
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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

Expand All @@ -82,27 +78,27 @@ 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

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) */
Expand All @@ -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)
52 changes: 24 additions & 28 deletions arch/x86/64/exceptions.S
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#include <arch/x86/descriptor.h>

#define NUM_INT 0x100
#define NUM_EXC 0x14
#define ISR_STUB_LEN 16

.text

Expand All @@ -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 */
Expand Down Expand Up @@ -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

Expand All @@ -114,24 +108,25 @@ 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

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)

Expand All @@ -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)


10 changes: 7 additions & 3 deletions arch/x86/gdt.S
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,24 @@

.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
.int _gdt
#elif ARCH_X86_64
.quad _gdt
#endif
END_DATA(_gdtr)

.data
.align 8
.balign 8
DATA(_gdt)
.int 0
.int 0
Expand Down Expand Up @@ -125,5 +127,7 @@ _tss_gde:
.set i, i+1
.endr

END_DATA(_gdt)

DATA(_gdt_end)

0 comments on commit ab0e1fd

Please sign in to comment.