[PATCH v3] RISC-V: Don't check text_mutex during stop_machine
Conor Dooley
conor at kernel.org
Sat Feb 25 05:45:13 PST 2023
On 25 February 2023 01:50:14 GMT, Changbin Du <changbin.du at huawei.com> wrote:
>On Fri, Feb 24, 2023 at 01:46:38PM +0000, Conor Dooley wrote:
>> On Fri, Feb 24, 2023 at 08:58:57PM +0800, Changbin Du wrote:
>> > On Fri, Feb 24, 2023 at 11:07:42AM +0000, Conor Dooley wrote:
>> > > > > - 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;
>> > > }
>> > hmm, why not just put 'riscv_patch_in_stop_machine' into patch_text()? Then you
>> > just need to modify that function.
>>
>> Right, I intentionally didn't do that as `riscv_patch_in_stop_machine`
>> skips the lockdep check, which we only want to do for codepaths we know
>> the lock will be held for.
>> I didn't want to put it in patch_text() so if users of patch_text() that
>> do not take the lock are added, they will be caught.
>>
>Understood your concern. Then how abount below instead of discrete changes?
Seems fair enough to me, I'll respin Monday - had some hardware fail so out of action right now.
Thanks,
Conor.
>
>int patch_text(void *addr, u32 insn)
> {
>+ int ret;
> struct patch_insn patch = {
> .addr = addr,
> .insn = insn,
> .cpu_count = ATOMIC_INIT(0),
> };
>
>- return stop_machine_cpuslocked(patch_text_cb,
>+ lockdep_assert_held(&text_mutex);
>+ riscv_patch_in_stop_machine = true
>+ ret = stop_machine_cpuslocked(patch_text_cb,
> &patch, cpu_online_mask);
>+ riscv_patch_in_stop_machine = false;
>+ return ret;
> }
>
>> I'm probably just erring on the paranoid/conservative side of things!
More information about the linux-riscv
mailing list