BPF List
 help / color / mirror / Atom feed
* [PATCH 0/7] riscv: Various text patching improvements
@ 2024-02-12  2:55 Samuel Holland
  2024-02-12  2:55 ` [PATCH 5/7] riscv: Pass patch_text() the length in bytes Samuel Holland
  2024-02-13 12:58 ` [PATCH 0/7] riscv: Various text patching improvements Andrea Parri
  0 siblings, 2 replies; 7+ messages in thread
From: Samuel Holland @ 2024-02-12  2:55 UTC (permalink / raw)
  To: Palmer Dabbelt
  Cc: linux-riscv, linux-kernel, Samuel Holland, Ard Biesheuvel,
	Daniel Borkmann, Jason Baron, Josh Poimboeuf, Peter Zijlstra,
	Steven Rostedt, bpf

Here are a few changes to minimize calls to stop_machine() and
flush_icache_*() in the various text patching functions, as well as
to simplify the code.


Samuel Holland (7):
  riscv: jump_label: Batch icache maintenance
  riscv: jump_label: Simplify assembly syntax
  riscv: kprobes: Use patch_text_nosync() for insn slots
  riscv: Simplify text patching loops
  riscv: Pass patch_text() the length in bytes
  riscv: Use offset_in_page() in text patching functions
  riscv: Remove extra variable in patch_text_nosync()

 arch/riscv/include/asm/jump_label.h |  4 ++-
 arch/riscv/include/asm/patch.h      |  3 +-
 arch/riscv/kernel/jump_label.c      | 16 ++++++---
 arch/riscv/kernel/patch.c           | 56 +++++++++++++----------------
 arch/riscv/kernel/probes/kprobes.c  | 20 ++++++-----
 arch/riscv/net/bpf_jit_comp64.c     |  7 ++--
 6 files changed, 56 insertions(+), 50 deletions(-)

-- 
2.43.0


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

* [PATCH 5/7] riscv: Pass patch_text() the length in bytes
  2024-02-12  2:55 [PATCH 0/7] riscv: Various text patching improvements Samuel Holland
@ 2024-02-12  2:55 ` Samuel Holland
  2024-02-19 13:04   ` Björn Töpel
  2024-02-13 12:58 ` [PATCH 0/7] riscv: Various text patching improvements Andrea Parri
  1 sibling, 1 reply; 7+ messages in thread
From: Samuel Holland @ 2024-02-12  2:55 UTC (permalink / raw)
  To: Palmer Dabbelt
  Cc: linux-riscv, linux-kernel, Samuel Holland, Daniel Borkmann, bpf

patch_text_nosync() already handles an arbitrary length of code, so this
removes a superfluous loop and reduces the number of icache flushes.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
---

 arch/riscv/include/asm/patch.h     |  2 +-
 arch/riscv/kernel/patch.c          | 15 +++++----------
 arch/riscv/kernel/probes/kprobes.c | 20 +++++++++++---------
 arch/riscv/net/bpf_jit_comp64.c    |  7 ++++---
 4 files changed, 21 insertions(+), 23 deletions(-)

diff --git a/arch/riscv/include/asm/patch.h b/arch/riscv/include/asm/patch.h
index 9f5d6e14c405..7228e266b9a1 100644
--- a/arch/riscv/include/asm/patch.h
+++ b/arch/riscv/include/asm/patch.h
@@ -9,7 +9,7 @@
 int patch_insn_write(void *addr, const void *insn, size_t len);
 int patch_text_nosync(void *addr, const void *insns, size_t len);
 int patch_text_set_nosync(void *addr, u8 c, size_t len);
-int patch_text(void *addr, u32 *insns, int ninsns);
+int patch_text(void *addr, u32 *insns, size_t len);
 
 extern int riscv_patch_in_stop_machine;
 
diff --git a/arch/riscv/kernel/patch.c b/arch/riscv/kernel/patch.c
index 7f030b46eae5..9aa0050225c0 100644
--- a/arch/riscv/kernel/patch.c
+++ b/arch/riscv/kernel/patch.c
@@ -19,7 +19,7 @@
 struct patch_insn {
 	void *addr;
 	u32 *insns;
-	int ninsns;
+	size_t len;
 	atomic_t cpu_count;
 };
 
@@ -227,15 +227,10 @@ NOKPROBE_SYMBOL(patch_text_nosync);
 static int patch_text_cb(void *data)
 {
 	struct patch_insn *patch = data;
-	unsigned long len;
-	int i, ret = 0;
+	int ret = 0;
 
 	if (atomic_inc_return(&patch->cpu_count) == num_online_cpus()) {
-		for (i = 0; ret == 0 && i < patch->ninsns; i++) {
-			len = GET_INSN_LENGTH(patch->insns[i]);
-			ret = patch_text_nosync(patch->addr + i * len,
-						&patch->insns[i], len);
-		}
+		ret = patch_text_nosync(patch->addr, patch->insns, patch->len);
 		atomic_inc(&patch->cpu_count);
 	} else {
 		while (atomic_read(&patch->cpu_count) <= num_online_cpus())
@@ -247,13 +242,13 @@ static int patch_text_cb(void *data)
 }
 NOKPROBE_SYMBOL(patch_text_cb);
 
-int patch_text(void *addr, u32 *insns, int ninsns)
+int patch_text(void *addr, u32 *insns, size_t len)
 {
 	int ret;
 	struct patch_insn patch = {
 		.addr = addr,
 		.insns = insns,
-		.ninsns = ninsns,
+		.len = len,
 		.cpu_count = ATOMIC_INIT(0),
 	};
 
diff --git a/arch/riscv/kernel/probes/kprobes.c b/arch/riscv/kernel/probes/kprobes.c
index cbf8197072bf..a64461fa715c 100644
--- a/arch/riscv/kernel/probes/kprobes.c
+++ b/arch/riscv/kernel/probes/kprobes.c
@@ -23,14 +23,14 @@ post_kprobe_handler(struct kprobe *, struct kprobe_ctlblk *, struct pt_regs *);
 
 static void __kprobes arch_prepare_ss_slot(struct kprobe *p)
 {
+	size_t len = GET_INSN_LENGTH(p->opcode);
 	u32 insn = __BUG_INSN_32;
-	unsigned long offset = GET_INSN_LENGTH(p->opcode);
 
-	p->ainsn.api.restore = (unsigned long)p->addr + offset;
+	p->ainsn.api.restore = (unsigned long)p->addr + len;
 
-	patch_text_nosync(p->ainsn.api.insn, &p->opcode, 1);
-	patch_text_nosync(p->ainsn.api.insn + offset,
-			  &insn, 1);
+	patch_text_nosync(p->ainsn.api.insn, &p->opcode, len);
+	patch_text_nosync(p->ainsn.api.insn + len,
+			  &insn, GET_INSN_LENGTH(insn));
 }
 
 static void __kprobes arch_prepare_simulate(struct kprobe *p)
@@ -117,16 +117,18 @@ void *alloc_insn_page(void)
 /* install breakpoint in text */
 void __kprobes arch_arm_kprobe(struct kprobe *p)
 {
-	u32 insn = (p->opcode & __INSN_LENGTH_MASK) == __INSN_LENGTH_32 ?
-		   __BUG_INSN_32 : __BUG_INSN_16;
+	size_t len = GET_INSN_LENGTH(p->opcode);
+	u32 insn = len == 4 ? __BUG_INSN_32 : __BUG_INSN_16;
 
-	patch_text(p->addr, &insn, 1);
+	patch_text(p->addr, &insn, len);
 }
 
 /* remove breakpoint from text */
 void __kprobes arch_disarm_kprobe(struct kprobe *p)
 {
-	patch_text(p->addr, &p->opcode, 1);
+	size_t len = GET_INSN_LENGTH(p->opcode);
+
+	patch_text(p->addr, &p->opcode, len);
 }
 
 void __kprobes arch_remove_kprobe(struct kprobe *p)
diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c
index 719a97e7edb2..43be2585f0d4 100644
--- a/arch/riscv/net/bpf_jit_comp64.c
+++ b/arch/riscv/net/bpf_jit_comp64.c
@@ -14,6 +14,7 @@
 #include "bpf_jit.h"
 
 #define RV_FENTRY_NINSNS 2
+#define RV_FENTRY_NBYTES (RV_FENTRY_NINSNS * 4)
 
 #define RV_REG_TCC RV_REG_A6
 #define RV_REG_TCC_SAVED RV_REG_S6 /* Store A6 in S6 if program do calls */
@@ -681,7 +682,7 @@ int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type poke_type,
 	if (ret)
 		return ret;
 
-	if (memcmp(ip, old_insns, RV_FENTRY_NINSNS * 4))
+	if (memcmp(ip, old_insns, RV_FENTRY_NBYTES))
 		return -EFAULT;
 
 	ret = gen_jump_or_nops(new_addr, ip, new_insns, is_call);
@@ -690,8 +691,8 @@ int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type poke_type,
 
 	cpus_read_lock();
 	mutex_lock(&text_mutex);
-	if (memcmp(ip, new_insns, RV_FENTRY_NINSNS * 4))
-		ret = patch_text(ip, new_insns, RV_FENTRY_NINSNS);
+	if (memcmp(ip, new_insns, RV_FENTRY_NBYTES))
+		ret = patch_text(ip, new_insns, RV_FENTRY_NBYTES);
 	mutex_unlock(&text_mutex);
 	cpus_read_unlock();
 
-- 
2.43.0


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

* Re: [PATCH 0/7] riscv: Various text patching improvements
  2024-02-12  2:55 [PATCH 0/7] riscv: Various text patching improvements Samuel Holland
  2024-02-12  2:55 ` [PATCH 5/7] riscv: Pass patch_text() the length in bytes Samuel Holland
@ 2024-02-13 12:58 ` Andrea Parri
  2024-02-19 12:25   ` Björn Töpel
  2024-03-27 15:32   ` Samuel Holland
  1 sibling, 2 replies; 7+ messages in thread
From: Andrea Parri @ 2024-02-13 12:58 UTC (permalink / raw)
  To: Samuel Holland
  Cc: Palmer Dabbelt, linux-riscv, linux-kernel, Ard Biesheuvel,
	Daniel Borkmann, Jason Baron, Josh Poimboeuf, Peter Zijlstra,
	Steven Rostedt, bpf, Alexandre Ghiti, Björn Töpel

Hi Samuel,

On Sun, Feb 11, 2024 at 06:55:11PM -0800, Samuel Holland wrote:
> Here are a few changes to minimize calls to stop_machine() and
> flush_icache_*() in the various text patching functions, as well as
> to simplify the code.
> 
> 
> Samuel Holland (7):
>   riscv: jump_label: Batch icache maintenance
>   riscv: jump_label: Simplify assembly syntax
>   riscv: kprobes: Use patch_text_nosync() for insn slots
>   riscv: Simplify text patching loops
>   riscv: Pass patch_text() the length in bytes
>   riscv: Use offset_in_page() in text patching functions
>   riscv: Remove extra variable in patch_text_nosync()

This does look like a nice clean-up.  Just curious (a "teach me"-like question),
how did you test these changes? kselftests, micro-benchmarks, other?

BTW, I recall a parallel work from Alex and Bjorn [1] that might have some minor
conflict with these changes; + both of them to Cc: for further sync.

  Andrea

[1] https://lore.kernel.org/lkml/20240206204607.527195-1-alexghiti@rivosinc.com/



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

* Re: [PATCH 0/7] riscv: Various text patching improvements
  2024-02-13 12:58 ` [PATCH 0/7] riscv: Various text patching improvements Andrea Parri
@ 2024-02-19 12:25   ` Björn Töpel
  2024-02-20 22:11     ` Alexandre Ghiti
  2024-03-27 15:32   ` Samuel Holland
  1 sibling, 1 reply; 7+ messages in thread
From: Björn Töpel @ 2024-02-19 12:25 UTC (permalink / raw)
  To: Andrea Parri, Samuel Holland
  Cc: Palmer Dabbelt, linux-riscv, linux-kernel, Ard Biesheuvel,
	Daniel Borkmann, Jason Baron, Josh Poimboeuf, Peter Zijlstra,
	Steven Rostedt, bpf, Alexandre Ghiti, Björn Töpel

Andrea Parri <parri.andrea@gmail.com> writes:

> Hi Samuel,
>
> On Sun, Feb 11, 2024 at 06:55:11PM -0800, Samuel Holland wrote:
>> Here are a few changes to minimize calls to stop_machine() and
>> flush_icache_*() in the various text patching functions, as well as
>> to simplify the code.
>> 
>> 
>> Samuel Holland (7):
>>   riscv: jump_label: Batch icache maintenance
>>   riscv: jump_label: Simplify assembly syntax
>>   riscv: kprobes: Use patch_text_nosync() for insn slots
>>   riscv: Simplify text patching loops
>>   riscv: Pass patch_text() the length in bytes
>>   riscv: Use offset_in_page() in text patching functions
>>   riscv: Remove extra variable in patch_text_nosync()
>
> This does look like a nice clean-up.  Just curious (a "teach me"-like question),
> how did you test these changes? kselftests, micro-benchmarks, other?
>
> BTW, I recall a parallel work from Alex and Bjorn [1] that might have some minor
> conflict with these changes; + both of them to Cc: for further sync.

Indeed! I think Alex is still working on the v2.

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

* Re: [PATCH 5/7] riscv: Pass patch_text() the length in bytes
  2024-02-12  2:55 ` [PATCH 5/7] riscv: Pass patch_text() the length in bytes Samuel Holland
@ 2024-02-19 13:04   ` Björn Töpel
  0 siblings, 0 replies; 7+ messages in thread
From: Björn Töpel @ 2024-02-19 13:04 UTC (permalink / raw)
  To: Samuel Holland, Palmer Dabbelt
  Cc: linux-riscv, linux-kernel, Samuel Holland, Daniel Borkmann, bpf

Samuel Holland <samuel.holland@sifive.com> writes:

> patch_text_nosync() already handles an arbitrary length of code, so this
> removes a superfluous loop and reduces the number of icache flushes.
>
> Signed-off-by: Samuel Holland <samuel.holland@sifive.com>

Nice!

Nit: 100 chars lines, please.

Reviewed-by: Björn Töpel <bjorn@rivosinc.com>

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

* Re: [PATCH 0/7] riscv: Various text patching improvements
  2024-02-19 12:25   ` Björn Töpel
@ 2024-02-20 22:11     ` Alexandre Ghiti
  0 siblings, 0 replies; 7+ messages in thread
From: Alexandre Ghiti @ 2024-02-20 22:11 UTC (permalink / raw)
  To: Björn Töpel
  Cc: Andrea Parri, Samuel Holland, Palmer Dabbelt, linux-riscv,
	linux-kernel, Ard Biesheuvel, Daniel Borkmann, Jason Baron,
	Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, bpf,
	Björn Töpel

On Mon, Feb 19, 2024 at 1:25 PM Björn Töpel <bjorn@kernel.org> wrote:
>
> Andrea Parri <parri.andrea@gmail.com> writes:
>
> > Hi Samuel,
> >
> > On Sun, Feb 11, 2024 at 06:55:11PM -0800, Samuel Holland wrote:
> >> Here are a few changes to minimize calls to stop_machine() and
> >> flush_icache_*() in the various text patching functions, as well as
> >> to simplify the code.
> >>
> >>
> >> Samuel Holland (7):
> >>   riscv: jump_label: Batch icache maintenance
> >>   riscv: jump_label: Simplify assembly syntax
> >>   riscv: kprobes: Use patch_text_nosync() for insn slots
> >>   riscv: Simplify text patching loops
> >>   riscv: Pass patch_text() the length in bytes
> >>   riscv: Use offset_in_page() in text patching functions
> >>   riscv: Remove extra variable in patch_text_nosync()
> >
> > This does look like a nice clean-up.  Just curious (a "teach me"-like question),
> > how did you test these changes? kselftests, micro-benchmarks, other?
> >
> > BTW, I recall a parallel work from Alex and Bjorn [1] that might have some minor
> > conflict with these changes; + both of them to Cc: for further sync.
>
> Indeed! I think Alex is still working on the v2.

Actually I was blocked by Andrea's comment about patch_map(), but it's
not related so I can spin another version soon. I'd say mine should
land first because AIA support may get into 6.9 (?) and then this
patch would be needed. In case you re-spin another version, can you
rebase on top of it? Unless you have another solution of course.

Thanks,

Alex

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

* Re: [PATCH 0/7] riscv: Various text patching improvements
  2024-02-13 12:58 ` [PATCH 0/7] riscv: Various text patching improvements Andrea Parri
  2024-02-19 12:25   ` Björn Töpel
@ 2024-03-27 15:32   ` Samuel Holland
  1 sibling, 0 replies; 7+ messages in thread
From: Samuel Holland @ 2024-03-27 15:32 UTC (permalink / raw)
  To: Andrea Parri
  Cc: Palmer Dabbelt, linux-riscv, linux-kernel, Ard Biesheuvel,
	Daniel Borkmann, Jason Baron, Josh Poimboeuf, Peter Zijlstra,
	Steven Rostedt, bpf, Alexandre Ghiti, Björn Töpel

Hi Andrea,

On 2024-02-13 6:58 AM, Andrea Parri wrote:
> On Sun, Feb 11, 2024 at 06:55:11PM -0800, Samuel Holland wrote:
>> Here are a few changes to minimize calls to stop_machine() and
>> flush_icache_*() in the various text patching functions, as well as
>> to simplify the code.
>>
>>
>> Samuel Holland (7):
>>   riscv: jump_label: Batch icache maintenance
>>   riscv: jump_label: Simplify assembly syntax
>>   riscv: kprobes: Use patch_text_nosync() for insn slots
>>   riscv: Simplify text patching loops
>>   riscv: Pass patch_text() the length in bytes
>>   riscv: Use offset_in_page() in text patching functions
>>   riscv: Remove extra variable in patch_text_nosync()
> 
> This does look like a nice clean-up.  Just curious (a "teach me"-like question),
> how did you test these changes? kselftests, micro-benchmarks, other?

For all my patches, I do boot testing on various physical boards (Unmatched, D1,
some internal hardware), plus some standard internal workloads. For
performance-related patches, I run microbenchmarks or whole-system benchmarks
(e.g. UnixBench). For this series specifically, I didn't do any extra
benchmarking, as all of the functional changes should be as fast or faster by
virtue of simply doing less work.

> BTW, I recall a parallel work from Alex and Bjorn [1] that might have some minor
> conflict with these changes; + both of them to Cc: for further sync.

As suggested by Alex, v2 of this series will be based on the latest version of
that patch.

Regards,
Samuel

> 
>   Andrea
> 
> [1] https://lore.kernel.org/lkml/20240206204607.527195-1-alexghiti@rivosinc.com/


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

end of thread, other threads:[~2024-03-27 15:32 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-02-12  2:55 [PATCH 0/7] riscv: Various text patching improvements Samuel Holland
2024-02-12  2:55 ` [PATCH 5/7] riscv: Pass patch_text() the length in bytes Samuel Holland
2024-02-19 13:04   ` Björn Töpel
2024-02-13 12:58 ` [PATCH 0/7] riscv: Various text patching improvements Andrea Parri
2024-02-19 12:25   ` Björn Töpel
2024-02-20 22:11     ` Alexandre Ghiti
2024-03-27 15:32   ` Samuel Holland

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