From: Charlie Jenkins <charlie@rivosinc.com>
To: Emil Renner Berthing <emil.renner.berthing@canonical.com>
Cc: linux-riscv@lists.infradead.org, linux-mm@kvack.org,
linux-kernel@vger.kernel.org,
Eric Biederman <ebiederm@xmission.com>,
Kees Cook <keescook@chromium.org>,
Paul Walmsley <paul.walmsley@sifive.com>,
Palmer Dabbelt <palmer@dabbelt.com>,
Albert Ou <aou@eecs.berkeley.edu>
Subject: Re: [PATCH v4 1/2] riscv: Add remaining module relocations
Date: Wed, 18 Oct 2023 11:31:00 -0700 [thread overview]
Message-ID: <ZTAkZAm21O3gtA7i@ghost> (raw)
In-Reply-To: <CAJM55Z9xgyJoCX83hgwerF6SRo6yit8=0rmLzhF8Ju4TmZq3BA@mail.gmail.com>
On Wed, Oct 18, 2023 at 05:17:44AM -0700, Emil Renner Berthing wrote:
> Charlie Jenkins wrote:
> > Add all final module relocations and add error logs explaining the ones
> > that are not supported.
> >
> > Signed-off-by: Charlie Jenkins <charlie@rivosinc.com>
> > ---
> > arch/riscv/include/uapi/asm/elf.h | 5 +-
> > arch/riscv/kernel/module.c | 207 +++++++++++++++++++++++++++++++++-----
> > 2 files changed, 186 insertions(+), 26 deletions(-)
> >
> > diff --git a/arch/riscv/include/uapi/asm/elf.h b/arch/riscv/include/uapi/asm/elf.h
> > index d696d6610231..11a71b8533d5 100644
> > --- a/arch/riscv/include/uapi/asm/elf.h
> > +++ b/arch/riscv/include/uapi/asm/elf.h
> > @@ -49,6 +49,7 @@ typedef union __riscv_fp_state elf_fpregset_t;
> > #define R_RISCV_TLS_DTPREL64 9
> > #define R_RISCV_TLS_TPREL32 10
> > #define R_RISCV_TLS_TPREL64 11
> > +#define R_RISCV_IRELATIVE 58
> >
> > /* Relocation types not used by the dynamic linker */
> > #define R_RISCV_BRANCH 16
> > @@ -81,7 +82,6 @@ typedef union __riscv_fp_state elf_fpregset_t;
> > #define R_RISCV_ALIGN 43
> > #define R_RISCV_RVC_BRANCH 44
> > #define R_RISCV_RVC_JUMP 45
> > -#define R_RISCV_LUI 46
> > #define R_RISCV_GPREL_I 47
> > #define R_RISCV_GPREL_S 48
> > #define R_RISCV_TPREL_I 49
> > @@ -93,6 +93,9 @@ typedef union __riscv_fp_state elf_fpregset_t;
> > #define R_RISCV_SET16 55
> > #define R_RISCV_SET32 56
> > #define R_RISCV_32_PCREL 57
> > +#define R_RISCV_PLT32 59
> > +#define R_RISCV_SET_ULEB128 60
> > +#define R_RISCV_SUB_ULEB128 61
> >
> >
> > #endif /* _UAPI_ASM_RISCV_ELF_H */
> > diff --git a/arch/riscv/kernel/module.c b/arch/riscv/kernel/module.c
> > index 7c651d55fcbd..e860726352ac 100644
> > --- a/arch/riscv/kernel/module.c
> > +++ b/arch/riscv/kernel/module.c
> > @@ -7,6 +7,7 @@
> > #include <linux/elf.h>
> > #include <linux/err.h>
> > #include <linux/errno.h>
> > +#include <linux/kernel.h>
> > #include <linux/moduleloader.h>
> > #include <linux/vmalloc.h>
> > #include <linux/sizes.h>
> > @@ -268,6 +269,12 @@ static int apply_r_riscv_align_rela(struct module *me, u32 *location,
> > return -EINVAL;
> > }
> >
> > +static int apply_r_riscv_add8_rela(struct module *me, u32 *location, Elf_Addr v)
> > +{
> > + *(u8 *)location += (u8)v;
> > + return 0;
> > +}
> > +
> > static int apply_r_riscv_add16_rela(struct module *me, u32 *location,
> > Elf_Addr v)
> > {
> > @@ -289,6 +296,12 @@ static int apply_r_riscv_add64_rela(struct module *me, u32 *location,
> > return 0;
> > }
> >
> > +static int apply_r_riscv_sub8_rela(struct module *me, u32 *location, Elf_Addr v)
> > +{
> > + *(u8 *)location -= (u8)v;
> > + return 0;
> > +}
> > +
> > static int apply_r_riscv_sub16_rela(struct module *me, u32 *location,
> > Elf_Addr v)
> > {
> > @@ -310,31 +323,149 @@ static int apply_r_riscv_sub64_rela(struct module *me, u32 *location,
> > return 0;
> > }
> >
> > -static int (*reloc_handlers_rela[]) (struct module *me, u32 *location,
> > - Elf_Addr v) = {
> > - [R_RISCV_32] = apply_r_riscv_32_rela,
> > - [R_RISCV_64] = apply_r_riscv_64_rela,
> > - [R_RISCV_BRANCH] = apply_r_riscv_branch_rela,
> > - [R_RISCV_JAL] = apply_r_riscv_jal_rela,
> > - [R_RISCV_RVC_BRANCH] = apply_r_riscv_rvc_branch_rela,
> > - [R_RISCV_RVC_JUMP] = apply_r_riscv_rvc_jump_rela,
> > - [R_RISCV_PCREL_HI20] = apply_r_riscv_pcrel_hi20_rela,
> > - [R_RISCV_PCREL_LO12_I] = apply_r_riscv_pcrel_lo12_i_rela,
> > - [R_RISCV_PCREL_LO12_S] = apply_r_riscv_pcrel_lo12_s_rela,
> > - [R_RISCV_HI20] = apply_r_riscv_hi20_rela,
> > - [R_RISCV_LO12_I] = apply_r_riscv_lo12_i_rela,
> > - [R_RISCV_LO12_S] = apply_r_riscv_lo12_s_rela,
> > - [R_RISCV_GOT_HI20] = apply_r_riscv_got_hi20_rela,
> > - [R_RISCV_CALL_PLT] = apply_r_riscv_call_plt_rela,
> > - [R_RISCV_CALL] = apply_r_riscv_call_rela,
> > - [R_RISCV_RELAX] = apply_r_riscv_relax_rela,
> > - [R_RISCV_ALIGN] = apply_r_riscv_align_rela,
> > - [R_RISCV_ADD16] = apply_r_riscv_add16_rela,
> > - [R_RISCV_ADD32] = apply_r_riscv_add32_rela,
> > - [R_RISCV_ADD64] = apply_r_riscv_add64_rela,
> > - [R_RISCV_SUB16] = apply_r_riscv_sub16_rela,
> > - [R_RISCV_SUB32] = apply_r_riscv_sub32_rela,
> > - [R_RISCV_SUB64] = apply_r_riscv_sub64_rela,
> > +static int dynamic_linking_not_supported(struct module *me, u32 *location,
> > + Elf_Addr v)
> > +{
> > + pr_err("%s: Dynamic linking not supported in kernel modules PC = %p\n",
> > + me->name, location);
> > + return -EINVAL;
> > +}
> > +
> > +static int tls_not_supported(struct module *me, u32 *location, Elf_Addr v)
> > +{
> > + pr_err("%s: Thread local storage not supported in kernel modules PC = %p\n",
> > + me->name, location);
> > + return -EINVAL;
> > +}
> > +
> > +static int apply_r_riscv_sub6_rela(struct module *me, u32 *location, Elf_Addr v)
> > +{
> > + *(u8 *)location = (*location - ((u8)v & 0x3F)) & 0x3F;
> > + return 0;
> > +}
> > +
> > +static int apply_r_riscv_set6_rela(struct module *me, u32 *location, Elf_Addr v)
> > +{
> > + *(u8 *)location = (*(u8 *)location & 0xc0) | ((u8)v & 0x3F);
> > + return 0;
> > +}
> > +
> > +static int apply_r_riscv_set8_rela(struct module *me, u32 *location, Elf_Addr v)
> > +{
> > + *(u8 *)location = (u8)v;
> > + return 0;
> > +}
> > +
> > +static int apply_r_riscv_set16_rela(struct module *me, u32 *location,
> > + Elf_Addr v)
> > +{
> > + *(u16 *)location = (u16)v;
> > + return 0;
> > +}
> > +
> > +static int apply_r_riscv_set32_rela(struct module *me, u32 *location,
> > + Elf_Addr v)
> > +{
> > + *(u32 *)location = (u32)v;
> > + return 0;
> > +}
> > +
> > +static int apply_r_riscv_32_pcrel_rela(struct module *me, u32 *location,
> > + Elf_Addr v)
> > +{
> > + *(u32 *)location = (u32)v;
> > + return 0;
> > +}
> > +
> > +static int apply_r_riscv_plt32_rela(struct module *me, u32 *location,
> > + Elf_Addr v)
> > +{
> > + *(u32 *)location = (u32)v;
> > + return 0;
> > +}
> > +
> > +static int apply_r_riscv_set_uleb128(struct module *me, u32 *location, Elf_Addr v)
> > +{
> > + /*
> > + * Relocation is only performed if R_RISCV_SET_ULEB128 is followed by
> > + * R_RISCV_SUB_ULEB128 so do computation there
> > + */
> > + return 0;
> > +}
> > +
> > +static int apply_r_riscv_sub_uleb128(struct module *me, u32 *location, Elf_Addr v)
> > +{
> > + if (v >= 128) {
> > + pr_err("%s: uleb128 must be in [0, 127] (not %ld) at PC = %p\n",
> > + me->name, (unsigned long)v, location);
> > + return -EINVAL;
> > + }
> > +
> > + *location = v;
> > + return 0;
> > +}
> > +
> > +/*
> > + * Relocations defined in the riscv-elf-psabi-doc.
> > + * This handles static linking only.
> > + */
> > +static int (*reloc_handlers_rela[])(struct module *me, u32 *location,
> > + Elf_Addr v) = {
> > + [R_RISCV_32] = apply_r_riscv_32_rela,
> > + [R_RISCV_64] = apply_r_riscv_64_rela,
> > + [R_RISCV_RELATIVE] = dynamic_linking_not_supported,
> > + [R_RISCV_COPY] = dynamic_linking_not_supported,
> > + [R_RISCV_JUMP_SLOT] = dynamic_linking_not_supported,
> > + [R_RISCV_TLS_DTPMOD32] = dynamic_linking_not_supported,
> > + [R_RISCV_TLS_DTPMOD64] = dynamic_linking_not_supported,
> > + [R_RISCV_TLS_DTPREL32] = dynamic_linking_not_supported,
> > + [R_RISCV_TLS_DTPREL64] = dynamic_linking_not_supported,
> > + [R_RISCV_TLS_TPREL32] = dynamic_linking_not_supported,
> > + [R_RISCV_TLS_TPREL64] = dynamic_linking_not_supported,
> > + /* 12-15 undefined */
> > + [R_RISCV_BRANCH] = apply_r_riscv_branch_rela,
> > + [R_RISCV_JAL] = apply_r_riscv_jal_rela,
> > + [R_RISCV_CALL] = apply_r_riscv_call_rela,
> > + [R_RISCV_CALL_PLT] = apply_r_riscv_call_plt_rela,
> > + [R_RISCV_GOT_HI20] = apply_r_riscv_got_hi20_rela,
> > + [R_RISCV_TLS_GOT_HI20] = tls_not_supported,
> > + [R_RISCV_TLS_GD_HI20] = tls_not_supported,
> > + [R_RISCV_PCREL_HI20] = apply_r_riscv_pcrel_hi20_rela,
> > + [R_RISCV_PCREL_LO12_I] = apply_r_riscv_pcrel_lo12_i_rela,
> > + [R_RISCV_PCREL_LO12_S] = apply_r_riscv_pcrel_lo12_s_rela,
> > + [R_RISCV_HI20] = apply_r_riscv_hi20_rela,
> > + [R_RISCV_LO12_I] = apply_r_riscv_lo12_i_rela,
> > + [R_RISCV_LO12_S] = apply_r_riscv_lo12_s_rela,
> > + [R_RISCV_TPREL_HI20] = tls_not_supported,
> > + [R_RISCV_TPREL_LO12_I] = tls_not_supported,
> > + [R_RISCV_TPREL_LO12_S] = tls_not_supported,
> > + [R_RISCV_TPREL_ADD] = tls_not_supported,
> > + [R_RISCV_ADD8] = apply_r_riscv_add8_rela,
> > + [R_RISCV_ADD16] = apply_r_riscv_add16_rela,
> > + [R_RISCV_ADD32] = apply_r_riscv_add32_rela,
> > + [R_RISCV_ADD64] = apply_r_riscv_add64_rela,
> > + [R_RISCV_SUB8] = apply_r_riscv_sub8_rela,
> > + [R_RISCV_SUB16] = apply_r_riscv_sub16_rela,
> > + [R_RISCV_SUB32] = apply_r_riscv_sub32_rela,
> > + [R_RISCV_SUB64] = apply_r_riscv_sub64_rela,
> > + /* 41-42 reserved for future standard use */
> > + [R_RISCV_ALIGN] = apply_r_riscv_align_rela,
> > + [R_RISCV_RVC_BRANCH] = apply_r_riscv_rvc_branch_rela,
> > + [R_RISCV_RVC_JUMP] = apply_r_riscv_rvc_jump_rela,
> > + /* 46-50 reserved for future standard use */
> > + [R_RISCV_RELAX] = apply_r_riscv_relax_rela,
> > + [R_RISCV_SUB6] = apply_r_riscv_sub6_rela,
> > + [R_RISCV_SET6] = apply_r_riscv_set6_rela,
> > + [R_RISCV_SET8] = apply_r_riscv_set8_rela,
> > + [R_RISCV_SET16] = apply_r_riscv_set16_rela,
> > + [R_RISCV_SET32] = apply_r_riscv_set32_rela,
> > + [R_RISCV_32_PCREL] = apply_r_riscv_32_pcrel_rela,
> > + [R_RISCV_IRELATIVE] = dynamic_linking_not_supported,
> > + [R_RISCV_PLT32] = apply_r_riscv_plt32_rela,
> > + [R_RISCV_SET_ULEB128] = apply_r_riscv_set_uleb128,
> > + [R_RISCV_SUB_ULEB128] = apply_r_riscv_sub_uleb128,
> > + /* 62-191 reserved for future standard use */
> > + /* 192-255 nonstandard ABI extensions */
> > };
>
> Hi Charlie,
>
> This is not a critique of this patch, but all these callbacks take a
> u32 *location and
> because of the compressed instructions this pointer may not be
> aligned, so a lot of
> the callbacks end up doing unaligned access which may fault to an
> M-mode handler on
> some platforms.
>
> I once sent a patch to fix this:
> https://lore.kernel.org/linux-riscv/20220224152456.493365-2-kernel@esmil.dk/
>
> Maybe that's something you want to look into while touching this code anyway.
>
> /Emil
Oh nice, I will pick up that patch and change the "native-endian"
wording to be "little-endian" in the commit.
- Charlie
> >
> > int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
> > @@ -348,6 +479,10 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
> > unsigned int i, type;
> > Elf_Addr v;
> > int res;
> > + bool uleb128_set_exists = false;
> > + u32 *uleb128_set_loc;
> > + unsigned long uleb128_set_sym_val;
> > +
> >
> > pr_debug("Applying relocate section %u to %u\n", relsec,
> > sechdrs[relsec].sh_info);
> > @@ -425,6 +560,28 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
> > me->name);
> > return -EINVAL;
> > }
> > + } else if (type == R_RISCV_SET_ULEB128) {
> > + if (uleb128_set_exists) {
> > + pr_err("%s: riscv psABI requires the next ULEB128 relocation to come after a R_RISCV_SET_ULEB128 is an R_RISCV_SUB_ULEB128, not another R_RISCV_SET_ULEB128.\n",
> > + me->name);
> > + return -EINVAL;
> > + }
> > + uleb128_set_exists = true;
> > + uleb128_set_loc = location;
> > + uleb128_set_sym_val =
> > + ((Elf_Sym *)sechdrs[symindex].sh_addr +
> > + ELF_RISCV_R_SYM(rel[i].r_info))
> > + ->st_value +
> > + rel[i].r_addend;
> > + } else if (type == R_RISCV_SUB_ULEB128) {
> > + if (uleb128_set_exists && uleb128_set_loc == location) {
> > + /* Calculate set and subtraction */
> > + v = uleb128_set_sym_val - v;
> > + } else {
> > + pr_err("%s: R_RISCV_SUB_ULEB128 must always be paired with the first R_RISCV_SET_ULEB128 that comes before it. PC = %p\n",
> > + me->name, location);
> > + return -EINVAL;
> > + }
> > }
> >
> > res = handler(me, location, v);
> >
> > --
> > 2.34.1
> >
> >
> > _______________________________________________
> > linux-riscv mailing list
> > linux-riscv@lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-riscv
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
WARNING: multiple messages have this Message-ID (diff)
From: Charlie Jenkins <charlie@rivosinc.com>
To: Emil Renner Berthing <emil.renner.berthing@canonical.com>
Cc: linux-riscv@lists.infradead.org, linux-mm@kvack.org,
linux-kernel@vger.kernel.org,
Eric Biederman <ebiederm@xmission.com>,
Kees Cook <keescook@chromium.org>,
Paul Walmsley <paul.walmsley@sifive.com>,
Palmer Dabbelt <palmer@dabbelt.com>,
Albert Ou <aou@eecs.berkeley.edu>
Subject: Re: [PATCH v4 1/2] riscv: Add remaining module relocations
Date: Wed, 18 Oct 2023 11:31:00 -0700 [thread overview]
Message-ID: <ZTAkZAm21O3gtA7i@ghost> (raw)
In-Reply-To: <CAJM55Z9xgyJoCX83hgwerF6SRo6yit8=0rmLzhF8Ju4TmZq3BA@mail.gmail.com>
On Wed, Oct 18, 2023 at 05:17:44AM -0700, Emil Renner Berthing wrote:
> Charlie Jenkins wrote:
> > Add all final module relocations and add error logs explaining the ones
> > that are not supported.
> >
> > Signed-off-by: Charlie Jenkins <charlie@rivosinc.com>
> > ---
> > arch/riscv/include/uapi/asm/elf.h | 5 +-
> > arch/riscv/kernel/module.c | 207 +++++++++++++++++++++++++++++++++-----
> > 2 files changed, 186 insertions(+), 26 deletions(-)
> >
> > diff --git a/arch/riscv/include/uapi/asm/elf.h b/arch/riscv/include/uapi/asm/elf.h
> > index d696d6610231..11a71b8533d5 100644
> > --- a/arch/riscv/include/uapi/asm/elf.h
> > +++ b/arch/riscv/include/uapi/asm/elf.h
> > @@ -49,6 +49,7 @@ typedef union __riscv_fp_state elf_fpregset_t;
> > #define R_RISCV_TLS_DTPREL64 9
> > #define R_RISCV_TLS_TPREL32 10
> > #define R_RISCV_TLS_TPREL64 11
> > +#define R_RISCV_IRELATIVE 58
> >
> > /* Relocation types not used by the dynamic linker */
> > #define R_RISCV_BRANCH 16
> > @@ -81,7 +82,6 @@ typedef union __riscv_fp_state elf_fpregset_t;
> > #define R_RISCV_ALIGN 43
> > #define R_RISCV_RVC_BRANCH 44
> > #define R_RISCV_RVC_JUMP 45
> > -#define R_RISCV_LUI 46
> > #define R_RISCV_GPREL_I 47
> > #define R_RISCV_GPREL_S 48
> > #define R_RISCV_TPREL_I 49
> > @@ -93,6 +93,9 @@ typedef union __riscv_fp_state elf_fpregset_t;
> > #define R_RISCV_SET16 55
> > #define R_RISCV_SET32 56
> > #define R_RISCV_32_PCREL 57
> > +#define R_RISCV_PLT32 59
> > +#define R_RISCV_SET_ULEB128 60
> > +#define R_RISCV_SUB_ULEB128 61
> >
> >
> > #endif /* _UAPI_ASM_RISCV_ELF_H */
> > diff --git a/arch/riscv/kernel/module.c b/arch/riscv/kernel/module.c
> > index 7c651d55fcbd..e860726352ac 100644
> > --- a/arch/riscv/kernel/module.c
> > +++ b/arch/riscv/kernel/module.c
> > @@ -7,6 +7,7 @@
> > #include <linux/elf.h>
> > #include <linux/err.h>
> > #include <linux/errno.h>
> > +#include <linux/kernel.h>
> > #include <linux/moduleloader.h>
> > #include <linux/vmalloc.h>
> > #include <linux/sizes.h>
> > @@ -268,6 +269,12 @@ static int apply_r_riscv_align_rela(struct module *me, u32 *location,
> > return -EINVAL;
> > }
> >
> > +static int apply_r_riscv_add8_rela(struct module *me, u32 *location, Elf_Addr v)
> > +{
> > + *(u8 *)location += (u8)v;
> > + return 0;
> > +}
> > +
> > static int apply_r_riscv_add16_rela(struct module *me, u32 *location,
> > Elf_Addr v)
> > {
> > @@ -289,6 +296,12 @@ static int apply_r_riscv_add64_rela(struct module *me, u32 *location,
> > return 0;
> > }
> >
> > +static int apply_r_riscv_sub8_rela(struct module *me, u32 *location, Elf_Addr v)
> > +{
> > + *(u8 *)location -= (u8)v;
> > + return 0;
> > +}
> > +
> > static int apply_r_riscv_sub16_rela(struct module *me, u32 *location,
> > Elf_Addr v)
> > {
> > @@ -310,31 +323,149 @@ static int apply_r_riscv_sub64_rela(struct module *me, u32 *location,
> > return 0;
> > }
> >
> > -static int (*reloc_handlers_rela[]) (struct module *me, u32 *location,
> > - Elf_Addr v) = {
> > - [R_RISCV_32] = apply_r_riscv_32_rela,
> > - [R_RISCV_64] = apply_r_riscv_64_rela,
> > - [R_RISCV_BRANCH] = apply_r_riscv_branch_rela,
> > - [R_RISCV_JAL] = apply_r_riscv_jal_rela,
> > - [R_RISCV_RVC_BRANCH] = apply_r_riscv_rvc_branch_rela,
> > - [R_RISCV_RVC_JUMP] = apply_r_riscv_rvc_jump_rela,
> > - [R_RISCV_PCREL_HI20] = apply_r_riscv_pcrel_hi20_rela,
> > - [R_RISCV_PCREL_LO12_I] = apply_r_riscv_pcrel_lo12_i_rela,
> > - [R_RISCV_PCREL_LO12_S] = apply_r_riscv_pcrel_lo12_s_rela,
> > - [R_RISCV_HI20] = apply_r_riscv_hi20_rela,
> > - [R_RISCV_LO12_I] = apply_r_riscv_lo12_i_rela,
> > - [R_RISCV_LO12_S] = apply_r_riscv_lo12_s_rela,
> > - [R_RISCV_GOT_HI20] = apply_r_riscv_got_hi20_rela,
> > - [R_RISCV_CALL_PLT] = apply_r_riscv_call_plt_rela,
> > - [R_RISCV_CALL] = apply_r_riscv_call_rela,
> > - [R_RISCV_RELAX] = apply_r_riscv_relax_rela,
> > - [R_RISCV_ALIGN] = apply_r_riscv_align_rela,
> > - [R_RISCV_ADD16] = apply_r_riscv_add16_rela,
> > - [R_RISCV_ADD32] = apply_r_riscv_add32_rela,
> > - [R_RISCV_ADD64] = apply_r_riscv_add64_rela,
> > - [R_RISCV_SUB16] = apply_r_riscv_sub16_rela,
> > - [R_RISCV_SUB32] = apply_r_riscv_sub32_rela,
> > - [R_RISCV_SUB64] = apply_r_riscv_sub64_rela,
> > +static int dynamic_linking_not_supported(struct module *me, u32 *location,
> > + Elf_Addr v)
> > +{
> > + pr_err("%s: Dynamic linking not supported in kernel modules PC = %p\n",
> > + me->name, location);
> > + return -EINVAL;
> > +}
> > +
> > +static int tls_not_supported(struct module *me, u32 *location, Elf_Addr v)
> > +{
> > + pr_err("%s: Thread local storage not supported in kernel modules PC = %p\n",
> > + me->name, location);
> > + return -EINVAL;
> > +}
> > +
> > +static int apply_r_riscv_sub6_rela(struct module *me, u32 *location, Elf_Addr v)
> > +{
> > + *(u8 *)location = (*location - ((u8)v & 0x3F)) & 0x3F;
> > + return 0;
> > +}
> > +
> > +static int apply_r_riscv_set6_rela(struct module *me, u32 *location, Elf_Addr v)
> > +{
> > + *(u8 *)location = (*(u8 *)location & 0xc0) | ((u8)v & 0x3F);
> > + return 0;
> > +}
> > +
> > +static int apply_r_riscv_set8_rela(struct module *me, u32 *location, Elf_Addr v)
> > +{
> > + *(u8 *)location = (u8)v;
> > + return 0;
> > +}
> > +
> > +static int apply_r_riscv_set16_rela(struct module *me, u32 *location,
> > + Elf_Addr v)
> > +{
> > + *(u16 *)location = (u16)v;
> > + return 0;
> > +}
> > +
> > +static int apply_r_riscv_set32_rela(struct module *me, u32 *location,
> > + Elf_Addr v)
> > +{
> > + *(u32 *)location = (u32)v;
> > + return 0;
> > +}
> > +
> > +static int apply_r_riscv_32_pcrel_rela(struct module *me, u32 *location,
> > + Elf_Addr v)
> > +{
> > + *(u32 *)location = (u32)v;
> > + return 0;
> > +}
> > +
> > +static int apply_r_riscv_plt32_rela(struct module *me, u32 *location,
> > + Elf_Addr v)
> > +{
> > + *(u32 *)location = (u32)v;
> > + return 0;
> > +}
> > +
> > +static int apply_r_riscv_set_uleb128(struct module *me, u32 *location, Elf_Addr v)
> > +{
> > + /*
> > + * Relocation is only performed if R_RISCV_SET_ULEB128 is followed by
> > + * R_RISCV_SUB_ULEB128 so do computation there
> > + */
> > + return 0;
> > +}
> > +
> > +static int apply_r_riscv_sub_uleb128(struct module *me, u32 *location, Elf_Addr v)
> > +{
> > + if (v >= 128) {
> > + pr_err("%s: uleb128 must be in [0, 127] (not %ld) at PC = %p\n",
> > + me->name, (unsigned long)v, location);
> > + return -EINVAL;
> > + }
> > +
> > + *location = v;
> > + return 0;
> > +}
> > +
> > +/*
> > + * Relocations defined in the riscv-elf-psabi-doc.
> > + * This handles static linking only.
> > + */
> > +static int (*reloc_handlers_rela[])(struct module *me, u32 *location,
> > + Elf_Addr v) = {
> > + [R_RISCV_32] = apply_r_riscv_32_rela,
> > + [R_RISCV_64] = apply_r_riscv_64_rela,
> > + [R_RISCV_RELATIVE] = dynamic_linking_not_supported,
> > + [R_RISCV_COPY] = dynamic_linking_not_supported,
> > + [R_RISCV_JUMP_SLOT] = dynamic_linking_not_supported,
> > + [R_RISCV_TLS_DTPMOD32] = dynamic_linking_not_supported,
> > + [R_RISCV_TLS_DTPMOD64] = dynamic_linking_not_supported,
> > + [R_RISCV_TLS_DTPREL32] = dynamic_linking_not_supported,
> > + [R_RISCV_TLS_DTPREL64] = dynamic_linking_not_supported,
> > + [R_RISCV_TLS_TPREL32] = dynamic_linking_not_supported,
> > + [R_RISCV_TLS_TPREL64] = dynamic_linking_not_supported,
> > + /* 12-15 undefined */
> > + [R_RISCV_BRANCH] = apply_r_riscv_branch_rela,
> > + [R_RISCV_JAL] = apply_r_riscv_jal_rela,
> > + [R_RISCV_CALL] = apply_r_riscv_call_rela,
> > + [R_RISCV_CALL_PLT] = apply_r_riscv_call_plt_rela,
> > + [R_RISCV_GOT_HI20] = apply_r_riscv_got_hi20_rela,
> > + [R_RISCV_TLS_GOT_HI20] = tls_not_supported,
> > + [R_RISCV_TLS_GD_HI20] = tls_not_supported,
> > + [R_RISCV_PCREL_HI20] = apply_r_riscv_pcrel_hi20_rela,
> > + [R_RISCV_PCREL_LO12_I] = apply_r_riscv_pcrel_lo12_i_rela,
> > + [R_RISCV_PCREL_LO12_S] = apply_r_riscv_pcrel_lo12_s_rela,
> > + [R_RISCV_HI20] = apply_r_riscv_hi20_rela,
> > + [R_RISCV_LO12_I] = apply_r_riscv_lo12_i_rela,
> > + [R_RISCV_LO12_S] = apply_r_riscv_lo12_s_rela,
> > + [R_RISCV_TPREL_HI20] = tls_not_supported,
> > + [R_RISCV_TPREL_LO12_I] = tls_not_supported,
> > + [R_RISCV_TPREL_LO12_S] = tls_not_supported,
> > + [R_RISCV_TPREL_ADD] = tls_not_supported,
> > + [R_RISCV_ADD8] = apply_r_riscv_add8_rela,
> > + [R_RISCV_ADD16] = apply_r_riscv_add16_rela,
> > + [R_RISCV_ADD32] = apply_r_riscv_add32_rela,
> > + [R_RISCV_ADD64] = apply_r_riscv_add64_rela,
> > + [R_RISCV_SUB8] = apply_r_riscv_sub8_rela,
> > + [R_RISCV_SUB16] = apply_r_riscv_sub16_rela,
> > + [R_RISCV_SUB32] = apply_r_riscv_sub32_rela,
> > + [R_RISCV_SUB64] = apply_r_riscv_sub64_rela,
> > + /* 41-42 reserved for future standard use */
> > + [R_RISCV_ALIGN] = apply_r_riscv_align_rela,
> > + [R_RISCV_RVC_BRANCH] = apply_r_riscv_rvc_branch_rela,
> > + [R_RISCV_RVC_JUMP] = apply_r_riscv_rvc_jump_rela,
> > + /* 46-50 reserved for future standard use */
> > + [R_RISCV_RELAX] = apply_r_riscv_relax_rela,
> > + [R_RISCV_SUB6] = apply_r_riscv_sub6_rela,
> > + [R_RISCV_SET6] = apply_r_riscv_set6_rela,
> > + [R_RISCV_SET8] = apply_r_riscv_set8_rela,
> > + [R_RISCV_SET16] = apply_r_riscv_set16_rela,
> > + [R_RISCV_SET32] = apply_r_riscv_set32_rela,
> > + [R_RISCV_32_PCREL] = apply_r_riscv_32_pcrel_rela,
> > + [R_RISCV_IRELATIVE] = dynamic_linking_not_supported,
> > + [R_RISCV_PLT32] = apply_r_riscv_plt32_rela,
> > + [R_RISCV_SET_ULEB128] = apply_r_riscv_set_uleb128,
> > + [R_RISCV_SUB_ULEB128] = apply_r_riscv_sub_uleb128,
> > + /* 62-191 reserved for future standard use */
> > + /* 192-255 nonstandard ABI extensions */
> > };
>
> Hi Charlie,
>
> This is not a critique of this patch, but all these callbacks take a
> u32 *location and
> because of the compressed instructions this pointer may not be
> aligned, so a lot of
> the callbacks end up doing unaligned access which may fault to an
> M-mode handler on
> some platforms.
>
> I once sent a patch to fix this:
> https://lore.kernel.org/linux-riscv/20220224152456.493365-2-kernel@esmil.dk/
>
> Maybe that's something you want to look into while touching this code anyway.
>
> /Emil
Oh nice, I will pick up that patch and change the "native-endian"
wording to be "little-endian" in the commit.
- Charlie
> >
> > int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
> > @@ -348,6 +479,10 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
> > unsigned int i, type;
> > Elf_Addr v;
> > int res;
> > + bool uleb128_set_exists = false;
> > + u32 *uleb128_set_loc;
> > + unsigned long uleb128_set_sym_val;
> > +
> >
> > pr_debug("Applying relocate section %u to %u\n", relsec,
> > sechdrs[relsec].sh_info);
> > @@ -425,6 +560,28 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
> > me->name);
> > return -EINVAL;
> > }
> > + } else if (type == R_RISCV_SET_ULEB128) {
> > + if (uleb128_set_exists) {
> > + pr_err("%s: riscv psABI requires the next ULEB128 relocation to come after a R_RISCV_SET_ULEB128 is an R_RISCV_SUB_ULEB128, not another R_RISCV_SET_ULEB128.\n",
> > + me->name);
> > + return -EINVAL;
> > + }
> > + uleb128_set_exists = true;
> > + uleb128_set_loc = location;
> > + uleb128_set_sym_val =
> > + ((Elf_Sym *)sechdrs[symindex].sh_addr +
> > + ELF_RISCV_R_SYM(rel[i].r_info))
> > + ->st_value +
> > + rel[i].r_addend;
> > + } else if (type == R_RISCV_SUB_ULEB128) {
> > + if (uleb128_set_exists && uleb128_set_loc == location) {
> > + /* Calculate set and subtraction */
> > + v = uleb128_set_sym_val - v;
> > + } else {
> > + pr_err("%s: R_RISCV_SUB_ULEB128 must always be paired with the first R_RISCV_SET_ULEB128 that comes before it. PC = %p\n",
> > + me->name, location);
> > + return -EINVAL;
> > + }
> > }
> >
> > res = handler(me, location, v);
> >
> > --
> > 2.34.1
> >
> >
> > _______________________________________________
> > linux-riscv mailing list
> > linux-riscv@lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-riscv
next prev parent reply other threads:[~2023-10-18 18:31 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-10-18 5:34 [PATCH v4 0/2] riscv: Add remaining module relocations and tests Charlie Jenkins
2023-10-18 5:34 ` Charlie Jenkins
2023-10-18 5:34 ` [PATCH v4 1/2] riscv: Add remaining module relocations Charlie Jenkins
2023-10-18 5:34 ` Charlie Jenkins
2023-10-18 12:17 ` Emil Renner Berthing
2023-10-18 12:17 ` Emil Renner Berthing
2023-10-18 18:31 ` Charlie Jenkins [this message]
2023-10-18 18:31 ` Charlie Jenkins
2023-10-18 18:38 ` Emil Renner Berthing
2023-10-18 18:38 ` Emil Renner Berthing
2023-10-18 20:19 ` Charlie Jenkins
2023-10-18 20:19 ` Charlie Jenkins
2023-10-18 20:28 ` Emil Renner Berthing
2023-10-18 20:28 ` Emil Renner Berthing
2023-10-18 18:28 ` Samuel Holland
2023-10-18 18:28 ` Samuel Holland
2023-10-18 22:19 ` Charlie Jenkins
2023-10-18 22:19 ` Charlie Jenkins
2023-10-18 18:47 ` Andreas Schwab
2023-10-18 18:47 ` Andreas Schwab
2023-10-18 22:19 ` Charlie Jenkins
2023-10-18 22:19 ` Charlie Jenkins
2023-10-18 5:34 ` [PATCH v4 2/2] riscv: Add tests for riscv module loading Charlie Jenkins
2023-10-18 5:34 ` Charlie Jenkins
2023-10-18 11:35 ` [PATCH v4 0/2] riscv: Add remaining module relocations and tests Conor Dooley
2023-10-18 11:35 ` Conor Dooley
2023-10-18 17:31 ` Charlie Jenkins
2023-10-18 17:31 ` Charlie Jenkins
2023-10-18 17:41 ` Conor Dooley
2023-10-18 17:41 ` Conor Dooley
2023-10-19 5:56 ` Björn Töpel
2023-10-19 5:56 ` Björn Töpel
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=ZTAkZAm21O3gtA7i@ghost \
--to=charlie@rivosinc.com \
--cc=aou@eecs.berkeley.edu \
--cc=ebiederm@xmission.com \
--cc=emil.renner.berthing@canonical.com \
--cc=keescook@chromium.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=linux-riscv@lists.infradead.org \
--cc=palmer@dabbelt.com \
--cc=paul.walmsley@sifive.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.