2004-09-12 11:32:24

by Christoph Hellwig

[permalink] [raw]
Subject: [PATCH] irq_enter/irq_exit consolidation

Move irq_enter/irq_exit from <asm/hardirq.h> to <linux/hardirq.h>.
There some fishy things going on with the do_softirq invokation on
arm, arm26 and s390.

arm calls __do_softirq directly without local irq disabling which looks
like a real bug to me.

arm26 has a duplicate __do_softirq entry point (which makes me wonder
whether it still compiles with any 2.6 tree since a few month)

s390 has an assembly wrapper around do_softirq.

I've extended the invoke_softirq mechanism used by s390 (also called
by ksoftirqd) to the two arm variants, but the right thing to do is
probably to use the normal do_softirq call in arm and set
__ARCH_HAS_DO_SOFTIRQ + providing a per-arch do_softirq for all callers
for s390 and maybe arm26.

--- 1.20/arch/ia64/kernel/irq_ia64.c 2004-05-15 04:00:12 +02:00
+++ edited/arch/ia64/kernel/irq_ia64.c 2004-09-11 21:06:21 +02:00
@@ -59,21 +59,6 @@
};
EXPORT_SYMBOL(isa_irq_to_vector_map);

-static inline void
-irq_enter (void)
-{
- preempt_count() += HARDIRQ_OFFSET;
-}
-
-static inline void
-irq_exit (void)
-{
- preempt_count() -= IRQ_EXIT_OFFSET;
- if (!in_interrupt() && local_softirq_pending())
- do_softirq();
- preempt_enable_no_resched();
-}
-
int
assign_irq_vector (int irq)
{
===== include/asm-alpha/hardirq.h 1.9 vs edited =====
--- 1.9/include/asm-alpha/hardirq.h 2004-09-08 08:32:57 +02:00
+++ edited/include/asm-alpha/hardirq.h 2004-09-11 21:14:41 +02:00
@@ -50,14 +50,4 @@
#error HARDIRQ_BITS is too low!
#endif

-#define irq_enter() (preempt_count() += HARDIRQ_OFFSET)
-#define irq_exit() \
-do { \
- preempt_count() -= IRQ_EXIT_OFFSET; \
- if (!in_interrupt() && \
- softirq_pending(smp_processor_id())) \
- do_softirq(); \
- preempt_enable_no_resched(); \
-} while (0)
-
#endif /* _ALPHA_HARDIRQ_H */
===== include/asm-arm/hardirq.h 1.13 vs edited =====
--- 1.13/include/asm-arm/hardirq.h 2004-09-08 08:32:57 +02:00
+++ edited/include/asm-arm/hardirq.h 2004-09-11 21:09:10 +02:00
@@ -50,18 +50,7 @@
# error HARDIRQ_BITS is too low!
#endif

-#define irq_enter() (preempt_count() += HARDIRQ_OFFSET)
-
-#ifndef CONFIG_SMP
extern asmlinkage void __do_softirq(void);
-
-#define irq_exit() \
- do { \
- preempt_count() -= IRQ_EXIT_OFFSET; \
- if (!in_interrupt() && local_softirq_pending()) \
- __do_softirq(); \
- preempt_enable_no_resched(); \
- } while (0)
-#endif
+#define invoke_softirq() __do_softirq()

#endif /* __ASM_HARDIRQ_H */
--- 1.3/include/asm-arm26/hardirq.h 2004-09-08 08:32:57 +02:00
+++ edited/include/asm-arm26/hardirq.h 2004-09-11 21:09:41 +02:00
@@ -41,17 +41,6 @@
# error HARDIRQ_BITS is too low!
#endif

-#define irq_enter() (preempt_count() += HARDIRQ_OFFSET)
-
-#ifndef CONFIG_SMP
-#define irq_exit() \
- do { \
- preempt_count() -= HARDIRQ_OFFSET; \
- if (!in_interrupt() && softirq_pending(smp_processor_id())) \
- __asm__("bl%? __do_softirq": : : "lr");/* out of line */\
- preempt_enable_no_resched(); \
- } while (0)
-
-#endif
+#define invoke_softirq() __asm__("bl%? __do_softirq": : : "lr")

#endif /* __ASM_HARDIRQ_H */
===== include/asm-cris/hardirq.h 1.4 vs edited =====
--- 1.4/include/asm-cris/hardirq.h 2004-09-08 08:32:57 +02:00
+++ edited/include/asm-cris/hardirq.h 2004-09-11 21:15:19 +02:00
@@ -49,13 +49,4 @@
# error HARDIRQ_BITS is too low!
#endif

-#define irq_enter() (preempt_count() += HARDIRQ_OFFSET)
-#define irq_exit() \
-do { \
- preempt_count() -= IRQ_EXIT_OFFSET; \
- if (!in_interrupt() && softirq_pending(smp_processor_id())) \
- do_softirq(); \
- preempt_enable_no_resched(); \
-} while (0)
-
#endif /* __ASM_HARDIRQ_H */
===== include/asm-h8300/hardirq.h 1.5 vs edited =====
--- 1.5/include/asm-h8300/hardirq.h 2004-09-08 08:32:57 +02:00
+++ edited/include/asm-h8300/hardirq.h 2004-09-11 21:09:54 +02:00
@@ -47,13 +47,4 @@
# error HARDIRQ_BITS is too low!
#endif

-#define irq_enter() (preempt_count() += HARDIRQ_OFFSET)
-#define irq_exit() \
-do { \
- preempt_count() -= IRQ_EXIT_OFFSET; \
- if (!in_interrupt() && softirq_pending(smp_processor_id())) \
- do_softirq(); \
- preempt_enable_no_resched(); \
-} while (0)
-
#endif
===== include/asm-i386/hardirq.h 1.22 vs edited =====
--- 1.22/include/asm-i386/hardirq.h 2004-09-08 08:32:57 +02:00
+++ edited/include/asm-i386/hardirq.h 2004-09-11 21:25:23 +02:00
@@ -46,16 +46,4 @@
# error HARDIRQ_BITS is too low!
#endif

-#define nmi_enter() (irq_enter())
-#define nmi_exit() (preempt_count() -= HARDIRQ_OFFSET)
-
-#define irq_enter() (preempt_count() += HARDIRQ_OFFSET)
-#define irq_exit() \
-do { \
- preempt_count() -= IRQ_EXIT_OFFSET; \
- if (!in_interrupt() && softirq_pending(smp_processor_id())) \
- do_softirq(); \
- preempt_enable_no_resched(); \
-} while (0)
-
#endif /* __ASM_HARDIRQ_H */
===== include/asm-m68k/hardirq.h 1.7 vs edited =====
--- 1.7/include/asm-m68k/hardirq.h 2004-09-08 08:32:57 +02:00
+++ edited/include/asm-m68k/hardirq.h 2004-09-11 21:10:09 +02:00
@@ -44,13 +44,4 @@
# error HARDIRQ_BITS is too low!
#endif

-#define irq_enter() (preempt_count() += HARDIRQ_OFFSET)
-#define irq_exit() \
-do { \
- preempt_count() -= IRQ_EXIT_OFFSET; \
- if (!in_interrupt() && softirq_pending(smp_processor_id())) \
- do_softirq(); \
- preempt_enable_no_resched(); \
-} while (0)
-
#endif
===== include/asm-m68knommu/hardirq.h 1.4 vs edited =====
--- 1.4/include/asm-m68knommu/hardirq.h 2004-09-08 08:32:57 +02:00
+++ edited/include/asm-m68knommu/hardirq.h 2004-09-11 21:10:17 +02:00
@@ -45,13 +45,4 @@
# error HARDIRQ_BITS is too low!
#endif

-#define irq_enter() (preempt_count() += HARDIRQ_OFFSET)
-#define irq_exit() \
-do { \
- preempt_count() -= IRQ_EXIT_OFFSET; \
- if (!in_interrupt() && softirq_pending(smp_processor_id())) \
- do_softirq(); \
- preempt_enable_no_resched(); \
-} while (0)
-
#endif /* __M68K_HARDIRQ_H */
===== include/asm-mips/hardirq.h 1.9 vs edited =====
--- 1.9/include/asm-mips/hardirq.h 2004-09-08 08:32:57 +02:00
+++ edited/include/asm-mips/hardirq.h 2004-09-11 21:10:24 +02:00
@@ -52,13 +52,4 @@
# error HARDIRQ_BITS is too low!
#endif

-#define irq_enter() (preempt_count() += HARDIRQ_OFFSET)
-#define irq_exit() \
-do { \
- preempt_count() -= IRQ_EXIT_OFFSET; \
- if (!in_interrupt() && softirq_pending(smp_processor_id())) \
- do_softirq(); \
- preempt_enable_no_resched(); \
-} while (0)
-
#endif /* _ASM_HARDIRQ_H */
===== include/asm-parisc/hardirq.h 1.4 vs edited =====
--- 1.4/include/asm-parisc/hardirq.h 2004-09-08 08:32:57 +02:00
+++ edited/include/asm-parisc/hardirq.h 2004-09-11 21:10:30 +02:00
@@ -59,13 +59,4 @@
# error HARDIRQ_BITS is too low!
#endif

-#define irq_enter() (preempt_count() += HARDIRQ_OFFSET)
-#define irq_exit() \
-do { \
- preempt_count() -= IRQ_EXIT_OFFSET; \
- if (!in_interrupt() && softirq_pending(smp_processor_id())) \
- do_softirq(); \
- preempt_enable_no_resched(); \
-} while (0)
-
#endif /* _PARISC_HARDIRQ_H */
===== include/asm-ppc/hardirq.h 1.25 vs edited =====
--- 1.25/include/asm-ppc/hardirq.h 2004-09-08 08:32:57 +02:00
+++ edited/include/asm-ppc/hardirq.h 2004-09-11 21:11:01 +02:00
@@ -53,14 +53,5 @@
# error HARDIRQ_BITS is too low!
#endif

-#define irq_enter() (preempt_count() += HARDIRQ_OFFSET)
-#define irq_exit() \
-do { \
- preempt_count() -= IRQ_EXIT_OFFSET; \
- if (!in_interrupt() && softirq_pending(smp_processor_id())) \
- do_softirq(); \
- preempt_enable_no_resched(); \
-} while (0)
-
#endif /* __ASM_HARDIRQ_H */
#endif /* __KERNEL__ */
===== include/asm-ppc64/hardirq.h 1.14 vs edited =====
--- 1.14/include/asm-ppc64/hardirq.h 2004-09-08 08:32:57 +02:00
+++ edited/include/asm-ppc64/hardirq.h 2004-09-11 21:11:12 +02:00
@@ -51,13 +51,4 @@
# error HARDIRQ_BITS is too low!
#endif

-#define irq_enter() (preempt_count() += HARDIRQ_OFFSET)
-#define irq_exit() \
-do { \
- preempt_count() -= IRQ_EXIT_OFFSET; \
- if (!in_interrupt() && softirq_pending(smp_processor_id())) \
- do_softirq(); \
- preempt_enable_no_resched(); \
-} while (0)
-
#endif /* __ASM_HARDIRQ_H */
===== include/asm-s390/hardirq.h 1.14 vs edited =====
--- 1.14/include/asm-s390/hardirq.h 2004-09-08 08:32:57 +02:00
+++ edited/include/asm-s390/hardirq.h 2004-09-11 21:11:28 +02:00
@@ -66,17 +66,4 @@

#define invoke_softirq() do_call_softirq()

-#define irq_enter() \
-do { \
- (preempt_count() += HARDIRQ_OFFSET); \
-} while(0)
-#define irq_exit() \
-do { \
- preempt_count() -= IRQ_EXIT_OFFSET; \
- if (!in_interrupt() && local_softirq_pending()) \
- /* Use the async. stack for softirq */ \
- do_call_softirq(); \
- preempt_enable_no_resched(); \
-} while (0)
-
#endif /* __ASM_HARDIRQ_H */
===== include/asm-sh/hardirq.h 1.7 vs edited =====
--- 1.7/include/asm-sh/hardirq.h 2004-09-08 08:32:57 +02:00
+++ edited/include/asm-sh/hardirq.h 2004-09-11 21:25:35 +02:00
@@ -44,16 +44,4 @@
# error HARDIRQ_BITS is too low!
#endif

-#define nmi_enter() (irq_enter())
-#define nmi_exit() (preempt_count() -= HARDIRQ_OFFSET)
-
-#define irq_enter() (preempt_count() += HARDIRQ_OFFSET)
-#define irq_exit() \
-do { \
- preempt_count() -= IRQ_EXIT_OFFSET; \
- if (!in_interrupt() && softirq_pending(smp_processor_id())) \
- do_softirq(); \
- preempt_enable_no_resched(); \
-} while (0)
-
#endif /* __ASM_SH_HARDIRQ_H */
===== include/asm-sparc/hardirq.h 1.15 vs edited =====
--- 1.15/include/asm-sparc/hardirq.h 2004-09-08 08:32:57 +02:00
+++ edited/include/asm-sparc/hardirq.h 2004-09-11 21:12:26 +02:00
@@ -42,13 +42,4 @@
#define SOFTIRQ_SHIFT (PREEMPT_SHIFT + PREEMPT_BITS)
#define HARDIRQ_SHIFT (SOFTIRQ_SHIFT + SOFTIRQ_BITS)

-#define irq_enter() (preempt_count() += HARDIRQ_OFFSET)
-#define irq_exit() \
-do { \
- preempt_count() -= IRQ_EXIT_OFFSET; \
- if (!in_interrupt() && softirq_pending(smp_processor_id())) \
- do_softirq(); \
- preempt_enable_no_resched(); \
-} while (0)
-
#endif /* __SPARC_HARDIRQ_H */
===== include/asm-sparc64/hardirq.h 1.19 vs edited =====
--- 1.19/include/asm-sparc64/hardirq.h 2004-09-08 08:32:57 +02:00
+++ edited/include/asm-sparc64/hardirq.h 2004-09-11 21:12:43 +02:00
@@ -41,13 +41,4 @@
#define SOFTIRQ_SHIFT (PREEMPT_SHIFT + PREEMPT_BITS)
#define HARDIRQ_SHIFT (SOFTIRQ_SHIFT + SOFTIRQ_BITS)

-#define irq_enter() (preempt_count() += HARDIRQ_OFFSET)
-#define irq_exit() \
-do { \
- preempt_count() -= IRQ_EXIT_OFFSET; \
- if (!in_interrupt() && softirq_pending(smp_processor_id())) \
- do_softirq(); \
- preempt_enable_no_resched(); \
-} while (0)
-
#endif /* !(__SPARC64_HARDIRQ_H) */
===== include/asm-v850/hardirq.h 1.5 vs edited =====
--- 1.5/include/asm-v850/hardirq.h 2004-09-08 08:32:57 +02:00
+++ edited/include/asm-v850/hardirq.h 2004-09-11 21:13:01 +02:00
@@ -45,13 +45,4 @@
# error HARDIRQ_BITS is too low!
#endif

-#define irq_enter() (preempt_count() += HARDIRQ_OFFSET)
-#define irq_exit() \
-do { \
- preempt_count() -= IRQ_EXIT_OFFSET; \
- if (!in_interrupt() && softirq_pending(smp_processor_id())) \
- do_softirq(); \
- preempt_enable_no_resched(); \
-} while (0)
-
#endif /* __V850_HARDIRQ_H__ */
===== include/asm-x86_64/hardirq.h 1.7 vs edited =====
--- 1.7/include/asm-x86_64/hardirq.h 2004-09-08 08:32:57 +02:00
+++ edited/include/asm-x86_64/hardirq.h 2004-09-11 21:26:04 +02:00
@@ -46,16 +46,4 @@
# error HARDIRQ_BITS is too low!
#endif

-#define nmi_enter() (irq_enter())
-#define nmi_exit() (preempt_count() -= HARDIRQ_OFFSET)
-
-#define irq_enter() (preempt_count() += HARDIRQ_OFFSET)
-#define irq_exit() \
-do { \
- preempt_count() -= IRQ_EXIT_OFFSET; \
- if (!in_interrupt() && softirq_pending(smp_processor_id())) \
- do_softirq(); \
- preempt_enable_no_resched(); \
-} while (0)
-
#endif /* __ASM_HARDIRQ_H */
===== include/linux/hardirq.h 1.1 vs edited =====
--- 1.1/include/linux/hardirq.h 2004-09-08 08:32:57 +02:00
+++ edited/include/linux/hardirq.h 2004-09-11 21:26:28 +02:00
@@ -41,6 +36,22 @@
# define preemptible() 0
# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
#endif
+
+#ifndef invoke_softirq
+#define invoke_softirq() do_softirq()
+#endif
+
+#define irq_enter() (preempt_count() += HARDIRQ_OFFSET)
+#define irq_exit() \
+do { \
+ preempt_count() -= IRQ_EXIT_OFFSET; \
+ if (!in_interrupt() && local_softirq_pending()) \
+ invoke_softirq(); \
+ preempt_enable_no_resched(); \
+} while (0)
+
+#define nmi_enter() (preempt_count() += HARDIRQ_OFFSET)
+#define nmi_exit() (preempt_count() -= HARDIRQ_OFFSET)

#ifdef CONFIG_SMP
extern void synchronize_irq(unsigned int irq);
===== include/linux/interrupt.h 1.30 vs edited =====
--- 1.30/include/linux/interrupt.h 2004-09-08 08:32:57 +02:00
+++ edited/include/linux/interrupt.h 2004-09-11 21:24:23 +02:00
@@ -100,11 +100,6 @@
extern void FASTCALL(raise_softirq_irqoff(unsigned int nr));
extern void FASTCALL(raise_softirq(unsigned int nr));

-#ifndef invoke_softirq
-#define invoke_softirq() do_softirq()
-#endif
-
-
/* Tasklets --- multithreaded analogue of BHs.

Main feature differing them of generic softirqs: tasklet


2004-09-12 11:52:22

by Russell King

[permalink] [raw]
Subject: Re: [PATCH] irq_enter/irq_exit consolidation

On Sun, Sep 12, 2004 at 01:25:54PM +0200, Christoph Hellwig wrote:
> Move irq_enter/irq_exit from <asm/hardirq.h> to <linux/hardirq.h>.
> There some fishy things going on with the do_softirq invokation on
> arm, arm26 and s390.
>
> arm calls __do_softirq directly without local irq disabling which looks
> like a real bug to me.

The ARM interrupt subsystem guarantees that local IRQs are disabled
prior to irq_exit() being invoked. This is a must for reasons other
than softirq semantics - hardware IRQ controllers may require a
nonatomic read-modify-write to update their IRQ masking state.

This guarantee must also exist on every other architecture, otherwise:

> ===== include/linux/hardirq.h 1.1 vs edited =====
> --- 1.1/include/linux/hardirq.h 2004-09-08 08:32:57 +02:00
> +++ edited/include/linux/hardirq.h 2004-09-11 21:26:28 +02:00
> +#define irq_exit() \
> +do { \
> + preempt_count() -= IRQ_EXIT_OFFSET; \

would be buggy - it's an inherently non-atomic operation. Not only that
but the behaviour of nested interrupts would change depending on whether
they interrupted before or after preempt count has been updated.

So maybe every other architecture except ARM is buggy? 8)

--
Russell King
Linux kernel 2.6 ARM Linux - http://www.arm.linux.org.uk/
maintainer of: 2.6 PCMCIA - http://pcmcia.arm.linux.org.uk/
2.6 Serial core

2004-09-12 22:59:00

by David Miller

[permalink] [raw]
Subject: Re: [PATCH] irq_enter/irq_exit consolidation

On Sun, 12 Sep 2004 12:44:48 +0100
Russell King <[email protected]> wrote:

> This guarantee must also exist on every other architecture, otherwise:
>
> > ===== include/linux/hardirq.h 1.1 vs edited =====
> > --- 1.1/include/linux/hardirq.h 2004-09-08 08:32:57 +02:00
> > +++ edited/include/linux/hardirq.h 2004-09-11 21:26:28 +02:00
> > +#define irq_exit() \
> > +do { \
> > + preempt_count() -= IRQ_EXIT_OFFSET; \
>
> would be buggy - it's an inherently non-atomic operation.

It works out actually, if we take an interrupt in the middle
of the operation, that's fine because the preemption count
will be precisely the same as we first read it by the time
we return from that interrupt, work out some example cases
as I think that makes it easier to understand.

2004-09-13 08:11:29

by Russell King

[permalink] [raw]
Subject: Re: [PATCH] irq_enter/irq_exit consolidation

On Sun, Sep 12, 2004 at 03:57:20PM -0700, David S. Miller wrote:
> On Sun, 12 Sep 2004 12:44:48 +0100
> Russell King <[email protected]> wrote:
>
> > This guarantee must also exist on every other architecture, otherwise:
> >
> > > ===== include/linux/hardirq.h 1.1 vs edited =====
> > > --- 1.1/include/linux/hardirq.h 2004-09-08 08:32:57 +02:00
> > > +++ edited/include/linux/hardirq.h 2004-09-11 21:26:28 +02:00
> > > +#define irq_exit() \
> > > +do { \
> > > + preempt_count() -= IRQ_EXIT_OFFSET; \
> >
> > would be buggy - it's an inherently non-atomic operation.
>
> It works out actually, if we take an interrupt in the middle
> of the operation, that's fine because the preemption count
> will be precisely the same as we first read it by the time
> we return from that interrupt, work out some example cases
> as I think that makes it easier to understand.

I realise that, and it's precisely why I wrote the sentence following
the one you quoted above.

However, ARM ain't buggy whatever.

--
Russell King
Linux kernel 2.6 ARM Linux - http://www.arm.linux.org.uk/
maintainer of: 2.6 PCMCIA - http://pcmcia.arm.linux.org.uk/
2.6 Serial core

2004-09-13 13:03:44

by Martin Schwidefsky

[permalink] [raw]
Subject: Re: [PATCH] irq_enter/irq_exit consolidation

Hi Christoph,

> s390 has an assembly wrapper around do_softirq.
>
> I've extended the invoke_softirq mechanism used by s390 (also called
> by ksoftirqd) to the two arm variants, but the right thing to do is
> probably to use the normal do_softirq call in arm and set
> __ARCH_HAS_DO_SOFTIRQ + providing a per-arch do_softirq for all callers
> for s390 and maybe arm26.

do_call_softirq switches to the asynchronous interrupt stack,
just what i386 does now as well. Trouble is that on s390 it is
non-trivial to do the switch in C with inline assembly. We need
a bit of assembly. But we could get rid of invoke_softirq, define
__ARCH_HAS_DO_SOFTIRQ and use do_softirq to call the assembly
wrapper.

blue skies,
Martin.

---

From: Martin Schwidefsky <[email protected]>

Replace invoke_softirq mechanism by __ARCH_HAS_DO_SOFTIRQ
mechanism for s390.

Signed-off-by: Martin Schwidefsky <[email protected]>

diffstat:
arch/s390/kernel/entry.S | 4 +---
arch/s390/kernel/entry64.S | 4 +---
arch/s390/kernel/s390_ext.c | 1 +
arch/s390/kernel/s390_ksyms.c | 1 -
arch/s390/kernel/setup.c | 20 ++++++++++++++++++++
include/asm-s390/hardirq.h | 3 +--
6 files changed, 24 insertions(+), 9 deletions(-)

diff -urN linux-2.6/arch/s390/kernel/entry64.S linux-2.6-s390/arch/s390/kernel/entry64.S
--- linux-2.6/arch/s390/kernel/entry64.S 2004-09-13 14:30:42.000000000 +0200
+++ linux-2.6-s390/arch/s390/kernel/entry64.S 2004-09-13 14:21:29.000000000 +0200
@@ -153,7 +153,6 @@
*/
.global do_call_softirq
do_call_softirq:
- stnsm __SF_EMPTY(%r15),0xfc
stmg %r12,%r15,__SF_GPRS(%r15)
lgr %r12,%r15
lg %r0,__LC_ASYNC_STACK
@@ -163,9 +162,8 @@
lg %r15,__LC_ASYNC_STACK
0: aghi %r15,-STACK_FRAME_OVERHEAD
stg %r12,__SF_BACKCHAIN(%r15) # store back chain
- brasl %r14,do_softirq
+ brasl %r14,__do_softirq
lmg %r12,%r15,__SF_GPRS(%r12)
- ssm __SF_EMPTY(%r15)
br %r14

__critical_start:
diff -urN linux-2.6/arch/s390/kernel/entry.S linux-2.6-s390/arch/s390/kernel/entry.S
--- linux-2.6/arch/s390/kernel/entry.S 2004-09-13 14:30:42.000000000 +0200
+++ linux-2.6-s390/arch/s390/kernel/entry.S 2004-09-13 14:21:29.000000000 +0200
@@ -156,7 +156,6 @@
*/
.global do_call_softirq
do_call_softirq:
- stnsm __SF_EMPTY(%r15),0xfc
stm %r12,%r15,__SF_GPRS(%r15)
lr %r12,%r15
basr %r13,0
@@ -171,7 +170,6 @@
l %r1,.Ldo_softirq-do_call_base(%r13)
basr %r14,%r1
lm %r12,%r15,__SF_GPRS(%r12)
- ssm __SF_EMPTY(%r15)
br %r14

__critical_start:
@@ -733,7 +731,7 @@
.Ldo_IRQ: .long do_IRQ
.Ldo_extint: .long do_extint
.Ldo_signal: .long do_signal
-.Ldo_softirq: .long do_softirq
+.Ldo_softirq: .long __do_softirq
.Lhandle_per: .long do_single_step
.Ljump_table: .long pgm_check_table
.Lschedule: .long schedule
diff -urN linux-2.6/arch/s390/kernel/s390_ext.c linux-2.6-s390/arch/s390/kernel/s390_ext.c
--- linux-2.6/arch/s390/kernel/s390_ext.c 2004-08-14 12:55:32.000000000 +0200
+++ linux-2.6-s390/arch/s390/kernel/s390_ext.c 2004-09-13 14:34:14.000000000 +0200
@@ -12,6 +12,7 @@
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/kernel_stat.h>
+#include <linux/interrupt.h>

#include <asm/lowcore.h>
#include <asm/s390_ext.h>
diff -urN linux-2.6/arch/s390/kernel/s390_ksyms.c linux-2.6-s390/arch/s390/kernel/s390_ksyms.c
--- linux-2.6/arch/s390/kernel/s390_ksyms.c 2004-09-13 14:03:55.000000000 +0200
+++ linux-2.6-s390/arch/s390/kernel/s390_ksyms.c 2004-09-13 14:33:34.000000000 +0200
@@ -61,6 +61,5 @@
EXPORT_SYMBOL(console_mode);
EXPORT_SYMBOL(console_devno);
EXPORT_SYMBOL(console_irq);
-EXPORT_SYMBOL(do_call_softirq);
EXPORT_SYMBOL(sys_wait4);
EXPORT_SYMBOL(cpcmd);
diff -urN linux-2.6/arch/s390/kernel/setup.c linux-2.6-s390/arch/s390/kernel/setup.c
--- linux-2.6/arch/s390/kernel/setup.c 2004-09-13 14:30:42.000000000 +0200
+++ linux-2.6-s390/arch/s390/kernel/setup.c 2004-09-13 14:31:53.000000000 +0200
@@ -654,3 +654,23 @@
{
/* nothing... */
}
+
+extern void do_call_softirq(void);
+
+asmlinkage void do_softirq(void)
+{
+ unsigned long flags;
+
+ if (in_interrupt())
+ return;
+
+ local_irq_save(flags);
+
+ if (local_softirq_pending())
+ /* Call __do_softirq on asynchromous interrupt stack. */
+ do_call_softirq();
+
+ local_irq_restore(flags);
+}
+
+EXPORT_SYMBOL(do_softirq);
diff -urN linux-2.6/include/asm-s390/hardirq.h linux-2.6-s390/include/asm-s390/hardirq.h
--- linux-2.6/include/asm-s390/hardirq.h 2004-09-13 14:30:42.000000000 +0200
+++ linux-2.6-s390/include/asm-s390/hardirq.h 2004-09-13 14:31:42.000000000 +0200
@@ -61,9 +61,8 @@
#define SOFTIRQ_SHIFT (PREEMPT_SHIFT + PREEMPT_BITS)
#define HARDIRQ_SHIFT (SOFTIRQ_SHIFT + SOFTIRQ_BITS)

-extern void do_call_softirq(void);
extern void account_ticks(struct pt_regs *);

-#define invoke_softirq() do_call_softirq()
+#define __ARCH_HAS_DO_SOFTIRQ

#endif /* __ASM_HARDIRQ_H */

2004-09-14 18:32:22

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH] irq_enter/irq_exit consolidation

On Mon, Sep 13, 2004 at 03:02:40PM +0200, Martin Schwidefsky wrote:
> Hi Christoph,
>
> > s390 has an assembly wrapper around do_softirq.
> >
> > I've extended the invoke_softirq mechanism used by s390 (also called
> > by ksoftirqd) to the two arm variants, but the right thing to do is
> > probably to use the normal do_softirq call in arm and set
> > __ARCH_HAS_DO_SOFTIRQ + providing a per-arch do_softirq for all callers
> > for s390 and maybe arm26.
>
> do_call_softirq switches to the asynchronous interrupt stack,
> just what i386 does now as well. Trouble is that on s390 it is
> non-trivial to do the switch in C with inline assembly. We need
> a bit of assembly. But we could get rid of invoke_softirq, define
> __ARCH_HAS_DO_SOFTIRQ and use do_softirq to call the assembly
> wrapper.

Well, the question is do you want the direct do_softirq invocations from
the networking code use the separate stack or not? If not the current
code is fine. If yes you should sent the patch to Andrew.