From: Sven Schnelle <svens@stackframe.org>
To: deller@gmx.de
Cc: linux-parisc@vger.kernel.org, Sven Schnelle <svens@stackframe.org>
Subject: [PATCH 1/6] parisc: add support for patching multiple words
Date: Mon, 27 May 2019 21:04:45 +0200 [thread overview]
Message-ID: <20190527190450.14988-2-svens@stackframe.org> (raw)
In-Reply-To: <20190527190450.14988-1-svens@stackframe.org>
add patch_text_multiple() which allows to patch multiple
text words in memory. This can be used to copy functions.
Signed-off-by: Sven Schnelle <svens@stackframe.org>
---
arch/parisc/include/asm/patch.h | 4 +-
arch/parisc/kernel/patch.c | 75 ++++++++++++++++++++++++++-------
2 files changed, 62 insertions(+), 17 deletions(-)
diff --git a/arch/parisc/include/asm/patch.h b/arch/parisc/include/asm/patch.h
index 685b58a13968..1156fe11249a 100644
--- a/arch/parisc/include/asm/patch.h
+++ b/arch/parisc/include/asm/patch.h
@@ -4,8 +4,10 @@
/* stop machine and patch kernel text */
void patch_text(void *addr, unsigned int insn);
+void patch_text_multiple(void *addr, u32 *insn, int len);
/* patch kernel text with machine already stopped (e.g. in kgdb) */
-void __patch_text(void *addr, unsigned int insn);
+void __patch_text(void *addr, u32 insn);
+void __patch_text_multiple(void *addr, u32 *insn, int len);
#endif
diff --git a/arch/parisc/kernel/patch.c b/arch/parisc/kernel/patch.c
index cdcd981278b3..eaef5515f5b6 100644
--- a/arch/parisc/kernel/patch.c
+++ b/arch/parisc/kernel/patch.c
@@ -17,15 +17,18 @@
struct patch {
void *addr;
- unsigned int insn;
+ u32 *insn;
+ int len;
};
-static void __kprobes *patch_map(void *addr, int fixmap)
-{
+static DEFINE_RAW_SPINLOCK(patch_lock);
+
+static void __kprobes *patch_map(void *addr, int fixmap, int *need_unmap)
unsigned long uintaddr = (uintptr_t) addr;
bool module = !core_kernel_text(uintaddr);
struct page *page;
+ *need_unmap = 0;
if (module && IS_ENABLED(CONFIG_STRICT_MODULE_RWX))
page = vmalloc_to_page(addr);
else if (!module && IS_ENABLED(CONFIG_STRICT_KERNEL_RWX))
@@ -33,6 +36,7 @@ static void __kprobes *patch_map(void *addr, int fixmap)
else
return addr;
+ *need_unmap = 1;
set_fixmap(fixmap, page_to_phys(page));
return (void *) (__fix_to_virt(fixmap) + (uintaddr & ~PAGE_MASK));
@@ -43,34 +47,73 @@ static void __kprobes patch_unmap(int fixmap)
clear_fixmap(fixmap);
}
-void __kprobes __patch_text(void *addr, unsigned int insn)
+void __kprobes __patch_text_multiple(void *addr, u32 *insn, int len)
+{
+ unsigned long start = (unsigned long)addr;
+ unsigned long end = (unsigned long)addr + len;
+ u32 *p, *fixmap;
+ int mapped;
+
+ /* Make sure we don't have any aliases in cache */
+ flush_kernel_vmap_range(addr, len);
+ flush_icache_range(start, end);
+
+ p = fixmap = patch_map(addr, FIX_TEXT_POKE0, &mapped);
+
+ while (len > 0) {
+ *p++ = *insn++;
+ addr += 4;
+ len -= sizeof(u32);
+ if (len && !((unsigned long)addr & ~PAGE_MASK)) {
+ /*
+ * We're crossing a page boundary, so
+ * need to remap
+ */
+ flush_kernel_vmap_range((void *)fixmap,
+ (p-fixmap) * sizeof(*p));
+ if (mapped)
+ patch_unmap(FIX_TEXT_POKE0);
+ p = fixmap = patch_map(addr, FIX_TEXT_POKE0, &mapped);
+ }
+ }
+
+ flush_kernel_vmap_range((void *)fixmap, (p-fixmap) * sizeof(*p));
+ if (mapped)
+ patch_unmap(FIX_TEXT_POKE0);
+ flush_icache_range(start, end);
+}
+
+void __kprobes __patch_text(void *addr, u32 insn)
{
- void *waddr = addr;
- int size;
-
- waddr = patch_map(addr, FIX_TEXT_POKE0);
- *(u32 *)waddr = insn;
- size = sizeof(u32);
- flush_kernel_vmap_range(waddr, size);
- patch_unmap(FIX_TEXT_POKE0);
- flush_icache_range((uintptr_t)(addr),
- (uintptr_t)(addr) + size);
+ __patch_text_multiple(addr, &insn, sizeof(insn));
}
static int __kprobes patch_text_stop_machine(void *data)
{
struct patch *patch = data;
- __patch_text(patch->addr, patch->insn);
-
+ __patch_text_multiple(patch->addr, patch->insn, patch->len);
return 0;
}
void __kprobes patch_text(void *addr, unsigned int insn)
{
+ struct patch patch = {
+ .addr = addr,
+ .insn = &insn,
+ .len = 4
+ };
+
+ stop_machine_cpuslocked(patch_text_stop_machine, &patch, NULL);
+}
+
+void __kprobes patch_text_multiple(void *addr, u32 *insn, int len)
+{
+
struct patch patch = {
.addr = addr,
.insn = insn,
+ .len = len
};
stop_machine_cpuslocked(patch_text_stop_machine, &patch, NULL);
--
2.20.1
next prev parent reply other threads:[~2019-05-27 19:05 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-05-27 19:04 [PATCH 0/6] Dynamic FTRACE for PA-RISC Sven Schnelle
2019-05-27 19:04 ` Sven Schnelle [this message]
2019-05-28 8:19 ` [PATCH 1/6] parisc: add support for patching multiple words Rolf Eike Beer
2019-05-29 17:49 ` Sven Schnelle
2019-05-29 17:58 ` Rolf Eike Beer
2019-05-29 18:18 ` Sven Schnelle
2019-05-27 19:04 ` [PATCH 2/6] parisc: add spinlock to patch function Sven Schnelle
2019-05-27 19:04 ` [PATCH 3/6] parisc: add WARN_ON() to clear_fixmap Sven Schnelle
2019-05-27 19:04 ` [PATCH 4/6] parisc: use pr_debug() in kernel/module.c Sven Schnelle
2019-05-28 8:24 ` Rolf Eike Beer
2019-05-29 17:54 ` Sven Schnelle
2019-05-27 19:04 ` [PATCH 5/6] compiler.h: add CC_USING_PATCHABLE_FUNCTION_ENTRY Sven Schnelle
2019-05-27 19:04 ` [PATCH 6/6] parisc: add dynamic ftrace Sven Schnelle
2019-05-28 8:26 ` Rolf Eike Beer
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=20190527190450.14988-2-svens@stackframe.org \
--to=svens@stackframe.org \
--cc=deller@gmx.de \
--cc=linux-parisc@vger.kernel.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).