diff mbox series

[v3,bpf-next,5/7] x86/alternative: introduce text_poke_jit

Message ID 20220106022533.2950016-6-song@kernel.org (mailing list archive)
State Superseded
Delegated to: BPF
Headers show
Series bpf_prog_pack allocator | expand

Checks

Context Check Description
netdev/tree_selection success Clearly marked for bpf-next
netdev/fixes_present success Fixes tag not required for -next series
netdev/subject_prefix success Link
netdev/cover_letter success Series has a cover letter
netdev/patch_count success Link
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 7492 this patch: 7492
netdev/cc_maintainers warning 11 maintainers not CCed: hpa@zytor.com jpoimboe@redhat.com bp@alien8.de kpsingh@kernel.org john.fastabend@gmail.com kafai@fb.com songliubraving@fb.com dave.hansen@linux.intel.com yhs@fb.com mingo@redhat.com tglx@linutronix.de
netdev/build_clang success Errors and warnings before: 754 this patch: 754
netdev/module_param success Was 0 now: 0
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 6579 this patch: 6579
netdev/checkpatch warning CHECK: extern prototypes should be avoided in .h files WARNING: line length of 86 exceeds 80 columns
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0
bpf/vmtest-bpf-next-PR success PR summary
bpf/vmtest-bpf-next success VM_Test

Commit Message

Song Liu Jan. 6, 2022, 2:25 a.m. UTC
This will be used by BPF jit compiler to dump JITed binary to a RX huge
page, and thus allow multiple BPF programs sharing the a huge (2MB) page.

Signed-off-by: Song Liu <song@kernel.org>
---
 arch/x86/include/asm/text-patching.h |  1 +
 arch/x86/kernel/alternative.c        | 28 ++++++++++++++++++++++++++++
 2 files changed, 29 insertions(+)

Comments

Peter Zijlstra Jan. 11, 2022, 12:13 p.m. UTC | #1
On Wed, Jan 05, 2022 at 06:25:31PM -0800, Song Liu wrote:

> diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
> index 23fb4d51a5da..02c35725cc62 100644
> --- a/arch/x86/kernel/alternative.c
> +++ b/arch/x86/kernel/alternative.c
> @@ -1102,6 +1102,34 @@ void *text_poke_kgdb(void *addr, const void *opcode, size_t len)
>  	return __text_poke(addr, opcode, len);
>  }
>  
> +/**
> + * text_poke_jit - Update instructions on a live kernel by jit engine
> + * @addr: address to modify
> + * @opcode: source of the copy
> + * @len: length to copy, could be more than 2x PAGE_SIZE
> + *
> + * Only module memory taking jit text (e.g. for bpf) should be patched.
> + */

Maybe:

	text_poke_copy() - Copy instructions into (an unused part of) RX memory
	@args...

	Not safe against concurrent execution; useful for JITs to dump
	new code blocks into unused regions of RX memory. Can be used in
	conjunction with synchronize_rcu_tasks() to wait for existing
	execution to quiesce after having made sure no existing
	functions pointers are life.

or something along those lines?

> +void *text_poke_jit(void *addr, const void *opcode, size_t len)
> +{
> +	unsigned long start = (unsigned long)addr;
> +	size_t patched = 0;
> +
> +	if (WARN_ON_ONCE(core_kernel_text(start)))
> +		return NULL;
> +
> +	while (patched < len) {
> +		unsigned long ptr = start + patched;
> +		size_t s;
> +
> +		s = min_t(size_t, PAGE_SIZE * 2 - offset_in_page(ptr), len - patched);
> +
> +		__text_poke((void *)ptr, opcode + patched, s);
> +		patched += s;
> +	}
> +	return addr;
> +}
> +
>  static void do_sync_core(void *info)
>  {
>  	sync_core();
> -- 
> 2.30.2
>
Song Liu Jan. 11, 2022, 5:43 p.m. UTC | #2
> On Jan 11, 2022, at 4:13 AM, Peter Zijlstra <peterz@infradead.org> wrote:
> 
> On Wed, Jan 05, 2022 at 06:25:31PM -0800, Song Liu wrote:
> 
>> diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
>> index 23fb4d51a5da..02c35725cc62 100644
>> --- a/arch/x86/kernel/alternative.c
>> +++ b/arch/x86/kernel/alternative.c
>> @@ -1102,6 +1102,34 @@ void *text_poke_kgdb(void *addr, const void *opcode, size_t len)
>> 	return __text_poke(addr, opcode, len);
>> }
>> 
>> +/**
>> + * text_poke_jit - Update instructions on a live kernel by jit engine
>> + * @addr: address to modify
>> + * @opcode: source of the copy
>> + * @len: length to copy, could be more than 2x PAGE_SIZE
>> + *
>> + * Only module memory taking jit text (e.g. for bpf) should be patched.
>> + */
> 
> Maybe:
> 
> 	text_poke_copy() - Copy instructions into (an unused part of) RX memory
> 	@args...
> 
> 	Not safe against concurrent execution; useful for JITs to dump
> 	new code blocks into unused regions of RX memory. Can be used in
> 	conjunction with synchronize_rcu_tasks() to wait for existing
> 	execution to quiesce after having made sure no existing
> 	functions pointers are life.
> 
> or something along those lines?

This sounds good! Thanks!

Song
diff mbox series

Patch

diff --git a/arch/x86/include/asm/text-patching.h b/arch/x86/include/asm/text-patching.h
index b7421780e4e9..991058c9b4b1 100644
--- a/arch/x86/include/asm/text-patching.h
+++ b/arch/x86/include/asm/text-patching.h
@@ -44,6 +44,7 @@  extern void text_poke_early(void *addr, const void *opcode, size_t len);
 extern void *text_poke(void *addr, const void *opcode, size_t len);
 extern void text_poke_sync(void);
 extern void *text_poke_kgdb(void *addr, const void *opcode, size_t len);
+extern void *text_poke_jit(void *addr, const void *opcode, size_t len);
 extern int poke_int3_handler(struct pt_regs *regs);
 extern void text_poke_bp(void *addr, const void *opcode, size_t len, const void *emulate);
 
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
index 23fb4d51a5da..02c35725cc62 100644
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -1102,6 +1102,34 @@  void *text_poke_kgdb(void *addr, const void *opcode, size_t len)
 	return __text_poke(addr, opcode, len);
 }
 
+/**
+ * text_poke_jit - Update instructions on a live kernel by jit engine
+ * @addr: address to modify
+ * @opcode: source of the copy
+ * @len: length to copy, could be more than 2x PAGE_SIZE
+ *
+ * Only module memory taking jit text (e.g. for bpf) should be patched.
+ */
+void *text_poke_jit(void *addr, const void *opcode, size_t len)
+{
+	unsigned long start = (unsigned long)addr;
+	size_t patched = 0;
+
+	if (WARN_ON_ONCE(core_kernel_text(start)))
+		return NULL;
+
+	while (patched < len) {
+		unsigned long ptr = start + patched;
+		size_t s;
+
+		s = min_t(size_t, PAGE_SIZE * 2 - offset_in_page(ptr), len - patched);
+
+		__text_poke((void *)ptr, opcode + patched, s);
+		patched += s;
+	}
+	return addr;
+}
+
 static void do_sync_core(void *info)
 {
 	sync_core();