All new accounts created on Gitlab now require administrator approval. If you invite any collaborators, please let Flux staff know so they can approve the accounts.

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,6 +324,7 @@ int init_per_cpu(int cpunum) ...@@ -324,6 +324,7 @@ 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;
if (cpunum == 0)
printk(KERN_INFO "FP[%d] enabled: Rev %ld Model %ld\n", printk(KERN_INFO "FP[%d] enabled: Rev %ld Model %ld\n",
cpunum, coproc_cfg.revision, coproc_cfg.model); cpunum, coproc_cfg.revision, coproc_cfg.model);
......
...@@ -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