Commit 5975b2c0 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull parisc fixes from Helge Deller:

 - Fix printk time stamps on SMP systems which got wrong due to a patch
   which was added during the merge window

 - Fix two bugs in the stack backtrace code: Races in module unloading
   and possible invalid accesses to memory due to wrong instruction
   decoding (Mikulas Patocka)

 - Fix userspace crash when syscalls access invalid unaligned userspace
   addresses.  Those syscalls will now return EFAULT as expected.
   (tagged for stable kernel series)

* 'parisc-4.7-2' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux:
  parisc: Move die_if_kernel() prototype into traps.h header
  parisc: Fix pagefault crash in unaligned __get_user() call
  parisc: Fix printk time during boot
  parisc: Fix backtrace on PA-RISC
parents d834502e 58f1c654
...@@ -8,6 +8,8 @@ struct pt_regs; ...@@ -8,6 +8,8 @@ struct pt_regs;
void parisc_terminate(char *msg, struct pt_regs *regs, void parisc_terminate(char *msg, struct pt_regs *regs,
int code, unsigned long offset) __noreturn __cold; int code, unsigned long offset) __noreturn __cold;
void die_if_kernel(char *str, struct pt_regs *regs, long err);
/* mm/fault.c */ /* mm/fault.c */
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);
......
...@@ -324,8 +324,9 @@ int init_per_cpu(int cpunum) ...@@ -324,8 +324,9 @@ int init_per_cpu(int cpunum)
per_cpu(cpu_data, cpunum).fp_rev = coproc_cfg.revision; per_cpu(cpu_data, cpunum).fp_rev = coproc_cfg.revision;
per_cpu(cpu_data, cpunum).fp_model = coproc_cfg.model; per_cpu(cpu_data, cpunum).fp_model = coproc_cfg.model;
printk(KERN_INFO "FP[%d] enabled: Rev %ld Model %ld\n", if (cpunum == 0)
cpunum, coproc_cfg.revision, coproc_cfg.model); printk(KERN_INFO "FP[%d] enabled: Rev %ld Model %ld\n",
cpunum, coproc_cfg.revision, coproc_cfg.model);
/* /*
** store status register to stack (hopefully aligned) ** store status register to stack (hopefully aligned)
......
...@@ -309,11 +309,6 @@ void __init time_init(void) ...@@ -309,11 +309,6 @@ void __init time_init(void)
clocks_calc_mult_shift(&cyc2ns_mul, &cyc2ns_shift, current_cr16_khz, clocks_calc_mult_shift(&cyc2ns_mul, &cyc2ns_shift, current_cr16_khz,
NSEC_PER_MSEC, 0); NSEC_PER_MSEC, 0);
#if defined(CONFIG_HAVE_UNSTABLE_SCHED_CLOCK) && defined(CONFIG_64BIT)
/* At bootup only one 64bit CPU is online and cr16 is "stable" */
set_sched_clock_stable();
#endif
start_cpu_itimer(); /* get CPU 0 started */ start_cpu_itimer(); /* get CPU 0 started */
/* register at clocksource framework */ /* register at clocksource framework */
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <linux/ratelimit.h> #include <linux/ratelimit.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/hardirq.h> #include <asm/hardirq.h>
#include <asm/traps.h>
/* #define DEBUG_UNALIGNED 1 */ /* #define DEBUG_UNALIGNED 1 */
...@@ -130,8 +131,6 @@ ...@@ -130,8 +131,6 @@
int unaligned_enabled __read_mostly = 1; int unaligned_enabled __read_mostly = 1;
void die_if_kernel (char *str, struct pt_regs *regs, long err);
static int emulate_ldh(struct pt_regs *regs, int toreg) static int emulate_ldh(struct pt_regs *regs, int toreg)
{ {
unsigned long saddr = regs->ior; unsigned long saddr = regs->ior;
...@@ -666,7 +665,7 @@ void handle_unaligned(struct pt_regs *regs) ...@@ -666,7 +665,7 @@ void handle_unaligned(struct pt_regs *regs)
break; break;
} }
if (modify && R1(regs->iir)) if (ret == 0 && modify && R1(regs->iir))
regs->gr[R1(regs->iir)] = newbase; regs->gr[R1(regs->iir)] = newbase;
...@@ -677,6 +676,14 @@ void handle_unaligned(struct pt_regs *regs) ...@@ -677,6 +676,14 @@ void handle_unaligned(struct pt_regs *regs)
if (ret) if (ret)
{ {
/*
* The unaligned handler failed.
* If we were called by __get_user() or __put_user() jump
* to it's exception fixup handler instead of crashing.
*/
if (!user_mode(regs) && fixup_exception(regs))
return;
printk(KERN_CRIT "Unaligned handler failed, ret = %d\n", ret); printk(KERN_CRIT "Unaligned handler failed, ret = %d\n", ret);
die_if_kernel("Unaligned data reference", regs, 28); die_if_kernel("Unaligned data reference", regs, 28);
......
...@@ -75,7 +75,10 @@ find_unwind_entry(unsigned long addr) ...@@ -75,7 +75,10 @@ find_unwind_entry(unsigned long addr)
if (addr >= kernel_unwind_table.start && if (addr >= kernel_unwind_table.start &&
addr <= kernel_unwind_table.end) addr <= kernel_unwind_table.end)
e = find_unwind_entry_in_table(&kernel_unwind_table, addr); e = find_unwind_entry_in_table(&kernel_unwind_table, addr);
else else {
unsigned long flags;
spin_lock_irqsave(&unwind_lock, flags);
list_for_each_entry(table, &unwind_tables, list) { list_for_each_entry(table, &unwind_tables, list) {
if (addr >= table->start && if (addr >= table->start &&
addr <= table->end) addr <= table->end)
...@@ -86,6 +89,8 @@ find_unwind_entry(unsigned long addr) ...@@ -86,6 +89,8 @@ find_unwind_entry(unsigned long addr)
break; break;
} }
} }
spin_unlock_irqrestore(&unwind_lock, flags);
}
return e; return e;
} }
...@@ -303,18 +308,16 @@ static void unwind_frame_regs(struct unwind_frame_info *info) ...@@ -303,18 +308,16 @@ static void unwind_frame_regs(struct unwind_frame_info *info)
insn = *(unsigned int *)npc; insn = *(unsigned int *)npc;
if ((insn & 0xffffc000) == 0x37de0000 || if ((insn & 0xffffc001) == 0x37de0000 ||
(insn & 0xffe00000) == 0x6fc00000) { (insn & 0xffe00001) == 0x6fc00000) {
/* ldo X(sp), sp, or stwm X,D(sp) */ /* ldo X(sp), sp, or stwm X,D(sp) */
frame_size += (insn & 0x1 ? -1 << 13 : 0) | frame_size += (insn & 0x3fff) >> 1;
((insn & 0x3fff) >> 1);
dbg("analyzing func @ %lx, insn=%08x @ " dbg("analyzing func @ %lx, insn=%08x @ "
"%lx, frame_size = %ld\n", info->ip, "%lx, frame_size = %ld\n", info->ip,
insn, npc, frame_size); insn, npc, frame_size);
} else if ((insn & 0xffe00008) == 0x73c00008) { } else if ((insn & 0xffe00009) == 0x73c00008) {
/* std,ma X,D(sp) */ /* std,ma X,D(sp) */
frame_size += (insn & 0x1 ? -1 << 13 : 0) | frame_size += ((insn >> 4) & 0x3ff) << 3;
(((insn >> 4) & 0x3ff) << 3);
dbg("analyzing func @ %lx, insn=%08x @ " dbg("analyzing func @ %lx, insn=%08x @ "
"%lx, frame_size = %ld\n", info->ip, "%lx, frame_size = %ld\n", info->ip,
insn, npc, frame_size); insn, npc, frame_size);
...@@ -333,6 +336,9 @@ static void unwind_frame_regs(struct unwind_frame_info *info) ...@@ -333,6 +336,9 @@ static void unwind_frame_regs(struct unwind_frame_info *info)
} }
} }
if (frame_size > e->Total_frame_size << 3)
frame_size = e->Total_frame_size << 3;
if (!unwind_special(info, e->region_start, frame_size)) { if (!unwind_special(info, e->region_start, frame_size)) {
info->prev_sp = info->sp - frame_size; info->prev_sp = info->sp - frame_size;
if (e->Millicode) if (e->Millicode)
......
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