Skip to content

Commit

Permalink
Merge branch 'parisc-3.15-4' of git://git.kernel.org/pub/scm/linux/ke…
Browse files Browse the repository at this point in the history
…rnel/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
  • Loading branch information
Linus Torvalds committed May 20, 2014
2 parents 8d900e7 + c776cd8 commit 6ed8bf8
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 46 deletions.
1 change: 1 addition & 0 deletions arch/parisc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ config PARISC
select GENERIC_SMP_IDLE_THREAD
select GENERIC_STRNCPY_FROM_USER
select SYSCTL_ARCH_UNALIGN_ALLOW
select SYSCTL_EXCEPTION_TRACE
select HAVE_MOD_ARCH_SPECIFIC
select VIRT_TO_BUS
select MODULES_USE_ELF_RELA
Expand Down
12 changes: 9 additions & 3 deletions arch/parisc/kernel/syscall.S
Original file line number Diff line number Diff line change
Expand Up @@ -589,10 +589,13 @@ cas_nocontend:
# endif
/* 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 */
cmpb,<>,n %r0, %r28, cas_action /* Did we get it? */
cas_wouldblock:
ldo 2(%r0), %r28 /* 2nd case */
ssm PSW_SM_I, %r0
b lws_exit /* Contended... */
ldo -EAGAIN(%r0), %r21 /* Spin in userspace */

Expand All @@ -619,15 +622,17 @@ cas_action:
stw %r1, 4(%sr2,%r20)
#endif
/* The load and store could fail */
1: ldw 0(%sr3,%r26), %r28
1: ldw,ma 0(%sr3,%r26), %r28
sub,<> %r28, %r25, %r0
2: stw %r24, 0(%sr3,%r26)
2: stw,ma %r24, 0(%sr3,%r26)
/* Free lock */
stw %r20, 0(%sr2,%r20)
stw,ma %r20, 0(%sr2,%r20)
#if ENABLE_LWS_DEBUG
/* Clear thread register indicator */
stw %r0, 4(%sr2,%r20)
#endif
/* Enable interrupts */
ssm PSW_SM_I, %r0
/* Return to userspace, set no error */
b lws_exit
copy %r0, %r21
Expand All @@ -639,6 +644,7 @@ cas_action:
#if ENABLE_LWS_DEBUG
stw %r0, 4(%sr2,%r20)
#endif
ssm PSW_SM_I, %r0
b lws_exit
ldo -EFAULT(%r0),%r21 /* set errno */
nop
Expand Down
54 changes: 25 additions & 29 deletions arch/parisc/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <linux/interrupt.h>
#include <linux/console.h>
#include <linux/bug.h>
#include <linux/ratelimit.h>

#include <asm/assembly.h>
#include <asm/uaccess.h>
Expand All @@ -42,9 +43,6 @@

#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)
DEFINE_SPINLOCK(pa_dbit_lock);
#endif
Expand Down Expand Up @@ -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)
{
int i = 1;
Expand Down Expand Up @@ -229,12 +238,10 @@ void die_if_kernel(char *str, struct pt_regs *regs, long err)
if (err == 0)
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]);
#ifdef PRINT_USER_FAULTS
/* XXX for debugging only */
show_regs(regs);
#endif

return;
}

Expand Down Expand Up @@ -321,14 +328,11 @@ static void handle_break(struct pt_regs *regs)
(tt == BUG_TRAP_TYPE_NONE) ? 9 : 0);
}

#ifdef PRINT_USER_FAULTS
if (unlikely(iir != GDB_BREAK_INSN)) {
printk(KERN_DEBUG "break %d,%d: pid=%d command='%s'\n",
if (unlikely(iir != GDB_BREAK_INSN))
parisc_printk_ratelimited(0, regs,
KERN_DEBUG "break %d,%d: pid=%d command='%s'\n",
iir & 31, (iir>>13) & ((1<<13)-1),
task_pid_nr(current), current->comm);
show_regs(regs);
}
#endif

/* send standard GDB signal */
handle_gdb_break(regs, TRAP_BRKPT);
Expand Down Expand Up @@ -758,11 +762,9 @@ void notrace handle_interruption(int code, struct pt_regs *regs)

default:
if (user_mode(regs)) {
#ifdef PRINT_USER_FAULTS
printk(KERN_DEBUG "\nhandle_interruption() pid=%d command='%s'\n",
task_pid_nr(current), current->comm);
show_regs(regs);
#endif
parisc_printk_ratelimited(0, regs, KERN_DEBUG
"handle_interruption() pid=%d command='%s'\n",
task_pid_nr(current), current->comm);
/* SIGBUS, for lack of a better one. */
si.si_signo = SIGBUS;
si.si_code = BUS_OBJERR;
Expand All @@ -779,16 +781,10 @@ void notrace handle_interruption(int code, struct pt_regs *regs)

if (user_mode(regs)) {
if ((fault_space >> SPACEID_SHIFT) != (regs->sr[7] >> SPACEID_SHIFT)) {
#ifdef PRINT_USER_FAULTS
if (fault_space == 0)
printk(KERN_DEBUG "User Fault on Kernel Space ");
else
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
parisc_printk_ratelimited(0, regs, KERN_DEBUG
"User fault %d on space 0x%08lx, pid=%d command='%s'\n",
code, fault_space,
task_pid_nr(current), current->comm);
si.si_signo = SIGSEGV;
si.si_errno = 0;
si.si_code = SEGV_MAPERR;
Expand Down
44 changes: 30 additions & 14 deletions arch/parisc/mm/fault.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,6 @@
#include <asm/uaccess.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 */
#define bit22set(x) (x & 0x00000200)
#define bits23_25set(x) (x & 0x000001c0)
Expand All @@ -34,6 +30,8 @@

DEFINE_PER_CPU(struct exception_data, exception_data);

int show_unhandled_signals = 1;

/*
* parisc_acctyp(unsigned int inst) --
* Given a PA-RISC memory access instruction, determine if the
Expand Down Expand Up @@ -173,6 +171,32 @@ int fixup_exception(struct pt_regs *regs)
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,
unsigned long address)
{
Expand Down Expand Up @@ -270,16 +294,8 @@ void do_page_fault(struct pt_regs *regs, unsigned long code,
if (user_mode(regs)) {
struct siginfo si;

#ifdef PRINT_USER_FAULTS
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
show_signal_msg(regs, code, address, tsk, vma);

switch (code) {
case 15: /* Data TLB miss fault/Data page fault */
/* send SIGSEGV when outside of vma */
Expand Down

0 comments on commit 6ed8bf8

Please sign in to comment.