From: Conor Dooley <conor.dooley@microchip.com>
To: Changbin Du <changbin.du@huawei.com>
Cc: Conor Dooley <conor@kernel.org>, <palmer@dabbelt.com>,
Palmer Dabbelt <palmerdabbelt@google.com>,
<linux-riscv@lists.infradead.org>,
Steven Rostedt <rostedt@goodmis.org>,
Changbin Du <changbin.du@gmail.com>,
Palmer Dabbelt <palmer@rivosinc.com>
Subject: Re: [PATCH v3] RISC-V: Don't check text_mutex during stop_machine
Date: Fri, 24 Feb 2023 11:07:42 +0000 [thread overview]
Message-ID: <Y/iafgRdYtWCmQZ2@wendy> (raw)
In-Reply-To: <20230216113126.kio4uqovoo4p6ubm@M910t>
[-- Attachment #1.1: Type: text/plain, Size: 7252 bytes --]
On Thu, Feb 16, 2023 at 07:31:26PM +0800, Changbin Du wrote:
> On Wed, Feb 15, 2023 at 04:43:17PM +0000, Conor Dooley wrote:
> > From: Palmer Dabbelt <palmerdabbelt@google.com>
> >
> > We're currently using stop_machine() to update ftrace, which means that
> > the thread that takes text_mutex during ftrace_prepare() may not be the
> > same as the thread that eventually patches the code. This isn't
> > actually a race because the lock is still held (preventing any other
> > concurrent accesses) and there is only one thread running during
> > stop_machine(), but it does trigger a lockdep failure.
> >
> > This patch just elides the lockdep check during stop_machine.
> >
> > Fixes: c15ac4fd60d5 ("riscv/ftrace: Add dynamic function tracer support")
> > Suggested-by: Steven Rostedt <rostedt@goodmis.org>
> > Reported-by: Changbin Du <changbin.du@gmail.com>
> > Signed-off-by: Palmer Dabbelt <palmerdabbelt@google.com>
> > Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
> > Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
> > ---
> > Resending this version as I am quite averse to deleting the assertion!
> >
> > Changes since v2 [<20220322022331.32136-1-palmer@rivosinc.com>]:
> > * rebase on riscv/for-next as it as been a year.
> > * incorporate Changbin's suggestion that init_nop should take the lock
> > rather than call prepare() & post_process().
> >
> > Changes since v1 [<20210506071041.417854-1-palmer@dabbelt.com>]:
> > * Use ftrace_arch_ocde_modify_{prepare,post_process}() to set the flag.
> > I remember having a reason I wanted the function when I wrote the v1,
> > but it's been almost a year and I forget what that was -- maybe I was
> > just crazy, the patch was sent at midnight.
> > * Fix DYNAMIC_FTRACE=n builds.
> > ---
> > arch/riscv/include/asm/ftrace.h | 7 +++++++
> > arch/riscv/kernel/ftrace.c | 15 +++++++++++++--
> > arch/riscv/kernel/patch.c | 10 +++++++++-
> > 3 files changed, 29 insertions(+), 3 deletions(-)
> >
> > diff --git a/arch/riscv/include/asm/ftrace.h b/arch/riscv/include/asm/ftrace.h
> > index 04dad3380041..3ac7609f4ee9 100644
> > --- a/arch/riscv/include/asm/ftrace.h
> > +++ b/arch/riscv/include/asm/ftrace.h
> > @@ -81,8 +81,15 @@ do { \
> > struct dyn_ftrace;
> > int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec);
> > #define ftrace_init_nop ftrace_init_nop
> > +extern int riscv_ftrace_in_stop_machine;
> > #endif
> >
> > +#else /* CONFIG_DYNAMIC_FTRACE */
> > +
> > +#ifndef __ASSEMBLY__
> > +#define riscv_ftrace_in_stop_machine 0
> > #endif
> >
> > +#endif /* CONFIG_DYNAMIC_FTRACE */
> > +
> > #endif /* _ASM_RISCV_FTRACE_H */
> > diff --git a/arch/riscv/kernel/ftrace.c b/arch/riscv/kernel/ftrace.c
> > index 2086f6585773..661bfa72f359 100644
> > --- a/arch/riscv/kernel/ftrace.c
> > +++ b/arch/riscv/kernel/ftrace.c
> > @@ -11,14 +11,25 @@
> > #include <asm/cacheflush.h>
> > #include <asm/patch.h>
> >
> > +int riscv_ftrace_in_stop_machine;
> > +
> > #ifdef CONFIG_DYNAMIC_FTRACE
> > void ftrace_arch_code_modify_prepare(void) __acquires(&text_mutex)
> > {
> > mutex_lock(&text_mutex);
> > +
> > + /*
> > + * The code sequences we use for ftrace can't be patched while the
> > + * kernel is running, so we need to use stop_machine() to modify them
> > + * for now. This doesn't play nice with text_mutex, we use this flag
> > + * to elide the check.
> > + */
> > + riscv_ftrace_in_stop_machine = true;
> > }
> >
> > void ftrace_arch_code_modify_post_process(void) __releases(&text_mutex)
> > {
> > + riscv_ftrace_in_stop_machine = false;
> > mutex_unlock(&text_mutex);
> > }
> >
> > @@ -134,9 +145,9 @@ int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec)
> > {
> > int out;
> >
> > - ftrace_arch_code_modify_prepare();
> > + mutex_lock(&text_mutex);
> > out = ftrace_make_nop(mod, rec, MCOUNT_ADDR);
> > - ftrace_arch_code_modify_post_process();
> > + mutex_unlock(&text_mutex);
> >
> > return out;
> > }
> > diff --git a/arch/riscv/kernel/patch.c b/arch/riscv/kernel/patch.c
> > index 765004b60513..56b70271518d 100644
> > --- a/arch/riscv/kernel/patch.c
> > +++ b/arch/riscv/kernel/patch.c
> > @@ -11,6 +11,7 @@
> > #include <asm/kprobes.h>
> > #include <asm/cacheflush.h>
> > #include <asm/fixmap.h>
> > +#include <asm/ftrace.h>
> > #include <asm/patch.h>
> >
> > struct patch_insn {
> > @@ -59,8 +60,15 @@ static int patch_insn_write(void *addr, const void *insn, size_t len)
> > * Before reaching here, it was expected to lock the text_mutex
> > * already, so we don't need to give another lock here and could
> > * ensure that it was safe between each cores.
> > + *
> > + * We're currently using stop_machine() for ftrace, and while that
> > + * ensures text_mutex is held before installing the mappings it does
> > + * not ensure text_mutex is held by the calling thread. That's safe
> > + * but triggers a lockdep failure, so just elide it for that specific
> > + * case.
> > */
> > - lockdep_assert_held(&text_mutex);
> > + if (!riscv_ftrace_in_stop_machine)
> > + lockdep_assert_held(&text_mutex);
> >
> > if (across_pages)
> > patch_map(addr + len, FIX_TEXT_POKE1);
> This misses this function.
>
> int patch_text(void *addr, u32 insn)
So, with a corresponding rename to the symbol, does the following look
okay to you?
diff --git a/arch/riscv/kernel/probes/kprobes.c b/arch/riscv/kernel/probes/kprobes.c
index f21592d20306..433b454e693f 100644
--- a/arch/riscv/kernel/probes/kprobes.c
+++ b/arch/riscv/kernel/probes/kprobes.c
@@ -27,9 +27,15 @@ static void __kprobes arch_prepare_ss_slot(struct kprobe *p)
p->ainsn.api.restore = (unsigned long)p->addr + offset;
+ /*
+ * kprobes takes text_mutex, but patch_text() calls stop_machine and
+ * lockdep gets confused by the context in which the lock is taken.
+ */
+ riscv_patch_in_stop_machine = true;
patch_text(p->ainsn.api.insn, p->opcode);
patch_text((void *)((unsigned long)(p->ainsn.api.insn) + offset),
__BUG_INSN_32);
+ riscv_patch_in_stop_machine = false;
}
static void __kprobes arch_prepare_simulate(struct kprobe *p)
@@ -96,16 +102,28 @@ void *alloc_insn_page(void)
/* install breakpoint in text */
void __kprobes arch_arm_kprobe(struct kprobe *p)
{
+ /*
+ * kprobes takes text_mutex, but patch_text() calls stop_machine and
+ * lockdep gets confused by the context in which the lock is taken.
+ */
+ riscv_patch_in_stop_machine = true;
if ((p->opcode & __INSN_LENGTH_MASK) == __INSN_LENGTH_32)
patch_text(p->addr, __BUG_INSN_32);
else
patch_text(p->addr, __BUG_INSN_16);
+ riscv_patch_in_stop_machine = false;
}
/* remove breakpoint from text */
void __kprobes arch_disarm_kprobe(struct kprobe *p)
{
+ /*
+ * kprobes takes text_mutex, but patch_text() calls stop_machine and
+ * lockdep gets confused by the context in which the lock is taken.
+ */
+ riscv_patch_in_stop_machine = true;
patch_text(p->addr, p->opcode);
+ riscv_patch_in_stop_machine = false;
}
void __kprobes arch_remove_kprobe(struct kprobe *p)
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
[-- Attachment #2: Type: text/plain, Size: 161 bytes --]
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
next prev parent reply other threads:[~2023-02-24 11:08 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-02-15 16:43 [PATCH v3] RISC-V: Don't check text_mutex during stop_machine Conor Dooley
2023-02-16 11:31 ` Changbin Du
2023-02-24 11:07 ` Conor Dooley [this message]
2023-02-24 12:58 ` Changbin Du
2023-02-24 13:46 ` Conor Dooley
2023-02-25 1:50 ` Changbin Du
2023-02-25 13:45 ` Conor Dooley
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=Y/iafgRdYtWCmQZ2@wendy \
--to=conor.dooley@microchip.com \
--cc=changbin.du@gmail.com \
--cc=changbin.du@huawei.com \
--cc=conor@kernel.org \
--cc=linux-riscv@lists.infradead.org \
--cc=palmer@dabbelt.com \
--cc=palmer@rivosinc.com \
--cc=palmerdabbelt@google.com \
--cc=rostedt@goodmis.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 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.