[U-Boot] [BUG] x86: invalid size calculations in interrupts.c with newer GCC

J. Tang tang at jtang.org
Sun Feb 5 15:54:18 UTC 2017


On latest master (commit 0ff27d), when using the stock qemu-x86_defconfig, it is possible to build an invalid U-Boot. I traced the issue to arch/x86/cpu/interrupts.c. The problem is that cpu_init_interrupts() assumes that each IRQ entry consumes the same number of bytes. Depending upon the compiler used, this assumption is incorrect.

Commit 564a9984 added this hunk:

   +void irq_0(void);
   +void irq_1(void);
 
    int cpu_init_interrupts(void)
    {
            int i;
 
   +        int irq_entry_size = irq_1 - irq_0;
   +        void *irq_entry = (void *)irq_0;

When I used a Buildroot derived compiler, I got this assembly code for arch/x86/cpu/interrupts.o:

$ /home/tang/buildroot-x86/output/host/usr/bin/x86_64-linux-gcc --version
x86_64-linux-gcc.br_real (Buildroot 2016.11.1) 5.4.0
$ objdump -d interrupts.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>

Based upon the offset difference, the newer GCC optimizer will use a shorter jmp opcode instruction. This results in varying size IRQ entries. As a comparison, a stock Debian compiler produced this assembly:

$ gcc --version
gcc (Debian 4.9.2-10) 4.9.2
$ objdump -d interrupts.o
<snip>
00000240 <irq_18>:
 240:   6a 12                   push   $0x12
 242:   e9 fc ff ff ff          jmp    243 <irq_18+0x3>

00000247 <irq_19>:
 247:   6a 13                   push   $0x13
 249:   e9 fc ff ff ff          jmp    24a <irq_19+0x3>

0000024e <irq_20>:
 24e:   6a 14                   push   $0x14
 250:   e9 fc ff ff ff          jmp    251 <irq_20+0x3>

00000255 <irq_21>:
 255:   6a 15                   push   $0x15
 257:   e9 fc ff ff ff          jmp    258 <irq_21+0x3>

I got around this temporarily by having directly referencing all 256 IRQ symbols, rather than compute the next IRQ address relative to the previous. Hopefully someone can come up with a more elegant solution.

-- 
Jason Tang  /  tang at jtang.org




More information about the U-Boot mailing list