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:
Коммит
c83bb88589
|
@ -245,7 +245,7 @@ config SMP
|
|||
|
||||
config IRQSTACKS
|
||||
bool "Use separate kernel stacks when processing interrupts"
|
||||
default n
|
||||
default y
|
||||
help
|
||||
If you say Y here the kernel will use separate kernel stacks
|
||||
for handling hard and soft interrupts. This can help avoid
|
||||
|
|
|
@ -23,24 +23,21 @@ NM = sh $(srctree)/arch/parisc/nm
|
|||
CHECKFLAGS += -D__hppa__=1
|
||||
LIBGCC = $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
|
||||
|
||||
MACHINE := $(shell uname -m)
|
||||
NATIVE := $(if $(filter parisc%,$(MACHINE)),1,0)
|
||||
|
||||
ifdef CONFIG_64BIT
|
||||
UTS_MACHINE := parisc64
|
||||
CHECKFLAGS += -D__LP64__=1 -m64
|
||||
WIDTH := 64
|
||||
CC_ARCHES = hppa64
|
||||
else # 32-bit
|
||||
WIDTH :=
|
||||
CC_ARCHES = hppa hppa2.0 hppa1.1
|
||||
endif
|
||||
|
||||
# attempt to help out folks who are cross-compiling
|
||||
ifeq ($(NATIVE),1)
|
||||
CROSS_COMPILE := hppa$(WIDTH)-linux-
|
||||
else
|
||||
ifeq ($(CROSS_COMPILE),)
|
||||
CROSS_COMPILE := hppa$(WIDTH)-linux-gnu-
|
||||
endif
|
||||
ifneq ($(SUBARCH),$(UTS_MACHINE))
|
||||
ifeq ($(CROSS_COMPILE),)
|
||||
CC_SUFFIXES = linux linux-gnu unknown-linux-gnu
|
||||
CROSS_COMPILE := $(call cc-cross-prefix, \
|
||||
$(foreach a,$(CC_ARCHES), \
|
||||
$(foreach s,$(CC_SUFFIXES),$(a)-$(s)-)))
|
||||
endif
|
||||
endif
|
||||
|
||||
OBJCOPY_FLAGS =-O binary -R .note -R .comment -S
|
||||
|
|
|
@ -11,10 +11,18 @@
|
|||
#include <linux/threads.h>
|
||||
#include <linux/irq.h>
|
||||
|
||||
#ifdef CONFIG_IRQSTACKS
|
||||
#define __ARCH_HAS_DO_SOFTIRQ
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
unsigned int __softirq_pending;
|
||||
#ifdef CONFIG_DEBUG_STACKOVERFLOW
|
||||
unsigned int kernel_stack_usage;
|
||||
#ifdef CONFIG_IRQSTACKS
|
||||
unsigned int irq_stack_usage;
|
||||
unsigned int irq_stack_counter;
|
||||
#endif
|
||||
#endif
|
||||
#ifdef CONFIG_SMP
|
||||
unsigned int irq_resched_count;
|
||||
|
@ -28,6 +36,7 @@ DECLARE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat);
|
|||
#define __ARCH_IRQ_STAT
|
||||
#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 local_softirq_pending() this_cpu_read(irq_stat.__softirq_pending)
|
||||
|
||||
#define __ARCH_SET_SOFTIRQ_PENDING
|
||||
|
|
|
@ -63,10 +63,13 @@
|
|||
*/
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#include <linux/spinlock_types.h>
|
||||
|
||||
#define IRQ_STACK_SIZE (4096 << 2) /* 16k irq stack size */
|
||||
|
||||
union irq_stack_union {
|
||||
unsigned long stack[IRQ_STACK_SIZE/sizeof(unsigned long)];
|
||||
raw_spinlock_t lock;
|
||||
};
|
||||
|
||||
DECLARE_PER_CPU(union irq_stack_union, irq_stack_union);
|
||||
|
|
|
@ -452,9 +452,41 @@
|
|||
L2_ptep \pgd,\pte,\index,\va,\fault
|
||||
.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
|
||||
* 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
|
||||
or \tmp1,\pte,\tmp
|
||||
and,COND(<>) \tmp1,\pte,%r0
|
||||
|
@ -463,7 +495,11 @@
|
|||
|
||||
/* Set the dirty bit (and accessed bit). No need to be
|
||||
* 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
|
||||
or \tmp,\pte,\pte
|
||||
STREG \pte,0(\ptep)
|
||||
|
@ -1111,11 +1147,13 @@ dtlb_miss_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
|
||||
|
||||
idtlbt pte,prot
|
||||
dbit_unlock1 spc,t0
|
||||
|
||||
rfir
|
||||
nop
|
||||
|
@ -1135,11 +1173,13 @@ nadtlb_miss_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
|
||||
|
||||
idtlbt pte,prot
|
||||
dbit_unlock1 spc,t0
|
||||
|
||||
rfir
|
||||
nop
|
||||
|
@ -1161,7 +1201,8 @@ dtlb_miss_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
|
||||
|
||||
|
@ -1172,6 +1213,7 @@ dtlb_miss_11:
|
|||
idtlbp prot,(%sr1,va)
|
||||
|
||||
mtsp t0, %sr1 /* Restore sr1 */
|
||||
dbit_unlock1 spc,t0
|
||||
|
||||
rfir
|
||||
nop
|
||||
|
@ -1192,7 +1234,8 @@ nadtlb_miss_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
|
||||
|
||||
|
@ -1204,6 +1247,7 @@ nadtlb_miss_11:
|
|||
idtlbp prot,(%sr1,va)
|
||||
|
||||
mtsp t0, %sr1 /* Restore sr1 */
|
||||
dbit_unlock1 spc,t0
|
||||
|
||||
rfir
|
||||
nop
|
||||
|
@ -1224,13 +1268,15 @@ dtlb_miss_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
|
||||
|
||||
f_extend pte,t0
|
||||
|
||||
idtlbt pte,prot
|
||||
dbit_unlock1 spc,t0
|
||||
|
||||
rfir
|
||||
nop
|
||||
|
@ -1250,13 +1296,15 @@ nadtlb_miss_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
|
||||
|
||||
f_extend pte,t0
|
||||
|
||||
idtlbt pte,prot
|
||||
dbit_unlock1 spc,t0
|
||||
|
||||
rfir
|
||||
nop
|
||||
|
@ -1357,11 +1405,13 @@ itlb_miss_20w:
|
|||
|
||||
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
|
||||
|
||||
iitlbt pte,prot
|
||||
dbit_unlock1 spc,t0
|
||||
|
||||
rfir
|
||||
nop
|
||||
|
@ -1379,11 +1429,13 @@ naitlb_miss_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
|
||||
|
||||
iitlbt pte,prot
|
||||
dbit_unlock1 spc,t0
|
||||
|
||||
rfir
|
||||
nop
|
||||
|
@ -1405,7 +1457,8 @@ itlb_miss_11:
|
|||
|
||||
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
|
||||
|
||||
|
@ -1416,6 +1469,7 @@ itlb_miss_11:
|
|||
iitlbp prot,(%sr1,va)
|
||||
|
||||
mtsp t0, %sr1 /* Restore sr1 */
|
||||
dbit_unlock1 spc,t0
|
||||
|
||||
rfir
|
||||
nop
|
||||
|
@ -1427,7 +1481,8 @@ naitlb_miss_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
|
||||
|
||||
|
@ -1438,6 +1493,7 @@ naitlb_miss_11:
|
|||
iitlbp prot,(%sr1,va)
|
||||
|
||||
mtsp t0, %sr1 /* Restore sr1 */
|
||||
dbit_unlock1 spc,t0
|
||||
|
||||
rfir
|
||||
nop
|
||||
|
@ -1459,13 +1515,15 @@ itlb_miss_20:
|
|||
|
||||
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
|
||||
|
||||
f_extend pte,t0
|
||||
|
||||
iitlbt pte,prot
|
||||
dbit_unlock1 spc,t0
|
||||
|
||||
rfir
|
||||
nop
|
||||
|
@ -1477,13 +1535,15 @@ naitlb_miss_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
|
||||
|
||||
f_extend pte,t0
|
||||
|
||||
iitlbt pte,prot
|
||||
dbit_unlock1 spc,t0
|
||||
|
||||
rfir
|
||||
nop
|
||||
|
@ -1507,29 +1567,13 @@ dbit_trap_20w:
|
|||
|
||||
L3_ptep ptp,pte,t0,va,dbit_fault
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
cmpib,COND(=),n 0,spc,dbit_nolock_20w
|
||||
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
|
||||
dbit_lock spc,t0,t1
|
||||
update_dirty spc,ptp,pte,t1
|
||||
|
||||
make_insert_tlb spc,pte,prot
|
||||
|
||||
idtlbt pte,prot
|
||||
#ifdef CONFIG_SMP
|
||||
cmpib,COND(=),n 0,spc,dbit_nounlock_20w
|
||||
ldi 1,t1
|
||||
stw t1,0(t0)
|
||||
|
||||
dbit_nounlock_20w:
|
||||
#endif
|
||||
dbit_unlock0 spc,t0
|
||||
|
||||
rfir
|
||||
nop
|
||||
|
@ -1543,18 +1587,8 @@ dbit_trap_11:
|
|||
|
||||
L2_ptep ptp,pte,t0,va,dbit_fault
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
cmpib,COND(=),n 0,spc,dbit_nolock_11
|
||||
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
|
||||
dbit_lock spc,t0,t1
|
||||
update_dirty spc,ptp,pte,t1
|
||||
|
||||
make_insert_tlb_11 spc,pte,prot
|
||||
|
||||
|
@ -1565,13 +1599,7 @@ dbit_nolock_11:
|
|||
idtlbp prot,(%sr1,va)
|
||||
|
||||
mtsp t1, %sr1 /* Restore sr1 */
|
||||
#ifdef CONFIG_SMP
|
||||
cmpib,COND(=),n 0,spc,dbit_nounlock_11
|
||||
ldi 1,t1
|
||||
stw t1,0(t0)
|
||||
|
||||
dbit_nounlock_11:
|
||||
#endif
|
||||
dbit_unlock0 spc,t0
|
||||
|
||||
rfir
|
||||
nop
|
||||
|
@ -1583,32 +1611,15 @@ dbit_trap_20:
|
|||
|
||||
L2_ptep ptp,pte,t0,va,dbit_fault
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
cmpib,COND(=),n 0,spc,dbit_nolock_20
|
||||
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
|
||||
dbit_lock spc,t0,t1
|
||||
update_dirty spc,ptp,pte,t1
|
||||
|
||||
make_insert_tlb spc,pte,prot
|
||||
|
||||
f_extend pte,t1
|
||||
|
||||
idtlbt pte,prot
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
cmpib,COND(=),n 0,spc,dbit_nounlock_20
|
||||
ldi 1,t1
|
||||
stw t1,0(t0)
|
||||
|
||||
dbit_nounlock_20:
|
||||
#endif
|
||||
dbit_unlock0 spc,t0
|
||||
|
||||
rfir
|
||||
nop
|
||||
|
|
|
@ -166,22 +166,32 @@ int arch_show_interrupts(struct seq_file *p, int prec)
|
|||
seq_printf(p, "%*s: ", prec, "STK");
|
||||
for_each_online_cpu(j)
|
||||
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
|
||||
#ifdef CONFIG_SMP
|
||||
seq_printf(p, "%*s: ", prec, "RES");
|
||||
for_each_online_cpu(j)
|
||||
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");
|
||||
for_each_online_cpu(j)
|
||||
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
|
||||
seq_printf(p, "%*s: ", prec, "TLB");
|
||||
for_each_online_cpu(j)
|
||||
seq_printf(p, "%10u ", irq_stats(j)->irq_tlb_count);
|
||||
seq_printf(p, " TLB shootdowns\n");
|
||||
seq_puts(p, " TLB shootdowns\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -378,6 +388,7 @@ static inline void stack_overflow_check(struct pt_regs *regs)
|
|||
unsigned long sp = regs->gr[30];
|
||||
unsigned long stack_usage;
|
||||
unsigned int *last_usage;
|
||||
int cpu = smp_processor_id();
|
||||
|
||||
/* 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. */
|
||||
|
@ -386,7 +397,31 @@ static inline void stack_overflow_check(struct pt_regs *regs)
|
|||
|
||||
/* calculate kernel stack usage */
|
||||
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))
|
||||
*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",
|
||||
current->comm, sp, stack_start, stack_start + THREAD_SIZE);
|
||||
|
||||
#ifdef CONFIG_IRQSTACKS
|
||||
panic_check:
|
||||
#endif
|
||||
if (sysctl_panic_on_stackoverflow)
|
||||
panic("low stack detected by irq handler - check messages\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
#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)
|
||||
{
|
||||
unsigned long *irq_stack_start;
|
||||
union irq_stack_union *union_ptr;
|
||||
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];
|
||||
irq_stack = (unsigned long) irq_stack_start;
|
||||
irq_stack = ALIGN(irq_stack, 16); /* align for stack frame usage */
|
||||
union_ptr = &per_cpu(irq_stack_union, smp_processor_id());
|
||||
irq_stack = (unsigned long) &union_ptr->stack;
|
||||
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. */
|
||||
*irq_stack_start = 1;
|
||||
/* We may be called recursive. If we are already using the irq stack,
|
||||
* 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. */
|
||||
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 */
|
||||
|
||||
|
|
|
@ -1069,7 +1069,7 @@ void flush_tlb_all(void)
|
|||
{
|
||||
int do_recycle;
|
||||
|
||||
inc_irq_stat(irq_tlb_count);
|
||||
__inc_irq_stat(irq_tlb_count);
|
||||
do_recycle = 0;
|
||||
spin_lock(&sid_lock);
|
||||
if (dirty_space_ids > RECYCLE_THRESHOLD) {
|
||||
|
@ -1090,7 +1090,7 @@ void flush_tlb_all(void)
|
|||
#else
|
||||
void flush_tlb_all(void)
|
||||
{
|
||||
inc_irq_stat(irq_tlb_count);
|
||||
__inc_irq_stat(irq_tlb_count);
|
||||
spin_lock(&sid_lock);
|
||||
flush_tlb_all_local(NULL);
|
||||
recycle_sids();
|
||||
|
|
Загрузка…
Ссылка в новой задаче