All of lore.kernel.org
 help / color / mirror / Atom feed
From: Zong Li <zong@andestech.com>
To: <palmer@sifive.com>, <albert@sifive.com>,
	<linux-riscv@lists.infradead.org>, <linux-kernel@vger.kernel.org>,
	<zong@andestech.com>, <zongbox@gmail.com>
Cc: <greentime@andestech.com>
Subject: [PATCH 02/11] RISC-V: Add section of GOT.PLT for kernel module
Date: Tue, 13 Mar 2018 16:35:07 +0800	[thread overview]
Message-ID: <66eb534368782f411021e1a59f3292761d6576cd.1520928420.git.zong@andestech.com> (raw)
In-Reply-To: <cover.1520928420.git.zong@andestech.com>

Separate the function symbol address from .plt to .got.plt section.

The original plt entry has trampoline code with symbol address,
there is a 32-bit padding bwtween jar instruction and symbol address.

Extract the symbol address to .got.plt to reduce the module size.

Signed-off-by: Zong Li <zong@andestech.com>
---
 arch/riscv/include/asm/module.h     | 40 +++++++++++++++++++++++--------------
 arch/riscv/kernel/module-sections.c | 21 +++++++++++++++++--
 arch/riscv/kernel/module.lds        |  1 +
 3 files changed, 45 insertions(+), 17 deletions(-)

diff --git a/arch/riscv/include/asm/module.h b/arch/riscv/include/asm/module.h
index bcc48d113deb..016e6a618e83 100644
--- a/arch/riscv/include/asm/module.h
+++ b/arch/riscv/include/asm/module.h
@@ -18,6 +18,7 @@ struct mod_section {
 struct mod_arch_specific {
 	struct mod_section got;
 	struct mod_section plt;
+	struct mod_section got_plt;
 };
 #endif
 
@@ -49,13 +50,10 @@ struct plt_entry {
 	/*
 	 * Trampoline code to real target address. The return address
 	 * should be the original (pc+4) before entring plt entry.
-	 * For 8 byte alignment of symbol_addr,
-	 * don't pack structure to remove the padding.
 	 */
 	u32 insn_auipc;		/* auipc t0, 0x0                       */
 	u32 insn_ld;		/* ld    t1, 0x10(t0)                  */
 	u32 insn_jr;		/* jr    t1                            */
-	u64 symbol_addr;	/* the real jump target address        */
 };
 
 #define OPC_AUIPC  0x0017
@@ -63,9 +61,8 @@ struct plt_entry {
 #define OPC_JALR   0x0067
 #define REG_T0     0x5
 #define REG_T1     0x6
-#define IMM_OFFSET 0x10
 
-static inline struct plt_entry emit_plt_entry(u64 val)
+static inline struct plt_entry emit_plt_entry(u64 val, u64 plt, u64 got_plt)
 {
 	/*
 	 * U-Type encoding:
@@ -79,24 +76,37 @@ static inline struct plt_entry emit_plt_entry(u64 val)
 	 * +------------+------------+--------+----------+----------+
 	 *
 	 */
+	u64 offset = got_plt - plt;
+	u32 hi20 = (offset + 0x800) & 0xfffff000;
+	u32 lo12 = (offset - hi20);
 	return (struct plt_entry) {
-		OPC_AUIPC | (REG_T0 << 7),
-		OPC_LD | (IMM_OFFSET << 20) | (REG_T0 << 15) | (REG_T1 << 7),
-		OPC_JALR | (REG_T1 << 15),
-		val
+		OPC_AUIPC | (REG_T0 << 7) | hi20,
+		OPC_LD | (lo12 << 20) | (REG_T0 << 15) | (REG_T1 << 7),
+		OPC_JALR | (REG_T1 << 15)
 	};
 }
 
-static inline struct plt_entry *get_plt_entry(u64 val,
-					      const struct mod_section *sec)
+static inline int get_got_plt_idx(u64 val, const struct mod_section *sec)
 {
-	struct plt_entry *plt = (struct plt_entry *)sec->shdr->sh_addr;
+	struct got_entry *got_plt = (struct got_entry *)sec->shdr->sh_addr;
 	int i;
 	for (i = 0; i < sec->num_entries; i++) {
-		if (plt[i].symbol_addr == val)
-			return &plt[i];
+		if (got_plt[i].symbol_addr == val)
+			return i;
 	}
-	return NULL;
+	return -1;
+}
+
+static inline struct plt_entry *get_plt_entry(u64 val,
+				      const struct mod_section *sec_plt,
+				      const struct mod_section *sec_got_plt)
+{
+	struct plt_entry *plt = (struct plt_entry *)sec_plt->shdr->sh_addr;
+	int got_plt_idx = get_got_plt_idx(val, sec_got_plt);
+	if (got_plt_idx >= 0)
+		return plt + got_plt_idx;
+	else
+		return NULL;
 }
 
 #endif /* _ASM_RISCV_MODULE_H */
diff --git a/arch/riscv/kernel/module-sections.c b/arch/riscv/kernel/module-sections.c
index 94ba1551eac3..bbbd26e19bfd 100644
--- a/arch/riscv/kernel/module-sections.c
+++ b/arch/riscv/kernel/module-sections.c
@@ -30,18 +30,23 @@ u64 module_emit_got_entry(struct module *mod, u64 val)
 
 u64 module_emit_plt_entry(struct module *mod, u64 val)
 {
+	struct mod_section *got_plt_sec = &mod->arch.got_plt;
+	struct got_entry *got_plt;
 	struct mod_section *plt_sec = &mod->arch.plt;
-	struct plt_entry *plt = get_plt_entry(val, plt_sec);
+	struct plt_entry *plt = get_plt_entry(val, plt_sec, got_plt_sec);
 	int i = plt_sec->num_entries;
 
 	if (plt)
 		return (u64)plt;
 
 	/* There is no duplicate entry, create a new one */
+	got_plt = (struct got_entry *)got_plt_sec->shdr->sh_addr;
+	got_plt[i] = emit_got_entry(val);
 	plt = (struct plt_entry *)plt_sec->shdr->sh_addr;
-	plt[i] = emit_plt_entry(val);
+	plt[i] = emit_plt_entry(val, (u64)&plt[i], (u64)&got_plt[i]);
 
 	plt_sec->num_entries++;
+	got_plt_sec->num_entries++;
 	BUG_ON(plt_sec->num_entries > plt_sec->max_entries);
 
 	return (u64)&plt[i];
@@ -94,6 +99,8 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
 			mod->arch.plt.shdr = sechdrs + i;
 		else if (!strcmp(secstrings + sechdrs[i].sh_name, ".got"))
 			mod->arch.got.shdr = sechdrs + i;
+		else if (!strcmp(secstrings + sechdrs[i].sh_name, ".got.plt"))
+			mod->arch.got_plt.shdr = sechdrs + i;
 	}
 
 	if (!mod->arch.plt.shdr) {
@@ -104,6 +111,10 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
 		pr_err("%s: module GOT section(s) missing\n", mod->name);
 		return -ENOEXEC;
 	}
+	if (!mod->arch.got_plt.shdr) {
+		pr_err("%s: module GOT.PLT section(s) missing\n", mod->name);
+		return -ENOEXEC;
+	}
 
 	/* Calculate the maxinum number of entries */
 	for (i = 0; i < ehdr->e_shnum; i++) {
@@ -135,5 +146,11 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
 	mod->arch.got.num_entries = 0;
 	mod->arch.got.max_entries = num_gots;
 
+	mod->arch.got_plt.shdr->sh_type = SHT_NOBITS;
+	mod->arch.got_plt.shdr->sh_flags = SHF_ALLOC;
+	mod->arch.got_plt.shdr->sh_addralign = L1_CACHE_BYTES;
+	mod->arch.got_plt.shdr->sh_size = (num_plts + 1) * sizeof(struct got_entry);
+	mod->arch.got_plt.num_entries = 0;
+	mod->arch.got_plt.max_entries = num_plts;
 	return 0;
 }
diff --git a/arch/riscv/kernel/module.lds b/arch/riscv/kernel/module.lds
index 7ef580e62883..295ecfb341a2 100644
--- a/arch/riscv/kernel/module.lds
+++ b/arch/riscv/kernel/module.lds
@@ -4,4 +4,5 @@
 SECTIONS {
 	.plt (NOLOAD) : { BYTE(0) }
 	.got (NOLOAD) : { BYTE(0) }
+	.got.plt (NOLOAD) : { BYTE(0) }
 }
-- 
2.16.1

WARNING: multiple messages have this Message-ID (diff)
From: zong@andestech.com (Zong Li)
To: linux-riscv@lists.infradead.org
Subject: [PATCH 02/11] RISC-V: Add section of GOT.PLT for kernel module
Date: Tue, 13 Mar 2018 16:35:07 +0800	[thread overview]
Message-ID: <66eb534368782f411021e1a59f3292761d6576cd.1520928420.git.zong@andestech.com> (raw)
In-Reply-To: <cover.1520928420.git.zong@andestech.com>

Separate the function symbol address from .plt to .got.plt section.

The original plt entry has trampoline code with symbol address,
there is a 32-bit padding bwtween jar instruction and symbol address.

Extract the symbol address to .got.plt to reduce the module size.

Signed-off-by: Zong Li <zong@andestech.com>
---
 arch/riscv/include/asm/module.h     | 40 +++++++++++++++++++++++--------------
 arch/riscv/kernel/module-sections.c | 21 +++++++++++++++++--
 arch/riscv/kernel/module.lds        |  1 +
 3 files changed, 45 insertions(+), 17 deletions(-)

diff --git a/arch/riscv/include/asm/module.h b/arch/riscv/include/asm/module.h
index bcc48d113deb..016e6a618e83 100644
--- a/arch/riscv/include/asm/module.h
+++ b/arch/riscv/include/asm/module.h
@@ -18,6 +18,7 @@ struct mod_section {
 struct mod_arch_specific {
 	struct mod_section got;
 	struct mod_section plt;
+	struct mod_section got_plt;
 };
 #endif
 
@@ -49,13 +50,10 @@ struct plt_entry {
 	/*
 	 * Trampoline code to real target address. The return address
 	 * should be the original (pc+4) before entring plt entry.
-	 * For 8 byte alignment of symbol_addr,
-	 * don't pack structure to remove the padding.
 	 */
 	u32 insn_auipc;		/* auipc t0, 0x0                       */
 	u32 insn_ld;		/* ld    t1, 0x10(t0)                  */
 	u32 insn_jr;		/* jr    t1                            */
-	u64 symbol_addr;	/* the real jump target address        */
 };
 
 #define OPC_AUIPC  0x0017
@@ -63,9 +61,8 @@ struct plt_entry {
 #define OPC_JALR   0x0067
 #define REG_T0     0x5
 #define REG_T1     0x6
-#define IMM_OFFSET 0x10
 
-static inline struct plt_entry emit_plt_entry(u64 val)
+static inline struct plt_entry emit_plt_entry(u64 val, u64 plt, u64 got_plt)
 {
 	/*
 	 * U-Type encoding:
@@ -79,24 +76,37 @@ static inline struct plt_entry emit_plt_entry(u64 val)
 	 * +------------+------------+--------+----------+----------+
 	 *
 	 */
+	u64 offset = got_plt - plt;
+	u32 hi20 = (offset + 0x800) & 0xfffff000;
+	u32 lo12 = (offset - hi20);
 	return (struct plt_entry) {
-		OPC_AUIPC | (REG_T0 << 7),
-		OPC_LD | (IMM_OFFSET << 20) | (REG_T0 << 15) | (REG_T1 << 7),
-		OPC_JALR | (REG_T1 << 15),
-		val
+		OPC_AUIPC | (REG_T0 << 7) | hi20,
+		OPC_LD | (lo12 << 20) | (REG_T0 << 15) | (REG_T1 << 7),
+		OPC_JALR | (REG_T1 << 15)
 	};
 }
 
-static inline struct plt_entry *get_plt_entry(u64 val,
-					      const struct mod_section *sec)
+static inline int get_got_plt_idx(u64 val, const struct mod_section *sec)
 {
-	struct plt_entry *plt = (struct plt_entry *)sec->shdr->sh_addr;
+	struct got_entry *got_plt = (struct got_entry *)sec->shdr->sh_addr;
 	int i;
 	for (i = 0; i < sec->num_entries; i++) {
-		if (plt[i].symbol_addr == val)
-			return &plt[i];
+		if (got_plt[i].symbol_addr == val)
+			return i;
 	}
-	return NULL;
+	return -1;
+}
+
+static inline struct plt_entry *get_plt_entry(u64 val,
+				      const struct mod_section *sec_plt,
+				      const struct mod_section *sec_got_plt)
+{
+	struct plt_entry *plt = (struct plt_entry *)sec_plt->shdr->sh_addr;
+	int got_plt_idx = get_got_plt_idx(val, sec_got_plt);
+	if (got_plt_idx >= 0)
+		return plt + got_plt_idx;
+	else
+		return NULL;
 }
 
 #endif /* _ASM_RISCV_MODULE_H */
diff --git a/arch/riscv/kernel/module-sections.c b/arch/riscv/kernel/module-sections.c
index 94ba1551eac3..bbbd26e19bfd 100644
--- a/arch/riscv/kernel/module-sections.c
+++ b/arch/riscv/kernel/module-sections.c
@@ -30,18 +30,23 @@ u64 module_emit_got_entry(struct module *mod, u64 val)
 
 u64 module_emit_plt_entry(struct module *mod, u64 val)
 {
+	struct mod_section *got_plt_sec = &mod->arch.got_plt;
+	struct got_entry *got_plt;
 	struct mod_section *plt_sec = &mod->arch.plt;
-	struct plt_entry *plt = get_plt_entry(val, plt_sec);
+	struct plt_entry *plt = get_plt_entry(val, plt_sec, got_plt_sec);
 	int i = plt_sec->num_entries;
 
 	if (plt)
 		return (u64)plt;
 
 	/* There is no duplicate entry, create a new one */
+	got_plt = (struct got_entry *)got_plt_sec->shdr->sh_addr;
+	got_plt[i] = emit_got_entry(val);
 	plt = (struct plt_entry *)plt_sec->shdr->sh_addr;
-	plt[i] = emit_plt_entry(val);
+	plt[i] = emit_plt_entry(val, (u64)&plt[i], (u64)&got_plt[i]);
 
 	plt_sec->num_entries++;
+	got_plt_sec->num_entries++;
 	BUG_ON(plt_sec->num_entries > plt_sec->max_entries);
 
 	return (u64)&plt[i];
@@ -94,6 +99,8 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
 			mod->arch.plt.shdr = sechdrs + i;
 		else if (!strcmp(secstrings + sechdrs[i].sh_name, ".got"))
 			mod->arch.got.shdr = sechdrs + i;
+		else if (!strcmp(secstrings + sechdrs[i].sh_name, ".got.plt"))
+			mod->arch.got_plt.shdr = sechdrs + i;
 	}
 
 	if (!mod->arch.plt.shdr) {
@@ -104,6 +111,10 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
 		pr_err("%s: module GOT section(s) missing\n", mod->name);
 		return -ENOEXEC;
 	}
+	if (!mod->arch.got_plt.shdr) {
+		pr_err("%s: module GOT.PLT section(s) missing\n", mod->name);
+		return -ENOEXEC;
+	}
 
 	/* Calculate the maxinum number of entries */
 	for (i = 0; i < ehdr->e_shnum; i++) {
@@ -135,5 +146,11 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
 	mod->arch.got.num_entries = 0;
 	mod->arch.got.max_entries = num_gots;
 
+	mod->arch.got_plt.shdr->sh_type = SHT_NOBITS;
+	mod->arch.got_plt.shdr->sh_flags = SHF_ALLOC;
+	mod->arch.got_plt.shdr->sh_addralign = L1_CACHE_BYTES;
+	mod->arch.got_plt.shdr->sh_size = (num_plts + 1) * sizeof(struct got_entry);
+	mod->arch.got_plt.num_entries = 0;
+	mod->arch.got_plt.max_entries = num_plts;
 	return 0;
 }
diff --git a/arch/riscv/kernel/module.lds b/arch/riscv/kernel/module.lds
index 7ef580e62883..295ecfb341a2 100644
--- a/arch/riscv/kernel/module.lds
+++ b/arch/riscv/kernel/module.lds
@@ -4,4 +4,5 @@
 SECTIONS {
 	.plt (NOLOAD) : { BYTE(0) }
 	.got (NOLOAD) : { BYTE(0) }
+	.got.plt (NOLOAD) : { BYTE(0) }
 }
-- 
2.16.1

  parent reply	other threads:[~2018-03-13  8:51 UTC|newest]

Thread overview: 62+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-03-13  8:35 [PATCH 00/11] RISC-V: Resolve the issue of loadable module on 64-bit Zong Li
2018-03-13  8:35 ` Zong Li
2018-03-13  8:35 ` [PATCH 01/11] RISC-V: Add sections of PLT and GOT for kernel module Zong Li
2018-03-13  8:35   ` Zong Li
2018-03-14 17:20   ` kbuild test robot
2018-03-14 17:20     ` kbuild test robot
2018-03-13  8:35 ` Zong Li [this message]
2018-03-13  8:35   ` [PATCH 02/11] RISC-V: Add section of GOT.PLT " Zong Li
2018-03-14 17:34   ` kbuild test robot
2018-03-14 17:34     ` kbuild test robot
2018-03-15  9:35     ` Zong Li
2018-03-15  9:35       ` Zong Li
2018-03-13  8:35 ` [PATCH 03/11] RISC-V: Support GOT_HI20/CALL_PLT relocation type in " Zong Li
2018-03-13  8:35   ` Zong Li
2018-03-13  8:35 ` [PATCH 04/11] RISC-V: Support CALL " Zong Li
2018-03-13  8:35   ` Zong Li
2018-03-13  8:35 ` [PATCH 05/11] RISC-V: Support HI20/LO12_I/LO12_S " Zong Li
2018-03-13  8:35   ` Zong Li
2018-03-13  8:35 ` [PATCH 06/11] RISC-V: Support RVC_BRANCH/JUMP relocation type in kernel modulewq Zong Li
2018-03-13  8:35   ` Zong Li
2018-03-13  8:35 ` [PATCH 07/11] RISC-V: Support ALIGN relocation type in kernel module Zong Li
2018-03-13  8:35   ` Zong Li
2018-03-13  8:35 ` [PATCH 08/11] RISC-V: Support ADD32 " Zong Li
2018-03-13  8:35   ` Zong Li
2018-03-13  8:35 ` [PATCH 09/11] RISC-V: Support SUB32 " Zong Li
2018-03-13  8:35   ` Zong Li
2018-03-13  8:35 ` [PATCH 10/11] RISC-V: Enable module support in defconfig Zong Li
2018-03-13  8:35   ` Zong Li
2018-03-13  8:35 ` [PATCH 11/11] RISC-V: Add definition of relocation types Zong Li
2018-03-13  8:35   ` Zong Li
2018-03-13 10:35 ` [PATCH 00/11] RISC-V: Resolve the issue of loadable module on 64-bit Zong Li
2018-03-13 10:35   ` Zong Li
2018-03-13 18:35 ` Palmer Dabbelt
2018-03-13 18:35   ` Palmer Dabbelt
2018-03-13 21:30   ` Shea Levy
2018-03-13 21:30     ` Shea Levy
2018-03-14  1:34     ` Zong Li
2018-03-14  1:34       ` Zong Li
2018-03-14  3:07       ` Palmer Dabbelt
2018-03-14  3:07         ` Palmer Dabbelt
2018-03-14 11:15         ` Zong Li
2018-03-14 11:15           ` Zong Li
2018-03-14 11:56           ` Shea Levy
2018-03-14 11:56             ` Shea Levy
2018-03-14 12:20             ` Zong Li
2018-03-14 12:20               ` Zong Li
2018-03-14 11:54         ` Shea Levy
2018-03-14 11:54           ` Shea Levy
2018-03-14 17:07           ` Palmer Dabbelt
2018-03-14 17:07             ` Palmer Dabbelt
2018-03-14  3:51     ` Palmer Dabbelt
2018-03-14  3:51       ` Palmer Dabbelt
2018-03-14 12:07       ` Shea Levy
2018-03-14 12:07         ` Shea Levy
2018-03-14 17:07         ` Palmer Dabbelt
2018-03-14 17:07           ` Palmer Dabbelt
2018-03-14 17:11           ` Shea Levy
2018-03-14 17:11             ` Shea Levy
2018-03-14 17:30             ` Palmer Dabbelt
2018-03-14 17:30               ` Palmer Dabbelt
2018-03-13 21:26 ` Shea Levy
2018-03-13 21:26   ` Shea Levy

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=66eb534368782f411021e1a59f3292761d6576cd.1520928420.git.zong@andestech.com \
    --to=zong@andestech.com \
    --cc=albert@sifive.com \
    --cc=greentime@andestech.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-riscv@lists.infradead.org \
    --cc=palmer@sifive.com \
    --cc=zongbox@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.