* [PATCH] Documentation: Clarify better about the rwsem non-owner release issue
From: Joel Fernandes (Google) @ 2020-03-22 2:19 UTC (permalink / raw)
To: linux-kernel
Cc: linux-doc, Peter Zijlstra, Sebastian Andrzej Siewior, netdev,
Joel Fernandes (Google), Will Deacon, Thomas Gleixner,
Davidlohr Bueso, Arnd Bergmann, Jonathan Corbet, Ingo Molnar,
Ingo Molnar, Paul E . McKenney, linuxppc-dev, Steven Rostedt,
Bjorn Helgaas, Kurt Schwemmer,
linux-usb@vger.kernel.org Kalle Valo,
linux-pci@vger.kernel.org Felipe Balbi, Logan Gunthorpe,
Randy Dunlap, linux-wireless, Oleg Nesterov, Greg Kroah-Hartman,
Linus Torvalds, David S. Miller
Reword and clarify better about the rwsem non-owner release issue.
Link: https://lore.kernel.org/linux-pci/20200321212144.GA6475@google.com/
Signed-off-by: Joel Fernandes (Google) <joel@joelfernandes.org>
---
Documentation/locking/locktypes.rst | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/Documentation/locking/locktypes.rst b/Documentation/locking/locktypes.rst
index 6f2c0f5b041e..656dce72f11f 100644
--- a/Documentation/locking/locktypes.rst
+++ b/Documentation/locking/locktypes.rst
@@ -292,7 +292,7 @@ implementations to provide priority inheritance for all lock types except
the truly spinning ones. Priority inheritance on ownerless locks is
obviously impossible.
-For now the rwsem non-owner release excludes code which utilizes it from
-being used on PREEMPT_RT enabled kernels. In same cases this can be
-mitigated by disabling portions of the code, in other cases the complete
-functionality has to be disabled until a workable solution has been found.
+For now, a PREEMPT_RT kernel just disables code sections that perform a
+non-owner release of an rwsem. In some cases, parts of the code are disabled.
+In other cases, the complete functionality has to be disabled until a workable
+solution has been found.
--
2.25.1.696.g5e7596f4ac-goog
^ permalink raw reply related
* Re: [patch V2 08/15] Documentation: Add lock ordering and nesting documentation
From: Joel Fernandes @ 2020-03-22 1:36 UTC (permalink / raw)
To: Thomas Gleixner
Cc: Randy Dunlap, Peter Zijlstra, linux-pci,
Sebastian Andrzej Siewior, Oleg Nesterov, Will Deacon,
Ingo Molnar, Davidlohr Bueso, Arnd Bergmann, Logan Gunthorpe,
Paul E . McKenney, linuxppc-dev, Steven Rostedt, Bjorn Helgaas,
Kurt Schwemmer, Kalle Valo, Felipe Balbi, Greg Kroah-Hartman,
linux-usb, linux-wireless, LKML, netdev, Linus Torvalds,
David S. Miller
In-Reply-To: <874kuhqsz3.fsf@nanos.tec.linutronix.de>
On Sat, Mar 21, 2020 at 10:49:04PM +0100, Thomas Gleixner wrote:
[...]
> >> +rwsems have grown interfaces which allow non owner release for special
> >> +purposes. This usage is problematic on PREEMPT_RT because PREEMPT_RT
> >> +substitutes all locking primitives except semaphores with RT-mutex based
> >> +implementations to provide priority inheritance for all lock types except
> >> +the truly spinning ones. Priority inheritance on ownerless locks is
> >> +obviously impossible.
> >> +
> >> +For now the rwsem non-owner release excludes code which utilizes it from
> >> +being used on PREEMPT_RT enabled kernels.
> >
> > I could not parse the last sentence here, but I think you meant "For now,
> > PREEMPT_RT enabled kernels disable code that perform a non-owner release of
> > an rwsem". Correct me if I'm wrong.
>
> Right, that's what I wanted to say :)
>
> Care to send a delta patch?
Absolutely, doing that now. :-)
thanks,
- Joel
^ permalink raw reply
* Re: [patch V2 08/15] Documentation: Add lock ordering and nesting documentation
From: Thomas Gleixner @ 2020-03-21 21:49 UTC (permalink / raw)
To: Joel Fernandes
Cc: Randy Dunlap, Peter Zijlstra, linux-pci,
Sebastian Andrzej Siewior, Oleg Nesterov, Will Deacon,
Ingo Molnar, Davidlohr Bueso, Arnd Bergmann, Logan Gunthorpe,
Paul E . McKenney, linuxppc-dev, Steven Rostedt, Bjorn Helgaas,
Kurt Schwemmer, Kalle Valo, Felipe Balbi, Greg Kroah-Hartman,
linux-usb, linux-wireless, LKML, netdev, Linus Torvalds,
David S. Miller
In-Reply-To: <20200321212144.GA6475@google.com>
Joel Fernandes <joel@joelfernandes.org> writes:
>> +rwlock_t
>> +========
>> +
>> +rwlock_t is a multiple readers and single writer lock mechanism.
>> +
>> +On a non PREEMPT_RT enabled kernel rwlock_t is implemented as a spinning
>> +lock and the suffix rules of spinlock_t apply accordingly. The
>> +implementation is fair and prevents writer starvation.
>>
>
> You mentioned writer starvation, but I think it would be good to also mention
> that rwlock_t on a non-PREEMPT_RT kernel also does not have _reader_
> starvation problem, since it uses queued implementation. This fact is worth
> mentioning here, since further below you explain that an rwlock in PREEMPT_RT
> does have reader starvation problem.
It's worth mentioning. But RT really has only write starvation not
reader starvation.
>> +rwlock_t and PREEMPT_RT
>> +-----------------------
>> +
>> +On a PREEMPT_RT enabled kernel rwlock_t is mapped to a separate
>> +implementation based on rt_mutex which changes the semantics:
>> +
>> + - Same changes as for spinlock_t
>> +
>> + - The implementation is not fair and can cause writer starvation under
>> + certain circumstances. The reason for this is that a writer cannot grant
>> + its priority to multiple readers. Readers which are blocked on a writer
>> + fully support the priority inheritance protocol.
>
> Is it hard to give priority to multiple readers because the number of readers
> to give priority to could be unbounded?
Yes, and it's horribly complex and racy. We had an implemetation years
ago which taught us not to try it again :)
>> +PREEMPT_RT also offers a local_lock mechanism to substitute the
>> +local_irq_disable/save() constructs in cases where a separation of the
>> +interrupt disabling and the locking is really unavoidable. This should be
>> +restricted to very rare cases.
>
> It would also be nice to mention where else local_lock() can be used, such as
> protecting per-cpu variables without disabling preemption. Could we add a
> section on protecting per-cpu data? (Happy to do that and send a patch if you
> prefer).
The local lock section will come soon when we post the local lock
patches again.
>> +rwsems have grown interfaces which allow non owner release for special
>> +purposes. This usage is problematic on PREEMPT_RT because PREEMPT_RT
>> +substitutes all locking primitives except semaphores with RT-mutex based
>> +implementations to provide priority inheritance for all lock types except
>> +the truly spinning ones. Priority inheritance on ownerless locks is
>> +obviously impossible.
>> +
>> +For now the rwsem non-owner release excludes code which utilizes it from
>> +being used on PREEMPT_RT enabled kernels.
>
> I could not parse the last sentence here, but I think you meant "For now,
> PREEMPT_RT enabled kernels disable code that perform a non-owner release of
> an rwsem". Correct me if I'm wrong.
Right, that's what I wanted to say :)
Care to send a delta patch?
Thanks!
tglx
^ permalink raw reply
* Re: [patch V2 08/15] Documentation: Add lock ordering and nesting documentation
From: Joel Fernandes @ 2020-03-21 21:21 UTC (permalink / raw)
To: Thomas Gleixner
Cc: Randy Dunlap, Peter Zijlstra, linux-pci,
Sebastian Andrzej Siewior, Oleg Nesterov, Will Deacon,
Ingo Molnar, Davidlohr Bueso, Arnd Bergmann, Logan Gunthorpe,
Paul E . McKenney, linuxppc-dev, Steven Rostedt, Bjorn Helgaas,
Kurt Schwemmer, Kalle Valo, Felipe Balbi, Greg Kroah-Hartman,
linux-usb, linux-wireless, LKML, netdev, Linus Torvalds,
David S. Miller
In-Reply-To: <20200318204408.211530902@linutronix.de>
Hi Thomas,
Just a few comments:
[...]
> +rtmutex
> +=======
> +
> +RT-mutexes are mutexes with support for priority inheritance (PI).
> +
> +PI has limitations on non PREEMPT_RT enabled kernels due to preemption and
> +interrupt disabled sections.
> +
> +On a PREEMPT_RT enabled kernel most of these sections are fully
> +preemptible. This is possible because PREEMPT_RT forces most executions
> +into task context, especially interrupt handlers and soft interrupts, which
> +allows to substitute spinlock_t and rwlock_t with RT-mutex based
> +implementations.
> +
> +
> +raw_spinlock_t and spinlock_t
> +=============================
> +
> +raw_spinlock_t
> +--------------
> +
> +raw_spinlock_t is a strict spinning lock implementation regardless of the
> +kernel configuration including PREEMPT_RT enabled kernels.
> +
> +raw_spinlock_t is to be used only in real critical core code, low level
> +interrupt handling and places where protecting (hardware) state is required
> +to be safe against preemption and eventually interrupts.
> +
> +Another reason to use raw_spinlock_t is when the critical section is tiny
> +to avoid the overhead of spinlock_t on a PREEMPT_RT enabled kernel in the
> +contended case.
> +
> +spinlock_t
> +----------
> +
> +The semantics of spinlock_t change with the state of CONFIG_PREEMPT_RT.
> +
> +On a non PREEMPT_RT enabled kernel spinlock_t is mapped to raw_spinlock_t
> +and has exactly the same semantics.
> +
> +spinlock_t and PREEMPT_RT
> +-------------------------
> +
> +On a PREEMPT_RT enabled kernel spinlock_t is mapped to a separate
> +implementation based on rt_mutex which changes the semantics:
> +
> + - Preemption is not disabled
> +
> + - The hard interrupt related suffixes for spin_lock / spin_unlock
> + operations (_irq, _irqsave / _irqrestore) do not affect the CPUs
> + interrupt disabled state
> +
> + - The soft interrupt related suffix (_bh()) is still disabling the
> + execution of soft interrupts, but contrary to a non PREEMPT_RT enabled
> + kernel, which utilizes the preemption count, this is achieved by a per
> + CPU bottom half locking mechanism.
> +
> +All other semantics of spinlock_t are preserved:
> +
> + - Migration of tasks which hold a spinlock_t is prevented. On a non
> + PREEMPT_RT enabled kernel this is implicit due to preemption disable.
> + PREEMPT_RT has a separate mechanism to achieve this. This ensures that
> + pointers to per CPU variables stay valid even if the task is preempted.
> +
> + - Task state preservation. The task state is not affected when a lock is
> + contended and the task has to schedule out and wait for the lock to
> + become available. The lock wake up restores the task state unless there
> + was a regular (not lock related) wake up on the task. This ensures that
> + the task state rules are always correct independent of the kernel
> + configuration.
> +
> +rwlock_t
> +========
> +
> +rwlock_t is a multiple readers and single writer lock mechanism.
> +
> +On a non PREEMPT_RT enabled kernel rwlock_t is implemented as a spinning
> +lock and the suffix rules of spinlock_t apply accordingly. The
> +implementation is fair and prevents writer starvation.
>
You mentioned writer starvation, but I think it would be good to also mention
that rwlock_t on a non-PREEMPT_RT kernel also does not have _reader_
starvation problem, since it uses queued implementation. This fact is worth
mentioning here, since further below you explain that an rwlock in PREEMPT_RT
does have reader starvation problem.
> +rwlock_t and PREEMPT_RT
> +-----------------------
> +
> +On a PREEMPT_RT enabled kernel rwlock_t is mapped to a separate
> +implementation based on rt_mutex which changes the semantics:
> +
> + - Same changes as for spinlock_t
> +
> + - The implementation is not fair and can cause writer starvation under
> + certain circumstances. The reason for this is that a writer cannot grant
> + its priority to multiple readers. Readers which are blocked on a writer
> + fully support the priority inheritance protocol.
Is it hard to give priority to multiple readers because the number of readers
to give priority to could be unbounded?
> +
> +
> +PREEMPT_RT caveats
> +==================
> +
> +spinlock_t and rwlock_t
> +-----------------------
> +
> +The substitution of spinlock_t and rwlock_t on PREEMPT_RT enabled kernels
> +with RT-mutex based implementations has a few implications.
> +
> +On a non PREEMPT_RT enabled kernel the following code construct is
> +perfectly fine::
> +
> + local_irq_disable();
> + spin_lock(&lock);
> +
> +and fully equivalent to::
> +
> + spin_lock_irq(&lock);
> +
> +Same applies to rwlock_t and the _irqsave() suffix variant.
> +
> +On a PREEMPT_RT enabled kernel this breaks because the RT-mutex
> +substitution expects a fully preemptible context.
> +
> +The preferred solution is to use :c:func:`spin_lock_irq()` or
> +:c:func:`spin_lock_irqsave()` and their unlock counterparts.
> +
> +PREEMPT_RT also offers a local_lock mechanism to substitute the
> +local_irq_disable/save() constructs in cases where a separation of the
> +interrupt disabling and the locking is really unavoidable. This should be
> +restricted to very rare cases.
It would also be nice to mention where else local_lock() can be used, such as
protecting per-cpu variables without disabling preemption. Could we add a
section on protecting per-cpu data? (Happy to do that and send a patch if you
prefer).
> +raw_spinlock_t
> +--------------
> +
> +Locking of a raw_spinlock_t disables preemption and eventually interrupts.
> +Therefore code inside the critical region has to be careful to avoid calls
> +into code which takes a regular spinlock_t or rwlock_t. A prime example is
> +memory allocation.
> +
> +On a non PREEMPT_RT enabled kernel the following code construct is
> +perfectly fine code::
> +
> + raw_spin_lock(&lock);
> + p = kmalloc(sizeof(*p), GFP_ATOMIC);
> +
> +On a PREEMPT_RT enabled kernel this breaks because the memory allocator is
> +fully preemptible and therefore does not support allocations from truly
> +atomic contexts.
> +
> +Contrary to that the following code construct is perfectly fine on
> +PREEMPT_RT as spin_lock() does not disable preemption::
> +
> + spin_lock(&lock);
> + p = kmalloc(sizeof(*p), GFP_ATOMIC);
> +
> +Most places which use GFP_ATOMIC allocations are safe on PREEMPT_RT as the
> +execution is forced into thread context and the lock substitution is
> +ensuring preemptibility.
> +
> +
> +bit spinlocks
> +-------------
> +
> +Bit spinlocks are problematic for PREEMPT_RT as they cannot be easily
> +substituted by an RT-mutex based implementation for obvious reasons.
> +
> +The semantics of bit spinlocks are preserved on a PREEMPT_RT enabled kernel
> +and the caveats vs. raw_spinlock_t apply.
> +
> +Some bit spinlocks are substituted by regular spinlock_t for PREEMPT_RT but
> +this requires conditional (#ifdef'ed) code changes at the usage side while
> +the spinlock_t substitution is simply done by the compiler and the
> +conditionals are restricted to header files and core implementation of the
> +locking primitives and the usage sites do not require any changes.
> +
> +
> +Lock type nesting rules
> +=======================
> +
> +The most basic rules are:
> +
> + - Lock types of the same lock category (sleeping, spinning) can nest
> + arbitrarily as long as they respect the general lock ordering rules to
> + prevent deadlocks.
> +
> + - Sleeping lock types cannot nest inside spinning lock types.
> +
> + - Spinning lock types can nest inside sleeping lock types.
> +
> +These rules apply in general independent of CONFIG_PREEMPT_RT.
> +
> +As PREEMPT_RT changes the lock category of spinlock_t and rwlock_t from
> +spinning to sleeping this has obviously restrictions how they can nest with
> +raw_spinlock_t.
> +
> +This results in the following nest ordering:
> +
> + 1) Sleeping locks
> + 2) spinlock_t and rwlock_t
> + 3) raw_spinlock_t and bit spinlocks
> +
> +Lockdep is aware of these constraints to ensure that they are respected.
> +
> +
> +Owner semantics
> +===============
> +
> +Most lock types in the Linux kernel have strict owner semantics, i.e. the
> +context (task) which acquires a lock has to release it.
> +
> +There are two exceptions:
> +
> + - semaphores
> + - rwsems
> +
> +semaphores have no strict owner semantics for historical reasons. They are
> +often used for both serialization and waiting purposes. That's generally
> +discouraged and should be replaced by separate serialization and wait
> +mechanisms.
> +
> +rwsems have grown interfaces which allow non owner release for special
> +purposes. This usage is problematic on PREEMPT_RT because PREEMPT_RT
> +substitutes all locking primitives except semaphores with RT-mutex based
> +implementations to provide priority inheritance for all lock types except
> +the truly spinning ones. Priority inheritance on ownerless locks is
> +obviously impossible.
> +
> +For now the rwsem non-owner release excludes code which utilizes it from
> +being used on PREEMPT_RT enabled kernels.
I could not parse the last sentence here, but I think you meant "For now,
PREEMPT_RT enabled kernels disable code that perform a non-owner release of
an rwsem". Correct me if I'm wrong.
Reviewed-by: Joel Fernandes (Google) <joel@joelfernandes.org>
thanks,
- Joel
> In same cases this can be
> +mitigated by disabling portions of the code, in other cases the complete
> +functionality has to be disabled until a workable solution has been found.
>
^ permalink raw reply
* Re: [patch V3 00/20] Lock ordering documentation and annotation for lockdep
From: Thomas Gleixner @ 2020-03-21 17:45 UTC (permalink / raw)
To: Davidlohr Bueso
Cc: Randy Dunlap, linux-ia64, Peter Zijlstra, linux-pci,
Sebastian Siewior, Oleg Nesterov, Guo Ren, Joel Fernandes,
Vincent Chen, Ingo Molnar, Jonathan Corbet, kbuild test robot,
Brian Cain, linux-acpi, Paul E . McKenney, linux-hexagon,
Rafael J. Wysocki, linux-csky, Linus Torvalds, Darren Hart,
Zhang Rui, Len Brown, Fenghua Yu, Arnd Bergmann, linux-pm,
linuxppc-dev, Greentime Hu, Bjorn Helgaas, Kurt Schwemmer,
platform-driver-x86, Kalle Valo, Felipe Balbi, Michal Simek,
Tony Luck, Nick Hu, Geoff Levand, netdev, linux-usb,
linux-wireless, LKML, Davidlohr Bueso, Greg Kroah-Hartman,
Logan Gunthorpe, David S. Miller, Andy Shevchenko
In-Reply-To: <20200321171902.xxlnpikc65wd3b4m@linux-p48b>
Davidlohr Bueso <dave@stgolabs.net> writes:
> On Sat, 21 Mar 2020, Thomas Gleixner wrote:
>
>>This is the third and hopefully final version of this work. The second one
>>can be found here:
>
> Would you rather I send in a separate series with the kvm changes, or
> should I just send a v2 with the fixes here again?
Send a separate series please. These nested threads are hard to follow.
Thanks,
tglx
^ permalink raw reply
* Re: [PATCH 00/18] genirq: Remove setup_irq()
From: afzal mohammed @ 2020-03-21 17:43 UTC (permalink / raw)
To: Thomas Gleixner
Cc: linux-s390, linux-samsung-soc, linux-ia64, linux-c6x-dev,
linux-parisc, linux-sh, linux-hexagon, x86, Nicolas Palix,
linux-kernel, linux-mips, Julia Lawall, linux-m68k, Michal Marek,
linux-rpi-kernel, linux-alpha, Gilles Muller, linux-omap,
linuxppc-dev, linux-arm-kernel
In-Reply-To: <20200227110713.GA5708@afzalpc>
Hi Thomas,
On Thu, Feb 27, 2020 at 04:37:13PM +0530, afzal mohammed wrote:
> On Thu, Feb 27, 2020 at 11:31:15AM +0100, Thomas Gleixner wrote:
> > Vs. merging this series, I suggest the following approach:
> >
> > - Resubmit the individual changes as single patches or small series
> > to the relevant maintainers and subsystem mailing lists. They have
> > no dependency on a core change and can be applied where they belong
> > to.
> >
> > - After 5.6-rc6, verify which parts have made their way into
> > linux-next and resubmit the ignored ones as a series to me along
> > with the removal of the core parts.
> >
> > That way we can avoid conflicting changes between subsystems and the tip
> > irq/core branch as much as possible.
>
> Okay, i will do accordingly.
i am on it, is delayed due to the reason as mentioned at,
https://lkml.kernel.org/r/20200321172626.GA6323@afzalpc
[ not repeating contents here since other mail was sent just now,
cc'ing you ]
Regards
afzal
^ permalink raw reply
* Re: [patch V2 08/15] Documentation: Add lock ordering and nesting documentation
From: Paul E. McKenney @ 2020-03-21 17:23 UTC (permalink / raw)
To: Thomas Gleixner
Cc: Randy Dunlap, Peter Zijlstra, linux-pci,
Sebastian Andrzej Siewior, Oleg Nesterov, Joel Fernandes,
Will Deacon, Ingo Molnar, Davidlohr Bueso, Logan Gunthorpe,
Arnd Bergmann, linuxppc-dev, Steven Rostedt, Bjorn Helgaas,
Kurt Schwemmer, Kalle Valo, Felipe Balbi, Greg Kroah-Hartman,
linux-usb, linux-wireless, LKML, netdev, Linus Torvalds,
David S. Miller
In-Reply-To: <875zeyrold.fsf@nanos.tec.linutronix.de>
On Sat, Mar 21, 2020 at 11:26:06AM +0100, Thomas Gleixner wrote:
> "Paul E. McKenney" <paulmck@kernel.org> writes:
> > On Fri, Mar 20, 2020 at 11:36:03PM +0100, Thomas Gleixner wrote:
> >> I agree that what I tried to express is hard to parse, but it's at least
> >> halfways correct :)
> >
> > Apologies! That is what I get for not looking it up in the source. :-/
> >
> > OK, so I am stupid enough not only to get it wrong, but also to try again:
> >
> > ... Other types of wakeups would normally unconditionally set the
> > task state to RUNNING, but that does not work here because the task
> > must remain blocked until the lock becomes available. Therefore,
> > when a non-lock wakeup attempts to awaken a task blocked waiting
> > for a spinlock, it instead sets the saved state to RUNNING. Then,
> > when the lock acquisition completes, the lock wakeup sets the task
> > state to the saved state, in this case setting it to RUNNING.
> >
> > Is that better?
>
> Definitely!
>
> Thanks for all the editorial work!
NP, and glad you like it!
But I felt even more stupid sometime in the middle of the night. Why on
earth didn't I work in your nice examples? :-/
I will pull them in later. Time to go hike!!!
Thanx, Paul
^ permalink raw reply
* Re: [patch V3 00/20] Lock ordering documentation and annotation for lockdep
From: Davidlohr Bueso @ 2020-03-21 17:19 UTC (permalink / raw)
To: Thomas Gleixner
Cc: Randy Dunlap, linux-ia64, Peter Zijlstra, linux-pci,
Sebastian Siewior, Oleg Nesterov, Guo Ren, Joel Fernandes,
Vincent Chen, Ingo Molnar, Jonathan Corbet, kbuild test robot,
Brian Cain, linux-acpi, Paul E . McKenney, linux-hexagon,
Rafael J. Wysocki, linux-csky, Linus Torvalds, Darren Hart,
Zhang Rui, Len Brown, Fenghua Yu, Arnd Bergmann, linux-pm,
linuxppc-dev, Greentime Hu, Bjorn Helgaas, Kurt Schwemmer,
platform-driver-x86, Kalle Valo, Felipe Balbi, Michal Simek,
Tony Luck, Nick Hu, Geoff Levand, netdev, linux-usb,
linux-wireless, LKML, Davidlohr Bueso, Greg Kroah-Hartman,
Logan Gunthorpe, David S. Miller, Andy Shevchenko
In-Reply-To: <20200321112544.878032781@linutronix.de>
On Sat, 21 Mar 2020, Thomas Gleixner wrote:
>This is the third and hopefully final version of this work. The second one
>can be found here:
Would you rather I send in a separate series with the kvm changes, or
should I just send a v2 with the fixes here again?
Thanks,
Davidlohr
^ permalink raw reply
* Re: [GIT PULL] Please pull powerpc/linux.git powerpc-5.6-5 tag
From: pr-tracker-bot @ 2020-03-21 16:45 UTC (permalink / raw)
To: Michael Ellerman; +Cc: linuxppc-dev, Linus Torvalds, groug, linux-kernel
In-Reply-To: <87fte1dg0x.fsf@mpe.ellerman.id.au>
The pull request you sent on Sat, 21 Mar 2020 23:54:54 +1100:
> https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git tags/powerpc-5.6-5
has been merged into torvalds/linux.git:
https://git.kernel.org/torvalds/c/c63c50fc2ec9afc4de21ef9ead2eac64b178cce1
Thank you!
--
Deet-doot-dot, I am a bot.
https://korg.wiki.kernel.org/userdoc/prtracker
^ permalink raw reply
* Re: [PATCH 2/5] csky: Remove mm.h from asm/uaccess.h
From: Guo Ren @ 2020-03-21 14:11 UTC (permalink / raw)
To: Thomas Gleixner
Cc: Randy Dunlap, Peter Zijlstra, linux-pci,
Sebastian Andrzej Siewior, Linux Kernel Mailing List, joel,
Will Deacon, mingo, dave, Arnd Bergmann, linux-csky, torvalds,
paulmck, linuxppc-dev, Steven Rostedt, Bjorn Helgaas,
kurt.schwemmer, kvalo, kbuild test robot, balbi, gregkh,
linux-usb, linux-wireless, oleg, netdev, logang, David Miller
In-Reply-To: <87zhc9rjuz.fsf@nanos.tec.linutronix.de>
On Sat, Mar 21, 2020 at 8:08 PM Thomas Gleixner <tglx@linutronix.de> wrote:
>
> Guo Ren <guoren@kernel.org> writes:
>
> > Tested and Acked by me.
> >
> > Queued for next pull request, thx
>
> Can we please route that with the rcuwait changes to avoid breakage
> unless you ship it to Linus right away?
Ok, I won't queue it.
^ permalink raw reply
* Re: [patch V3 12/20] powerpc/ps3: Convert half completion to rcuwait
From: Thomas Gleixner @ 2020-03-21 13:22 UTC (permalink / raw)
To: LKML
Cc: Randy Dunlap, linux-ia64, Peter Zijlstra, linux-pci,
Sebastian Siewior, platform-driver-x86, Guo Ren, Joel Fernandes,
linux-hexagon, Vincent Chen, Ingo Molnar, Jonathan Corbet,
Davidlohr Bueso, kbuild test robot, Brian Cain, linux-acpi,
Paul E . McKenney, Rafael J. Wysocki, linux-csky, Linus Torvalds,
Darren Hart, Zhang Rui, Len Brown, Fenghua Yu, Arnd Bergmann,
linux-pm, Greentime Hu, Bjorn Helgaas, Kurt Schwemmer, Kalle Valo,
Felipe Balbi, Michal Simek, Tony Luck, Nick Hu, Geoff Levand,
Greg Kroah-Hartman, linux-usb, linux-wireless, Oleg Nesterov,
Davidlohr Bueso, Logan Gunthorpe, netdev, linuxppc-dev,
David S. Miller, Andy Shevchenko
In-Reply-To: <20200321113241.930037873@linutronix.de>
Thomas Gleixner <tglx@linutronix.de> writes:
> From: Thomas Gleixner <tglx@linutronix.de>
That's obviously bogus and wants to be:
From: Peter Zijlstra (Intel) <peterz@infradead.org>
^ permalink raw reply
* [GIT PULL] Please pull powerpc/linux.git powerpc-5.6-5 tag
From: Michael Ellerman @ 2020-03-21 12:54 UTC (permalink / raw)
To: Linus Torvalds; +Cc: linuxppc-dev, groug, linux-kernel
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256
Hi Linus,
Please pull a couple more powerpc fixes for 5.6:
The following changes since commit 59bee45b9712c759ea4d3dcc4eff1752f3a66558:
powerpc/mm: Fix missing KUAP disable in flush_coherent_icache() (2020-03-05 17:15:08 +1100)
are available in the git repository at:
https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git tags/powerpc-5.6-5
for you to fetch changes up to 1d0c32ec3b860a32df593a22bad0d1dbc5546a59:
KVM: PPC: Fix kernel crash with PR KVM (2020-03-20 13:39:10 +1100)
- ------------------------------------------------------------------
powerpc fixes for 5.6 #5
Two fixes for bugs introduced this cycle.
One for a crash when shutting down a KVM PR guest (our original style of KVM
which doesn't use hypervisor mode).
And one fix for the recently added 32-bit KASAN_VMALLOC support.
Thanks to:
Christophe Leroy, Greg Kurz, Sean Christopherson.
- ------------------------------------------------------------------
Christophe Leroy (1):
powerpc/kasan: Fix shadow memory protection with CONFIG_KASAN_VMALLOC
Greg Kurz (1):
KVM: PPC: Fix kernel crash with PR KVM
arch/powerpc/kvm/book3s_pr.c | 1 +
arch/powerpc/kvm/powerpc.c | 2 --
arch/powerpc/mm/kasan/kasan_init_32.c | 9 ++-------
3 files changed, 3 insertions(+), 9 deletions(-)
-----BEGIN PGP SIGNATURE-----
iQIzBAEBCAAdFiEEJFGtCPCthwEv2Y/bUevqPMjhpYAFAl52BiYACgkQUevqPMjh
pYDwqhAAsiBYfVZiof+3JQM1Qaf2nnrYHMCLgwT6BJ6l8IxcjPih/4tcWAhe9plX
8xAa44leV0I+HpO0gxFOcfmPTtMmgdk8elUq8NEN7NBQgCb0vDyhjRBPuotwFqvx
U5Hiztra4c87NSL3A/h9JXxtRQBTw5Eg3NuxVPHV6seMtUhBkJThfYWFY7DWvolX
v8poLVZjO2Tq+QuEwJuC1lFTCqT1u1V+IdxEbNrBWy3yNqvb9p4gAlvB+0s/xe30
SFmTyNWUdW4KCE+8Vvbpgr9+s7m6CCvysjlmPra+m7pgFe+X6qcRFLWz+L+8MSSj
+mSmFuyI6KYOxRRY3Er4Q7gnssfiNlcxr5I/jvhiXWJNwS3inv4OinlEfV4pW/eT
++Uy7JCwqel1JZANh0oqcydeuGdU8emozsi5LuRKLB6Mm5mFymzYRc+W6MEpUwM6
b+2rPAagOwY44DN517Ixkc/jdad3BCiLeuDWqzx1BVUHgEKNvu3RWhrHClM1kEey
AaH6u1KGQ81XuKqYrODFaLkOoCumPzUgK42CcjblAQcea1PpYl5myCVNILLBQjJK
kTa1CzX9JG0z9mWLjQwJSpYKB7MOQxBGy0BmxOdjjUBD9DkhGm0Pt7NGz1Xo0n9s
hCSVtCV9M1cfaPyvCDICbDtR+j8SQTfjFk9fDwWcnrssbhtac3c=
=3KDP
-----END PGP SIGNATURE-----
^ permalink raw reply
* FSL P5020/Cyrus+ Board: Poweroff and Restart Support
From: Christian Zigotzky @ 2020-03-21 12:50 UTC (permalink / raw)
To: linuxppc-dev
Cc: Julian Margetson, Darren Stevens, contact@a-eon.com, mad skateman,
R.T.Dickinson
In-Reply-To: <mailman.1087.1584789896.27067.linuxppc-dev@lists.ozlabs.org>
[-- Attachment #1: Type: text/plain, Size: 456 bytes --]
Hello,
We would like to add poweroff and restart support for the Cyrus+ board
[1] [2] to the mainline vanilla kernel.
There is a patch for adding poweroff and restart support. (attached)
It works but I am not sure if it is good enough for the mainline vanilla
kernel.
Please post some suggestions and comments about this patch.
Thanks,
Christian
[1] http://wiki.amiga.org/index.php?title=X5000
[2] https://www.amigaos.net/hardware/133/amigaone-x5000
[-- Attachment #2: cyrus_5.6-2.txt --]
[-- Type: text/plain, Size: 1708 bytes --]
diff -rupN a/arch/powerpc/boot/dts/fsl/cyrus_p5020.dts b/arch/powerpc/boot/dts/fsl/cyrus_p5020.dts
--- a/arch/powerpc/boot/dts/fsl/cyrus_p5020.dts 2020-02-10 01:08:48.000000000 +0100
+++ b/arch/powerpc/boot/dts/fsl/cyrus_p5020.dts 2020-02-10 08:49:47.953680947 +0100
@@ -146,6 +146,25 @@
0 0x00010000>;
};
};
+
+ gpio-poweroff {
+ compatible = "gpio-poweroff";
+ gpios = <&gpio0 3 1>;
+ };
+
+ gpio-restart {
+ compatible = "gpio-restart";
+ gpios = <&gpio0 2 1>;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ hdd {
+ label = "Disk activity";
+ gpios = <&gpio0 5 0>;
+ linux,default-trigger = "disk-activity";
+ };
+ };
};
/include/ "p5020si-post.dtsi"
diff -rupN a/arch/powerpc/platforms/85xx/corenet_generic.c b/arch/powerpc/platforms/85xx/corenet_generic.c
--- a/arch/powerpc/platforms/85xx/corenet_generic.c 2020-02-10 01:08:48.000000000 +0100
+++ b/arch/powerpc/platforms/85xx/corenet_generic.c 2020-02-10 08:49:47.953680947 +0100
@@ -46,6 +46,16 @@ void __init corenet_gen_pic_init(void)
mpic_init(mpic);
}
+/* If someone has registered a poweroff callback, invoke it */
+static void __noreturn corenet_generic_halt(void)
+{
+ if (pm_power_off)
+ pm_power_off();
+
+ /* Should not return */
+ for(;;);
+}
+
/*
* Setup the architecture
*/
@@ -99,6 +109,15 @@ static const struct of_device_id of_devi
{
.name = "handles",
},
+ {
+ .name = "gpio-poweroff",
+ },
+ {
+ .name = "gpio-restart",
+ },
+ {
+ .name = "leds",
+ },
{}
};
@@ -149,6 +168,8 @@ static int __init corenet_generic_probe(
extern struct smp_ops_t smp_85xx_ops;
#endif
+ ppc_md.halt = corenet_generic_halt;
+
if (of_device_compatible_match(of_root, boards))
return 1;
^ permalink raw reply
* Re: [patch V3 05/20] acpi: Remove header dependency
From: Andy Shevchenko @ 2020-03-21 12:23 UTC (permalink / raw)
To: Thomas Gleixner
Cc: USB, linux-ia64, Peter Zijlstra, linux-pci, Sebastian Siewior,
Oleg Nesterov, Guo Ren, Joel Fernandes, Vincent Chen, Ingo Molnar,
Davidlohr Bueso, kbuild test robot, Brian Cain, Jonathan Corbet,
Paul E . McKenney, linux-hexagon, Rafael J. Wysocki, linux-csky,
ACPI Devel Maling List, Darren Hart, Zhang Rui, Len Brown,
Fenghua Yu, Randy Dunlap, Arnd Bergmann, Linux PM,
open list:LINUX FOR POWERPC PA SEMI PWRFICIENT, Greentime Hu,
Bjorn Helgaas, Kurt Schwemmer, Platform Driver, Kalle Valo,
Felipe Balbi, Michal Simek, Tony Luck, Nick Hu, Geoff Levand,
Greg Kroah-Hartman, Linus Torvalds,
open list:TI WILINK WIRELES..., LKML, Davidlohr Bueso, netdev,
Logan Gunthorpe, David S. Miller, Andy Shevchenko
In-Reply-To: <20200321113241.246190285@linutronix.de>
On Sat, Mar 21, 2020 at 1:34 PM Thomas Gleixner <tglx@linutronix.de> wrote:
>
> From: Peter Zijlstra <peterz@infradead.org>
>
> In order to avoid future header hell, remove the inclusion of
> proc_fs.h from acpi_bus.h. All it needs is a forward declaration of a
> struct.
>
Acked-by: Andy Shevchenko <andy.shevchenko@gmail.com> # for PDx86
> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> Cc: Darren Hart <dvhart@infradead.org>
> Cc: Andy Shevchenko <andy@infradead.org>
> Cc: platform-driver-x86@vger.kernel.org
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Cc: Zhang Rui <rui.zhang@intel.com>
> Cc: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
> Cc: linux-pm@vger.kernel.org
> Cc: Len Brown <lenb@kernel.org>
> Cc: linux-acpi@vger.kernel.org
> ---
> drivers/platform/x86/dell-smo8800.c | 1 +
> drivers/platform/x86/wmi.c | 1 +
> drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.c | 1 +
> include/acpi/acpi_bus.h | 2 +-
> 4 files changed, 4 insertions(+), 1 deletion(-)
>
> --- a/drivers/platform/x86/dell-smo8800.c
> +++ b/drivers/platform/x86/dell-smo8800.c
> @@ -16,6 +16,7 @@
> #include <linux/interrupt.h>
> #include <linux/miscdevice.h>
> #include <linux/uaccess.h>
> +#include <linux/fs.h>
>
> struct smo8800_device {
> u32 irq; /* acpi device irq */
> --- a/drivers/platform/x86/wmi.c
> +++ b/drivers/platform/x86/wmi.c
> @@ -29,6 +29,7 @@
> #include <linux/uaccess.h>
> #include <linux/uuid.h>
> #include <linux/wmi.h>
> +#include <linux/fs.h>
> #include <uapi/linux/wmi.h>
>
> ACPI_MODULE_NAME("wmi");
> --- a/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.c
> +++ b/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.c
> @@ -19,6 +19,7 @@
> #include <linux/acpi.h>
> #include <linux/uaccess.h>
> #include <linux/miscdevice.h>
> +#include <linux/fs.h>
> #include "acpi_thermal_rel.h"
>
> static acpi_handle acpi_thermal_rel_handle;
> --- a/include/acpi/acpi_bus.h
> +++ b/include/acpi/acpi_bus.h
> @@ -80,7 +80,7 @@ bool acpi_dev_present(const char *hid, c
>
> #ifdef CONFIG_ACPI
>
> -#include <linux/proc_fs.h>
> +struct proc_dir_entry;
>
> #define ACPI_BUS_FILE_ROOT "acpi"
> extern struct proc_dir_entry *acpi_root_dir;
>
>
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH 2/5] csky: Remove mm.h from asm/uaccess.h
From: Thomas Gleixner @ 2020-03-21 12:08 UTC (permalink / raw)
To: Guo Ren, Sebastian Andrzej Siewior
Cc: Randy Dunlap, Peter Zijlstra, linux-pci,
Linux Kernel Mailing List, joel, Will Deacon, mingo, dave,
Arnd Bergmann, linux-csky, torvalds, paulmck, linuxppc-dev,
Steven Rostedt, bhelgaas, kurt.schwemmer, kvalo,
kbuild test robot, balbi, gregkh, linux-usb, linux-wireless, oleg,
netdev, logang, David Miller
In-Reply-To: <CAJF2gTQDvmSdJB3R0By0Q6d9ganVBV1FBm3urL8Jf1fyiEi+1A@mail.gmail.com>
Guo Ren <guoren@kernel.org> writes:
> Tested and Acked by me.
>
> Queued for next pull request, thx
Can we please route that with the rcuwait changes to avoid breakage
unless you ship it to Linus right away?
Thanks,
tglx
^ permalink raw reply
* Re: [PATCH 1/3] KVM: PPC: Fix kernel crash with PR KVM
From: Michael Ellerman @ 2020-03-21 11:37 UTC (permalink / raw)
To: Greg Kurz, Paul Mackerras
Cc: Paolo Bonzini, linuxppc-dev, Sean Christopherson, kvm-ppc
In-Reply-To: <158455341029.178873.15248663726399374882.stgit@bahia.lan>
On Wed, 2020-03-18 at 17:43:30 UTC, Greg Kurz wrote:
> With PR KVM, shutting down a VM causes the host kernel to crash:
>
> [ 314.219284] BUG: Unable to handle kernel data access on read at 0xc00800000176c638
> [ 314.219299] Faulting instruction address: 0xc008000000d4ddb0
> cpu 0x0: Vector: 300 (Data Access) at [c00000036da077a0]
> pc: c008000000d4ddb0: kvmppc_mmu_pte_flush_all+0x68/0xd0 [kvm_pr]
> lr: c008000000d4dd94: kvmppc_mmu_pte_flush_all+0x4c/0xd0 [kvm_pr]
> sp: c00000036da07a30
> msr: 900000010280b033
> dar: c00800000176c638
> dsisr: 40000000
> current = 0xc00000036d4c0000
> paca = 0xc000000001a00000 irqmask: 0x03 irq_happened: 0x01
> pid = 1992, comm = qemu-system-ppc
> Linux version 5.6.0-master-gku+ (greg@palmb) (gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04)) #17 SMP Wed Mar 18 13:49:29 CET 2020
> enter ? for help
> [c00000036da07ab0] c008000000d4fbe0 kvmppc_mmu_destroy_pr+0x28/0x60 [kvm_pr]
> [c00000036da07ae0] c0080000009eab8c kvmppc_mmu_destroy+0x34/0x50 [kvm]
> [c00000036da07b00] c0080000009e50c0 kvm_arch_vcpu_destroy+0x108/0x140 [kvm]
> [c00000036da07b30] c0080000009d1b50 kvm_vcpu_destroy+0x28/0x80 [kvm]
> [c00000036da07b60] c0080000009e4434 kvm_arch_destroy_vm+0xbc/0x190 [kvm]
> [c00000036da07ba0] c0080000009d9c2c kvm_put_kvm+0x1d4/0x3f0 [kvm]
> [c00000036da07c00] c0080000009da760 kvm_vm_release+0x38/0x60 [kvm]
> [c00000036da07c30] c000000000420be0 __fput+0xe0/0x310
> [c00000036da07c90] c0000000001747a0 task_work_run+0x150/0x1c0
> [c00000036da07cf0] c00000000014896c do_exit+0x44c/0xd00
> [c00000036da07dc0] c0000000001492f4 do_group_exit+0x64/0xd0
> [c00000036da07e00] c000000000149384 sys_exit_group+0x24/0x30
> [c00000036da07e20] c00000000000b9d0 system_call+0x5c/0x68
>
> This is caused by a use-after-free in kvmppc_mmu_pte_flush_all()
> which dereferences vcpu->arch.book3s which was previously freed by
> kvmppc_core_vcpu_free_pr(). This happens because kvmppc_mmu_destroy()
> is called after kvmppc_core_vcpu_free() since commit ff030fdf5573
> ("KVM: PPC: Move kvm_vcpu_init() invocation to common code").
>
> The kvmppc_mmu_destroy() helper calls one of the following depending
> on the KVM backend:
>
> - kvmppc_mmu_destroy_hv() which does nothing (Book3s HV)
>
> - kvmppc_mmu_destroy_pr() which undoes the effects of
> kvmppc_mmu_init() (Book3s PR 32-bit)
>
> - kvmppc_mmu_destroy_pr() which undoes the effects of
> kvmppc_mmu_init() (Book3s PR 64-bit)
>
> - kvmppc_mmu_destroy_e500() which does nothing (BookE e500/e500mc)
>
> It turns out that this is only relevant to PR KVM actually. And both
> 32 and 64 backends need vcpu->arch.book3s to be valid when calling
> kvmppc_mmu_destroy_pr(). So instead of calling kvmppc_mmu_destroy()
> from kvm_arch_vcpu_destroy(), call kvmppc_mmu_destroy_pr() at the
> beginning of kvmppc_core_vcpu_free_pr(). This is consistent with
> kvmppc_mmu_init() being the last call in kvmppc_core_vcpu_create_pr().
>
> For the same reason, if kvmppc_core_vcpu_create_pr() returns an
> error then this means that kvmppc_mmu_init() was either not called
> or failed, in which case kvmppc_mmu_destroy() should not be called.
> Drop the line in the error path of kvm_arch_vcpu_create().
>
> Fixes: ff030fdf5573 ("KVM: PPC: Move kvm_vcpu_init() invocation to common code")
> Signed-off-by: Greg Kurz <groug@kaod.org>
Applied to powerpc fixes, thanks.
https://git.kernel.org/powerpc/c/1d0c32ec3b860a32df593a22bad0d1dbc5546a59
cheers
^ permalink raw reply
* Re: [PATCH v3] powerpc/kasan: Fix shadow memory protection with CONFIG_KASAN_VMALLOC
From: Michael Ellerman @ 2020-03-21 11:37 UTC (permalink / raw)
To: Christophe Leroy, Benjamin Herrenschmidt, Paul Mackerras
Cc: linuxppc-dev, linux-kernel
In-Reply-To: <ef5248fc1f496c6b0dfdb59380f24968f25f75c5.1583513368.git.christophe.leroy@c-s.fr>
On Fri, 2020-03-06 at 16:49:49 UTC, Christophe Leroy wrote:
> With CONFIG_KASAN_VMALLOC, new page tables are created at the time
> shadow memory for vmalloc area in unmapped. If some parts of the
> page table still has entries to the zero page shadow memory, the
> entries are wrongly marked RW.
>
> With CONFIG_KASAN_VMALLOC, almost the entire kernel address space
> is managed by KASAN. To make it simple, just create KASAN page tables
> for the entire kernel space at kasan_init(). That doesn't use much
> more space, and that's anyway already done for hash platforms.
>
> Fixes: 3d4247fcc938 ("powerpc/32: Add support of KASAN_VMALLOC")
> Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
Applied to powerpc fixes, thanks.
https://git.kernel.org/powerpc/c/af3d0a68698c7e5df8b72267086b23422a3954bb
cheers
^ permalink raw reply
* [patch V3 17/20] lockdep: Introduce wait-type checks
From: Thomas Gleixner @ 2020-03-21 11:26 UTC (permalink / raw)
To: LKML
Cc: Randy Dunlap, linux-ia64, Peter Zijlstra, linux-pci,
Sebastian Siewior, platform-driver-x86, Guo Ren, Joel Fernandes,
Vincent Chen, Ingo Molnar, Jonathan Corbet, Davidlohr Bueso,
kbuild test robot, Brian Cain, linux-acpi, Paul E . McKenney,
linux-hexagon, Rafael J. Wysocki, linux-csky, Linus Torvalds,
Darren Hart, Zhang Rui, Len Brown, Fenghua Yu, Arnd Bergmann,
linux-pm, linuxppc-dev, Greentime Hu, Bjorn Helgaas,
Kurt Schwemmer, Kalle Valo, Felipe Balbi, Michal Simek, Tony Luck,
Nick Hu, Geoff Levand, Greg Kroah-Hartman, linux-usb,
linux-wireless, Oleg Nesterov, Davidlohr Bueso, netdev,
Logan Gunthorpe, David S. Miller, Andy Shevchenko
In-Reply-To: <20200321112544.878032781@linutronix.de>
From: Peter Zijlstra <peterz@infradead.org>
Extend lockdep to validate lock wait-type context.
The current wait-types are:
LD_WAIT_FREE, /* wait free, rcu etc.. */
LD_WAIT_SPIN, /* spin loops, raw_spinlock_t etc.. */
LD_WAIT_CONFIG, /* CONFIG_PREEMPT_LOCK, spinlock_t etc.. */
LD_WAIT_SLEEP, /* sleeping locks, mutex_t etc.. */
Where lockdep validates that the current lock (the one being acquired)
fits in the current wait-context (as generated by the held stack).
This ensures that there is no attempt to acquire mutexes while holding
spinlocks, to acquire spinlocks while holding raw_spinlocks and so on. In
other words, its a more fancy might_sleep().
Obviously RCU made the entire ordeal more complex than a simple single
value test because RCU can be acquired in (pretty much) any context and
while it presents a context to nested locks it is not the same as it
got acquired in.
Therefore its necessary to split the wait_type into two values, one
representing the acquire (outer) and one representing the nested context
(inner). For most 'normal' locks these two are the same.
[ To make static initialization easier we have the rule that:
.outer == INV means .outer == .inner; because INV == 0. ]
It further means that its required to find the minimal .inner of the held
stack to compare against the outer of the new lock; because while 'normal'
RCU presents a CONFIG type to nested locks, if it is taken while already
holding a SPIN type it obviously doesn't relax the rules.
Below is an example output generated by the trivial test code:
raw_spin_lock(&foo);
spin_lock(&bar);
spin_unlock(&bar);
raw_spin_unlock(&foo);
[ BUG: Invalid wait context ]
-----------------------------
swapper/0/1 is trying to lock:
ffffc90000013f20 (&bar){....}-{3:3}, at: kernel_init+0xdb/0x187
other info that might help us debug this:
1 lock held by swapper/0/1:
#0: ffffc90000013ee0 (&foo){+.+.}-{2:2}, at: kernel_init+0xd1/0x187
The way to read it is to look at the new -{n,m} part in the lock
description; -{3:3} for the attempted lock, and try and match that up to
the held locks, which in this case is the one: -{2,2}.
This tells that the acquiring lock requires a more relaxed environment than
presented by the lock stack.
Currently only the normal locks and RCU are converted, the rest of the
lockdep users defaults to .inner = INV which is ignored. More conversions
can be done when desired.
The check for spinlock_t nesting is not enabled by default. It's a separate
config option for now as there are known problems which are currently
addressed. The config option allows to identify these problems and to
verify that the solutions found are indeed solving them.
The config switch will be removed and the checks will permanently enabled
once the vast majority of issues has been addressed.
[ bigeasy: Move LD_WAIT_FREE,… out of CONFIG_LOCKDEP to avoid compile
failure with CONFIG_DEBUG_SPINLOCK + !CONFIG_LOCKDEP]
[ tglx: Add the config option ]
Requested-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
V2: Fix the LOCKDEP=y && LOCK_PROVE=n case
---
include/linux/irqflags.h | 8 ++
include/linux/lockdep.h | 71 +++++++++++++++++---
include/linux/mutex.h | 7 +-
include/linux/rwlock_types.h | 6 +
include/linux/rwsem.h | 6 +
include/linux/sched.h | 1
include/linux/spinlock.h | 35 +++++++---
include/linux/spinlock_types.h | 24 +++++-
kernel/irq/handle.c | 7 ++
kernel/locking/lockdep.c | 138 ++++++++++++++++++++++++++++++++++++++--
kernel/locking/mutex-debug.c | 2
kernel/locking/rwsem.c | 2
kernel/locking/spinlock_debug.c | 6 -
kernel/rcu/update.c | 24 +++++-
lib/Kconfig.debug | 17 ++++
15 files changed, 307 insertions(+), 47 deletions(-)
--- a/include/linux/irqflags.h
+++ b/include/linux/irqflags.h
@@ -37,7 +37,12 @@
# define trace_softirqs_enabled(p) ((p)->softirqs_enabled)
# define trace_hardirq_enter() \
do { \
- current->hardirq_context++; \
+ if (!current->hardirq_context++) \
+ current->hardirq_threaded = 0; \
+} while (0)
+# define trace_hardirq_threaded() \
+do { \
+ current->hardirq_threaded = 1; \
} while (0)
# define trace_hardirq_exit() \
do { \
@@ -59,6 +64,7 @@ do { \
# define trace_hardirqs_enabled(p) 0
# define trace_softirqs_enabled(p) 0
# define trace_hardirq_enter() do { } while (0)
+# define trace_hardirq_threaded() do { } while (0)
# define trace_hardirq_exit() do { } while (0)
# define lockdep_softirq_enter() do { } while (0)
# define lockdep_softirq_exit() do { } while (0)
--- a/include/linux/lockdep.h
+++ b/include/linux/lockdep.h
@@ -21,6 +21,22 @@ extern int lock_stat;
#include <linux/types.h>
+enum lockdep_wait_type {
+ LD_WAIT_INV = 0, /* not checked, catch all */
+
+ LD_WAIT_FREE, /* wait free, rcu etc.. */
+ LD_WAIT_SPIN, /* spin loops, raw_spinlock_t etc.. */
+
+#ifdef CONFIG_PROVE_RAW_LOCK_NESTING
+ LD_WAIT_CONFIG, /* CONFIG_PREEMPT_LOCK, spinlock_t etc.. */
+#else
+ LD_WAIT_CONFIG = LD_WAIT_SPIN,
+#endif
+ LD_WAIT_SLEEP, /* sleeping locks, mutex_t etc.. */
+
+ LD_WAIT_MAX, /* must be last */
+};
+
#ifdef CONFIG_LOCKDEP
#include <linux/linkage.h>
@@ -111,6 +127,9 @@ struct lock_class {
int name_version;
const char *name;
+ short wait_type_inner;
+ short wait_type_outer;
+
#ifdef CONFIG_LOCK_STAT
unsigned long contention_point[LOCKSTAT_POINTS];
unsigned long contending_point[LOCKSTAT_POINTS];
@@ -158,6 +177,8 @@ struct lockdep_map {
struct lock_class_key *key;
struct lock_class *class_cache[NR_LOCKDEP_CACHING_CLASSES];
const char *name;
+ short wait_type_outer; /* can be taken in this context */
+ short wait_type_inner; /* presents this context */
#ifdef CONFIG_LOCK_STAT
int cpu;
unsigned long ip;
@@ -299,8 +320,21 @@ extern void lockdep_unregister_key(struc
* to lockdep:
*/
-extern void lockdep_init_map(struct lockdep_map *lock, const char *name,
- struct lock_class_key *key, int subclass);
+extern void lockdep_init_map_waits(struct lockdep_map *lock, const char *name,
+ struct lock_class_key *key, int subclass, short inner, short outer);
+
+static inline void
+lockdep_init_map_wait(struct lockdep_map *lock, const char *name,
+ struct lock_class_key *key, int subclass, short inner)
+{
+ lockdep_init_map_waits(lock, name, key, subclass, inner, LD_WAIT_INV);
+}
+
+static inline void lockdep_init_map(struct lockdep_map *lock, const char *name,
+ struct lock_class_key *key, int subclass)
+{
+ lockdep_init_map_wait(lock, name, key, subclass, LD_WAIT_INV);
+}
/*
* Reinitialize a lock key - for cases where there is special locking or
@@ -308,18 +342,29 @@ extern void lockdep_init_map(struct lock
* of dependencies wrong: they are either too broad (they need a class-split)
* or they are too narrow (they suffer from a false class-split):
*/
-#define lockdep_set_class(lock, key) \
- lockdep_init_map(&(lock)->dep_map, #key, key, 0)
-#define lockdep_set_class_and_name(lock, key, name) \
- lockdep_init_map(&(lock)->dep_map, name, key, 0)
-#define lockdep_set_class_and_subclass(lock, key, sub) \
- lockdep_init_map(&(lock)->dep_map, #key, key, sub)
-#define lockdep_set_subclass(lock, sub) \
- lockdep_init_map(&(lock)->dep_map, #lock, \
- (lock)->dep_map.key, sub)
+#define lockdep_set_class(lock, key) \
+ lockdep_init_map_waits(&(lock)->dep_map, #key, key, 0, \
+ (lock)->dep_map.wait_type_inner, \
+ (lock)->dep_map.wait_type_outer)
+
+#define lockdep_set_class_and_name(lock, key, name) \
+ lockdep_init_map_waits(&(lock)->dep_map, name, key, 0, \
+ (lock)->dep_map.wait_type_inner, \
+ (lock)->dep_map.wait_type_outer)
+
+#define lockdep_set_class_and_subclass(lock, key, sub) \
+ lockdep_init_map_waits(&(lock)->dep_map, #key, key, sub,\
+ (lock)->dep_map.wait_type_inner, \
+ (lock)->dep_map.wait_type_outer)
+
+#define lockdep_set_subclass(lock, sub) \
+ lockdep_init_map_waits(&(lock)->dep_map, #lock, (lock)->dep_map.key, sub,\
+ (lock)->dep_map.wait_type_inner, \
+ (lock)->dep_map.wait_type_outer)
#define lockdep_set_novalidate_class(lock) \
lockdep_set_class_and_name(lock, &__lockdep_no_validate__, #lock)
+
/*
* Compare locking classes
*/
@@ -432,6 +477,10 @@ static inline void lockdep_set_selftest_
# define lock_set_class(l, n, k, s, i) do { } while (0)
# define lock_set_subclass(l, s, i) do { } while (0)
# define lockdep_init() do { } while (0)
+# define lockdep_init_map_waits(lock, name, key, sub, inner, outer) \
+ do { (void)(name); (void)(key); } while (0)
+# define lockdep_init_map_wait(lock, name, key, sub, inner) \
+ do { (void)(name); (void)(key); } while (0)
# define lockdep_init_map(lock, name, key, sub) \
do { (void)(name); (void)(key); } while (0)
# define lockdep_set_class(lock, key) do { (void)(key); } while (0)
--- a/include/linux/mutex.h
+++ b/include/linux/mutex.h
@@ -109,8 +109,11 @@ do { \
} while (0)
#ifdef CONFIG_DEBUG_LOCK_ALLOC
-# define __DEP_MAP_MUTEX_INITIALIZER(lockname) \
- , .dep_map = { .name = #lockname }
+# define __DEP_MAP_MUTEX_INITIALIZER(lockname) \
+ , .dep_map = { \
+ .name = #lockname, \
+ .wait_type_inner = LD_WAIT_SLEEP, \
+ }
#else
# define __DEP_MAP_MUTEX_INITIALIZER(lockname)
#endif
--- a/include/linux/rwlock_types.h
+++ b/include/linux/rwlock_types.h
@@ -22,7 +22,11 @@ typedef struct {
#define RWLOCK_MAGIC 0xdeaf1eed
#ifdef CONFIG_DEBUG_LOCK_ALLOC
-# define RW_DEP_MAP_INIT(lockname) .dep_map = { .name = #lockname }
+# define RW_DEP_MAP_INIT(lockname) \
+ .dep_map = { \
+ .name = #lockname, \
+ .wait_type_inner = LD_WAIT_CONFIG, \
+ }
#else
# define RW_DEP_MAP_INIT(lockname)
#endif
--- a/include/linux/rwsem.h
+++ b/include/linux/rwsem.h
@@ -71,7 +71,11 @@ static inline int rwsem_is_locked(struct
/* Common initializer macros and functions */
#ifdef CONFIG_DEBUG_LOCK_ALLOC
-# define __RWSEM_DEP_MAP_INIT(lockname) , .dep_map = { .name = #lockname }
+# define __RWSEM_DEP_MAP_INIT(lockname) \
+ , .dep_map = { \
+ .name = #lockname, \
+ .wait_type_inner = LD_WAIT_SLEEP, \
+ }
#else
# define __RWSEM_DEP_MAP_INIT(lockname)
#endif
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -970,6 +970,7 @@ struct task_struct {
#ifdef CONFIG_TRACE_IRQFLAGS
unsigned int irq_events;
+ unsigned int hardirq_threaded;
unsigned long hardirq_enable_ip;
unsigned long hardirq_disable_ip;
unsigned int hardirq_enable_event;
--- a/include/linux/spinlock.h
+++ b/include/linux/spinlock.h
@@ -93,12 +93,13 @@
#ifdef CONFIG_DEBUG_SPINLOCK
extern void __raw_spin_lock_init(raw_spinlock_t *lock, const char *name,
- struct lock_class_key *key);
-# define raw_spin_lock_init(lock) \
-do { \
- static struct lock_class_key __key; \
- \
- __raw_spin_lock_init((lock), #lock, &__key); \
+ struct lock_class_key *key, short inner);
+
+# define raw_spin_lock_init(lock) \
+do { \
+ static struct lock_class_key __key; \
+ \
+ __raw_spin_lock_init((lock), #lock, &__key, LD_WAIT_SPIN); \
} while (0)
#else
@@ -327,12 +328,26 @@ static __always_inline raw_spinlock_t *s
return &lock->rlock;
}
-#define spin_lock_init(_lock) \
-do { \
- spinlock_check(_lock); \
- raw_spin_lock_init(&(_lock)->rlock); \
+#ifdef CONFIG_DEBUG_SPINLOCK
+
+# define spin_lock_init(lock) \
+do { \
+ static struct lock_class_key __key; \
+ \
+ __raw_spin_lock_init(spinlock_check(lock), \
+ #lock, &__key, LD_WAIT_CONFIG); \
+} while (0)
+
+#else
+
+# define spin_lock_init(_lock) \
+do { \
+ spinlock_check(_lock); \
+ *(_lock) = __SPIN_LOCK_UNLOCKED(_lock); \
} while (0)
+#endif
+
static __always_inline void spin_lock(spinlock_t *lock)
{
raw_spin_lock(&lock->rlock);
--- a/include/linux/spinlock_types.h
+++ b/include/linux/spinlock_types.h
@@ -33,8 +33,18 @@ typedef struct raw_spinlock {
#define SPINLOCK_OWNER_INIT ((void *)-1L)
#ifdef CONFIG_DEBUG_LOCK_ALLOC
-# define SPIN_DEP_MAP_INIT(lockname) .dep_map = { .name = #lockname }
+# define RAW_SPIN_DEP_MAP_INIT(lockname) \
+ .dep_map = { \
+ .name = #lockname, \
+ .wait_type_inner = LD_WAIT_SPIN, \
+ }
+# define SPIN_DEP_MAP_INIT(lockname) \
+ .dep_map = { \
+ .name = #lockname, \
+ .wait_type_inner = LD_WAIT_CONFIG, \
+ }
#else
+# define RAW_SPIN_DEP_MAP_INIT(lockname)
# define SPIN_DEP_MAP_INIT(lockname)
#endif
@@ -51,7 +61,7 @@ typedef struct raw_spinlock {
{ \
.raw_lock = __ARCH_SPIN_LOCK_UNLOCKED, \
SPIN_DEBUG_INIT(lockname) \
- SPIN_DEP_MAP_INIT(lockname) }
+ RAW_SPIN_DEP_MAP_INIT(lockname) }
#define __RAW_SPIN_LOCK_UNLOCKED(lockname) \
(raw_spinlock_t) __RAW_SPIN_LOCK_INITIALIZER(lockname)
@@ -72,11 +82,17 @@ typedef struct spinlock {
};
} spinlock_t;
+#define ___SPIN_LOCK_INITIALIZER(lockname) \
+ { \
+ .raw_lock = __ARCH_SPIN_LOCK_UNLOCKED, \
+ SPIN_DEBUG_INIT(lockname) \
+ SPIN_DEP_MAP_INIT(lockname) }
+
#define __SPIN_LOCK_INITIALIZER(lockname) \
- { { .rlock = __RAW_SPIN_LOCK_INITIALIZER(lockname) } }
+ { { .rlock = ___SPIN_LOCK_INITIALIZER(lockname) } }
#define __SPIN_LOCK_UNLOCKED(lockname) \
- (spinlock_t ) __SPIN_LOCK_INITIALIZER(lockname)
+ (spinlock_t) __SPIN_LOCK_INITIALIZER(lockname)
#define DEFINE_SPINLOCK(x) spinlock_t x = __SPIN_LOCK_UNLOCKED(x)
--- a/kernel/irq/handle.c
+++ b/kernel/irq/handle.c
@@ -145,6 +145,13 @@ irqreturn_t __handle_irq_event_percpu(st
for_each_action_of_desc(desc, action) {
irqreturn_t res;
+ /*
+ * If this IRQ would be threaded under force_irqthreads, mark it so.
+ */
+ if (irq_settings_can_thread(desc) &&
+ !(action->flags & (IRQF_NO_THREAD | IRQF_PERCPU | IRQF_ONESHOT)))
+ trace_hardirq_threaded();
+
trace_irq_handler_entry(irq, action);
res = action->handler(irq, action->dev_id);
trace_irq_handler_exit(irq, action, res);
--- a/kernel/locking/lockdep.c
+++ b/kernel/locking/lockdep.c
@@ -653,7 +653,9 @@ static void print_lock_name(struct lock_
printk(KERN_CONT " (");
__print_lock_name(class);
- printk(KERN_CONT "){%s}", usage);
+ printk(KERN_CONT "){%s}-{%hd:%hd}", usage,
+ class->wait_type_outer ?: class->wait_type_inner,
+ class->wait_type_inner);
}
static void print_lockdep_cache(struct lockdep_map *lock)
@@ -1230,6 +1232,8 @@ register_lock_class(struct lockdep_map *
WARN_ON_ONCE(!list_empty(&class->locks_before));
WARN_ON_ONCE(!list_empty(&class->locks_after));
class->name_version = count_matching_names(class);
+ class->wait_type_inner = lock->wait_type_inner;
+ class->wait_type_outer = lock->wait_type_outer;
/*
* We use RCU's safe list-add method to make
* parallel walking of the hash-list safe:
@@ -3682,6 +3686,113 @@ static int mark_lock(struct task_struct
return ret;
}
+static int
+print_lock_invalid_wait_context(struct task_struct *curr,
+ struct held_lock *hlock)
+{
+ if (!debug_locks_off())
+ return 0;
+ if (debug_locks_silent)
+ return 0;
+
+ pr_warn("\n");
+ pr_warn("=============================\n");
+ pr_warn("[ BUG: Invalid wait context ]\n");
+ print_kernel_ident();
+ pr_warn("-----------------------------\n");
+
+ pr_warn("%s/%d is trying to lock:\n", curr->comm, task_pid_nr(curr));
+ print_lock(hlock);
+
+ pr_warn("other info that might help us debug this:\n");
+ lockdep_print_held_locks(curr);
+
+ pr_warn("stack backtrace:\n");
+ dump_stack();
+
+ return 0;
+}
+
+/*
+ * Verify the wait_type context.
+ *
+ * This check validates we takes locks in the right wait-type order; that is it
+ * ensures that we do not take mutexes inside spinlocks and do not attempt to
+ * acquire spinlocks inside raw_spinlocks and the sort.
+ *
+ * The entire thing is slightly more complex because of RCU, RCU is a lock that
+ * can be taken from (pretty much) any context but also has constraints.
+ * However when taken in a stricter environment the RCU lock does not loosen
+ * the constraints.
+ *
+ * Therefore we must look for the strictest environment in the lock stack and
+ * compare that to the lock we're trying to acquire.
+ */
+static int check_wait_context(struct task_struct *curr, struct held_lock *next)
+{
+ short next_inner = hlock_class(next)->wait_type_inner;
+ short next_outer = hlock_class(next)->wait_type_outer;
+ short curr_inner;
+ int depth;
+
+ if (!curr->lockdep_depth || !next_inner || next->trylock)
+ return 0;
+
+ if (!next_outer)
+ next_outer = next_inner;
+
+ /*
+ * Find start of current irq_context..
+ */
+ for (depth = curr->lockdep_depth - 1; depth >= 0; depth--) {
+ struct held_lock *prev = curr->held_locks + depth;
+ if (prev->irq_context != next->irq_context)
+ break;
+ }
+ depth++;
+
+ /*
+ * Set appropriate wait type for the context; for IRQs we have to take
+ * into account force_irqthread as that is implied by PREEMPT_RT.
+ */
+ if (curr->hardirq_context) {
+ /*
+ * Check if force_irqthreads will run us threaded.
+ */
+ if (curr->hardirq_threaded)
+ curr_inner = LD_WAIT_CONFIG;
+ else
+ curr_inner = LD_WAIT_SPIN;
+ } else if (curr->softirq_context) {
+ /*
+ * Softirqs are always threaded.
+ */
+ curr_inner = LD_WAIT_CONFIG;
+ } else {
+ curr_inner = LD_WAIT_MAX;
+ }
+
+ for (; depth < curr->lockdep_depth; depth++) {
+ struct held_lock *prev = curr->held_locks + depth;
+ short prev_inner = hlock_class(prev)->wait_type_inner;
+
+ if (prev_inner) {
+ /*
+ * We can have a bigger inner than a previous one
+ * when outer is smaller than inner, as with RCU.
+ *
+ * Also due to trylocks.
+ */
+ curr_inner = min(curr_inner, prev_inner);
+ }
+ }
+
+ if (next_outer > curr_inner)
+ return print_lock_invalid_wait_context(curr, next);
+
+ return 0;
+}
+
#else /* CONFIG_PROVE_LOCKING */
static inline int
@@ -3701,13 +3812,20 @@ static inline int separate_irq_context(s
return 0;
}
+static inline int check_wait_context(struct task_struct *curr,
+ struct held_lock *next)
+{
+ return 0;
+}
+
#endif /* CONFIG_PROVE_LOCKING */
/*
* Initialize a lock instance's lock-class mapping info:
*/
-void lockdep_init_map(struct lockdep_map *lock, const char *name,
- struct lock_class_key *key, int subclass)
+void lockdep_init_map_waits(struct lockdep_map *lock, const char *name,
+ struct lock_class_key *key, int subclass,
+ short inner, short outer)
{
int i;
@@ -3728,6 +3846,9 @@ void lockdep_init_map(struct lockdep_map
lock->name = name;
+ lock->wait_type_outer = outer;
+ lock->wait_type_inner = inner;
+
/*
* No key, no joy, we need to hash something.
*/
@@ -3761,7 +3882,7 @@ void lockdep_init_map(struct lockdep_map
raw_local_irq_restore(flags);
}
}
-EXPORT_SYMBOL_GPL(lockdep_init_map);
+EXPORT_SYMBOL_GPL(lockdep_init_map_waits);
struct lock_class_key __lockdep_no_validate__;
EXPORT_SYMBOL_GPL(__lockdep_no_validate__);
@@ -3862,7 +3983,7 @@ static int __lock_acquire(struct lockdep
class_idx = class - lock_classes;
- if (depth) {
+ if (depth) { /* we're holding locks */
hlock = curr->held_locks + depth - 1;
if (hlock->class_idx == class_idx && nest_lock) {
if (!references)
@@ -3904,6 +4025,9 @@ static int __lock_acquire(struct lockdep
#endif
hlock->pin_count = pin_count;
+ if (check_wait_context(curr, hlock))
+ return 0;
+
/* Initialize the lock usage bit */
if (!mark_usage(curr, hlock, check))
return 0;
@@ -4139,7 +4263,9 @@ static int
return 0;
}
- lockdep_init_map(lock, name, key, 0);
+ lockdep_init_map_waits(lock, name, key, 0,
+ lock->wait_type_inner,
+ lock->wait_type_outer);
class = register_lock_class(lock, subclass, 0);
hlock->class_idx = class - lock_classes;
--- a/kernel/locking/mutex-debug.c
+++ b/kernel/locking/mutex-debug.c
@@ -85,7 +85,7 @@ void debug_mutex_init(struct mutex *lock
* Make sure we are not reinitializing a held lock:
*/
debug_check_no_locks_freed((void *)lock, sizeof(*lock));
- lockdep_init_map(&lock->dep_map, name, key, 0);
+ lockdep_init_map_wait(&lock->dep_map, name, key, 0, LD_WAIT_SLEEP);
#endif
lock->magic = lock;
}
--- a/kernel/locking/rwsem.c
+++ b/kernel/locking/rwsem.c
@@ -329,7 +329,7 @@ void __init_rwsem(struct rw_semaphore *s
* Make sure we are not reinitializing a held semaphore:
*/
debug_check_no_locks_freed((void *)sem, sizeof(*sem));
- lockdep_init_map(&sem->dep_map, name, key, 0);
+ lockdep_init_map_wait(&sem->dep_map, name, key, 0, LD_WAIT_SLEEP);
#endif
#ifdef CONFIG_DEBUG_RWSEMS
sem->magic = sem;
--- a/kernel/locking/spinlock_debug.c
+++ b/kernel/locking/spinlock_debug.c
@@ -14,14 +14,14 @@
#include <linux/export.h>
void __raw_spin_lock_init(raw_spinlock_t *lock, const char *name,
- struct lock_class_key *key)
+ struct lock_class_key *key, short inner)
{
#ifdef CONFIG_DEBUG_LOCK_ALLOC
/*
* Make sure we are not reinitializing a held lock:
*/
debug_check_no_locks_freed((void *)lock, sizeof(*lock));
- lockdep_init_map(&lock->dep_map, name, key, 0);
+ lockdep_init_map_wait(&lock->dep_map, name, key, 0, inner);
#endif
lock->raw_lock = (arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED;
lock->magic = SPINLOCK_MAGIC;
@@ -39,7 +39,7 @@ void __rwlock_init(rwlock_t *lock, const
* Make sure we are not reinitializing a held lock:
*/
debug_check_no_locks_freed((void *)lock, sizeof(*lock));
- lockdep_init_map(&lock->dep_map, name, key, 0);
+ lockdep_init_map_wait(&lock->dep_map, name, key, 0, LD_WAIT_CONFIG);
#endif
lock->raw_lock = (arch_rwlock_t) __ARCH_RW_LOCK_UNLOCKED;
lock->magic = RWLOCK_MAGIC;
--- a/kernel/rcu/update.c
+++ b/kernel/rcu/update.c
@@ -227,18 +227,30 @@ core_initcall(rcu_set_runtime_mode);
#ifdef CONFIG_DEBUG_LOCK_ALLOC
static struct lock_class_key rcu_lock_key;
-struct lockdep_map rcu_lock_map =
- STATIC_LOCKDEP_MAP_INIT("rcu_read_lock", &rcu_lock_key);
+struct lockdep_map rcu_lock_map = {
+ .name = "rcu_read_lock",
+ .key = &rcu_lock_key,
+ .wait_type_outer = LD_WAIT_FREE,
+ .wait_type_inner = LD_WAIT_CONFIG, /* XXX PREEMPT_RCU ? */
+};
EXPORT_SYMBOL_GPL(rcu_lock_map);
static struct lock_class_key rcu_bh_lock_key;
-struct lockdep_map rcu_bh_lock_map =
- STATIC_LOCKDEP_MAP_INIT("rcu_read_lock_bh", &rcu_bh_lock_key);
+struct lockdep_map rcu_bh_lock_map = {
+ .name = "rcu_read_lock_bh",
+ .key = &rcu_bh_lock_key,
+ .wait_type_outer = LD_WAIT_FREE,
+ .wait_type_inner = LD_WAIT_CONFIG, /* PREEMPT_LOCK also makes BH preemptible */
+};
EXPORT_SYMBOL_GPL(rcu_bh_lock_map);
static struct lock_class_key rcu_sched_lock_key;
-struct lockdep_map rcu_sched_lock_map =
- STATIC_LOCKDEP_MAP_INIT("rcu_read_lock_sched", &rcu_sched_lock_key);
+struct lockdep_map rcu_sched_lock_map = {
+ .name = "rcu_read_lock_sched",
+ .key = &rcu_sched_lock_key,
+ .wait_type_outer = LD_WAIT_FREE,
+ .wait_type_inner = LD_WAIT_SPIN,
+};
EXPORT_SYMBOL_GPL(rcu_sched_lock_map);
static struct lock_class_key rcu_callback_key;
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -1086,6 +1086,23 @@ config PROVE_LOCKING
For more details, see Documentation/locking/lockdep-design.rst.
+config PROVE_RAW_LOCK_NESTING
+ bool "Enable raw_spinlock - spinlock nesting checks"
+ depends on PROVE_LOCKING
+ default n
+ help
+ Enable the raw_spinlock vs. spinlock nesting checks which ensure
+ that the lock nesting rules for PREEMPT_RT enabled kernels are
+ not violated.
+
+ NOTE: There are known nesting problems. So if you enable this
+ option expect lockdep splats until these problems have been fully
+ addressed which is work in progress. This config switch allows to
+ identify and analyze these problems. It will be removed and the
+ check permanentely enabled once the main issues have been fixed.
+
+ If unsure, select N.
+
config LOCK_STAT
bool "Lock usage statistics"
depends on DEBUG_KERNEL && LOCK_DEBUGGING_SUPPORT
^ permalink raw reply
* [patch V3 16/20] completion: Use simple wait queues
From: Thomas Gleixner @ 2020-03-21 11:26 UTC (permalink / raw)
To: LKML
Cc: Randy Dunlap, linux-ia64, Peter Zijlstra, linux-pci,
Sebastian Siewior, platform-driver-x86, Guo Ren, Joel Fernandes,
Vincent Chen, Ingo Molnar, Jonathan Corbet, Davidlohr Bueso,
linux-acpi, Brian Cain, Davidlohr Bueso, Paul E . McKenney,
linux-hexagon, Rafael J. Wysocki, linux-csky, Linus Torvalds,
Darren Hart, Zhang Rui, Len Brown, Fenghua Yu, Arnd Bergmann,
linux-pm, linuxppc-dev, Greentime Hu, Bjorn Helgaas,
Kurt Schwemmer, Kalle Valo, kbuild test robot, Felipe Balbi,
Michal Simek, Tony Luck, Nick Hu, Geoff Levand,
Greg Kroah-Hartman, linux-usb, linux-wireless, Oleg Nesterov,
netdev, Logan Gunthorpe, David S. Miller, Andy Shevchenko
In-Reply-To: <20200321112544.878032781@linutronix.de>
From: Thomas Gleixner <tglx@linutronix.de>
completion uses a wait_queue_head_t to enqueue waiters.
wait_queue_head_t contains a spinlock_t to protect the list of waiters
which excludes it from being used in truly atomic context on a PREEMPT_RT
enabled kernel.
The spinlock in the wait queue head cannot be replaced by a raw_spinlock
because:
- wait queues can have custom wakeup callbacks, which acquire other
spinlock_t locks and have potentially long execution times
- wake_up() walks an unbounded number of list entries during the wake up
and may wake an unbounded number of waiters.
For simplicity and performance reasons complete() should be usable on
PREEMPT_RT enabled kernels.
completions do not use custom wakeup callbacks and are usually single
waiter, except for a few corner cases.
Replace the wait queue in the completion with a simple wait queue (swait),
which uses a raw_spinlock_t for protecting the waiter list and therefore is
safe to use inside truly atomic regions on PREEMPT_RT.
There is no semantical or functional change:
- completions use the exclusive wait mode which is what swait provides
- complete() wakes one exclusive waiter
- complete_all() wakes all waiters while holding the lock which protects
the wait queue against newly incoming waiters. The conversion to swait
preserves this behaviour.
complete_all() might cause unbound latencies with a large number of waiters
being woken at once, but most complete_all() usage sites are either in
testing or initialization code or have only a really small number of
concurrent waiters which for now does not cause a latency problem. Keep it
simple for now.
The fixup of the warning check in the USB gadget driver is just a straight
forward conversion of the lockless waiter check from one waitqueue type to
the other.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Joel Fernandes (Google) <joel@joelfernandes.org>
Reviewed-by: Davidlohr Bueso <dbueso@suse.de>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Acked-by: Linus Torvalds <torvalds@linux-foundation.org>
---
V2: Split out the orinoco and usb gadget parts and amended change log
---
drivers/usb/gadget/function/f_fs.c | 2 +-
include/linux/completion.h | 8 ++++----
kernel/sched/completion.c | 36 +++++++++++++++++++-----------------
3 files changed, 24 insertions(+), 22 deletions(-)
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -1703,7 +1703,7 @@ static void ffs_data_put(struct ffs_data
pr_info("%s(): freeing\n", __func__);
ffs_data_clear(ffs);
BUG_ON(waitqueue_active(&ffs->ev.waitq) ||
- waitqueue_active(&ffs->ep0req_completion.wait) ||
+ swait_active(&ffs->ep0req_completion.wait) ||
waitqueue_active(&ffs->wait));
destroy_workqueue(ffs->io_completion_wq);
kfree(ffs->dev_name);
--- a/include/linux/completion.h
+++ b/include/linux/completion.h
@@ -9,7 +9,7 @@
* See kernel/sched/completion.c for details.
*/
-#include <linux/wait.h>
+#include <linux/swait.h>
/*
* struct completion - structure used to maintain state for a "completion"
@@ -25,7 +25,7 @@
*/
struct completion {
unsigned int done;
- wait_queue_head_t wait;
+ struct swait_queue_head wait;
};
#define init_completion_map(x, m) __init_completion(x)
@@ -34,7 +34,7 @@ static inline void complete_acquire(stru
static inline void complete_release(struct completion *x) {}
#define COMPLETION_INITIALIZER(work) \
- { 0, __WAIT_QUEUE_HEAD_INITIALIZER((work).wait) }
+ { 0, __SWAIT_QUEUE_HEAD_INITIALIZER((work).wait) }
#define COMPLETION_INITIALIZER_ONSTACK_MAP(work, map) \
(*({ init_completion_map(&(work), &(map)); &(work); }))
@@ -85,7 +85,7 @@ static inline void complete_release(stru
static inline void __init_completion(struct completion *x)
{
x->done = 0;
- init_waitqueue_head(&x->wait);
+ init_swait_queue_head(&x->wait);
}
/**
--- a/kernel/sched/completion.c
+++ b/kernel/sched/completion.c
@@ -29,12 +29,12 @@ void complete(struct completion *x)
{
unsigned long flags;
- spin_lock_irqsave(&x->wait.lock, flags);
+ raw_spin_lock_irqsave(&x->wait.lock, flags);
if (x->done != UINT_MAX)
x->done++;
- __wake_up_locked(&x->wait, TASK_NORMAL, 1);
- spin_unlock_irqrestore(&x->wait.lock, flags);
+ swake_up_locked(&x->wait);
+ raw_spin_unlock_irqrestore(&x->wait.lock, flags);
}
EXPORT_SYMBOL(complete);
@@ -58,10 +58,12 @@ void complete_all(struct completion *x)
{
unsigned long flags;
- spin_lock_irqsave(&x->wait.lock, flags);
+ WARN_ON(irqs_disabled());
+
+ raw_spin_lock_irqsave(&x->wait.lock, flags);
x->done = UINT_MAX;
- __wake_up_locked(&x->wait, TASK_NORMAL, 0);
- spin_unlock_irqrestore(&x->wait.lock, flags);
+ swake_up_all_locked(&x->wait);
+ raw_spin_unlock_irqrestore(&x->wait.lock, flags);
}
EXPORT_SYMBOL(complete_all);
@@ -70,20 +72,20 @@ do_wait_for_common(struct completion *x,
long (*action)(long), long timeout, int state)
{
if (!x->done) {
- DECLARE_WAITQUEUE(wait, current);
+ DECLARE_SWAITQUEUE(wait);
- __add_wait_queue_entry_tail_exclusive(&x->wait, &wait);
do {
if (signal_pending_state(state, current)) {
timeout = -ERESTARTSYS;
break;
}
+ __prepare_to_swait(&x->wait, &wait);
__set_current_state(state);
- spin_unlock_irq(&x->wait.lock);
+ raw_spin_unlock_irq(&x->wait.lock);
timeout = action(timeout);
- spin_lock_irq(&x->wait.lock);
+ raw_spin_lock_irq(&x->wait.lock);
} while (!x->done && timeout);
- __remove_wait_queue(&x->wait, &wait);
+ __finish_swait(&x->wait, &wait);
if (!x->done)
return timeout;
}
@@ -100,9 +102,9 @@ static inline long __sched
complete_acquire(x);
- spin_lock_irq(&x->wait.lock);
+ raw_spin_lock_irq(&x->wait.lock);
timeout = do_wait_for_common(x, action, timeout, state);
- spin_unlock_irq(&x->wait.lock);
+ raw_spin_unlock_irq(&x->wait.lock);
complete_release(x);
@@ -291,12 +293,12 @@ bool try_wait_for_completion(struct comp
if (!READ_ONCE(x->done))
return false;
- spin_lock_irqsave(&x->wait.lock, flags);
+ raw_spin_lock_irqsave(&x->wait.lock, flags);
if (!x->done)
ret = false;
else if (x->done != UINT_MAX)
x->done--;
- spin_unlock_irqrestore(&x->wait.lock, flags);
+ raw_spin_unlock_irqrestore(&x->wait.lock, flags);
return ret;
}
EXPORT_SYMBOL(try_wait_for_completion);
@@ -322,8 +324,8 @@ bool completion_done(struct completion *
* otherwise we can end up freeing the completion before complete()
* is done referencing it.
*/
- spin_lock_irqsave(&x->wait.lock, flags);
- spin_unlock_irqrestore(&x->wait.lock, flags);
+ raw_spin_lock_irqsave(&x->wait.lock, flags);
+ raw_spin_unlock_irqrestore(&x->wait.lock, flags);
return true;
}
EXPORT_SYMBOL(completion_done);
^ permalink raw reply
* [patch V3 09/20] ia64: Remove mm.h from asm/uaccess.h
From: Thomas Gleixner @ 2020-03-21 11:25 UTC (permalink / raw)
To: LKML
Cc: Randy Dunlap, linux-ia64, Peter Zijlstra, linux-pci,
Sebastian Siewior, platform-driver-x86, Guo Ren, Joel Fernandes,
Vincent Chen, Ingo Molnar, Jonathan Corbet, Davidlohr Bueso,
kbuild test robot, Brian Cain, linux-acpi, Paul E . McKenney,
linux-hexagon, Rafael J. Wysocki, linux-csky, Linus Torvalds,
Darren Hart, Zhang Rui, Len Brown, Fenghua Yu, Arnd Bergmann,
linux-pm, linuxppc-dev, Greentime Hu, Bjorn Helgaas,
Kurt Schwemmer, Kalle Valo, Felipe Balbi, Michal Simek, Tony Luck,
Nick Hu, Geoff Levand, netdev, linux-usb, linux-wireless,
Oleg Nesterov, Davidlohr Bueso, Greg Kroah-Hartman,
Logan Gunthorpe, David S. Miller, Andy Shevchenko
In-Reply-To: <20200321112544.878032781@linutronix.de>
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
The defconfig compiles without linux/mm.h. With mm.h included the
include chain leands to:
| CC kernel/locking/percpu-rwsem.o
| In file included from include/linux/huge_mm.h:8,
| from include/linux/mm.h:567,
| from arch/ia64/include/asm/uaccess.h:,
| from include/linux/uaccess.h:11,
| from include/linux/sched/task.h:11,
| from include/linux/sched/signal.h:9,
| from include/linux/rcuwait.h:6,
| from include/linux/percpu-rwsem.h:8,
| from kernel/locking/percpu-rwsem.c:6:
| include/linux/fs.h:1422:29: error: array type has incomplete element type 'struct percpu_rw_semaphore'
| 1422 | struct percpu_rw_semaphore rw_sem[SB_FREEZE_LEVELS];
once rcuwait.h includes linux/sched/signal.h.
Remove the linux/mm.h include.
Reported-by: kbuild test robot <lkp@intel.com>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: linux-ia64@vger.kernel.org
---
V3: New patch
---
arch/ia64/include/asm/uaccess.h | 1 -
arch/ia64/kernel/process.c | 1 +
arch/ia64/mm/ioremap.c | 1 +
3 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/ia64/include/asm/uaccess.h b/arch/ia64/include/asm/uaccess.h
index 89782ad3fb887..5c7e79eccaeed 100644
--- a/arch/ia64/include/asm/uaccess.h
+++ b/arch/ia64/include/asm/uaccess.h
@@ -35,7 +35,6 @@
#include <linux/compiler.h>
#include <linux/page-flags.h>
-#include <linux/mm.h>
#include <asm/intrinsics.h>
#include <asm/pgtable.h>
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
index 968b5f33e725e..743aaf5283278 100644
--- a/arch/ia64/kernel/process.c
+++ b/arch/ia64/kernel/process.c
@@ -681,3 +681,4 @@ machine_power_off (void)
machine_halt();
}
+EXPORT_SYMBOL(ia64_delay_loop);
diff --git a/arch/ia64/mm/ioremap.c b/arch/ia64/mm/ioremap.c
index a09cfa0645369..55fd3eb753ff9 100644
--- a/arch/ia64/mm/ioremap.c
+++ b/arch/ia64/mm/ioremap.c
@@ -8,6 +8,7 @@
#include <linux/module.h>
#include <linux/efi.h>
#include <linux/io.h>
+#include <linux/mm.h>
#include <linux/vmalloc.h>
#include <asm/io.h>
#include <asm/meminit.h>
--
2.26.0.rc2
^ permalink raw reply related
* [patch V3 18/20] lockdep: Add hrtimer context tracing bits
From: Thomas Gleixner @ 2020-03-21 11:26 UTC (permalink / raw)
To: LKML
Cc: Randy Dunlap, linux-ia64, Peter Zijlstra, linux-pci,
Sebastian Siewior, platform-driver-x86, Guo Ren, Joel Fernandes,
Vincent Chen, Ingo Molnar, Jonathan Corbet, Davidlohr Bueso,
kbuild test robot, Brian Cain, linux-acpi, Paul E . McKenney,
linux-hexagon, Rafael J. Wysocki, linux-csky, Linus Torvalds,
Darren Hart, Zhang Rui, Len Brown, Fenghua Yu, Arnd Bergmann,
linux-pm, linuxppc-dev, Greentime Hu, Bjorn Helgaas,
Kurt Schwemmer, Kalle Valo, Felipe Balbi, Michal Simek, Tony Luck,
Nick Hu, Geoff Levand, Greg Kroah-Hartman, linux-usb,
linux-wireless, Oleg Nesterov, Davidlohr Bueso, netdev,
Logan Gunthorpe, David S. Miller, Andy Shevchenko
In-Reply-To: <20200321112544.878032781@linutronix.de>
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Set current->irq_config = 1 for hrtimers which are not marked to expire in
hard interrupt context during hrtimer_init(). These timers will expire in
softirq context on PREEMPT_RT.
Setting this allows lockdep to differentiate these timers. If a timer is
marked to expire in hard interrupt context then the timer callback is not
supposed to acquire a regular spinlock instead of a raw_spinlock in the
expiry callback.
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
include/linux/irqflags.h | 15 +++++++++++++++
include/linux/sched.h | 1 +
kernel/locking/lockdep.c | 2 +-
kernel/time/hrtimer.c | 6 +++++-
4 files changed, 22 insertions(+), 2 deletions(-)
--- a/include/linux/irqflags.h
+++ b/include/linux/irqflags.h
@@ -56,6 +56,19 @@ do { \
do { \
current->softirq_context--; \
} while (0)
+
+# define lockdep_hrtimer_enter(__hrtimer) \
+ do { \
+ if (!__hrtimer->is_hard) \
+ current->irq_config = 1; \
+ } while (0)
+
+# define lockdep_hrtimer_exit(__hrtimer) \
+ do { \
+ if (!__hrtimer->is_hard) \
+ current->irq_config = 0; \
+ } while (0)
+
#else
# define trace_hardirqs_on() do { } while (0)
# define trace_hardirqs_off() do { } while (0)
@@ -68,6 +81,8 @@ do { \
# define trace_hardirq_exit() do { } while (0)
# define lockdep_softirq_enter() do { } while (0)
# define lockdep_softirq_exit() do { } while (0)
+# define lockdep_hrtimer_enter(__hrtimer) do { } while (0)
+# define lockdep_hrtimer_exit(__hrtimer) do { } while (0)
#endif
#if defined(CONFIG_IRQSOFF_TRACER) || \
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -983,6 +983,7 @@ struct task_struct {
unsigned int softirq_enable_event;
int softirqs_enabled;
int softirq_context;
+ int irq_config;
#endif
#ifdef CONFIG_LOCKDEP
--- a/kernel/locking/lockdep.c
+++ b/kernel/locking/lockdep.c
@@ -3759,7 +3759,7 @@ static int check_wait_context(struct tas
/*
* Check if force_irqthreads will run us threaded.
*/
- if (curr->hardirq_threaded)
+ if (curr->hardirq_threaded || curr->irq_config)
curr_inner = LD_WAIT_CONFIG;
else
curr_inner = LD_WAIT_SPIN;
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -1404,7 +1404,7 @@ static void __hrtimer_init(struct hrtime
base = softtimer ? HRTIMER_MAX_CLOCK_BASES / 2 : 0;
base += hrtimer_clockid_to_base(clock_id);
timer->is_soft = softtimer;
- timer->is_hard = !softtimer;
+ timer->is_hard = !!(mode & HRTIMER_MODE_HARD);
timer->base = &cpu_base->clock_base[base];
timerqueue_init(&timer->node);
}
@@ -1514,7 +1514,11 @@ static void __run_hrtimer(struct hrtimer
*/
raw_spin_unlock_irqrestore(&cpu_base->lock, flags);
trace_hrtimer_expire_entry(timer, now);
+ lockdep_hrtimer_enter(timer);
+
restart = fn(timer);
+
+ lockdep_hrtimer_exit(timer);
trace_hrtimer_expire_exit(timer);
raw_spin_lock_irq(&cpu_base->lock);
^ permalink raw reply
* [patch V3 01/20] PCI/switchtec: Fix init_completion race condition with poll_wait()
From: Thomas Gleixner @ 2020-03-21 11:25 UTC (permalink / raw)
To: LKML
Cc: Randy Dunlap, linux-ia64, Peter Zijlstra, linux-pci,
Sebastian Siewior, platform-driver-x86, Guo Ren, Joel Fernandes,
Vincent Chen, Ingo Molnar, Jonathan Corbet, Davidlohr Bueso,
kbuild test robot, Brian Cain, linux-acpi, Paul E . McKenney,
linux-hexagon, Rafael J. Wysocki, linux-csky, Linus Torvalds,
Darren Hart, Zhang Rui, Len Brown, Fenghua Yu, Arnd Bergmann,
linux-pm, linuxppc-dev, Greentime Hu, Bjorn Helgaas,
Kurt Schwemmer, Kalle Valo, Felipe Balbi, Michal Simek, Tony Luck,
Nick Hu, Geoff Levand, Greg Kroah-Hartman, linux-usb,
linux-wireless, Oleg Nesterov, Davidlohr Bueso, netdev,
Logan Gunthorpe, David S. Miller, Andy Shevchenko
In-Reply-To: <20200321112544.878032781@linutronix.de>
From: Logan Gunthorpe <logang@deltatee.com>
The call to init_completion() in mrpc_queue_cmd() can theoretically
race with the call to poll_wait() in switchtec_dev_poll().
poll() write()
switchtec_dev_poll() switchtec_dev_write()
poll_wait(&s->comp.wait); mrpc_queue_cmd()
init_completion(&s->comp)
init_waitqueue_head(&s->comp.wait)
To my knowledge, no one has hit this bug.
Fix this by using reinit_completion() instead of init_completion() in
mrpc_queue_cmd().
Fixes: 080b47def5e5 ("MicroSemi Switchtec management interface driver")
Reported-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: Bjorn Helgaas <bhelgaas@google.com>
Cc: Kurt Schwemmer <kurt.schwemmer@microsemi.com>
Cc: linux-pci@vger.kernel.org
Link: https://lkml.kernel.org/r/20200313183608.2646-1-logang@deltatee.com
---
drivers/pci/switch/switchtec.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/pci/switch/switchtec.c b/drivers/pci/switch/switchtec.c
index a823b4b8ef8a..81dc7ac01381 100644
--- a/drivers/pci/switch/switchtec.c
+++ b/drivers/pci/switch/switchtec.c
@@ -175,7 +175,7 @@ static int mrpc_queue_cmd(struct switchtec_user *stuser)
kref_get(&stuser->kref);
stuser->read_len = sizeof(stuser->data);
stuser_set_state(stuser, MRPC_QUEUED);
- init_completion(&stuser->comp);
+ reinit_completion(&stuser->comp);
list_add_tail(&stuser->list, &stdev->mrpc_queue);
mrpc_cmd_submit(stdev);
--
2.20.1
^ permalink raw reply related
* [patch V3 11/20] rcuwait: Add @state argument to rcuwait_wait_event()
From: Thomas Gleixner @ 2020-03-21 11:25 UTC (permalink / raw)
To: LKML
Cc: Randy Dunlap, linux-ia64, Peter Zijlstra, linux-pci,
Sebastian Siewior, platform-driver-x86, Guo Ren, Joel Fernandes,
Vincent Chen, Ingo Molnar, Jonathan Corbet, Davidlohr Bueso,
kbuild test robot, Brian Cain, linux-acpi, Paul E . McKenney,
linux-hexagon, Rafael J. Wysocki, linux-csky, Linus Torvalds,
Darren Hart, Zhang Rui, Len Brown, Fenghua Yu, Arnd Bergmann,
linux-pm, linuxppc-dev, Greentime Hu, Bjorn Helgaas,
Kurt Schwemmer, Kalle Valo, Felipe Balbi, Michal Simek, Tony Luck,
Nick Hu, Geoff Levand, Greg Kroah-Hartman, linux-usb,
linux-wireless, Oleg Nesterov, Davidlohr Bueso, netdev,
Logan Gunthorpe, David S. Miller, Andy Shevchenko
In-Reply-To: <20200321112544.878032781@linutronix.de>
From: Peter Zijlstra (Intel) <peterz@infradead.org>
Extend rcuwait_wait_event() with a state variable so that it is not
restricted to UNINTERRUPTIBLE waits.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Davidlohr Bueso <dave@stgolabs.net>
---
include/linux/rcuwait.h | 12 ++++++++++--
kernel/locking/percpu-rwsem.c | 2 +-
2 files changed, 11 insertions(+), 3 deletions(-)
--- a/include/linux/rcuwait.h
+++ b/include/linux/rcuwait.h
@@ -3,6 +3,7 @@
#define _LINUX_RCUWAIT_H_
#include <linux/rcupdate.h>
+#include <linux/sched/signal.h>
/*
* rcuwait provides a way of blocking and waking up a single
@@ -30,23 +31,30 @@ extern void rcuwait_wake_up(struct rcuwa
* The caller is responsible for locking around rcuwait_wait_event(),
* such that writes to @task are properly serialized.
*/
-#define rcuwait_wait_event(w, condition) \
+#define rcuwait_wait_event(w, condition, state) \
({ \
+ int __ret = 0; \
rcu_assign_pointer((w)->task, current); \
for (;;) { \
/* \
* Implicit barrier (A) pairs with (B) in \
* rcuwait_wake_up(). \
*/ \
- set_current_state(TASK_UNINTERRUPTIBLE); \
+ set_current_state(state); \
if (condition) \
break; \
\
+ if (signal_pending_state(state, current)) { \
+ __ret = -EINTR; \
+ break; \
+ } \
+ \
schedule(); \
} \
\
WRITE_ONCE((w)->task, NULL); \
__set_current_state(TASK_RUNNING); \
+ __ret; \
})
#endif /* _LINUX_RCUWAIT_H_ */
--- a/kernel/locking/percpu-rwsem.c
+++ b/kernel/locking/percpu-rwsem.c
@@ -162,7 +162,7 @@ void percpu_down_write(struct percpu_rw_
*/
/* Wait for all now active readers to complete. */
- rcuwait_wait_event(&sem->writer, readers_active_check(sem));
+ rcuwait_wait_event(&sem->writer, readers_active_check(sem), TASK_UNINTERRUPTIBLE);
}
EXPORT_SYMBOL_GPL(percpu_down_write);
^ permalink raw reply
* [patch V3 03/20] usb: gadget: Use completion interface instead of open coding it
From: Thomas Gleixner @ 2020-03-21 11:25 UTC (permalink / raw)
To: LKML
Cc: Randy Dunlap, linux-ia64, Peter Zijlstra, linux-pci,
Sebastian Siewior, platform-driver-x86, Guo Ren, Joel Fernandes,
Vincent Chen, Ingo Molnar, Jonathan Corbet, Davidlohr Bueso,
kbuild test robot, Brian Cain, linux-acpi, Paul E . McKenney,
linux-hexagon, Rafael J. Wysocki, linux-csky, Linus Torvalds,
Darren Hart, Zhang Rui, Len Brown, Fenghua Yu, Arnd Bergmann,
linux-pm, linuxppc-dev, Greentime Hu, Bjorn Helgaas,
Kurt Schwemmer, Kalle Valo, Felipe Balbi, Michal Simek, Tony Luck,
Nick Hu, Geoff Levand, Greg Kroah-Hartman, linux-usb,
linux-wireless, Oleg Nesterov, Davidlohr Bueso, netdev,
Logan Gunthorpe, David S. Miller, Andy Shevchenko
In-Reply-To: <20200321112544.878032781@linutronix.de>
From: Thomas Gleixner <tglx@linutronix.de>
ep_io() uses a completion on stack and open codes the waiting with:
wait_event_interruptible (done.wait, done.done);
and
wait_event (done.wait, done.done);
This waits in non-exclusive mode for complete(), but there is no reason to
do so because the completion can only be waited for by the task itself and
complete() wakes exactly one exlusive waiter.
Replace the open coded implementation with the corresponding
wait_for_completion*() functions.
No functional change.
Reported-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Felipe Balbi <balbi@kernel.org>
Cc: linux-usb@vger.kernel.org
---
V2: New patch to avoid the conversion to swait interfaces later
---
drivers/usb/gadget/legacy/inode.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/usb/gadget/legacy/inode.c
+++ b/drivers/usb/gadget/legacy/inode.c
@@ -344,7 +344,7 @@ ep_io (struct ep_data *epdata, void *buf
spin_unlock_irq (&epdata->dev->lock);
if (likely (value == 0)) {
- value = wait_event_interruptible (done.wait, done.done);
+ value = wait_for_completion_interruptible(&done);
if (value != 0) {
spin_lock_irq (&epdata->dev->lock);
if (likely (epdata->ep != NULL)) {
@@ -353,7 +353,7 @@ ep_io (struct ep_data *epdata, void *buf
usb_ep_dequeue (epdata->ep, epdata->req);
spin_unlock_irq (&epdata->dev->lock);
- wait_event (done.wait, done.done);
+ wait_for_completion(&done);
if (epdata->status == -ECONNRESET)
epdata->status = -EINTR;
} else {
^ permalink raw reply
* [patch V3 10/20] microblaze: Remove mm.h from asm/uaccess.h
From: Thomas Gleixner @ 2020-03-21 11:25 UTC (permalink / raw)
To: LKML
Cc: Randy Dunlap, linux-ia64, Peter Zijlstra, linux-pci,
Sebastian Siewior, platform-driver-x86, Guo Ren, Joel Fernandes,
Vincent Chen, Ingo Molnar, Jonathan Corbet, Davidlohr Bueso,
kbuild test robot, Brian Cain, linux-acpi, Paul E . McKenney,
linux-hexagon, Rafael J. Wysocki, linux-csky, Linus Torvalds,
Darren Hart, Zhang Rui, Len Brown, Fenghua Yu, Arnd Bergmann,
linux-pm, linuxppc-dev, Greentime Hu, Bjorn Helgaas,
Kurt Schwemmer, Kalle Valo, Felipe Balbi, Michal Simek, Tony Luck,
Nick Hu, Geoff Levand, Greg Kroah-Hartman, linux-usb,
linux-wireless, Oleg Nesterov, Davidlohr Bueso, netdev,
Logan Gunthorpe, David S. Miller, Andy Shevchenko
In-Reply-To: <20200321112544.878032781@linutronix.de>
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
The defconfig compiles without linux/mm.h. With mm.h included the
include chain leands to:
| CC kernel/locking/percpu-rwsem.o
| In file included from include/linux/huge_mm.h:8,
| from include/linux/mm.h:567,
| from arch/microblaze/include/asm/uaccess.h:,
| from include/linux/uaccess.h:11,
| from include/linux/sched/task.h:11,
| from include/linux/sched/signal.h:9,
| from include/linux/rcuwait.h:6,
| from include/linux/percpu-rwsem.h:8,
| from kernel/locking/percpu-rwsem.c:6:
| include/linux/fs.h:1422:29: error: array type has incomplete element type 'struct percpu_rw_semaphore'
| 1422 | struct percpu_rw_semaphore rw_sem[SB_FREEZE_LEVELS];
once rcuwait.h includes linux/sched/signal.h.
Remove the linux/mm.h include.
Reported-by: kbuild test robot <lkp@intel.com>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Michal Simek <monstr@monstr.eu>
---
V3; New patch
---
arch/microblaze/include/asm/uaccess.h | 1 -
1 file changed, 1 deletion(-)
diff --git a/arch/microblaze/include/asm/uaccess.h b/arch/microblaze/include/asm/uaccess.h
index a1f206b90753a..4916d5fbea5e3 100644
--- a/arch/microblaze/include/asm/uaccess.h
+++ b/arch/microblaze/include/asm/uaccess.h
@@ -12,7 +12,6 @@
#define _ASM_MICROBLAZE_UACCESS_H
#include <linux/kernel.h>
-#include <linux/mm.h>
#include <asm/mmu.h>
#include <asm/page.h>
--
2.26.0.rc2
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox