Merge branch 'parisc-for-3.10' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux

Pull parisc update from Helge Deller:
 "The second round of parisc updates for 3.10 includes build fixes and
  enhancements to utilize irq stacks, fixes SMP races when updating PTE
  and TLB entries by proper locking and makes the search for the correct
  cross compiler more robust on Debian and Gentoo."

* 'parisc-for-3.10' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux:
  parisc: make default cross compiler search more robust (v3)
  parisc: fix SMP races when updating PTE and TLB entries in entry.S
  parisc: implement irq stacks - part 2 (v2)
This commit is contained in:
Linus Torvalds 2013-05-13 16:49:59 -07:00
Родитель dbbffe6898 6880b0150a
Коммит c83bb88589
7 изменённых файлов: 194 добавлений и 101 удалений

Просмотреть файл

@ -245,7 +245,7 @@ config SMP
config IRQSTACKS config IRQSTACKS
bool "Use separate kernel stacks when processing interrupts" bool "Use separate kernel stacks when processing interrupts"
default n default y
help help
If you say Y here the kernel will use separate kernel stacks If you say Y here the kernel will use separate kernel stacks
for handling hard and soft interrupts. This can help avoid for handling hard and soft interrupts. This can help avoid

Просмотреть файл

@ -23,24 +23,21 @@ NM = sh $(srctree)/arch/parisc/nm
CHECKFLAGS += -D__hppa__=1 CHECKFLAGS += -D__hppa__=1
LIBGCC = $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name) LIBGCC = $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
MACHINE := $(shell uname -m)
NATIVE := $(if $(filter parisc%,$(MACHINE)),1,0)
ifdef CONFIG_64BIT ifdef CONFIG_64BIT
UTS_MACHINE := parisc64 UTS_MACHINE := parisc64
CHECKFLAGS += -D__LP64__=1 -m64 CHECKFLAGS += -D__LP64__=1 -m64
WIDTH := 64 CC_ARCHES = hppa64
else # 32-bit else # 32-bit
WIDTH := CC_ARCHES = hppa hppa2.0 hppa1.1
endif endif
# attempt to help out folks who are cross-compiling ifneq ($(SUBARCH),$(UTS_MACHINE))
ifeq ($(NATIVE),1) ifeq ($(CROSS_COMPILE),)
CROSS_COMPILE := hppa$(WIDTH)-linux- CC_SUFFIXES = linux linux-gnu unknown-linux-gnu
else CROSS_COMPILE := $(call cc-cross-prefix, \
ifeq ($(CROSS_COMPILE),) $(foreach a,$(CC_ARCHES), \
CROSS_COMPILE := hppa$(WIDTH)-linux-gnu- $(foreach s,$(CC_SUFFIXES),$(a)-$(s)-)))
endif endif
endif endif
OBJCOPY_FLAGS =-O binary -R .note -R .comment -S OBJCOPY_FLAGS =-O binary -R .note -R .comment -S

Просмотреть файл

@ -11,10 +11,18 @@
#include <linux/threads.h> #include <linux/threads.h>
#include <linux/irq.h> #include <linux/irq.h>
#ifdef CONFIG_IRQSTACKS
#define __ARCH_HAS_DO_SOFTIRQ
#endif
typedef struct { typedef struct {
unsigned int __softirq_pending; unsigned int __softirq_pending;
#ifdef CONFIG_DEBUG_STACKOVERFLOW #ifdef CONFIG_DEBUG_STACKOVERFLOW
unsigned int kernel_stack_usage; unsigned int kernel_stack_usage;
#ifdef CONFIG_IRQSTACKS
unsigned int irq_stack_usage;
unsigned int irq_stack_counter;
#endif
#endif #endif
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
unsigned int irq_resched_count; unsigned int irq_resched_count;
@ -28,6 +36,7 @@ DECLARE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat);
#define __ARCH_IRQ_STAT #define __ARCH_IRQ_STAT
#define __IRQ_STAT(cpu, member) (irq_stat[cpu].member) #define __IRQ_STAT(cpu, member) (irq_stat[cpu].member)
#define inc_irq_stat(member) this_cpu_inc(irq_stat.member) #define inc_irq_stat(member) this_cpu_inc(irq_stat.member)
#define __inc_irq_stat(member) __this_cpu_inc(irq_stat.member)
#define local_softirq_pending() this_cpu_read(irq_stat.__softirq_pending) #define local_softirq_pending() this_cpu_read(irq_stat.__softirq_pending)
#define __ARCH_SET_SOFTIRQ_PENDING #define __ARCH_SET_SOFTIRQ_PENDING

Просмотреть файл

@ -63,10 +63,13 @@
*/ */
#ifdef __KERNEL__ #ifdef __KERNEL__
#include <linux/spinlock_types.h>
#define IRQ_STACK_SIZE (4096 << 2) /* 16k irq stack size */ #define IRQ_STACK_SIZE (4096 << 2) /* 16k irq stack size */
union irq_stack_union { union irq_stack_union {
unsigned long stack[IRQ_STACK_SIZE/sizeof(unsigned long)]; unsigned long stack[IRQ_STACK_SIZE/sizeof(unsigned long)];
raw_spinlock_t lock;
}; };
DECLARE_PER_CPU(union irq_stack_union, irq_stack_union); DECLARE_PER_CPU(union irq_stack_union, irq_stack_union);

Просмотреть файл

@ -452,9 +452,41 @@
L2_ptep \pgd,\pte,\index,\va,\fault L2_ptep \pgd,\pte,\index,\va,\fault
.endm .endm
/* Acquire pa_dbit_lock lock. */
.macro dbit_lock spc,tmp,tmp1
#ifdef CONFIG_SMP
cmpib,COND(=),n 0,\spc,2f
load32 PA(pa_dbit_lock),\tmp
1: LDCW 0(\tmp),\tmp1
cmpib,COND(=) 0,\tmp1,1b
nop
2:
#endif
.endm
/* Release pa_dbit_lock lock without reloading lock address. */
.macro dbit_unlock0 spc,tmp
#ifdef CONFIG_SMP
or,COND(=) %r0,\spc,%r0
stw \spc,0(\tmp)
#endif
.endm
/* Release pa_dbit_lock lock. */
.macro dbit_unlock1 spc,tmp
#ifdef CONFIG_SMP
load32 PA(pa_dbit_lock),\tmp
dbit_unlock0 \spc,\tmp
#endif
.endm
/* Set the _PAGE_ACCESSED bit of the PTE. Be clever and /* Set the _PAGE_ACCESSED bit of the PTE. Be clever and
* don't needlessly dirty the cache line if it was already set */ * don't needlessly dirty the cache line if it was already set */
.macro update_ptep ptep,pte,tmp,tmp1 .macro update_ptep spc,ptep,pte,tmp,tmp1
#ifdef CONFIG_SMP
or,COND(=) %r0,\spc,%r0
LDREG 0(\ptep),\pte
#endif
ldi _PAGE_ACCESSED,\tmp1 ldi _PAGE_ACCESSED,\tmp1
or \tmp1,\pte,\tmp or \tmp1,\pte,\tmp
and,COND(<>) \tmp1,\pte,%r0 and,COND(<>) \tmp1,\pte,%r0
@ -463,7 +495,11 @@
/* Set the dirty bit (and accessed bit). No need to be /* Set the dirty bit (and accessed bit). No need to be
* clever, this is only used from the dirty fault */ * clever, this is only used from the dirty fault */
.macro update_dirty ptep,pte,tmp .macro update_dirty spc,ptep,pte,tmp
#ifdef CONFIG_SMP
or,COND(=) %r0,\spc,%r0
LDREG 0(\ptep),\pte
#endif
ldi _PAGE_ACCESSED|_PAGE_DIRTY,\tmp ldi _PAGE_ACCESSED|_PAGE_DIRTY,\tmp
or \tmp,\pte,\pte or \tmp,\pte,\pte
STREG \pte,0(\ptep) STREG \pte,0(\ptep)
@ -1111,11 +1147,13 @@ dtlb_miss_20w:
L3_ptep ptp,pte,t0,va,dtlb_check_alias_20w L3_ptep ptp,pte,t0,va,dtlb_check_alias_20w
update_ptep ptp,pte,t0,t1 dbit_lock spc,t0,t1
update_ptep spc,ptp,pte,t0,t1
make_insert_tlb spc,pte,prot make_insert_tlb spc,pte,prot
idtlbt pte,prot idtlbt pte,prot
dbit_unlock1 spc,t0
rfir rfir
nop nop
@ -1135,11 +1173,13 @@ nadtlb_miss_20w:
L3_ptep ptp,pte,t0,va,nadtlb_check_alias_20w L3_ptep ptp,pte,t0,va,nadtlb_check_alias_20w
update_ptep ptp,pte,t0,t1 dbit_lock spc,t0,t1
update_ptep spc,ptp,pte,t0,t1
make_insert_tlb spc,pte,prot make_insert_tlb spc,pte,prot
idtlbt pte,prot idtlbt pte,prot
dbit_unlock1 spc,t0
rfir rfir
nop nop
@ -1161,7 +1201,8 @@ dtlb_miss_11:
L2_ptep ptp,pte,t0,va,dtlb_check_alias_11 L2_ptep ptp,pte,t0,va,dtlb_check_alias_11
update_ptep ptp,pte,t0,t1 dbit_lock spc,t0,t1
update_ptep spc,ptp,pte,t0,t1
make_insert_tlb_11 spc,pte,prot make_insert_tlb_11 spc,pte,prot
@ -1172,6 +1213,7 @@ dtlb_miss_11:
idtlbp prot,(%sr1,va) idtlbp prot,(%sr1,va)
mtsp t0, %sr1 /* Restore sr1 */ mtsp t0, %sr1 /* Restore sr1 */
dbit_unlock1 spc,t0
rfir rfir
nop nop
@ -1192,7 +1234,8 @@ nadtlb_miss_11:
L2_ptep ptp,pte,t0,va,nadtlb_check_alias_11 L2_ptep ptp,pte,t0,va,nadtlb_check_alias_11
update_ptep ptp,pte,t0,t1 dbit_lock spc,t0,t1
update_ptep spc,ptp,pte,t0,t1
make_insert_tlb_11 spc,pte,prot make_insert_tlb_11 spc,pte,prot
@ -1204,6 +1247,7 @@ nadtlb_miss_11:
idtlbp prot,(%sr1,va) idtlbp prot,(%sr1,va)
mtsp t0, %sr1 /* Restore sr1 */ mtsp t0, %sr1 /* Restore sr1 */
dbit_unlock1 spc,t0
rfir rfir
nop nop
@ -1224,13 +1268,15 @@ dtlb_miss_20:
L2_ptep ptp,pte,t0,va,dtlb_check_alias_20 L2_ptep ptp,pte,t0,va,dtlb_check_alias_20
update_ptep ptp,pte,t0,t1 dbit_lock spc,t0,t1
update_ptep spc,ptp,pte,t0,t1
make_insert_tlb spc,pte,prot make_insert_tlb spc,pte,prot
f_extend pte,t0 f_extend pte,t0
idtlbt pte,prot idtlbt pte,prot
dbit_unlock1 spc,t0
rfir rfir
nop nop
@ -1250,13 +1296,15 @@ nadtlb_miss_20:
L2_ptep ptp,pte,t0,va,nadtlb_check_alias_20 L2_ptep ptp,pte,t0,va,nadtlb_check_alias_20
update_ptep ptp,pte,t0,t1 dbit_lock spc,t0,t1
update_ptep spc,ptp,pte,t0,t1
make_insert_tlb spc,pte,prot make_insert_tlb spc,pte,prot
f_extend pte,t0 f_extend pte,t0
idtlbt pte,prot idtlbt pte,prot
dbit_unlock1 spc,t0
rfir rfir
nop nop
@ -1357,11 +1405,13 @@ itlb_miss_20w:
L3_ptep ptp,pte,t0,va,itlb_fault L3_ptep ptp,pte,t0,va,itlb_fault
update_ptep ptp,pte,t0,t1 dbit_lock spc,t0,t1
update_ptep spc,ptp,pte,t0,t1
make_insert_tlb spc,pte,prot make_insert_tlb spc,pte,prot
iitlbt pte,prot iitlbt pte,prot
dbit_unlock1 spc,t0
rfir rfir
nop nop
@ -1379,11 +1429,13 @@ naitlb_miss_20w:
L3_ptep ptp,pte,t0,va,naitlb_check_alias_20w L3_ptep ptp,pte,t0,va,naitlb_check_alias_20w
update_ptep ptp,pte,t0,t1 dbit_lock spc,t0,t1
update_ptep spc,ptp,pte,t0,t1
make_insert_tlb spc,pte,prot make_insert_tlb spc,pte,prot
iitlbt pte,prot iitlbt pte,prot
dbit_unlock1 spc,t0
rfir rfir
nop nop
@ -1405,7 +1457,8 @@ itlb_miss_11:
L2_ptep ptp,pte,t0,va,itlb_fault L2_ptep ptp,pte,t0,va,itlb_fault
update_ptep ptp,pte,t0,t1 dbit_lock spc,t0,t1
update_ptep spc,ptp,pte,t0,t1
make_insert_tlb_11 spc,pte,prot make_insert_tlb_11 spc,pte,prot
@ -1416,6 +1469,7 @@ itlb_miss_11:
iitlbp prot,(%sr1,va) iitlbp prot,(%sr1,va)
mtsp t0, %sr1 /* Restore sr1 */ mtsp t0, %sr1 /* Restore sr1 */
dbit_unlock1 spc,t0
rfir rfir
nop nop
@ -1427,7 +1481,8 @@ naitlb_miss_11:
L2_ptep ptp,pte,t0,va,naitlb_check_alias_11 L2_ptep ptp,pte,t0,va,naitlb_check_alias_11
update_ptep ptp,pte,t0,t1 dbit_lock spc,t0,t1
update_ptep spc,ptp,pte,t0,t1
make_insert_tlb_11 spc,pte,prot make_insert_tlb_11 spc,pte,prot
@ -1438,6 +1493,7 @@ naitlb_miss_11:
iitlbp prot,(%sr1,va) iitlbp prot,(%sr1,va)
mtsp t0, %sr1 /* Restore sr1 */ mtsp t0, %sr1 /* Restore sr1 */
dbit_unlock1 spc,t0
rfir rfir
nop nop
@ -1459,13 +1515,15 @@ itlb_miss_20:
L2_ptep ptp,pte,t0,va,itlb_fault L2_ptep ptp,pte,t0,va,itlb_fault
update_ptep ptp,pte,t0,t1 dbit_lock spc,t0,t1
update_ptep spc,ptp,pte,t0,t1
make_insert_tlb spc,pte,prot make_insert_tlb spc,pte,prot
f_extend pte,t0 f_extend pte,t0
iitlbt pte,prot iitlbt pte,prot
dbit_unlock1 spc,t0
rfir rfir
nop nop
@ -1477,13 +1535,15 @@ naitlb_miss_20:
L2_ptep ptp,pte,t0,va,naitlb_check_alias_20 L2_ptep ptp,pte,t0,va,naitlb_check_alias_20
update_ptep ptp,pte,t0,t1 dbit_lock spc,t0,t1
update_ptep spc,ptp,pte,t0,t1
make_insert_tlb spc,pte,prot make_insert_tlb spc,pte,prot
f_extend pte,t0 f_extend pte,t0
iitlbt pte,prot iitlbt pte,prot
dbit_unlock1 spc,t0
rfir rfir
nop nop
@ -1507,29 +1567,13 @@ dbit_trap_20w:
L3_ptep ptp,pte,t0,va,dbit_fault L3_ptep ptp,pte,t0,va,dbit_fault
#ifdef CONFIG_SMP dbit_lock spc,t0,t1
cmpib,COND(=),n 0,spc,dbit_nolock_20w update_dirty spc,ptp,pte,t1
load32 PA(pa_dbit_lock),t0
dbit_spin_20w:
LDCW 0(t0),t1
cmpib,COND(=) 0,t1,dbit_spin_20w
nop
dbit_nolock_20w:
#endif
update_dirty ptp,pte,t1
make_insert_tlb spc,pte,prot make_insert_tlb spc,pte,prot
idtlbt pte,prot idtlbt pte,prot
#ifdef CONFIG_SMP dbit_unlock0 spc,t0
cmpib,COND(=),n 0,spc,dbit_nounlock_20w
ldi 1,t1
stw t1,0(t0)
dbit_nounlock_20w:
#endif
rfir rfir
nop nop
@ -1543,18 +1587,8 @@ dbit_trap_11:
L2_ptep ptp,pte,t0,va,dbit_fault L2_ptep ptp,pte,t0,va,dbit_fault
#ifdef CONFIG_SMP dbit_lock spc,t0,t1
cmpib,COND(=),n 0,spc,dbit_nolock_11 update_dirty spc,ptp,pte,t1
load32 PA(pa_dbit_lock),t0
dbit_spin_11:
LDCW 0(t0),t1
cmpib,= 0,t1,dbit_spin_11
nop
dbit_nolock_11:
#endif
update_dirty ptp,pte,t1
make_insert_tlb_11 spc,pte,prot make_insert_tlb_11 spc,pte,prot
@ -1565,13 +1599,7 @@ dbit_nolock_11:
idtlbp prot,(%sr1,va) idtlbp prot,(%sr1,va)
mtsp t1, %sr1 /* Restore sr1 */ mtsp t1, %sr1 /* Restore sr1 */
#ifdef CONFIG_SMP dbit_unlock0 spc,t0
cmpib,COND(=),n 0,spc,dbit_nounlock_11
ldi 1,t1
stw t1,0(t0)
dbit_nounlock_11:
#endif
rfir rfir
nop nop
@ -1583,32 +1611,15 @@ dbit_trap_20:
L2_ptep ptp,pte,t0,va,dbit_fault L2_ptep ptp,pte,t0,va,dbit_fault
#ifdef CONFIG_SMP dbit_lock spc,t0,t1
cmpib,COND(=),n 0,spc,dbit_nolock_20 update_dirty spc,ptp,pte,t1
load32 PA(pa_dbit_lock),t0
dbit_spin_20:
LDCW 0(t0),t1
cmpib,= 0,t1,dbit_spin_20
nop
dbit_nolock_20:
#endif
update_dirty ptp,pte,t1
make_insert_tlb spc,pte,prot make_insert_tlb spc,pte,prot
f_extend pte,t1 f_extend pte,t1
idtlbt pte,prot idtlbt pte,prot
dbit_unlock0 spc,t0
#ifdef CONFIG_SMP
cmpib,COND(=),n 0,spc,dbit_nounlock_20
ldi 1,t1
stw t1,0(t0)
dbit_nounlock_20:
#endif
rfir rfir
nop nop

Просмотреть файл

@ -166,22 +166,32 @@ int arch_show_interrupts(struct seq_file *p, int prec)
seq_printf(p, "%*s: ", prec, "STK"); seq_printf(p, "%*s: ", prec, "STK");
for_each_online_cpu(j) for_each_online_cpu(j)
seq_printf(p, "%10u ", irq_stats(j)->kernel_stack_usage); seq_printf(p, "%10u ", irq_stats(j)->kernel_stack_usage);
seq_printf(p, " Kernel stack usage\n"); seq_puts(p, " Kernel stack usage\n");
# ifdef CONFIG_IRQSTACKS
seq_printf(p, "%*s: ", prec, "IST");
for_each_online_cpu(j)
seq_printf(p, "%10u ", irq_stats(j)->irq_stack_usage);
seq_puts(p, " Interrupt stack usage\n");
seq_printf(p, "%*s: ", prec, "ISC");
for_each_online_cpu(j)
seq_printf(p, "%10u ", irq_stats(j)->irq_stack_counter);
seq_puts(p, " Interrupt stack usage counter\n");
# endif
#endif #endif
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
seq_printf(p, "%*s: ", prec, "RES"); seq_printf(p, "%*s: ", prec, "RES");
for_each_online_cpu(j) for_each_online_cpu(j)
seq_printf(p, "%10u ", irq_stats(j)->irq_resched_count); seq_printf(p, "%10u ", irq_stats(j)->irq_resched_count);
seq_printf(p, " Rescheduling interrupts\n"); seq_puts(p, " Rescheduling interrupts\n");
seq_printf(p, "%*s: ", prec, "CAL"); seq_printf(p, "%*s: ", prec, "CAL");
for_each_online_cpu(j) for_each_online_cpu(j)
seq_printf(p, "%10u ", irq_stats(j)->irq_call_count); seq_printf(p, "%10u ", irq_stats(j)->irq_call_count);
seq_printf(p, " Function call interrupts\n"); seq_puts(p, " Function call interrupts\n");
#endif #endif
seq_printf(p, "%*s: ", prec, "TLB"); seq_printf(p, "%*s: ", prec, "TLB");
for_each_online_cpu(j) for_each_online_cpu(j)
seq_printf(p, "%10u ", irq_stats(j)->irq_tlb_count); seq_printf(p, "%10u ", irq_stats(j)->irq_tlb_count);
seq_printf(p, " TLB shootdowns\n"); seq_puts(p, " TLB shootdowns\n");
return 0; return 0;
} }
@ -378,6 +388,7 @@ static inline void stack_overflow_check(struct pt_regs *regs)
unsigned long sp = regs->gr[30]; unsigned long sp = regs->gr[30];
unsigned long stack_usage; unsigned long stack_usage;
unsigned int *last_usage; unsigned int *last_usage;
int cpu = smp_processor_id();
/* if sr7 != 0, we interrupted a userspace process which we do not want /* if sr7 != 0, we interrupted a userspace process which we do not want
* to check for stack overflow. We will only check the kernel stack. */ * to check for stack overflow. We will only check the kernel stack. */
@ -386,7 +397,31 @@ static inline void stack_overflow_check(struct pt_regs *regs)
/* calculate kernel stack usage */ /* calculate kernel stack usage */
stack_usage = sp - stack_start; stack_usage = sp - stack_start;
last_usage = &per_cpu(irq_stat.kernel_stack_usage, smp_processor_id()); #ifdef CONFIG_IRQSTACKS
if (likely(stack_usage <= THREAD_SIZE))
goto check_kernel_stack; /* found kernel stack */
/* check irq stack usage */
stack_start = (unsigned long) &per_cpu(irq_stack_union, cpu).stack;
stack_usage = sp - stack_start;
last_usage = &per_cpu(irq_stat.irq_stack_usage, cpu);
if (unlikely(stack_usage > *last_usage))
*last_usage = stack_usage;
if (likely(stack_usage < (IRQ_STACK_SIZE - STACK_MARGIN)))
return;
pr_emerg("stackcheck: %s will most likely overflow irq stack "
"(sp:%lx, stk bottom-top:%lx-%lx)\n",
current->comm, sp, stack_start, stack_start + IRQ_STACK_SIZE);
goto panic_check;
check_kernel_stack:
#endif
/* check kernel stack usage */
last_usage = &per_cpu(irq_stat.kernel_stack_usage, cpu);
if (unlikely(stack_usage > *last_usage)) if (unlikely(stack_usage > *last_usage))
*last_usage = stack_usage; *last_usage = stack_usage;
@ -398,31 +433,69 @@ static inline void stack_overflow_check(struct pt_regs *regs)
"(sp:%lx, stk bottom-top:%lx-%lx)\n", "(sp:%lx, stk bottom-top:%lx-%lx)\n",
current->comm, sp, stack_start, stack_start + THREAD_SIZE); current->comm, sp, stack_start, stack_start + THREAD_SIZE);
#ifdef CONFIG_IRQSTACKS
panic_check:
#endif
if (sysctl_panic_on_stackoverflow) if (sysctl_panic_on_stackoverflow)
panic("low stack detected by irq handler - check messages\n"); panic("low stack detected by irq handler - check messages\n");
#endif #endif
} }
#ifdef CONFIG_IRQSTACKS #ifdef CONFIG_IRQSTACKS
DEFINE_PER_CPU(union irq_stack_union, irq_stack_union); DEFINE_PER_CPU(union irq_stack_union, irq_stack_union) = {
.lock = __RAW_SPIN_LOCK_UNLOCKED((irq_stack_union).lock)
};
static void execute_on_irq_stack(void *func, unsigned long param1) static void execute_on_irq_stack(void *func, unsigned long param1)
{ {
unsigned long *irq_stack_start; union irq_stack_union *union_ptr;
unsigned long irq_stack; unsigned long irq_stack;
int cpu = smp_processor_id(); raw_spinlock_t *irq_stack_in_use;
irq_stack_start = &per_cpu(irq_stack_union, cpu).stack[0]; union_ptr = &per_cpu(irq_stack_union, smp_processor_id());
irq_stack = (unsigned long) irq_stack_start; irq_stack = (unsigned long) &union_ptr->stack;
irq_stack = ALIGN(irq_stack, 16); /* align for stack frame usage */ irq_stack = ALIGN(irq_stack + sizeof(irq_stack_union.lock),
64); /* align for stack frame usage */
BUG_ON(*irq_stack_start); /* report bug if we were called recursive. */ /* We may be called recursive. If we are already using the irq stack,
*irq_stack_start = 1; * just continue to use it. Use spinlocks to serialize
* the irq stack usage.
*/
irq_stack_in_use = &union_ptr->lock;
if (!raw_spin_trylock(irq_stack_in_use)) {
void (*direct_call)(unsigned long p1) = func;
/* We are using the IRQ stack already.
* Do direct call on current stack. */
direct_call(param1);
return;
}
/* This is where we switch to the IRQ stack. */ /* This is where we switch to the IRQ stack. */
call_on_stack(param1, func, irq_stack); call_on_stack(param1, func, irq_stack);
*irq_stack_start = 0; __inc_irq_stat(irq_stack_counter);
/* free up irq stack usage. */
do_raw_spin_unlock(irq_stack_in_use);
}
asmlinkage void do_softirq(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);
} }
#endif /* CONFIG_IRQSTACKS */ #endif /* CONFIG_IRQSTACKS */

Просмотреть файл

@ -1069,7 +1069,7 @@ void flush_tlb_all(void)
{ {
int do_recycle; int do_recycle;
inc_irq_stat(irq_tlb_count); __inc_irq_stat(irq_tlb_count);
do_recycle = 0; do_recycle = 0;
spin_lock(&sid_lock); spin_lock(&sid_lock);
if (dirty_space_ids > RECYCLE_THRESHOLD) { if (dirty_space_ids > RECYCLE_THRESHOLD) {
@ -1090,7 +1090,7 @@ void flush_tlb_all(void)
#else #else
void flush_tlb_all(void) void flush_tlb_all(void)
{ {
inc_irq_stat(irq_tlb_count); __inc_irq_stat(irq_tlb_count);
spin_lock(&sid_lock); spin_lock(&sid_lock);
flush_tlb_all_local(NULL); flush_tlb_all_local(NULL);
recycle_sids(); recycle_sids();