2021-01-16 17:33:06

by Alexander Lobakin

[permalink] [raw]
Subject: [PATCH mips-next 0/2] MIPS: optimize relocations processing

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



2021-01-16 18:13:57

by Alexander Lobakin

[permalink] [raw]
Subject: [PATCH mips-next 1/2] MIPS: module: optimize module relocations processing

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 <[email protected]>
---
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


2021-01-16 18:14:29

by Alexander Lobakin

[permalink] [raw]
Subject: [PATCH mips-next 2/2] MIPS: relocatable: optimize the relocation process

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 <[email protected]>
---
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


2021-01-18 01:53:14

by Jiaxun Yang

[permalink] [raw]
Subject: Re: [PATCH mips-next 1/2] MIPS: module: optimize module relocations processing

在 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 <[email protected]>

Reviewed-by: Jiaxun Yang <[email protected]>

> ---
> 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;
> }

2021-01-19 04:36:31

by Thomas Bogendoerfer

[permalink] [raw]
Subject: Re: [PATCH mips-next 0/2] MIPS: optimize relocations processing

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 ]