diff mbox

[U-Boot] x86: Force 32-bit jumps in interrupt handlers

Message ID D469A2E0-1B3C-4786-9EAF-EAFF03D08683@jtang.org
State Accepted
Commit 3c03f4928e96dce4c6cd14fb630dacad13a141ae
Delegated to: Bin Meng
Headers show

Commit Message

J. Tang Feb. 10, 2017, 2:54 a.m. UTC
Depending upon the compiler used, IRQ entries could vary in sizes. With
GCC 5.x, the code generator will use short jumps for some IRQ entries
but near jumps for others. For example, GCC 5.4.0 generates the
following:

$ objdump -d interrupt.o
<snip>
00000207 <irq_18>:
207:   6a 12                   push   $0x12
209:   eb 85                   jmp    190 <irq_common_entry>

0000020b <irq_19>:
20b:   6a 13                   push   $0x13
20d:   eb 81                   jmp    190 <irq_common_entry>

0000020f <irq_20>:
20f:   6a 14                   push   $0x14
211:   e9 7a ff ff ff          jmp    190 <irq_common_entry>

00000216 <irq_21>:
216:   6a 15                   push   $0x15
218:   e9 73 ff ff ff          jmp    190 <irq_common_entry>

This causes a problem in cpu_init_interrupts(), because the IDT setup
assumed same sizes for all IRQ entries. GCC 4.x always generated 32-bit
jumps, so this previously was not a problem.

The fix is to force 32-bit near jumps for all entries within the
inline assembly. This works for GCC 5.x, and 4.x was already using
that form of jumping.

Signed-off-by: Jason Tang <tang@jtang.org>
---
 arch/x86/cpu/i386/interrupt.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Comments

Bin Meng Feb. 10, 2017, 3:46 a.m. UTC | #1
On Fri, Feb 10, 2017 at 10:54 AM, J. Tang <tang@jtang.org> wrote:
> Depending upon the compiler used, IRQ entries could vary in sizes. With
> GCC 5.x, the code generator will use short jumps for some IRQ entries
> but near jumps for others. For example, GCC 5.4.0 generates the
> following:
>
> $ objdump -d interrupt.o
> <snip>
> 00000207 <irq_18>:
> 207:   6a 12                   push   $0x12
> 209:   eb 85                   jmp    190 <irq_common_entry>
>
> 0000020b <irq_19>:
> 20b:   6a 13                   push   $0x13
> 20d:   eb 81                   jmp    190 <irq_common_entry>
>
> 0000020f <irq_20>:
> 20f:   6a 14                   push   $0x14
> 211:   e9 7a ff ff ff          jmp    190 <irq_common_entry>
>
> 00000216 <irq_21>:
> 216:   6a 15                   push   $0x15
> 218:   e9 73 ff ff ff          jmp    190 <irq_common_entry>
>
> This causes a problem in cpu_init_interrupts(), because the IDT setup
> assumed same sizes for all IRQ entries. GCC 4.x always generated 32-bit
> jumps, so this previously was not a problem.
>
> The fix is to force 32-bit near jumps for all entries within the
> inline assembly. This works for GCC 5.x, and 4.x was already using
> that form of jumping.
>
> Signed-off-by: Jason Tang <tang@jtang.org>
> ---
>  arch/x86/cpu/i386/interrupt.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
Bin Meng Feb. 21, 2017, 6:54 a.m. UTC | #2
On Fri, Feb 10, 2017 at 11:46 AM, Bin Meng <bmeng.cn@gmail.com> wrote:
> On Fri, Feb 10, 2017 at 10:54 AM, J. Tang <tang@jtang.org> wrote:
>> Depending upon the compiler used, IRQ entries could vary in sizes. With
>> GCC 5.x, the code generator will use short jumps for some IRQ entries
>> but near jumps for others. For example, GCC 5.4.0 generates the
>> following:
>>
>> $ objdump -d interrupt.o
>> <snip>
>> 00000207 <irq_18>:
>> 207:   6a 12                   push   $0x12
>> 209:   eb 85                   jmp    190 <irq_common_entry>
>>
>> 0000020b <irq_19>:
>> 20b:   6a 13                   push   $0x13
>> 20d:   eb 81                   jmp    190 <irq_common_entry>
>>
>> 0000020f <irq_20>:
>> 20f:   6a 14                   push   $0x14
>> 211:   e9 7a ff ff ff          jmp    190 <irq_common_entry>
>>
>> 00000216 <irq_21>:
>> 216:   6a 15                   push   $0x15
>> 218:   e9 73 ff ff ff          jmp    190 <irq_common_entry>
>>
>> This causes a problem in cpu_init_interrupts(), because the IDT setup
>> assumed same sizes for all IRQ entries. GCC 4.x always generated 32-bit
>> jumps, so this previously was not a problem.
>>
>> The fix is to force 32-bit near jumps for all entries within the
>> inline assembly. This works for GCC 5.x, and 4.x was already using
>> that form of jumping.
>>
>> Signed-off-by: Jason Tang <tang@jtang.org>
>> ---
>>  arch/x86/cpu/i386/interrupt.c | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>
>
> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

applied to u-boot-x86, thanks!
diff mbox

Patch

diff --git a/arch/x86/cpu/i386/interrupt.c b/arch/x86/cpu/i386/interrupt.c
index a058303..ba576fe 100644
--- a/arch/x86/cpu/i386/interrupt.c
+++ b/arch/x86/cpu/i386/interrupt.c
@@ -28,7 +28,7 @@  DECLARE_GLOBAL_DATA_PTR;
 	".type irq_"#x", @function\n" \
 	"irq_"#x":\n" \
 	"pushl $"#x"\n" \
-	"jmp irq_common_entry\n"
+	"jmp.d32 irq_common_entry\n"
 
 static char *exceptions[] = {
 	"Divide Error",