Commit 11cd8a64 authored by Xi Ruoyao's avatar Xi Ruoyao Committed by Huacai Chen
Browse files

LoongArch: Adjust symbol addressing for AS_HAS_EXPLICIT_RELOCS

If explicit relocation hints are used by the toolchain, -Wa,-mla-*
options will be useless for the C code. So only use them for the
!CONFIG_AS_HAS_EXPLICIT_RELOCS case.

Replace "la" with "la.pcrel" in head.S to keep the semantic consistent
with new and old toolchains for the low level startup code.

For per-CPU variables, the "address" of the symbol is actually an offset
from $r21. The value is near the loading address of main kernel image,
but far from the loading address of modules. So we use model("extreme")
attibute to tell the compiler that a PC-relative addressing with 32-bit
offset is not sufficient for local per-CPU variables.

The behavior with different assemblers and compilers are summarized in
the following table:

AS has            CC has
explicit relocs   explicit relocs * Behavior
==============================================================
No                No                Use la.* macros.
                                    No change from Linux 6.0.
--------------------------------------------------------------
No                Yes               Disable explicit relocs.
                                    No change from Linux 6.0.
--------------------------------------------------------------
Yes               No                Not supported.
--------------------------------------------------------------
Yes               Yes               Enable explicit relocs.
                                    No -Wa,-mla* options used.
==============================================================
*: We assume CC must have model attribute if it has explicit relocs.
   Both features are added in GCC 13 development cycle, so any GCC
   release >= 13 should be OK. Using early GCC 13 development snapshots
   may produce modules with unsupported relocations.

Link: https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=f09482a
Link: https://gcc.gnu.org/r13-1834
Link: https://gcc.gnu.org/r13-2199


Tested-by: default avatarWANG Xuerui <git@xen0n.name>
Signed-off-by: default avatarXi Ruoyao <xry111@xry111.site>
Signed-off-by: default avatarHuacai Chen <chenhuacai@loongson.cn>
parent 0d8dad70
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -43,10 +43,28 @@ endif

cflags-y			+= -G0 -pipe -msoft-float
LDFLAGS_vmlinux			+= -G0 -static -n -nostdlib

# When the assembler supports explicit relocation hint, we must use it.
# GCC may have -mexplicit-relocs off by default if it was built with an old
# assembler, so we force it via an option.
#
# When the assembler does not supports explicit relocation hint, we can't use
# it.  Disable it if the compiler supports it.
#
# If you've seen "unknown reloc hint" message building the kernel and you are
# now wondering why "-mexplicit-relocs" is not wrapped with cc-option: the
# combination of a "new" assembler and "old" compiler is not supported.  Either
# upgrade the compiler or downgrade the assembler.
ifdef CONFIG_AS_HAS_EXPLICIT_RELOCS
cflags-y			+= -mexplicit-relocs
KBUILD_CFLAGS_KERNEL		+= -mdirect-extern-access
else
cflags-y			+= $(call cc-option,-mno-explicit-relocs)
KBUILD_AFLAGS_KERNEL		+= -Wa,-mla-global-with-pcrel
KBUILD_CFLAGS_KERNEL		+= -Wa,-mla-global-with-pcrel
KBUILD_AFLAGS_MODULE		+= -Wa,-mla-global-with-abs
KBUILD_CFLAGS_MODULE		+= -fplt -Wa,-mla-global-with-abs,-mla-local-with-abs
endif

cflags-y += -ffreestanding
cflags-y += $(call cc-option, -mno-check-zero-division)
+9 −0
Original line number Diff line number Diff line
@@ -8,6 +8,15 @@
#include <asm/cmpxchg.h>
#include <asm/loongarch.h>

/*
 * The "address" (in fact, offset from $r21) of a per-CPU variable is close to
 * the loading address of main kernel image, but far from where the modules are
 * loaded. Tell the compiler this fact when using explicit relocs.
 */
#if defined(MODULE) && defined(CONFIG_AS_HAS_EXPLICIT_RELOCS)
#define PER_CPU_ATTRIBUTES    __attribute__((model("extreme")))
#endif

/* Use r21 for fast access */
register unsigned long __my_cpu_offset __asm__("$r21");

+6 −6
Original line number Diff line number Diff line
@@ -57,19 +57,19 @@ SYM_CODE_START(kernel_entry) # kernel entry point
	li.w		t0, 0x00		# FPE=0, SXE=0, ASXE=0, BTE=0
	csrwr		t0, LOONGARCH_CSR_EUEN

	la		t0, __bss_start		# clear .bss
	la.pcrel	t0, __bss_start		# clear .bss
	st.d		zero, t0, 0
	la		t1, __bss_stop - LONGSIZE
	la.pcrel	t1, __bss_stop - LONGSIZE
1:
	addi.d		t0, t0, LONGSIZE
	st.d		zero, t0, 0
	bne		t0, t1, 1b

	la		t0, fw_arg0
	la.pcrel	t0, fw_arg0
	st.d		a0, t0, 0		# firmware arguments
	la		t0, fw_arg1
	la.pcrel	t0, fw_arg1
	st.d		a1, t0, 0
	la		t0, fw_arg2
	la.pcrel	t0, fw_arg2
	st.d		a2, t0, 0

	/* KSave3 used for percpu base, initialized as 0 */
@@ -77,7 +77,7 @@ SYM_CODE_START(kernel_entry) # kernel entry point
	/* GPR21 used for percpu base (runtime), initialized as 0 */
	move		u0, zero

	la		tp, init_thread_union
	la.pcrel	tp, init_thread_union
	/* Set the SP after an empty pt_regs.  */
	PTR_LI		sp, (_THREAD_SIZE - 32 - PT_SIZE)
	PTR_ADD		sp, sp, tp
+4 −0
Original line number Diff line number Diff line
@@ -55,6 +55,10 @@ SECTIONS

	EXCEPTION_TABLE(16)

	.got : ALIGN(16) { *(.got) }
	.plt : ALIGN(16) { *(.plt) }
	.got.plt : ALIGN(16) { *(.got.plt) }

	. = ALIGN(PECOFF_SEGMENT_ALIGN);
	__init_begin = .;
	__inittext_begin = .;