diff mbox series

riscv, kprobes: Stricter c.jr/c.jalr decoding

Message ID 20230102160748.1307289-1-bjorn@kernel.org (mailing list archive)
State Accepted
Commit b2d473a6019ef9a54b0156ecdb2e0398c9fa6a24
Delegated to: Palmer Dabbelt
Headers show
Series riscv, kprobes: Stricter c.jr/c.jalr decoding | expand

Checks

Context Check Description
conchuod/patch_count success Link
conchuod/cover_letter success Single patches do not need cover letters
conchuod/tree_selection success Guessed tree name to be fixes
conchuod/fixes_present success Fixes tag present in non-next series
conchuod/maintainers_pattern success MAINTAINERS pattern errors before the patch: 13 and now 13
conchuod/verify_signedoff success Signed-off-by tag matches author and committer
conchuod/kdoc success Errors and warnings before: 0 this patch: 0
conchuod/module_param success Was 0 now: 0
conchuod/alphanumeric_selects success Out of order selects before the patch: 57 and now 57
conchuod/build_rv32_defconfig success Build OK
conchuod/build_warn_rv64 success Errors and warnings before: 2054 this patch: 2054
conchuod/dtb_warn_rv64 success Errors and warnings before: 0 this patch: 0
conchuod/header_inline success No static functions without inline keyword in header files
conchuod/checkpatch success total: 0 errors, 0 warnings, 0 checks, 11 lines checked
conchuod/source_inline success Was 0 now: 0
conchuod/build_rv64_nommu_k210_defconfig success Build OK
conchuod/verify_fixes success Fixes tag looks correct
conchuod/build_rv64_nommu_virt_defconfig success Build OK

Commit Message

Björn Töpel Jan. 2, 2023, 4:07 p.m. UTC
From: Björn Töpel <bjorn@rivosinc.com>

In the compressed instruction extension, c.jr, c.jalr, c.mv, and c.add
is encoded the following way (each instruction is 16b):

---+-+-----------+-----------+--
100 0 rs1[4:0]!=0       00000 10 : c.jr
100 1 rs1[4:0]!=0       00000 10 : c.jalr
100 0  rd[4:0]!=0 rs2[4:0]!=0 10 : c.mv
100 1  rd[4:0]!=0 rs2[4:0]!=0 10 : c.add

The following logic is used to decode c.jr and c.jalr:

  insn & 0xf007 == 0x8002 => instruction is an c.jr
  insn & 0xf007 == 0x9002 => instruction is an c.jalr

When 0xf007 is used to mask the instruction, c.mv can be incorrectly
decoded as c.jr, and c.add as c.jalr.

Correct the decoding by changing the mask from 0xf007 to 0xf07f.

Fixes: c22b0bcb1dd0 ("riscv: Add kprobes supported")
Signed-off-by: Björn Töpel <bjorn@rivosinc.com>
---
 arch/riscv/kernel/probes/simulate-insn.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)


base-commit: 1b929c02afd37871d5afb9d498426f83432e71c2

Comments

Conor Dooley Jan. 2, 2023, 8:31 p.m. UTC | #1
Hey Bjorn,

On Mon, Jan 02, 2023 at 05:07:48PM +0100, Björn Töpel wrote:
> From: Björn Töpel <bjorn@rivosinc.com>
> 
> In the compressed instruction extension, c.jr, c.jalr, c.mv, and c.add
> is encoded the following way (each instruction is 16b):
> 
> ---+-+-----------+-----------+--
> 100 0 rs1[4:0]!=0       00000 10 : c.jr
> 100 1 rs1[4:0]!=0       00000 10 : c.jalr
> 100 0  rd[4:0]!=0 rs2[4:0]!=0 10 : c.mv
> 100 1  rd[4:0]!=0 rs2[4:0]!=0 10 : c.add
> 
> The following logic is used to decode c.jr and c.jalr:
> 
>   insn & 0xf007 == 0x8002 => instruction is an c.jr
>   insn & 0xf007 == 0x9002 => instruction is an c.jalr
> 
> When 0xf007 is used to mask the instruction, c.mv can be incorrectly
> decoded as c.jr, and c.add as c.jalr.
> 
> Correct the decoding by changing the mask from 0xf007 to 0xf07f.
> 
> Fixes: c22b0bcb1dd0 ("riscv: Add kprobes supported")
> Signed-off-by: Björn Töpel <bjorn@rivosinc.com>
> ---
>  arch/riscv/kernel/probes/simulate-insn.h | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/riscv/kernel/probes/simulate-insn.h b/arch/riscv/kernel/probes/simulate-insn.h
> index cb6ff7dccb92..de8474146a9b 100644
> --- a/arch/riscv/kernel/probes/simulate-insn.h
> +++ b/arch/riscv/kernel/probes/simulate-insn.h
> @@ -31,9 +31,9 @@ __RISCV_INSN_FUNCS(fence,	0x7f, 0x0f);
>  	} while (0)
>  
>  __RISCV_INSN_FUNCS(c_j,		0xe003, 0xa001);
> -__RISCV_INSN_FUNCS(c_jr,	0xf007, 0x8002);

Hmm, I wonder where the mask originally came from!
I had a look at the compressed spec, of which the version google gave to
me was v1.9 [1], and Table 1.6 in that (Instruction listing for RVC,
Quadrant 2) seems to list them all together.
Tedious it may be, but future instruction decoding bits probably need
more scrutiny as Drew found another clearly wrong bit a few weeks ago
[2].

Anyways, I checked against the doc and the new versions look good to
me. How'd you spot this, and did you check the other masks?
Reviewed-by: Conor Dooley <conor.dooley@microchip.com>

[1] - https://riscv.org/wp-content/uploads/2015/11/riscv-compressed-spec-v1.9.pdf
[2] - https://lore.kernel.org/linux-riscv/20221223221332.4127602-2-heiko@sntech.de/

> +__RISCV_INSN_FUNCS(c_jr,	0xf07f, 0x8002);
>  __RISCV_INSN_FUNCS(c_jal,	0xe003, 0x2001);
> -__RISCV_INSN_FUNCS(c_jalr,	0xf007, 0x9002);
> +__RISCV_INSN_FUNCS(c_jalr,	0xf07f, 0x9002);
>  __RISCV_INSN_FUNCS(c_beqz,	0xe003, 0xc001);
>  __RISCV_INSN_FUNCS(c_bnez,	0xe003, 0xe001);
>  __RISCV_INSN_FUNCS(c_ebreak,	0xffff, 0x9002);

Worth noting that this code is gone in riscv/for-next thanks to Heiko's
de-duplication:
https://lore.kernel.org/linux-riscv/20221223221332.4127602-7-heiko@sntech.de/

> 
> base-commit: 1b929c02afd37871d5afb9d498426f83432e71c2
> -- 
> 2.37.2
>
Björn Töpel Jan. 3, 2023, 6:44 a.m. UTC | #2
Conor Dooley <conor@kernel.org> writes:

> Hey Bjorn,
>
> On Mon, Jan 02, 2023 at 05:07:48PM +0100, Björn Töpel wrote:
>> From: Björn Töpel <bjorn@rivosinc.com>
>> 
>> In the compressed instruction extension, c.jr, c.jalr, c.mv, and c.add
>> is encoded the following way (each instruction is 16b):
>> 
>> ---+-+-----------+-----------+--
>> 100 0 rs1[4:0]!=0       00000 10 : c.jr
>> 100 1 rs1[4:0]!=0       00000 10 : c.jalr
>> 100 0  rd[4:0]!=0 rs2[4:0]!=0 10 : c.mv
>> 100 1  rd[4:0]!=0 rs2[4:0]!=0 10 : c.add
>> 
>> The following logic is used to decode c.jr and c.jalr:
>> 
>>   insn & 0xf007 == 0x8002 => instruction is an c.jr
>>   insn & 0xf007 == 0x9002 => instruction is an c.jalr
>> 
>> When 0xf007 is used to mask the instruction, c.mv can be incorrectly
>> decoded as c.jr, and c.add as c.jalr.
>> 
>> Correct the decoding by changing the mask from 0xf007 to 0xf07f.
>> 
>> Fixes: c22b0bcb1dd0 ("riscv: Add kprobes supported")
>> Signed-off-by: Björn Töpel <bjorn@rivosinc.com>
>> ---
>>  arch/riscv/kernel/probes/simulate-insn.h | 4 ++--
>>  1 file changed, 2 insertions(+), 2 deletions(-)
>> 
>> diff --git a/arch/riscv/kernel/probes/simulate-insn.h b/arch/riscv/kernel/probes/simulate-insn.h
>> index cb6ff7dccb92..de8474146a9b 100644
>> --- a/arch/riscv/kernel/probes/simulate-insn.h
>> +++ b/arch/riscv/kernel/probes/simulate-insn.h
>> @@ -31,9 +31,9 @@ __RISCV_INSN_FUNCS(fence,	0x7f, 0x0f);
>>  	} while (0)
>>  
>>  __RISCV_INSN_FUNCS(c_j,		0xe003, 0xa001);
>> -__RISCV_INSN_FUNCS(c_jr,	0xf007, 0x8002);
>
> Hmm, I wonder where the mask originally came from!

I think it's just a simple bug -- missing that "rs2" must be zero.

> I had a look at the compressed spec, of which the version google gave to
> me was v1.9 [1], and Table 1.6 in that (Instruction listing for RVC,
> Quadrant 2) seems to list them all together.
> Tedious it may be, but future instruction decoding bits probably need
> more scrutiny as Drew found another clearly wrong bit a few weeks ago
> [2].
>
> Anyways, I checked against the doc and the new versions look good to
> me. How'd you spot this, and did you check the other masks?

I got hit by it when testing the optprobe series (c.mv was rejected as
c.jr).

Skimmed the other masks quickly, but will take another look.

> Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
>
> [1] -
> https://riscv.org/wp-content/uploads/2015/11/riscv-compressed-spec-v1.9.pdf

C-ext is part of the unpriv spec:
https://github.com/riscv/riscv-isa-manual/releases

> [2] - https://lore.kernel.org/linux-riscv/20221223221332.4127602-2-heiko@sntech.de/
>
>> +__RISCV_INSN_FUNCS(c_jr,	0xf07f, 0x8002);
>>  __RISCV_INSN_FUNCS(c_jal,	0xe003, 0x2001);
>> -__RISCV_INSN_FUNCS(c_jalr,	0xf007, 0x9002);
>> +__RISCV_INSN_FUNCS(c_jalr,	0xf07f, 0x9002);
>>  __RISCV_INSN_FUNCS(c_beqz,	0xe003, 0xc001);
>>  __RISCV_INSN_FUNCS(c_bnez,	0xe003, 0xe001);
>>  __RISCV_INSN_FUNCS(c_ebreak,	0xffff, 0x9002);
>
> Worth noting that this code is gone in riscv/for-next thanks to Heiko's
> de-duplication:
> https://lore.kernel.org/linux-riscv/20221223221332.4127602-7-heiko@sntech.de/

Yay!


Björn
Guo Ren Jan. 3, 2023, 9:59 a.m. UTC | #3
Thx for catching it.

On Tue, Jan 3, 2023 at 12:07 AM Björn Töpel <bjorn@kernel.org> wrote:
>
> From: Björn Töpel <bjorn@rivosinc.com>
>
> In the compressed instruction extension, c.jr, c.jalr, c.mv, and c.add
> is encoded the following way (each instruction is 16b):
>
> ---+-+-----------+-----------+--
> 100 0 rs1[4:0]!=0       00000 10 : c.jr
> 100 1 rs1[4:0]!=0       00000 10 : c.jalr
> 100 0  rd[4:0]!=0 rs2[4:0]!=0 10 : c.mv
> 100 1  rd[4:0]!=0 rs2[4:0]!=0 10 : c.add
Yes, I forgot the c.mv & c.add effect.

Reviewed-by: Guo Ren <guoren@kernel.org>

>
> The following logic is used to decode c.jr and c.jalr:
>
>   insn & 0xf007 == 0x8002 => instruction is an c.jr
>   insn & 0xf007 == 0x9002 => instruction is an c.jalr
>
> When 0xf007 is used to mask the instruction, c.mv can be incorrectly
> decoded as c.jr, and c.add as c.jalr.
>
> Correct the decoding by changing the mask from 0xf007 to 0xf07f.
>
> Fixes: c22b0bcb1dd0 ("riscv: Add kprobes supported")
> Signed-off-by: Björn Töpel <bjorn@rivosinc.com>
> ---
>  arch/riscv/kernel/probes/simulate-insn.h | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/arch/riscv/kernel/probes/simulate-insn.h b/arch/riscv/kernel/probes/simulate-insn.h
> index cb6ff7dccb92..de8474146a9b 100644
> --- a/arch/riscv/kernel/probes/simulate-insn.h
> +++ b/arch/riscv/kernel/probes/simulate-insn.h
> @@ -31,9 +31,9 @@ __RISCV_INSN_FUNCS(fence,     0x7f, 0x0f);
>         } while (0)
>
>  __RISCV_INSN_FUNCS(c_j,                0xe003, 0xa001);
> -__RISCV_INSN_FUNCS(c_jr,       0xf007, 0x8002);
> +__RISCV_INSN_FUNCS(c_jr,       0xf07f, 0x8002);
>  __RISCV_INSN_FUNCS(c_jal,      0xe003, 0x2001);
> -__RISCV_INSN_FUNCS(c_jalr,     0xf007, 0x9002);
> +__RISCV_INSN_FUNCS(c_jalr,     0xf07f, 0x9002);
>  __RISCV_INSN_FUNCS(c_beqz,     0xe003, 0xc001);
>  __RISCV_INSN_FUNCS(c_bnez,     0xe003, 0xe001);
>  __RISCV_INSN_FUNCS(c_ebreak,   0xffff, 0x9002);
>
> base-commit: 1b929c02afd37871d5afb9d498426f83432e71c2
> --
> 2.37.2
>
Conor Dooley Jan. 3, 2023, 10:33 a.m. UTC | #4
On Tue, Jan 03, 2023 at 07:44:49AM +0100, Björn Töpel wrote:
> Conor Dooley <conor@kernel.org> writes:
> > On Mon, Jan 02, 2023 at 05:07:48PM +0100, Björn Töpel wrote:
> >> From: Björn Töpel <bjorn@rivosinc.com>
> >> diff --git a/arch/riscv/kernel/probes/simulate-insn.h b/arch/riscv/kernel/probes/simulate-insn.h
> >> index cb6ff7dccb92..de8474146a9b 100644
> >> --- a/arch/riscv/kernel/probes/simulate-insn.h
> >> +++ b/arch/riscv/kernel/probes/simulate-insn.h
> >> @@ -31,9 +31,9 @@ __RISCV_INSN_FUNCS(fence,	0x7f, 0x0f);
> >>  	} while (0)
> >>  
> >>  __RISCV_INSN_FUNCS(c_j,		0xe003, 0xa001);
> >> -__RISCV_INSN_FUNCS(c_jr,	0xf007, 0x8002);
> >
> > Hmm, I wonder where the mask originally came from!
> 
> I think it's just a simple bug -- missing that "rs2" must be zero.
> 
> > I had a look at the compressed spec, of which the version google gave to
> > me was v1.9 [1], and Table 1.6 in that (Instruction listing for RVC,
> > Quadrant 2) seems to list them all together.

> > [1] -
> > https://riscv.org/wp-content/uploads/2015/11/riscv-compressed-spec-v1.9.pdf
> 
> C-ext is part of the unpriv spec:
> https://github.com/riscv/riscv-isa-manual/releases

Yah, I was trying to see if there was some period piece which was
misleading that would have explained the mask. I looked again & the v1.7
spec doesn't have that table, but also has no reason to suggest the
current mask either. Guess it was just a mistake :)
Palmer Dabbelt Jan. 5, 2023, 10:52 p.m. UTC | #5
On Mon, 2 Jan 2023 17:07:48 +0100, Björn Töpel wrote:
> From: Björn Töpel <bjorn@rivosinc.com>
> 
> In the compressed instruction extension, c.jr, c.jalr, c.mv, and c.add
> is encoded the following way (each instruction is 16b):
> 
> ---+-+-----------+-----------+--
> 100 0 rs1[4:0]!=0       00000 10 : c.jr
> 100 1 rs1[4:0]!=0       00000 10 : c.jalr
> 100 0  rd[4:0]!=0 rs2[4:0]!=0 10 : c.mv
> 100 1  rd[4:0]!=0 rs2[4:0]!=0 10 : c.add
> 
> [...]

Applied, thanks!

[1/1] riscv, kprobes: Stricter c.jr/c.jalr decoding
      https://git.kernel.org/palmer/c/b2d473a6019e

Best regards,
patchwork-bot+linux-riscv@kernel.org Jan. 5, 2023, 11 p.m. UTC | #6
Hello:

This patch was applied to riscv/linux.git (fixes)
by Palmer Dabbelt <palmer@rivosinc.com>:

On Mon,  2 Jan 2023 17:07:48 +0100 you wrote:
> From: Björn Töpel <bjorn@rivosinc.com>
> 
> In the compressed instruction extension, c.jr, c.jalr, c.mv, and c.add
> is encoded the following way (each instruction is 16b):
> 
> ---+-+-----------+-----------+--
> 100 0 rs1[4:0]!=0       00000 10 : c.jr
> 100 1 rs1[4:0]!=0       00000 10 : c.jalr
> 100 0  rd[4:0]!=0 rs2[4:0]!=0 10 : c.mv
> 100 1  rd[4:0]!=0 rs2[4:0]!=0 10 : c.add
> 
> [...]

Here is the summary with links:
  - riscv, kprobes: Stricter c.jr/c.jalr decoding
    https://git.kernel.org/riscv/c/b2d473a6019e

You are awesome, thank you!
diff mbox series

Patch

diff --git a/arch/riscv/kernel/probes/simulate-insn.h b/arch/riscv/kernel/probes/simulate-insn.h
index cb6ff7dccb92..de8474146a9b 100644
--- a/arch/riscv/kernel/probes/simulate-insn.h
+++ b/arch/riscv/kernel/probes/simulate-insn.h
@@ -31,9 +31,9 @@  __RISCV_INSN_FUNCS(fence,	0x7f, 0x0f);
 	} while (0)
 
 __RISCV_INSN_FUNCS(c_j,		0xe003, 0xa001);
-__RISCV_INSN_FUNCS(c_jr,	0xf007, 0x8002);
+__RISCV_INSN_FUNCS(c_jr,	0xf07f, 0x8002);
 __RISCV_INSN_FUNCS(c_jal,	0xe003, 0x2001);
-__RISCV_INSN_FUNCS(c_jalr,	0xf007, 0x9002);
+__RISCV_INSN_FUNCS(c_jalr,	0xf07f, 0x9002);
 __RISCV_INSN_FUNCS(c_beqz,	0xe003, 0xc001);
 __RISCV_INSN_FUNCS(c_bnez,	0xe003, 0xe001);
 __RISCV_INSN_FUNCS(c_ebreak,	0xffff, 0x9002);