diff mbox series

riscv: optimize ELF relocation function in riscv

Message ID 1683717018-12882-1-git-send-email-lixiaoyun@binary-semi.com (mailing list archive)
State Superseded
Delegated to: Palmer Dabbelt
Headers show
Series riscv: optimize ELF relocation function in riscv | expand

Checks

Context Check Description
conchuod/cover_letter success Single patches do not need cover letters
conchuod/tree_selection success Guessed tree name to be for-next at HEAD ac9a78681b92
conchuod/fixes_present success Fixes tag not required for -next series
conchuod/maintainers_pattern success MAINTAINERS pattern errors before the patch: 6 and now 6
conchuod/verify_signedoff success Signed-off-by tag matches author and committer
conchuod/kdoc success Errors and warnings before: 0 this patch: 0
conchuod/build_rv64_clang_allmodconfig success Errors and warnings before: 14 this patch: 14
conchuod/module_param success Was 0 now: 0
conchuod/build_rv64_gcc_allmodconfig success Errors and warnings before: 28 this patch: 28
conchuod/build_rv32_defconfig success Build OK
conchuod/dtb_warn_rv64 success Errors and warnings before: 3 this patch: 3
conchuod/header_inline success No static functions without inline keyword in header files
conchuod/checkpatch warning CHECK: Blank lines aren't necessary before a close brace '}' CHECK: Lines should not end with a '(' CHECK: Logical continuations should be on the previous line CHECK: Please don't use multiple blank lines WARNING: Too many leading tabs - consider code refactoring
conchuod/build_rv64_nommu_k210_defconfig success Build OK
conchuod/verify_fixes success No Fixes tag
conchuod/build_rv64_nommu_virt_defconfig success Build OK

Commit Message

Amma Lee May 10, 2023, 11:10 a.m. UTC
The patch can optimize the running times of "insmod" command by modify ELF
relocation function.
In the riscv kernel, when install the ELF driver which contains multiple
symbol table items to be relocated, kernel takes a lot of time to
execute the relocation. For example, we install a 3+MB driver need 180+s.

We focus on the riscv kernel handle R_RISCV_HI20 and R_RISCV_LO12 type
items relocation function and find that there are two for-loops in this
function. If we modify the begin number in the second for-loops iteration,
we could save significant time for installation. We install the 3+MB
driver could just need 2s.

Signed-off-by: Amma.Lee<lixiaoyun@binary-semi.com>
---
 arch/riscv/kernel/module.c | 69 ++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 61 insertions(+), 8 deletions(-)

Comments

Conor Dooley May 11, 2023, 10:45 p.m. UTC | #1
Hey Amma,

The patchwork automation seems to have skipped this patch for some
reason, so here I am doing it manually instead!

On Wed, May 10, 2023 at 07:10:18PM +0800, Amma.Lee wrote:
> The patch can optimize the running times of "insmod" command by modify ELF
> relocation function.
> In the riscv kernel, when install the ELF driver which contains multiple
> symbol table items to be relocated, kernel takes a lot of time to
> execute the relocation. For example, we install a 3+MB driver need 180+s.
> 
> We focus on the riscv kernel handle R_RISCV_HI20 and R_RISCV_LO12 type
> items relocation function and find that there are two for-loops in this
> function. If we modify the begin number in the second for-loops iteration,
> we could save significant time for installation. We install the 3+MB
> driver could just need 2s.
> 
> Signed-off-by: Amma.Lee<lixiaoyun@binary-semi.com>

Firstly, please remove the . between your names, and add a space before
the <.
`git commit -s` will automagically add a SoB FYI.

When I applied this patch I got:
Applying: riscv: optimize ELF relocation function in riscv
warning: arch/riscv/kernel/module.c has type 100644, expected 100755

There are also quite a lot of checkpatch coding-style issues:
| 65: CHECK: Lines should not end with a '('
| 71: CHECK: Please don't use multiple blank lines
| 78: CHECK: Please don't use multiple blank lines
| 81: CHECK: Logical continuations should be on the previous line
| 82: CHECK: Logical continuations should be on the previous line
| 91: CHECK: Please don't use multiple blank lines
| 95: WARNING: Too many leading tabs - consider code refactoring
| 96: CHECK: Logical continuations should be on the previous line
| 97: CHECK: Lines should not end with a '('
| 101: CHECK: Blank lines aren't necessary before a close brace '}'
| 111: CHECK: Lines should not end with a '('
| 117: CHECK: Please don't use multiple blank lines
| total: 0 errors, 1 warnings, 11 checks, 93 lines checked

Hopefully you get some comments on the code itself, and when you resend,
the automation does actually pick it up.

Thanks,
Conor.
diff mbox series

Patch

diff --git a/arch/riscv/kernel/module.c b/arch/riscv/kernel/module.c
index 7c651d5..55507b0 100755
--- a/arch/riscv/kernel/module.c
+++ b/arch/riscv/kernel/module.c
@@ -345,13 +345,13 @@  int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
 	int (*handler)(struct module *me, u32 *location, Elf_Addr v);
 	Elf_Sym *sym;
 	u32 *location;
-	unsigned int i, type;
+	unsigned int i, type, j_idx;
 	Elf_Addr v;
 	int res;
 
 	pr_debug("Applying relocate section %u to %u\n", relsec,
 	       sechdrs[relsec].sh_info);
-
+	j_idx = 0;
 	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
 		/* This is where to make the change */
 		location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
@@ -385,8 +385,9 @@  int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
 
 		if (type == R_RISCV_PCREL_LO12_I || type == R_RISCV_PCREL_LO12_S) {
 			unsigned int j;
-
-			for (j = 0; j < sechdrs[relsec].sh_size / sizeof(*rel); j++) {
+			/*Modify the j for-loops begin number from last iterates end value*/
+			for (j = j_idx; j < sechdrs[relsec].sh_size / sizeof(*rel); j++) {
+			/* Modify end */
 				unsigned long hi20_loc =
 					sechdrs[sechdrs[relsec].sh_info].sh_addr
 					+ rel[j].r_offset;
@@ -420,11 +421,63 @@  int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
 				}
 			}
 			if (j == sechdrs[relsec].sh_size / sizeof(*rel)) {
-				pr_err(
-				  "%s: Can not find HI20 relocation information\n",
-				  me->name);
-				return -EINVAL;
+				if (j_idx == 0) {
+					pr_err(
+						"%s: Can not find HI20 relocation information\n",
+						me->name);
+					return -EINVAL;
+				}
+
+
+				for (j = 0; j < j_idx; j++) {
+					unsigned long hi20_loc =
+						sechdrs[sechdrs[relsec].sh_info].sh_addr
+						+ rel[j].r_offset;
+					u32 hi20_type = ELF_RISCV_R_TYPE(rel[j].r_info);
+
+
+					/* Find the corresponding HI20 relocation entry */
+					if (hi20_loc == sym->st_value
+						&& (hi20_type == R_RISCV_PCREL_HI20
+						|| hi20_type == R_RISCV_GOT_HI20)) {
+						s32 hi20, lo12;
+						Elf_Sym *hi20_sym =
+							(Elf_Sym *)sechdrs[symindex].sh_addr
+							+ ELF_RISCV_R_SYM(rel[j].r_info);
+						unsigned long hi20_sym_val =
+							hi20_sym->st_value
+							+ rel[j].r_addend;
+
+
+						/* Calculate lo12 */
+						size_t offset = hi20_sym_val - hi20_loc;
+						/* Calculate lo12 */
+						if (IS_ENABLED(CONFIG_MODULE_SECTIONS)
+							&& hi20_type == R_RISCV_GOT_HI20) {
+							offset = module_emit_got_entry(
+								me, hi20_sym_val);
+							offset = offset - hi20_loc;
+
+						}
+						hi20 = (offset + 0x800) & 0xfffff000;
+						lo12 = offset - hi20;
+						v = lo12;
+
+						break;
+					}
+				}
+
+				if (j == j_idx) {
+					pr_err(
+						"%s: Can not find HI20 relocation information\n",
+						me->name);
+					return -EINVAL;
+				}
+
+
 			}
+
+			j_idx = j;
 		}
 
 		res = handler(me, location, v);