mirror of
https://github.com/torvalds/linux.git
synced 2024-11-28 07:01:32 +00:00
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
This commit is contained in:
commit
6ed8bf82fe
@ -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
|
||||
|
@ -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 */
|
||||
|
||||
@ -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
|
||||
@ -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
|
||||
|
@ -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>
|
||||
@ -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
|
||||
@ -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;
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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);
|
||||
@ -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",
|
||||
parisc_printk_ratelimited(0, regs, KERN_DEBUG
|
||||
"handle_interruption() pid=%d command='%s'\n",
|
||||
task_pid_nr(current), current->comm);
|
||||
show_regs(regs);
|
||||
#endif
|
||||
/* SIGBUS, for lack of a better one. */
|
||||
si.si_signo = SIGBUS;
|
||||
si.si_code = BUS_OBJERR;
|
||||
@ -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",
|
||||
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);
|
||||
show_regs(regs);
|
||||
#endif
|
||||
si.si_signo = SIGSEGV;
|
||||
si.si_errno = 0;
|
||||
si.si_code = SEGV_MAPERR;
|
||||
|
@ -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)
|
||||
@ -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
|
||||
@ -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)
|
||||
{
|
||||
@ -270,16 +294,8 @@ bad_area:
|
||||
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 */
|
||||
|
Loading…
Reference in New Issue
Block a user