mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
To: Shrikanth Hegde <sshegde@linux.ibm.com>,
	maddy@linux.ibm.com, linuxppc-dev@lists.ozlabs.org,
	chzigotzky@xenosoft.de
Cc: sshegde@linux.ibm.com, mpe@ellerman.id.au, npiggin@gmail.com,
	christophe.leroy@csgroup.eu, linux-kernel@vger.kernel.org,
	msuchanek@suse.de, harshpb@linux.ibm.com, gautam@linux.ibm.com,
	amachhiw@linux.ibm.com, venkat88@linux.ibm.com,
	nnmlinux@linux.ibm.com, mkchauras@gmail.com
Subject: Re: [PATCH v3 1/3] powerpc/irq: Add ppc_hard_irq_disable()
Date: Sat, 14 Nov 2026 10:46:15 +0530	[thread overview]
Message-ID: <fqx4802o.ritesh.list@gmail.com> (raw)
In-Reply-To: <20261112130913.4124175-2-sshegde@linux.ibm.com>

Shrikanth Hegde <sshegde@linux.ibm.com> writes:

> Add a flavour of interrupt disable which could be used in
> multiple places which also takes care of lockdep in both 32 and
> 64 bit archs.
>
> On PPC64:
> - Disable hard interrupts using hard_irq_disable. It takes care of
>   lockdep and tracing. local_irq_disable only alters softmask's state.
>
> On PPC32:
> - Interrupts are hard disabled with local_irq_disable. It also takes
>   care of lockdep and tacing.
>
> Subsequent patch uses this API in KVM code to avoid the warnings.
> Wider use of it is possible, but it will be taken subsequently.
>
> Suggested-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
> Tested-by: Christian Zigotzky <chzigotzky@xenosoft.de>
> Reviewed-by: Mukesh Kumar Chaurasiya (IBM) <mkchauras@gmail.com>
> Signed-off-by: Shrikanth Hegde <sshegde@linux.ibm.com>
> ---
>  arch/powerpc/include/asm/hw_irq.h | 17 +++++++++++++++++
>  1 file changed, 17 insertions(+)
>
> diff --git a/arch/powerpc/include/asm/hw_irq.h b/arch/powerpc/include/asm/hw_irq.h
> index b7eee6385ae5..075442366e1e 100644
> --- a/arch/powerpc/include/asm/hw_irq.h
> +++ b/arch/powerpc/include/asm/hw_irq.h
> @@ -516,6 +516,23 @@ static inline unsigned long mtmsr_isync_irqsafe(unsigned long msr)
>  
>  #define ARCH_IRQ_INIT_FLAGS	IRQ_NOREQUEST
>  
> +/*
> + * Hard-disable interrupts while keeping the IRQ tracing state
> + * consistent.
> + *
> + * On PPC64, local_irq_disable() only soft-disables interrupts, leaving
> + * a window where an interrupt can be recorded in irq_happened before
> + * interrupts are hard-disabled.
> + *
> + * On PPC32, hard_irq_disable() does not update the IRQ tracing state, so
> + * use local_irq_disable().
> + */
> +#ifdef CONFIG_PPC64
> +#define ppc_hard_irq_disable()	hard_irq_disable()
> +#else
> +#define ppc_hard_irq_disable()	local_irq_disable()
> +#endif
> +

So I looked up the history of how did we end up here. And looks like we
will be papering over the problem, if we make the above change and add
yet another helper on PPC :)

Ideally, ppc32 shouldn't need a hard_irq_disable() definition at all.
As I understand it, the contract when this was all added was that, it is
meant for architectures which implement lazy IRQ disabling i.e.
    commit d04c56f73c30a5e593202ecfcf25ed43d42363a2
    Author: Paul Mackerras <paulus@ozlabs.org>
    Date:   Wed Oct 4 16:47:49 2006 +1000
        [POWERPC] Lazy interrupt disabling for 64-bit machines
 
...where local_irq_disable() only sets a soft mask. Code that really
wants interrupts disabled at the hardware level then calls
hard_irq_disable() as well.

This commit which defined a generic stub for hard_irq_disable() makes the
contract clear i.e.
    commit 2d3fbbb391e280724f7f7804ab00ff61cf1b6a4c
    Author: Benjamin Herrenschmidt <benh@kernel.crashing.org>
    Date:   Thu May 10 22:22:46 2007 -0700

        Add hard_irq_disable()
which says:
    This patch implements a generic hard_irq_disable() function which is meant to
    be called -after- local_irq_disable() and ensures that interrupts are fully
    disabled on that CPU.  The default implementation is a nop, though powerpc
    does already provide an appropriate one.

And then the following even implements such a contract in stop_machine() i.e.:
    commit a12bb44471b819c7f33d8a83044e7116c124e3d5
    Author: Benjamin Herrenschmidt <benh@kernel.crashing.org>
    Date:   Thu May 10 22:22:47 2007 -0700

        stop_machine() now uses hard_irq_disable

        Add a call to hard_irq_disable() to stop_machine so that we make sure IRQs are
        really disabled and not only lazy-disabled on archs like powerpc as some users
        of stop_machine() may rely on that.

        [akpm@linux-foundation.org: build fix]
        Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
        Acked-by: Rusty Russell <rusty@rustcorp.com.au>
        Cc: Paul Mackerras <paulus@samba.org>
        Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
        Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

    diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
    index daabb74ee0bc..fcee2a8e6da3 100644
    --- a/kernel/stop_machine.c
    +++ b/kernel/stop_machine.c
    @@ -8,6 +8,8 @@
    #include <linux/sched.h>
    #include <linux/stop_machine.h>
    #include <linux/syscalls.h>
    +#include <linux/interrupt.h>
    +
    #include <asm/atomic.h>
    #include <asm/semaphore.h>
    #include <asm/uaccess.h>
    @@ -45,6 +47,7 @@ static int stopmachine(void *cpu)
            if (stopmachine_state == STOPMACHINE_DISABLE_IRQ 
                && !irqs_disabled) {
                local_irq_disable();
    +			hard_irq_disable();
                irqs_disabled = 1;
                /* Ack: irqs disabled. */
                smp_mb(); /* Must read state first. */
    @@ -124,6 +127,7 @@ static int stop_machine(void)

        /* Make them disable irqs. */
        local_irq_disable();
    +	hard_irq_disable();
        stopmachine_set_state(STOPMACHINE_DISABLE_IRQ);

        return 0;


However, note that after introducing the lazy interrupt disabling in
2006, we saw build failures on ppc32, since hard_irq_disable()
definition didn't exist on that until then. This commit adds that
definition, which is not wrong, since the lazy interrupt disabling patch
really needed hard_irq_disable() to disable hardware interrupts. Hence
this commit defined it on PPC32 as well, as local_irq_disable() itself
i.e.

    commit 143db67af02cecab28032ec3a52e586b1433fe70
    Author: Michael Ellerman <michael@ellerman.id.au>
    Date:   Sun Nov 26 17:36:15 2006 +1100

        [POWERPC] Provide dummy hard_irq_enable/disable() for PPC32

        To allow arch/powerpc/kernel/crash.c to build on 32-bit we need a
        definition of hard_irq_disable(). 32-bit doesn't support the lazy
        interrupt disabling mechanism, so on 32-bit hard_irq_disable() is
        simply local_irq_disable(). Add a definition for hard_irq_enable()
        just for completeness.

        This allows (KEXEC=y && PPC32=y) to build again. Broken since
        d04c56f73c30a5e593202ecfcf25ed43d42363a2.

        Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
        Signed-off-by: Paul Mackerras <paulus@samba.org>

    diff --git a/include/asm-powerpc/hw_irq.h b/include/asm-powerpc/hw_irq.h
    index fd3f2a206271..d604863d72fb 100644
    --- a/include/asm-powerpc/hw_irq.h
    +++ b/include/asm-powerpc/hw_irq.h
    @@ -102,6 +102,9 @@ static inline void local_irq_save_ptr(unsigned long *flags)
    #define local_irq_save(flags)	local_irq_save_ptr(&flags)
    #define irqs_disabled()		((mfmsr() & MSR_EE) == 0)

    +#define hard_irq_enable()	local_irq_enable()
    +#define hard_irq_disable()	local_irq_disable()
    +
    #endif /* CONFIG_PPC64 */

    #define mask_irq(irq)						\


Note that the above is where we first defined hard_irq_disable() for
PPC32.
Ideally, IIUC, we don't really need this on PPC32 assuming the contract
is only for archs which uses lazy interrupt disabling (i.e. PPC64),
however, there were places where we ended up using hard_irq_disable()
assuming it disables hardware interrupts for both PPC32 and PPC64 code
and later maybe at a number of other places too.

Note that until this time, lockdep and IRQ tracing was not added. So it
wasn't a problem. However, later somewhere we ended up changing the
definition of hard_irq_disable(), to arch_local_irq_disable, maybe in
this...
   commit 5d38902c4838 ("powerpc: Add irqtrace support for 32-bit powerpc")


So IMO, in the longer term, I think we don't need hard_irq_disable() for
PPC32, and it should fallback to generic empty stub, after we fix all
those code paths and use appropriate helpers there. However, that might
need careful inspection of a lot of code paths.


Hence, meanwhile, I think instead of defining another helper like
ppc_hard_irq_disable(), (which was stupid on my part to even suggest w/o
looking at this history), we should change hard_irq_disable() definition
back to local_irq_disable() for PPC32, which anyways takes care of
trace_hardirqs_off().

Therefore, I think we need the following 2 diffs - which should fix both
of the reported issues as well. And this way, we don't need another hard
irq disabling helper on PPC.

DIFF(1)

    diff --git a/arch/powerpc/include/asm/hw_irq.h b/arch/powerpc/include/asm/hw_irq.h
    index b7eee6385ae5..ddb850e62abd 100644
    --- a/arch/powerpc/include/asm/hw_irq.h
    +++ b/arch/powerpc/include/asm/hw_irq.h
    @@ -464,7 +464,7 @@ static inline bool arch_irqs_disabled(void)
            return arch_irqs_disabled_flags(arch_local_save_flags());
     }
    
    -#define hard_irq_disable()             arch_local_irq_disable()
    +#define hard_irq_disable()             local_irq_disable()
    
     static inline bool regs_irqs_disabled(struct pt_regs *regs)
     {


and...

DIFF(2)

    diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
    index 13ad4cf5fa71..543479fc9630 100644
    --- a/arch/powerpc/kvm/booke.c
    +++ b/arch/powerpc/kvm/booke.c
    @@ -722,7 +722,6 @@ int kvmppc_core_prepare_to_enter(struct kvm_vcpu *vcpu)
            if (vcpu->arch.shared->msr & MSR_WE) {
                    local_irq_enable();
                    kvm_vcpu_halt(vcpu);
    -               local_irq_disable();
                    hard_irq_disable();

                    kvmppc_set_exit_type(vcpu, EMULATED_MTMSRWE_EXITS);
    diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
    index 9194cf492d1c..f4db7dea57b3 100644
    --- a/arch/powerpc/kvm/powerpc.c
    +++ b/arch/powerpc/kvm/powerpc.c
    @@ -81,12 +81,6 @@ int kvmppc_prepare_to_enter(struct kvm_vcpu *vcpu)
            int r;

            WARN_ON(irqs_disabled());
    -       /*
    -        * local_irq_disable() first: on 32-bit, hard_irq_disable() alone is a
    -        * raw MSR[EE] clear that bypasses the lockdep/irq-tracing state, and
    -        * the xfer_to_guest_mode helpers assert IRQs are seen as disabled.
    -        */
    -       local_irq_disable();
            hard_irq_disable();

            while (true) {
    @@ -101,7 +95,6 @@ int kvmppc_prepare_to_enter(struct kvm_vcpu *vcpu)
                            */
                            local_irq_enable();
                            r = kvm_xfer_to_guest_mode_handle_work(vcpu);
    -                       local_irq_disable();
                            hard_irq_disable();
                            if (r) {
                                    /*
    @@ -134,7 +127,6 @@ int kvmppc_prepare_to_enter(struct kvm_vcpu *vcpu)
                            local_irq_enable();
                            trace_kvm_check_requests(vcpu);
                            r = kvmppc_core_check_requests(vcpu);
    -                       local_irq_disable();
                            hard_irq_disable();
                            if (r > 0)
                                    continue;


@Shrikanth, @Mukesh, your thoughts?
If this looks good to you too, would you like to take this forward?

And, if I am not wrong, with the above 2 diffs, we don't need this patch
either [1].

[1]: [PATCH] powerpc/entry: Trace the IRQ disable before irqentry_exit() on 32-bit
[1]: https://lore.kernel.org/linuxppc-dev/a14571be1897955f43d9994f0e093de3ada6ecde.1793447880.git.ritesh.list@gmail.com/



-ritesh

  reply	other threads:[~2026-11-14 10:36 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-12 13:09 [PATCH v3 0/3] KVM: PPC: BookE: Fix boot hang on preemptible kernels Shrikanth Hegde
2026-11-12 13:09 ` [PATCH v3 1/3] powerpc/irq: Add ppc_hard_irq_disable() Shrikanth Hegde
2026-11-14  5:16   ` Ritesh Harjani [this message]
2026-11-12 13:09 ` [PATCH v3 2/3] KVM: PPC: BookE: Load FP and Altivec before enabling the interrupts Shrikanth Hegde
2026-11-13  7:45   ` Narayana Murty N
2026-11-14  5:12   ` Ritesh Harjani
2026-11-12 13:09 ` [PATCH v3 3/3] KVM: PPC: Use ppc_hard_irq_disable before guest entry Shrikanth Hegde
2026-11-13  7:48   ` Narayana Murty N

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=fqx4802o.ritesh.list@gmail.com \
    --to=ritesh.list@gmail.com \
    --cc=amachhiw@linux.ibm.com \
    --cc=christophe.leroy@csgroup.eu \
    --cc=chzigotzky@xenosoft.de \
    --cc=gautam@linux.ibm.com \
    --cc=harshpb@linux.ibm.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linuxppc-dev@lists.ozlabs.org \
    --cc=maddy@linux.ibm.com \
    --cc=mkchauras@gmail.com \
    --cc=mpe@ellerman.id.au \
    --cc=msuchanek@suse.de \
    --cc=nnmlinux@linux.ibm.com \
    --cc=npiggin@gmail.com \
    --cc=sshegde@linux.ibm.com \
    --cc=venkat88@linux.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®