Re: [PATCH v4 2/5] LoongArch: Use la.pcrel instead of la.abs for exception handlers

From: Youling Tang
Date: Thu Feb 16 2023 - 06:19:07 EST



On 02/16/2023 04:03 PM, Youling Tang wrote:


On 02/16/2023 03:10 PM, Xi Ruoyao wrote:
On Thu, 2023-02-16 at 14:59 +0800, Jinyang He wrote:
+.macro la.abs reg, sym
+766:
+ nop
+ nop
+ nop
+ nop

In the "formal" version we can code

lu12i.w reg, 0
ori reg, reg, 0
lu32i.d reg, 0
lu52i.d reg, reg, 0

here. Then we only need to fixup the immediate slot so we can avoid
using parse_r.


+ .pushsection ".laabs", "aw", %progbits
+768:
+ .word 768b-766b
+ parse_r regno, \reg
+ .word regno
+ .dword \sym
+ .popsection
+.endm

I will try to modify a version for testing, using the following
definition, when the RELOCATABLE is turned on, the "la.abs macro" is
used, otherwise the "la.abs pseudo instruction" is still used as before.

#ifdef CONFIG_RELOCATABLE
.macro la.abs reg, sym
lu12i.w reg, 0
ori reg, reg, 0
lu32i.d reg, 0
lu52i.d reg, reg, 0
.endm
#endif

On the basis of the v4 patch set, remove patch2, and then add the following patches, and the test is successful on qemu.

If this method is more acceptable to everyone, I will send v5.

diff --git a/arch/loongarch/include/asm/asmmacro.h b/arch/loongarch/include/asm/asmmacro.h
index 328bb956f241..adb04ae6b208 100644
--- a/arch/loongarch/include/asm/asmmacro.h
+++ b/arch/loongarch/include/asm/asmmacro.h
@@ -667,4 +667,19 @@
nor \dst, \src, zero
.endm

+#ifdef CONFIG_RELOCATABLE
+.macro la.abs reg, sym
+766:
+ lu12i.w \reg, 0
+ ori \reg, \reg, 0
+ lu32i.d \reg, 0
+ lu52i.d \reg, \reg, 0
+ .pushsection ".laabs", "aw", %progbits
+768:
+ .dword 768b-766b
+ .dword \sym
+ .popsection
+.endm
+#endif
+
#endif /* _ASM_ASMMACRO_H */
diff --git a/arch/loongarch/kernel/relocate.c b/arch/loongarch/kernel/relocate.c
index 7d19cc0d2185..7ad327a554f9 100644
--- a/arch/loongarch/kernel/relocate.c
+++ b/arch/loongarch/kernel/relocate.c
@@ -12,6 +12,7 @@
#include <linux/start_kernel.h>
#include <asm/bootinfo.h>
#include <asm/early_ioremap.h>
+#include <asm/inst.h>
#include <asm/sections.h>

#define RELOCATED(x) ((void *)((long)x + reloc_offset))
@@ -45,6 +46,32 @@ static inline __init void relocate_relative(void)
}
}

+static inline void __init relocate_laabs(long offset)
+{
+ extern void *__laabs_begin;
+ extern void *__laabs_end;
+ struct laabs {
+ long offset;
+ long symvalue;
+ } *p;
+
+ for (p = (void *)&__laabs_begin; (void *)p < (void *)&__laabs_end; p++) {
+ long v = p->symvalue + reloc_offset;
+ union loongarch_instruction *insn = (void *)p - p->offset + offset;
+ u32 lu12iw, ori, lu32id, lu52id;
+
+ lu12iw = (v >> 12) & 0xfffff;
+ ori = v & 0xfff;
+ lu32id = (v >> 32) & 0xfffff;
+ lu52id = v >> 52;
+
+ insn[0].reg1i20_format.immediate = lu12iw;
+ insn[1].reg2i12_format.immediate = ori;
+ insn[2].reg1i20_format.immediate = lu32id;
+ insn[3].reg2i12_format.immediate = lu52id;
+ }
+}
+
#ifdef CONFIG_RANDOMIZE_BASE
static inline __init unsigned long rotate_xor(unsigned long hash,
const void *area, size_t size)
@@ -168,8 +195,10 @@ void *__init do_kaslr(void)
update_reloc_offset(&reloc_offset, offset);
}

- if (reloc_offset)
+ if (reloc_offset) {
relocate_relative();
+ relocate_laabs(offset);
+ }

return kernel_entry;
}
@@ -181,6 +210,8 @@ void __init relocate_kernel(void)

if (reloc_offset)
relocate_relative();
+
+ relocate_laabs(0);
}

/*
diff --git a/arch/loongarch/kernel/vmlinux.lds.S b/arch/loongarch/kernel/vmlinux.lds.S
index aec0b6567d24..0e58c68bf427 100644
--- a/arch/loongarch/kernel/vmlinux.lds.S
+++ b/arch/loongarch/kernel/vmlinux.lds.S
@@ -66,6 +66,13 @@ SECTIONS
__alt_instructions_end = .;
}

+ . = ALIGN(8);
+ .laabs : AT(ADDR(.laabs) - LOAD_OFFSET) {
+ __laabs_begin = .;
+ *(.laabs)
+ __laabs_end = .;
+ }
+
.got : ALIGN(16) { *(.got) }


Youling.