[U-Boot] [PATCH 00/12] x86: Attempt to bring qemu-x86_64 target in travis-ci build/testing

At present the QEMU x86_64 target is broken here and there, for example with newer compiler it even does not boot. EFI loader does not work either.
This series is a combination of Heinrich's EFI loader fixes and my fixes to QEMU x86_64 target. The goal is to enable qemu-x86_64 target in travis-ci for build and testing. So far there are still 2 failures which are tftpboot related which seem to only occur on the travis-ci machines. It is still under investigation.
The series is available at u-boot-x86/qemu-working for testing.
Bin Meng (8): x86: Specify -march=core2 to build 64-bit U-Boot proper x86: Ensure no instruction sets of MMX/SSE are generated in 64-bit build x86: doc: Mention qemu-x86_64 support x86: doc: Remove stale sections of 64-bit support x86: Fix the mystery of printch() during 64-bit boot x86: tsc: Introduce config option for early timer frequency x86: quark: Specify X86_TSC_TIMER_EARLY_FREQ WIP: travis: Add qemu-x86_64 target for test.py testing
Heinrich Schuchardt (4): x86: qemu: enable CONFIG_SPL_DM_RTC x86: detect unsupported relocation types x86: put global data pointer into the .data section efi_loader: fix relocation on x86_64
.travis.yml | 8 ++++++++ arch/x86/config.mk | 3 ++- arch/x86/cpu/quark/Kconfig | 4 ++++ arch/x86/cpu/start64.S | 1 + arch/x86/cpu/x86_64/cpu.c | 28 ++++++++-------------------- arch/x86/lib/relocate.c | 18 ++++++++++++++++++ configs/qemu-x86_64_defconfig | 1 + doc/README.x86 | 36 +++++++++++++++++------------------- drivers/timer/Kconfig | 10 ++++++++++ drivers/timer/tsc_timer.c | 10 ++++++---- lib/efi_loader/efi_runtime.c | 16 ++++++++++++---- 11 files changed, 87 insertions(+), 48 deletions(-)

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 Reviewed-by: Simon Glass sjg@chromium.org ---
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.
The reset actually originates from undefined instruction exception caused by these SSE instructions. To keep U-Boot as a bootloader as simple as possible, we don't want to handle such advanced SIMD stuff. 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
--- Changes in this version: - revise the commit message for the reason of turning off MMX/SSE
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/13/2018 05:06 PM, 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.
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.
The reset actually originates from undefined instruction exception caused by these SSE instructions. To keep U-Boot as a bootloader as simple as possible, we don't want to handle such advanced SIMD stuff. 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
Reviewed-by: Heinrich Schuchardt xypron.glpk@gmx.de

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
--- Changes in this version: - add more information about 64-bit support
doc/README.x86 | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-)
diff --git a/doc/README.x86 b/doc/README.x86 index 8cc4672..64da4ac 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 @@ -479,6 +481,19 @@ Here the kernel (bzImage) is loaded to 01000000 and initrd is to 04000000. Then,
=> zboot 01000000 - 04000000 1b1ab50
+To run 64-bit U-Boot, qemu-system-x86_64 should be used instead, e.g.: +$ qemu-system-x86_64 -nographic -bios path/to/u-boot.rom + +Specific CPU can be specified via the '-cpu' parameter but please make +sure the specified CPU supports 64-bit like '-cpu core2duo'. Conversely +'-cpu pentium' won't work for obvious reasons that the processor only +supports 32-bit. + +Note 64-bit support is very preliminary at this point. Lots of features +are missing in the 64-bit world. One notable feature is VGA console +support which is currently missing, so that you must specify '-nographic' +to get 64-bit U-Boot up and running. + Updating U-Boot on Edison ------------------------- By default Intel Edison boards are shipped with preinstalled heavily

On 10/13/2018 05:06 PM, 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
Changes in this version:
- add more information about 64-bit support
doc/README.x86 | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-)
diff --git a/doc/README.x86 b/doc/README.x86 index 8cc4672..64da4ac 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 @@ -479,6 +481,19 @@ Here the kernel (bzImage) is loaded to 01000000 and initrd is to 04000000. Then,
=> zboot 01000000 - 04000000 1b1ab50
+To run 64-bit U-Boot, qemu-system-x86_64 should be used instead, e.g.: +$ qemu-system-x86_64 -nographic -bios path/to/u-boot.rom
+Specific CPU can be specified via the '-cpu' parameter but please make
A specfic CPU ...
+sure the specified CPU supports 64-bit like '-cpu core2duo'. Conversely +'-cpu pentium' won't work for obvious reasons that the processor only +supports 32-bit.
+Note 64-bit support is very preliminary at this point. Lots of features +are missing in the 64-bit world. One notable feature is VGA console
... is the VGA console ...
+support which is currently missing, so that you must specify '-nographic' +to get 64-bit U-Boot up and running.
Updating U-Boot on Edison
By default Intel Edison boards are shipped with preinstalled heavily
Reviewed-by: Heinrich Schuchardt xypron.glpk@gmx.de

There are some sections in current doc saying 64-bit is unsupported. This apparently is out of date. Remove it.
Signed-off-by: Bin Meng bmeng.cn@gmail.com ---
doc/README.x86 | 17 ----------------- 1 file changed, 17 deletions(-)
diff --git a/doc/README.x86 b/doc/README.x86 index 64da4ac..fe47221 100644 --- a/doc/README.x86 +++ b/doc/README.x86 @@ -1160,27 +1160,10 @@ to load a 'u-boot-payload.efi', see below test logs on QEMU.
See README.u-boot_on_efi and README.uefi for details of EFI support in U-Boot.
-64-bit Support --------------- -U-Boot supports booting a 64-bit kernel directly and is able to change to -64-bit mode to do so. However, U-Boot itself is currently always built -in 32-bit mode. Some access to the full memory range is provided with -arch_phys_memset(). - -The development work to make U-Boot itself run in 64-bit mode has not yet -been attempted. The best approach would likely be to build a 32-bit SPL -image for U-Boot, with CONFIG_SPL_BUILD. This could then handle the early CPU -init in 16-bit and 32-bit mode, running the FSP and any other binaries that -are needed. Then it could change to 64-bit model and jump to U-Boot proper. - -Given U-Boot's extensive 64-bit support this has not been a high priority, -but it would be a nice addition. - TODO List --------- - Audio - Chrome OS verified boot -- Building U-Boot to run in 64-bit mode
References ----------

On 10/13/2018 05:06 PM, Bin Meng wrote:
There are some sections in current doc saying 64-bit is unsupported. This apparently is out of date. Remove it.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
Reviewed-by: Heinrich Schuchardt xypron.glpk@gmx.de

From: Heinrich Schuchardt xypron.glpk@gmx.de
Since commit 380d4f787a3f ("rtc: Allow use of RTC in SPL and TPL") qemu-x86_64_defconfig does not boot anymore.
Fixes: 380d4f787a3f ("rtc: Allow use of RTC in SPL and TPL") Signed-off-by: Heinrich Schuchardt xypron.glpk@gmx.de Signed-off-by: Bin Meng bmeng.cn@gmail.com ---
configs/qemu-x86_64_defconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/configs/qemu-x86_64_defconfig b/configs/qemu-x86_64_defconfig index cf1ba8e..32922b8 100644 --- a/configs/qemu-x86_64_defconfig +++ b/configs/qemu-x86_64_defconfig @@ -63,6 +63,7 @@ CONFIG_SPL_REGMAP=y CONFIG_SYSCON=y CONFIG_SPL_SYSCON=y CONFIG_CPU=y +CONFIG_SPL_DM_RTC=y CONFIG_SPI=y CONFIG_SPL_TIMER=y CONFIG_USB_STORAGE=y

On 13 October 2018 at 09:06, Bin Meng bmeng.cn@gmail.com wrote:
From: Heinrich Schuchardt xypron.glpk@gmx.de
Since commit 380d4f787a3f ("rtc: Allow use of RTC in SPL and TPL") qemu-x86_64_defconfig does not boot anymore.
Fixes: 380d4f787a3f ("rtc: Allow use of RTC in SPL and TPL") Signed-off-by: Heinrich Schuchardt xypron.glpk@gmx.de Signed-off-by: Bin Meng bmeng.cn@gmail.com
configs/qemu-x86_64_defconfig | 1 + 1 file changed, 1 insertion(+)
Reviewed-by: Simon Glass sjg@chromium.org

From: Heinrich Schuchardt xypron.glpk@gmx.de
Currently we support only relocations of type ELF64_R_TYPE or ELF32_R_TYPE. We should be warned if other relocation types appear in the relocation sections.
This type of message has helped to identify code overwriting a relocation section before relocation and incorrect parsing of relocation tables.
Signed-off-by: Heinrich Schuchardt xypron.glpk@gmx.de Reviewed-by: Bin Meng bmeng.cn@gmail.com Signed-off-by: Bin Meng bmeng.cn@gmail.com ---
arch/x86/lib/relocate.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
diff --git a/arch/x86/lib/relocate.c b/arch/x86/lib/relocate.c index ed10755..4d09e4d 100644 --- a/arch/x86/lib/relocate.c +++ b/arch/x86/lib/relocate.c @@ -53,6 +53,15 @@ static void do_elf_reloc_fixups64(unsigned int text_base, uintptr_t size, Elf64_Addr *offset_ptr_ram;
do { + unsigned long long type = ELF64_R_TYPE(re_src->r_info); + + if (type != R_X86_64_RELATIVE) { + printf("%s: unsupported relocation type 0x%llx " + "at %p, ", __func__, type, re_src); + printf("offset = 0x%llx\n", re_src->r_offset); + continue; + } + /* Get the location from the relocation entry */ offset_ptr_rom = (Elf64_Addr *)(uintptr_t)re_src->r_offset;
@@ -91,6 +100,15 @@ static void do_elf_reloc_fixups32(unsigned int text_base, uintptr_t size, Elf32_Addr *offset_ptr_ram;
do { + unsigned int type = ELF32_R_TYPE(re_src->r_info); + + if (type != R_386_RELATIVE) { + printf("%s: unsupported relocation type 0x%x " + "at %p, ", __func__, type, re_src); + printf("offset = 0x%x\n", re_src->r_offset); + continue; + } + /* Get the location from the relocation entry */ offset_ptr_rom = (Elf32_Addr *)(uintptr_t)re_src->r_offset;

From: Heinrich Schuchardt xypron.glpk@gmx.de
On x86_64 the field global_data_ptr is assigned before relocation. As sections for uninitialized global data (.bss) overlap with the relocation sections (.rela) this destroys the relocation table and leads to spurious errors.
Initialization forces the global_data_ptr into a section for initialized global data (.data) which cannot overlap any .rela section.
Fixes: a160092a610f ("x86: Support global_data on x86_64") Signed-off-by: Heinrich Schuchardt xypron.glpk@gmx.de Reviewed-by: Bin Meng bmeng.cn@gmail.com Tested-by: Bin Meng bmeng.cn@gmail.com Signed-off-by: Bin Meng bmeng.cn@gmail.com ---
arch/x86/cpu/x86_64/cpu.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/arch/x86/cpu/x86_64/cpu.c b/arch/x86/cpu/x86_64/cpu.c index 18b3e94..ef5e812 100644 --- a/arch/x86/cpu/x86_64/cpu.c +++ b/arch/x86/cpu/x86_64/cpu.c @@ -7,8 +7,14 @@ #include <common.h> #include <debug_uart.h>
-/* Global declaration of gd */ -struct global_data *global_data_ptr; +/* + * Global declaration of gd. + * + * As we write to it before relocation we have to make sure it is not put into + * a .bss section which may overlap a .rela section. Initialization forces it + * into a .data section which cannot overlap any .rela section. + */ +struct global_data *global_data_ptr = (struct global_data *)~0;
void arch_setup_gd(gd_t *new_gd) {

On 13 October 2018 at 09:06, Bin Meng bmeng.cn@gmail.com wrote:
From: Heinrich Schuchardt xypron.glpk@gmx.de
On x86_64 the field global_data_ptr is assigned before relocation. As sections for uninitialized global data (.bss) overlap with the relocation sections (.rela) this destroys the relocation table and leads to spurious errors.
Initialization forces the global_data_ptr into a section for initialized global data (.data) which cannot overlap any .rela section.
Fixes: a160092a610f ("x86: Support global_data on x86_64") Signed-off-by: Heinrich Schuchardt xypron.glpk@gmx.de Reviewed-by: Bin Meng bmeng.cn@gmail.com Tested-by: Bin Meng bmeng.cn@gmail.com Signed-off-by: Bin Meng bmeng.cn@gmail.com
arch/x86/cpu/x86_64/cpu.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org
(see below)
diff --git a/arch/x86/cpu/x86_64/cpu.c b/arch/x86/cpu/x86_64/cpu.c index 18b3e94..ef5e812 100644 --- a/arch/x86/cpu/x86_64/cpu.c +++ b/arch/x86/cpu/x86_64/cpu.c @@ -7,8 +7,14 @@ #include <common.h> #include <debug_uart.h>
-/* Global declaration of gd */ -struct global_data *global_data_ptr; +/*
- Global declaration of gd.
- As we write to it before relocation we have to make sure it is not put into
- a .bss section which may overlap a .rela section. Initialization forces it
- into a .data section which cannot overlap any .rela section.
- */
+struct global_data *global_data_ptr = (struct global_data *)~0;
You could use __attribute__ ((section*.data")))) perhaps as this is a bit obscure
void arch_setup_gd(gd_t *new_gd) { -- 2.7.4

From: Heinrich Schuchardt xypron.glpk@gmx.de
Currently the relocation of the EFI runtime on x86_64 fails. This renders the EFI subsystem unusable. The ELF relocation records for x86_64 contain an addend field.
Always write the function name into error messages related to the EFI runtime relocation.
Break an excessively long line.
Signed-off-by: Heinrich Schuchardt xypron.glpk@gmx.de Reviewed-by: Bin Meng bmeng.cn@gmail.com Tested-by: Bin Meng bmeng.cn@gmail.com Signed-off-by: Bin Meng bmeng.cn@gmail.com ---
lib/efi_loader/efi_runtime.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c index c5fbd91..f059dc9 100644 --- a/lib/efi_loader/efi_runtime.c +++ b/lib/efi_loader/efi_runtime.c @@ -41,9 +41,13 @@ static efi_status_t __efi_runtime EFIAPI efi_invalid_parameter(void); #elif defined(__arm__) #define R_RELATIVE R_ARM_RELATIVE #define R_MASK 0xffULL -#elif defined(__x86_64__) || defined(__i386__) +#elif defined(__i386__) #define R_RELATIVE R_386_RELATIVE #define R_MASK 0xffULL +#elif defined(__x86_64__) +#define R_RELATIVE R_X86_64_RELATIVE +#define R_MASK 0xffffffffULL +#define IS_RELA 1 #elif defined(__riscv) #define R_RELATIVE R_RISCV_RELATIVE #define R_MASK 0xffULL @@ -358,7 +362,8 @@ void efi_runtime_relocate(ulong offset, struct efi_mem_desc *map)
p = (void*)((ulong)rel->offset - base) + gd->relocaddr;
- debug("%s: rel->info=%#lx *p=%#lx rel->offset=%p\n", __func__, rel->info, *p, rel->offset); + debug("%s: rel->info=%#lx *p=%#lx rel->offset=%p\n", __func__, + rel->info, *p, rel->offset);
switch (rel->info & R_MASK) { case R_RELATIVE: @@ -377,6 +382,9 @@ void efi_runtime_relocate(ulong offset, struct efi_mem_desc *map) } #endif default: + if (!efi_runtime_tobedetached(p)) + printf("%s: Unknown relocation type %llx\n", + __func__, rel->info & R_MASK); continue; }
@@ -385,8 +393,8 @@ void efi_runtime_relocate(ulong offset, struct efi_mem_desc *map) newaddr > (map->virtual_start + (map->num_pages << EFI_PAGE_SHIFT)))) { if (!efi_runtime_tobedetached(p)) - printf("U-Boot EFI: Relocation at %p is out of " - "range (%lx)\n", p, newaddr); + printf("%s: Relocation at %p is out of " + "range (%lx)\n", __func__, p, newaddr); continue; }

At present in arch_setup_gd() it calls printch(' ') at the end which has been a mystery for a long time as without such call the 64-bit U-Boot just does not boot at all.
In fact this is due to the bug that board_init_f() was called with boot_flags not being set. Hence whatever value being there in the rdi register becomes the boot_flags if without such magic call. With a printch(' ') call the rdi register is initialized as 0x20 and this value seems to be sane enough for the whole boot process.
Signed-off-by: Bin Meng bmeng.cn@gmail.com ---
arch/x86/cpu/start64.S | 1 + arch/x86/cpu/x86_64/cpu.c | 18 ------------------ 2 files changed, 1 insertion(+), 18 deletions(-)
diff --git a/arch/x86/cpu/start64.S b/arch/x86/cpu/start64.S index a473fd1..a78a331 100644 --- a/arch/x86/cpu/start64.S +++ b/arch/x86/cpu/start64.S @@ -20,6 +20,7 @@ _start:
call board_init_f_init_reserve
+ xor %rdi, %rdi call board_init_f call board_init_f_r
diff --git a/arch/x86/cpu/x86_64/cpu.c b/arch/x86/cpu/x86_64/cpu.c index ef5e812..6c063e8 100644 --- a/arch/x86/cpu/x86_64/cpu.c +++ b/arch/x86/cpu/x86_64/cpu.c @@ -19,24 +19,6 @@ struct global_data *global_data_ptr = (struct global_data *)~0; void arch_setup_gd(gd_t *new_gd) { global_data_ptr = new_gd; - - /* - * TODO(sjg@chromium.org): For some reason U-Boot does not boot - * without this line. It fails to start up U-Boot proper and instead - * restarts SPL. Need to figure out why: - * - * U-Boot SPL 2017.01 - * - * U-Boot SPL 2017.01 - * CPU: Intel(R) Core(TM) i5-3427U CPU @ 1.80GHz - * Trying to boot from SPIJumping to 64-bit U-Boot: Note many - * features are missing - * - * U-Boot SPL 2017.01 - */ -#ifdef CONFIG_DEBUG_UART - printch(' '); -#endif }
int cpu_has_64bit(void)

On 10/13/2018 05:06 PM, Bin Meng wrote:
At present in arch_setup_gd() it calls printch(' ') at the end which has been a mystery for a long time as without such call the 64-bit U-Boot just does not boot at all.
In fact this is due to the bug that board_init_f() was called with boot_flags not being set. Hence whatever value being there in the rdi register becomes the boot_flags if without such magic call. With a printch(' ') call the rdi register is initialized as 0x20 and this value seems to be sane enough for the whole boot process.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
So up to now we set gd->flags = GD_FLG_LOGINIT here.
Reviewed-by: Heinrich Schuchardt xypron.glpk@gmx.de

So far the TSC timer driver supports trying hardware calibration first and using device tree as last resort for its running frequency as the normal timer.
However when it is used as the early timer, it only supports hardware calibration and if it fails, the driver just panics. This introduces a new config option to specify the early timer frequency and it should be equal to the value described in the device tree.
Without this patch, the travis-ci testing on QEMU x86_64 target fails each time after it finishes the 'bootefi selftest' as the test.py see an error was emitted on the console like this:
TSC frequency is ZERO resetting ... ### ERROR ### Please RESET the board ###
It's strange that this error is consistently seen on the travis-ci machine, but only occasionally seen on my local machine (maybe 1 out of 10). Since QEMU x86_64 target enables BOOTSTAGE support which uses early timer, with this fix it should work without any failure.
Signed-off-by: Bin Meng bmeng.cn@gmail.com ---
drivers/timer/Kconfig | 10 ++++++++++ drivers/timer/tsc_timer.c | 10 ++++++---- 2 files changed, 16 insertions(+), 4 deletions(-)
diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig index 45a256a..f300f87 100644 --- a/drivers/timer/Kconfig +++ b/drivers/timer/Kconfig @@ -82,6 +82,16 @@ config X86_TSC_TIMER help Select this to enable Time-Stamp Counter (TSC) timer for x86.
+config X86_TSC_TIMER_EARLY_FREQ + int "x86 TSC timer frequency when it is used as the early timer" + depends on X86_TSC_TIMER + default 1000000000 + help + Sets the TSC timer frequency when TSC is used as the ealy timer + and the frequency can neither be calibrated via some hardware + ways, nor got from device tree at the time when device tree is + not available yet. + config OMAP_TIMER bool "Omap timer support" depends on TIMER diff --git a/drivers/timer/tsc_timer.c b/drivers/timer/tsc_timer.c index 6473de2..5dc6f9e 100644 --- a/drivers/timer/tsc_timer.c +++ b/drivers/timer/tsc_timer.c @@ -341,7 +341,7 @@ static int tsc_timer_get_count(struct udevice *dev, u64 *count) return 0; }
-static void tsc_timer_ensure_setup(bool stop) +static void tsc_timer_ensure_setup(bool early) { if (gd->arch.tsc_base) return; @@ -362,10 +362,12 @@ static void tsc_timer_ensure_setup(bool stop) if (fast_calibrate) goto done;
- if (stop) - panic("TSC frequency is ZERO"); - else + if (early) { + gd->arch.clock_rate = CONFIG_X86_TSC_TIMER_EARLY_FREQ; + return; + } else { return; + }
done: gd->arch.clock_rate = fast_calibrate * 1000000;

On 10/13/2018 05:06 PM, Bin Meng wrote:
So far the TSC timer driver supports trying hardware calibration first and using device tree as last resort for its running frequency as the normal timer.
However when it is used as the early timer, it only supports hardware calibration and if it fails, the driver just panics. This introduces a new config option to specify the early timer frequency and it should be equal to the value described in the device tree.
Without this patch, the travis-ci testing on QEMU x86_64 target fails each time after it finishes the 'bootefi selftest' as the test.py see an error was emitted on the console like this:
TSC frequency is ZERO resetting ... ### ERROR ### Please RESET the board ###
It's strange that this error is consistently seen on the travis-ci machine, but only occasionally seen on my local machine (maybe 1 out of 10). Since QEMU x86_64 target enables BOOTSTAGE support which uses early timer, with this fix it should work without any failure.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
drivers/timer/Kconfig | 10 ++++++++++ drivers/timer/tsc_timer.c | 10 ++++++---- 2 files changed, 16 insertions(+), 4 deletions(-)
diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig index 45a256a..f300f87 100644 --- a/drivers/timer/Kconfig +++ b/drivers/timer/Kconfig @@ -82,6 +82,16 @@ config X86_TSC_TIMER help Select this to enable Time-Stamp Counter (TSC) timer for x86.
+config X86_TSC_TIMER_EARLY_FREQ
- int "x86 TSC timer frequency when it is used as the early timer"
- depends on X86_TSC_TIMER
- default 1000000000
default 1000
see suggested code simplification below
- help
Sets the TSC timer frequency when TSC is used as the ealy timer
Sets the estimated CPU frequency in MHz ...
%s/ealy/early/
and the frequency can neither be calibrated via some hardware
ways, nor got from device tree at the time when device tree is
not available yet.
config OMAP_TIMER bool "Omap timer support" depends on TIMER diff --git a/drivers/timer/tsc_timer.c b/drivers/timer/tsc_timer.c index 6473de2..5dc6f9e 100644 --- a/drivers/timer/tsc_timer.c +++ b/drivers/timer/tsc_timer.c @@ -341,7 +341,7 @@ static int tsc_timer_get_count(struct udevice *dev, u64 *count) return 0; }
-static void tsc_timer_ensure_setup(bool stop) +static void tsc_timer_ensure_setup(bool early) { if (gd->arch.tsc_base) return; @@ -362,10 +362,12 @@ static void tsc_timer_ensure_setup(bool stop) if (fast_calibrate) goto done;
if (stop)
panic("TSC frequency is ZERO");
else
if (early) {
gd->arch.clock_rate = CONFIG_X86_TSC_TIMER_EARLY_FREQ;
return;
} else { return;
}
This can be simplified to one line, letting us use values in MHz instead of Hz in Kconfig:
fast_calibrate = CONFIG_X86_TSC_TIMER_EARLY_FREQ;
Why shouldn't we use the default value if early = false and configuration fails?
done: gd->arch.clock_rate = fast_calibrate * 1000000;
Regards
Heinrich

Hi Heinrich,
On Sun, Oct 14, 2018 at 12:44 AM Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 10/13/2018 05:06 PM, Bin Meng wrote:
So far the TSC timer driver supports trying hardware calibration first and using device tree as last resort for its running frequency as the normal timer.
However when it is used as the early timer, it only supports hardware calibration and if it fails, the driver just panics. This introduces a new config option to specify the early timer frequency and it should be equal to the value described in the device tree.
Without this patch, the travis-ci testing on QEMU x86_64 target fails each time after it finishes the 'bootefi selftest' as the test.py see an error was emitted on the console like this:
TSC frequency is ZERO resetting ... ### ERROR ### Please RESET the board ###
It's strange that this error is consistently seen on the travis-ci machine, but only occasionally seen on my local machine (maybe 1 out of 10). Since QEMU x86_64 target enables BOOTSTAGE support which uses early timer, with this fix it should work without any failure.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
drivers/timer/Kconfig | 10 ++++++++++ drivers/timer/tsc_timer.c | 10 ++++++---- 2 files changed, 16 insertions(+), 4 deletions(-)
diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig index 45a256a..f300f87 100644 --- a/drivers/timer/Kconfig +++ b/drivers/timer/Kconfig @@ -82,6 +82,16 @@ config X86_TSC_TIMER help Select this to enable Time-Stamp Counter (TSC) timer for x86.
+config X86_TSC_TIMER_EARLY_FREQ
int "x86 TSC timer frequency when it is used as the early timer"
depends on X86_TSC_TIMER
default 1000000000
default 1000
see suggested code simplification below
help
Sets the TSC timer frequency when TSC is used as the ealy timer
Sets the estimated CPU frequency in MHz ...
%s/ealy/early/
Will fix in v2.
and the frequency can neither be calibrated via some hardware
ways, nor got from device tree at the time when device tree is
not available yet.
config OMAP_TIMER bool "Omap timer support" depends on TIMER diff --git a/drivers/timer/tsc_timer.c b/drivers/timer/tsc_timer.c index 6473de2..5dc6f9e 100644 --- a/drivers/timer/tsc_timer.c +++ b/drivers/timer/tsc_timer.c @@ -341,7 +341,7 @@ static int tsc_timer_get_count(struct udevice *dev, u64 *count) return 0; }
-static void tsc_timer_ensure_setup(bool stop) +static void tsc_timer_ensure_setup(bool early) { if (gd->arch.tsc_base) return; @@ -362,10 +362,12 @@ static void tsc_timer_ensure_setup(bool stop) if (fast_calibrate) goto done;
if (stop)
panic("TSC frequency is ZERO");
else
if (early) {
gd->arch.clock_rate = CONFIG_X86_TSC_TIMER_EARLY_FREQ;
return;
} else { return;
}
This can be simplified to one line, letting us use values in MHz instead of Hz in Kconfig:
fast_calibrate = CONFIG_X86_TSC_TIMER_EARLY_FREQ;
Ah, yes! This is simpler.
Why shouldn't we use the default value if early = false and configuration fails?
if (early = false) that means it is not used as early timer, instead the normal timer, see tsc_timer_probe(). The normal timer will read the frequency from device tree instead.
Regards, Bin

Specify X86_TSC_TIMER_EARLY_FREQ for Quark SoC so that TSC as the early timer can be supported.
Signed-off-by: Bin Meng bmeng.cn@gmail.com ---
arch/x86/cpu/quark/Kconfig | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/arch/x86/cpu/quark/Kconfig b/arch/x86/cpu/quark/Kconfig index 76f1592..2d667ca 100644 --- a/arch/x86/cpu/quark/Kconfig +++ b/arch/x86/cpu/quark/Kconfig @@ -130,4 +130,8 @@ config SYS_CAR_SIZE Space in bytes in eSRAM used as Cache-As-ARM (CAR). Note this size must not exceed eSRAM's total size.
+config X86_TSC_TIMER_EARLY_FREQ + int + default 400000000 + endif

On 10/13/2018 05:06 PM, Bin Meng wrote:
Specify X86_TSC_TIMER_EARLY_FREQ for Quark SoC so that TSC as the early timer can be supported.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
The Intel Quark CPU runs at 400 MHz. If you follow my suggestion for patch 10 to set the parameter in MHz instead of Hz, please adjust the value to 400 here.
Reviewed-by: Heinrich Schuchardt xypron.glpk@gmx.de
arch/x86/cpu/quark/Kconfig | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/arch/x86/cpu/quark/Kconfig b/arch/x86/cpu/quark/Kconfig index 76f1592..2d667ca 100644 --- a/arch/x86/cpu/quark/Kconfig +++ b/arch/x86/cpu/quark/Kconfig @@ -130,4 +130,8 @@ config SYS_CAR_SIZE Space in bytes in eSRAM used as Cache-As-ARM (CAR). Note this size must not exceed eSRAM's total size.
+config X86_TSC_TIMER_EARLY_FREQ
- int
- default 400000000
endif

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 'tftpboot grub_x86.efi/u-boot', still investigating why. tftpboot works well on my local machine.
.travis.yml | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/.travis.yml b/.travis.yml index f78749a..a1045dd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -409,6 +409,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"

On Sat, Oct 13, 2018 at 11:02 PM 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 'tftpboot grub_x86.efi/u-boot', still investigating why. tftpboot works well on my local machine.
Looks the issue is with uboot-test-hooks. Retesting ..
.travis.yml | 8 ++++++++ 1 file changed, 8 insertions(+)
Regards, Bin

On Sat, Oct 13, 2018 at 11:52 PM Bin Meng bmeng.cn@gmail.com wrote:
On Sat, Oct 13, 2018 at 11:02 PM 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 'tftpboot grub_x86.efi/u-boot', still investigating why. tftpboot works well on my local machine.
Looks the issue is with uboot-test-hooks. Retesting ..
Finally pass. See https://travis-ci.org/lbmeng/u-boot/builds/441042913
.travis.yml | 8 ++++++++ 1 file changed, 8 insertions(+)
Regards, Bin
participants (3)
-
Bin Meng
-
Heinrich Schuchardt
-
Simon Glass