Commit 6ed8bf82 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull parisc fixes from Helge Deller:
 "There are two patches in here:

  The first patch greatly improves latency and corrects the memory
  ordering in our light-weight atomic locking syscall.

  The second patch ratelimits printing of userspace segfaults in the
  same way as it's done on other platforms.  This fixes a possible DOS
  on parisc since it prevents the syslog to grow too fast.  For example,
  when the debian acl2 package was built on our debian buildd servers,
  this package produced lots of gigabytes in syslog in very short time
  and thus filled our harddisks, which then turned the server nearly
  completely unaccessible and unresponsive"

* 'parisc-3.15-4' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux:
  parisc: Improve LWS-CAS performance
  parisc: ratelimit userspace segfault printing
parents 8d900e7f c776cd89
...@@ -22,6 +22,7 @@ config PARISC ...@@ -22,6 +22,7 @@ config PARISC
select GENERIC_SMP_IDLE_THREAD select GENERIC_SMP_IDLE_THREAD
select GENERIC_STRNCPY_FROM_USER select GENERIC_STRNCPY_FROM_USER
select SYSCTL_ARCH_UNALIGN_ALLOW select SYSCTL_ARCH_UNALIGN_ALLOW
select SYSCTL_EXCEPTION_TRACE
select HAVE_MOD_ARCH_SPECIFIC select HAVE_MOD_ARCH_SPECIFIC
select VIRT_TO_BUS select VIRT_TO_BUS
select MODULES_USE_ELF_RELA select MODULES_USE_ELF_RELA
......
...@@ -589,10 +589,13 @@ cas_nocontend: ...@@ -589,10 +589,13 @@ cas_nocontend:
# endif # endif
/* ENABLE_LWS_DEBUG */ /* ENABLE_LWS_DEBUG */
rsm PSW_SM_I, %r0 /* Disable interrupts */
/* COW breaks can cause contention on UP systems */
LDCW 0(%sr2,%r20), %r28 /* Try to acquire the lock */ LDCW 0(%sr2,%r20), %r28 /* Try to acquire the lock */
cmpb,<>,n %r0, %r28, cas_action /* Did we get it? */ cmpb,<>,n %r0, %r28, cas_action /* Did we get it? */
cas_wouldblock: cas_wouldblock:
ldo 2(%r0), %r28 /* 2nd case */ ldo 2(%r0), %r28 /* 2nd case */
ssm PSW_SM_I, %r0
b lws_exit /* Contended... */ b lws_exit /* Contended... */
ldo -EAGAIN(%r0), %r21 /* Spin in userspace */ ldo -EAGAIN(%r0), %r21 /* Spin in userspace */
...@@ -619,15 +622,17 @@ cas_action: ...@@ -619,15 +622,17 @@ cas_action:
stw %r1, 4(%sr2,%r20) stw %r1, 4(%sr2,%r20)
#endif #endif
/* The load and store could fail */ /* The load and store could fail */
1: ldw 0(%sr3,%r26), %r28 1: ldw,ma 0(%sr3,%r26), %r28
sub,<> %r28, %r25, %r0 sub,<> %r28, %r25, %r0
2: stw %r24, 0(%sr3,%r26) 2: stw,ma %r24, 0(%sr3,%r26)
/* Free lock */ /* Free lock */
stw %r20, 0(%sr2,%r20) stw,ma %r20, 0(%sr2,%r20)
#if ENABLE_LWS_DEBUG #if ENABLE_LWS_DEBUG
/* Clear thread register indicator */ /* Clear thread register indicator */
stw %r0, 4(%sr2,%r20) stw %r0, 4(%sr2,%r20)
#endif #endif
/* Enable interrupts */
ssm PSW_SM_I, %r0
/* Return to userspace, set no error */ /* Return to userspace, set no error */
b lws_exit b lws_exit
copy %r0, %r21 copy %r0, %r21
...@@ -639,6 +644,7 @@ cas_action: ...@@ -639,6 +644,7 @@ cas_action:
#if ENABLE_LWS_DEBUG #if ENABLE_LWS_DEBUG
stw %r0, 4(%sr2,%r20) stw %r0, 4(%sr2,%r20)
#endif #endif
ssm PSW_SM_I, %r0
b lws_exit b lws_exit
ldo -EFAULT(%r0),%r21 /* set errno */ ldo -EFAULT(%r0),%r21 /* set errno */
nop nop
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/console.h> #include <linux/console.h>
#include <linux/bug.h> #include <linux/bug.h>
#include <linux/ratelimit.h>
#include <asm/assembly.h> #include <asm/assembly.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -42,9 +43,6 @@ ...@@ -42,9 +43,6 @@
#include "../math-emu/math-emu.h" /* for handle_fpe() */ #include "../math-emu/math-emu.h" /* for handle_fpe() */
#define PRINT_USER_FAULTS /* (turn this on if you want user faults to be */
/* dumped to the console via printk) */
#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK) #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
DEFINE_SPINLOCK(pa_dbit_lock); DEFINE_SPINLOCK(pa_dbit_lock);
#endif #endif
...@@ -160,6 +158,17 @@ void show_regs(struct pt_regs *regs) ...@@ -160,6 +158,17 @@ void show_regs(struct pt_regs *regs)
} }
} }
static DEFINE_RATELIMIT_STATE(_hppa_rs,
DEFAULT_RATELIMIT_INTERVAL, DEFAULT_RATELIMIT_BURST);
#define parisc_printk_ratelimited(critical, regs, fmt, ...) { \
if ((critical || show_unhandled_signals) && __ratelimit(&_hppa_rs)) { \
printk(fmt, ##__VA_ARGS__); \
show_regs(regs); \
} \
}
static void do_show_stack(struct unwind_frame_info *info) static void do_show_stack(struct unwind_frame_info *info)
{ {
int i = 1; int i = 1;
...@@ -229,12 +238,10 @@ void die_if_kernel(char *str, struct pt_regs *regs, long err) ...@@ -229,12 +238,10 @@ void die_if_kernel(char *str, struct pt_regs *regs, long err)
if (err == 0) if (err == 0)
return; /* STFU */ return; /* STFU */
printk(KERN_CRIT "%s (pid %d): %s (code %ld) at " RFMT "\n", parisc_printk_ratelimited(1, regs,
KERN_CRIT "%s (pid %d): %s (code %ld) at " RFMT "\n",
current->comm, task_pid_nr(current), str, err, regs->iaoq[0]); current->comm, task_pid_nr(current), str, err, regs->iaoq[0]);
#ifdef PRINT_USER_FAULTS
/* XXX for debugging only */
show_regs(regs);
#endif
return; return;
} }
...@@ -321,14 +328,11 @@ static void handle_break(struct pt_regs *regs) ...@@ -321,14 +328,11 @@ static void handle_break(struct pt_regs *regs)
(tt == BUG_TRAP_TYPE_NONE) ? 9 : 0); (tt == BUG_TRAP_TYPE_NONE) ? 9 : 0);
} }
#ifdef PRINT_USER_FAULTS if (unlikely(iir != GDB_BREAK_INSN))
if (unlikely(iir != GDB_BREAK_INSN)) { parisc_printk_ratelimited(0, regs,
printk(KERN_DEBUG "break %d,%d: pid=%d command='%s'\n", KERN_DEBUG "break %d,%d: pid=%d command='%s'\n",
iir & 31, (iir>>13) & ((1<<13)-1), iir & 31, (iir>>13) & ((1<<13)-1),
task_pid_nr(current), current->comm); task_pid_nr(current), current->comm);
show_regs(regs);
}
#endif
/* send standard GDB signal */ /* send standard GDB signal */
handle_gdb_break(regs, TRAP_BRKPT); handle_gdb_break(regs, TRAP_BRKPT);
...@@ -758,11 +762,9 @@ void notrace handle_interruption(int code, struct pt_regs *regs) ...@@ -758,11 +762,9 @@ void notrace handle_interruption(int code, struct pt_regs *regs)
default: default:
if (user_mode(regs)) { if (user_mode(regs)) {
#ifdef PRINT_USER_FAULTS parisc_printk_ratelimited(0, regs, KERN_DEBUG
printk(KERN_DEBUG "\nhandle_interruption() pid=%d command='%s'\n", "handle_interruption() pid=%d command='%s'\n",
task_pid_nr(current), current->comm); task_pid_nr(current), current->comm);
show_regs(regs);
#endif
/* SIGBUS, for lack of a better one. */ /* SIGBUS, for lack of a better one. */
si.si_signo = SIGBUS; si.si_signo = SIGBUS;
si.si_code = BUS_OBJERR; si.si_code = BUS_OBJERR;
...@@ -779,16 +781,10 @@ void notrace handle_interruption(int code, struct pt_regs *regs) ...@@ -779,16 +781,10 @@ void notrace handle_interruption(int code, struct pt_regs *regs)
if (user_mode(regs)) { if (user_mode(regs)) {
if ((fault_space >> SPACEID_SHIFT) != (regs->sr[7] >> SPACEID_SHIFT)) { if ((fault_space >> SPACEID_SHIFT) != (regs->sr[7] >> SPACEID_SHIFT)) {
#ifdef PRINT_USER_FAULTS parisc_printk_ratelimited(0, regs, KERN_DEBUG
if (fault_space == 0) "User fault %d on space 0x%08lx, pid=%d command='%s'\n",
printk(KERN_DEBUG "User Fault on Kernel Space "); code, fault_space,
else task_pid_nr(current), current->comm);
printk(KERN_DEBUG "User Fault (long pointer) (fault %d) ",
code);
printk(KERN_CONT "pid=%d command='%s'\n",
task_pid_nr(current), current->comm);
show_regs(regs);
#endif
si.si_signo = SIGSEGV; si.si_signo = SIGSEGV;
si.si_errno = 0; si.si_errno = 0;
si.si_code = SEGV_MAPERR; si.si_code = SEGV_MAPERR;
......
...@@ -19,10 +19,6 @@ ...@@ -19,10 +19,6 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/traps.h> #include <asm/traps.h>
#define PRINT_USER_FAULTS /* (turn this on if you want user faults to be */
/* dumped to the console via printk) */
/* Various important other fields */ /* Various important other fields */
#define bit22set(x) (x & 0x00000200) #define bit22set(x) (x & 0x00000200)
#define bits23_25set(x) (x & 0x000001c0) #define bits23_25set(x) (x & 0x000001c0)
...@@ -34,6 +30,8 @@ ...@@ -34,6 +30,8 @@
DEFINE_PER_CPU(struct exception_data, exception_data); DEFINE_PER_CPU(struct exception_data, exception_data);
int show_unhandled_signals = 1;
/* /*
* parisc_acctyp(unsigned int inst) -- * parisc_acctyp(unsigned int inst) --
* Given a PA-RISC memory access instruction, determine if the * Given a PA-RISC memory access instruction, determine if the
...@@ -173,6 +171,32 @@ int fixup_exception(struct pt_regs *regs) ...@@ -173,6 +171,32 @@ int fixup_exception(struct pt_regs *regs)
return 0; return 0;
} }
/*
* Print out info about fatal segfaults, if the show_unhandled_signals
* sysctl is set:
*/
static inline void
show_signal_msg(struct pt_regs *regs, unsigned long code,
unsigned long address, struct task_struct *tsk,
struct vm_area_struct *vma)
{
if (!unhandled_signal(tsk, SIGSEGV))
return;
if (!printk_ratelimit())
return;
pr_warn("\n");
pr_warn("do_page_fault() command='%s' type=%lu address=0x%08lx",
tsk->comm, code, address);
print_vma_addr(KERN_CONT " in ", regs->iaoq[0]);
if (vma)
pr_warn(" vm_start = 0x%08lx, vm_end = 0x%08lx\n",
vma->vm_start, vma->vm_end);
show_regs(regs);
}
void do_page_fault(struct pt_regs *regs, unsigned long code, void do_page_fault(struct pt_regs *regs, unsigned long code,
unsigned long address) unsigned long address)
{ {
...@@ -270,16 +294,8 @@ void do_page_fault(struct pt_regs *regs, unsigned long code, ...@@ -270,16 +294,8 @@ void do_page_fault(struct pt_regs *regs, unsigned long code,
if (user_mode(regs)) { if (user_mode(regs)) {
struct siginfo si; struct siginfo si;
#ifdef PRINT_USER_FAULTS show_signal_msg(regs, code, address, tsk, vma);
printk(KERN_DEBUG "\n");
printk(KERN_DEBUG "do_page_fault() pid=%d command='%s' type=%lu address=0x%08lx\n",
task_pid_nr(tsk), tsk->comm, code, address);
if (vma) {
printk(KERN_DEBUG "vm_start = 0x%08lx, vm_end = 0x%08lx\n",
vma->vm_start, vma->vm_end);
}
show_regs(regs);
#endif
switch (code) { switch (code) {
case 15: /* Data TLB miss fault/Data page fault */ case 15: /* Data TLB miss fault/Data page fault */
/* send SIGSEGV when outside of vma */ /* send SIGSEGV when outside of vma */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment