From: Puranjay Mohan <puranjay12@gmail.com>
To: paul.walmsley@sifive.com, palmer@dabbelt.com,
aou@eecs.berkeley.edu, pulehui@huawei.com,
conor.dooley@microchip.com, ast@kernel.org, daniel@iogearbox.net,
andrii@kernel.org, martin.lau@linux.dev, song@kernel.org,
yhs@fb.com, kpsingh@kernel.org, bjorn@kernel.org,
bpf@vger.kernel.org, linux-riscv@lists.infradead.org,
linux-kernel@vger.kernel.org
Cc: puranjay12@gmail.com
Subject: [PATCH bpf-next v3 1/3] riscv: extend patch_text_nosync() for multiple pages
Date: Mon, 28 Aug 2023 16:59:56 +0000 [thread overview]
Message-ID: <20230828165958.1714079-2-puranjay12@gmail.com> (raw)
In-Reply-To: <20230828165958.1714079-1-puranjay12@gmail.com>
The patch_insn_write() function currently doesn't work for multiple pages
of instructions, therefore patch_text_nosync() will fail with a page fault
if called with lengths spanning multiple pages.
This commit extends the patch_insn_write() function to support multiple
pages by copying at max 2 pages at a time in a loop. This implementation
is similar to text_poke_copy() function of x86.
Signed-off-by: Puranjay Mohan <puranjay12@gmail.com>
Reviewed-by: Björn Töpel <bjorn@rivosinc.com>
---
arch/riscv/kernel/patch.c | 37 ++++++++++++++++++++++++++++++++-----
1 file changed, 32 insertions(+), 5 deletions(-)
diff --git a/arch/riscv/kernel/patch.c b/arch/riscv/kernel/patch.c
index 575e71d6c8ae..2c97e246f4dc 100644
--- a/arch/riscv/kernel/patch.c
+++ b/arch/riscv/kernel/patch.c
@@ -53,12 +53,18 @@ static void patch_unmap(int fixmap)
}
NOKPROBE_SYMBOL(patch_unmap);
-static int patch_insn_write(void *addr, const void *insn, size_t len)
+static int __patch_insn_write(void *addr, const void *insn, size_t len)
{
void *waddr = addr;
bool across_pages = (((uintptr_t) addr & ~PAGE_MASK) + len) > PAGE_SIZE;
int ret;
+ /*
+ * Only two pages can be mapped at a time for writing.
+ */
+ if (len + offset_in_page(addr) > 2 * PAGE_SIZE)
+ return -EINVAL;
+
/*
* Before reaching here, it was expected to lock the text_mutex
* already, so we don't need to give another lock here and could
@@ -74,7 +80,7 @@ static int patch_insn_write(void *addr, const void *insn, size_t len)
lockdep_assert_held(&text_mutex);
if (across_pages)
- patch_map(addr + len, FIX_TEXT_POKE1);
+ patch_map(addr + PAGE_SIZE, FIX_TEXT_POKE1);
waddr = patch_map(addr, FIX_TEXT_POKE0);
@@ -87,15 +93,36 @@ static int patch_insn_write(void *addr, const void *insn, size_t len)
return ret;
}
-NOKPROBE_SYMBOL(patch_insn_write);
+NOKPROBE_SYMBOL(__patch_insn_write);
#else
-static int patch_insn_write(void *addr, const void *insn, size_t len)
+static int __patch_insn_write(void *addr, const void *insn, size_t len)
{
return copy_to_kernel_nofault(addr, insn, len);
}
-NOKPROBE_SYMBOL(patch_insn_write);
+NOKPROBE_SYMBOL(__patch_insn_write);
#endif /* CONFIG_MMU */
+static int patch_insn_write(void *addr, const void *insn, size_t len)
+{
+ size_t patched = 0;
+ size_t size;
+ int ret = 0;
+
+ /*
+ * Copy the instructions to the destination address, two pages at a time
+ * because __patch_insn_write() can only handle len <= 2 * PAGE_SIZE.
+ */
+ while (patched < len && !ret) {
+ size = min_t(size_t, PAGE_SIZE * 2 - offset_in_page(addr + patched), len - patched);
+ ret = __patch_insn_write(addr + patched, insn + patched, size);
+
+ patched += size;
+ }
+
+ return ret;
+}
+NOKPROBE_SYMBOL(patch_insn_write);
+
int patch_text_nosync(void *addr, const void *insns, size_t len)
{
u32 *tp = addr;
--
2.40.1
WARNING: multiple messages have this Message-ID (diff)
From: Puranjay Mohan <puranjay12@gmail.com>
To: paul.walmsley@sifive.com, palmer@dabbelt.com,
aou@eecs.berkeley.edu, pulehui@huawei.com,
conor.dooley@microchip.com, ast@kernel.org, daniel@iogearbox.net,
andrii@kernel.org, martin.lau@linux.dev, song@kernel.org,
yhs@fb.com, kpsingh@kernel.org, bjorn@kernel.org,
bpf@vger.kernel.org, linux-riscv@lists.infradead.org,
linux-kernel@vger.kernel.org
Cc: puranjay12@gmail.com
Subject: [PATCH bpf-next v3 1/3] riscv: extend patch_text_nosync() for multiple pages
Date: Mon, 28 Aug 2023 16:59:56 +0000 [thread overview]
Message-ID: <20230828165958.1714079-2-puranjay12@gmail.com> (raw)
In-Reply-To: <20230828165958.1714079-1-puranjay12@gmail.com>
The patch_insn_write() function currently doesn't work for multiple pages
of instructions, therefore patch_text_nosync() will fail with a page fault
if called with lengths spanning multiple pages.
This commit extends the patch_insn_write() function to support multiple
pages by copying at max 2 pages at a time in a loop. This implementation
is similar to text_poke_copy() function of x86.
Signed-off-by: Puranjay Mohan <puranjay12@gmail.com>
Reviewed-by: Björn Töpel <bjorn@rivosinc.com>
---
arch/riscv/kernel/patch.c | 37 ++++++++++++++++++++++++++++++++-----
1 file changed, 32 insertions(+), 5 deletions(-)
diff --git a/arch/riscv/kernel/patch.c b/arch/riscv/kernel/patch.c
index 575e71d6c8ae..2c97e246f4dc 100644
--- a/arch/riscv/kernel/patch.c
+++ b/arch/riscv/kernel/patch.c
@@ -53,12 +53,18 @@ static void patch_unmap(int fixmap)
}
NOKPROBE_SYMBOL(patch_unmap);
-static int patch_insn_write(void *addr, const void *insn, size_t len)
+static int __patch_insn_write(void *addr, const void *insn, size_t len)
{
void *waddr = addr;
bool across_pages = (((uintptr_t) addr & ~PAGE_MASK) + len) > PAGE_SIZE;
int ret;
+ /*
+ * Only two pages can be mapped at a time for writing.
+ */
+ if (len + offset_in_page(addr) > 2 * PAGE_SIZE)
+ return -EINVAL;
+
/*
* Before reaching here, it was expected to lock the text_mutex
* already, so we don't need to give another lock here and could
@@ -74,7 +80,7 @@ static int patch_insn_write(void *addr, const void *insn, size_t len)
lockdep_assert_held(&text_mutex);
if (across_pages)
- patch_map(addr + len, FIX_TEXT_POKE1);
+ patch_map(addr + PAGE_SIZE, FIX_TEXT_POKE1);
waddr = patch_map(addr, FIX_TEXT_POKE0);
@@ -87,15 +93,36 @@ static int patch_insn_write(void *addr, const void *insn, size_t len)
return ret;
}
-NOKPROBE_SYMBOL(patch_insn_write);
+NOKPROBE_SYMBOL(__patch_insn_write);
#else
-static int patch_insn_write(void *addr, const void *insn, size_t len)
+static int __patch_insn_write(void *addr, const void *insn, size_t len)
{
return copy_to_kernel_nofault(addr, insn, len);
}
-NOKPROBE_SYMBOL(patch_insn_write);
+NOKPROBE_SYMBOL(__patch_insn_write);
#endif /* CONFIG_MMU */
+static int patch_insn_write(void *addr, const void *insn, size_t len)
+{
+ size_t patched = 0;
+ size_t size;
+ int ret = 0;
+
+ /*
+ * Copy the instructions to the destination address, two pages at a time
+ * because __patch_insn_write() can only handle len <= 2 * PAGE_SIZE.
+ */
+ while (patched < len && !ret) {
+ size = min_t(size_t, PAGE_SIZE * 2 - offset_in_page(addr + patched), len - patched);
+ ret = __patch_insn_write(addr + patched, insn + patched, size);
+
+ patched += size;
+ }
+
+ return ret;
+}
+NOKPROBE_SYMBOL(patch_insn_write);
+
int patch_text_nosync(void *addr, const void *insns, size_t len)
{
u32 *tp = addr;
--
2.40.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-08-28 17:00 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-08-28 16:59 [PATCH bpf-next v3 0/3] bpf, riscv: use BPF prog pack allocator in BPF JIT Puranjay Mohan
2023-08-28 16:59 ` Puranjay Mohan
2023-08-28 16:59 ` Puranjay Mohan [this message]
2023-08-28 16:59 ` [PATCH bpf-next v3 1/3] riscv: extend patch_text_nosync() for multiple pages Puranjay Mohan
2023-08-29 2:49 ` Pu Lehui
2023-08-29 2:49 ` Pu Lehui
2023-08-28 16:59 ` [PATCH bpf-next v3 2/3] riscv: implement a memset like function for text Puranjay Mohan
2023-08-28 16:59 ` Puranjay Mohan
2023-08-29 2:49 ` Pu Lehui
2023-08-29 2:49 ` Pu Lehui
2023-08-28 16:59 ` [PATCH bpf-next v3 3/3] bpf, riscv: use prog pack allocator in the BPF JIT Puranjay Mohan
2023-08-28 16:59 ` Puranjay Mohan
2023-08-29 2:54 ` Pu Lehui
2023-08-29 2:54 ` Pu Lehui
2023-08-29 10:06 ` [PATCH bpf-next v3 0/3] bpf, riscv: use BPF prog pack allocator in " Björn Töpel
2023-08-29 10:06 ` Björn Töpel
2023-08-30 8:18 ` Daniel Borkmann
2023-08-30 8:18 ` Daniel Borkmann
2023-08-30 8:30 ` Björn Töpel
2023-08-30 8:30 ` Björn Töpel
2023-08-30 13:54 ` Palmer Dabbelt
2023-08-30 13:54 ` Palmer Dabbelt
2023-08-30 22:48 ` Daniel Borkmann
2023-08-30 22:48 ` Daniel Borkmann
2023-08-31 13:15 ` Puranjay Mohan
2023-08-31 13:15 ` Puranjay Mohan
2023-08-30 13:59 ` Björn Töpel
2023-08-30 13:59 ` Björn Töpel
2023-08-30 20:43 ` Palmer Dabbelt
2023-08-30 20:43 ` Palmer Dabbelt
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=20230828165958.1714079-2-puranjay12@gmail.com \
--to=puranjay12@gmail.com \
--cc=andrii@kernel.org \
--cc=aou@eecs.berkeley.edu \
--cc=ast@kernel.org \
--cc=bjorn@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=conor.dooley@microchip.com \
--cc=daniel@iogearbox.net \
--cc=kpsingh@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-riscv@lists.infradead.org \
--cc=martin.lau@linux.dev \
--cc=palmer@dabbelt.com \
--cc=paul.walmsley@sifive.com \
--cc=pulehui@huawei.com \
--cc=song@kernel.org \
--cc=yhs@fb.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.