"Das U-Boot" Source Tree

riscv: Access gd with inline assembly when building with LTO or Clang

Similar to AArch64's case, Clang may wrongly fold accesses to gd pointer
which is defined with register qualifier into constants, breaking
various components.

This patch defines gd as a macro when building with Clang or LTO, which
expands to get_gd() that accesses gp pointer in assembly, making RISC-V
ports function properly and preparing for introduction of LTO in the
future. Board initialization code is also adapted for non-assignable gd.

Reported-by: Nathaniel Hourt <I@nathaniel.land>
Signed-off-by: Yao Zi <ziyao@disroot.org>
Reviewed-by: Leo Yu-Chi Liang <ycliang@andestech.com>

authored by

Yao Zi and committed by
Leo Yu-Chi Liang
307666be 60163080

+33 -3
+6
arch/riscv/cpu/cpu.c
··· 18 18 #include <asm/hwcap.h> 19 19 #include <asm/cpufeature.h> 20 20 #include <asm/cache.h> 21 + #include <asm/global_data.h> 21 22 #include <dm/uclass-internal.h> 22 23 #include <linux/bitops.h> 23 24 #include <linux/log2.h> ··· 746 747 747 748 return 0; 748 749 } 750 + 751 + void arch_setup_gd(gd_t *new_gd) 752 + { 753 + set_gd(new_gd); 754 + }
+19
arch/riscv/include/asm/global_data.h
··· 14 14 #include <asm/smp.h> 15 15 #include <asm/u-boot.h> 16 16 #include <compiler.h> 17 + #include <config.h> 17 18 18 19 /* Architecture-specific global data */ 19 20 struct arch_global_data { ··· 47 48 48 49 #include <asm-generic/global_data.h> 49 50 51 + #if defined(__clang__) || CONFIG_IS_ENABLED(LTO) 52 + 53 + #define DECLARE_GLOBAL_DATA_PTR 54 + #define gd get_gd() 55 + 56 + static inline gd_t *get_gd(void) 57 + { 58 + gd_t *gd_ptr; 59 + 60 + __asm__ volatile ("mv %0, gp\n" : "=r" (gd_ptr)); 61 + 62 + return gd_ptr; 63 + } 64 + 65 + #else 66 + 50 67 #define DECLARE_GLOBAL_DATA_PTR register gd_t *gd asm ("gp") 68 + 69 + #endif 51 70 52 71 static inline void set_gd(volatile gd_t *gd_ptr) 53 72 {
+3 -1
common/board_r.c
··· 815 815 if (CONFIG_IS_ENABLED(X86_64) && !IS_ENABLED(CONFIG_EFI_APP)) 816 816 arch_setup_gd(new_gd); 817 817 818 - #if !defined(CONFIG_X86) && !defined(CONFIG_ARM) && !defined(CONFIG_ARM64) 818 + #if defined(CONFIG_RISCV) 819 + set_gd(new_gd); 820 + #elif !defined(CONFIG_X86) && !defined(CONFIG_ARM) && !defined(CONFIG_ARM64) 819 821 gd = new_gd; 820 822 #endif 821 823 gd->flags &= ~GD_FLG_LOG_READY;
+5 -2
common/init/board_init.c
··· 13 13 14 14 DECLARE_GLOBAL_DATA_PTR; 15 15 16 - /* Unfortunately x86 or ARM can't compile this code as gd cannot be assigned */ 17 - #if !defined(CONFIG_X86) && !defined(CONFIG_ARM) 16 + /* 17 + * Unfortunately x86, ARM and RISC-V can't compile this code as gd is defined 18 + * as macro and cannot be assigned. 19 + */ 20 + #if !defined(CONFIG_X86) && !defined(CONFIG_ARM) && !defined(CONFIG_RISCV) 18 21 __weak void arch_setup_gd(struct global_data *gd_ptr) 19 22 { 20 23 gd = gd_ptr;