Message ID | 20211118192251.749c04f7@xhacker (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | riscv: switch to relative extable and other improvements | expand |
Hi jisheng: eBPF's exception tables needs to be modified to relative synchronously. I modified and verified the code as follows: =================== --- a/arch/riscv/net/bpf_jit_comp64.c +++ b/arch/riscv/net/bpf_jit_comp64.c @@ -499,7 +499,7 @@ static int add_exception_handler(const struct bpf_insn *insn, offset = pc - (long)&ex->insn; if (WARN_ON_ONCE(offset >= 0 || offset < INT_MIN)) return -ERANGE; - ex->insn = pc; + ex->insn = offset; =================== Thanks. Reviewed-by:Tong Tiangen <tongtiangen@huawei.com> On 2021/11/18 19:22, Jisheng Zhang wrote: > From: Jisheng Zhang <jszhang@kernel.org> > > Similar as other architectures such as arm64, x86 and so on, use > offsets relative to the exception table entry values rather than > absolute addresses for both the exception locationand the fixup. > > However, RISCV label difference will actually produce two relocations, > a pair of R_RISCV_ADD32 and R_RISCV_SUB32. Take below simple code for > example: > > $ cat test.S > .section .text > 1: > nop > .section __ex_table,"a" > .balign 4 > .long (1b - .) > .previous > > $ riscv64-linux-gnu-gcc -c test.S > $ riscv64-linux-gnu-readelf -r test.o > Relocation section '.rela__ex_table' at offset 0x100 contains 2 entries: > Offset Info Type Sym. Value Sym. Name + Addend > 000000000000 000600000023 R_RISCV_ADD32 0000000000000000 .L1^B1 + 0 > 000000000000 000500000027 R_RISCV_SUB32 0000000000000000 .L0 + 0 > > The modpost will complain the R_RISCV_SUB32 relocation, so we need to > patch modpost.c to skip this relocation for .rela__ex_table section. > > After this patch, the __ex_table section size of defconfig vmlinux is > reduced from 7072 Bytes to 3536 Bytes. > > Signed-off-by: Jisheng Zhang <jszhang@kernel.org> > Reviewed-by: Kefeng Wang <wangkefeng.wang@huawei.com> > --- > arch/riscv/include/asm/Kbuild | 1 - > arch/riscv/include/asm/extable.h | 25 +++++++++++++++++++++++++ > arch/riscv/include/asm/uaccess.h | 4 ++-- > arch/riscv/lib/uaccess.S | 4 ++-- > arch/riscv/mm/extable.c | 2 +- > scripts/mod/modpost.c | 15 +++++++++++++++ > scripts/sorttable.c | 2 +- > 7 files changed, 46 insertions(+), 7 deletions(-) > create mode 100644 arch/riscv/include/asm/extable.h > > diff --git a/arch/riscv/include/asm/Kbuild b/arch/riscv/include/asm/Kbuild > index 445ccc97305a..57b86fd9916c 100644 > --- a/arch/riscv/include/asm/Kbuild > +++ b/arch/riscv/include/asm/Kbuild > @@ -1,6 +1,5 @@ > # SPDX-License-Identifier: GPL-2.0 > generic-y += early_ioremap.h > -generic-y += extable.h > generic-y += flat.h > generic-y += kvm_para.h > generic-y += user.h > diff --git a/arch/riscv/include/asm/extable.h b/arch/riscv/include/asm/extable.h > new file mode 100644 > index 000000000000..84760392fc69 > --- /dev/null > +++ b/arch/riscv/include/asm/extable.h > @@ -0,0 +1,25 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +#ifndef _ASM_RISCV_EXTABLE_H > +#define _ASM_RISCV_EXTABLE_H > + > +/* > + * The exception table consists of pairs of relative offsets: the first > + * is the relative offset to an instruction that is allowed to fault, > + * and the second is the relative offset at which the program should > + * continue. No registers are modified, so it is entirely up to the > + * continuation code to figure out what to do. > + * > + * All the routines below use bits of fixup code that are out of line > + * with the main instruction path. This means when everything is well, > + * we don't even have to jump over them. Further, they do not intrude > + * on our cache or tlb entries. > + */ > + > +struct exception_table_entry { > + int insn, fixup; > +}; > + > +#define ARCH_HAS_RELATIVE_EXTABLE > + > +int fixup_exception(struct pt_regs *regs); > +#endif > diff --git a/arch/riscv/include/asm/uaccess.h b/arch/riscv/include/asm/uaccess.h > index 714cd311d9f1..0f2c5b9d2e8f 100644 > --- a/arch/riscv/include/asm/uaccess.h > +++ b/arch/riscv/include/asm/uaccess.h > @@ -12,8 +12,8 @@ > > #define _ASM_EXTABLE(from, to) \ > " .pushsection __ex_table, \"a\"\n" \ > - " .balign " RISCV_SZPTR " \n" \ > - " " RISCV_PTR "(" #from "), (" #to ")\n" \ > + " .balign 4\n" \ > + " .long (" #from " - .), (" #to " - .)\n" \ > " .popsection\n" > > /* > diff --git a/arch/riscv/lib/uaccess.S b/arch/riscv/lib/uaccess.S > index 63bc691cff91..55f80f84e23f 100644 > --- a/arch/riscv/lib/uaccess.S > +++ b/arch/riscv/lib/uaccess.S > @@ -7,8 +7,8 @@ > 100: > \op \reg, \addr > .section __ex_table,"a" > - .balign RISCV_SZPTR > - RISCV_PTR 100b, \lbl > + .balign 4 > + .long (100b - .), (\lbl - .) > .previous > .endm > > diff --git a/arch/riscv/mm/extable.c b/arch/riscv/mm/extable.c > index ddb7d3b99e89..d8d239c2c1bd 100644 > --- a/arch/riscv/mm/extable.c > +++ b/arch/riscv/mm/extable.c > @@ -28,6 +28,6 @@ int fixup_exception(struct pt_regs *regs) > return rv_bpf_fixup_exception(fixup, regs); > #endif > > - regs->epc = fixup->fixup; > + regs->epc = (unsigned long)&fixup->fixup + fixup->fixup; > return 1; > } > diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c > index cb8ab7d91d30..6bfa33217914 100644 > --- a/scripts/mod/modpost.c > +++ b/scripts/mod/modpost.c > @@ -1830,6 +1830,14 @@ static int addend_mips_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r) > return 0; > } > > +#ifndef EM_RISCV > +#define EM_RISCV 243 > +#endif > + > +#ifndef R_RISCV_SUB32 > +#define R_RISCV_SUB32 39 > +#endif > + > static void section_rela(const char *modname, struct elf_info *elf, > Elf_Shdr *sechdr) > { > @@ -1866,6 +1874,13 @@ static void section_rela(const char *modname, struct elf_info *elf, > r_sym = ELF_R_SYM(r.r_info); > #endif > r.r_addend = TO_NATIVE(rela->r_addend); > + switch (elf->hdr->e_machine) { > + case EM_RISCV: > + if (!strcmp("__ex_table", fromsec) && > + ELF_R_TYPE(r.r_info) == R_RISCV_SUB32) > + continue; > + break; > + } > sym = elf->symtab_start + r_sym; > /* Skip special sections */ > if (is_shndx_special(sym->st_shndx)) > diff --git a/scripts/sorttable.c b/scripts/sorttable.c > index b7c2ad71f9cf..0c031e47a419 100644 > --- a/scripts/sorttable.c > +++ b/scripts/sorttable.c > @@ -376,6 +376,7 @@ static int do_file(char const *const fname, void *addr) > case EM_PARISC: > case EM_PPC: > case EM_PPC64: > + case EM_RISCV: > custom_sort = sort_relative_table; > break; > case EM_ARCOMPACT: > @@ -383,7 +384,6 @@ static int do_file(char const *const fname, void *addr) > case EM_ARM: > case EM_MICROBLAZE: > case EM_MIPS: > - case EM_RISCV: > case EM_XTENSA: > break; > default: >
diff --git a/arch/riscv/include/asm/Kbuild b/arch/riscv/include/asm/Kbuild index 445ccc97305a..57b86fd9916c 100644 --- a/arch/riscv/include/asm/Kbuild +++ b/arch/riscv/include/asm/Kbuild @@ -1,6 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 generic-y += early_ioremap.h -generic-y += extable.h generic-y += flat.h generic-y += kvm_para.h generic-y += user.h diff --git a/arch/riscv/include/asm/extable.h b/arch/riscv/include/asm/extable.h new file mode 100644 index 000000000000..84760392fc69 --- /dev/null +++ b/arch/riscv/include/asm/extable.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_RISCV_EXTABLE_H +#define _ASM_RISCV_EXTABLE_H + +/* + * The exception table consists of pairs of relative offsets: the first + * is the relative offset to an instruction that is allowed to fault, + * and the second is the relative offset at which the program should + * continue. No registers are modified, so it is entirely up to the + * continuation code to figure out what to do. + * + * All the routines below use bits of fixup code that are out of line + * with the main instruction path. This means when everything is well, + * we don't even have to jump over them. Further, they do not intrude + * on our cache or tlb entries. + */ + +struct exception_table_entry { + int insn, fixup; +}; + +#define ARCH_HAS_RELATIVE_EXTABLE + +int fixup_exception(struct pt_regs *regs); +#endif diff --git a/arch/riscv/include/asm/uaccess.h b/arch/riscv/include/asm/uaccess.h index 714cd311d9f1..0f2c5b9d2e8f 100644 --- a/arch/riscv/include/asm/uaccess.h +++ b/arch/riscv/include/asm/uaccess.h @@ -12,8 +12,8 @@ #define _ASM_EXTABLE(from, to) \ " .pushsection __ex_table, \"a\"\n" \ - " .balign " RISCV_SZPTR " \n" \ - " " RISCV_PTR "(" #from "), (" #to ")\n" \ + " .balign 4\n" \ + " .long (" #from " - .), (" #to " - .)\n" \ " .popsection\n" /* diff --git a/arch/riscv/lib/uaccess.S b/arch/riscv/lib/uaccess.S index 63bc691cff91..55f80f84e23f 100644 --- a/arch/riscv/lib/uaccess.S +++ b/arch/riscv/lib/uaccess.S @@ -7,8 +7,8 @@ 100: \op \reg, \addr .section __ex_table,"a" - .balign RISCV_SZPTR - RISCV_PTR 100b, \lbl + .balign 4 + .long (100b - .), (\lbl - .) .previous .endm diff --git a/arch/riscv/mm/extable.c b/arch/riscv/mm/extable.c index ddb7d3b99e89..d8d239c2c1bd 100644 --- a/arch/riscv/mm/extable.c +++ b/arch/riscv/mm/extable.c @@ -28,6 +28,6 @@ int fixup_exception(struct pt_regs *regs) return rv_bpf_fixup_exception(fixup, regs); #endif - regs->epc = fixup->fixup; + regs->epc = (unsigned long)&fixup->fixup + fixup->fixup; return 1; } diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index cb8ab7d91d30..6bfa33217914 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -1830,6 +1830,14 @@ static int addend_mips_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r) return 0; } +#ifndef EM_RISCV +#define EM_RISCV 243 +#endif + +#ifndef R_RISCV_SUB32 +#define R_RISCV_SUB32 39 +#endif + static void section_rela(const char *modname, struct elf_info *elf, Elf_Shdr *sechdr) { @@ -1866,6 +1874,13 @@ static void section_rela(const char *modname, struct elf_info *elf, r_sym = ELF_R_SYM(r.r_info); #endif r.r_addend = TO_NATIVE(rela->r_addend); + switch (elf->hdr->e_machine) { + case EM_RISCV: + if (!strcmp("__ex_table", fromsec) && + ELF_R_TYPE(r.r_info) == R_RISCV_SUB32) + continue; + break; + } sym = elf->symtab_start + r_sym; /* Skip special sections */ if (is_shndx_special(sym->st_shndx)) diff --git a/scripts/sorttable.c b/scripts/sorttable.c index b7c2ad71f9cf..0c031e47a419 100644 --- a/scripts/sorttable.c +++ b/scripts/sorttable.c @@ -376,6 +376,7 @@ static int do_file(char const *const fname, void *addr) case EM_PARISC: case EM_PPC: case EM_PPC64: + case EM_RISCV: custom_sort = sort_relative_table; break; case EM_ARCOMPACT: @@ -383,7 +384,6 @@ static int do_file(char const *const fname, void *addr) case EM_ARM: case EM_MICROBLAZE: case EM_MIPS: - case EM_RISCV: case EM_XTENSA: break; default: