From ab0e1fd3a164ac3dedcd61810dd33863b42cd9da Mon Sep 17 00:00:00 2001 From: Travis Geiselbrecht Date: Sun, 10 Mar 2024 21:29:47 -0700 Subject: [PATCH] [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 --- arch/x86/32/exceptions.S | 59 ++++++++++++++++------------------------ arch/x86/64/exceptions.S | 52 ++++++++++++++++------------------- arch/x86/gdt.S | 10 +++++-- 3 files changed, 54 insertions(+), 67 deletions(-) diff --git a/arch/x86/32/exceptions.S b/arch/x86/32/exceptions.S index 98ac81f176..e1bca374d4 100644 --- a/arch/x86/32/exceptions.S +++ b/arch/x86/32/exceptions.S @@ -10,39 +10,34 @@ #include #include -#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) diff --git a/arch/x86/64/exceptions.S b/arch/x86/64/exceptions.S index 86a54827b4..cecb5eb5f7 100644 --- a/arch/x86/64/exceptions.S +++ b/arch/x86/64/exceptions.S @@ -11,7 +11,7 @@ #include #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) + diff --git a/arch/x86/gdt.S b/arch/x86/gdt.S index 398a267130..abb9c7946c 100644 --- a/arch/x86/gdt.S +++ b/arch/x86/gdt.S @@ -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)