Skip to content

Commit

Permalink
Merge branch 'parisc-for-3.10' of git://git.kernel.org/pub/scm/linux/…
Browse files Browse the repository at this point in the history
…kernel/git/deller/parisc-linux

Pull parisc updates from Helge Deller:
 "Main fixes and updates in this patch series are:
   - we faced kernel stack corruptions because of multiple delivery of
     interrupts
   - added kernel stack overflow checks
   - added possibility to use dedicated stacks for irq processing
   - initial support for page sizes > 4k
   - more information in /proc/interrupts (e.g.  TLB flushes and number
     of IPI calls)
   - documented how the parisc gateway page works
   - and of course quite some other smaller cleanups and fixes."

* 'parisc-for-3.10' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux:
  parisc: tlb flush counting fix for SMP and UP
  parisc: more irq statistics in /proc/interrupts
  parisc: implement irq stacks
  parisc: add kernel stack overflow check
  parisc: only re-enable interrupts if we need to schedule or deliver signals when returning to userspace
  parisc: implement atomic64_dec_if_positive()
  parisc: use long branch in fork_like macro
  parisc: fix NATIVE set up in build
  parisc: document the parisc gateway page
  parisc: fix partly 16/64k PAGE_SIZE boot
  parisc: Provide default implementation for dma_{alloc, free}_attrs
  parisc: fix whitespace errors in arch/parisc/kernel/traps.c
  parisc: remove the second argument of kmap_atomic
  • Loading branch information
torvalds committed May 7, 2013
2 parents d75e2f9 + 0fc537d commit bc2d968
Show file tree
Hide file tree
Showing 21 changed files with 348 additions and 70 deletions.
9 changes: 9 additions & 0 deletions arch/parisc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ config PARISC
select BUG
select HAVE_PERF_EVENTS
select GENERIC_ATOMIC64 if !64BIT
select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
select HAVE_GENERIC_HARDIRQS
select BROKEN_RODATA
select GENERIC_IRQ_PROBE
Expand Down Expand Up @@ -242,6 +243,14 @@ config SMP

If you don't know what to do here, say N.

config IRQSTACKS
bool "Use separate kernel stacks when processing interrupts"
default n
help
If you say Y here the kernel will use separate kernel stacks
for handling hard and soft interrupts. This can help avoid
overflowing the process kernel stacks.

config HOTPLUG_CPU
bool
default y if SMP
Expand Down
11 changes: 11 additions & 0 deletions arch/parisc/Kconfig.debug
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,14 @@ config DEBUG_RODATA
If in doubt, say "N".

endmenu

config DEBUG_STACKOVERFLOW
bool "Check for stack overflows"
default y
depends on DEBUG_KERNEL
---help---
Say Y here if you want to check the overflows of kernel, IRQ
and exception stacks. This option will cause messages of the
stacks in detail when free stack space drops below a certain
limit.
If in doubt, say "N".
4 changes: 1 addition & 3 deletions arch/parisc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,7 @@ CHECKFLAGS += -D__hppa__=1
LIBGCC = $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)

MACHINE := $(shell uname -m)
ifeq ($(MACHINE),parisc*)
NATIVE := 1
endif
NATIVE := $(if $(filter parisc%,$(MACHINE)),1,0)

ifdef CONFIG_64BIT
UTS_MACHINE := parisc64
Expand Down
23 changes: 23 additions & 0 deletions arch/parisc/include/asm/atomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,29 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)

#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)

/*
* atomic64_dec_if_positive - decrement by 1 if old value positive
* @v: pointer of type atomic_t
*
* The function returns the old value of *v minus 1, even if
* the atomic variable, v, was not decremented.
*/
static inline long atomic64_dec_if_positive(atomic64_t *v)
{
long c, old, dec;
c = atomic64_read(v);
for (;;) {
dec = c - 1;
if (unlikely(dec < 0))
break;
old = atomic64_cmpxchg((v), c, dec);
if (likely(old == c))
break;
c = old;
}
return dec;
}

#endif /* !CONFIG_64BIT */


Expand Down
3 changes: 3 additions & 0 deletions arch/parisc/include/asm/dma-mapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ extern struct hppa_dma_ops pcx_dma_ops;

extern struct hppa_dma_ops *hppa_dma_ops;

#define dma_alloc_attrs(d, s, h, f, a) dma_alloc_coherent(d, s, h, f)
#define dma_free_attrs(d, s, h, f, a) dma_free_coherent(d, s, h, f)

static inline void *
dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
gfp_t flag)
Expand Down
32 changes: 31 additions & 1 deletion arch/parisc/include/asm/hardirq.h
Original file line number Diff line number Diff line change
@@ -1,11 +1,41 @@
/* hardirq.h: PA-RISC hard IRQ support.
*
* Copyright (C) 2001 Matthew Wilcox <[email protected]>
* Copyright (C) 2013 Helge Deller <[email protected]>
*/

#ifndef _PARISC_HARDIRQ_H
#define _PARISC_HARDIRQ_H

#include <asm-generic/hardirq.h>
#include <linux/cache.h>
#include <linux/threads.h>
#include <linux/irq.h>

typedef struct {
unsigned int __softirq_pending;
#ifdef CONFIG_DEBUG_STACKOVERFLOW
unsigned int kernel_stack_usage;
#endif
#ifdef CONFIG_SMP
unsigned int irq_resched_count;
unsigned int irq_call_count;
#endif
unsigned int irq_tlb_count;
} ____cacheline_aligned irq_cpustat_t;

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 local_softirq_pending() this_cpu_read(irq_stat.__softirq_pending)

#define __ARCH_SET_SOFTIRQ_PENDING

#define set_softirq_pending(x) \
this_cpu_write(irq_stat.__softirq_pending, (x))
#define or_softirq_pending(x) this_cpu_or(irq_stat.__softirq_pending, (x))

#define ack_bad_irq(irq) WARN(1, "unexpected IRQ trap at vector %02x\n", irq)

#endif /* _PARISC_HARDIRQ_H */
20 changes: 17 additions & 3 deletions arch/parisc/include/asm/processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@

#endif /* __ASSEMBLY__ */

#define KERNEL_STACK_SIZE (4*PAGE_SIZE)

/*
* Default implementation of macro that returns current
* instruction pointer ("program counter").
Expand Down Expand Up @@ -60,6 +58,23 @@

#ifndef __ASSEMBLY__

/*
* IRQ STACK - used for irq handler
*/
#ifdef __KERNEL__

#define IRQ_STACK_SIZE (4096 << 2) /* 16k irq stack size */

union irq_stack_union {
unsigned long stack[IRQ_STACK_SIZE/sizeof(unsigned long)];
};

DECLARE_PER_CPU(union irq_stack_union, irq_stack_union);

void call_on_stack(unsigned long p1, void *func, unsigned long new_stack);

#endif /* __KERNEL__ */

/*
* Data detected about CPUs at boot time which is the same for all CPU's.
* HP boxes are SMP - ie identical processors.
Expand Down Expand Up @@ -97,7 +112,6 @@ struct cpuinfo_parisc {
unsigned long txn_addr; /* MMIO addr of EIR or id_eid */
#ifdef CONFIG_SMP
unsigned long pending_ipi; /* bitmap of type ipi_message_type */
unsigned long ipi_count; /* number ipi Interrupts */
#endif
unsigned long bh_count; /* number of times bh was invoked */
unsigned long prof_counter; /* per CPU profiling support */
Expand Down
2 changes: 1 addition & 1 deletion arch/parisc/include/asm/thread_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ struct thread_info {

/* thread information allocation */

#define THREAD_SIZE_ORDER 2
#define THREAD_SIZE_ORDER 2 /* PA-RISC requires at least 16k stack */
/* Be sure to hunt all references to this down when you change the size of
* the kernel stack */
#define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER)
Expand Down
2 changes: 2 additions & 0 deletions arch/parisc/include/asm/tlbflush.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ extern spinlock_t pa_tlb_lock;
extern void flush_tlb_all(void);
extern void flush_tlb_all_local(void *);

#define smp_flush_tlb_all() flush_tlb_all()

/*
* flush_tlb_mm()
*
Expand Down
6 changes: 3 additions & 3 deletions arch/parisc/kernel/cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -606,7 +606,7 @@ void clear_user_highpage(struct page *page, unsigned long vaddr)
/* Clear using TMPALIAS region. The page doesn't need to
be flushed but the kernel mapping needs to be purged. */

vto = kmap_atomic(page, KM_USER0);
vto = kmap_atomic(page);

/* The PA-RISC 2.0 Architecture book states on page F-6:
"Before a write-capable translation is enabled, *all*
Expand Down Expand Up @@ -641,8 +641,8 @@ void copy_user_highpage(struct page *to, struct page *from,
the `to' page must be flushed in copy_user_page_asm since
it can be used to bring in executable code. */

vfrom = kmap_atomic(from, KM_USER0);
vto = kmap_atomic(to, KM_USER1);
vfrom = kmap_atomic(from);
vto = kmap_atomic(to);

purge_kernel_dcache_page_asm((unsigned long)vto);
purge_tlb_start(flags);
Expand Down
68 changes: 61 additions & 7 deletions arch/parisc/kernel/entry.S
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,15 @@
#if PT_NLEVELS == 3
extru \va,31-ASM_PMD_SHIFT,ASM_BITS_PER_PMD,\index
#else
# if defined(CONFIG_64BIT)
extrd,u \va,63-ASM_PGDIR_SHIFT,ASM_BITS_PER_PGD,\index
#else
# if PAGE_SIZE > 4096
extru \va,31-ASM_PGDIR_SHIFT,32-ASM_PGDIR_SHIFT,\index
# else
extru \va,31-ASM_PGDIR_SHIFT,ASM_BITS_PER_PGD,\index
# endif
# endif
#endif
dep %r0,31,PAGE_SHIFT,\pmd /* clear offset */
copy %r0,\pte
Expand Down Expand Up @@ -615,7 +623,7 @@

.text

.align PAGE_SIZE
.align 4096

ENTRY(fault_vector_20)
/* First vector is invalid (0) */
Expand Down Expand Up @@ -825,11 +833,6 @@ ENTRY(syscall_exit_rfi)
STREG %r19,PT_SR7(%r16)

intr_return:
/* NOTE: Need to enable interrupts incase we schedule. */
ssm PSW_SM_I, %r0

intr_check_resched:

/* check for reschedule */
mfctl %cr30,%r1
LDREG TI_FLAGS(%r1),%r19 /* sched.h: TIF_NEED_RESCHED */
Expand All @@ -856,6 +859,11 @@ intr_check_sig:
LDREG PT_IASQ1(%r16), %r20
cmpib,COND(=),n 0,%r20,intr_restore /* backward */

/* NOTE: We need to enable interrupts if we have to deliver
* signals. We used to do this earlier but it caused kernel
* stack overflows. */
ssm PSW_SM_I, %r0

copy %r0, %r25 /* long in_syscall = 0 */
#ifdef CONFIG_64BIT
ldo -16(%r30),%r29 /* Reference param save area */
Expand Down Expand Up @@ -907,6 +915,10 @@ intr_do_resched:
cmpib,COND(=) 0, %r20, intr_do_preempt
nop

/* NOTE: We need to enable interrupts if we schedule. We used
* to do this earlier but it caused kernel stack overflows. */
ssm PSW_SM_I, %r0

#ifdef CONFIG_64BIT
ldo -16(%r30),%r29 /* Reference param save area */
#endif
Expand Down Expand Up @@ -1694,7 +1706,8 @@ ENTRY(sys_\name\()_wrapper)
ldo TASK_REGS(%r1),%r1
reg_save %r1
mfctl %cr27, %r28
b sys_\name
ldil L%sys_\name, %r31
be R%sys_\name(%sr4,%r31)
STREG %r28, PT_CR27(%r1)
ENDPROC(sys_\name\()_wrapper)
.endm
Expand Down Expand Up @@ -1997,6 +2010,47 @@ ftrace_stub:
ENDPROC(return_to_handler)
#endif /* CONFIG_FUNCTION_TRACER */

#ifdef CONFIG_IRQSTACKS
/* void call_on_stack(unsigned long param1, void *func,
unsigned long new_stack) */
ENTRY(call_on_stack)
copy %sp, %r1

/* Regarding the HPPA calling conventions for function pointers,
we assume the PIC register is not changed across call. For
CONFIG_64BIT, the argument pointer is left to point at the
argument region allocated for the call to call_on_stack. */
# ifdef CONFIG_64BIT
/* Switch to new stack. We allocate two 128 byte frames. */
ldo 256(%arg2), %sp
/* Save previous stack pointer and return pointer in frame marker */
STREG %rp, -144(%sp)
/* Calls always use function descriptor */
LDREG 16(%arg1), %arg1
bve,l (%arg1), %rp
STREG %r1, -136(%sp)
LDREG -144(%sp), %rp
bve (%rp)
LDREG -136(%sp), %sp
# else
/* Switch to new stack. We allocate two 64 byte frames. */
ldo 128(%arg2), %sp
/* Save previous stack pointer and return pointer in frame marker */
STREG %r1, -68(%sp)
STREG %rp, -84(%sp)
/* Calls use function descriptor if PLABEL bit is set */
bb,>=,n %arg1, 30, 1f
depwi 0,31,2, %arg1
LDREG 0(%arg1), %arg1
1:
be,l 0(%sr4,%arg1), %sr0, %r31
copy %r31, %rp
LDREG -84(%sp), %rp
bv (%rp)
LDREG -68(%sp), %sp
# endif /* CONFIG_64BIT */
ENDPROC(call_on_stack)
#endif /* CONFIG_IRQSTACKS */

get_register:
/*
Expand Down
4 changes: 2 additions & 2 deletions arch/parisc/kernel/hpmc.S
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,13 @@
* IODC requires 7K byte stack. That leaves 1K byte for os_hpmc.
*/

.align PAGE_SIZE
.align 4096
hpmc_stack:
.block 16384

#define HPMC_IODC_BUF_SIZE 0x8000

.align PAGE_SIZE
.align 4096
hpmc_iodc_buf:
.block HPMC_IODC_BUF_SIZE

Expand Down
Loading

0 comments on commit bc2d968

Please sign in to comment.