linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH mips-next 0/2] MIPS: optimize relocations processing
@ 2021-01-16 15:01 Alexander Lobakin
  2021-01-16 15:02 ` [PATCH mips-next 1/2] MIPS: module: optimize module " Alexander Lobakin
  2021-01-18 14:57 ` [PATCH mips-next 0/2] MIPS: optimize " Thomas Bogendoerfer
  0 siblings, 2 replies; 5+ messages in thread
From: Alexander Lobakin @ 2021-01-16 15:01 UTC (permalink / raw)
  To: Thomas Bogendoerfer
  Cc: Nathan Chancellor, Nick Desaulniers, Kees Cook, Andrew Morton,
	Mike Rapoport, Alexander Lobakin, Jinyang He, linux-mips,
	linux-kernel

This series converts the logics of two main relocation functions,
one for relocatable kernel and one for modules, from the arrays of
handlers (callbacks) to plain switch-case functions, which allows
the compiler to greatly optimize the code, so the relocations will
be applied faster with lesser code size.

Tested on MIPS32 R2 with GCC 10.2 and LLVM 11.0 with -O2.

Alexander Lobakin (2):
  MIPS: module: optimize module relocations processing
  MIPS: relocatable: optimize the relocation process

 arch/mips/kernel/module.c   | 109 +++++++++++++++++-------------------
 arch/mips/kernel/relocate.c |  54 ++++++++++--------
 2 files changed, 82 insertions(+), 81 deletions(-)

-- 
2.30.0



^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH mips-next 1/2] MIPS: module: optimize module relocations processing
  2021-01-16 15:01 [PATCH mips-next 0/2] MIPS: optimize relocations processing Alexander Lobakin
@ 2021-01-16 15:02 ` Alexander Lobakin
  2021-01-16 15:02   ` [PATCH mips-next 2/2] MIPS: relocatable: optimize the relocation process Alexander Lobakin
  2021-01-18  1:49   ` [PATCH mips-next 1/2] MIPS: module: optimize module relocations processing Jiaxun Yang
  2021-01-18 14:57 ` [PATCH mips-next 0/2] MIPS: optimize " Thomas Bogendoerfer
  1 sibling, 2 replies; 5+ messages in thread
From: Alexander Lobakin @ 2021-01-16 15:02 UTC (permalink / raw)
  To: Thomas Bogendoerfer
  Cc: Nathan Chancellor, Nick Desaulniers, Kees Cook, Andrew Morton,
	Mike Rapoport, Alexander Lobakin, Jinyang He, linux-mips,
	linux-kernel

For now, module relocation functions are implemented as an array
of handlers of type reloc_handler_t.

Convert that array into a single switch-case function to:
 - remove unused arguments;
 - change the return type of simple handlers to void;
 - remove the array and don't use any data at all;
 - avoid using indirect calls;
 - allow the compiler to inline and greatly optimize
   the relocation function[s].

The result on MIPS32 R2 with GCC 10.2 -O2 is:

scripts/bloat-o-meter -c arch/mips/kernel/__module.o arch/mips/kernel/module.o
add/remove: 1/11 grow/shrink: 1/0 up/down: 876/-1436 (-560)
Function                                     old     new   delta
apply_relocate                               456    1148    +692
apply_r_mips_pc                                -     184    +184
apply_r_mips_none                              8       -      -8
apply_r_mips_32                               16       -     -16
apply_r_mips_64                               76       -     -76
apply_r_mips_highest                          88       -     -88
apply_r_mips_higher                          108       -    -108
apply_r_mips_26                              132       -    -132
apply_r_mips_pc26                            160       -    -160
apply_r_mips_pc21                            160       -    -160
apply_r_mips_pc16                            160       -    -160
apply_r_mips_hi16                            172       -    -172
apply_r_mips_lo16                            356       -    -356
Total: Before=2608, After=2048, chg -21.47%
add/remove: 0/0 grow/shrink: 0/0 up/down: 0/0 (0)
Data                                         old     new   delta
Total: Before=12, After=12, chg +0.00%
add/remove: 0/1 grow/shrink: 0/0 up/down: 0/-248 (-248)
RO Data                                      old     new   delta
reloc_handlers                               248       -    -248
Total: Before=248, After=0, chg -100.00%

All functions were collapsed into a single one that is called
directly by $(srctree)/kernel/module.c.

Signed-off-by: Alexander Lobakin <alobakin@pm.me>
---
 arch/mips/kernel/module.c | 109 ++++++++++++++++++--------------------
 1 file changed, 52 insertions(+), 57 deletions(-)

diff --git a/arch/mips/kernel/module.c b/arch/mips/kernel/module.c
index 3c0c3d1260c1..14f46d17500a 100644
--- a/arch/mips/kernel/module.c
+++ b/arch/mips/kernel/module.c
@@ -40,22 +40,13 @@ void *module_alloc(unsigned long size)
 }
 #endif
 
-static int apply_r_mips_none(struct module *me, u32 *location,
-			     u32 base, Elf_Addr v, bool rela)
-{
-	return 0;
-}
-
-static int apply_r_mips_32(struct module *me, u32 *location,
-			   u32 base, Elf_Addr v, bool rela)
+static void apply_r_mips_32(u32 *location, u32 base, Elf_Addr v)
 {
 	*location = base + v;
-
-	return 0;
 }
 
-static int apply_r_mips_26(struct module *me, u32 *location,
-			   u32 base, Elf_Addr v, bool rela)
+static int apply_r_mips_26(struct module *me, u32 *location, u32 base,
+			   Elf_Addr v)
 {
 	if (v % 4) {
 		pr_err("module %s: dangerous R_MIPS_26 relocation\n",
@@ -75,8 +66,8 @@ static int apply_r_mips_26(struct module *me, u32 *location,
 	return 0;
 }
 
-static int apply_r_mips_hi16(struct module *me, u32 *location,
-			     u32 base, Elf_Addr v, bool rela)
+static int apply_r_mips_hi16(struct module *me, u32 *location, Elf_Addr v,
+			     bool rela)
 {
 	struct mips_hi16 *n;
 
@@ -217,26 +208,25 @@ static int apply_r_mips_pc(struct module *me, u32 *location, u32 base,
 	return 0;
 }
 
-static int apply_r_mips_pc16(struct module *me, u32 *location,
-			     u32 base, Elf_Addr v, bool rela)
+static int apply_r_mips_pc16(struct module *me, u32 *location, u32 base,
+			     Elf_Addr v)
 {
 	return apply_r_mips_pc(me, location, base, v, 16);
 }
 
-static int apply_r_mips_pc21(struct module *me, u32 *location,
-			     u32 base, Elf_Addr v, bool rela)
+static int apply_r_mips_pc21(struct module *me, u32 *location, u32 base,
+			     Elf_Addr v)
 {
 	return apply_r_mips_pc(me, location, base, v, 21);
 }
 
-static int apply_r_mips_pc26(struct module *me, u32 *location,
-			     u32 base, Elf_Addr v, bool rela)
+static int apply_r_mips_pc26(struct module *me, u32 *location, u32 base,
+			     Elf_Addr v)
 {
 	return apply_r_mips_pc(me, location, base, v, 26);
 }
 
-static int apply_r_mips_64(struct module *me, u32 *location,
-			   u32 base, Elf_Addr v, bool rela)
+static int apply_r_mips_64(u32 *location, Elf_Addr v, bool rela)
 {
 	if (WARN_ON(!rela))
 		return -EINVAL;
@@ -246,8 +236,7 @@ static int apply_r_mips_64(struct module *me, u32 *location,
 	return 0;
 }
 
-static int apply_r_mips_higher(struct module *me, u32 *location,
-			       u32 base, Elf_Addr v, bool rela)
+static int apply_r_mips_higher(u32 *location, Elf_Addr v, bool rela)
 {
 	if (WARN_ON(!rela))
 		return -EINVAL;
@@ -258,8 +247,7 @@ static int apply_r_mips_higher(struct module *me, u32 *location,
 	return 0;
 }
 
-static int apply_r_mips_highest(struct module *me, u32 *location,
-				u32 base, Elf_Addr v, bool rela)
+static int apply_r_mips_highest(u32 *location, Elf_Addr v, bool rela)
 {
 	if (WARN_ON(!rela))
 		return -EINVAL;
@@ -272,12 +260,14 @@ static int apply_r_mips_highest(struct module *me, u32 *location,
 
 /**
  * reloc_handler() - Apply a particular relocation to a module
+ * @type: type of the relocation to apply
  * @me: the module to apply the reloc to
  * @location: the address at which the reloc is to be applied
  * @base: the existing value at location for REL-style; 0 for RELA-style
  * @v: the value of the reloc, with addend for RELA-style
+ * @rela: indication of is this a RELA (true) or REL (false) relocation
  *
- * Each implemented reloc_handler function applies a particular type of
+ * Each implemented relocation function applies a particular type of
  * relocation to the module @me. Relocs that may be found in either REL or RELA
  * variants can be handled by making use of the @base & @v parameters which are
  * set to values which abstract the difference away from the particular reloc
@@ -285,23 +275,40 @@ static int apply_r_mips_highest(struct module *me, u32 *location,
  *
  * Return: 0 upon success, else -ERRNO
  */
-typedef int (*reloc_handler)(struct module *me, u32 *location,
-			     u32 base, Elf_Addr v, bool rela);
-
-/* The handlers for known reloc types */
-static reloc_handler reloc_handlers[] = {
-	[R_MIPS_NONE]		= apply_r_mips_none,
-	[R_MIPS_32]		= apply_r_mips_32,
-	[R_MIPS_26]		= apply_r_mips_26,
-	[R_MIPS_HI16]		= apply_r_mips_hi16,
-	[R_MIPS_LO16]		= apply_r_mips_lo16,
-	[R_MIPS_PC16]		= apply_r_mips_pc16,
-	[R_MIPS_64]		= apply_r_mips_64,
-	[R_MIPS_HIGHER]		= apply_r_mips_higher,
-	[R_MIPS_HIGHEST]	= apply_r_mips_highest,
-	[R_MIPS_PC21_S2]	= apply_r_mips_pc21,
-	[R_MIPS_PC26_S2]	= apply_r_mips_pc26,
-};
+static int reloc_handler(u32 type, struct module *me, u32 *location, u32 base,
+			 Elf_Addr v, bool rela)
+{
+	switch (type) {
+	case R_MIPS_NONE:
+		break;
+	case R_MIPS_32:
+		apply_r_mips_32(location, base, v);
+		break;
+	case R_MIPS_26:
+		return apply_r_mips_26(me, location, base, v);
+	case R_MIPS_HI16:
+		return apply_r_mips_hi16(me, location, v, rela);
+	case R_MIPS_LO16:
+		return apply_r_mips_lo16(me, location, base, v, rela);
+	case R_MIPS_PC16:
+		return apply_r_mips_pc16(me, location, base, v);
+	case R_MIPS_PC21_S2:
+		return apply_r_mips_pc21(me, location, base, v);
+	case R_MIPS_PC26_S2:
+		return apply_r_mips_pc26(me, location, base, v);
+	case R_MIPS_64:
+		return apply_r_mips_64(location, v, rela);
+	case R_MIPS_HIGHER:
+		return apply_r_mips_higher(location, v, rela);
+	case R_MIPS_HIGHEST:
+		return apply_r_mips_highest(location, v, rela);
+	default:
+		pr_err("%s: Unknown relocation type %u\n", me->name, type);
+		return -EINVAL;
+	}
+
+	return 0;
+}
 
 static int __apply_relocate(Elf_Shdr *sechdrs, const char *strtab,
 			    unsigned int symindex, unsigned int relsec,
@@ -311,7 +318,6 @@ static int __apply_relocate(Elf_Shdr *sechdrs, const char *strtab,
 		Elf_Mips_Rel *rel;
 		Elf_Mips_Rela *rela;
 	} r;
-	reloc_handler handler;
 	Elf_Sym *sym;
 	u32 *location, base;
 	unsigned int i, type;
@@ -343,17 +349,6 @@ static int __apply_relocate(Elf_Shdr *sechdrs, const char *strtab,
 		}
 
 		type = ELF_MIPS_R_TYPE(*r.rel);
-		if (type < ARRAY_SIZE(reloc_handlers))
-			handler = reloc_handlers[type];
-		else
-			handler = NULL;
-
-		if (!handler) {
-			pr_err("%s: Unknown relocation type %u\n",
-			       me->name, type);
-			err = -EINVAL;
-			goto out;
-		}
 
 		if (rela) {
 			v = sym->st_value + r.rela->r_addend;
@@ -365,7 +360,7 @@ static int __apply_relocate(Elf_Shdr *sechdrs, const char *strtab,
 			r.rel = &r.rel[1];
 		}
 
-		err = handler(me, location, base, v, rela);
+		err = reloc_handler(type, me, location, base, v, rela);
 		if (err)
 			goto out;
 	}
-- 
2.30.0



^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH mips-next 2/2] MIPS: relocatable: optimize the relocation process
  2021-01-16 15:02 ` [PATCH mips-next 1/2] MIPS: module: optimize module " Alexander Lobakin
@ 2021-01-16 15:02   ` Alexander Lobakin
  2021-01-18  1:49   ` [PATCH mips-next 1/2] MIPS: module: optimize module relocations processing Jiaxun Yang
  1 sibling, 0 replies; 5+ messages in thread
From: Alexander Lobakin @ 2021-01-16 15:02 UTC (permalink / raw)
  To: Thomas Bogendoerfer
  Cc: Nathan Chancellor, Nick Desaulniers, Kees Cook, Andrew Morton,
	Mike Rapoport, Alexander Lobakin, Jinyang He, linux-mips,
	linux-kernel

For now, vmlinux relocation functions for relocatable kernel are
implemented as an array of handlers of a particular type.

Convert that array into a single switch-case function to:
 - remove unused arguments;
 - change the return type of simple handlers to void;
 - remove the array and don't use any data at all;
 - avoid using indirect calls;
 - allow the compiler to inline and greatly optimize
   the relocation function[s];

and also mark do_relocations() and show_kernel_relocation() static
as they aren't used anywhere else.

The result on MIPS32 R2 with GCC 10.2 -O2 is:

scripts/bloat-o-meter -c arch/mips/kernel/__relocate.o arch/mips/kernel/relocate.o
add/remove: 0/6 grow/shrink: 1/0 up/down: 356/-640 (-284)
Function                                     old     new   delta
relocate_kernel                              852    1208    +356
apply_r_mips_32_rel                           20       -     -20
apply_r_mips_hi16_rel                         40       -     -40
apply_r_mips_64_rel                           44       -     -44
apply_r_mips_26_rel                          144       -    -144
show_kernel_relocation                       164       -    -164
do_relocations                               228       -    -228
Total: Before=1780, After=1496, chg -15.96%
add/remove: 0/1 grow/shrink: 0/0 up/down: 0/-76 (-76)
Data                                         old     new   delta
reloc_handlers_rel                            76       -     -76
Total: Before=92, After=16, chg -82.61%
add/remove: 0/0 grow/shrink: 0/0 up/down: 0/0 (0)
RO Data                                      old     new   delta
Total: Before=0, After=0, chg +0.00%

All functions were collapsed into the main one, relocate_kernel().

Signed-off-by: Alexander Lobakin <alobakin@pm.me>
---
 arch/mips/kernel/relocate.c | 54 ++++++++++++++++++++-----------------
 1 file changed, 30 insertions(+), 24 deletions(-)

diff --git a/arch/mips/kernel/relocate.c b/arch/mips/kernel/relocate.c
index 47aeb3350a76..c643c816cbe0 100644
--- a/arch/mips/kernel/relocate.c
+++ b/arch/mips/kernel/relocate.c
@@ -70,18 +70,14 @@ static void __init sync_icache(void *kbase, unsigned long kernel_length)
 	__sync();
 }
 
-static int __init apply_r_mips_64_rel(u32 *loc_orig, u32 *loc_new, long offset)
+static void __init apply_r_mips_64_rel(u32 *loc_new, long offset)
 {
 	*(u64 *)loc_new += offset;
-
-	return 0;
 }
 
-static int __init apply_r_mips_32_rel(u32 *loc_orig, u32 *loc_new, long offset)
+static void __init apply_r_mips_32_rel(u32 *loc_new, long offset)
 {
 	*loc_new += offset;
-
-	return 0;
 }
 
 static int __init apply_r_mips_26_rel(u32 *loc_orig, u32 *loc_new, long offset)
@@ -114,7 +110,8 @@ static int __init apply_r_mips_26_rel(u32 *loc_orig, u32 *loc_new, long offset)
 }
 
 
-static int __init apply_r_mips_hi16_rel(u32 *loc_orig, u32 *loc_new, long offset)
+static void __init apply_r_mips_hi16_rel(u32 *loc_orig, u32 *loc_new,
+					 long offset)
 {
 	unsigned long insn = *loc_orig;
 	unsigned long target = (insn & 0xffff) << 16; /* high 16bits of target */
@@ -122,17 +119,33 @@ static int __init apply_r_mips_hi16_rel(u32 *loc_orig, u32 *loc_new, long offset
 	target += offset;
 
 	*loc_new = (insn & ~0xffff) | ((target >> 16) & 0xffff);
-	return 0;
 }
 
-static int (*reloc_handlers_rel[]) (u32 *, u32 *, long) __initdata = {
-	[R_MIPS_64]		= apply_r_mips_64_rel,
-	[R_MIPS_32]		= apply_r_mips_32_rel,
-	[R_MIPS_26]		= apply_r_mips_26_rel,
-	[R_MIPS_HI16]		= apply_r_mips_hi16_rel,
-};
+static int __init reloc_handler(u32 type, u32 *loc_orig, u32 *loc_new,
+				long offset)
+{
+	switch (type) {
+	case R_MIPS_64:
+		apply_r_mips_64_rel(loc_new, offset);
+		break;
+	case R_MIPS_32:
+		apply_r_mips_32_rel(loc_new, offset);
+		break;
+	case R_MIPS_26:
+		return apply_r_mips_26_rel(loc_orig, loc_new, offset);
+	case R_MIPS_HI16:
+		apply_r_mips_hi16_rel(loc_orig, loc_new, offset);
+		break;
+	default:
+		pr_err("Unhandled relocation type %d at 0x%pK\n", type,
+		       loc_orig);
+		return -ENOEXEC;
+	}
 
-int __init do_relocations(void *kbase_old, void *kbase_new, long offset)
+	return 0;
+}
+
+static int __init do_relocations(void *kbase_old, void *kbase_new, long offset)
 {
 	u32 *r;
 	u32 *loc_orig;
@@ -149,14 +162,7 @@ int __init do_relocations(void *kbase_old, void *kbase_new, long offset)
 		loc_orig = kbase_old + ((*r & 0x00ffffff) << 2);
 		loc_new = RELOCATED(loc_orig);
 
-		if (reloc_handlers_rel[type] == NULL) {
-			/* Unsupported relocation */
-			pr_err("Unhandled relocation type %d at 0x%pK\n",
-			       type, loc_orig);
-			return -ENOEXEC;
-		}
-
-		res = reloc_handlers_rel[type](loc_orig, loc_new, offset);
+		res = reloc_handler(type, loc_orig, loc_new, offset);
 		if (res)
 			return res;
 	}
@@ -412,7 +418,7 @@ void *__init relocate_kernel(void)
 /*
  * Show relocation information on panic.
  */
-void show_kernel_relocation(const char *level)
+static void show_kernel_relocation(const char *level)
 {
 	unsigned long offset;
 
-- 
2.30.0



^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH mips-next 1/2] MIPS: module: optimize module relocations processing
  2021-01-16 15:02 ` [PATCH mips-next 1/2] MIPS: module: optimize module " Alexander Lobakin
  2021-01-16 15:02   ` [PATCH mips-next 2/2] MIPS: relocatable: optimize the relocation process Alexander Lobakin
@ 2021-01-18  1:49   ` Jiaxun Yang
  1 sibling, 0 replies; 5+ messages in thread
From: Jiaxun Yang @ 2021-01-18  1:49 UTC (permalink / raw)
  To: Alexander Lobakin, Thomas Bogendoerfer
  Cc: Nathan Chancellor, Nick Desaulniers, Kees Cook, Andrew Morton,
	Mike Rapoport, Jinyang He, linux-mips, linux-kernel

在 2021/1/16 下午11:02, Alexander Lobakin 写道:
> For now, module relocation functions are implemented as an array
> of handlers of type reloc_handler_t.
>
> Convert that array into a single switch-case function to:
>   - remove unused arguments;
>   - change the return type of simple handlers to void;
>   - remove the array and don't use any data at all;
>   - avoid using indirect calls;
>   - allow the compiler to inline and greatly optimize
>     the relocation function[s].
>
> The result on MIPS32 R2 with GCC 10.2 -O2 is:
>
> scripts/bloat-o-meter -c arch/mips/kernel/__module.o arch/mips/kernel/module.o
> add/remove: 1/11 grow/shrink: 1/0 up/down: 876/-1436 (-560)
> Function                                     old     new   delta
> apply_relocate                               456    1148    +692
> apply_r_mips_pc                                -     184    +184
> apply_r_mips_none                              8       -      -8
> apply_r_mips_32                               16       -     -16
> apply_r_mips_64                               76       -     -76
> apply_r_mips_highest                          88       -     -88
> apply_r_mips_higher                          108       -    -108
> apply_r_mips_26                              132       -    -132
> apply_r_mips_pc26                            160       -    -160
> apply_r_mips_pc21                            160       -    -160
> apply_r_mips_pc16                            160       -    -160
> apply_r_mips_hi16                            172       -    -172
> apply_r_mips_lo16                            356       -    -356
> Total: Before=2608, After=2048, chg -21.47%
> add/remove: 0/0 grow/shrink: 0/0 up/down: 0/0 (0)
> Data                                         old     new   delta
> Total: Before=12, After=12, chg +0.00%
> add/remove: 0/1 grow/shrink: 0/0 up/down: 0/-248 (-248)
> RO Data                                      old     new   delta
> reloc_handlers                               248       -    -248
> Total: Before=248, After=0, chg -100.00%
>
> All functions were collapsed into a single one that is called
> directly by $(srctree)/kernel/module.c.
>
> Signed-off-by: Alexander Lobakin <alobakin@pm.me>

Reviewed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>

> ---
>   arch/mips/kernel/module.c | 109 ++++++++++++++++++--------------------
>   1 file changed, 52 insertions(+), 57 deletions(-)
>
> diff --git a/arch/mips/kernel/module.c b/arch/mips/kernel/module.c
> index 3c0c3d1260c1..14f46d17500a 100644
> --- a/arch/mips/kernel/module.c
> +++ b/arch/mips/kernel/module.c
> @@ -40,22 +40,13 @@ void *module_alloc(unsigned long size)
>   }
>   #endif
>   
> -static int apply_r_mips_none(struct module *me, u32 *location,
> -			     u32 base, Elf_Addr v, bool rela)
> -{
> -	return 0;
> -}
> -
> -static int apply_r_mips_32(struct module *me, u32 *location,
> -			   u32 base, Elf_Addr v, bool rela)
> +static void apply_r_mips_32(u32 *location, u32 base, Elf_Addr v)
>   {
>   	*location = base + v;
> -
> -	return 0;
>   }
>   
> -static int apply_r_mips_26(struct module *me, u32 *location,
> -			   u32 base, Elf_Addr v, bool rela)
> +static int apply_r_mips_26(struct module *me, u32 *location, u32 base,
> +			   Elf_Addr v)
>   {
>   	if (v % 4) {
>   		pr_err("module %s: dangerous R_MIPS_26 relocation\n",
> @@ -75,8 +66,8 @@ static int apply_r_mips_26(struct module *me, u32 *location,
>   	return 0;
>   }
>   
> -static int apply_r_mips_hi16(struct module *me, u32 *location,
> -			     u32 base, Elf_Addr v, bool rela)
> +static int apply_r_mips_hi16(struct module *me, u32 *location, Elf_Addr v,
> +			     bool rela)
>   {
>   	struct mips_hi16 *n;
>   
> @@ -217,26 +208,25 @@ static int apply_r_mips_pc(struct module *me, u32 *location, u32 base,
>   	return 0;
>   }
>   
> -static int apply_r_mips_pc16(struct module *me, u32 *location,
> -			     u32 base, Elf_Addr v, bool rela)
> +static int apply_r_mips_pc16(struct module *me, u32 *location, u32 base,
> +			     Elf_Addr v)
>   {
>   	return apply_r_mips_pc(me, location, base, v, 16);
>   }
>   
> -static int apply_r_mips_pc21(struct module *me, u32 *location,
> -			     u32 base, Elf_Addr v, bool rela)
> +static int apply_r_mips_pc21(struct module *me, u32 *location, u32 base,
> +			     Elf_Addr v)
>   {
>   	return apply_r_mips_pc(me, location, base, v, 21);
>   }
>   
> -static int apply_r_mips_pc26(struct module *me, u32 *location,
> -			     u32 base, Elf_Addr v, bool rela)
> +static int apply_r_mips_pc26(struct module *me, u32 *location, u32 base,
> +			     Elf_Addr v)
>   {
>   	return apply_r_mips_pc(me, location, base, v, 26);
>   }
>   
> -static int apply_r_mips_64(struct module *me, u32 *location,
> -			   u32 base, Elf_Addr v, bool rela)
> +static int apply_r_mips_64(u32 *location, Elf_Addr v, bool rela)
>   {
>   	if (WARN_ON(!rela))
>   		return -EINVAL;
> @@ -246,8 +236,7 @@ static int apply_r_mips_64(struct module *me, u32 *location,
>   	return 0;
>   }
>   
> -static int apply_r_mips_higher(struct module *me, u32 *location,
> -			       u32 base, Elf_Addr v, bool rela)
> +static int apply_r_mips_higher(u32 *location, Elf_Addr v, bool rela)
>   {
>   	if (WARN_ON(!rela))
>   		return -EINVAL;
> @@ -258,8 +247,7 @@ static int apply_r_mips_higher(struct module *me, u32 *location,
>   	return 0;
>   }
>   
> -static int apply_r_mips_highest(struct module *me, u32 *location,
> -				u32 base, Elf_Addr v, bool rela)
> +static int apply_r_mips_highest(u32 *location, Elf_Addr v, bool rela)
>   {
>   	if (WARN_ON(!rela))
>   		return -EINVAL;
> @@ -272,12 +260,14 @@ static int apply_r_mips_highest(struct module *me, u32 *location,
>   
>   /**
>    * reloc_handler() - Apply a particular relocation to a module
> + * @type: type of the relocation to apply
>    * @me: the module to apply the reloc to
>    * @location: the address at which the reloc is to be applied
>    * @base: the existing value at location for REL-style; 0 for RELA-style
>    * @v: the value of the reloc, with addend for RELA-style
> + * @rela: indication of is this a RELA (true) or REL (false) relocation
>    *
> - * Each implemented reloc_handler function applies a particular type of
> + * Each implemented relocation function applies a particular type of
>    * relocation to the module @me. Relocs that may be found in either REL or RELA
>    * variants can be handled by making use of the @base & @v parameters which are
>    * set to values which abstract the difference away from the particular reloc
> @@ -285,23 +275,40 @@ static int apply_r_mips_highest(struct module *me, u32 *location,
>    *
>    * Return: 0 upon success, else -ERRNO
>    */
> -typedef int (*reloc_handler)(struct module *me, u32 *location,
> -			     u32 base, Elf_Addr v, bool rela);
> -
> -/* The handlers for known reloc types */
> -static reloc_handler reloc_handlers[] = {
> -	[R_MIPS_NONE]		= apply_r_mips_none,
> -	[R_MIPS_32]		= apply_r_mips_32,
> -	[R_MIPS_26]		= apply_r_mips_26,
> -	[R_MIPS_HI16]		= apply_r_mips_hi16,
> -	[R_MIPS_LO16]		= apply_r_mips_lo16,
> -	[R_MIPS_PC16]		= apply_r_mips_pc16,
> -	[R_MIPS_64]		= apply_r_mips_64,
> -	[R_MIPS_HIGHER]		= apply_r_mips_higher,
> -	[R_MIPS_HIGHEST]	= apply_r_mips_highest,
> -	[R_MIPS_PC21_S2]	= apply_r_mips_pc21,
> -	[R_MIPS_PC26_S2]	= apply_r_mips_pc26,
> -};
> +static int reloc_handler(u32 type, struct module *me, u32 *location, u32 base,
> +			 Elf_Addr v, bool rela)
> +{
> +	switch (type) {
> +	case R_MIPS_NONE:
> +		break;
> +	case R_MIPS_32:
> +		apply_r_mips_32(location, base, v);
> +		break;
> +	case R_MIPS_26:
> +		return apply_r_mips_26(me, location, base, v);
> +	case R_MIPS_HI16:
> +		return apply_r_mips_hi16(me, location, v, rela);
> +	case R_MIPS_LO16:
> +		return apply_r_mips_lo16(me, location, base, v, rela);
> +	case R_MIPS_PC16:
> +		return apply_r_mips_pc16(me, location, base, v);
> +	case R_MIPS_PC21_S2:
> +		return apply_r_mips_pc21(me, location, base, v);
> +	case R_MIPS_PC26_S2:
> +		return apply_r_mips_pc26(me, location, base, v);
> +	case R_MIPS_64:
> +		return apply_r_mips_64(location, v, rela);
> +	case R_MIPS_HIGHER:
> +		return apply_r_mips_higher(location, v, rela);
> +	case R_MIPS_HIGHEST:
> +		return apply_r_mips_highest(location, v, rela);
> +	default:
> +		pr_err("%s: Unknown relocation type %u\n", me->name, type);
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
>   
>   static int __apply_relocate(Elf_Shdr *sechdrs, const char *strtab,
>   			    unsigned int symindex, unsigned int relsec,
> @@ -311,7 +318,6 @@ static int __apply_relocate(Elf_Shdr *sechdrs, const char *strtab,
>   		Elf_Mips_Rel *rel;
>   		Elf_Mips_Rela *rela;
>   	} r;
> -	reloc_handler handler;
>   	Elf_Sym *sym;
>   	u32 *location, base;
>   	unsigned int i, type;
> @@ -343,17 +349,6 @@ static int __apply_relocate(Elf_Shdr *sechdrs, const char *strtab,
>   		}
>   
>   		type = ELF_MIPS_R_TYPE(*r.rel);
> -		if (type < ARRAY_SIZE(reloc_handlers))
> -			handler = reloc_handlers[type];
> -		else
> -			handler = NULL;
> -
> -		if (!handler) {
> -			pr_err("%s: Unknown relocation type %u\n",
> -			       me->name, type);
> -			err = -EINVAL;
> -			goto out;
> -		}
>   
>   		if (rela) {
>   			v = sym->st_value + r.rela->r_addend;
> @@ -365,7 +360,7 @@ static int __apply_relocate(Elf_Shdr *sechdrs, const char *strtab,
>   			r.rel = &r.rel[1];
>   		}
>   
> -		err = handler(me, location, base, v, rela);
> +		err = reloc_handler(type, me, location, base, v, rela);
>   		if (err)
>   			goto out;
>   	}


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH mips-next 0/2] MIPS: optimize relocations processing
  2021-01-16 15:01 [PATCH mips-next 0/2] MIPS: optimize relocations processing Alexander Lobakin
  2021-01-16 15:02 ` [PATCH mips-next 1/2] MIPS: module: optimize module " Alexander Lobakin
@ 2021-01-18 14:57 ` Thomas Bogendoerfer
  1 sibling, 0 replies; 5+ messages in thread
From: Thomas Bogendoerfer @ 2021-01-18 14:57 UTC (permalink / raw)
  To: Alexander Lobakin
  Cc: Nathan Chancellor, Nick Desaulniers, Kees Cook, Andrew Morton,
	Mike Rapoport, Jinyang He, linux-mips, linux-kernel

On Sat, Jan 16, 2021 at 03:01:57PM +0000, Alexander Lobakin wrote:
> This series converts the logics of two main relocation functions,
> one for relocatable kernel and one for modules, from the arrays of
> handlers (callbacks) to plain switch-case functions, which allows
> the compiler to greatly optimize the code, so the relocations will
> be applied faster with lesser code size.
> 
> Tested on MIPS32 R2 with GCC 10.2 and LLVM 11.0 with -O2.
> 
> Alexander Lobakin (2):
>   MIPS: module: optimize module relocations processing
>   MIPS: relocatable: optimize the relocation process
> 
>  arch/mips/kernel/module.c   | 109 +++++++++++++++++-------------------
>  arch/mips/kernel/relocate.c |  54 ++++++++++--------
>  2 files changed, 82 insertions(+), 81 deletions(-)

series applied to mips-next.

Thomas.

-- 
Crap can work. Given enough thrust pigs will fly, but it's not necessarily a
good idea.                                                [ RFC1925, 2.3 ]

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2021-01-18 14:59 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-16 15:01 [PATCH mips-next 0/2] MIPS: optimize relocations processing Alexander Lobakin
2021-01-16 15:02 ` [PATCH mips-next 1/2] MIPS: module: optimize module " Alexander Lobakin
2021-01-16 15:02   ` [PATCH mips-next 2/2] MIPS: relocatable: optimize the relocation process Alexander Lobakin
2021-01-18  1:49   ` [PATCH mips-next 1/2] MIPS: module: optimize module relocations processing Jiaxun Yang
2021-01-18 14:57 ` [PATCH mips-next 0/2] MIPS: optimize " Thomas Bogendoerfer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).