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>
#include <asm/hwcap.h>
#include <asm/cpufeature.h>
#include <asm/cache.h>
+#include <asm/global_data.h>
#include <dm/uclass-internal.h>
#include <linux/bitops.h>
#include <linux/log2.h>
return 0;
}
+
+void arch_setup_gd(gd_t *new_gd)
+{
+ set_gd(new_gd);
+}
#include <asm/smp.h>
#include <asm/u-boot.h>
#include <compiler.h>
+#include <config.h>
/* Architecture-specific global data */
struct arch_global_data {
#include <asm-generic/global_data.h>
+#if defined(__clang__) || CONFIG_IS_ENABLED(LTO)
+
+#define DECLARE_GLOBAL_DATA_PTR
+#define gd get_gd()
+
+static inline gd_t *get_gd(void)
+{
+ gd_t *gd_ptr;
+
+ __asm__ volatile ("mv %0, gp\n" : "=r" (gd_ptr));
+
+ return gd_ptr;
+}
+
+#else
+
#define DECLARE_GLOBAL_DATA_PTR register gd_t *gd asm ("gp")
+#endif
+
static inline void set_gd(volatile gd_t *gd_ptr)
{
#ifdef CONFIG_64BIT
if (CONFIG_IS_ENABLED(X86_64) && !IS_ENABLED(CONFIG_EFI_APP))
arch_setup_gd(new_gd);
-#if !defined(CONFIG_X86) && !defined(CONFIG_ARM) && !defined(CONFIG_ARM64)
+#if defined(CONFIG_RISCV)
+ set_gd(new_gd);
+#elif !defined(CONFIG_X86) && !defined(CONFIG_ARM) && !defined(CONFIG_ARM64)
gd = new_gd;
#endif
gd->flags &= ~GD_FLG_LOG_READY;
DECLARE_GLOBAL_DATA_PTR;
-/* Unfortunately x86 or ARM can't compile this code as gd cannot be assigned */
-#if !defined(CONFIG_X86) && !defined(CONFIG_ARM)
+/*
+ * Unfortunately x86, ARM and RISC-V can't compile this code as gd is defined
+ * as macro and cannot be assigned.
+ */
+#if !defined(CONFIG_X86) && !defined(CONFIG_ARM) && !defined(CONFIG_RISCV)
__weak void arch_setup_gd(struct global_data *gd_ptr)
{
gd = gd_ptr;