Skip to content

Commit

Permalink
Merge branch 'irq-core-for-linus' of git://git.kernel.org/pub/scm/lin…
Browse files Browse the repository at this point in the history
…ux/kernel/git/tip/tip

Pull IRQ changes from Ingo Molnar:
 "The biggest change this cycle are the softirq/hardirq stack
  interaction and nesting fixes, cleanups and reorganizations from
  Frederic.  This is the longer followup story to the softirq nesting
  fix that is already upstream (commit ded7975: "irq: Force hardirq
  exit's softirq processing on its own stack")"

* 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  irqchip: bcm2835: Convert to use IRQCHIP_DECLARE macro
  powerpc: Tell about irq stack coverage
  x86: Tell about irq stack coverage
  irq: Optimize softirq stack selection in irq exit
  irq: Justify the various softirq stack choices
  irq: Improve a bit softirq debugging
  irq: Optimize call to softirq on hardirq exit
  irq: Consolidate do_softirq() arch overriden implementations
  x86/irq: Correct comment about i8259 initialization
  • Loading branch information
Linus Torvalds committed Nov 12, 2013
2 parents 70fdcb8 + 5702941 commit 1006fae
Show file tree
Hide file tree
Showing 18 changed files with 145 additions and 255 deletions.
10 changes: 10 additions & 0 deletions arch/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,16 @@ config HAVE_UNDERSCORE_SYMBOL_PREFIX
Some architectures generate an _ in front of C symbols; things like
module loading and assembly files need to know about this.

config HAVE_IRQ_EXIT_ON_IRQ_STACK
bool
help
Architecture doesn't only execute the irq handler on the irq stack
but also irq_exit(). This way we can process softirqs on this irq
stack instead of switching to a new one when we call __do_softirq()
in the end of an hardirq.
This spares a stack switch and improves cache usage on softirq
processing.

#
# ABI hall of shame
#
Expand Down
5 changes: 2 additions & 3 deletions arch/arm/mach-bcm2835/bcm2835.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

#include <linux/delay.h>
#include <linux/init.h>
#include <linux/irqchip/bcm2835.h>
#include <linux/irqchip.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/clk/bcm2835.h>
Expand Down Expand Up @@ -130,8 +130,7 @@ static const char * const bcm2835_compat[] = {

DT_MACHINE_START(BCM2835, "BCM2835")
.map_io = bcm2835_map_io,
.init_irq = bcm2835_init_irq,
.handle_irq = bcm2835_handle_irq,
.init_irq = irqchip_init,
.init_machine = bcm2835_init,
.restart = bcm2835_restart,
.dt_compat = bcm2835_compat
Expand Down
52 changes: 19 additions & 33 deletions arch/metag/kernel/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -159,44 +159,30 @@ void irq_ctx_exit(int cpu)

extern asmlinkage void __do_softirq(void);

asmlinkage void do_softirq(void)
void do_softirq_own_stack(void)
{
unsigned long flags;
struct thread_info *curctx;
union irq_ctx *irqctx;
u32 *isp;

if (in_interrupt())
return;

local_irq_save(flags);

if (local_softirq_pending()) {
curctx = current_thread_info();
irqctx = softirq_ctx[smp_processor_id()];
irqctx->tinfo.task = curctx->task;

/* build the stack frame on the softirq stack */
isp = (u32 *) ((char *)irqctx + sizeof(struct thread_info));

asm volatile (
"MOV D0.5,%0\n"
"SWAP A0StP,D0.5\n"
"CALLR D1RtP,___do_softirq\n"
"MOV A0StP,D0.5\n"
:
: "r" (isp)
: "memory", "cc", "D1Ar1", "D0Ar2", "D1Ar3", "D0Ar4",
"D1Ar5", "D0Ar6", "D0Re0", "D1Re0", "D0.4", "D1RtP",
"D0.5"
);
/*
* Shouldn't happen, we returned above if in_interrupt():
*/
WARN_ON_ONCE(softirq_count());
}

local_irq_restore(flags);
curctx = current_thread_info();
irqctx = softirq_ctx[smp_processor_id()];
irqctx->tinfo.task = curctx->task;

/* build the stack frame on the softirq stack */
isp = (u32 *) ((char *)irqctx + sizeof(struct thread_info));

asm volatile (
"MOV D0.5,%0\n"
"SWAP A0StP,D0.5\n"
"CALLR D1RtP,___do_softirq\n"
"MOV A0StP,D0.5\n"
:
: "r" (isp)
: "memory", "cc", "D1Ar1", "D0Ar2", "D1Ar3", "D0Ar4",
"D1Ar5", "D0Ar6", "D0Re0", "D1Re0", "D0.4", "D1RtP",
"D0.5"
);
}
#endif

Expand Down
17 changes: 2 additions & 15 deletions arch/parisc/kernel/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -495,22 +495,9 @@ static void execute_on_irq_stack(void *func, unsigned long param1)
*irq_stack_in_use = 1;
}

asmlinkage void do_softirq(void)
void do_softirq_own_stack(void)
{
__u32 pending;
unsigned long flags;

if (in_interrupt())
return;

local_irq_save(flags);

pending = local_softirq_pending();

if (pending)
execute_on_irq_stack(__do_softirq, 0);

local_irq_restore(flags);
execute_on_irq_stack(__do_softirq, 0);
}
#endif /* CONFIG_IRQSTACKS */

Expand Down
1 change: 1 addition & 0 deletions arch/powerpc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ config PPC
select OLD_SIGSUSPEND
select OLD_SIGACTION if PPC32
select HAVE_DEBUG_STACKOVERFLOW
select HAVE_IRQ_EXIT_ON_IRQ_STACK

config EARLY_PRINTK
bool
Expand Down
17 changes: 1 addition & 16 deletions arch/powerpc/kernel/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -594,7 +594,7 @@ void irq_ctx_init(void)
}
}

static inline void do_softirq_onstack(void)
void do_softirq_own_stack(void)
{
struct thread_info *curtp, *irqtp;

Expand All @@ -612,21 +612,6 @@ static inline void do_softirq_onstack(void)
set_bits(irqtp->flags, &curtp->flags);
}

void do_softirq(void)
{
unsigned long flags;

if (in_interrupt())
return;

local_irq_save(flags);

if (local_softirq_pending())
do_softirq_onstack();

local_irq_restore(flags);
}

irq_hw_number_t virq_to_hw(unsigned int virq)
{
struct irq_data *irq_data = irq_get_irq_data(virq);
Expand Down
52 changes: 21 additions & 31 deletions arch/s390/kernel/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -157,39 +157,29 @@ int arch_show_interrupts(struct seq_file *p, int prec)
/*
* Switch to the asynchronous interrupt stack for softirq execution.
*/
asmlinkage void do_softirq(void)
void do_softirq_own_stack(void)
{
unsigned long flags, old, new;

if (in_interrupt())
return;

local_irq_save(flags);

if (local_softirq_pending()) {
/* Get current stack pointer. */
asm volatile("la %0,0(15)" : "=a" (old));
/* Check against async. stack address range. */
new = S390_lowcore.async_stack;
if (((new - old) >> (PAGE_SHIFT + THREAD_ORDER)) != 0) {
/* Need to switch to the async. stack. */
new -= STACK_FRAME_OVERHEAD;
((struct stack_frame *) new)->back_chain = old;

asm volatile(" la 15,0(%0)\n"
" basr 14,%2\n"
" la 15,0(%1)\n"
: : "a" (new), "a" (old),
"a" (__do_softirq)
: "0", "1", "2", "3", "4", "5", "14",
"cc", "memory" );
} else {
/* We are already on the async stack. */
__do_softirq();
}
unsigned long old, new;

/* Get current stack pointer. */
asm volatile("la %0,0(15)" : "=a" (old));
/* Check against async. stack address range. */
new = S390_lowcore.async_stack;
if (((new - old) >> (PAGE_SHIFT + THREAD_ORDER)) != 0) {
/* Need to switch to the async. stack. */
new -= STACK_FRAME_OVERHEAD;
((struct stack_frame *) new)->back_chain = old;
asm volatile(" la 15,0(%0)\n"
" basr 14,%2\n"
" la 15,0(%1)\n"
: : "a" (new), "a" (old),
"a" (__do_softirq)
: "0", "1", "2", "3", "4", "5", "14",
"cc", "memory" );
} else {
/* We are already on the async stack. */
__do_softirq();
}

local_irq_restore(flags);
}

/*
Expand Down
57 changes: 21 additions & 36 deletions arch/sh/kernel/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,47 +149,32 @@ void irq_ctx_exit(int cpu)
hardirq_ctx[cpu] = NULL;
}

asmlinkage void do_softirq(void)
void do_softirq_own_stack(void)
{
unsigned long flags;
struct thread_info *curctx;
union irq_ctx *irqctx;
u32 *isp;

if (in_interrupt())
return;

local_irq_save(flags);

if (local_softirq_pending()) {
curctx = current_thread_info();
irqctx = softirq_ctx[smp_processor_id()];
irqctx->tinfo.task = curctx->task;
irqctx->tinfo.previous_sp = current_stack_pointer;

/* build the stack frame on the softirq stack */
isp = (u32 *)((char *)irqctx + sizeof(*irqctx));

__asm__ __volatile__ (
"mov r15, r9 \n"
"jsr @%0 \n"
/* switch to the softirq stack */
" mov %1, r15 \n"
/* restore the thread stack */
"mov r9, r15 \n"
: /* no outputs */
: "r" (__do_softirq), "r" (isp)
: "memory", "r0", "r1", "r2", "r3", "r4",
"r5", "r6", "r7", "r8", "r9", "r15", "t", "pr"
);

/*
* Shouldn't happen, we returned above if in_interrupt():
*/
WARN_ON_ONCE(softirq_count());
}

local_irq_restore(flags);
curctx = current_thread_info();
irqctx = softirq_ctx[smp_processor_id()];
irqctx->tinfo.task = curctx->task;
irqctx->tinfo.previous_sp = current_stack_pointer;

/* build the stack frame on the softirq stack */
isp = (u32 *)((char *)irqctx + sizeof(*irqctx));

__asm__ __volatile__ (
"mov r15, r9 \n"
"jsr @%0 \n"
/* switch to the softirq stack */
" mov %1, r15 \n"
/* restore the thread stack */
"mov r9, r15 \n"
: /* no outputs */
: "r" (__do_softirq), "r" (isp)
: "memory", "r0", "r1", "r2", "r3", "r4",
"r5", "r6", "r7", "r8", "r9", "r15", "t", "pr"
);
}
#else
static inline void handle_one_irq(unsigned int irq)
Expand Down
31 changes: 10 additions & 21 deletions arch/sparc/kernel/irq_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -698,30 +698,19 @@ void __irq_entry handler_irq(int pil, struct pt_regs *regs)
set_irq_regs(old_regs);
}

void do_softirq(void)
void do_softirq_own_stack(void)
{
unsigned long flags;

if (in_interrupt())
return;

local_irq_save(flags);
void *orig_sp, *sp = softirq_stack[smp_processor_id()];

if (local_softirq_pending()) {
void *orig_sp, *sp = softirq_stack[smp_processor_id()];

sp += THREAD_SIZE - 192 - STACK_BIAS;

__asm__ __volatile__("mov %%sp, %0\n\t"
"mov %1, %%sp"
: "=&r" (orig_sp)
: "r" (sp));
__do_softirq();
__asm__ __volatile__("mov %0, %%sp"
: : "r" (orig_sp));
}
sp += THREAD_SIZE - 192 - STACK_BIAS;

local_irq_restore(flags);
__asm__ __volatile__("mov %%sp, %0\n\t"
"mov %1, %%sp"
: "=&r" (orig_sp)
: "r" (sp));
__do_softirq();
__asm__ __volatile__("mov %0, %%sp"
: : "r" (orig_sp));
}

#ifdef CONFIG_HOTPLUG_CPU
Expand Down
1 change: 1 addition & 0 deletions arch/x86/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ config X86
select COMPAT_OLD_SIGACTION if IA32_EMULATION
select RTC_LIB
select HAVE_DEBUG_STACKOVERFLOW
select HAVE_IRQ_EXIT_ON_IRQ_STACK if X86_64

config INSTRUCTION_DECODER
def_bool y
Expand Down
4 changes: 2 additions & 2 deletions arch/x86/kernel/entry_64.S
Original file line number Diff line number Diff line change
Expand Up @@ -1342,7 +1342,7 @@ bad_gs:
.previous

/* Call softirq on interrupt stack. Interrupts are off. */
ENTRY(call_softirq)
ENTRY(do_softirq_own_stack)
CFI_STARTPROC
pushq_cfi %rbp
CFI_REL_OFFSET rbp,0
Expand All @@ -1359,7 +1359,7 @@ ENTRY(call_softirq)
decl PER_CPU_VAR(irq_count)
ret
CFI_ENDPROC
END(call_softirq)
END(do_softirq_own_stack)

#ifdef CONFIG_XEN
zeroentry xen_hypervisor_callback xen_do_hypervisor_callback
Expand Down
3 changes: 1 addition & 2 deletions arch/x86/kernel/i8259.c
Original file line number Diff line number Diff line change
Expand Up @@ -312,8 +312,7 @@ static void init_8259A(int auto_eoi)
*/
outb_pic(0x11, PIC_MASTER_CMD); /* ICW1: select 8259A-1 init */

/* ICW2: 8259A-1 IR0-7 mapped to 0x30-0x37 on x86-64,
to 0x20-0x27 on i386 */
/* ICW2: 8259A-1 IR0-7 mapped to 0x30-0x37 */
outb_pic(IRQ0_VECTOR, PIC_MASTER_IMR);

/* 8259A-1 (the master) has a slave on IR2 */
Expand Down
Loading

0 comments on commit 1006fae

Please sign in to comment.