aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-06-05 14:15:33 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-06-05 14:15:33 -0400
commit5975b2c0c10adbc7894a54ab7b30db4fbcdd8c41 (patch)
treef62bb70c952848e00caead9ac08acbee7e75a5d0
parentd834502e2fca9380a1579fecd134ef94c063b662 (diff)
parent58f1c654d13a42575d507ea61f6de0332a761e75 (diff)
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
-rw-r--r--arch/parisc/include/asm/traps.h2
-rw-r--r--arch/parisc/kernel/processor.c5
-rw-r--r--arch/parisc/kernel/time.c5
-rw-r--r--arch/parisc/kernel/unaligned.c13
-rw-r--r--arch/parisc/kernel/unwind.c22
5 files changed, 29 insertions, 18 deletions
diff --git a/arch/parisc/include/asm/traps.h b/arch/parisc/include/asm/traps.h
index 4736020ba5ea..5e953ab4530d 100644
--- a/arch/parisc/include/asm/traps.h
+++ b/arch/parisc/include/asm/traps.h
@@ -8,6 +8,8 @@ struct pt_regs;
8void parisc_terminate(char *msg, struct pt_regs *regs, 8void parisc_terminate(char *msg, struct pt_regs *regs,
9 int code, unsigned long offset) __noreturn __cold; 9 int code, unsigned long offset) __noreturn __cold;
10 10
11void die_if_kernel(char *str, struct pt_regs *regs, long err);
12
11/* mm/fault.c */ 13/* mm/fault.c */
12void do_page_fault(struct pt_regs *regs, unsigned long code, 14void do_page_fault(struct pt_regs *regs, unsigned long code,
13 unsigned long address); 15 unsigned long address);
diff --git a/arch/parisc/kernel/processor.c b/arch/parisc/kernel/processor.c
index e81ccf1716e9..5adc339eb7c8 100644
--- a/arch/parisc/kernel/processor.c
+++ b/arch/parisc/kernel/processor.c
@@ -324,8 +324,9 @@ int init_per_cpu(int cpunum)
324 per_cpu(cpu_data, cpunum).fp_rev = coproc_cfg.revision; 324 per_cpu(cpu_data, cpunum).fp_rev = coproc_cfg.revision;
325 per_cpu(cpu_data, cpunum).fp_model = coproc_cfg.model; 325 per_cpu(cpu_data, cpunum).fp_model = coproc_cfg.model;
326 326
327 printk(KERN_INFO "FP[%d] enabled: Rev %ld Model %ld\n", 327 if (cpunum == 0)
328 cpunum, coproc_cfg.revision, coproc_cfg.model); 328 printk(KERN_INFO "FP[%d] enabled: Rev %ld Model %ld\n",
329 cpunum, coproc_cfg.revision, coproc_cfg.model);
329 330
330 /* 331 /*
331 ** store status register to stack (hopefully aligned) 332 ** store status register to stack (hopefully aligned)
diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c
index 58dd6801f5be..31ec99a5f119 100644
--- a/arch/parisc/kernel/time.c
+++ b/arch/parisc/kernel/time.c
@@ -309,11 +309,6 @@ void __init time_init(void)
309 clocks_calc_mult_shift(&cyc2ns_mul, &cyc2ns_shift, current_cr16_khz, 309 clocks_calc_mult_shift(&cyc2ns_mul, &cyc2ns_shift, current_cr16_khz,
310 NSEC_PER_MSEC, 0); 310 NSEC_PER_MSEC, 0);
311 311
312#if defined(CONFIG_HAVE_UNSTABLE_SCHED_CLOCK) && defined(CONFIG_64BIT)
313 /* At bootup only one 64bit CPU is online and cr16 is "stable" */
314 set_sched_clock_stable();
315#endif
316
317 start_cpu_itimer(); /* get CPU 0 started */ 312 start_cpu_itimer(); /* get CPU 0 started */
318 313
319 /* register at clocksource framework */ 314 /* register at clocksource framework */
diff --git a/arch/parisc/kernel/unaligned.c b/arch/parisc/kernel/unaligned.c
index d7c0acb35ec2..2b65c0177778 100644
--- a/arch/parisc/kernel/unaligned.c
+++ b/arch/parisc/kernel/unaligned.c
@@ -28,6 +28,7 @@
28#include <linux/ratelimit.h> 28#include <linux/ratelimit.h>
29#include <asm/uaccess.h> 29#include <asm/uaccess.h>
30#include <asm/hardirq.h> 30#include <asm/hardirq.h>
31#include <asm/traps.h>
31 32
32/* #define DEBUG_UNALIGNED 1 */ 33/* #define DEBUG_UNALIGNED 1 */
33 34
@@ -130,8 +131,6 @@
130 131
131int unaligned_enabled __read_mostly = 1; 132int unaligned_enabled __read_mostly = 1;
132 133
133void die_if_kernel (char *str, struct pt_regs *regs, long err);
134
135static int emulate_ldh(struct pt_regs *regs, int toreg) 134static int emulate_ldh(struct pt_regs *regs, int toreg)
136{ 135{
137 unsigned long saddr = regs->ior; 136 unsigned long saddr = regs->ior;
@@ -666,7 +665,7 @@ void handle_unaligned(struct pt_regs *regs)
666 break; 665 break;
667 } 666 }
668 667
669 if (modify && R1(regs->iir)) 668 if (ret == 0 && modify && R1(regs->iir))
670 regs->gr[R1(regs->iir)] = newbase; 669 regs->gr[R1(regs->iir)] = newbase;
671 670
672 671
@@ -677,6 +676,14 @@ void handle_unaligned(struct pt_regs *regs)
677 676
678 if (ret) 677 if (ret)
679 { 678 {
679 /*
680 * The unaligned handler failed.
681 * If we were called by __get_user() or __put_user() jump
682 * to it's exception fixup handler instead of crashing.
683 */
684 if (!user_mode(regs) && fixup_exception(regs))
685 return;
686
680 printk(KERN_CRIT "Unaligned handler failed, ret = %d\n", ret); 687 printk(KERN_CRIT "Unaligned handler failed, ret = %d\n", ret);
681 die_if_kernel("Unaligned data reference", regs, 28); 688 die_if_kernel("Unaligned data reference", regs, 28);
682 689
diff --git a/arch/parisc/kernel/unwind.c b/arch/parisc/kernel/unwind.c
index ddd988b267a9..e278a87f43cc 100644
--- a/arch/parisc/kernel/unwind.c
+++ b/arch/parisc/kernel/unwind.c
@@ -75,7 +75,10 @@ find_unwind_entry(unsigned long addr)
75 if (addr >= kernel_unwind_table.start && 75 if (addr >= kernel_unwind_table.start &&
76 addr <= kernel_unwind_table.end) 76 addr <= kernel_unwind_table.end)
77 e = find_unwind_entry_in_table(&kernel_unwind_table, addr); 77 e = find_unwind_entry_in_table(&kernel_unwind_table, addr);
78 else 78 else {
79 unsigned long flags;
80
81 spin_lock_irqsave(&unwind_lock, flags);
79 list_for_each_entry(table, &unwind_tables, list) { 82 list_for_each_entry(table, &unwind_tables, list) {
80 if (addr >= table->start && 83 if (addr >= table->start &&
81 addr <= table->end) 84 addr <= table->end)
@@ -86,6 +89,8 @@ find_unwind_entry(unsigned long addr)
86 break; 89 break;
87 } 90 }
88 } 91 }
92 spin_unlock_irqrestore(&unwind_lock, flags);
93 }
89 94
90 return e; 95 return e;
91} 96}
@@ -303,18 +308,16 @@ static void unwind_frame_regs(struct unwind_frame_info *info)
303 308
304 insn = *(unsigned int *)npc; 309 insn = *(unsigned int *)npc;
305 310
306 if ((insn & 0xffffc000) == 0x37de0000 || 311 if ((insn & 0xffffc001) == 0x37de0000 ||
307 (insn & 0xffe00000) == 0x6fc00000) { 312 (insn & 0xffe00001) == 0x6fc00000) {
308 /* ldo X(sp), sp, or stwm X,D(sp) */ 313 /* ldo X(sp), sp, or stwm X,D(sp) */
309 frame_size += (insn & 0x1 ? -1 << 13 : 0) | 314 frame_size += (insn & 0x3fff) >> 1;
310 ((insn & 0x3fff) >> 1);
311 dbg("analyzing func @ %lx, insn=%08x @ " 315 dbg("analyzing func @ %lx, insn=%08x @ "
312 "%lx, frame_size = %ld\n", info->ip, 316 "%lx, frame_size = %ld\n", info->ip,
313 insn, npc, frame_size); 317 insn, npc, frame_size);
314 } else if ((insn & 0xffe00008) == 0x73c00008) { 318 } else if ((insn & 0xffe00009) == 0x73c00008) {
315 /* std,ma X,D(sp) */ 319 /* std,ma X,D(sp) */
316 frame_size += (insn & 0x1 ? -1 << 13 : 0) | 320 frame_size += ((insn >> 4) & 0x3ff) << 3;
317 (((insn >> 4) & 0x3ff) << 3);
318 dbg("analyzing func @ %lx, insn=%08x @ " 321 dbg("analyzing func @ %lx, insn=%08x @ "
319 "%lx, frame_size = %ld\n", info->ip, 322 "%lx, frame_size = %ld\n", info->ip,
320 insn, npc, frame_size); 323 insn, npc, frame_size);
@@ -333,6 +336,9 @@ static void unwind_frame_regs(struct unwind_frame_info *info)
333 } 336 }
334 } 337 }
335 338
339 if (frame_size > e->Total_frame_size << 3)
340 frame_size = e->Total_frame_size << 3;
341
336 if (!unwind_special(info, e->region_start, frame_size)) { 342 if (!unwind_special(info, e->region_start, frame_size)) {
337 info->prev_sp = info->sp - frame_size; 343 info->prev_sp = info->sp - frame_size;
338 if (e->Millicode) 344 if (e->Millicode)