[U-Boot] [PATCH 1/4] x86: Specify -march=core2 to build 64-bit U-Boot proper

With newer kernel.org GCC (7.3.0 or 8.1.0), the u-boot.rom image built for qemu-x86_64 target does not boot. It keeps resetting soon after the 32-bit SPL jumps to 64-bit proper. Debugging shows that the reset happens inside env_callback_init().
000000000113dd85 <env_callback_init>: 113dd85: 41 54 push %r12 113dd87: 55 push %rbp 113dd88: 31 c0 xor %eax,%eax 113dd8a: 53 push %rbx 113dd8b: 0f 57 c0 xorps %xmm0,%xmm0
Executing "xorps %xmm0,%xmm0" causes CPU to immediately reset. However older GCC like 5.4.0 (the one shipped by Ubuntu 16.04) does not generate such instructions that utilizes SSE for this function - env_callback_init() and U-Boot boots without any issue. Explicitly specifying -march=core2 for newer GCC allows U-Boot proper to boot again. Examine assembly codes of env_callback_init and there is no SSE instruction in that function hence U-Boot continues to boot.
core2 seems to be the oldest arch in GCC that supports 64-bit. Like 32-bit U-Boot build we use -march=i386 which is the most conservative cpu type so that the image can run on any x86 processor, let's do the same for the 64-bit U-Boot build.
Signed-off-by: Bin Meng bmeng.cn@gmail.com ---
arch/x86/config.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/x86/config.mk b/arch/x86/config.mk index cc94071..576501e 100644 --- a/arch/x86/config.mk +++ b/arch/x86/config.mk @@ -23,7 +23,7 @@ endif ifeq ($(IS_32BIT),y) PLATFORM_CPPFLAGS += -march=i386 -m32 else -PLATFORM_CPPFLAGS += $(if $(CONFIG_SPL_BUILD),,-fpic) -fno-common -m64 +PLATFORM_CPPFLAGS += $(if $(CONFIG_SPL_BUILD),,-fpic) -fno-common -march=core2 -m64 endif
PLATFORM_RELFLAGS += -fdata-sections -ffunction-sections -fvisibility=hidden

With the '-march=core2' fix, it seems that we have some luck that the 64-bit U-Boot boots again. However if we examine the disassembly codes there are still SSE instructions elsewhere which means passing cpu type to GCC is not enough to prevent it from generating these instructions. A simple test case is doing a 'bootefi selftest' from the U-Boot shell and it leads to a reset too.
The 'bootefi selftest' reset is even seen with the image created by the relative older GCC 5.4.0, the one shipped by Ubuntu 16.04.
To make sure no MMX/SSE instruction sets are generated, tell GCC not to do this. Note AVX is out of the question as CORE2 is old enough to support AVX yet.
Signed-off-by: Bin Meng bmeng.cn@gmail.com ---
arch/x86/config.mk | 1 + 1 file changed, 1 insertion(+)
diff --git a/arch/x86/config.mk b/arch/x86/config.mk index 576501e..8151e47 100644 --- a/arch/x86/config.mk +++ b/arch/x86/config.mk @@ -24,6 +24,7 @@ ifeq ($(IS_32BIT),y) PLATFORM_CPPFLAGS += -march=i386 -m32 else PLATFORM_CPPFLAGS += $(if $(CONFIG_SPL_BUILD),,-fpic) -fno-common -march=core2 -m64 +PLATFORM_CPPFLAGS += -mno-mmx -mno-sse endif
PLATFORM_RELFLAGS += -fdata-sections -ffunction-sections -fvisibility=hidden

On 10/11/2018 03:53 AM, Bin Meng wrote:
With the '-march=core2' fix, it seems that we have some luck that the 64-bit U-Boot boots again. However if we examine the disassembly codes there are still SSE instructions elsewhere which means passing cpu type to GCC is not enough to prevent it from generating these instructions. A simple test case is doing a 'bootefi selftest' from the U-Boot shell and it leads to a reset too.
I can confirm that an unexpected reset patch occurs without the patch.
The 'bootefi selftest' reset is even seen with the image created by the relative older GCC 5.4.0, the one shipped by Ubuntu 16.04.
To make sure no MMX/SSE instruction sets are generated, tell GCC not to do this. Note AVX is out of the question as CORE2 is old enough to support AVX yet.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
arch/x86/config.mk | 1 + 1 file changed, 1 insertion(+)
diff --git a/arch/x86/config.mk b/arch/x86/config.mk index 576501e..8151e47 100644 --- a/arch/x86/config.mk +++ b/arch/x86/config.mk @@ -24,6 +24,7 @@ ifeq ($(IS_32BIT),y) PLATFORM_CPPFLAGS += -march=i386 -m32 else PLATFORM_CPPFLAGS += $(if $(CONFIG_SPL_BUILD),,-fpic) -fno-common -march=core2 -m64 +PLATFORM_CPPFLAGS += -mno-mmx -mno-sse
According to https://wiki.osdev.org/SSE SSE has to be initialized. Otherwise SSE instructions lead to an undefined instruction exception. Is it this initialization that we lack? If this is your motivation please, state it in the commit message.
I think this patch could be squashed with the prior one.
Heinrich
endif
PLATFORM_RELFLAGS += -fdata-sections -ffunction-sections -fvisibility=hidden

Hi Heinrich,
On Fri, Oct 12, 2018 at 2:04 AM Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 10/11/2018 03:53 AM, Bin Meng wrote:
With the '-march=core2' fix, it seems that we have some luck that the 64-bit U-Boot boots again. However if we examine the disassembly codes there are still SSE instructions elsewhere which means passing cpu type to GCC is not enough to prevent it from generating these instructions. A simple test case is doing a 'bootefi selftest' from the U-Boot shell and it leads to a reset too.
I can confirm that an unexpected reset patch occurs without the patch.
I think you mean "bootefi selftest" reset, right?
The 'bootefi selftest' reset is even seen with the image created by the relative older GCC 5.4.0, the one shipped by Ubuntu 16.04.
To make sure no MMX/SSE instruction sets are generated, tell GCC not to do this. Note AVX is out of the question as CORE2 is old enough to support AVX yet.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
arch/x86/config.mk | 1 + 1 file changed, 1 insertion(+)
diff --git a/arch/x86/config.mk b/arch/x86/config.mk index 576501e..8151e47 100644 --- a/arch/x86/config.mk +++ b/arch/x86/config.mk @@ -24,6 +24,7 @@ ifeq ($(IS_32BIT),y) PLATFORM_CPPFLAGS += -march=i386 -m32 else PLATFORM_CPPFLAGS += $(if $(CONFIG_SPL_BUILD),,-fpic) -fno-common -march=core2 -m64 +PLATFORM_CPPFLAGS += -mno-mmx -mno-sse
According to https://wiki.osdev.org/SSE SSE has to be initialized. Otherwise SSE instructions lead to an undefined instruction exception. Is it this initialization that we lack? If this is your motivation please, state it in the commit message.
Yes, it's intentional. U-Boot as a bootloader does not want to handle these advanced SIMD stuff.
I think this patch could be squashed with the prior one.
They are different thing, although they solved similar reset. The first patch is adding the -march=core2 which is the counterpart of -march=i386 for 32-bit U-Boot. This patch is to disable MMX/SSE completely which I think deserve a separate patch.
Regards, Bin

Currently only 32-bit U-Boot for QEMU x86 is documented. Mention the 64-bit support.
Signed-off-by: Bin Meng bmeng.cn@gmail.com ---
doc/README.x86 | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/doc/README.x86 b/doc/README.x86 index 8cc4672..ab48466 100644 --- a/doc/README.x86 +++ b/doc/README.x86 @@ -32,7 +32,7 @@ are supported: - Link (Chromebook Pixel) - Minnowboard MAX - Samus (Chromebook Pixel 2015) - - QEMU x86 + - QEMU x86 (32-bit & 64-bit)
As for loading an OS, U-Boot supports directly booting a 32-bit or 64-bit Linux kernel as part of a FIT image. It also supports a compressed zImage. @@ -376,7 +376,9 @@ QEMU x86 target instructions for bare mode:
To build u-boot.rom for QEMU x86 targets, just simply run
-$ make qemu-x86_defconfig +$ make qemu-x86_defconfig (for 32-bit) +or +$ make qemu-x86_64_defconfig (for 64-bit) $ make all
Note this default configuration will build a U-Boot for the QEMU x86 i440FX @@ -387,6 +389,8 @@ Device Tree Control ---> ... (qemu-x86_q35) Default Device Tree for DT control
+To run 64-bit U-Boot, qemu-system-x86_64 should be used instead. + Test with coreboot ------------------ For testing U-Boot as the coreboot payload, there are things that need be paid

On 10/11/2018 03:53 AM, Bin Meng wrote:
Currently only 32-bit U-Boot for QEMU x86 is documented. Mention the 64-bit support.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
doc/README.x86 | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/doc/README.x86 b/doc/README.x86 index 8cc4672..ab48466 100644 --- a/doc/README.x86 +++ b/doc/README.x86 @@ -32,7 +32,7 @@ are supported: - Link (Chromebook Pixel) - Minnowboard MAX - Samus (Chromebook Pixel 2015)
- QEMU x86
- QEMU x86 (32-bit & 64-bit)
As for loading an OS, U-Boot supports directly booting a 32-bit or 64-bit Linux kernel as part of a FIT image. It also supports a compressed zImage. @@ -376,7 +376,9 @@ QEMU x86 target instructions for bare mode:
To build u-boot.rom for QEMU x86 targets, just simply run
-$ make qemu-x86_defconfig +$ make qemu-x86_defconfig (for 32-bit) +or +$ make qemu-x86_64_defconfig (for 64-bit) $ make all
If your patch series creates a U-Boot usable with QEMU depends on the chosen CPU:
This one seems to work: qemu-system-x86_64 -bios u-boot.rom -nographic -cpu core2duo
This one fails (as expected): qemu-system-x86_64 -bios u-boot.rom --nographic -cpu pentium
I could not get the emulation running without -nographic. Do you know why?
The documentation above is insufficient. Please, provide a minimum QEMU command line which includes a CPU specification.
I would prefer if you could specify two lines per bitness - one with kvm and one without, e.g.
qemu-system-x86_64 -bios u-boot.rom -nographic -enable-kvm -cpu host qemu-system-x86_64 -bios u-boot.rom -nographic -cpu core2duo
qemu-system-i386 -bios u-boot.rom -nographic -enable-kvm -cpu host qemu-system-i386 -bios u-boot.rom -nographic -cpu core2duo
Best regards
Heinrich
Note this default configuration will build a U-Boot for the QEMU x86 i440FX @@ -387,6 +389,8 @@ Device Tree Control ---> ... (qemu-x86_q35) Default Device Tree for DT control
+To run 64-bit U-Boot, qemu-system-x86_64 should be used instead.
Test with coreboot
For testing U-Boot as the coreboot payload, there are things that need be paid

Hi Heinrich,
On Thu, Oct 11, 2018 at 11:15 PM Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 10/11/2018 03:53 AM, Bin Meng wrote:
Currently only 32-bit U-Boot for QEMU x86 is documented. Mention the 64-bit support.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
doc/README.x86 | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/doc/README.x86 b/doc/README.x86 index 8cc4672..ab48466 100644 --- a/doc/README.x86 +++ b/doc/README.x86 @@ -32,7 +32,7 @@ are supported: - Link (Chromebook Pixel) - Minnowboard MAX - Samus (Chromebook Pixel 2015)
- QEMU x86
- QEMU x86 (32-bit & 64-bit)
As for loading an OS, U-Boot supports directly booting a 32-bit or 64-bit Linux kernel as part of a FIT image. It also supports a compressed zImage. @@ -376,7 +376,9 @@ QEMU x86 target instructions for bare mode:
To build u-boot.rom for QEMU x86 targets, just simply run
-$ make qemu-x86_defconfig +$ make qemu-x86_defconfig (for 32-bit) +or +$ make qemu-x86_64_defconfig (for 64-bit) $ make all
If your patch series creates a U-Boot usable with QEMU depends on the chosen CPU:
This one seems to work: qemu-system-x86_64 -bios u-boot.rom -nographic -cpu core2duo
This one fails (as expected): qemu-system-x86_64 -bios u-boot.rom --nographic -cpu pentium
Pentium does not support 64-bit, so it is expected. In my testing I always omit the '-cpu' so this is not a problem. But I can document this.
I could not get the emulation running without -nographic. Do you know why?
This is due to currently the VGA support is missing in the 64-bit U-Boot.
The documentation above is insufficient. Please, provide a minimum QEMU command line which includes a CPU specification.
I would prefer if you could specify two lines per bitness - one with kvm and one without, e.g.
I doubt -enable-kvm works with U-Boot.
qemu-system-x86_64 -bios u-boot.rom -nographic -enable-kvm -cpu host qemu-system-x86_64 -bios u-boot.rom -nographic -cpu core2duo
qemu-system-i386 -bios u-boot.rom -nographic -enable-kvm -cpu host qemu-system-i386 -bios u-boot.rom -nographic -cpu core2duo
Will add more info in v2.
Regards, Bin

On 10/11/2018 05:27 PM, Bin Meng wrote:
Hi Heinrich,
On Thu, Oct 11, 2018 at 11:15 PM Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 10/11/2018 03:53 AM, Bin Meng wrote:
Currently only 32-bit U-Boot for QEMU x86 is documented. Mention the 64-bit support.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
doc/README.x86 | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/doc/README.x86 b/doc/README.x86 index 8cc4672..ab48466 100644 --- a/doc/README.x86 +++ b/doc/README.x86 @@ -32,7 +32,7 @@ are supported: - Link (Chromebook Pixel) - Minnowboard MAX - Samus (Chromebook Pixel 2015)
- QEMU x86
- QEMU x86 (32-bit & 64-bit)
As for loading an OS, U-Boot supports directly booting a 32-bit or 64-bit Linux kernel as part of a FIT image. It also supports a compressed zImage. @@ -376,7 +376,9 @@ QEMU x86 target instructions for bare mode:
To build u-boot.rom for QEMU x86 targets, just simply run
-$ make qemu-x86_defconfig +$ make qemu-x86_defconfig (for 32-bit) +or +$ make qemu-x86_64_defconfig (for 64-bit) $ make all
If your patch series creates a U-Boot usable with QEMU depends on the chosen CPU:
This one seems to work: qemu-system-x86_64 -bios u-boot.rom -nographic -cpu core2duo
This one fails (as expected): qemu-system-x86_64 -bios u-boot.rom --nographic -cpu pentium
Pentium does not support 64-bit, so it is expected. In my testing I always omit the '-cpu' so this is not a problem. But I can document this.
I could not get the emulation running without -nographic. Do you know why?
This is due to currently the VGA support is missing in the 64-bit U-Boot.
The documentation above is insufficient. Please, provide a minimum QEMU command line which includes a CPU specification.
I would prefer if you could specify two lines per bitness - one with kvm and one without, e.g.
I doubt -enable-kvm works with U-Boot.
Why? It is just an instruction how QEMU should emulate the CPU. KVM does not require anything on the target software side.
I have had no problem with KVM on the i386 target.
Regards
Heinrich
qemu-system-x86_64 -bios u-boot.rom -nographic -enable-kvm -cpu host qemu-system-x86_64 -bios u-boot.rom -nographic -cpu core2duo
qemu-system-i386 -bios u-boot.rom -nographic -enable-kvm -cpu host qemu-system-i386 -bios u-boot.rom -nographic -cpu core2duo
Will add more info in v2.
Regards, Bin

Hi Heinrich,
On Thu, Oct 11, 2018 at 11:32 PM Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 10/11/2018 05:27 PM, Bin Meng wrote:
Hi Heinrich,
On Thu, Oct 11, 2018 at 11:15 PM Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 10/11/2018 03:53 AM, Bin Meng wrote:
Currently only 32-bit U-Boot for QEMU x86 is documented. Mention the 64-bit support.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
doc/README.x86 | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/doc/README.x86 b/doc/README.x86 index 8cc4672..ab48466 100644 --- a/doc/README.x86 +++ b/doc/README.x86 @@ -32,7 +32,7 @@ are supported: - Link (Chromebook Pixel) - Minnowboard MAX - Samus (Chromebook Pixel 2015)
- QEMU x86
- QEMU x86 (32-bit & 64-bit)
As for loading an OS, U-Boot supports directly booting a 32-bit or 64-bit Linux kernel as part of a FIT image. It also supports a compressed zImage. @@ -376,7 +376,9 @@ QEMU x86 target instructions for bare mode:
To build u-boot.rom for QEMU x86 targets, just simply run
-$ make qemu-x86_defconfig +$ make qemu-x86_defconfig (for 32-bit) +or +$ make qemu-x86_64_defconfig (for 64-bit) $ make all
If your patch series creates a U-Boot usable with QEMU depends on the chosen CPU:
This one seems to work: qemu-system-x86_64 -bios u-boot.rom -nographic -cpu core2duo
This one fails (as expected): qemu-system-x86_64 -bios u-boot.rom --nographic -cpu pentium
Pentium does not support 64-bit, so it is expected. In my testing I always omit the '-cpu' so this is not a problem. But I can document this.
I could not get the emulation running without -nographic. Do you know why?
This is due to currently the VGA support is missing in the 64-bit U-Boot.
The documentation above is insufficient. Please, provide a minimum QEMU command line which includes a CPU specification.
I would prefer if you could specify two lines per bitness - one with kvm and one without, e.g.
I doubt -enable-kvm works with U-Boot.
Why? It is just an instruction how QEMU should emulate the CPU. KVM does not require anything on the target software side.
I have had no problem with KVM on the i386 target.
I suspect some drivers may have issues when working with KVM, eg: some memory barriers might be needed due to guest (U-Boot) and host (x86 machine) are speaking the same language. But I have never fully test this configuration.
Regards, Bin

Add qemu-x86_64 to the list of targets we use for test.py runs.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
--- testp.py testing is currently failing at 'bootefi selftest'.
.travis.yml | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/.travis.yml b/.travis.yml index 2b759c9..9d0531f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -408,6 +408,14 @@ matrix: BUILDMAN="^qemu-x86$" TOOLCHAIN="x86_64" BUILD_ROM="yes" + - name: "test/py qemu-x86_64" + env: + - TEST_PY_BD="qemu-x86_64" + TEST_PY_TEST_SPEC="not sleep" + QEMU_TARGET="x86_64-softmmu" + BUILDMAN="^qemu-x86_64$" + TOOLCHAIN="x86_64" + BUILD_ROM="yes" - name: "test/py zynq_zc702" env: - TEST_PY_BD="zynq_zc702"

Hi Heinrich,
On Thu, Oct 11, 2018 at 9:48 AM Bin Meng bmeng.cn@gmail.com wrote:
Add qemu-x86_64 to the list of targets we use for test.py runs.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
testp.py testing is currently failing at 'bootefi selftest'.
Can you try this series for the 'bootefi selftest' testing?
BTW: do you know how to call test.py on the local machine to do testing on QEMU? The doc does not provide enough information ..
.travis.yml | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/.travis.yml b/.travis.yml index 2b759c9..9d0531f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -408,6 +408,14 @@ matrix: BUILDMAN="^qemu-x86$" TOOLCHAIN="x86_64" BUILD_ROM="yes"
- name: "test/py qemu-x86_64"
env:
- TEST_PY_BD="qemu-x86_64"
TEST_PY_TEST_SPEC="not sleep"
QEMU_TARGET="x86_64-softmmu"
BUILDMAN="^qemu-x86_64$"
TOOLCHAIN="x86_64"
BUILD_ROM="yes"
- name: "test/py zynq_zc702" env:
- TEST_PY_BD="zynq_zc702"
--
Regards, Bin

On 10/11/2018 03:57 AM, Bin Meng wrote:
Hi Heinrich,
On Thu, Oct 11, 2018 at 9:48 AM Bin Meng bmeng.cn@gmail.com wrote:
Add qemu-x86_64 to the list of targets we use for test.py runs.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
testp.py testing is currently failing at 'bootefi selftest'.
Can you try this series for the 'bootefi selftest' testing?
I am clueless why the EFI subsystems is failing completely on qemu-x86_64_defconfig.
Any printf() or puts() statement I put into lib/efi_loader/efi_boottime.c leads to no output at all.
I connected gdb with
gdb u-boot -ex 'target remote localhost:1234' add-symbol-file u-boot <relocaddr>
But the debugger did not stop at breakpoints.
Regards
Heinrich
BTW: do you know how to call test.py on the local machine to do testing on QEMU? The doc does not provide enough information ..
.travis.yml | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/.travis.yml b/.travis.yml index 2b759c9..9d0531f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -408,6 +408,14 @@ matrix: BUILDMAN="^qemu-x86$" TOOLCHAIN="x86_64" BUILD_ROM="yes"
- name: "test/py qemu-x86_64"
env:
- TEST_PY_BD="qemu-x86_64"
TEST_PY_TEST_SPEC="not sleep"
QEMU_TARGET="x86_64-softmmu"
BUILDMAN="^qemu-x86_64$"
TOOLCHAIN="x86_64"
BUILD_ROM="yes"
- name: "test/py zynq_zc702" env:
- TEST_PY_BD="zynq_zc702"
--
Regards, Bin

Hi Heinrich,
On Fri, Oct 12, 2018 at 6:10 AM Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 10/11/2018 03:57 AM, Bin Meng wrote:
Hi Heinrich,
On Thu, Oct 11, 2018 at 9:48 AM Bin Meng bmeng.cn@gmail.com wrote:
Add qemu-x86_64 to the list of targets we use for test.py runs.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
testp.py testing is currently failing at 'bootefi selftest'.
Can you try this series for the 'bootefi selftest' testing?
I am clueless why the EFI subsystems is failing completely on qemu-x86_64_defconfig.
Any printf() or puts() statement I put into lib/efi_loader/efi_boottime.c leads to no output at all.
I connected gdb with
gdb u-boot -ex 'target remote localhost:1234' add-symbol-file u-boot <relocaddr>
But the debugger did not stop at breakpoints.
I encountered exactly the same issue that breakpoint is not hit when debugging this endless loop issue. And I finally figured it out:
The symbol table should not be loaded to <relocaddr>, instead it needs to be loaded to <relocaddr + .text - .text.start>.
The .text.start was introduced in commit 7e21fbca26d18327cf7cabaad08df276a06a07d8 "efi_loader: Rename sections to allow for implicit data", and its commit message mentioned: [agraf: Fix x86_64 breakage], although I was not sure what x86_64 breakage was fixed.
Please have a try.
Regards, Bin

On 10/12/2018 03:45 AM, Bin Meng wrote:
Hi Heinrich,
On Fri, Oct 12, 2018 at 6:10 AM Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 10/11/2018 03:57 AM, Bin Meng wrote:
Hi Heinrich,
On Thu, Oct 11, 2018 at 9:48 AM Bin Meng bmeng.cn@gmail.com wrote:
Add qemu-x86_64 to the list of targets we use for test.py runs.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
testp.py testing is currently failing at 'bootefi selftest'.
Can you try this series for the 'bootefi selftest' testing?
I am clueless why the EFI subsystems is failing completely on qemu-x86_64_defconfig.
Any printf() or puts() statement I put into lib/efi_loader/efi_boottime.c leads to no output at all.
I connected gdb with
gdb u-boot -ex 'target remote localhost:1234' add-symbol-file u-boot <relocaddr>
But the debugger did not stop at breakpoints.
I encountered exactly the same issue that breakpoint is not hit when debugging this endless loop issue. And I finally figured it out:
The symbol table should not be loaded to <relocaddr>, instead it needs to be loaded to <relocaddr + .text - .text.start>.
The .text.start was introduced in commit 7e21fbca26d18327cf7cabaad08df276a06a07d8 "efi_loader: Rename sections to allow for implicit data", and its commit message mentioned: [agraf: Fix x86_64 breakage], although I was not sure what x86_64 breakage was fixed.
Please have a try.
Regards, Bin
Hello Bin,
thanks for your hint. Now I was able to debug the problem.
The code is not correctly relocated.
Function do_elf_reloc_fixups64() only analyzes re_src->r_offset but not the relocation type.
I put a print statement into the relocation loop and found the relocation type of the first relocation to be reported as having an illegal value of 0x10ff70. All other relocation types were reported as 0x8 as expected.
diff --git a/arch/x86/lib/relocate.c b/arch/x86/lib/relocate.c index ed10755d9c..095374830f 100644 --- a/arch/x86/lib/relocate.c +++ b/arch/x86/lib/relocate.c @@ -55,6 +55,7 @@ static void do_elf_reloc_fixups64(unsigned int text_base, uintptr_t size, do { . /* Get the location from the relocation entry */ . offset_ptr_rom = (Elf64_Addr *)(uintptr_t)re_src->r_offset; + printf("Reloc type %llx\n", ELF64_R_TYPE(re_src->r_info)); . . /* Check that the location of the relocation is in .text */ . if (offset_ptr_rom >= (Elf64_Addr *)(uintptr_t)text_base &&
Reloc type 10ff70 Reloc type 8 Reloc type 8 Reloc type 8 ..
The relocation types in efi_runtime_relocate() are complete garbage:
efi_runtime_relocate: 8 efi_runtime_relocate: 30 efi_runtime_relocate: b0 efi_runtime_relocate: 8 efi_runtime_relocate: 50 efi_runtime_relocate: 20 efi_runtime_relocate: 8 efi_runtime_relocate: 60 efi_runtime_relocate: 20 efi_runtime_relocate: 8 efi_runtime_relocate: a0 efi_runtime_relocate: b5 efi_runtime_relocate: 8 efi_runtime_relocate: b0 efi_runtime_relocate: aa efi_runtime_relocate: 8 efi_runtime_relocate: c0 efi_runtime_relocate: c0 efi_runtime_relocate: 8 efi_runtime_relocate: d0 efi_runtime_relocate: 68 efi_runtime_relocate: 8 efi_runtime_relocate: e0 efi_runtime_relocate: b5 efi_runtime_relocate: 8 efi_runtime_relocate: f0 efi_runtime_relocate: cb efi_runtime_relocate: 8 efi_runtime_relocate: 0 efi_runtime_relocate: e1
I will send a patch for efi_runtime_relocate().
Bin, can you please, have a look at the first problem.
Best regards
Heinrich

On 10/12/2018 11:02 PM, Heinrich Schuchardt wrote:
On 10/12/2018 03:45 AM, Bin Meng wrote:
Hi Heinrich,
On Fri, Oct 12, 2018 at 6:10 AM Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 10/11/2018 03:57 AM, Bin Meng wrote:
Hi Heinrich,
On Thu, Oct 11, 2018 at 9:48 AM Bin Meng bmeng.cn@gmail.com wrote:
Add qemu-x86_64 to the list of targets we use for test.py runs.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
testp.py testing is currently failing at 'bootefi selftest'.
Can you try this series for the 'bootefi selftest' testing?
I am clueless why the EFI subsystems is failing completely on qemu-x86_64_defconfig.
Any printf() or puts() statement I put into lib/efi_loader/efi_boottime.c leads to no output at all.
I connected gdb with
gdb u-boot -ex 'target remote localhost:1234' add-symbol-file u-boot <relocaddr>
But the debugger did not stop at breakpoints.
I encountered exactly the same issue that breakpoint is not hit when debugging this endless loop issue. And I finally figured it out:
The symbol table should not be loaded to <relocaddr>, instead it needs to be loaded to <relocaddr + .text - .text.start>.
The .text.start was introduced in commit 7e21fbca26d18327cf7cabaad08df276a06a07d8 "efi_loader: Rename sections to allow for implicit data", and its commit message mentioned: [agraf: Fix x86_64 breakage], although I was not sure what x86_64 breakage was fixed.
Please have a try.
Regards, Bin
Hello Bin,
thanks for your hint. Now I was able to debug the problem.
The code is not correctly relocated.
Function do_elf_reloc_fixups64() only analyzes re_src->r_offset but not the relocation type.
I put a print statement into the relocation loop and found the relocation type of the first relocation to be reported as having an illegal value of 0x10ff70. All other relocation types were reported as 0x8 as expected.
diff --git a/arch/x86/lib/relocate.c b/arch/x86/lib/relocate.c index ed10755d9c..095374830f 100644 --- a/arch/x86/lib/relocate.c +++ b/arch/x86/lib/relocate.c @@ -55,6 +55,7 @@ static void do_elf_reloc_fixups64(unsigned int text_base, uintptr_t size, do { . /* Get the location from the relocation entry */ . offset_ptr_rom = (Elf64_Addr *)(uintptr_t)re_src->r_offset;
- printf("Reloc type %llx\n", ELF64_R_TYPE(re_src->r_info));
. . /* Check that the location of the relocation is in .text */ . if (offset_ptr_rom >= (Elf64_Addr *)(uintptr_t)text_base &&
Reloc type 10ff70 Reloc type 8 Reloc type 8 Reloc type 8 ..
The relocation types in efi_runtime_relocate() are complete garbage:
efi_runtime_relocate: 8 efi_runtime_relocate: 30 efi_runtime_relocate: b0 efi_runtime_relocate: 8 efi_runtime_relocate: 50 efi_runtime_relocate: 20 efi_runtime_relocate: 8 efi_runtime_relocate: 60 efi_runtime_relocate: 20 efi_runtime_relocate: 8 efi_runtime_relocate: a0 efi_runtime_relocate: b5 efi_runtime_relocate: 8 efi_runtime_relocate: b0 efi_runtime_relocate: aa efi_runtime_relocate: 8 efi_runtime_relocate: c0 efi_runtime_relocate: c0 efi_runtime_relocate: 8 efi_runtime_relocate: d0 efi_runtime_relocate: 68 efi_runtime_relocate: 8 efi_runtime_relocate: e0 efi_runtime_relocate: b5 efi_runtime_relocate: 8 efi_runtime_relocate: f0 efi_runtime_relocate: cb efi_runtime_relocate: 8 efi_runtime_relocate: 0 efi_runtime_relocate: e1
I will send a patch for efi_runtime_relocate().
Bin, can you please, have a look at the first problem.
Best regards
Heinrich
Using a memory watchpoint pinpoints the culprit overwriting the relocation table with an illegal relocation type:
Hardware access (read/write) watchpoint 1: *0x118b188
Old value = 8 New value = 1113968 arch_setup_gd (new_gd=0x10ff70) at arch/x86/cpu/x86_64/cpu.c:32 (gdb)
0x111173e <arch_setup_gd> mov %rdi,0x79a43(%rip) # 0x118b188
0x1111745 <arch_setup_gd+7> mov $0x20,%edi
0x111174a <arch_setup_gd+12> jmpq 0x11399fb <printch>
0x111174f <cpu_has_64bit> mov $0x1,%eax
The global_data_ptr and the relocation table occupy the same memory location:
.bss.global_data_ptr 0x000000000118b188 0x8 arch/x86/cpu/built-in.o 0x000000000118b188 global_data_ptr
.rela.got 0x000000000118b180 0x90 arch/x86/cpu/start64.o .rela.bss 0x000000000118b210 0x0 arch/x86/cpu/start64.o
Essentially we have to relocate before accessing any global symbols in the data section. I have sent a patch moving global_data_ptr to the .text section.
Best regards
Heinrich

On 10/11/2018 03:53 AM, Bin Meng wrote:
With newer kernel.org GCC (7.3.0 or 8.1.0), the u-boot.rom image built for qemu-x86_64 target does not boot. It keeps resetting soon after the 32-bit SPL jumps to 64-bit proper. Debugging shows that the reset happens inside env_callback_init().
000000000113dd85 <env_callback_init>: 113dd85: 41 54 push %r12 113dd87: 55 push %rbp 113dd88: 31 c0 xor %eax,%eax 113dd8a: 53 push %rbx 113dd8b: 0f 57 c0 xorps %xmm0,%xmm0
Executing "xorps %xmm0,%xmm0" causes CPU to immediately reset. However older GCC like 5.4.0 (the one shipped by Ubuntu 16.04) does not generate such instructions that utilizes SSE for this function - env_callback_init() and U-Boot boots without any issue. Explicitly specifying -march=core2 for newer GCC allows U-Boot proper to boot again. Examine assembly codes of env_callback_init and there is no SSE instruction in that function hence U-Boot continues to boot.
core2 seems to be the oldest arch in GCC that supports 64-bit. Like 32-bit U-Boot build we use -march=i386 which is the most conservative cpu type so that the image can run on any x86 processor, let's do the same for the 64-bit U-Boot build.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
Reviewed-by: Heinrich Schuchardt xypron.glpk@gmx.de
arch/x86/config.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/x86/config.mk b/arch/x86/config.mk index cc94071..576501e 100644 --- a/arch/x86/config.mk +++ b/arch/x86/config.mk @@ -23,7 +23,7 @@ endif ifeq ($(IS_32BIT),y) PLATFORM_CPPFLAGS += -march=i386 -m32 else -PLATFORM_CPPFLAGS += $(if $(CONFIG_SPL_BUILD),,-fpic) -fno-common -m64 +PLATFORM_CPPFLAGS += $(if $(CONFIG_SPL_BUILD),,-fpic) -fno-common -march=core2 -m64 endif
PLATFORM_RELFLAGS += -fdata-sections -ffunction-sections -fvisibility=hidden

On 10 October 2018 at 19:53, Bin Meng bmeng.cn@gmail.com wrote:
With newer kernel.org GCC (7.3.0 or 8.1.0), the u-boot.rom image built for qemu-x86_64 target does not boot. It keeps resetting soon after the 32-bit SPL jumps to 64-bit proper. Debugging shows that the reset happens inside env_callback_init().
000000000113dd85 <env_callback_init>: 113dd85: 41 54 push %r12 113dd87: 55 push %rbp 113dd88: 31 c0 xor %eax,%eax 113dd8a: 53 push %rbx 113dd8b: 0f 57 c0 xorps %xmm0,%xmm0
Executing "xorps %xmm0,%xmm0" causes CPU to immediately reset. However older GCC like 5.4.0 (the one shipped by Ubuntu 16.04) does not generate such instructions that utilizes SSE for this function - env_callback_init() and U-Boot boots without any issue. Explicitly specifying -march=core2 for newer GCC allows U-Boot proper to boot again. Examine assembly codes of env_callback_init and there is no SSE instruction in that function hence U-Boot continues to boot.
core2 seems to be the oldest arch in GCC that supports 64-bit. Like 32-bit U-Boot build we use -march=i386 which is the most conservative cpu type so that the image can run on any x86 processor, let's do the same for the 64-bit U-Boot build.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
arch/x86/config.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Reviewed-by: Simon Glass sjg@chromium.org
participants (3)
-
Bin Meng
-
Heinrich Schuchardt
-
Simon Glass