mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH bpf-next] riscv/bpf: Fix truncated immediate warning in rv_s_insn
@ 2023-07-27  2:49 Luke Nelson
  2023-07-27  7:42 ` Pu Lehui
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Luke Nelson @ 2023-07-27  2:49 UTC (permalink / raw)
  To: bpf
  Cc: Luke Nelson, kernel test robot, Xi Wang, Daniel Borkmann,
	Alexei Starovoitov, Andrii Nakryiko, Martin KaFai Lau, Song Liu,
	Yonghong Song, John Fastabend, KP Singh, Stanislav Fomichev,
	Hao Luo, Jiri Olsa, Björn Töpel, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, linux-riscv, linux-kernel

Sparse warns that a cast in rv_s_insn truncates bits from the constant
0x7ff to 0xff.  The warning originates from the use of a constant offset
of -8 in a store instruction in bpf_jit_comp64.c:

  emit(rv_sd(RV_REG_SP, -8, RV_REG_RA), &ctx);

rv_sd then calls rv_s_insn, with imm11_0 equal to (u16)(-8), or 0xfff8.

Here's the current implementation of rv_s_insn:

  static inline u32 rv_s_insn(u16 imm11_0, u8 rs2, u8 rs1, u8 funct3, u8 opcode)
  {
          u8 imm11_5 = imm11_0 >> 5, imm4_0 = imm11_0 & 0x1f;

          return (imm11_5 << 25) | (rs2 << 20) | (rs1 << 15) | (funct3 << 12) |
                 (imm4_0 << 7) | opcode;
  }

imm11_0 is a signed 12-bit immediate offset of the store instruction. The
instruction encoding requires splitting the immediate into bits 11:5 and
bits 4:0. In this case, imm11_0 >> 5 = 0x7ff, which then gets truncated
to 0xff when cast to u8, causing the warning from sparse. However, this is
not actually an issue because the immediate offset is signed---truncating
upper bits that are all set to 1 has no effect on the value of the
immediate.

There is another subtle quirk with this code, which is imm11_5 is
supposed to be the upper 7 bits of the 12-bit signed immediate, but its
type is u8 with no explicit mask to select out only the bottom 7 bits.
This happens to be okay here because imm11_5 is the left-most field in
the instruction and the "extra" bit will be shifted out when imm11_5 is
shifted left by 25.

This commit fixes the warning by changing the type of imm11_5 and imm4_0
to be u32 instead of u8, and adding an explicit mask to compute imm11_5
instead of relying on truncation + shifting.

Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202307260704.dUElCrWU-lkp@intel.com/
In-Reply-To: <202307260704.dUElCrWU-lkp@intel.com>
Signed-off-by: Luke Nelson <luke.r.nels@gmail.com>
Cc: Xi Wang <xi.wang@gmail.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
---
 arch/riscv/net/bpf_jit.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/riscv/net/bpf_jit.h b/arch/riscv/net/bpf_jit.h
index 2717f5490428..e159c6e3ff43 100644
--- a/arch/riscv/net/bpf_jit.h
+++ b/arch/riscv/net/bpf_jit.h
@@ -238,7 +238,7 @@ static inline u32 rv_i_insn(u16 imm11_0, u8 rs1, u8 funct3, u8 rd, u8 opcode)

 static inline u32 rv_s_insn(u16 imm11_0, u8 rs2, u8 rs1, u8 funct3, u8 opcode)
 {
-	u8 imm11_5 = imm11_0 >> 5, imm4_0 = imm11_0 & 0x1f;
+	u32 imm11_5 = (imm11_0 >> 5) & 0x7f, imm4_0 = imm11_0 & 0x1f;

 	return (imm11_5 << 25) | (rs2 << 20) | (rs1 << 15) | (funct3 << 12) |
 		(imm4_0 << 7) | opcode;
--
2.34.1


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH bpf-next] riscv/bpf: Fix truncated immediate warning in rv_s_insn
  2023-07-27  2:49 [PATCH bpf-next] riscv/bpf: Fix truncated immediate warning in rv_s_insn Luke Nelson
@ 2023-07-27  7:42 ` Pu Lehui
  2023-08-08 16:08   ` Luke Nelson
  2023-07-27  8:08 ` Pu Lehui
  2023-08-14 12:34 ` Björn Töpel
  2 siblings, 1 reply; 6+ messages in thread
From: Pu Lehui @ 2023-07-27  7:42 UTC (permalink / raw)
  To: Luke Nelson, bpf
  Cc: Luke Nelson, kernel test robot, Xi Wang, Daniel Borkmann,
	Alexei Starovoitov, Andrii Nakryiko, Martin KaFai Lau, Song Liu,
	Yonghong Song, John Fastabend, KP Singh, Stanislav Fomichev,
	Hao Luo, Jiri Olsa, Björn Töpel, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, linux-riscv, linux-kernel



On 2023/7/27 10:49, Luke Nelson wrote:
> Sparse warns that a cast in rv_s_insn truncates bits from the constant
> 0x7ff to 0xff.  The warning originates from the use of a constant offset
> of -8 in a store instruction in bpf_jit_comp64.c:
> 
>    emit(rv_sd(RV_REG_SP, -8, RV_REG_RA), &ctx);
> 
> rv_sd then calls rv_s_insn, with imm11_0 equal to (u16)(-8), or 0xfff8.
> 
> Here's the current implementation of rv_s_insn:
> 
>    static inline u32 rv_s_insn(u16 imm11_0, u8 rs2, u8 rs1, u8 funct3, u8 opcode)
>    {
>            u8 imm11_5 = imm11_0 >> 5, imm4_0 = imm11_0 & 0x1f;
> 
>            return (imm11_5 << 25) | (rs2 << 20) | (rs1 << 15) | (funct3 << 12) |
>                   (imm4_0 << 7) | opcode;
>    }
> 
> imm11_0 is a signed 12-bit immediate offset of the store instruction. The
> instruction encoding requires splitting the immediate into bits 11:5 and
> bits 4:0. In this case, imm11_0 >> 5 = 0x7ff, which then gets truncated
> to 0xff when cast to u8, causing the warning from sparse. However, this is
> not actually an issue because the immediate offset is signed---truncating
> upper bits that are all set to 1 has no effect on the value of the
> immediate.
> 
> There is another subtle quirk with this code, which is imm11_5 is
> supposed to be the upper 7 bits of the 12-bit signed immediate, but its
> type is u8 with no explicit mask to select out only the bottom 7 bits.
> This happens to be okay here because imm11_5 is the left-most field in
> the instruction and the "extra" bit will be shifted out when imm11_5 is
> shifted left by 25.
> 
> This commit fixes the warning by changing the type of imm11_5 and imm4_0
> to be u32 instead of u8, and adding an explicit mask to compute imm11_5
> instead of relying on truncation + shifting.
> 
> Reported-by: kernel test robot <lkp@intel.com>
> Closes: https://lore.kernel.org/oe-kbuild-all/202307260704.dUElCrWU-lkp@intel.com/
> In-Reply-To: <202307260704.dUElCrWU-lkp@intel.com>
> Signed-off-by: Luke Nelson <luke.r.nels@gmail.com>
> Cc: Xi Wang <xi.wang@gmail.com>
> Cc: Daniel Borkmann <daniel@iogearbox.net>
> ---
>   arch/riscv/net/bpf_jit.h | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/riscv/net/bpf_jit.h b/arch/riscv/net/bpf_jit.h
> index 2717f5490428..e159c6e3ff43 100644
> --- a/arch/riscv/net/bpf_jit.h
> +++ b/arch/riscv/net/bpf_jit.h
> @@ -238,7 +238,7 @@ static inline u32 rv_i_insn(u16 imm11_0, u8 rs1, u8 funct3, u8 rd, u8 opcode)
> 
>   static inline u32 rv_s_insn(u16 imm11_0, u8 rs2, u8 rs1, u8 funct3, u8 opcode)
>   {
> -	u8 imm11_5 = imm11_0 >> 5, imm4_0 = imm11_0 & 0x1f;
> +	u32 imm11_5 = (imm11_0 >> 5) & 0x7f, imm4_0 = imm11_0 & 0x1f;

Hi Luke,

keep u8 and add 0x7f explicit mask should work. I ran the repro case and 
it can silence the warning.

>
>   	return (imm11_5 << 25) | (rs2 << 20) | (rs1 << 15) | (funct3 << 12) |
>   		(imm4_0 << 7) | opcode;
> --
> 2.34.1
> 
> 

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH bpf-next] riscv/bpf: Fix truncated immediate warning in rv_s_insn
  2023-07-27  2:49 [PATCH bpf-next] riscv/bpf: Fix truncated immediate warning in rv_s_insn Luke Nelson
  2023-07-27  7:42 ` Pu Lehui
@ 2023-07-27  8:08 ` Pu Lehui
  2023-08-14 12:34 ` Björn Töpel
  2 siblings, 0 replies; 6+ messages in thread
From: Pu Lehui @ 2023-07-27  8:08 UTC (permalink / raw)
  To: Luke Nelson, bpf
  Cc: Luke Nelson, kernel test robot, Xi Wang, Daniel Borkmann,
	Alexei Starovoitov, Andrii Nakryiko, Martin KaFai Lau, Song Liu,
	Yonghong Song, John Fastabend, KP Singh, Stanislav Fomichev,
	Hao Luo, Jiri Olsa, Björn Töpel, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, linux-riscv, linux-kernel

Nit: maybe use "riscv, bpf" for the subject will look nice for the 
riscv-bpf git log tree.

On 2023/7/27 10:49, Luke Nelson wrote:
> Sparse warns that a cast in rv_s_insn truncates bits from the constant
> 0x7ff to 0xff.  The warning originates from the use of a constant offset
> of -8 in a store instruction in bpf_jit_comp64.c:
> 
>    emit(rv_sd(RV_REG_SP, -8, RV_REG_RA), &ctx);
> 
> rv_sd then calls rv_s_insn, with imm11_0 equal to (u16)(-8), or 0xfff8.
> 
> Here's the current implementation of rv_s_insn:
> 
>    static inline u32 rv_s_insn(u16 imm11_0, u8 rs2, u8 rs1, u8 funct3, u8 opcode)
>    {
>            u8 imm11_5 = imm11_0 >> 5, imm4_0 = imm11_0 & 0x1f;
> 
>            return (imm11_5 << 25) | (rs2 << 20) | (rs1 << 15) | (funct3 << 12) |
>                   (imm4_0 << 7) | opcode;
>    }
> 
> imm11_0 is a signed 12-bit immediate offset of the store instruction. The
> instruction encoding requires splitting the immediate into bits 11:5 and
> bits 4:0. In this case, imm11_0 >> 5 = 0x7ff, which then gets truncated
> to 0xff when cast to u8, causing the warning from sparse. However, this is
> not actually an issue because the immediate offset is signed---truncating
> upper bits that are all set to 1 has no effect on the value of the
> immediate.
> 
> There is another subtle quirk with this code, which is imm11_5 is
> supposed to be the upper 7 bits of the 12-bit signed immediate, but its
> type is u8 with no explicit mask to select out only the bottom 7 bits.
> This happens to be okay here because imm11_5 is the left-most field in
> the instruction and the "extra" bit will be shifted out when imm11_5 is
> shifted left by 25.
> 
> This commit fixes the warning by changing the type of imm11_5 and imm4_0
> to be u32 instead of u8, and adding an explicit mask to compute imm11_5
> instead of relying on truncation + shifting.
> 
> Reported-by: kernel test robot <lkp@intel.com>
> Closes: https://lore.kernel.org/oe-kbuild-all/202307260704.dUElCrWU-lkp@intel.com/
> In-Reply-To: <202307260704.dUElCrWU-lkp@intel.com>
> Signed-off-by: Luke Nelson <luke.r.nels@gmail.com>
> Cc: Xi Wang <xi.wang@gmail.com>
> Cc: Daniel Borkmann <daniel@iogearbox.net>
> ---
>   arch/riscv/net/bpf_jit.h | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/riscv/net/bpf_jit.h b/arch/riscv/net/bpf_jit.h
> index 2717f5490428..e159c6e3ff43 100644
> --- a/arch/riscv/net/bpf_jit.h
> +++ b/arch/riscv/net/bpf_jit.h
> @@ -238,7 +238,7 @@ static inline u32 rv_i_insn(u16 imm11_0, u8 rs1, u8 funct3, u8 rd, u8 opcode)
> 
>   static inline u32 rv_s_insn(u16 imm11_0, u8 rs2, u8 rs1, u8 funct3, u8 opcode)
>   {
> -	u8 imm11_5 = imm11_0 >> 5, imm4_0 = imm11_0 & 0x1f;
> +	u32 imm11_5 = (imm11_0 >> 5) & 0x7f, imm4_0 = imm11_0 & 0x1f;
> 
>   	return (imm11_5 << 25) | (rs2 << 20) | (rs1 << 15) | (funct3 << 12) |
>   		(imm4_0 << 7) | opcode;
> --
> 2.34.1
> 
> 

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH bpf-next] riscv/bpf: Fix truncated immediate warning in rv_s_insn
  2023-07-27  7:42 ` Pu Lehui
@ 2023-08-08 16:08   ` Luke Nelson
  2023-08-09  2:32     ` Pu Lehui
  0 siblings, 1 reply; 6+ messages in thread
From: Luke Nelson @ 2023-08-08 16:08 UTC (permalink / raw)
  To: Pu Lehui
  Cc: bpf, kernel test robot, Xi Wang, Daniel Borkmann,
	Alexei Starovoitov, Andrii Nakryiko, Martin KaFai Lau, Song Liu,
	Yonghong Song, John Fastabend, KP Singh, Stanislav Fomichev,
	Hao Luo, Jiri Olsa, Björn Töpel, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, linux-riscv, linux-kernel


>>  static inline u32 rv_s_insn(u16 imm11_0, u8 rs2, u8 rs1, u8 funct3, u8 opcode)
>>  {
>> - u8 imm11_5 = imm11_0 >> 5, imm4_0 = imm11_0 & 0x1f;
>> + u32 imm11_5 = (imm11_0 >> 5) & 0x7f, imm4_0 = imm11_0 & 0x1f;
> 
> Hi Luke,
> 
> keep u8 and add 0x7f explicit mask should work. I ran the repro case and it can silence the warning.
> 
>> 
>>   return (imm11_5 << 25) | (rs2 << 20) | (rs1 << 15) | (funct3 << 12) |
>>   (imm4_0 << 7) | opcode;

That does fix the warning, but I think explicitly declaring imm11_5
as u32 is more clear here than the current code which relies on
implicit promotion of imm11_5 from u8 to signed int in the expression
(imm11_5 << 25).

Because of the promotion to signed int, (imm11_5 << 25) is technically
signed overflow and undefined behavior whenever the shift changes
the value in the sign bit. In practice, this isn't an issue; both
because the kernel is compiled with -fno-strict-overflow, but also
because GCC documentation explicitly states that "GCC does not use
the latitude given in C99 and C11 only to treat certain aspects of
signed '<<' as undefined" [1].

Though it may not be an issue in practice, since I'm touching this
line anyways to fix the warning, I think it makes sense to update
the type of imm11_5 to be u32 at the same time.

> Nit: maybe use "riscv, bpf" for the subject will look nice for the riscv-bpf git log tree.

Sure, I can send out a new revision with an updated subject line.

- Luke


[1]: https://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH bpf-next] riscv/bpf: Fix truncated immediate warning in rv_s_insn
  2023-08-08 16:08   ` Luke Nelson
@ 2023-08-09  2:32     ` Pu Lehui
  0 siblings, 0 replies; 6+ messages in thread
From: Pu Lehui @ 2023-08-09  2:32 UTC (permalink / raw)
  To: Luke Nelson
  Cc: bpf, kernel test robot, Xi Wang, Daniel Borkmann,
	Alexei Starovoitov, Andrii Nakryiko, Martin KaFai Lau, Song Liu,
	Yonghong Song, John Fastabend, KP Singh, Stanislav Fomichev,
	Hao Luo, Jiri Olsa, Björn Töpel, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, linux-riscv, linux-kernel



On 2023/8/9 0:08, Luke Nelson wrote:
> 
>>>   static inline u32 rv_s_insn(u16 imm11_0, u8 rs2, u8 rs1, u8 funct3, u8 opcode)
>>>   {
>>> - u8 imm11_5 = imm11_0 >> 5, imm4_0 = imm11_0 & 0x1f;
>>> + u32 imm11_5 = (imm11_0 >> 5) & 0x7f, imm4_0 = imm11_0 & 0x1f;
>>
>> Hi Luke,
>>
>> keep u8 and add 0x7f explicit mask should work. I ran the repro case and it can silence the warning.
>>
>>>
>>>    return (imm11_5 << 25) | (rs2 << 20) | (rs1 << 15) | (funct3 << 12) |
>>>    (imm4_0 << 7) | opcode;
> 

Hi Luke,

Thank for more detailed explanation.

> That does fix the warning, but I think explicitly declaring imm11_5
> as u32 is more clear here than the current code which relies on
> implicit promotion of imm11_5 from u8 to signed int in the expression
> (imm11_5 << 25).
> 
> Because of the promotion to signed int, (imm11_5 << 25) is technically
> signed overflow and undefined behavior whenever the shift changes
> the value in the sign bit. In practice, this isn't an issue; both
> because the kernel is compiled with -fno-strict-overflow, but also
> because GCC documentation explicitly states that "GCC does not use
> the latitude given in C99 and C11 only to treat certain aspects of
> signed '<<' as undefined" [1].
> 
> Though it may not be an issue in practice, since I'm touching this
> line anyways to fix the warning, I think it makes sense to update
> the type of imm11_5 to be u32 at the same time.
> 

Agree. But this inconsistency looks weird, i.e. imm11_5 change to u32 
while rs2, rs1 and funct3 still u8. Anyway, our primary goal is to 
silence the sparse warning, and the current patch looks good to me. 
Let's go ahead.

Feel free to add:
Reviewed-by: Pu Lehui <pulehui@huawei.com>

>> Nit: maybe use "riscv, bpf" for the subject will look nice for the riscv-bpf git log tree.
> 
> Sure, I can send out a new revision with an updated subject line.
> 
> - Luke
> 
> 
> [1]: https://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH bpf-next] riscv/bpf: Fix truncated immediate warning in rv_s_insn
  2023-07-27  2:49 [PATCH bpf-next] riscv/bpf: Fix truncated immediate warning in rv_s_insn Luke Nelson
  2023-07-27  7:42 ` Pu Lehui
  2023-07-27  8:08 ` Pu Lehui
@ 2023-08-14 12:34 ` Björn Töpel
  2 siblings, 0 replies; 6+ messages in thread
From: Björn Töpel @ 2023-08-14 12:34 UTC (permalink / raw)
  To: Luke Nelson, bpf
  Cc: Luke Nelson, kernel test robot, Xi Wang, Daniel Borkmann,
	Alexei Starovoitov, Andrii Nakryiko, Martin KaFai Lau, Song Liu,
	Yonghong Song, John Fastabend, KP Singh, Stanislav Fomichev,
	Hao Luo, Jiri Olsa, Paul Walmsley, Palmer Dabbelt, Albert Ou,
	linux-riscv, linux-kernel

Luke Nelson <lukenels@cs.washington.edu> writes:

> Sparse warns that a cast in rv_s_insn truncates bits from the constant
> 0x7ff to 0xff.  The warning originates from the use of a constant offset
> of -8 in a store instruction in bpf_jit_comp64.c:
>
>   emit(rv_sd(RV_REG_SP, -8, RV_REG_RA), &ctx);
>
> rv_sd then calls rv_s_insn, with imm11_0 equal to (u16)(-8), or 0xfff8.
>
> Here's the current implementation of rv_s_insn:
>
>   static inline u32 rv_s_insn(u16 imm11_0, u8 rs2, u8 rs1, u8 funct3, u8 opcode)
>   {
>           u8 imm11_5 = imm11_0 >> 5, imm4_0 = imm11_0 & 0x1f;
>
>           return (imm11_5 << 25) | (rs2 << 20) | (rs1 << 15) | (funct3 << 12) |
>                  (imm4_0 << 7) | opcode;
>   }
>
> imm11_0 is a signed 12-bit immediate offset of the store instruction. The
> instruction encoding requires splitting the immediate into bits 11:5 and
> bits 4:0. In this case, imm11_0 >> 5 = 0x7ff, which then gets truncated
> to 0xff when cast to u8, causing the warning from sparse. However, this is
> not actually an issue because the immediate offset is signed---truncating
> upper bits that are all set to 1 has no effect on the value of the
> immediate.
>
> There is another subtle quirk with this code, which is imm11_5 is
> supposed to be the upper 7 bits of the 12-bit signed immediate, but its
> type is u8 with no explicit mask to select out only the bottom 7 bits.
> This happens to be okay here because imm11_5 is the left-most field in
> the instruction and the "extra" bit will be shifted out when imm11_5 is
> shifted left by 25.
>
> This commit fixes the warning by changing the type of imm11_5 and imm4_0
> to be u32 instead of u8, and adding an explicit mask to compute imm11_5
> instead of relying on truncation + shifting.
>
> Reported-by: kernel test robot <lkp@intel.com>
> Closes: https://lore.kernel.org/oe-kbuild-all/202307260704.dUElCrWU-lkp@intel.com/
> In-Reply-To: <202307260704.dUElCrWU-lkp@intel.com>
> Signed-off-by: Luke Nelson <luke.r.nels@gmail.com>
> Cc: Xi Wang <xi.wang@gmail.com>
> Cc: Daniel Borkmann <daniel@iogearbox.net>


Thanks, Luke!

Acked-by: Björn Töpel <bjorn@kernel.org>

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2023-08-14 12:34 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-07-27  2:49 [PATCH bpf-next] riscv/bpf: Fix truncated immediate warning in rv_s_insn Luke Nelson
2023-07-27  7:42 ` Pu Lehui
2023-08-08 16:08   ` Luke Nelson
2023-08-09  2:32     ` Pu Lehui
2023-07-27  8:08 ` Pu Lehui
2023-08-14 12:34 ` Björn Töpel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®